Commit Graph

687 Commits

Author SHA1 Message Date
Peter Steinberger 4a846f1d61 refactor(reef): remove obsolete JSONL protocol stores (#129698)
* refactor(reef): remove obsolete JSONL protocol stores

* test(reef): remove orphaned protocol test helper
2026-08-25 18:22:54 -07:00
Peter Steinberger c1bab399ab refactor(cli): consolidate image option validation (#129463) 2026-08-25 17:19:09 -07:00
Vyctor H. Brzezowski 64853b1a9d improve(control-ui): restructure the composer as a multiline surface (#124301)
* improve(control-ui): align composer stack with current main

* refactor(ui): isolate new-session permission state

* fix(ui): close composer CI regressions

* test(ui): align composer presentation contracts

* test(ui): fix composer browser contracts

* test(ui): stabilize composer browser ownership

* test(ui): target presented mobile composer

* test(ui): select accessible mobile composer

* test(ui): open mobile rail session directly

* fix(ui): keep mobile composer content laid out

* fix(ui): address composer review findings

* fix(ui): close composer interaction gaps

* fix(ui): bound swarm task popover

* fix(ui): restore progress-card docking beside the wide composer

The multiline restructure dropped the .session-progress-card--dock
placement shipped in #129141 and left the completed marker inside the
collapsed-only summary span, so it vanished when the disclosure opened.
Restore the dock positioning block and hoist the marker into the
always-visible summary grid.

* fix(ui): bound swarm task popover by its composer anchor

The popover capped its height against the raw viewport, so on short
mobile viewports its top rendered above the screen. Register the swarm
group with the existing composer popover anchor observer and consume the
measured --chat-composer-popover-max-height, keeping the viewport calc
only as fallback. The new actual-tree mobile regression failed with
-71px top clipping before the fix.

* fix(ui): restore Draft capability controls and split the new-session composer

Restores the Draft option and selected-state indicators the capability
menu lost in the restructure, and moves the capability/visibility
controls into composer-capability-controls.ts so composer.ts drops back
under the 700-line lint gate (677 lines) without a suppression.

* test(ui): prove permission-mode final effect before session creation

Adds mocked-gateway proof that an admin's Full selection reaches
sessions.create as permissionMode:"full" exactly once, and that a
write-scoped operator's retained Full selection is rejected before
creation with a visible status notice and zero create requests. Also
aligns the mobile footer reading-order assertion with the shipped
attachments-draft-model order.

* test(ui): register swarm popover layout test as node-driven

chat-swarm-progress.browser.test.ts drives its own Playwright chromium
from node, but d3396c4d3b added it without registering it in
nodeDrivenBrowserLayoutTests, so the browser-mode chromium project tried
to fetch it into the page and failed on the node-only playwright import.
This was the deterministic checks-ui failure on both prior heads.

* test(ci): register codex attempt-startup-retry in its support lane

#129505 added extensions/codex/src/app-server/attempt-startup-retry.test.ts
without lane ownership, so the full-suite coverage guard
(test/vitest-projects-config.test.ts) fails on every full run. Register it
beside attempt-startup.test.ts in the attempt-support lane.

* test(ui): expect last-activity suffix in composer summary label

Merge weave: #129520 appends the accessible last-activity to the summary
aria-label; align the restructured composer card's assertion with it.

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-25 16:59:46 -07:00
Peter Steinberger b5864ba1db fix(skills): fail closed for unavailable remote Gateway (#117567)
* fix(cli): respect explicit Gateway ownership

* fix(gateway): fence offline CLI fallbacks

* fix(gateway): restrict local recovery closes

* fix(cli): preserve offline Gateway ownership and log recovery
2026-08-25 16:58:39 -07:00
Vincent Koc e66731ac08 refactor(agents): share media action resolution (#120014) 2026-08-26 07:52:28 +08:00
xingzhou b0526f7be7 fix(buzz): bound relay information responses (#119182)
Reject malformed relay metadata and cancel oversized response streams at the existing 16 MiB provider boundary.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-25 16:36:24 -07:00
Peter Steinberger 79532b5a4e refactor(plugins): remove obsolete compaction registry facade (#129565)
* refactor(plugins): remove obsolete compaction registry facade

Amp-Thread-ID: https://ampcode.com/threads/T-01a037b7-827c-72ea-b58b-6fef778d08fe

* test(plugins): reset runtime after compaction cases

Amp-Thread-ID: https://ampcode.com/threads/T-01a03a1a-d1fb-75ef-a904-7083040e37f1

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-25 16:03:55 -07:00
Vincent Koc b6a2366f64 refactor(qa): reuse canonical string normalization (#120566) 2026-08-26 06:41:08 +08:00
Peter Steinberger 9b7c95a0f0 fix(anthropic): keep automated heartbeats on subscription usage (#129513)
* fix(anthropic): keep automated heartbeats on subscription usage

* test(agents): align retired heartbeat template expectations

* fix(anthropic): avoid heavyweight policy bootstrap imports

* chore(config): prune retired template assertion baseline

* test(vitest): cover Codex startup test family

* refactor(anthropic): remove obsolete thinking-profile re-export
2026-08-25 14:11:38 -07:00
Sasan e9620fba9d fix(gateway): usage.status no longer waits on provider HTTP (#121799)
* fix(gateway): refresh provider usage asynchronously

* fix(ui): report a stalled provider-usage refresh on Model Providers

The page observed the incomplete-usage marker but discarded the exhausted
outcome, so once the retry budget was spent it rendered ordinary provider
cards with no usage and no explanation — indistinguishable from providers
that report no usage at all. Keep the outcome and render the warning the
Usage page already owns, reusing usage.providerUsage.stalled rather than
minting a Model Providers key so no locale baseline churns.

A user-initiated refresh now restarts the retry budget. The notice tells the
operator to refresh, so the button has to hand back attempts to spend; only
the forced path resets it, or the budget could never exhaust.

Also fixes tsgo:core:test on the current head: createStore's inferred literal
had no usageStats, so the run-bookkeeping case could not stamp it, and
view.test.ts needed the new prop.

Closes the ClawSweeper P2 at model-providers-page.ts:169-175.

* fix(ui): keep the stalled usage notice when usage.status starts rejecting

loadModelProvidersData turned a rejected usage.status into providerUsage:
null, which the page read as a completed load. observe(false) then reset the
retry budget and cleared the stalled callout, so a permanently broken usage
endpoint rendered as ordinary cards with no usage and no explanation — the
same silent failure the callout was added to prevent. The reset also fired
mid-cycle: one incomplete response followed by one rejection restarted the
budget, so the notice could be deferred indefinitely.

Record the failure at its producer instead of inferring it downstream. A null
providerUsage also means "not loaded yet", and no caller can tell the two
apart, so load.ts now reports providerUsageFailed explicitly and the page
treats a failed read as unresolved rather than resolved-empty.

Found by a Codex review of 417d43b65d.

* revert(gateway): drop the opportunistic model-catalog fast path

It broke two chat.history tests on main — both assert the cold catalog loader
runs exactly once, and reading the prepared snapshot first means it never does.
checks-node-compact-small-10 was red for that reason.

The change was a separate-surface latency fix that this PR picked up in passing,
and the body already offered to split it. Dropping it is the honest resolution:
rewriting main's assertions to accommodate a drive-by optimization would trade
one concern's proof for another's convenience. optional-model-catalog.ts,
server-model-catalog-auth.ts and their test return to the merge-base.

This PR is now only the usage.status non-blocking contract and its clients.

* fix(usage): preserve incomplete retry state

* perf(ui): keep usage capability startup-neutral

* fix(ui): restore provider usage retry convergence

* fix(usage): restore retry and cache invariants

* fix(usage): stabilize provider convergence

* test(ui): exercise provider recovery path

* test(ui): remove stale usage route fixture field

* fix(macos): show provider usage errors

* fix(macos): bound usage retries per menu open

* fix(macos): end usage retries on menu close

---------

Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
2026-08-25 13:20:10 -07:00
Ayaan Zaidi b0c27e2d8f fix(skills): fork the foreground session for lean experience review (#129282)
## What Problem This Solves

Skill Workshop experience review ran as an isolated agent with a re-rendered 60k-character transcript, its own bootstrap, and a trimmed tool surface. Every review was a cold request: no prompt-cache reuse, a large re-serialized trajectory, and a reasoning/tool profile that differed from the foreground turn. Autonomous updates could target any workspace skill, size limits allowed 40 KB skills to grow unchecked (one deployed workspace hit a 21 KB `SKILL.md`), the collection reviewer had to re-list every skill in its plan and read them under a fixed 24k-character budget (a 16-skill workspace failed every pass with "Read every current skill before reconciling"), collection review only recorded successes so a failing pass retried on every Gateway restart, and `openclaw skills curator status` showed nothing about what the last reviews did.

## Why This Change Was Made

- **Warm fork.** Experience review now continues the finished turn from the same in-memory session prefix (same session identity, bootstrap, skills prompt, tool schemas, `promptCacheKey`), appends one short review message, and runs with `sessionPersistence: "detached"` so nothing it writes reaches the foreground transcript or session record. Only `skill_workshop` executes; every other tool keeps its schema for cache parity and fails with a next-step message. The gate wraps the core tool list before Code Mode / Tool Search compaction, so catalog-hidden tools stay gated while `tool_call`/`exec` remain callable. `src/agents/embedded-agent-runner/run/attempt.skills-policy.test.ts` asserts identical system-prompt and tool digests between a foreground turn and its review, and that `tool_call` reaches `skill_workshop` but not `read` during review. Code Mode swarm globals (`phase`, `log`, `agents.run`) are the `sessions_spawn` capability and gate on the same allowlist, so a review cannot emit foreground lifecycle events or launch collectors. The review shares the foreground session, so it no longer retires that session's MCP runtime on run end; it reuses the warm runtime like any turn. Accepted tradeoff: the review inherits foreground tool construction (it creates the session MCP runtime only when the session has none, and spawns per-attempt LSP servers only when configured), because splitting tool construction from the foreground turn would break the cache-parity invariant this PR exists for.
- **One apply owner, rechecked at the write boundary.** `src/skills/workshop/autonomous-apply.ts` decides apply-vs-pending for both the post-review loop and foreground repair: creates and updates to Workshop-authored skills apply; updates to user-authored skills stay pending with a recorded reason. `applySkillProposalTransition` rechecks path-based ownership under the commit lock for non-operator actors (agent, or no actor), so a claim released after the pre-check cannot let an agent write a user-authored skill; gateway and CLI operators still approve any pending proposal. The user-authored pending write runs under the same commit lock and rereads the row, so an operator apply that lands first is kept. The old `auto-apply.ts` path and name-based `listWorkshopAuthoredSkillNames` are deleted.
- **Sparse collection plan and model-relative reads.** The collection reviewer returns only `write` and `drop` entries; unlisted skills stay untouched, so a 16-skill workspace no longer has to restate 16 keeps. The skill read budget is derived from the model's context window (35%) instead of a fixed 24k characters, with the 10,000-character skill cap still enforced per skill. No windowed read parameters: a skill is read whole or not at all.
- **Weekly cadence.** Collection review runs once every 7 days instead of daily (`REVIEW_INTERVAL_MS`), matching how slowly a skill library actually changes; the attempt is recorded before the model starts, so a failed pass does not retry on every restart.
- **Lean cap.** `AUTONOMOUS_SKILL_MAX_CHARS = 10,000` in `src/skills/workshop/collection-contracts.ts` is enforced by the tool and by collection reconcile; an oversized skill may only shrink. Tool description, experience prompt, and collection prompt were rewritten around procedures-not-records, one trigger per branch, and "NOTHING_TO_LEARN is the correct answer for most turns".
- **Detached runs end quietly.** A detached run writes no transcript or session record and runs under the foreground session key, so `attempt-finalize` now skips agent_end side effects for it: plugins do not observe the review as a foreground turn, and a deep review cannot schedule a successor review of itself.
- **Recorded outcomes.** Experience review records `applied | proposed | nothing | failed` with usage; one attempt per turn, drop on error. `openclaw skills curator status` prints the last collection and experience review outcome.

## User Impact

- Default `auto` mode: experience review reuses the foreground prompt cache and skips message/other tool execution, so review cost is one bounded continuation instead of a cold re-render.
- Autonomous edits touch only Workshop-authored skills; handwritten skills surface as pending proposals for operator approval.
- Autonomous `SKILL.md` results stay ≤ 10,000 characters.
- Collection review runs weekly and succeeds on larger skill libraries. A workspace with no recorded attempt reviews at the first daily check after Gateway start; an upgraded install keeps its recorded last attempt and reviews once it is older than 7 days. The 10,000-character cap applies to the next autonomous write; existing oversized skills are only ever shrunk.
- `openclaw skills curator status` shows the last collection and experience review outcome, time, and tokens.
- Docs: https://docs.openclaw.ai/tools/self-learning, https://docs.openclaw.ai/tools/skill-workshop

Related: #123866, #128871 both patch skills above the reviewer read budget; this PR caps autonomous skill size and restricts oversized skills to shrink-only rewrites.

## Evidence

- Live gateway (Linux, Telegram, `xai` provider) at `133ffe3`: manual experience review on a real foreground turn → `nothing` (usage: 0 uncached input, 13,902 cached, 36 output — the forked review hit the foreground prompt cache); manual collection review over the workspace → `succeeded`; the three oversized skills were rewritten under the cap (21,002 → 9,449; 11,882 → 7,735; 10,300 → 7,413 bytes, originals in `skill-workshop/collection-backups/`), the rest untouched, and the pre-PR "Read every current skill before reconciling" failure is gone. The next foreground turn's automatic experience review recorded `nothing` and `openclaw skills curator status` shows both outcomes. The apply recheck, MCP-runtime change (`26e821f`), and detached agent_end skip (`7e4a506`) landed after that run and are covered by the regression tests below.
- `pnpm test src/skills/workshop src/agents/tools/skill-workshop-tool src/gateway/server-methods/skills` plus `src/agents/embedded-agent-runner/run/attempt.skills-policy.test.ts`, `src/agents/embedded-agent-runner/run/attempt.tool-search-catalog-abort.test.ts`, `src/cli/skills-cli.curator.test.ts`, `src/agents/harness/tool-surface-bridge.test.ts` — green. New regression tests (`service.test.ts` agent-vs-operator apply on a user-authored skill and operator apply kept over a stale pending snapshot; `experience-review.apply.test.ts` no `cleanupBundleMcpOnRunEnd`; `attempt-phase-lifecycle.test.ts` no agent_end for a detached run; `code-mode-swarm.test.ts` swarm globals refused under the review allowlist) fail on the pre-fix code.
- Dependent sweep: 46 test files importing the touched modules — green.
- `oxfmt`, `scripts/run-oxlint.mjs` on changed files, `git diff --check` — clean.
- `pnpm tsgo && pnpm check:test-types` on Blacksmith Testbox — clean.
- Local ClawSweeper review (`gpt-5.6-terra`, high): `133ffe3` raised two findings (ownership recheck removed from the apply boundary; review retiring the shared session's MCP runtime), fixed in `26e821f`; `26e821f` raised one (detached review re-entering agent-end scheduling), fixed in `7e4a506`; `7e4a506` raised three: pending write racing an operator apply and Code Mode swarm globals bypassing the execution gate, both fixed in `e4b4322`; "prove detached review does not start configured MCP or LSP runtimes" is skipped as the cache-parity tradeoff stated above (LSP tool schemas come from the LSP runtime; the MCP runtime is session-owned and already warm). Maintainer decision on `e4b4322`: accepted — a detached review reuses the session MCP runtime and re-spawns configured per-attempt LSP servers exactly like a foreground turn; it still cannot execute them.
- Unrelated CI on `26e821f`/`7e4a506`: `check-lint-core-2` (`max-lines` in `src/gateway/server-methods/models-list-result.ts`, unused param in `models.test.ts`, both from #129332) and `checks-node-compact-small-8` (`doctor-auth.profile-health.test.ts`, Claude CLI auth from #129052) fail identically on `main` run 32857954734; `checks-node-compact-small-31` pins plugin SDK export counts (`4340` vs `4342`) that #129052 moved — this PR touches no `src/plugin-sdk` file. On `e4b4322` the failing set is the same twelve `checks-node-compact` shards that fail on `main` run 32857954734 (`large-5/12/13/14/15/18/22`, `small-8/14/20/21/26`) plus `small-31`; `check-lint-core-2` passes here. None are fixed here; #129357 carries the `main` fix.
- LOC (raw numstat): production +712 / −664 (net +48; the four review-fix commits after the live run add +76 / −26); tests + docs +1269 / −1238 (net +31).
2026-08-25 20:27:25 +05:30
Colin Johnson 081ce11324 feat(ui): add collapsible Workboard columns (#128115)
Co-authored-by: Solver <solver@localhost>
Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>
2026-08-25 08:22:03 -04:00
Peter Steinberger 7401d21bdc refactor(scripts): remove obsolete sqlite incident reproductions (#129212) 2026-08-25 05:16:50 -07:00
Ayaan Zaidi 750a64e7cd fix(anthropic): keep Claude CLI authentication native (#129052)
Stop OpenClaw from copying or refreshing Claude CLI OAuth tokens.
Claude CLI now owns native login and refresh state; Doctor removes retired copies while preserving CLI routing.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-25 17:18:06 +05:30
Peter Steinberger b1e27db51c refactor(workboard): consolidate card normalization helpers (#129236) 2026-08-25 03:51:09 -07:00
Peter Steinberger a85dbdaf0d fix: cloud worker transfers fail after plain workspace results are staged (#129223)
* fix(gateway): preserve plain worker workspaces after result staging

* chore(gateway): prune obsolete worker snapshot assertion baseline

* chore: keep cloud worker release notes in pull request
2026-08-25 03:37:15 -07:00
Peter Steinberger a6b8eb5b41 refactor(gateway): share transcript usage aggregation (#129199)
* refactor(gateway): share transcript usage aggregation

* refactor(gateway): preserve transcript usage type ownership
2026-08-25 03:17:12 -07:00
Peter Steinberger 315969f669 fix(sessions): normalize package resource loading (#129098) 2026-08-25 02:27:20 -07:00
Peter Steinberger 1cf405f032 refactor(agents): consolidate extension runner callbacks (#129086) 2026-08-25 02:16:04 -07:00
Peter Steinberger a3d173d4cb perf(gateway): fix event-loop convoys from per-session hot paths under concurrent sessions (#129135)
* perf(gateway): stop sessions.files.list convoying on cold transcript folds

Raise the touched-files fold cache from 16 to 256 entries so >16 viewed
sessions no longer thrash it into repeated full-transcript refolds, use
in-process insideGitCheckout instead of spawning git rev-parse per call,
and reuse one prepared fs-safe workspace root per request instead of
re-opening it per touched file.

* perf(gateway): make session PR subscriptions non-blocking with poll-aligned caches

controlUi.sessionPullRequests.subscribe now registers the replace-set,
pushes cached snapshots, hydrates cold keys in the background (bounded
concurrency 4) and responds immediately instead of awaiting serial git
and GitHub batteries per session key. Local-git caches grow 10s->75s and
the GitHub success cache 60s->90s so the 60s poll hits warm caches
instead of re-running the full battery for every watched session every
minute; failure and rate-limit semantics are unchanged.

* perf(skills): memoize workspace skill discovery on the watcher snapshot seam

loadSkillEntries now serves repeat loads from a bounded 64-entry cache
keyed on the chokidar snapshot version plus config fingerprint, instead
of synchronously rescanning every skill root 4-6x per inbound message.
The session snapshot cache serves fresh sessions read-through, and the
skill precedence collision warning fires once per snapshot version
instead of ~9k times/day.

* perf(gateway): bound sessions.preview and chat.message.get transcript reads

sessions.preview reads a bounded recent tail (64-256 events/1MiB, one
8MiB escalation when filtered messages starve the 12-item preview) and
yields between batch keys instead of synchronously materializing every
transcript in a 64-key loop. chat.message.get resolves visibility via
the message-ID-anchored reader instead of loading the full projected
transcript per request.
2026-08-25 01:37:57 -07:00
Peter Steinberger 140e0ccda5 fix(health): secondary account failures incorrectly appear healthy (#129088)
* fix(health): surface unhealthy secondary channel accounts

* test(health): prune obsolete assertion safety baseline entry
2026-08-25 01:25:29 -07:00
xingzhou 736a03f9ad fix(line): prevent unbounded provider response buffering (#119099)
* fix(line): bound provider response bodies

* fix(line): preserve provider status on body errors

* test(line): keep response bounds coverage under lint budget

* test(line): cover bounded retry conflict responses

* chore(line): shrink assertion safety baseline
2026-08-25 01:13:58 -07:00
Peter Steinberger 041d48eccb refactor(config): simplify allowed-value formatting (#129064)
* refactor(config): simplify allowed-value formatting

* chore(config): tighten allowed-value assertion baseline
2026-08-25 00:22:20 -07:00
Peter Steinberger fbf8460da3 refactor(ui): consolidate presence payload parsing (#129029)
* refactor(ui): consolidate presence payload parsing

* chore(ui): tighten presence assertion safety baselines
2026-08-24 23:51:27 -07:00
Peter Steinberger 0a79ae5fd0 refactor(discord): reuse canonical interactive component renderer (#129031) 2026-08-24 23:30:25 -07:00
ClawSweeper b68c136609 feat(codex): upgrade main to app-server 0.149.1 (#128370)
* feat(codex): upgrade app-server integration to 0.149.0

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(codex): harden full app-server integration and lifecycle

* fix(codex): scope guardian trust and satisfy integration gates

* fix(codex): keep guardian startup and router tests within gates

* chore(codex): tighten guardian assertion safety baseline

* fix(ui): preserve sidebar icon path contracts

* test(codex): align side-question auth fixture

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

* style(codex): format transcript mirror imports

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

* test(codex): preserve native approval decisions

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

* test(codex): isolate app cache and catalog fixtures

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

* fix(ui): render guardian review and system notices

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

* test(codex): isolate native approval decisions

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

* fix(codex): revalidate reviewer config trust

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

* chore(codex): update app-server to 0.149.1

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

* test(codex): align desktop version warning

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

* fix(ui): scope notices to the active run

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

* fix(codex): isolate review, hosted app, and auth ownership

Co-authored-by: Vito Cappello <hixvac@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* chore(codex): keep release notes out of the release-owned changelog

* test(codex): reject reviewer cancellation with its explicit error

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Vito Cappello <hixvac@gmail.com>
2026-08-24 19:50:22 -07:00
RoboClaw c2602ded7c refactor(ui): compact live activity filters (#128972)
Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-24 19:47:55 -07:00
Peter Steinberger 97e732715a fix(slack): keep edited and deleted messages in their original threads (#128768)
* fix(slack): route threaded edits and deletes to their sessions

* fix(slack): tighten threaded-event assertion baseline
2026-08-24 14:00:52 -07:00
Peter Steinberger bea8740981 fix(matrix): show edited messages in replies and thread context (#128763)
* fix(matrix): use edited messages in reply and thread context

* fix(matrix): narrow bundled edit records without assertions
2026-08-24 13:38:57 -07:00
Peter Steinberger a99317ef97 refactor(gateway): unify bounded chat history across transports (#128844) 2026-08-24 13:06:06 -07:00
Peter Steinberger 3c2667ca40 fix(gateway): fill older chat pages without duplicate transcript storage (#128810)
* fix(gateway): page visible chat history without duplicate storage

* chore: keep release changelog owned by release automation
2026-08-24 10:43:59 -07:00
Shakker 59abf3de62 feat: persist stateful transcript display semantics (#126943)
Persist stateful transcript display semantics through one shared reducer for incremental and rebuilt projections.

Refs #126914.
2026-08-24 17:36:21 +01:00
Peter Steinberger 3dec4e3472 refactor(gateway): unify maintenance lifecycle ownership (#128766) 2026-08-24 08:09:33 -07:00
Peter Steinberger ec091478fc refactor(slack): reuse canonical interactive block renderer (#128760) 2026-08-24 07:55:00 -07:00
Peter Steinberger a8722e74ec refactor(agents): remove provider discovery test globals (#128758) 2026-08-24 07:45:27 -07:00
Peter Steinberger 15e9bea3cb refactor(telegram): unify interactive keyboard rendering (#128728)
* refactor(telegram): unify interactive keyboard rendering

* chore(telegram): ratchet removed keyboard assertion
2026-08-24 06:24:36 -07:00
Peter Steinberger 1c0e02ccb0 refactor(gateway): remove unused resident lifecycle registry (#128710)
* refactor(gateway): remove unused resident lifecycle registry

* chore(gateway): prune deleted registry assertion baseline
2026-08-24 05:57:43 -07:00
Peter Steinberger 03658a99a9 fix(browser): stop cancelled downloads from publishing files (#128651)
* fix(browser): cancel in-flight downloads before atomic publication

* fix(browser): type download capture event and deferred fixtures

* fix(browser): ratchet down obsolete download capture assertions
2026-08-24 05:10:48 -07:00
Peter Steinberger 8fe2c1b83c perf(ui): consolidate Control UI boot chunk graph for HTTP/1.1 gateways (#128514)
* perf(ui): consolidate Control UI boot chunk graph for HTTP/1.1 gateways

The Control UI boot flow (app shell + sidebar + chat route) lazily loaded
~124 automatic chunks in one burst after the gateway handshake, which the
gateway's HTTP/1.1 transport serializes into ~24 six-connection round-trips
on high-latency links (Tailscale, remote gateways).

Add a measured boot-module manifest (ui/config/control-ui-boot-modules.json,
regenerated via pnpm ui:boot-manifest:gen) and a control-ui-boot codeSplitting
group that merges exactly that module set into a handful of chunks with
recursive dependency inclusion. Lazy islands (locales, ghostty-web, novnc,
non-default routes) keep their own chunks; stale manifest entries degrade
gracefully back to automatic chunking.

Measured on the built dist with the mocked gateway (chat route, 3 runs):
unique boot JS requests 140 -> 45, raw boot JS 3751 -> 3717 KiB, chat
composer interactive at simulated 50 ms RTT ~1600 ms -> ~575 ms.

Largest-CSS budget rises 45 -> 47 KiB for the merged boot CSS; startup JS
gzip baseline ratchets down (345049 -> 339214 B) as consolidation shrinks
the startup graph.

* chore(ui): refresh boot module manifest after rebase onto current main

* fix(ui): stop the pending lazy shell action replay loop starving boot

When a pending lazy shell action (command palette open, panel toggle)
replayed while the shell was still splash-gated, the dispatched event had
no rendered element to consume it and re-entered requestLazyElement in a
microtask cycle: request -> load -> replay -> dispatch -> request. The
cycle starved tasks (Gateway WebSocket messages included), so the boot
never finished and the recovery e2e froze on the splash screen.

Gate replay on the element actually being rendered: the controller skips
the action after load until the host's render root contains the tag, and
restorePendingLazyAction skips dispatch while a defined element is still
render-gated. The host retries after every completed update, so the replay
fires on the update that first renders the element. Regression test fails
on the pre-fix controller.

* fix(ui): re-anchor the scope-upgrade details popover before opening

wa-popover resolves its `for` target once per property change and never
re-resolves a missing or replaced anchor. The trigger with the shared id
can render after the popover's first update (the header trigger ships with
the lazy chat chunk), leaving the opened popover permanently invisible:
active popup with a native [popover] part stuck at UA display:none because
showPopover() never ran without an anchor. Re-arm the watcher when opening
while the anchor is missing or disconnected.

* test(ui): compare settled layouts in device-scope stability assertions

The 0.5px no-move assertions sampled geometry that later reflowed when the
details surface's first render fetched glyph subsets, reporting sub-pixel
drift the open never caused. Burn in the one-time open per context and
sample the baseline adjacent to the click.

* fix(ui): map the keyboard shortcuts dialog in lazy replay gating

Current main added the keyboard-shortcuts lazy shell event; the replay
gate's exhaustive event-to-element record needs its entry.

* chore(ui): refresh startup budget baseline after rebase onto current main
2026-08-24 03:55:37 -07:00
Peter Steinberger 234df15a6d chore: refresh dependencies after seven-day cooldown (#128414)
* build(deps): refresh dependencies after cooldown

Apply dependency, toolchain, action, image, and exact tool updates released by the inclusive 2026-08-16 seven-day cutoff. Adapt owner boundaries for the resulting CUA, logging, Teams, Markdown, native, and test-harness contract changes while retaining versions blocked by upstream compatibility constraints.

* fix(ui): align markdown renderer env typing

* fix(deps): align postcss and mistral peer contracts

* fix(deps): repair refreshed dependency contracts

* fix(deps): retain tslog startup budget

* fix(ci): verify Android tools with SHA-256

* fix(ci): fence Android SDK cache version
2026-08-24 03:01:54 -07:00
Peter Steinberger 7d5b986a82 fix(gateway): reclaim cloud workers before session recovery (#128597)
* fix(gateway): reclaim cloud workers before recovery

* fix(workers): fence reclaim final effects

* test(workers): track reclaim authority temp dirs
2026-08-24 02:31:44 -07:00
Peter Steinberger 12d0fd2ef8 refactor(anthropic): replace handwritten Claude sessions with Agent SDK (#128131)
* refactor(anthropic): explore official Claude Agent SDK runtime

* refactor(anthropic): replace handwritten Claude sessions with SDK

* refactor(anthropic): collapse SDK live-session ownership

* refactor(anthropic): simplify SDK ownership and preserve live skills

* fix(anthropic): fence cancelled SDK runs before process startup

* fix(anthropic): harden SDK approvals, lifecycle, and packaging

* refactor(anthropic): own SDK process trees and streamline runtime

* fix(anthropic): repair rebased packaging and legacy test fixtures
2026-08-24 01:59:16 -07:00
Peter Steinberger 53dcaaedec feat(gateway): generic operator roles for non-maintainer access (#128548)
* feat(gateway): generic operator roles for non-maintainer access

Adds gateway.roles: named role bundles over a closed capability set —
sessions.others (none/view/suggest/write), an agents allowlist, and an
operator-scope ceiling. Roles are person-level (additive user_profiles.role
column, SQLite stays at v9); users.setRole (admin-only) assigns them. With
no gateway.roles config, behavior is unchanged for solo deployments.

Enforcement is deny-by-default from a host-minted actor identity
(system vs operator+profileId on server-only client.internal, never
accepted from the wire) and covers every entry point: WS RPCs, OpenAI-compat
and Responses HTTP, tools invocation, cron, questions, usage, task
suggestions, session catalog/sharing/reads. The agents allowlist gates both
session creation and run-start on existing sessions. Subagent completion
announce and descendant wake mint explicit system authority so role
boundaries never silently drop parent notifications.

The enforcement surface is expressed through a narrow policy vocabulary
(operatorSessionCap, hasOperatorBoundary, authorizeSessionSharing) rather
than per-handler policy internals.

* fix(gateway): heal PR CI after rebase onto main

- Break import cycles: extract GatewayOperatorRoleActor leaf contract; merge
  session-group-mutation-targets into session-sharing-target-input.
- Split sessions-suggestions.test.ts (max-lines) into a visibility suite.
- Add users.setRole to the 2026.8 train registry test and regenerate the
  Kotlin protocol client.
- Startup UNAVAILABLE gating now precedes session authorization: session
  stores are not loaded during startup, so authorization reads would deny
  with a misleading non-retryable error.
- sessions.assignOwner keeps its documented visibility-authorized contract
  when no operator role caps the caller; view/suggest-capped roles still
  cannot reassign foreign session ownership.
- Test stubs updated for main's socket readyState guard (#128144) and the
  system-authority arg on channel-native resets.

* test(gateway): chat.send pending-profile dispatch carries its required session target

chat.send requires a non-empty sessionKey at the protocol level; the mutation
pipeline now rejects targetless frames before profile-dependent dispatch, so
the pending-profile test must send a realistic frame.
2026-08-24 01:20:03 -07:00
Peter Steinberger ccc4e69052 fix(subagents): hide private commentary from logs and completion announcements (#128584)
* fix(subagents): hide commentary in logs and completion announcements

* refactor(agents): remove obsolete test-only history sanitizer export
2026-08-24 00:57:53 -07:00
Peter Steinberger 68ba1ef641 refactor(xai): share responses tool request transport (#128571)
* refactor(xai): share responses tool request transport

* refactor(xai): remove unused responses body test seam

* test(xai): preserve responses request contracts at fetch boundaries
2026-08-24 00:57:28 -07:00
RoboClaw 4e82e9256b refactor(ui): remove redundant chat reset actions (#128562)
Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-23 23:33:21 -07:00
Peter Steinberger f40cb158b1 fix(onboarding): preserve JSON option rejection output (#128542) 2026-08-23 23:22:54 -07:00
Ayaan Zaidi b41d5293b2 refactor(mantis): give Codex open-ended Telegram proof control (#128197)
* refactor(mantis): replace Telegram proof compiler with frozen visible replay

* refactor(mantis): let Codex own Telegram proof scenarios

* fix(mantis): isolate proof publication

* fix(mantis): bind baseline cache to revision

* chore(mantis): remove stale scenario-designer wording

* fix(mantis): align readable worktrees with trusted proof

* fix(mantis): register proof collector tooling

* refactor(mantis): keep collector functions private

* fix(mantis): publish agent-selected Telegram proof

* fix(mantis): trim proof media to final turn

* fix(mantis): fence lanes before evidence collection

* fix(mantis): verify lane termination before unlock
2026-08-24 11:47:26 +05:30
Peter Steinberger 91dc6e102a fix(ui): terminal messages no longer reload the session roster (#128397)
* perf(ui): avoid redundant terminal roster refreshes

* fix(ui): preserve filtered roster refreshes

* fix(ui): defer filtered roster snapshots

* fix(ui): classify roster snapshot eligibility

* fix(ui): fence terminal roster membership
2026-08-23 23:04:23 -07:00
Bek a5c8e00cb6 fix(codex): preserve child hooks across turns (#128485)
* fix(codex): preserve native hook relays across turns

* fix(codex): fail closed on relay renewal loss
2026-08-24 00:31:42 -04:00