Commit Graph

9611 Commits

Author SHA1 Message Date
xingzhou
75982be9a3 fix(cli): oversized secrets plans consume unbounded memory (#109652)
* fix(cli): reject oversized secrets plan files

* fix(cli): keep generated secrets plans applyable

* fix(cli): reject special plan files without blocking

* docs(cli): refresh secrets plan documentation map
2026-07-18 07:18:21 +01:00
Peter Lee
8539640abc fix(config,secrets): emit JSON errors and cover dotenv roots (#104340)
* fix(secrets): use resolveStateDir for .env path to cover legacy .clawdbot dir

* fix(secrets): replace override-based legacy .env test with true automatic fallback, add apply-path coverage

* fix(config-cli): emit JSON error on config get --json for missing paths

When  is used with a nonexistent
path, the command emits no JSON on stdout, only a text error on stderr.
This breaks automated consumers that expect machine-readable errors.

Fix: output  JSON to stdout before exit(1) when
opts.json is set. This matches the existing JSON error output pattern
already used by runConfigValidate and handleConfigMutationError.

Also re-throw synthetic exit errors in the catch block so the
--json branch's writeRuntimeJson+exit is not caught and re-emitted
as a text error.

* fix(config-cli): use typed ExitError signal instead of __exit__ string sentinel

* fix(secrets): reuse resolved stateDir for .env path in audit

* fix(secrets): pass resolved stateDir into apply .env scrubbing, add root-switch regression

* test(config-cli): migrate remaining __exit__ sentinel to ExitError

* fix(secrets): cover config and state dotenv roots

* style(secrets): format dotenv path helper

* test(secrets): track temporary directories

* test(config): expect typed exit for missing patch files

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-17 23:14:05 -07:00
Shakker
e613fd31bb docs: document Codex runtime availability checks (#110447) 2026-07-18 07:13:45 +01:00
Peter Steinberger
deddeb3dac feat(sqlite): move quarantine decisions to a dedicated store that survives primary database damage (#110453) 2026-07-18 07:13:43 +01:00
Peter Steinberger
723f5ba4fc improve(ui): restructure Settings around user-facing pages with full agent parity (#110445)
* refactor(ui): restructure Settings IA around user-facing pages

Settings sidebar shrinks to settings-only destinations grouped by attention:
General/Appearance/Notifications up top, Connections, Agents & Tools,
Privacy & Security, System. Sessions, Worktrees, Activity, and Memory
Import leave the takeover: Sessions/Activity return to the workspace
sidebar, Worktrees becomes a Sessions hub tab, Memory Import is reached
from the Agents memory panel. Model Setup becomes a Models subpage.

New config pages: Notifications (web push), Privacy & Security (curated
policy rows + security/approvals schema sections), Advanced (uncurated
schema sections + raw editor, replacing the General quick/advanced
toggle). General slims to model defaults, language, and gateway host;
identity moves to Profile, lobster appearance rows to Appearance.

* feat(agents): widen system-agent config writes to operator parity

Every config surface the Control UI can edit is now agent-writable behind
the exact-operation human approval gate, except a small documented
denylist ($include, auth, env, models, secrets). tools.* and
plugins.entries.* writes are allowed; plugin_uninstall works for plugins
that provably do not back the active default inference route (fail closed
otherwise); set_default_model takes an optional agentId and live-tests a
per-agent model with the same rigor as the default route. Per-agent
routing fields on non-default agents are direct-writable; the default
agent's route keeps the verified set_default_model/onboard paths. A new
config-write-parity contract test forces explicit classification of every
top-level config key.

* feat(ui): sync operator display prefs through config ui.prefs

Theme, theme mode, text scale, locale, and chat display prefs get a
canonical server-side home in config ui.prefs. The Control UI mirrors
them into localStorage for instant boot, writes local changes through to
the gateway (best-effort; viewer-scope or offline clients stay
device-local), and applies server-side deltas on connect and on every
config snapshot reload — so an agent changing the theme through the
approval gate takes effect in the UI, and prefs follow the operator
across devices.

* chore: prune quick.ts from max-lines baseline after slim-down

* style: oxfmt changed files

* chore: regenerate plugin-sdk api baseline for ui.prefs config surface

* fix: dedupe runPluginUninstall dep type and narrow locale extraction

* docs: update Control UI settings structure and ui.prefs sync

* fix: address autoreview findings on parity guards and prefs sync

- plugins.entries.* config writes get the same active-route ownership
  check as plugin_uninstall (fail closed when unprovable)
- system-agent prompt now describes the guarded write policy instead of
  the old blanket refusals
- per-agent set_default_model logs the agent-scoped label
- legacy /config?section=... deep links redirect to the Advanced page
- prefs sync: pushes coalesce and drain serially (no CAS races dropping
  updates), replaced config hashes mark pre-patch snapshots as stale, and
  the last-seen server value persists per gateway scope so reloads cannot
  revert unpushable viewer-scope edits
- lint: theme membership checks use Sets

* fix: harden uninstall route guard and scope prefs queue per gateway

- plugin uninstall ownership now covers execution owners (runtime policy,
  embedded harness override) in addition to the provider, and re-verifies
  inside the commit boundary so a concurrent route switch cannot slip a
  destructive uninstall past the pre-approval check
- prefs push queue binds to one gateway client; switching gateways drops
  the old queue (device-local fallback) instead of cross-writing prefs

* style: top-level type import in config-page test

* fix: close review races in config-write guards and prefs reconciliation

- config_set/config_set_ref re-verify the inference-route guard inside
  the commit boundary so conditional verdicts (per-agent routing, plugin
  entries) cannot be flipped by a concurrent edit after approval
- server prefs apply per changed field, so a server change to one pref
  no longer reverts unpushable local edits of the others
- replaced-hash staleness retires once post-patch state is observed, so
  a genuine restore of the pre-patch config becomes authoritative again
- moved-section deep links (communications notifications, automation
  approvals) redirect to their new pages

* style: satisfy no-useless-assignment and loop-condition lints in prefs sync

* fix(ci): resolve unhandled profile-test rejections and knip unused exports

The profile page's new identity section reads context.config; the test
context mock now provides it, eliminating the unhandled rejections that
failed checks-ui and the compact-large shard. Exports flagged by the
dependency gate (extract/patch helpers, section-key and prop types) go
module-private; extraction coverage moves behind applyServerUiPrefs.

* refactor(agents): move config-write policy to its own module

The static path classifier and documented denylist move to
config-write-policy.ts, shared by the execution guard and the parity
contract test — no test-only exports left for the dependency gate to
flag. Blocked-root refusals now cite the denylist's documented
escalation for that root.
2026-07-18 07:03:31 +01:00
Peter Steinberger
8992f92dab feat(gateway): idempotent start, non-interactive stop guard, unified lifecycle audit (#110323)
* feat: guard gateway lifecycle mutations

* fix: harden gateway lifecycle mutation guards

* fix: harden gateway lifecycle audit safety

* fix(cli): repair gateway lifecycle checks

* fix(cli): satisfy lifecycle CI gates
2026-07-18 07:01:38 +01:00
Peter Steinberger
8ae1581798 feat(clients): provider-grouped model picker with fast, verbosity, and inherited-thinking controls (#110339)
* feat(clients): provider-grouped model picker with fast, verbosity, and inherited-thinking controls

* chore(i18n): translate model-control strings and regenerate platform catalogs

* feat(clients): inherited-default restore for fast mode and verbosity controls

* fix(clients): preserve control state in thinking snapshots and persist inherited verbosity

* chore(i18n): resync native inventory after rebase onto message-reader main

* chore(i18n): realign locale artifacts after rebase onto message-reader main

* refactor(clients): drop superseded fast-mode accessors and picker convenience flagged by periphery

* chore(i18n): resync inventory line refs after dead-code removal
2026-07-18 07:01:31 +01:00
DaigoSoup
7a61f728bf fix(update): keep gateway healthy during concurrent updates (#108925)
* fix(update): prevent concurrent managed handoffs

* test(update): type managed handoff mock

* fix(update): reject concurrent handoff continuations

* refactor(update): clarify managed handoff ownership

---------

Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-07-17 22:56:09 -07:00
Peter Steinberger
442c166122 refactor(sessions): replace ambient watch sentinels with provenance (#110428)
* refactor(sessions): store watch provenance in cursors

* style(docs): align database schema table

* refactor(state): use Kysely for watch migration

* style(state): remove redundant timestamp casts
2026-07-18 06:55:29 +01:00
Peter Steinberger
746d257f05 feat: contract sessions-family tool outputs (#110424)
* feat(agents): contract sessions-family tool outputs

* refactor(agents): remove unused fast-mode exports
2026-07-18 06:43:12 +01:00
Peter Steinberger
3e74534a70 fix(channels): keep healthy accounts running when credential files fail (#110360)
* fix(channels): isolate unavailable credential files

* fix(channels): complete credential file type contract

* fix(channels): preserve credential path handling

* test(channels): cover credential file edge cases

* fix(channels): ignore blank credential file paths

* test(secrets): keep empty credential files unavailable

* test(googlechat): keep temp cleanup plugin-local

* fix(channels): keep credential diagnostic internal

* chore: defer release note to release automation
2026-07-18 06:27:59 +01:00
Peter Steinberger
b9c5c7c9fc feat(agents): contract filesystem tools for code mode (#110395) 2026-07-18 06:26:04 +01:00
Peter Steinberger
3997a996d4 fix(codex): bound app-server resume history (#110396)
* fix(codex): harden app-server resume protocol

* chore(codex): defer release note to release process

* fix(codex): align bounded resume checks
2026-07-18 06:25:17 +01:00
Peter Steinberger
f31de78ba6 fix: stop node alerts replaying after Gateway restart (#110391)
* fix(gateway): silence known node reconnect alerts

* fix(gateway): atomically claim node connections

* fix(gateway): type node connection claim results

* test(gateway): cover legacy node identity migration

* test(gateway): satisfy node migration lint
2026-07-18 06:20:24 +01:00
Peter Steinberger
1c225c855d fix: CLI timeout warnings explain stopped work (#110369)
* fix: clarify CLI timeout failures

* docs: update timeout docs map
2026-07-18 06:18:11 +01:00
Peter Steinberger
bee40b9e8e fix(messaging): align lifecycle follow-ups (#110413) 2026-07-18 06:14:24 +01:00
Peter Steinberger
a89f01abf4 perf(sqlite): fast schema gates, background integrity verification, and downgrade protection (#110271)
* perf(sqlite): gate schema version before integrity scans and quarantine terminal open failures

* feat(gateway): refuse incompatible database schemas at boot and verify integrity in the background

* feat(update): refuse installing builds that cannot open the current databases

* docs: add database schema reference with version history and downgrade guidance

* test(update): tolerate optional runner options in git-mutation mocks

* refactor(update): split npm package-target metadata out of update-check

* chore: model verifier internals for knip and regenerate docs map

* chore(i18n): resync stale iOS localization catalog

* chore: allowlist read-only preflight and verifier raw SQLite access
2026-07-18 05:49:39 +01:00
Peter Steinberger
9dec7acc91 feat(macos): visible-markdown copy, full-message reader, and independent reasoning/tool toggles (#110276)
* feat(clients): copy visible markdown, full-message reader for truncated messages, and independent reasoning/tool toggles

* chore(i18n): translate new reader and trace strings and regenerate catalogs

* test(ios): adopt reader display-options API in render smoke tests
2026-07-18 04:05:50 +01:00
Peter Steinberger
ff9cb0f679 fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies (#110225)
* fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies

* chore(onboarding): document deliberate dmScope personal-agent default

* docs(security): align formal-verification dmScope claim with the personal-agent default
2026-07-18 03:54:45 +01:00
Vito Cappello
cd1ab40632 fix: gateway boots when a configured plugin payload is broken (#110239)
* fix: quarantine broken plugins during gateway startup

* fix(plugins): preserve degraded boot on package read errors

* fix(gateway): emit quarantine diagnostic once

* fix(gateway): refresh plugin quarantine every boot

* fix(gateway): harden plugin payload quarantine

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* fix(ci): satisfy plugin quarantine checks

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 03:50:50 +01:00
Peter Steinberger
90b4a12ee9 feat(linux): Quick Chat agent switcher, avatars, per-agent routing, and configurable shortcut (#110285)
* feat(linux): expand Quick Chat agent controls

* docs(linux): document Quick Chat controls

* fix(agents): keep avatar summary additive

* refactor(linux): trim Quick Chat dead Default impl and speculative focus-failure recovery

* fix(linux): destroy the Quick Chat window when hide fails after a rejected focus grab

* fix(linux): fail Quick Chat sends when the pinned agent vanishes; classify avatar-only identities as config-derived

* docs(linux): note the accepted cache-fresh send-validation tradeoff

* style: satisfy no-map-spread and rustfmt in Quick Chat parity surfaces
2026-07-18 03:44:49 +01:00
Peter Steinberger
19296b003b improve(agents): normalized web_search output contract with boundary-owned wrapping (#110308)
* feat: normalize web search output contract

* refactor(agents): promote web_search contract from a dedicated output module

* fix(agents): wrap unwrapped web_search text and pass unknown provider payloads through as raw

* fix(agents): gate web_search results branch on conforming rows and cover metadata fields

* fix(agents): gate every provider text path at the web_search boundary

* test(agents): align web_search fixtures with boundary-owned wrapping

* fix(agents): make the web_search boundary own the untrusted-content envelope

* fix(agents): report declared web_search errors first and align the documented contract

* fix(agents): bind envelope stripping to real markers and densify result rows

* fix(agents): emit canonical urls and a closed error code from web_search

* fix(agents): keep structured provider error diagnostics in the wrapped message

* fix(agents): satisfy production export and lint gates for the web_search contract
2026-07-18 03:39:29 +01:00
Peter Steinberger
6a6d3465d8 improve: shorten release candidate validation (#110316)
* ci(release): shorten candidate validation critical path

* ci(test): parallelize memory extension lane

* ci(release): preserve read-only candidate validation
2026-07-18 03:39:03 +01:00
Peter Steinberger
53b53f1977 improve(agents): exact web_fetch output contract with cleaned result shape (#110223)
* feat: add web fetch output contract

* fix(agents): keep web_fetch contract schema module-local

* docs: refresh docs map for the web_fetch result section
2026-07-18 03:28:29 +01:00
Peter Steinberger
8c17d20cd9 improve(ci): preserve complete main validation during merge bursts (#110298)
* ci: serialize main and bound sticky caches

* fix(ci): pin cache warmer to validated SHA

* fix(ci): read current sticky retirement manifest
2026-07-18 03:27:54 +01:00
Peter Steinberger
125934addc feat(ios): harvest shared chat capabilities — verbosity, trace toggle, live talk level, sessions entry (#110254)
* feat(ios): wire verbosity, assistant trace toggle, live talk level, and chat-local sessions entry

* chore(i18n): translate new iOS chat strings and regenerate catalogs
2026-07-18 03:27:45 +01:00
Peter Steinberger
d8f2645c2c refactor(memory-wiki): move compiled cache to plugin state (#110167)
* feat(plugin-sdk): prepare memory prompts asynchronously

* refactor(memory-wiki): move compiled cache to plugin state

* fix(plugin-sdk): export memory prompt preparer type

* refactor(plugin-sdk): keep prompt preparer type private

* test(memory-wiki): isolate compiled cache state

* chore(memory-wiki): satisfy changed gates

* fix(memory): preserve prepared prompts across context engines

* docs(plugin-sdk): refresh API baseline

* fix(memory): revalidate prepared prompt ownership

* fix(codex): propagate sandboxed memory context

* test(memory-wiki): seed durable vault identity

* refactor(memory-wiki): keep cache lifecycle internal

* fix(memory-wiki): harden compiled cache publication

* style(memory-wiki): format cache lifecycle changes

* test(memory-wiki): support extension test lib target

* style(memory-wiki): remove redundant catch

* refactor(memory-wiki): keep vault generation helper private
2026-07-18 03:05:03 +01:00
mushuiyu886
8a234980ea fix(usage-bar): bound numeric verb arguments (#105297)
* fix(usage-bar): bound numeric verb arguments

* fix(usage-bar): preserve supported fixed precision

* fix(usage-bar): validate fixed precision

Co-authored-by: 杨浩宇0668001029 <yang.haoyu@xydigit.com>

* docs: refresh generated docs map

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:32:02 +01:00
Peter Steinberger
57a3739622 fix(ci): regenerate docs_map for the live-tests heading 2026-07-17 21:25:29 -04:00
Peter Steinberger
afcca01f40 feat(sessions): raise default session-store disk budget to 10 GiB (#110221) 2026-07-18 02:14:39 +01:00
Peter Steinberger
2ca4d92f1a docs: live-test gateway isolation policy (session-owned dev gateway, operator approval for real instances) 2026-07-17 17:55:33 -07:00
Peter Steinberger
a6102690dd perf(ci): cut the pre-fan-out critical path and bin canonical main runs (#110183)
* perf(ci): cut the pre-fan-out critical path on canonical runs

Two changes to the run head and matrix shape:

1. runner-admission was a hosted 90s sleep every run queued behind
(observed 1.7min hosted-queue latency before the sleep started). The
debounce now lives at the tail of preflight: heavy jobs all need
preflight, so a superseding main push still cancels the run before
fan-out while only one 4 vCPU runner has been spent, and preflight's
own work usually exceeds the window so the residual sleep is zero.
security-fast (hosted, dependency-free) starts immediately.

2. Canonical main pushes now use the compact bin plan like PRs: the
82-job named matrix drained the runner pool for ~4.5min (job starts
trickled from minute 5.2 to 9.7 in run 29592647843) with no
branch-protection consumer for per-shard names on main. Coverage is
identical; dispatch/release-gate runs keep the full named matrix.

* perf(test): boot TUI PTY suite fixtures concurrently

tsx+TUI startup dominated the harness file's wall time and the three
suite PTYs booted serially. Boot them concurrently in beforeAll
(allSettled so a failed boot still assigns survivors for afterAll
cleanup); the env-specific fixtures never receive input, so their tests
only await their own readiness output. The slow-startup test now proves
frame ordering on the append-only output, which the old sequential
waits did not. File wall 10.2s -> ~4.9s, 3/3 repeat runs green.

* docs(ci): align gate and debounce descriptions with the removed admission job

* test(tooling): wait for readiness file content, not existence

writeFileSync creates the file before its bytes land, so the existence
poll raced the child's write on loaded runners and read an empty ready
file (observed in compact-small-4, run 29615028678). Poll for non-empty
content at both readiness sites.
2026-07-18 01:05:07 +01:00
Peter Steinberger
d371ea1f01 perf(agents): wave-1 tool output contracts for code mode (#110215)
* feat(agents): keep output contracts complete across opaque schema leaves

* test(agents): add code mode schema-hint hot-path micro-benchmark

* test(agents): count raw-first inspection execs per tool in live bench

* feat(agents): expand compact output contract hints

* feat(agents): declare wave one tool output contracts

* docs(tools): list built-in output contracts

* fix(agents): bound union scans before literal-union analysis

* fix(agents): keep wave-1 contract schemas module-local and type-exact
2026-07-18 01:02:18 +01:00
Peter Steinberger
ec8f6e5e03 feat(browser): add secure per-tab copilot panel (#109817)
* feat(browser): add copilot security contracts

* fix(gateway): expose verified client identity to handlers

* feat(browser): add secure per-tab copilot panel

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* refactor(browser): separate copilot gateway hint custody

* fix(browser): preserve legacy pairing parse shape

* fix(browser): harden copilot lifecycle custody

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): enforce copilot lifecycle boundaries

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* style(browser): format copilot sources

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): preserve copilot consent revocation

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* refactor(browser): split copilot custody owners

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(browser): normalize websocket array buffers

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* chore(protocol): regenerate Swift gateway models

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* refactor(browser): model copilot runtime entrypoints

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): honor extension build boundaries

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(gateway): assert targeted chat delivery

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(gateway): cover targeted delivery calls

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): declare copilot build dependencies

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(ci): clear browser copilot gate failures

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(ci): cover copilot lint exclusion

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): gate copilot on relay custody

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(browser): bound copilot relay frames

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

---------

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>
2026-07-18 01:00:23 +01:00
Peter Steinberger
9a3231547b fix(macos): stop Canvas presents from stealing focus (#110245)
* fix(macos): stop Canvas presents from stealing focus

Agent-driven canvas.present/canvas.navigate activated the app with
NSApp.activate(ignoringOtherApps:), yanking keyboard focus from
whatever the user was doing. The Canvas panel's elevated window level
already keeps it visible without app activation, and user entry points
(AppNavigationActions) activate explicitly, so presentation now orders
the panel front without switching apps.

* fix(macos): order Canvas front without taking key focus

* fix(macos): drop showWindow from Canvas window presentation
2026-07-18 00:54:15 +01:00
Peter Steinberger
f7e386d26d feat(plugins): emit agent_settled when a session run fully quiesces (#110174) 2026-07-18 00:53:40 +01:00
Peter Steinberger
1607da89b7 fix: Claude CLI turns avoid observability overhead when unused (#110246)
* perf(agents): gate Claude CLI diagnostics on listeners

* refactor(infra): keep diagnostic listener state private

* fix(agents): bound serialized Claude diagnostics

* chore: remove release-owned changelog entry
2026-07-18 00:51:32 +01:00
Peter Steinberger
b0a2d02427 fix(ci): make plugin SDK API manifest mergeable (#110228) 2026-07-18 00:16:39 +01:00
WhatsSkiLL
9dedacf577 fix(android): restore the complete Wear companion experience (#110130)
* fix(android): restore full Wear companion UI

* chore(android): sync native i18n inventory

* fix(android): negotiate Wear companion capabilities

* chore(android): sync generated Japanese localization

* fix(android): preserve Wear reply notification setup

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): harden Wear conversation controls

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): preserve Wear control context

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): keep Wear sessions agent-scoped

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

* fix(android): isolate Wear conversation context

Co-authored-by: JARVIS-Glasses <whatsskilll@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 00:03:45 +01:00
Peter Steinberger
781913025b improve: stream native sessions as hosts finish (#110211)
* perf: stream native session catalogs by host

* fix: satisfy session catalog CI contracts

* fix: retain changed-session refresh timing

* fix: keep catalog refresh helpers private
2026-07-17 23:59:57 +01:00
Peter Steinberger
6903ab3d4f feat(mac): thread agent id through WebChat routes for global-scope sessions (#110118)
- WebChatRoute (sessionKey + normalized agentID) replaces string tracking in
  WebChatManager; window/panel reuse compares the full route; session-key
  callbacks retain the explicit agent and guard against stale controllers
- WebChatSwiftUIWindowController gains agentID; explicit selection feeds the
  existing MacGatewayChatTransport(defaultGlobalAgentID:)/initialActiveAgentID
  seams and is pinned against gateway-default refreshes
- AppNavigationActions.openChat(sessionKey:agentID:) route-aware; Quick Chat's
  Command-Return opens the accepted route's agent conversation (global scope
  included), retiring the v2 tradeoff comment
- tests: route reuse identity, explicit-vs-default precedence, navigation seam
2026-07-17 23:58:12 +01:00
Peter Steinberger
9a93a52a8a feat(onboard): recommendations store with once-semantics and self-naming bootstrap (#110173)
* feat(onboarding): persist app recommendations once

* feat(onboarding): add self-naming birth sequence

* chore(wizard): hoist bootstrap-defer imports to the top of the module

* docs(bootstrap): persist agreed identity into IDENTITY.md and SOUL.md as well

* docs: regenerate docs map after onboarding plan merge

* fix(wizard): reuse a pending stored offer instead of rescanning apps

* fix(onboard): deduplicate bootstrap recommendations
2026-07-17 23:42:01 +01:00
Peter Steinberger
ed2284c31a fix(macos): keep Canvas hidden for agent content operations (#110107)
* fix(macos): keep Canvas hidden for agent content operations

Agent canvas.evalJS, canvas.snapshot, and canvas.a2ui.* commands routed
through CanvasManager.show, which re-presented the panel and called
NSApp.activate(ignoringOtherApps:) on every content update. After a
gateway restart the hosted A2UI page is dead, so the next agent push
always re-opened a panel the user had closed and stole focus.

Content operations now use a non-presenting ensureController/prepare
path; only canvas.present, canvas.navigate, and user actions reveal the
panel. Snapshot is read-only: it requires a visible matching panel and
returns CANVAS_HIDDEN instead of mutating panel state (WebKit cannot
render ordered-out windows).

* chore(i18n): refresh native inventory line offsets
2026-07-17 23:40:35 +01:00
Peter Steinberger
e805dbb615 fix(signal): preserve newlines in debounced messages (#110090)
* fix(signal): use newlines in debounced messages

* docs: fix release gate command formatting
2026-07-17 23:35:05 +01:00
Peter Steinberger
5bab0c2ea8 feat(slack): support running as a real Slack user (user identity) (#109837)
* feat(slack): add user-identity config surface (session token/cookie)

Introduce an account-level identity discriminator ("bot" default | "user") for
the Slack channel, plus sessionToken/sessionCookie secret fields for the
browser-session (user) path. Schema enforces structural coupling only
(identity="user" rejects appToken/signingSecret/relay/non-default mode);
credential presence is deferred to runtime like bot/app tokens. Account entries
inherit the top-level identity. Adds env fallback (SLACK_SESSION_TOKEN/COOKIE,
default account only), secret-contract registration, provenance *Source fields,
and UI hints. Config surface only; resolver/transport are later phases.

* refactor(slack): identity-aware operation-token resolver + dedup

Route Slack read/write token selection through a single identity-aware
resolveSlackOperationToken: identity="user" selects the browser-session token
for both operations (companion cookie attached later at client construction),
identity="bot" keeps the exact userToken/botToken + userTokenReadOnly behavior.
Delete the duplicated token-selection gate in action-runtime and route direct
sends/DM opens through the shared resolver with identity-neutral error wording.
Behavior-neutral for bot identity; net non-test LOC -2.

* refactor(slack): retarget user identity to xoxp + companion app

Replace the abandoned browser-session (xoxc/xoxd) approach for identity="user"
with the official path: authenticate as the human via the existing userToken
(xoxp) while a companion app (appToken/socket or signingSecret/http) carries
events. Remove sessionToken/sessionCookie config, env vars, secret-contract
entries, resolver fields, and their tests. Invert the schema coupling so
identity="user" permits the companion-app transport credentials, and drop the
now-vestigial user-identity structural guard entirely (identity is a permissive
discriminator; credential presence is a runtime concern). Resolver returns the
user token for user-identity reads and writes. Behavior-neutral for bot
identity.

* feat(slack): user-identity provider transport (xoxp + companion app)

Wire the identity="user" event transport. The companion Slack app runs Socket
Mode (appToken) or HTTP (signingSecret) while Bolt authenticates as the human
via the user token (no bot token). Startup auth.test runs on the user token and
its user_id becomes the self/mention target and self-send dedupe id (Bolt's
lazy per-event authorize populates context.botUserId=user_id, so the existing
self-event middleware drops the human's own messages). Identity-aware token
requirements and diagnostics; the bot-token identity warning is suppressed for
user identity. Behavior-neutral for identity="bot".

* feat(slack): user-identity setup, doctor, and docs

Add the setup wizard, doctor/status, and documentation for identity="user".
The wizard collects a user token plus the companion-app transport credential
(app token for socket, signing secret for http) and only persists identity when
"user" so bot setups keep byte-identical generated config; doctor validates the
user token via auth.test and warns on a missing transport credential; account
inspection reports user-token status. Message actions are gated on the active
identity's credential so user accounts expose actions. Docs add the exact
companion-app recipe (user scopes, on-behalf-of-user message events, socket/http
examples, the DM/group-DM-only-via-user-scope note, and self-send dedupe).
Behavior-neutral for identity="bot".

* test(slack): isolate user-identity provider tests to fix parallel flake

The new user-identity provider tests shared the globalThis-stored Slack test
client/handlers across files under parallel isolate:false, so their reaction
closures could reference a prior file's state and intermittently fail sibling
monitor tests (monitor.tool-result reactions). Track started monitors and
abort/await them all in afterEach (even on failed assertions), reset the shared
auth.test/mock state, and dispose the global Slack test runtime per file via a
new disposeSlackTestRuntime helper. Full Slack suite green across repeated
parallel runs.

* fix(slack): regenerate channel config metadata after rebase

* fix(slack): resolve setup consistent-return and doctor dead-export lint

* style: format install script test

* docs(slack): regenerate docs map for user-identity section

* test(slack): use renamed createSlackBoltApp token param in interop test

The rebase folded main's new wrapReceiver test into the renamed
createSlackBoltApp signature (botToken -> token); update the call site.
2026-07-17 23:23:21 +01:00
Peter Steinberger
241143262a fix(ci): script-only changes cold-start every Node job (#110158)
* fix(ci): keep sticky deps warm across script edits

* fix(ci): register dependency fingerprint entrypoint

* fix(ci): distinguish missing fingerprint inputs

* fix(ci): invalidate delegated workspace scripts

* fix(ci): harden cold install recovery

* fix(docs): escape release gate placeholder

* fix(ci): reject unaudited dependency hooks
2026-07-17 23:05:16 +01:00
Peter Steinberger
da44d52ac6 feat: ask_user — structured questions from the agent with web card, channel buttons, and text answers (#109922)
* feat(gateway): add transient question runtime (question.* methods + broadcasts)

* feat(agents): add blocking ask_user question tool with chat prompt delivery and text-reply claim

* feat(ui): interactive in-thread question cards for ask_user

* feat(channels): native tap-to-answer buttons for ask_user on Telegram, Discord, and Slack

* feat(ui): unify codex and gateway question cards with interactive gateway answering

* refactor(agents): collapse ask_user pending state to one registry; docs for ask_user

* fix(agents): include ask_user in normal gateway runs; add question-flow control-ui e2e

* test(ui): avoid credential-shaped fixture in question card test

* refactor(ui): reorder stream-group context keys

* fix(gateway,ui): validate question answers at resolve; reject secret/duplicate-label questions; UI retry and reconnect hardening

* fix(gateway,agents): canonicalize accepted option answers; bound ask_user option labels to 64 chars

* chore(ci): prune unused question exports, allowlist mobile question events, fix discord lint

* chore(ci): regenerate protocol/i18n/docs/tool-display artifacts for question surface

* fix(protocol): flatten QuestionRecord for native codegen; drop TS-only alias from schema registry

* chore(android): regenerate ask-user localization resources

* docs: regenerate docs map after rebase

* fix(ci): avoid stale read-only dependency disks

* test: remove stale reef lint suppression ratchet

* fix(ci): keep source locale drift advisory in release gates

* fix(ci): scope locale advisory handling to parity check
2026-07-17 22:24:17 +01:00
Peter Steinberger
e7f4b99394 docs(onboarding): refresh redesign plan — shipped flow, landing playbook, phase 3 merged (#110121)
* docs(onboarding): refresh redesign plan — shipped flow, landing playbook, phase 3 merged

* docs: refresh generated docs map

* docs: correct onboarding trust and auth notes
2026-07-17 21:43:17 +01:00
Alex Knight
ddb4ed9a47 feat: trace Claude Code CLI model calls (#108304)
* feat: trace Claude CLI model calls

* fix: align Claude CLI trace hierarchy

* fix: distinguish model request and turn telemetry

* fix: satisfy diagnostics CI checks

* fix: distinguish agent-turn telemetry

---------

Authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-07-18 06:23:49 +10:00
Peter Steinberger
433b3ce86d fix(line): await deferred ingress release on stop (#110104)
* fix(channels): await abandoned ingress claims

* fix(channels): preserve abandonment boundaries
2026-07-17 20:56:17 +01:00