chore: promote staging to staging-promote/3df1bf38-24132614443 (2026-04-08 14:32 UTC) - #2152
Merged
henrypark133 merged 10 commits intoApr 9, 2026
Conversation
* feat: port ratatui tui onto staging * Add TUI model picker for /model * Fix TUI CI lint failures * Format /tools output as vertical list * Restore TUI approval modal on thread switch * Re-emit pending approval events on follow-up messages * Improve TUI thread handling and activity UI * Sort TUI resume conversations by activity * fix(tui): address PR review feedback * Add TUI thread detail modal for activity sidebar * feat(tui): improve conversation scrolling UX - Mouse wheel: 1-line increments (was 3-line jumps) - PageUp/PageDown: full-page scroll based on viewport height (was 5 lines) - Add scrollbar widget on conversation right edge (track │, thumb ┃) - Add "↓ N more ↓ End to return" indicator when scrolled up - Add auto-follow (pinned_to_bottom) that disengages on scroll-up and re-engages when reaching bottom or pressing End - Clamp scroll offset to valid range (can't scroll past content) - Add End key binding to jump to bottom Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tui): use engine context pressure data for status bar The context bar was using cumulative session tokens (total_input + total_output) which grow unboundedly across turns, making the bar always show 100% after a few exchanges. Now uses the actual context window usage from ContextPressure events when available, falling back to cumulative tokens only before the first engine update arrives. Also syncs context_window from the engine's max_tokens so the limit reflects the real model capability instead of name-based heuristics. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tui): render markdown in thread detail modal The thread detail modal was displaying raw markdown text (plain line splitting). Now uses render_markdown() for proper formatting of headers, lists, bold, code blocks, etc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tui): hydrate sidebar with engine threads and routines at startup The TUI sidebar was empty until the first user message because EngineThreadList and RoutineUpdate events were only sent after processing a message. Now sends initial data right before the message loop so the activity panel shows existing threads and routines immediately on startup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tui): use owner_id for engine thread hydration at startup list_engine_threads filters by user_id, so passing "" matched no threads. Now uses self.owner_id() which matches the TUI channel's user_id, so threads are visible in the sidebar immediately. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tui): fix CI — type errors and formatting in TUI tests Wrap `started_at` and `updated_at` in `Some(...)` to match `Option<DateTime<Utc>>` after upstream struct change, and run `cargo fmt` on files with formatting drift. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): resolve clippy warnings — collapsible ifs and needless borrow Collapse three nested `if` blocks into `if && let` chains and remove a needless `&` on the `process_list_threads` call, all in agent_loop.rs. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): add live_harness.rs with updated StatusUpdate patterns The live_harness.rs file was added to staging after this branch diverged. When CI merges the PR into staging, the file uses old StatusUpdate patterns that don't account for the new `detail` and `call_id` fields added by this branch. Add the file with `..` rest patterns to fix the merge-time compile errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(engine): add skill repair learning loop * fix(engine): guard skill repair mission updates * fix(engine): persist skill repair provenance * fix(engine): address skill-repair PR review feedback - Fix hex formatting: iterate GenericArray bytes individually instead of relying on Display impl which produces debug-like output - Always recompute content hash from actual doc.content when archiving a revision to prevent drift from out-of-band writes - Prune repair history on rollback to remove records for versions newer than the one being restored - Combine collect_error_messages + collect_observed_actions into a single pass (collect_errors_and_actions) to avoid redundant event iteration - Document bounded revision eviction policy (cap at 10) - Add comment clarifying concurrent skill-repair / error-diagnosis triggers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(engine): constrain skill repair updates * fix(engine): keep insights on completed threads * style(engine): satisfy fmt and clippy on mission.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Illia Polosukhin <ilblackdragon@gmail.com>
* allow private local llm endpoints * Fix private endpoint review issues * Fix link-local clippy warning * Tighten base URL validation follow-ups * fix(config): non-blocking DNS validation and admin-only LLM key filtering Address PR #1955 review feedback: - Wrap to_socket_addrs() in tokio::task::block_in_place when called from a multi-threaded async runtime so the LLM utility handlers (/api/llm/test_connection, /api/llm/list_models) can no longer stall a worker thread on slow DNS. Synchronous callers (env config, CLI) are unaffected. - Add ADMIN_ONLY_LLM_SETTING_KEYS + strip_admin_only_llm_keys helper as defense-in-depth: Config::from_db_with_toml and re_resolve_llm_with_secrets now take an is_operator flag and strip admin-only base-URL-bearing keys (llm_builtin_overrides, llm_custom_providers, ollama_base_url, openai_compatible_base_url) from the DB merge for non-operator users. This guards future per-user resolve paths and any pre-existing legacy rows from reactivating a private/loopback endpoint via the operator validation policy. Existing call sites pass true (owner_id is the operator scope). Adds regression tests covering: * strip_admin_only_llm_keys removes all four keys, leaves others * validate_base_url is callable from a multi-thread tokio runtime without panicking on the strict short-circuit path * validate_operator_base_url remains callable from async handlers * re_resolve_llm filters admin-only keys when is_operator=false and keeps them when is_operator=true Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(settings): de-dup admin-only LLM key list (#1955 review) `handlers/settings.rs::is_admin_only_setting_key` now delegates to `crate::config::helpers::ADMIN_ONLY_LLM_SETTING_KEYS` so the write-side gate cannot drift from the read-side `strip_admin_only_llm_keys` filter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(workspace): admin system prompt shared with all users (#2088) Introduce SYSTEM.md in a well-known __admin__ scope so admins can set a system prompt that all tenants receive. Gated behind multi-tenant mode (WorkspacePool sets admin_prompt_enabled on each workspace; owner workspace in app.rs also gets the flag when has_any_users() is true). New endpoints: - GET /api/admin/system-prompt — read admin system prompt - PUT /api/admin/system-prompt — set admin system prompt (64 KB limit) Safety: - SYSTEM.md added to injection scan list - is_reserved_scope() guard on user creation (defense-in-depth) - Multi-tenancy gate on both API and prompt assembly layers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: remove review audit file from tracked files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add 64 KB size limit to admin system prompt PUT handler Addresses PR review feedback: - Enforce 64 KB limit on system prompt content to prevent token budget exhaustion (the content is injected into every user's system prompt) - Add regression tests for the size limit (413 for oversized, not-413 for at-limit) - Document that is_multi_tenant is evaluated once at startup and the owner workspace requires a restart after the first user is created Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address remaining review feedback on admin system prompt - Restore rustdoc comments stripped from document.rs (DocumentMetadata, HygieneMetadata, DocumentVersion, VersionSummary, PatchResult, etc.) to keep the diff focused on feature additions only - Replace silent error swallowing (if let Ok) with discriminated match in admin prompt read — only DocumentNotFound is silent, other errors logged at debug! level - Cache admin system prompt on WorkspacePool to avoid an extra DB read on every turn; invalidated on PUT via invalidate_admin_prompt() - Add cache invalidation integration test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(workspace): tighten reserved-scope check and admin-prompt body limit - is_reserved_scope: case-insensitive, whitespace-tolerant, and reserves the entire `__*__` namespace so future system scopes (alongside `__admin__`) cannot be impersonated by hand-crafted user IDs - admin system-prompt route: layer-level DefaultBodyLimit of 128 KB rejects oversized payloads before JSON parse, complementing the in-handler 64 KB content cap - system_prompt put_handler: clarify that the in-handler size check is a clearer-error fallback for the layer cap - users_create_handler: drop the dead is_reserved_scope check on a freshly-minted UUID; the guard belongs at a code path that actually accepts user-supplied IDs - expand is_reserved_scope tests for case, whitespace, and the wider `__*__` namespace Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Illia Polosukhin <ilblackdragon@gmail.com>
* Fix skill installs for invalid catalog names * Fix clippy test module ordering * fix: address PR review feedback * fix: use PairingStore::new_noop() in SSRF test after merge with staging The staging branch introduced a new test (test_http_request_rejects_private_ip_targets) that calls PairingStore::new(), but this branch changed the signature to require db and cache arguments. Use new_noop() since this is a test context. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR #2040 review — remove expect() and dead strip_prefix - Restructure download_key flow in skills_install_handler to use the value directly instead of round-tripping through Option + expect(), satisfying the no-expect-in-production-code rule. - Remove dead strip_prefix("---\n") in render_skill_md — serde_yml does not emit a leading document marker for structs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(skills): preserve unknown frontmatter and tighten install matching - rewrite install-recovery to mutate the `name` field via raw YAML Value rather than re-serializing the typed SkillManifest, so unknown frontmatter keys (vendor extensions, future fields) survive the install rewrite - catalog_entry_is_installed: case-insensitive comparison for the display-name and normalized-slug branches, matching the slug branch - normalize_skill_identifier: document non-ASCII handling - normalizing-invalid-name log: warn -> debug (REPL/TUI rule) - add round-trip test asserting unknown top-level keys, nested mappings, and sequences survive install recovery Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Illia Polosukhin <ilblackdragon@gmail.com>
The test used a hyphenated channel name ("test-failing-channel") but
canonicalize_extension_name() converts hyphens to underscores. This
caused configure() to look for "test_failing_channel.capabilities.json"
which didn't exist, returning an early Err before reaching the
activation code path the test was designed to exercise.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…1770 chore: promote staging to staging-promote/bb2c3e1d-24154330911 (2026-04-08 21:41 UTC)
…0911 chore: promote staging to staging-promote/315c4cf8-24151502580 (2026-04-08 19:29 UTC)
…2580 chore: promote staging to staging-promote/8aa09412-24146405548 (2026-04-08 18:23 UTC)
…5548 chore: promote staging to staging-promote/482ee57c-24140982267 (2026-04-08 16:25 UTC)
henrypark133
merged commit Apr 9, 2026
75cd523
into
staging-promote/3df1bf38-24132614443
12 of 13 checks passed
theredspoon
pushed a commit
to theredspoon/ironclaw
that referenced
this pull request
Jun 21, 2026
…4140982267 chore: promote staging to staging-promote/ce63dee8-24132614443 (2026-04-08 14:32 UTC)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Auto-promotion from staging CI
Batch range:
a55aff980a4e235590c3af57ded2542512e2f9f6..482ee57c5f7bec64f0acbb5676bbdc1c3c82a3aePromotion branch:
staging-promote/482ee57c-24140982267Base:
staging-promote/3df1bf38-24132614443Triggered by: Staging CI batch at 2026-04-08 14:32 UTC
Commits in this batch (58):
Current commits in this promotion (1)
Current base:
staging-promote/3df1bf38-24132614443Current head:
staging-promote/482ee57c-24140982267Current range:
origin/staging-promote/3df1bf38-24132614443..origin/staging-promote/482ee57c-24140982267Auto-updated by staging promotion metadata workflow
Waiting for gates:
Auto-created by staging-ci workflow