Carry the prepared workspace worker cut onto current node launch, workspace,
and Codex lifecycle owners. Preserve synchronous external plugin acquisition,
transaction-time authority, and durable retirement semantics.
Join invocation and duplex cancellation through the runtime handoff and fence
legacy synchronous acquisition while async workspace mutation admission waits.
Private source checkpoint: fresh scoped review is clean through P2 and 43
selected ordinary/regression cases pass. Full changed checks and final build
remain incomplete; assertion baseline shrink maintenance and the current-main
schema 18 carry follow before qualification. The historical specific
reproduction remains held and was not replayed.
Grok (xAI) Talk saved each spoken sentence as several duplicate or truncated user messages, because every cumulative transcription snapshot was persisted as a final turn. Longer spoken replies were also cancelled when they overflowed the browser's 10 s playback queue. Tool-call consults did not tell the agent which blocked call the user had confirmed.
The xAI provider now previews input snapshots and commits one final per utterance at a real boundary: next speech, response end, session close, or 1.5 s of quiet after a late recognition. It fences output, cancel errors and buffered tool calls from retired responses. The relay forwards snapshot mode and the saved transcript id, so the Control UI hides a live caption once its saved row arrives. Browser playback allows 60 s / 4,096 sources, and the 20 ms relay frame contract is unchanged. Tool-call consults receive the same blocked-call retry context and confirmation-id reply as native delegation. A same-action retry in a new run reuses the pending challenge without extending it. `onTranscript` gains an optional `{ textMode: "snapshot" }` metadata argument.
Proof: live isolated Gateway and Control UI Talk runs on xAI Grok against main.
- Three utterances were saved as 3 turns instead of 22. Long answers played to the barge-in instead of being cut by overflow.
- A spoken "Yes." wrote the confirmed file exactly once; "No." wrote nothing.
- Non-affirmations, expired challenges, superseded or consumed ids, and ids from a closed session were all rejected before the exec ran.
Co-authored-by: Marvinthebored <peter@lindsey.jp>
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Apply the configured byte limit to each newline-terminated message before retaining the incoming chunk. Preserve atomic rejection and pending state when a later frame exceeds the limit, and keep the default SDK buffer contract unchanged.
The strict CUA/plugin-SDK client no longer disconnects when a pipe combines valid messages. Nineteen focused tests, real subprocess positive/oversized controls, selected checks, and independent P2 review pass.
* fix(agentsapi): include conversation context in native messages
* refactor(agentsapi): use private attempt context helper
* refactor(agents): keep inbound context type with shared owner
* fix(gateway): preserve context for active harness messages
---------
Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
Related: #155788
## What Problem This Solves
A Telegram answer could finish and be saved, yet vanish from the chat when final delivery failed: cleanup removed the only progress message and treated uncertain delivery as a visible success.
## User Impact
A failed final no longer silently erases progress or reports success. When the transport can still edit, the user gets a visible delivery warning; without a preview, it sends one separate warning under the existing error policy. Accepted final content stays intact even if preview deletion fails. A rejected tail keeps accepted chunks and reports the missing remainder without resending completed tool work or duplicate text.
**Limit:** This does not automatically re-send an unconfirmed answer. In the observed incident the answer was saved in OpenClaw history, but no existing Telegram command retrieves that exact final without a new model turn; an automatic resend from an ambiguous transport result could duplicate accepted content. The original incident's first plugin/worker invalidation is still unproven. The separate inventory-continuity PR #155875 addresses one plausible transient-database-lock route without claiming it was the incident's trigger. No new config, permission, storage schema, or durability policy is introduced.
## Why This Change Was Made
Telegram now uses the existing shared live-preview lifecycle for final start, confirmed acceptance, partial failure, intentional suppression, and preview cleanup. Native Telegram pagination, quotes, media and message IDs remain transport-owned. The shared durable sender no longer marks an identityless send as visibly delivered; that state still prevents unsafe competing retries. Removed the Telegram-local final-success and cleanup flags. A saved answer, a queued attempt, and a provider-accepted final are separate facts.
## Evidence
- Retained production incident: saved final answer, `PluginInstanceUnavailableError` on final send, progress gone. The first worker-inventory close preceded the failed config reload; its origin is not attributed here.
- Baseline negative controls: a real-dispatch plugin-unavailable rejection leaves zero visible messages; identityless durable send incorrectly reports `visibleReplySent: true`. Both regressions pass after this repair.
- Focused proof: 529 Telegram dispatch/lane/HTTP sibling tests and 44 shared lifecycle/turn tests passed before the final partial-visibility change; afterward, 52 focused partial/late-media and 44 shared lifecycle/turn tests passed. The latest head `da8efdbc09` passed the real Telegram Test Server rejected-final/next-turn flow: visible warning, one synthetic tool execution, one next reply, confirmed cleanup. Full source and Plugin SDK build succeeded before its successive-answer follow-up; the final runtime-only build succeeded afterward. Changed-lane checks passed formatting, boundaries, ratchets, dead exports, core and extension typechecks, and core lint. Extension lint preparation rejected an ancestor dependency; all 25 changed Telegram files then passed type-aware lint in an independently installed checkout outside that ancestor. Public SDK behavior and declarations passed an external-consumer smoke/typecheck.
- Telegram Test Server with an isolated, leased QA user, real Gateway, deterministic provider and actual client: baseline final-send rejection created and then deleted progress; the repaired run kept a visible terminal status, ran the synthetic tool once, and handled the next user turn once. Both variants used the same frozen QA harness revision. Accepted-ACK hold retained preview until final acknowledgment; rejected deletion preserved the accepted final; partial edit rejection used the normal fallback; progress, partial, block preview, durable blocks and streaming-off success paths were exercised. One long final-tail rejection kept accepted chunks, reported the missing tail immediately, and did not replay them; the next turn succeeded.
- Review follow-up: the exact-head ClawSweeper review found that a second assistant answer inherited the first final's delivery state. A real draft-stream/Bot API regression fails on the reviewed head (extra bubble for accepted B; no warning for rejected B), then passes for both outcomes after advancing the shared lifecycle and native message identity together. The affected Telegram rotation/progress sibling tests, shared lifecycle tests, extension source/test typechecks, docs MDX, ratchet and isolated extension lint passed after the correction.
- Hosted CI follow-up: a Telegram send that succeeded before prompt-context recording failed was incorrectly reported as uncertain. The confirmed receipt now settles before that recording error propagates; a genuinely rejected tail still emits the delivery warning without replaying accepted text. After merging current `main`, 17 quote/transcript regressions and 49 Telegram/shared lifecycle tests passed; extension source and test typechecks passed. Local extension lint preparation could not isolate an ancestor-installed `qrcode` manifest in this nested worktree; hosted lint remains the gate.
- Review correction on streamed previews: the prior head `8e1657152006` produced the accepted final **plus** a false delivery warning when a later prompt-context write failed. The new real-dispatch regression fails on that exact head and passes after recording confirmed preview content separately from failed buttons/media or context bookkeeping. Focused Telegram delivery/transcript/lane and shared lifecycle tests passed **84/84**; extension source and test typechecks passed.
- Separate hosted CI observation: an unchanged QA Lab private-production test intermittently read an empty `.request.json` immediately after the file appeared. The test and owner source are byte-identical to the exact base `86d353b748`; isolated runs passed **3/3** on both base and product head. No QA Lab code is included in this PR; the required hosted gate remains authoritative.
- Native Telegram CI correction: the earlier partial-receipt merge synthesized message-ID parts and overwrote an accepted chunk's provider topic. The receipt owner now preserves concrete provider parts and unions accepted IDs from the explicit result and receipts without inventing route metadata. The wrong-topic, late-media, queued-block control, and album-observer regressions pass; **193/193** Telegram receipt/progress/rotation sibling tests, extension source/test typechecks, and the line-cap ratchet passed.
- Another hosted shard failed in the unchanged Gateway yielded-reset test (`src/gateway/server-methods/chat.reset-visible-yield.test.ts`); no Gateway files or related runtime paths changed in this PR. The isolated reset and complete variants both passed **2/2** on the product head. No Gateway repair is claimed; the required hosted gate remains authoritative.
- Limits: the public config-reload scenario never reached Gateway actions because its QA provider did not become ready. An accepted-ACK hold is not a network timeout. Failed Telegram deletion can leave a stale progress message beside a confirmed final; no cleanup-success claim. The new nine-case real-dispatch test file measured about 3.5 seconds of test execution in a focused run; the Vitest worker/import setup is separate. It covers failure, partial acceptance, no-preview, cleanup, cancellation, successive answers, and next-turn transitions that helper-only tests cannot prove. Screenshots are real Telegram Test Server client pixels, cropped to the current synthetic conversation.
### Before: baseline deletes the only visible status after final rejection

