Commit Graph

419 Commits

Author SHA1 Message Date
Peter Steinberger 87b3c0e5df refactor(agents): split subscribe leaf ownership (#122249)
* refactor(agents): split embedded tool result ownership

* refactor(agents): split embedded message ownership
2026-08-11 15:04:07 -07:00
Peter Steinberger a40df57bae refactor(agent-runner): split run policy ownership (#122209)
* refactor(agent-runner): split tool-call normalization ownership

* refactor(agent-runner): split incomplete-turn ownership

* test(agent-runner): hide incomplete-turn test helper

* test(ci): route split incomplete-turn tests

* test(ci): enumerate split incomplete-turn tests

* test(vitest): route split incomplete-turn tests to their serial shard
2026-08-11 13:06:29 -07:00
Ayaan Zaidi 746a188c90 refactor(media): collapse attachment byte classification into media-core (#122168)
Attachment MIME gating and extraction dispatch used nine separate byte policies across five files; the allowlist could approve one MIME while dispatch observed another after a second sniff. @openclaw/media-core/attachment-classify now owns byte sniffing, text heuristics, extension mapping, and the seven attachment classes; the cache stores one classification that gates and dispatch share. Channel-declared MIME leads with the transport Content-Type as a byte-arbitrated hint, normalizeMimeType folds YAML/XML synonyms so existing configured allowlists keep matching, and input_file API callers keep declared-MIME precedence over cosmetic filenames. Net -135 production LOC.

Proof: 2,153 focused tests across media-core/media-understanding/media plus boundary-contract and deadcode-mirror suites; ClawSweeper local review clean (round 5, zero findings); live Telegram default-turn probe green.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-11 19:10:49 +00:00
Peter Steinberger 2d6a5d7356 refactor(gateway): split worker environment service by ownership (#122138)
* refactor(gateway): split worker environment service by ownership

* refactor(gateway): derive environment intent at the contract owner

* chore(lint): ratchet max-lines baseline after worker-service split

* style(gateway): prune unused symbols after worker-service split

* refactor(gateway): narrow worker-service seam exports

* chore(plugin-sdk): refresh API baseline
2026-08-11 11:48:28 -07:00
Peter Steinberger 5c81ed5883 refactor(ui): split runtime config into layered modules (#122117)
* refactor(ui): split runtime config into layered modules

* refactor(ui): delete redundant config wrappers

* chore(lint): ratchet max-lines baseline after ui config split
2026-08-11 10:17:00 -07:00
Peter Steinberger cc9119e22a refactor(agent-runner): split run leaf ownership (#122148)
* refactor(agent-runner): split payload warning ownership

* refactor(agent-runner): split model diagnostic ownership
2026-08-11 10:08:21 -07:00
Vyctor H. Brzezowski e7ba2e1f6b fix(ui): give the Gateway update a visible, truthful outcome (#121686)
* fix(ui): give the Gateway update a visible, truthful outcome

Confirming an update in the Control UI could end in nothing the operator
could see. The sidebar card only knew `updateRunning`, which clears as soon
as `update.run` answers, so a dev-channel handoff — git pull, install, full
build, restart — spent minutes back on the stale "N commits behind" call to
action. A verified install then published a null banner, so success was
never announced at all, and the reload that a verified install triggers
would have destroyed any in-memory notice anyway.

The lifecycle was already recorded; nothing rendered it. Feed the sidebar
the reconciliation fact the settings page already uses, narrate the wait in
the shell callout that survives the restart, and record the verified result
so it outlives the reload it causes.

Failures now name their cause. The updater already stores the failing step
and its captured output in the restart sentinel and `update.status` returns
it whole, so a disk-full install reads "The update failed at install:
ENOSPC: no space left on device" instead of a reason slug plus "see the
gateway logs". Missing handoff-reason guidance is filled in, and the
duplicate post-restart banner resolver is folded into the shared one.

Also fixes a callout clipped by the fixed shell chrome controls, and the
"Available 246 commits behind" double framing in the confirmation.

* fix(ui): report the Gateway update in the dialog that starts it

Follow-up to the first pass: the shell-top callout was the wrong surface for
this. The dialog the operator clicked is now the one that reports the whole
update, and the ambient surfaces are the fallback for anyone who leaves it.

Confirming no longer closes the dialog. It becomes stateful — the danger
button turns into a disabled "Updating…" with a spinner, and the body
narrates the phases in place: installing, then "The Gateway is restarting.
This page disconnects and reconnects on its own." The dialog is mounted on
document.body, outside the shell, so losing the connection cannot unmount
the only surface still reporting. A request the Gateway never accepts stops
spinning after a bounded grace and says so.

A failure lands in the dialog with its recorded cause and next step. Success
still arrives after the reload a verified install triggers, so it stays a
toast — no dialog exists by then.

The shell-top status callout is gone. The same outcome now renders beside
the sidebar update card that started the update, and stays hidden while the
dialog owns the report so the two surfaces never duplicate each other.

Splits the wire-payload readers out of update-overlay-helpers into
update-schedule-dto and moves update.run answer classification next to them,
keeping both owners under the file-size budget.

* fix(ui): keep the update dialog open through the install in E2E and use a defined warn token

* refactor(ui): wire the update progress stream into the floating card and drop unused video capture

* fix(ui): report the current update, not the previous failure

The dialog subscribed to progress before starting the update. Producers
replay their current snapshot synchronously on subscribe, so a retry
still carrying the previous attempt's failure banner painted that old
error as this update's outcome.

Start the request first, and treat a failure present on the subscribe
emit as the previous attempt's: an accepted run clears the banner before
its first await, so a failure that survives means the request was
refused, which the accept timer already reports truthfully.

* fix(ui): keep update helpers internal

* chore(perf): raise startup-JS budget to 350 KiB

Approved by maintainer Vyctor on 2026-08-11.

Trigger: after #121734, main measured 326650 B—6 B below the prior 319 KiB hard ceiling. Current main subsequently moved the ceiling to 320 KiB; this records the authorized final 350 KiB decision for #121686.

* fix(ui): announce update success without session storage

Show the verified install identity directly when the current document does not reload, so denied session storage cannot suppress the operator-visible outcome.

* test(ui): isolate update toast in overlay tests

The Node-only overlay suite now reaches the direct non-reload success toast. Mock the DOM-owned toast boundary so reconciliation assertions can complete without a browser document.
2026-08-11 13:49:12 -03:00
Peter Steinberger fe4cff7a6b refactor(ai): split completions transport into concept modules (#122122)
* refactor(ai): split completions transport into concept modules

* refactor(ai): delete duplicated transport helpers

* chore(lint): ratchet max-lines baseline after transport split

* test(scripts): update prefix expansion expectation
2026-08-11 09:47:52 -07:00
Vincent Koc 8d3f3377da fix(ci): make Control UI artifact validation consistent (#122086) 2026-08-12 00:11:22 +08:00
Peter Steinberger 1ccd701808 chore(deadcode): remove stale Knip scaffolding (#122069) 2026-08-11 08:15:11 -07:00
Ayaan Zaidi d699ed0198 fix(ui): record chat-header startup JS growth in the budget baseline
#121734 landed 982 B of startup JS, leaving merge-ref builds 1 B over the
baseline ceiling; every open PR's build-artifacts job fails inherited red.
CI-measured bytes per the updater contract.
2026-08-11 15:08:53 +02:00
Peter Steinberger 8327504c84 refactor(agents): split systemd into concept modules (#122002) 2026-08-11 04:09:49 -07:00
Peter Steinberger bef753b278 refactor(agents): split reply-run registry into concept modules (#121995) 2026-08-11 03:38:54 -07:00
Peter Steinberger 226c699a23 feat(ai): add provider video input contract (#121887)
* feat(llm): add user video input contract

* fix(ai): preserve structured tool results

* refactor(ai): isolate provider video input types

* style(ai): format provider transform imports

* chore(ai): register provider type entrypoint
2026-08-11 03:08:27 -07:00
Peter Steinberger a4c7b1b7b5 refactor(agents): split embedded-agent subscribe tool handlers into concept modules (#121974) 2026-08-11 02:37:48 -07:00
Peter Steinberger 3d707a9b96 refactor(daemon): split launchd into concept modules (#121929)
* refactor(agents): split launchd into concept modules

* fix(daemon): restore launchd service environment type

* refactor(daemon): keep launchd probe result internal
2026-08-11 01:49:23 -07:00
Peter Steinberger 64e3712e82 refactor(skills): split workspace loading into concept modules (#121916)
* refactor(skills): split workspace loading into concept modules

* refactor(skills): delete dead seams and duplicate helpers

* chore(lint): ratchet max-lines baseline after workspace split

* chore(plugin-sdk): refresh API baseline

* refactor(skills): internalize discovery result type

* test(tooling): drop stale unit-fast fixtures
2026-08-11 01:28:20 -07:00
Peter Steinberger 6e851103dc refactor(system-agent): split chat engine into concept modules (#121884)
* refactor(system-agent): split chat engine into concept modules

* refactor(system-agent): deduplicate hosted setup flows

* fix(system-agent): record interactive exit as a fact

* chore(lint): ratchet max-lines baseline after chat-engine split

* fix(system-agent): clear sensitive wizard state between sessions
2026-08-11 00:55:30 -07:00
Peter Steinberger 2b8dbc3a7b refactor(agents): split message-tool into concept modules (#121901)
* refactor(agents): split message-tool into concept modules

* fix(agents): restore message-tool split imports

* ci: preserve message-tool CodeQL boundary
2026-08-11 00:31:14 -07:00
Peter Steinberger 2715d1a878 refactor(agents): unify dot-family attempt helper names (#121550)
* refactor(agents): add dash-named attempt helpers

* refactor(agents): repoint dot-family attempt imports

* refactor(agents): remove dot-family attempt helpers
2026-08-10 20:27:56 -07:00
Peter Steinberger ebfd3ba154 improve: cut CI critical path without more workers (#121807)
* test(ci): remove redundant builds from critical path

Amp-Thread-ID: https://ampcode.com/threads/T-019fee8d-665d-707b-a380-23f2a6a1ce03
Co-authored-by: Peter Steinberger <steipete@gmail.com>

* docs(ci): format runner table

Amp-Thread-ID: https://ampcode.com/threads/T-019fee8d-665d-707b-a380-23f2a6a1ce03
Co-authored-by: Peter Steinberger <steipete@gmail.com>

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-10 20:21:20 -07:00
Peter Steinberger f5aba54437 refactor(agents): split Claude live sessions by concept (#121566)
* refactor(agents): split claude-live-session into concept modules

* refactor(agents): delete duplicated live-session helpers

* fix(agents): fence live-session close during pending spawn

* chore(lint): ratchet max-lines baseline after live-session split

* style(agents): satisfy lint on live-session split modules

* fix(agents): fence live session close state

* refactor(agents): extract Claude live turn timeouts

* fix(agents): preserve exec policy after Claude live split

* test(agents): complete Claude live policy session fixture
2026-08-10 19:39:16 -07:00
Peter Steinberger fada067277 feat(browser): add zero-click Chrome extension bootstrap (#121586)
* feat(browser): add zero-click extension bootstrap

Pre-register deterministic path-derived extension IDs and install a strict native messaging host.

Keep the popup and options UI minimal while removing the obsolete copilot and page-share flows.

* fix(browser): satisfy native bootstrap CI guards

* test(browser): isolate native bootstrap Chrome roots

* test(browser): flush native bootstrap profile before status

* test(browser): seed Linux native bootstrap identity

* fix(browser): preserve native bootstrap upgrade safety

Allow immutable root-owned package inputs while keeping mutable state, manifests, and launchers user-owned. Preserve all retired copilot keys whenever active or unrecognized recovery custody remains.

* fix(browser): preserve pending copilot custody

Retired cleanup now removes copilot state only when the durable registry is exactly empty. Any session, archive, malformed value, future shape, or read failure preserves every retired key.

* fix(browser): guard native bootstrap upgrades

Fail closed while retired copilot custody remains and make discard durable across partial failures.

Require exact launcher-embedded origins and repair full launcher drift without accepting mismatched registrations.

* fix(browser): remove stale layout export

* chore(release): leave changelog to release flow
2026-08-10 19:31:13 -07:00
Jesse Merhi d90e47783d fix(plugins): remove local dependency denylist (#101813) 2026-08-11 12:21:29 +10:00
Peter Steinberger 9175530fc1 fix(ci): heal skills reconciliation fallout (#121751)
* test(skills): cover collection review through scheduler

* test(skills): preserve scheduler failure signals
2026-08-10 16:34:03 -07:00
Peter Steinberger 750d0dcd9e improve(ui): make warm session switching instant (#121625)
* perf(ui): make warm session switching instant

Amp-Thread-ID: https://ampcode.com/threads/T-019fe957-0e49-707f-859f-9600ef536125

* fix(ui): harden retained session ownership

Amp-Thread-ID: https://ampcode.com/threads/T-019fe957-0e49-707f-859f-9600ef536125

* test(ui): scope retained session assertions

Amp-Thread-ID: https://ampcode.com/threads/T-019fe957-0e49-707f-859f-9600ef536125

* fix(ui): align generated image preview checks

* fix(ui): preserve early transcript reading position

Amp-Thread-ID: https://ampcode.com/threads/T-019fe957-0e49-707f-859f-9600ef536125

* fix(ui): adopt latest-navigation-wins router

Amp-Thread-ID: https://ampcode.com/threads/T-019fe957-0e49-707f-859f-9600ef536125

* fix(ui): restore retained pane reactivity

Amp-Thread-ID: https://ampcode.com/threads/T-019fe957-0e49-707f-859f-9600ef536125

* test(auto-reply): align item lifecycle expectations

* fix(ci): repair current-main validation gates

Amp-Thread-ID: https://ampcode.com/threads/T-019fe957-0e49-707f-859f-9600ef536125

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-10 16:17:25 -07:00
Peter Steinberger 1ced7441eb refactor(agents): move announce, completion, recovery, and registry families into concept directories (#121553)
* refactor(agents): move announce family into subagents/announce/

* refactor(agents): move completion and main-session recovery families

* refactor(agents): move registry family into subagents/registry

* refactor(agents): update registry state type imports

* style(agents): format moved subagent imports

* test(agents): preserve isolated registry test routing

* fix(scripts): recognize relocated subagent announce seams
2026-08-10 16:06:39 -07:00
Peter Steinberger db879e73fa fix(ci): heal dead-export scan and refresh plugin-sdk baseline
collection-rollback's directory helper lost its external caller in
bdf202ccc8 — make it local; register collection-review's focused-test
seam per the knip ignoreIssues convention; regenerate the API baseline
after recent harness/channel contract drift.
2026-08-10 14:34:54 -07:00
Peter Steinberger 87475758dc fix(cloud-workers): retry timed-out dispatches without reprovisioning (#121616)
* fix(cloud-workers): coalesce dispatch retries

Amp-Thread-ID: https://ampcode.com/threads/T-019feaaa-c7ed-769e-9f29-a3612bec72e7

* chore: lower environment variable count budget

Amp-Thread-ID: https://ampcode.com/threads/T-019feaaa-c7ed-769e-9f29-a3612bec72e7

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-10 09:17:17 -07:00
Peter Steinberger 3b3c540896 refactor: remove dead branches and test-only helpers (#121345)
* refactor: remove dead branches and test-only helpers

* fix: preserve codex cleanup error causes

* fix: preserve gateway error code compatibility

* chore: update plugin sdk api baseline

* docs: fix live cache runner path
2026-08-10 06:47:43 -07:00
Peter Steinberger 8d810d188b refactor: split ClawHub infrastructure by responsibility (#121565)
* refactor(infra): split clawhub into concept modules

* refactor(plugins): move compat predicates to their owners

* chore(lint): ratchet baselines after clawhub split
2026-08-10 06:42:37 -07:00
Ayaan Zaidi 4b0151682e refactor(commitments): remove inferred follow-up subsystem
Remove hidden follow-up extraction, heartbeat delivery, CLI, docs, and supporting tests/tooling. Existing commitment records remain inert pending separately approved cleanup.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-10 13:48:32 +05:30
Peter Steinberger 5fad24c8da refactor(agents): split CLI output into concept modules (#121412)
* refactor(agents): split cli-output into concept modules

* refactor(agents): canonicalize complete JSONL on the streaming parser

* refactor(agents): delete retired codex-exec projection residue

* chore(lint): ratchet max-lines baseline after cli-output split

* fix(agents): restore truncated-stream rejection and prune split leftovers

* fix(agents): prune cli-output lint leftovers

* style(agents): use import type for cli-output contract types
2026-08-10 00:03:34 -07:00
Peter Steinberger 145ec3778f refactor(agents): consolidate failover classification into one substrate (#121341)
* refactor(agents): consolidate failover classification substrate

* chore(agents): align failover refactor guards

* fix(agents): preserve leading 429 status handling

* perf(agents): retain lazy failover hook gating

* chore(agents): refresh failover guard artifacts
2026-08-09 23:58:44 -07:00
Peter Steinberger a6a464f4c0 feat(terminal): fullscreen /terminal route and dot-matrix claw intro (#121451)
* feat(ui): add fullscreen /terminal route and open button

* feat(terminal): dot-matrix claw intro banner and CLI mascot

* fix(terminal): satisfy lint and wizard-header assertions for the new mascot

* ci: account for fullscreen terminal startup bytes

* test(terminal): split session manager coverage
2026-08-09 23:52:59 -07:00
Peter Steinberger 627e5bb063 refactor(outbound): split message action runner by concept (#121434)
* refactor(outbound): split message-action-runner into concept modules

* refactor(outbound): delete forwarding and duplicate collectors

* chore(lint): ratchet max-lines baseline after message-action split
2026-08-09 23:11:32 -07:00
Peter Steinberger 8ee945b907 refactor(channels): flatten channel-turn dispatch naming layers (#121308)
* refactor(channels): flatten channel turn dispatch naming

* docs(plugin-sdk): narrow inbound reply compat guidance

* docs(channels): point stale references at turn defining modules

* fix(channels): preserve dispatch contracts after flattening

* chore(plugin-sdk): ratchet surface budgets after flattening

* chore(channels): ratchet removed export collisions

* fix(plugin-sdk): restore inbound reply compat exports

Restore eight still-existing legacy callable re-exports from canonical SDK seams and cover the deprecated package subpath with a table-driven compatibility test.

Raise the public export, callable export, and deprecated export budgets by exactly eight; the three maintainer-authorized zero-consumer symbols remain removed.

* test(channels): split channel turn kernel coverage

Replace the oversized kernel test with independently mocked delivery, pipeline, and finalize suites, preserving all 51 tests while removing the max-lines suppression and stale ratchet entry.

* chore(plugin-sdk): refresh inbound reply API hash

* fix(ci): align channel turn review fixes

Restore the test-local DeliveryResult type removed during the split.

Ratchet the public export, callable export, and deprecated export budgets by exactly seven: six channel-inbound plus one channel-outbound legacy re-export.
2026-08-09 22:22:46 -07:00
Peter Steinberger 8430fc0e3b refactor(agents): move spawn family into subagents/spawn (#121350)
* refactor(agents): move spawn family into subagents/spawn

* refactor(agents): keep spawn imports within lint budget
2026-08-09 19:51:29 -07:00
Peter Steinberger 5207c4765d feat(ui): float task-suggestion cards top-right with copy-prompt action (#121259)
* feat(ui): float task-suggestion cards top-right with copy-prompt action

- Float a compact tray in .chat-main__conversation with absolute positioning, min(400px, 100% - margins) sizing, elevation, and internal scrolling.
- Remove the icon column, keep dismiss in the header row, and move a compact split button to the bottom-right.
- Add Copy prompt to the menu via shared copyToClipboard, copying the raw prompt while display-only sanitization remains documented inline.

Release note: Suggested-task cards now float as compact cards at the chat top-right and offer Copy prompt in the action menu.

* style(ui): neutral grey task-suggestion card and actions

Drop the accent-tinted card border/background, mute the eyebrow, and use default grey button treatment for the split control per operator direction.

* fix(ui): ungate copy-prompt and surface clipboard outcomes

- Menu now always renders with the client-local Copy prompt while acceptance-mode items stay capability+scope gated (addresses ClawSweeper finding 1).
- Copy success shows a transient Copied label and failures surface through the pane error path (finding 2).
- Task-suggestion pane logic extracted to chat-pane-task-suggestions.ts and the tray adapter moved into the component to keep files under the 700-line cap.

* fix(ui): test task suggestions through tray adapter

* test(ui): cover task-suggestion clipboard failure

* test(ui): split task-suggestion pane coverage

* chore(ui): raise startup JS budget for task-suggestion card feature

QA-profile measurement was 324617-324620 B versus the 324608 B effective budget; this owner-directed PR #121259 bump follows the baseline file’s documented feature-growth precedent.

* chore(ui): raise startup JS ceiling to 318 KiB for task-suggestion cards

The fixed 317 KiB ceiling (324608 B) was within ~20 B of CI-measured startup bytes after accumulated main drift; the task-suggestion card feature crossed it. Ceiling raised with in-file maintainer-approval comment per its own convention; ratchet baseline set to CI-measured 324626 B.

* fix(ui): keep task-suggestion copy available read-only

Remove the stale accept-or-dismiss tray guard now that Copy prompt is a client-local action. Keep Gateway-backed accept and dismiss controls independently gated, with a regression for operators who can only list suggestions.

* test(ui): cover list-only task-suggestion copy

Update the mocked-Gateway E2E to match the repaired read-only behavior: the suggestion remains visible, its mutating Start action is disabled, and Copy prompt stays available.
2026-08-09 18:45:47 -07:00
Vyctor H. Brzezowski 32ced3053d fix(ui): scope the Control UI cursor convention to app-like display modes (#121258)
* fix(ui): scope the Control UI cursor convention to app-like display modes

The app-chrome cursor convention from #103357/#103411 was applied
unconditionally, so an ordinary browser tab lost the pointer hand on
buttons, menus, tabs, rails, selects and accordion summaries — the only
hover affordance a page owns. The convention is correct for the installed
window the manifest declares ("display": "standalone"), not for every
window the same bundle is served into.

base.css now owns one policy token, --cursor-action, selected by display
mode: pointer by default, the desktop arrow under standalone, minimal-ui
and window-controls-overlay. A low-specificity rule maps generic
actionable controls onto that token, restoring the affordance on the
surfaces #103411 stripped bare, while every component rule that owns a
semantic cursor (not-allowed, disabled, grab, resize, zoom-in, text,
wait) keeps winning without !important.

The 92 cursor: pointer declarations that had drifted back into ui/src
since July now consume the token instead of hardcoding the hand, so they
stop contradicting the policy in an installed window. Real hyperlinks
keep the pointer in every mode. The pre-boot mount fallback repeats the
policy locally because it must render when the bundle fails to load.

Closes #121242

* test(ui): run the cursor policy browser test in the node-driven project

ui/vitest.config.ts routes Playwright-from-Node .browser.test.ts files to the
unit-node project; without registering the new cursor policy test there, the
in-browser chromium project tried to import it and failed on node:fs/playwright.

* fix(ui): keep the desktop arrow in the native app hosts

The macOS dashboard embeds the Control UI in a plain web view, which
reports `display-mode: browser`, so the display-mode-only policy would
have handed it the browser-tab pointer. It already announces itself with
`openclaw-native-macos`/`-nav`/`-web-chrome` on `<html>`, the same markers
`ui/src/styles/layout.css` matches on, so the policy reads those too.
2026-08-09 22:23:00 -03:00
Peter Steinberger ce53f7e82e refactor(agents)!: remove the session write lease (#121113)
* refactor(agents): remove session write lease

* refactor(plugin-sdk): deprecate session write lease

* refactor(doctor): remove session lock checks

* test(agents): remove session lease fixtures

* test(agents): align writer rebound assertion

* refactor(infra): remove retired session lock exports

* test(tooling): preserve embedded abort race shard
2026-08-09 15:30:48 -07:00
Peter Steinberger c70aee247e refactor(scripts): migrate JavaScript tools to TypeScript (#121005)
* refactor(scripts): migrate JavaScript tools to TypeScript

* fix(ci): keep changed-scope preflight zero-install

* fix(ci): preserve zero-install script owners

* fix(ci): complete script migration follow-through

* fix(release): keep stable closeout zero-install

* fix(scripts): preserve standalone execution boundaries

* fix(scripts): repair standalone loader boundaries

* fix(scripts): normalize gateway observation ids

* fix(scripts): keep Docker packager standalone

* test(scripts): preserve rebase cleanup helpers

* test(sessions): use tracked temp directory
2026-08-09 07:21:35 -07:00
Peter Steinberger 52a76313e8 refactor(gateway): consolidate interactive connection resolution (#120865)
* refactor(gateway): consolidate interactive connection resolution

* test(gateway): remove superseded auth surface coverage

* chore(plugin-sdk): refresh API baseline

* fix(tui): preserve in-process exit fallback
2026-08-09 06:57:22 -07:00
Peter Steinberger b61bc5cd8d fix: sync Cloud Worker workspaces from macOS gateways (#121027)
* fix(cloud-workers): support Apple openrsync receivers

* build: register worker receiver entry

* fix(cloud-workers): narrow receiver invocation types

* test(cloud-workers): resolve real rsync before wrapping
2026-08-09 03:51:24 -07:00
Peter Steinberger 8b0735e89f refactor(memory)!: remove the QMD backend; builtin is the only memory engine (#120936)
* refactor(memory): remove qmd backend

Make builtin the sole memory-core engine, rename the retained session helper barrel, retire QMD config with doctor migrations, and remove QMD runtime/UI/policy surfaces.

* docs(memory): remove qmd backend guidance

Delete the QMD concept page, rewrite memory documentation for builtin retrieval, and remove QMD from navigation and taxonomy source.

* refactor(memory): remove qmd-only leftovers

* refactor(memory): finish qmd integration cleanup

* build(deps): align root string-width types

* build(deps): model root string-width tooling

* refactor(memory): align qmd removal ui and docs

* fix(memory): preserve qmd external paths in doctor

* test(memory): remove obsolete backend probe case

* test(plugin-sdk): refresh private type baseline
2026-08-09 03:05:47 -07:00
Peter Steinberger 7cf4f9aa6a refactor(acp): split grandfathered translator and event-ledger files (#120941)
* refactor(acp): split translator and event ledger

* refactor(acp): keep sqlite ledger owner stable
2026-08-09 01:23:11 -07:00
Vincent Koc 38039f5ea8 fix(secrets): preserve Windows ACL diagnostics (#120211)
* fix(secrets): preserve Windows ACL diagnostics

* fix(secrets): make Windows path security proof deterministic

* test(secrets): isolate Windows ACL tool failures

* test(secrets): preserve ACL preload process contract

* test(ci): route Doctor ACL proof to Windows

* test(qa): normalize Clack note borders

* test(ci): register Windows ACL preload for deadcode checks
2026-08-09 03:48:42 +08:00
Peter Steinberger eecbfcc960 fix(infra): unify env-truthiness, missing-path, realpath, and abort-sleep semantics (#120359)
* fix(infra): unify environment truthiness

* fix(infra): unify missing path classification

* refactor(infra): unify realpath fallbacks

* fix(infra): unify abortable sleep errors

* docs(infra): clarify path fallback semantics

* fix(infra): route realpaths through policy wrapper

* fix(infra): ratchet plugin SDK wildcard budget

* fix(agents): preserve zero-delay abort precedence

* fix(infra): preserve fallback and media recovery contracts

* fix(plugins): share quarantine path resolution
2026-08-08 10:58:57 -07:00
wonfong 9fdc266f64 fix(subagents): wake the parent when a follow-up finishes a yielded child (#120187)
* fix(subagents): wake the parent when a follow-up finishes a yielded child

A sub-agent that calls sessions_yield on its own behalf parks its run and
correctly withholds the parent's announce. But a later follow-up to that same
child session registered a sibling registry row instead of continuing the paused
one, so the requester defaulted to the child's own main session and the original
parent — itself idle behind sessions_yield — was never woken. The paused row also
stayed an unsettled descendant, deferring the parent's settle batch forever with
nothing recorded explaining the silence.

Follow-up dispatch now adopts the paused row through the existing post-steer
replacement seam, inheriting the requester identity and carrying the settle-wake
credential forward with its frozen batch membership remapped to the new run id.
A follow-up that names its own requester keeps registering separately, since an
explicit requester is a delivery opt-in that adoption would silently drop.

Also stops frozen-result refill from targeting paused rows: a yield clears the
result on purpose, so refilling from the session would attribute a later turn's
text to the paused run.

Closes #120157

* fix(subagents): select the paused owner past a requester-bound sibling

Adoption looked up the newest run for the child session and adopted it only
when that row was itself paused. A requester-bound follow-up deliberately stays
a sibling, but it registers at a higher generation and becomes that newest row,
so any later default follow-up saw an unpaused newest row, declined adoption,
and registered yet another sibling. The original requester stayed parked behind
a paused row that can never announce -- the same silent stall this fix exists to
remove, reached through a valid mixed-delivery sequence.

The latest-run query now takes an optional predicate applied before the
generation comparison, so a caller that owns a specific row class selects the
newest row of that class. Adoption asks for the newest `sessions_yield` row
directly instead of inferring it from generation order.

Docs now state that continuation applies to default delivery, since a follow-up
carrying its own requester runs as a sibling by design.

* test(qa): prove post-yield follow-up delivery through the gateway boundary

The unit and gateway-method tests for paused-run adoption assert on registry
rows, which proves the bookkeeping but not that an operator ever sees the
result. This adds the boundary proof: a real gateway child, the QA mock channel,
and the mock provider driving a subagent that pauses itself and finishes only on
a later follow-up.

A fixture plugin owns both legs. Its `before_dispatch` hook spawns the child with
`completionDelivery: "current-requester"`, so the announce has the operator turn
as its audience. An HTTP route then dispatches the follow-up to that same paused
session using default delivery -- the path adoption is meant to catch. A
requester-bound follow-up would opt into its own audience and run as a sibling
instead, so the two legs must differ here.

The mock provider gains a child that yields on its own behalf. Both of its turns
match on the current prompt rather than the shared transcript, so the yielded
kickoff cannot make the follow-up turn yield a second time.

The scenario asserts both sides of the invariant: no outbound traffic while the
child is paused, and exactly one announce carrying the follow-up marker once it
ends.

Reverting the adoption call site fails this test in the way that matters: the
child still produces its marker and the run still ends with stopReason=stop, but
nothing reaches the requester and the wait times out. The result is computed and
then silently dropped -- which is the failure this repair exists to remove.

* fix(ci): match QA Lab fixture plugin entries as a group in knip

The all-exports pass listed one fixture entry by name, so every new QA Lab
fixture plugin lands as an unused file and turns check-dependencies red until
someone remembers this file. Nothing imports these entries by design: the
Gateway E2E loads them through plugin config paths.

* docs(subagents): scope yield continuation to plugin runtime follow-ups

Adoption is gated on plugin_subagent task tracking, which only
createGatewaySubagentRuntime().run sets, so api.runtime.subagent.run is the
sole route into it. Writing that as one example implied other follow-up paths
to a paused session continue the run too; they are not tracked as sub-agent
runs and announce nobody.

* fix(subagents): reject undurable paused-run adoption

Fail plugin follow-up admission closed when the paused-run ownership swap cannot be persisted, while retaining the existing restart-recovery return-false contract. Trim duplicate tests and keep boundary coverage for requester routing, wake-batch remapping, repeated yield, and persistence rollback.

Co-authored-by: zhou.huanfeng <woundfongv3@163.com>

* docs(subagents): clarify yielded-run steering

Co-authored-by: zhou.huanfeng <woundfongv3@163.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 06:46:19 -07:00
Peter Steinberger 205753eef7 feat(ui): split model picker into searchable model + effort popovers (#120495)
* refactor(ui): remove fake token estimate

* feat(ui): split model picker into model and effort popovers

* fix(ui): hide filtered-out model rows under the flex option style

* fix(ui): drop unused model locator in cloud-startup e2e

* fix(ui): restore focus and expose active model option to assistive tech
2026-08-08 03:47:32 -07:00