chore: promote staging to staging-promote/86388958-23397163010 (2026-03-22 07:15 UTC) - #1560
Conversation
#1277) * feat(ux): complete UX overhaul — design system, boot screen, onboarding, web polish Shared design system: CSS custom properties for spacing, typography, transitions, and color tokens used across web UI and boot screen. Boot screen: compact feature-tags line showing enabled subsystems (db, tools, routines, heartbeat, skills, sandbox, embeddings) at a glance. Downgrade startup info logs (libSQL, webhook, workspace seed) to debug level since the boot screen now covers this. Onboarding wizard: model picker with live API fetch, provider-aware auth flow, improved error recovery and progress display. Web UI: ARIA attributes, welcome card, streaming debounce, connection status banner, skeleton loaders, send cooldown. CLI: doctor command enhancements, status command cleanup, REPL banner consolidation, shared fmt module. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(ux): Apple-level design refinements — spring physics, glass morphism, chat polish Merge staging theme support (dark/light/system toggle) and layer UX polish on top: spring-physics motion, glass morphism depth, chat experience improvements, and responsive mobile refinements. Design system: - Restore and extend design token system (spacing, typography, timing, easing) with legacy aliases for theme compatibility - Add shadow tiers, accent glow, glass morphism, spring easing tokens - Tokens defined in both dark (:root) and light ([data-theme="light"]) Micro-interactions (Phase 2): - Spring-overshoot message entry animation (slideUp) - Spring-scale button press on all interactive buttons - Tab crossfade animation, tool card smooth accordion (max-height) - Modal scale(0.95) + blur(8px) entry, toast spring slide - Sidebar width crossfade, card hover lift Visual depth (Phase 3): - Tab bar glass morphism + surface highlight + sliding indicator - Active tab accent background pill - Assistant message accent left border, user message bubble tail - Floating input area (rounded + shadow + margin) Chat polish (Phase 4): - Smooth streaming cursor (cursorPulse), message hover timestamps - Time separators (Today/Yesterday/date) - Textarea smooth auto-expand, send button glow Settings & forms (Phase 5): - iOS-style toggle switches for boolean settings - Input focus glow, save feedback spring animation - Welcome card with gradient background + proper spacing - Sticky settings group headers with glass backdrop Accessibility & mobile (Phase 6): - Animated focus ring, prefers-reduced-motion global kill-switch - Touch target audit (44px min), mobile bottom-sheet modals - Mobile bottom tab bar, toast redesign (icon + border + countdown) - Thread hover translateX, badge in_progress pulse Bug fixes: - Gateway/TEE popover z-index (tab-bar z-index: 200, popovers 500) - Connection lost banner as fixed top bar instead of flex child - Sidebar collapse keeps toggle + new thread buttons visible - Downgrade noisy startup logs (db, webhook, vector) to debug - Remove green dot pulse animation on connected status - Deduplicate confirm-modal in HTML, add tab-indicator div Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(web): mobile layout improvements — sidebar toggle, settings drill-down, tab bar polish - Fix mobile sidebar toggle: use expanded-mobile class instead of collapsed, add backdrop overlay, auto-close on thread select, outside-click dismiss - Settings: replace cramped horizontal tabs with drill-down navigation (category list → detail view → back button) - Bottom tab bar: add glass morphism, hide theme toggle, flip tab indicator to top edge - Keep thread toggle button visible in collapsed 36px sidebar strip Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(repl): interactive approval selector and transient status lines - Replace ASCII-art approval box with clean horizontal rule card - Add inquire-based interactive selector for tool approvals (↑↓ + Enter) - Selector runs directly from send_status via spawn_blocking, with stdin_locked flag to prevent readline from competing for stdin - Transient thinking/tool-started lines: each replaces the previous, all erased before final output (no clutter left in scrollback) - Esc in selector sends denial so agent never gets stuck Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: widen TurnCost token fields to u64 and remove unused variable - Change input_tokens/output_tokens from u32 to u64 in StatusUpdate::TurnCost, SseEvent::TurnCost, and the thread_ops emit site to avoid truncation on large conversations - Remove unused _routine_engine_for_loop binding in agent_loop.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: reduce startup log noise — demote info to debug Demote routine startup messages (builder, WASM tools, tunnel, WASM channels) from info to debug so the default log output stays clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(web): allow CDN scripts in CSP connect-src directive Add cdn.jsdelivr.net and cdnjs.cloudflare.com to connect-src so the browser can fetch marked.js and DOMPurify without CSP violations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: fix cargo fmt in repl.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(web): gate turn_cost SSE handler on current thread Prevents cost badge from attaching to the wrong message when switching threads or receiving events from background threads. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: retrigger CI * fix: add missing extension_manager to webhook EngineContext The webhook trigger path added in #736 was missing the extension_manager field introduced by #1453. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: ignore RUSTSEC-2026-0049 rustls-webpki CRL advisory Low impact — requires compromised CA to exploit. Tracked for upstream rustls-webpki upgrade. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(routines): use fields.join for cron normalization Use split_whitespace fields instead of re-trimming the original string to avoid preserving extra internal whitespace in cron expressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(repl): Apple-style approval card — clean vertical flow - Drop verbose tool description (the command IS the decision surface) - Unified vertical pipe layout: ◆ header → │ params → │ selector - Selector options show keyboard shortcuts inline: Approve (y) - Compact help message, answered state uses └ to close the flow - No horizontal rules, no blank-line padding — just breathing room Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(repl): replace inquire with crossterm for approval selector Drop the inquire dependency (which pulled in crossterm 0.25, duplicating the existing 0.28). The 3-option approval selector is now built directly with crossterm raw mode — same UX, zero new dependencies. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore(deps): upgrade crossterm 0.28 → 0.29, eliminate duplication termimad (via crokey) uses crossterm 0.29. Upgrading our direct dependency from 0.28 to 0.29 collapses to a single crossterm version in the dependency tree. Also migrated termimad::crossterm:: references to the direct crossterm import. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address review comments — box_top off-by-one, smart_truncate overflow, mobile theme toggle - Fix box_top() fill calculation: was off-by-one, producing boxes 1 char too wide (fmt.rs) - Fix smart_truncate(): account for "..." in the budget so output never exceeds max_chars (repl.rs) - Move theme toggle to settings sidebar on mobile instead of display:none, so mobile users can still switch themes (style.css, index.html, app.js) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt repl.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address review — retry duplication, CSP connect-src, deny color - Remove failed message before retry to prevent duplicate user messages - Revert connect-src to 'self' — CDN hosts only need script-src - Use red for Deny confirmation in REPL approval selector Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…894) (#924) * perf(agent): avoid preview allocation on non-truncated strings * Update src/worker/container.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * chore(ci): annotate test assertions for no-panics gate * fix: remove unnecessary allocation and consolidate tests - Remove redundant `.to_string()` on `&String` in container.rs error arm - Bind `format!()` result to a let in job.rs to avoid Cow borrowing from temporary - Merge borrowed/owned Cow assertions into existing tests, drop misleading comments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: restore separate test functions for CI regression check Keep dedicated `test_truncate_short_string_borrows` and `test_truncate_long_string_owns` tests so the PR diff contains new `#[test]` functions, satisfying the regression test enforcement check. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: ilblackdragon@gmail.com <ilblackdragon@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Code reviewFound 6 issues:
In
In
Two
In
The code calls
The web frontend uses |
* refactor(llm): move transcription module into src/llm/ Transcription is an LLM capability (Whisper, Chat Completions audio). Move it from a top-level module into src/llm/transcription/ to reflect this, and update all references across the codebase. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: fix rustfmt formatting after module move Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(tests): eliminate env mutex poison cascade and fix test flakiness
The shared ENV_MUTEX used by ~68 config tests would cascade a single
test panic into failures across every module. Replace all .unwrap() /
.expect() lock acquisitions with a poison-recovering lock_env() helper.
Consolidate rogue module-local ENV_LOCK instances (workspace, orchestrator,
bootstrap) onto the shared global mutex to prevent cross-module races.
Also fixes:
- gateway user_id fallback was hardcoded to "default" instead of owner_id
- test_ironclaw_env_path used LazyLock which is order-dependent
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(helpers): add regression test for lock_env poison recovery
Satisfies the regression-test-check CI gate by adding a test that
intentionally poisons ENV_MUTEX and verifies lock_env() recovers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): detect test changes inside #[cfg(test)] regions
The regression test check relied on git diff -W to expand context to
function boundaries, but git doesn't recognize Rust `mod tests {}` as a
function boundary. Changes to imports, helpers, or lock calls inside
test modules were invisible to the check.
Add a line-level fallback: for each changed .rs file, find where
#[cfg(test)] starts and check if any diff hunk targets a line at or
after that boundary. This catches edits anywhere inside test modules
regardless of git's language awareness.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review feedback
- Clear ENV_MUTEX poison after regression test so it doesn't leave
global state dirty for subsequent tests.
- Fix CI regression-test-check to match #[cfg(test)] only when followed
by `mod` (the test module pattern), avoiding false positives from
standalone #[cfg(test)] items like statics or functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mcp): handle empty 202 notification acknowledgements * test(mcp): tighten accepted response regression coverage * Update src/tools/mcp/http_transport.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
#893) (#926) * perf(tools): remove unconditional params clone in shared execution * Update src/tools/execute.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * chore(fmt): apply rustfmt in worker container tool execution * fix(tools): restore owned param call sites * fix(tools): pass normalized_params to tool.execute() instead of raw params The ownership refactor accidentally passed the un-coerced `params` to `tool.execute()` while validation ran against the coerced `normalized_params`. This meant tools received un-normalized input (e.g. stringified JSON arrays instead of actual arrays). Since `normalized_params` is owned and unused after the execute call, passing it directly achieves the original zero-clone goal without breaking parameter coercion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tools): update empty-tool-name test for owned params signature Adapts the test_execute_empty_tool_name_returns_not_found test (added on staging) to pass owned Value instead of &Value, matching the new execute_tool_with_safety signature. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: ilblackdragon@gmail.com <ilblackdragon@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…1242) * fix: generate Mistral-compatible 9-char alphanumeric tool call IDs Mistral's API requires tool call IDs to match [a-zA-Z0-9]{9} exactly. Previously, IDs like 'turn1_0', 'recovered_0', 'call_<uuid>', and 'generated_tool_call_N' were generated, which Mistral rejects with HTTP 400. Add generate_tool_call_id() that produces deterministic 9-char base-36 IDs from two seed values, and use it at all tool call ID generation sites. Fixes #1241 * Update src/llm/provider.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: address review feedback on Mistral tool-call ID generation - Remove .unwrap() in generate_tool_call_id (provider.rs) per zero-tolerance policy - Remove .expect() in normalized_tool_call_id (rig_adapter.rs), use direct array indexing - Replace magic constant 99 with named RECOVERED_TOOL_CALL_SEED in reasoning.rs - Add tests for normalized_tool_call_id: passthrough, hashing, empty/whitespace, determinism - Add comment explaining intentional use of turn_idx vs turn.turn_number in session.rs - Fix duplicate `mod tests` block in provider.rs (pre-existing compile error) - Update stale test assertions expecting old `generated_tool_call_` prefix format [skip-regression-check] * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Illia Polosukhin <ilblackdragon@gmail.com>
* docs(feishu): clarify webhook-only event subscription support * Update channels-src/feishu/feishu.capabilities.json Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Fix owner-scoped message routing fallbacks * Address PR feedback on routing regressions * Address review notes on routing fallbacks
* feat(workspace): multi-scope workspace reads Adds the ability for a workspace to read from multiple user scopes while keeping writes isolated to the primary scope. Configuration via WORKSPACE_READ_SCOPES env var (comma-separated user IDs). Includes identity file isolation (read_primary), multi-scope search, list, and read operations, WorkspaceConfig refactor, and comprehensive integration tests. * fix: address review feedback for multi-scope workspace reads - fix(memory): deduplicate timezone parsing for daily_log target parse_timezone was called twice when target was "daily_log" without a layer — once in path resolution, again in the fallback. Now computed once and reused. - fix(config): add character validation for WORKSPACE_READ_SCOPES and layer scopes — both enforce [a-zA-Z0-9_-] to prevent path traversal or injection via scope strings used as user_id in SQL queries. - fix(config): use chars().take(32) instead of byte-index slicing for scope length error messages (UTF-8 safety). - fix(error): remove unused WorkspaceError::NotFound variant Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: downgrade search log to debug, add comments on list iteration - Downgrade hybrid_search_multi tracing::info! to debug! — fires on every multi-scope search with the default backend, too noisy for info - Add comments explaining why list/list_all iterate per-scope instead of using _multi trait methods (identity path filtering needs scope attribution that merged results lose) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: ilblackdragon@gmail.com <ilblackdragon@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…1165) * fix: Google OAuth URL broken when initiated from Telegram channel * test: validate OAuth URL parameters for bug #992 Add comprehensive OAuth URL parameter validation tests for bug #992 (Google OAuth URL broken when initiated from Telegram channel). Tests verify: - Correct parameter names (client_id not clientid) - All required OAuth parameters present - Google OAuth spec compliance - CSRF state uniqueness per request - Extra parameters from capabilities preserved - URL parameter escaping Consolidates tests into tests/e2e/scenarios/ with improved fixture approach (session-scoped installed_gmail, auth_url, oauth_params fixtures for efficiency). Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * review fixes --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com> Co-authored-by: firat.sertgoz <f@nuff.tech>
…der) (#1043) * feat(cli): add ironclaw models subcommands (list/status/set/set-provider) Implements model management CLI (part of #83): - `models list [provider] [--verbose] [--json]` — list providers; fetches live model list from the provider API when a specific provider is given - `models status [--json]` — show active provider/model - `models set <model>` — set default model with validation - `models set-provider <id> [--model <name>]` — set provider with alias normalization - fix conflicts * fix(deps): update tar to 0.4.45 (RUSTSEC-2026-0067, RUSTSEC-2026-0068) --------- Co-authored-by: firat.sertgoz <f@nuff.tech>
* Fix REPL single-message hang and cap CI test duration * Fix Clippy nested-if lint in REPL startup * Fix single-message approval flow * Handle empty single-message REPL exits * Wait for one-shot event routines before exit * Fix MCP lifecycle trace user scope * Normalize cron schedules on routine create
…3131 chore: promote staging to staging-promote/ab0ad948-23563320113 (2026-03-25 21:37 UTC)
…0113 chore: promote staging to staging-promote/c949521d-23562109203 (2026-03-25 20:47 UTC)
…9203 chore: promote staging to staging-promote/0341fcc9-23558273569 (2026-03-25 20:19 UTC)
…3569 chore: promote staging to staging-promote/6daa2f15-23538193544 (2026-03-25 18:47 UTC)
…3544 chore: promote staging to staging-promote/82822d7b-23516534944 (2026-03-25 12:01 UTC)
…4944 chore: promote staging to staging-promote/59014516-23505370929 (2026-03-24 23:13 UTC)
…0929 chore: promote staging to staging-promote/d3d517fd-23491969691 (2026-03-24 18:16 UTC)
…9691 chore: promote staging to staging-promote/fb354895-23477842664 (2026-03-24 14:04 UTC)
…2664 chore: promote staging to staging-promote/fa51b9f5-23468747429 (2026-03-24 07:59 UTC)
…7429 chore: promote staging to staging-promote/dea789cc-23455694329 (2026-03-24 01:54 UTC)
…4329 chore: promote staging to staging-promote/485d1568-23439773006 (2026-03-23 19:48 UTC)
…3006 chore: promote staging to staging-promote/d9358b0f-23426138451 (2026-03-23 13:43 UTC)
…8451 chore: promote staging to staging-promote/abba0831-23415935143 (2026-03-23 07:37 UTC)
…5143 chore: promote staging to staging-promote/fbce9a5f-23403885064 (2026-03-23 01:32 UTC)
…5064 chore: promote staging to staging-promote/1a62febe-23398066063 (2026-03-22 13:21 UTC)
2f80b7b
into
staging-promote/86388958-23397163010
…3398066063 chore: promote staging to staging-promote/86388958-23397163010 (2026-03-22 07:15 UTC)
…3398066063 chore: promote staging to staging-promote/56dc74eb-23397163010 (2026-03-22 07:15 UTC)
Auto-promotion from staging CI
Batch range:
0d1a5c210b877f89bcb87e6f1d8584396d12f208..1a62febe67cbf0fafffa3f6ee35fe751d39a5a4dPromotion branch:
staging-promote/1a62febe-23398066063Base:
staging-promote/86388958-23397163010Triggered by: Staging CI batch at 2026-03-22 07:15 UTC
Commits in this batch (16):
ironclaw hooks listsubcommand ( feat(cli): addironclaw hooks listsubcommand #1023)Current commits in this promotion (2)
Current base:
staging-promote/86388958-23397163010Current head:
staging-promote/1a62febe-23398066063Current range:
origin/staging-promote/86388958-23397163010..origin/staging-promote/1a62febe-23398066063Auto-updated by staging promotion metadata workflow
Waiting for gates:
Auto-created by staging-ci workflow