### After: terminal delivery status remains visible

Related QA fault-injection harness: #155899. No runtime dependency; either PR can land first.
Merged current `main` (`86d353b748`) to align the older branch with its SQLite reader and PR wrapper inventory. The two earlier cherry-picked upstream CI fixes retain Peter Steinberger's commit authorship; they are already on `main` and disappear from the PR diff. The Telegram repair remains 31 files.
OpenClaw needs an alternative OpenAI harness that owns a hosted agent session instead of connecting to a Codex app-server session.
Add an explicitly selected Agents API plugin for hosted Linux sessions with API-key authentication, text streaming, session reuse, steering, interruption, and native idle settlement. Reuse shared binding and transcript authority, and dispatch the shared completion hooks from the actual attempt result.
Validation: required final-head CI passed; ClawSweeper accepted the real Docker authority proof and reports no remaining findings. Native Linux/arm64 Docker flows verified hosted VM execution, steering, authorized interruption, queued-input cancellation, completion-hook delivery, successor isolation, and strict transcript rejection. No local unit tests, mocks, or fakes were used.
Token accounting is best effort when terminal events omit usage. Apps, connectors, custom executors, file transfer, image generation, and additional configuration remain outside this MVP.
Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
* fix(codex): discover GPT-6 models with runtime 0.155.1
Keep the managed runtime, ACP adapter, and subscription catalog client version on the same exact release. Refresh the native model discovery snapshot from an authenticated 0.154.0 to 0.155.1 cache reuse probe. Related: #155937; follow-up to #155967.
* test(codex): sync runtime fixtures with 0.155.1
Add provider-neutral explicit Decision evaluation through the existing runtime, declared provider capabilities, and a default-off Labs consent foundation. Keep explicit evaluation independent of Labs and retire the unreleased TypeSafe-specific tool. No automatic consumer or public selection/local-availability inspection API is added.
Verified the registered core tool with real ONNX CPU inference, host-bound rejection before dispatch, and agent disablement. Preserve the contributor implementation and the reviewed Labs UI/config behavior.
Related: #155115, #155314, #155317
Co-authored-by: Jacqueline Henriksen <jjjhenriksen@gmail.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
* fix(release): preserve higher plugin API floors
Raise lower plugin API requirements during release alignment without lowering intentional floors for newer host APIs. Reuse the shared OpenClaw semver ordering for beta, RC, and correction releases, and preserve invalid declarations.
Add filesystem-boundary regression cases for check and write modes, and document floor preservation. The generator suite passes all 16 tests; focused cost is 3.01 seconds wall. P2 review and changed-file checks pass. Package versions, dependencies, host floors, manifests, and lockfiles are unchanged.
* chore: integrate main for plugin API floor validation
* test: retain PR controller output on close failure
Print the existing child output buffer if the fresh-main fixture cannot observe controller close, then rethrow the original error. Preserve the existing deadlines and joined cleanup. The earlier hosted timeouts remain unexplained.
* chore: integrate main after Gateway shard rebalance
Include the canonical worker-environments shard rebalance from #155734. Preserve the exact reviewed five-file API-floor and controller-output patch. The catalog timeout and earlier controller-close timeouts remain separately qualified.
* chore: integrate main after archive fixture repair
Include the canonical archive lifecycle fixture repair while preserving the exact reviewed five-file API-floor and controller-output patch. Retain prior failed CI and the noncausal catalog pass as qualified evidence.
* chore: preserve fixture diagnostics across main integration
Keep the upstream private-handoff setup and injection assertion alongside the unchanged controller-output catch. Preserve main and the original API-floor repair without adding timeout or retry policy.
* chore: integrate the canonical launcher fixture repair
* chore: integrate the canonical wrapper closure repair
* chore: integrate canonical wrapper and worker bundle fixes
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Related: #144839
## What Problem This Solves
Fixes partial prompts and multiple replies when Telegram delivers one long paste as a rapid burst of differently sized message chunks.
## User Impact
Telegram now batches ordinary text by default with a 300 ms quiet window, extending the wait for likely long-paste continuations. Existing global/per-channel settings still take precedence; explicit `0` disables ordinary burst batching while retaining automatic near-limit reassembly.
The tradeoff is a small delay before ordinary text starts a turn, and intentionally separate rapid messages may be combined. Commands and media remain separate, and stop still cancels pending input.
## Why This Change Was Made
Short text and near-limit fragments previously used separate collectors, and reassembly required consecutive message IDs. One shared keyed queue now collects both, preserves source metadata and cancellation, and orders forwarded batches without merging their origins into ordinary text.
Ordinary batches are bounded to 12 messages, 50,000 characters, and 7.5 seconds of collection (or a longer configured initial quiet window). Likely continuations retain a 1.5-second allowance. The separate fragment maps, timers, and completion bookkeeping are removed. No config migration or dependency change is required.
## Evidence
Real Telegram Test Server user → bot → OpenClaw Gateway → deterministic mock provider, with TDLib recording actual replies:
| Scenario | Pinned baseline | Candidate |
| --- | --- | --- |
| 3,999 + 4,096 + 200 characters, sent about 100 ms apart | Two user turns: first chunk, then remaining chunks; two replies | One combined user turn; one reply |
| 4,096 + 200 characters | One joined turn and one reply | One joined turn and one reply |
| Buffered long text, then native stop, then fresh text | — | Canceled text never reached the provider; fresh text produced one turn and reply |
The candidate mixed case exercised real transport deliveries 233 ms apart. Stop arrived 587 ms after the buffered text; the fresh message arrived at 2,999 ms. Counts above are primary user turns, not background session-recap requests. All proof leases, processes, listeners, and credential scratch were cleaned up.
- The mixed-burst regression fails on baseline `d15cac3f06` and passes on the candidate.
- **328 focused tests passed** across shared debouncing, Telegram bot/media handling, durable ingress, cancellation, authorization, reply/quote context, entity formatting, and SDK mock conformance.
- Targeted type-aware lint, generated SDK declaration checks, formatting, and line-count ratchets passed. Full repository checks remain for hosted CI.
- The complete shared-debounce suite moved into its own directly imported test file; no existing coverage was dropped, and one obsolete oversized-file allowance was removed.
- Independent correctness review completed. Its channel-post concern was checked against the ingress normalizer and passing sender-less channel-post reassembly case; channel posts already receive a stable synthetic sender before batching.
<details>
<summary>Measured test cost (one worker)</summary>
- Shared debounce: 24 tests, 0.59 s test time.
- Remaining inbound tests: 39 tests, 0.23 s test time; both shared files completed in 19.03 s command wall time including preparation.
- Telegram bot boundary: 163 tests, 66.54 s test time.
- Telegram channel-post/media boundary: 41 tests, 25.46 s test time; the two-file command completed in 120.38 s wall time.
- SDK mock admission conformance: 1 targeted case, 16.56 s command wall time including preparation; it fails without the new mock member and passes with it.
- The existing large bot suite exercises registered handlers and durable SQLite-backed admission. New timing cases reuse its fixtures and fake clock rather than adding Gateway/process boots.
- Hosted CI timings will be available on the PR checks.
</details>
### Hosted CI follow-up
Regenerated the config-doc fingerprint for the intentional help change. Fixtures testing immediate delivery now explicitly disable ordinary batching, and typed Feishu debounce doubles expose the admission query. The SDK mock reuses the canonical debounce resolver rather than growing its duplicate policy. The 56 targeted repair tests, plugin test-typecheck lane, and size ratchet passed; Telegram production batching is unchanged from the live proof.
The initial launcher failure came from an unchanged main-parent test and was fixed upstream in #155825; this PR does not change launcher code.
The remaining bot context/media suite now explicitly opts out of ordinary batching through its shared config builders while retaining explicit debounce windows. All137 cases pass (58.75s test time,83.46s command wall time); no assertions or production batching behavior were weakened.
The final integration includes current main rather than copying an unrelated wrapper repair into the Telegram code. The wrapper closure tests passed 2/2 on the integrated source. A newly added disabled-binding startup fixture was made explicitly immediate; all 9 cases pass. The mixed-burst registered-handler and forwarded-context controls passed on the integrated runtime; the original Test Server capture remains for the unchanged batching owner.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* fix(bindings): preserve current route ownership across async reads
* fix(telegram): keep replies working when thread bindings are disabled
Register a live empty binding owner for disabled Telegram accounts and
remove only that exact owner when the bot stops. Acquire binding ownership
after bot setup succeeds so constructor failures cannot leak it.
Preserve enabled missing-owner refusal and binding persistence. Cover real
bot startup, ordinary dispatch, disabled operations, and owner replacement.
Validation: real Test Server original-source failure; nine regression cases
and 65 enabled siblings; selected checks and independent P2 review passed.
The repaired built Test Server run follows this local commit.
Prevent completions cancelled or retired during transport initialization from invoking providers. Recheck existing PDF and image resource claims before dispatch.
Fixes#155813.
Capture the selected physical database, exact key, session identity, and lifecycle before queued consumption. Preserve the empty-queue prompt fast path and reject stale or ambiguous captured targets through the existing SQLite writer.
Refresh against current main using the relocated metadata-error owner. Validate 84 focused owner cases, core types, lint, and format; retain earlier source-bound proof. Fresh review findings about unsupported raw aliases were checked against canonical admission and rejected with four real accessor diagnostics.
* refactor(sessions): reconcile hydration with current worker context
* fix(sessions): remove unused hydration worker type export
Keep the hydration input private to its shared worker union owner while retaining the externally consumed SQLite target input export. This clears the unused-export finding without changing emitted runtime code.
* fix(sessions): stream full hydration within worker memory limits
Transfer canonical transcript chunks through the existing history worker while retaining one read-only snapshot and complete caller-side results. Preserve SQLite text encodings, BOM errors, cancellation, current-owner checks, and native cleanup without raising the worker heap limit.
* test(sessions): align hydration error controls with streaming
Model interactive admission and the canonical streaming result in the
existing quarantine error fixture, preserving its cleanup and retirement
assertions. Remove a redundant unknown-alias assertion from the reader;
emitted production JavaScript is unchanged.
The complete 21-case worker error file, assertion ratchet, owning types,
scoped lint, and fresh P0-P2 review pass.
* feat(browser): unify local Chrome setup across desktop and terminal
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* feat(browser): unify local Chrome setup across desktop and terminal
OpenClaw-Publication: d19e865e-b5a0-4c70-8876-c1662f6e7ef2
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* chore(linux): format Chrome setup fixture
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* feat(browser): keep desktop Chrome setup local and preserve pairing
Delegate Windows registration to the shared native management owner, preserve
released native bridge compatibility and saved launcher profiles, and integrate
serialized desktop setup through isolated local runtimes.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): repair native setup CI contracts
Keep Windows installer dependencies acyclic, validate Unicode within the
package library target, and remove unused private exports. Require all
eight packaged native-host proof cases and update lazy CLI inventory.
Apply native Swift formatter diagnostics without changing behavior.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(cli): account for plugin-owned browser extension catalog
Keep the core-only registration invariant aligned with the Browser plugin
owner already exercised by its lazy registration tests.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(macos): retain released Chrome bridge request expectation
Align the native bridge test with the shipped contract1 request retained
by the canonical setup owner, and reject extra legacy payload fields.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(tui): give command handler harness a unique export
Rename the shared TUI test helper and both consumers to avoid the
Gateway placement harness export collision. No alias or guard waiver.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* chore(sdk): allow canonical browser config path resolver
Apply the approved single public-export and callable allowance for
resolveConfigPath. Preserve canonical pre-config path ownership and
all other SDK surface checks.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): preserve desktop setup selection and supported actions
Keep native automatic setup selector-free and resolve saved local browser
selection through the canonical setup owner before installation. Respect
Mac action advertisements and the released legacy install projection in
the Apps card, and document the public config-path resolver contract.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(auth): retry model selection after concurrent credential refresh
Adopt upstream PR #152426, commit 32298b10f6, without changing its five source files.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test: preserve native setup selection and await dashboard document
Match the selector-free native CLI arguments exactly and preserve a saved work-profile result. Wait through the existing document-readiness owner only at the quota test browser-proof boundary, after auth assertions.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(ui): avoid preloading already imported modules
Remove exact direct static JavaScript imports from lazy preload tables using the emitted build graph. Preserve HTML, lazy-only JavaScript, CSS, and locale hints. Source-exact CI merge reproduction drops startup gzip from 363283 to 362968 bytes without changing budgets. Add a real emitted-bundle regression.
Apply rustfmt layout to the native Chrome selector-free expected arguments.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix: preserve Chrome profiles and attachment follow-up branch binding
Let the TUI canonical setup controller retain its saved browser profile and project only a bounded returned name. Align both native first-run fixture expectations with selector-free setup.
Join pending chat history before the composer task handoff can expose an admitted attachment to restored-outbox delivery. Preserve idempotency, attachment custody, restored delivery semantics, and all existing assertions and timeouts. Add a deterministic regression reproduced on the exact failed CI merge and its main parent.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(state): adopt canonical worker-custody fixture repair
Adopt src/plugin-state/plugin-state-worker.test.ts byte-for-byte from upstream bfec65a2a0 (#152456).
The former fixture held its late competing owner until after awaiting off-thread acquisition. Preserve that overlap, assert continued host authority checks and noncompletion, release custody, then assert the original result and persisted state. No production locking, guard, deadline or outcome assertion is relaxed.
Both prior failures reproduced on the exact CI main parent with independently installed frozen dependencies and Node 24.19.0. All 12 repaired file tests, selected state-logging types, scoped typed lint and fresh P0-P2 review passed.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): retain saved Windows setup profiles
Recover configured extension profiles through bounded serial read-only C# inspection. Select only independently validated current matching descriptors, confirm the selected generation before effects, and leave the single mutation under the existing C# owner. Preserve POSIX behavior, existing manual relay verification and explicit same-profile repair.
Missing descriptors, runtime/origin drift and unknown or changing observations fail closed without automatic mutation. Keep raw management facts private and populate the existing browserProfile field only from validated binding metadata. No ABI, schema, SDK, configuration flag or registry/activation owner change.
29 actual CLI/controller/Windows-adapter boundary cases plus sibling coverage: 94 tests pass. Canonical changed checks, full production build and fresh independent P0-P2 review passed. Actual C# native proof remains separately coordinated.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): preserve saved profiles after POSIX bundle relocation
Separate validated native registration ownership from supported origin-migration readiness. Recover the profile only after full private manifest and exact launcher validation; preserve the existing one-slot migration rule and all unsupported-origin, ACL and foreign-host refusals. Fail closed before selector-free installation when the saved selection cannot be proved.
Extract the unchanged shared origin helpers into a cohesive sibling to satisfy the existing line-cap guard without waivers. Windows admission, ABI and selector behavior remain unchanged.
Actual Linux/Darwin CLI-to-filesystem relocation regressions: 18 failures on original production, all 22 cases repaired. Preserve the private relay key and inode, config, Chrome preferences, work relay19444 and explicit-profile intent. 137 focused tests, eight real POSIX native-host E2E cases, canonical changed checks, full production build and fresh P0-P2 review passed.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(ui): retain input handoff through the shared outbox owner
Remove the superseded pending-history no-yield workaround after main introduced foreground submission custody in the shared outbox owner. Restore chat-submit-guard.ts exactly to pinned main cc7 rather than retaining competing timing policies. Keep passive drains fenced while the input task yields.
Preserve the retained history regression with explicit MessageChannel admission, no passive send before resume, and the same terminal leaf, idempotency key, attachment bytes and exactly-once assertions after completion. Original composed source fails all five focused cases; the repair passes 67 handoff/attachment cases and 20 real Chromium cases in the canonical secretless network-none runner. Canonical checks, UI build/performance and fresh P0-P2 review pass. No assertion, timeout, origin or proxy-policy weakening.
Browser POSIX/Windows repairs remain byte-identical to accepted255f. The failed e40e CI receipts remain preserved; fresh exact-head CI and parent handoff are still required.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(tasks): preserve reads across native event finalization
Hand joined event publication to its exact native successor after the native
flow and observer publication frame completes. Keep worker settlement and
cleanup, reversible claim transfer, current-authority and ABA checks, and
post-commit delivery in their existing owners without replaying writes.
Cover pre-result and readback finalization, native and reentrant successor
chains, rollback, failed publication, delivery, and terminal activity cleanup.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(ui): retain rail baseline geometry on readiness failure
Keep the exact existing readiness predicate, fixtures, case inventory, assertion and timeout. When the predicate is false, retain synthetic marker identity and numeric geometry so hosted CI can distinguish scroll, visibility and viewport failures.
This is diagnostic evidence, not a repair or waiver of the unresolved rail failure. Local rootless browser infrastructure is unavailable; the existing hosted CI lane will verify the reviewed task-publication repair and collect meaningful rail evidence. Canonical changed checks and P0-P2 diagnostic review pass.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* docs(linux): describe saved-profile Chrome setup selection
Match the selector-free adapter argument vector and its regression test. Address the fresh P3 review finding without changing runtime behavior. Markdown syntax and diff checks pass; the generic formatter excludes this subtree.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(transcripts): join configured startup before cleanup faults
Observe and await the real startTranscripts promise through a narrow call-through spy while retaining the configured service entry point and real SQLite/provider work. Bind the await to the existing test lifetime instead of charging startup to the subsequent short active-map poll.
Gate provider return after persisted utterance to prove readiness does not settle early; retain both missing/unreadable row injections and all cleanup, private-source, lifecycle-token and summary assertions. Cover real startup rejection explicitly. No production change, timeout increase, retries or broad module/storage mocks.
The deterministic ordering boundary fails with the old fire-and-forget readiness and passes with the real promise join. Final 39 tests across 3 files, canonical changed checks and full-owner P0-P2 review pass. This does not recover whether the historical CI startup was late or rejected.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): preserve automatic desktop status inspection
Restore read-only Device-page inspection for current and released Mac bridges while keeping installation and verification explicit. Preserve the native filesystem prerequisite proof, split installer repair tests within the existing line cap, and remove the superseded constant export.
* fix(browser): preserve registered setup configuration
Require canonical setup to match an owned launcher's effective state and
config selection before installation or relay access. Preserve equivalent
implicit/explicit default selections and the saved launch context. Recheck
automatic profile selection before effects and the current manifest before
publication through the existing registration owner. Keep manual install
and relocation repair contracts unchanged.
Cover mismatched configs, legacy selectors, equivalent defaults, selection
drift, and actual bootstrap after refused setup. Restore the missing Command
import in the existing Unix-only companion CLI test.
Focused tests, types, lint, fresh review, clean package build and sealed Mac
ARM64 runtime proof pass. The separate historical clock-jump CI failure has
bounded replay evidence and remains documented without a speculative fix.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* fix(browser): keep setup registration types acyclic
Move the private registration status contract beside its context policy and
point both consumers at that owner. Remove the publication-module back-edge
without keeping an unused compatibility export.
The full architecture gate, extension production/test types, typed lint and
fresh independent review pass. Node's transformed JavaScript is byte-identical
for all three affected modules, so the existing runtime proof remains valid.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* test(linux): handle Chrome setup in desktop sharing fixture
Recognize the exact automatic Chrome setup invocation and require its native
no-respawn flag. Keep unknown-command rejection, selected-auth validation,
process-group ownership and joined teardown assertions unchanged.
The original fixture reproduces the CI rejection against the real Linux app.
The repaired fixture passes all nine checks against that same binary, with
five Chrome setup calls and five node starts and joined stops. Fresh review
is clean; production app behavior is unchanged.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
---------
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Use the existing core draft lifecycle as the single owner of retired preview identities and deletion retries. Migrate Discord, Slack, and Matrix away from channel-local cleanup queues.
Keep delayed cleanup from deleting or stopping the next turn, retain failed deletions without replaying accepted finals, and serialize Slack human-context preservation with overlapping drains. Channel defaults, native streaming, configuration, and storage remain unchanged.
Verified with failing-before/passing-after queued-turn and human-context regressions, focused draft and dispatcher tests, and real-channel evidence with documented QA fixture limitations.
Related: #155550
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Centralize final acceptance and preview promotion in the existing core live-message owner, and migrate Mattermost, Discord, Slack compact previews, and Matrix to it.
Preserve accepted receipts across cleanup failure, protect promoted answers, and fence stale final callbacks from later generations. Keep channel defaults, native transport behavior, and released SDK helper signatures unchanged. Account for the explicitly approved three public exports and one callable without disabling SDK checks.
Verified with focused lifecycle regressions, built SDK consumer proof, real Mattermost transport, and leased Discord, Slack, and Telegram lifecycle evidence. Proof scope and QA fixture limitations are documented in the PR.
Related: #155550
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* test(anthropic): verify Vertex metadata in route coverage
* test(anthropic): exercise Vertex endpoint applicability
Prepare Anthropic and Google manifest metadata so the Vertex negative case
reaches the intended endpoint class. Keep native provider inputs eligible so
that endpoint policy controls the result, and use the explicit public
Anthropic endpoint in the positive case.
Retain isolated non-Anthropic-provider coverage in the existing policy table.
Preserve the metadata fixture lifecycle and existing single-root consumers.
No provider runtime or published SDK behavior changes.
Validation: 14 focused candidate cases pass; the missing-Google control
fails only the expected custom-vs-google-vertex assertion. Scoped formatting,
lint, and independent P0-P2 review pass.
* chore: merge main into provider metadata fixture repair
Merge main at 771a42dab0, including the
canonical Telegram fixture maintenance repair f28edb139e.
Preserve the original PR and published candidate ancestry.
The four-file provider fixture diff remains byte-for-byte unchanged. Retain
its 14-case proof, missing-Google control, and clean independent P2 review;
qualify main's separate acpx and Vitest cache ownership changes without
replaying unchanged tests. New-head hosted CI remains required.
The Telegram control proved removal could overtake admitted disk-budget
work, and its repaired original ten-file shard passed 84 cases. The exact
native sidecar actor behind the earlier ENOTEMPTY was not captured.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat: enable automatic Code Mode for preferred models
* test: preserve parser boundary and automatic default expectations
* ci: refresh merge proof after upstream tooling type repair
Refresh the merge ref after main restored the tsx CLI shim declaration in 80b9608a25. No source changes.
Closes#153016
## What Problem This Solves
Fixes: Memory settings reports an engine failure when a loaded, selected memory plugin does not provide host memory search.
## User Impact
User impact: the page describes absent host search neutrally instead of showing a false health warning. Real plugin-load and search-manager errors remain visible. Independently supplied memory integrations, including sidecar public artifacts, keep working. No configuration or migration is required.
## Why This Change Was Made
The existing runtime resolver now reports a missing search runtime only when the selected plugin is known to have loaded successfully. Unknown or failed owners are not treated as clean absence. The existing diagnostic handler passes that fact to the Memory page, which omits the contradictory Engine health card without certifying the health of other integrations.
This is a diagnostic-only change: no new RPC, plugin API, stored schema, permission, or plugin-selection policy. The existing status handler and its tests remain in place.
## Evidence
[Inspected actual Control UI before/after screenshots](https://github.com/openclaw/openclaw/pull/155117#issuecomment-5771965580), also delivered in the originating chat.
- Actual built Control UI and normal isolated Gateway: the selected plugin is reported active, the received `doctor.memory.status` frame carries `searchRuntimeRegistered: false`, and the page shows the neutral host-search state rather than “Memory needs attention.”
- Real registration and search-manager error controls retain failure presentation. The existing memory-core sidecar still lists a synthetic `MEMORY.md` through the supported public SDK; disabling the sidecar produces no artifacts. Optional Wiki stays disabled.
- Registered memory-core with search disabled remains a distinct null-manager/no-error case. Its existing CLI and diagnostic behavior is not claimed fixed by this PR.
- Focused checks pass: **33 runtime + 49 Gateway + 63 UI tests**. New regressions fail against the original runtime/renderer; real-error controls remain discriminating. The core/Gateway command took **24.57s wall**, and the two-file UI command took **6.34s wall**, both with `--maxWorkers=1`. The eight added cases report about **11ms combined test time**; no new test harness or suite was added.
- Scoped formatting, type-aware lint, localization verification and source-size and assertion-safety checks pass. The maintained clean-head runtime/UI build succeeds, and the actual served asset matches the built bytes. No live provider request or operator state was used.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Retained inspection resources can outlive the RPC scope that releases their last claim. Own and drain cleanup in the physical registration source so instance retirement succeeds without reopening the expired request, changing authority, or suppressing cleanup failures.
Extend the existing disposal matrix with captured closed release scopes: three cases fail before the fix and pass after it. The original Gateway Codex delivery-cache fixture completes all three turns with stable request bytes; 92 focused lifecycle cases and core production typechecking pass. Independent review is clean through P2.
* fix(geolocation): keep lookups available during cache write failures
* fix: keep geolocation cache complete during Windows downloads
* fix(geolocation): use private filesystem SDK for cache staging
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Queued shared GitHub publication retains its original requester and access grant across deferral and restart. Accepted results remain recoverable after access ends.
* fix: recognize verified team admins as channel owners
Resolve channel owner authority from SQLite profile identity links and current login grants, with immediate revocation across deferred work. Keep Gateway and bundled plugins on one native SDK graph and replace the related process-global authority registries with instance-owned capabilities.
* fix: preserve channel owner authority through deferred work
Authorize Discord commands before ACP preparation and retain the original live owner through backend effects and updater handoffs. Normalize direct notice recipients through channel contracts. Complete native test-loader and instance-runtime fixture coverage, including final-effect and revocation regressions.
* fix(plugins): retain host SDK access in captured workers
Link captured plugins to the selected host package for worker isolates, preserving native SDK identity through retained generations and recovery. Align CI fixtures with instance-owned runtimes and join owned asynchronous work in teardown and Telegram buffering tests.
Validation: native worker regression fails before the fix and passes across native/legacy and source/dist hosts; 325 core tests, the full 3121-test Slack suite, targeted channel tests, protocol generation, Android lint, changed checks, and independent review pass.
* fix(runtime): keep snapshot cleanup inside owned directories
Treat captured SDK host-package links as removable leaves, preserving ownership records until snapshot data is gone. Preserve sanitized readiness subprocess failures and exercise Doctor through its complete isolated runtime on clean installations.
* fix(plugins): keep lazy runtime ownership metadata local
Preserve deferred Gateway facets with instance-owned proxy metadata and retain redacted readiness failure diagnostics on the current subprocess result owner.
* fix(auth): retain live owner authority through command effects
Carry the admitted administrator assertion through command dispatch, ACP controls and metadata commits, config and allowlist writes, plugin consent and installation, MCP mutation, and restart preparation. Preserve accepted-operation settlement and condition restart acknowledgement cleanup on its owned revision. Prove allowed administrators, forbidden senders, revocation and reassignment through real handler and persistence boundaries.
* refactor(restart): require owned revisions for sentinel cleanup
Remove the unused unconditional clear facade and storage branch. Keep revision-floor migration, durable failure reporting, and updater consumption proof on the canonical conditional-clear operation.
* test(auth): align owner regressions with fixture lint contracts
* refactor(auth): simplify channel owner and runtime authority
Resolve linked channel administration from the current Team role policy, retaining identity-grant fallback only for roleless installations. Consolidate Gateway generation state into its lifecycle owner, simplify Discord native routing and remove redundant loader and ingress state. Preserve current-authority checks before writes and required cleanup after accepted operations.
* test(auth): compare public generation state values
* refactor(auth): keep authority fixtures and handoff types with their owners
Extract coherent fixture builders and internal updater types to keep large files from growing. Correct the task-identifier test import to its codec owner and remove the unused internal route-policy export. Preserve all runtime behavior, assertions, deadlines and revision-owned sentinel cleanup.
* fix(channels): preserve native conversation scope in ingress authority
* fix(imessage): bind ingress after reply ID mapping
* fix(test): preserve scoped filesystem and channel admission contracts
* test(fleet): share stopped container state fixture
* test(fleet): type stop mock against the container contract
* fix(auth): retain current owner authority through deferred effects
* refactor(auth): keep authority fixtures and helpers with their owners
* fix(ci): remove duplicate database worker test entry
Retain the existing worker.runtime test entry so compact CI planning includes every storage-state test once. The duplicate introduced in d2c8c34af2 made preflight reject all split timing generations for this owner.
Reproduced the exact preflight error before the repair. Hybrid, GitHub, and Blacksmith planning now preserve all 660 unique storage-state files. The 217 planner/config tests, selected changed-file checks, formatting, and diff checks pass.
* refactor(auth): prepare profile authority in SQLite workers
Move channel identity and affected profile writes onto the existing worker owners, with current authority at commit and explicit rollback recovery. Bind native Telegram commands to verified ingress and retain shared-owner administration.
* fix(auth): preserve owner checks and released ingress callers
Forward Telegram authority through configured backend preparation and retain released ingress helper provenance through the existing plugin instance owner. Keep identity result types in the leaf contract and repair worker-aware test routing and fixtures without weakening policy assertions.
* fix: correct ingress names and database test ownership
Keep supported SDK ingress adapters while distinguishing internal policy operations. Assign broker-dependent HTTP suites only to the Gateway fork owner, preserve sorted test discovery, reuse chat registration fixtures, and declare the dynamically loaded Telegram test entry.
* test(cli): use prepared runtime for MCP probe exit
Exercise the real CLI entrypoint instead of compiling source-backed SQLite workers inside the command deadline. Keep the 30-second deadline and the exit, JSON, and named diagnostic checks.
* test(codex): check native worker termination at teardown
Observe native Worker thread IDs after fixture cleanup instead of equating
thread exit with asynchronous resource-destroy notification. Keep the
allocation assertion and existing cleanup; do not wait for idle retirement.
The three-case file passes in 48.495s. Omitting only its harness disk-worker
drain fails immediately on a live thread in 30.715s. A Node 24.19 control
observes threadId -1 while the async destroy notification is still pending.
Managed review is clean through P2. The earlier CI worker identity remains
unproven; this is a test-contract repair, not a production leak claim.
* test: settle identity fixtures and route database cleanup
Wait for actual GitHub metadata entry and settle both identity requests on failure. Run the session-store consumer in the existing database fork owner so native retirement can use the host broker.
* test: settle admin fixtures at their owning boundaries
Await canonical asynchronous MCP OAuth reads and the existing Gateway attachment completion. Keep avatar work independently gated and preserve all permission assertions. Move ingress and callback fixture helpers into the existing support owner to keep the health suite within its line-growth limit.
* test(worker): share the compiled SDK graph in crash fixtures
* fix: keep temporary filename overrides inside their directory
* chore: sync main after cron and ACPX fixture repairs
* chore: merge main fixes into fs-safe filename cleanup
Integrate the released fs-safe 0.18.0 dependency and the landed approval readiness and request-cleanup fixture repair. Preserve the existing four-file filename patch unchanged.
Validation: all 73 focused SDK, ClawHub, iMessage, signed-runtime approval, and approval-fixture cases passed on the merged tree. Existing managed P2 review and static-check proof apply to the unchanged authored patch.
* chore: merge fixture repairs into fs-safe naming cleanup
Incorporate the landed session-store and survivor fixture repairs while preserving the four-file fs-safe naming change.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Load plugin skill previews without waiting for every supporting file.
Read the validated inventory and SKILL.md first, fetch supporting bodies only
when selected, and preserve bounded path/link/size/hash checks for installed
and catalog plugins. Scope caches to the open preview and connection, retain
retry/skeleton states, and preserve foreground reading position when a late
sibling response completes.
Measured live Composio initial-read median: 9.456s to 1.931s (7 to 2 requests).
Verified lazy reads, errors/races, rendered scroll regression, and review fixes.
Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>
* feat: add selectable Code Mode executors
Default enabled Code Mode to trusted Node execution and move QuickJS into a bundled executor plugin. Preserve typed discovery, JavaScript-only execution, tool authorization, continuation ownership, and explicit legacy QuickJS selections. Add a web settings selector and document both security boundaries.
* refactor: finish Code Mode executor source cutover
Remove the retired core worker copies and regenerate config documentation for the requested QuickJS plugin. The 21 added plugin paths are standard plugin management fields; core and channel counts stay unchanged.
* refactor: narrow the Code Mode plugin contract
Keep only the executor and guest protocol exports consumed by the QuickJS plugin, budget that generic contract, and load the public plugin artifact through the existing runtime test boundary.
* refactor: align Code Mode workers with current runtime boundaries
Use the worker-side task server, keep asynchronous cleanup ownership explicit, and model the real Promise contracts in lifecycle fixtures. Regenerate the requested plugin config surface and budget the exact 35 public executor exports.
* refactor: keep executor implementation types private
* chore: regenerate code mode config baseline
* fix: satisfy Code Mode executor integration contracts
* test: cover QuickJS plugin metadata and exact settings titles
* test: retain QuickJS integration in the agent runtime suite
* test: keep Code Mode validation within lint and type-shard contracts
* fix(codex): reset native context after history cuts
Retire the native binding only when a local rewind or branch switch commits, so the next turn uses selected OpenClaw history. Reuse existing lease, rollback, and subscription cleanup ownership while preserving predecessor lineage and compaction continuity.
* test(qa-lab): avoid writable executable races in Mantis fixtures
Launch generated command scripts through an immutable shell fixture so inherited write descriptors cannot cause ETXTBSY before process deadline tests start. Preserve real PATH lookup and process-tree assertions; model unregistered worktree cleanup accurately.
* test(codex): assert output fidelity independently of telemetry
Add native computer use and Browser/Terminal launchers for prepared macOS and Windows cloud workers through Crabbox's existing authenticated transport, placement, and teardown.
Launch the separately signed Mac Cloud Worker app through LaunchServices and let it own Node/CUA, desktop permissions, and the renewable idle assertion. Bind Windows enrollment and replay to the worker's interactive account and session. Preserve uncertain launch evidence for reprovisioning, and require confirmed lease teardown before downgrading readers of newer desktop metadata.
Preserve chat end-follow during coalesced composer and goal resizing by carrying the actual scroll correction through the existing resize event and offset owner. Retain the canonical rail, progress, and approval lifecycle implementations.
Validation: exact-head CI passed 165 jobs with seven skips; 142 focused approval cases passed locally. Historical native platform proof and the remaining current-driver, lock/account-loss, enrollment, and downgrade qualification limits are recorded in #152060 under the requested best-effort testing scope.
Refs #152060.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(gateway): keep slow catalogs from blocking other session sources
* test(gateway): preserve catalog proofs with provider serialization
* test(matrix): use the shared Doctor process fixture
Revalidate the existing reload transaction after asynchronous plugin metadata
preparation, before testing its source authority. An unchanged filesystem echo
can otherwise reject plugins.reload during prepare; newer writes and changed
source facts still supersede the operation.
Make the existing real-Gateway regression inject that echo deterministically,
without adding a server boot or weakening assertions. The controlled regression
fails without the checkpoint and passes with it. The original CI group passes
38 files / 510 tests on current main; focused file, changed checks, and independent
review also pass. The uncontrolled watcher replay failure remains documented in
the originating PR evidence.
CI context: https://github.com/openclaw/openclaw/actions/runs/35643858771/job/106479877271
Test cost: full file 91.74s wall with one worker; original group 134.91s wall on current main.
* fix(codex): keep inference bursts from failing turns
Queue one bounded request batch through the shared FIFO permit pool before upstream admission. Preserve handshake errors and headers, absolute connection deadlines, generation cancellation, and idle transport reuse without raising active limits.
* test(codex): allow either native child scheduling order
* fix(codex): cancel queued inference handshakes on disconnect
* test(codex): return void from native cleanup hooks
* test(codex): satisfy inference fixture lint checks
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Let plugin themes declare bounded, self-contained SVG assets for avatar hats
and composer visitors. Capture artwork with each plugin generation, expose
content-hashed authenticated resource URLs, and rasterize images lazily in
the Control UI. Personal imports remain limited to built-in artwork IDs.
Package declared assets through the shared filesystem boundary while keeping
manifest declarations usable by native build and updater tooling. Preserve
existing pointer interactions, loaded-photo hats, palette notifications,
and transcript invalidation. Document validation and reload behavior.
Validation: focused protocol, manifest, Gateway, UI, packaging, native updater,
and extracted PR tooling tests; core/UI/scripts and affected test typechecks;
protocol generators, style lint, dead-code checks, assertion and line-cap
ratchets, formatting, docs links, and scoped-clean P1 review. Inspected
synthetic before/after captures are attached to the PR. Startup budget files
remain unchanged at 370300 B baseline and 370876 B enforcement.