Skip to content

test(peer): check the vault refusal error envelope - #566

Merged
lukemaj merged 1 commit into
feat/379-cross-machine-parityfrom
fix/379-vault-error-envelope-proof
Oct 20, 2026
Merged

lukemaj merged 1 commit into
feat/379-cross-machine-parityfrom
fix/379-vault-error-envelope-proof

Conversation

@lukemaj

@lukemaj lukemaj commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

What: The CredentialFill MCP test now checks the exact refusal in the registered JSON error envelope.
Why: Its inherited plain-text assertion fails against the fork's existing safe error serializer, despite the same origin-mismatch message and correct no-fill behavior.
So what: This test-only #379 component targets the integration branch; both independent reviews and CI must pass before internal merge and #563 revalidation.

Related #379. Fixes the inherited failure seen in #563 Test Server 7: https://github.com/toolboxmd/chromeria/actions/runs/39396196252/job/118539645232. No closing linkage and no production change. The existing safe wire serializer remains authoritative; the test parses one text block containing a JSON object, compares its complete message to the exact originMismatch error, rejects excess fields, and retains sentinel and audit checks. It additionally proves that refusal reads only item URIs and leaves the real page input empty.

Requirements and who asked: The user requires inherited integration CI repairs without weakening vault refusal, privacy or audit behavior.
Deleted: Production/error-contract changes, substring-only assertions, browser skips and unrelated HTML changes.
Bottleneck: The stale public-envelope assertion in its owning test.
Checked myself: Full one-file diff, actual serializer and real Chromium red/green logs; the committed file matches the final passing test/lint/format inputs.

Proof, pinned Node 24.13.1 / pnpm 11.10.0, with task-private Playwright Chromium headless shell revision 1223:

  • Untouched e7a11: 24 pass, one failure, zero skips, matching CI's JSON-versus-plain-text mismatch.
  • Repaired vp test run apps/server/src/preview/CredentialFill.test.ts: all 25 pass, zero skips.
  • Targeted lint and formatting pass without warnings; git diff --check passes.
  • Real isolated browser contexts, synthetic .test origins and vault values; no product server, account, real vault or user profile. No actual product/UI or whole spec: native cross-machine control across linked environments #379 acceptance claim.

Base e7a11a8; head e0bbbe5; tree 6e5d60ba26612d66a21411b91880cf4aaf701e9c. Exact committed test SHA256 d4a1487499e415ee45e76ee37572aa39f4c4f525b43defa62f712608bb09af40. Upstream search found no CredentialFill or equivalent serializer fix; no upstream code was ported. This test-only maintenance changes no shipped feature part or map topology.

User authorization now permits the final #379 main merge only after all final acceptance, exact-final-head independent reviews and current green CI. No rollout, deploy or restart is authorized by this component.

Implementation: GPT-6.1 Sol, Codex, MEDIUM. Integration driver: GPT-6.1 Sol, Codex, MEDIUM.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S labels Oct 20, 2026
@lukemaj

lukemaj commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

What: Opus 5.5 MEDIUM approves the whole test-only #566 component at e0bbbe5, with no required findings.
Why: The strict assertion matches the actual safe registered-tool error contract and retains exact-message, no-read/no-fill, sentinel and audit oracles.
So what: Sol's independent verdict and current CI remain required before internal integration; review/independent stays pending until both reviews finish.

Requirements and who asked: User-approved #379 requires repaired inherited CI, meaningful vault proof and both independent exact-candidate reviews.
Deleted: No production contract change, weakened privacy oracle, second-family waiver, CI bypass or rollout authority.
Bottleneck: Remaining Sol verdict and CI for this lower-layer component, then #563 composition.
Checked myself: Read the complete Opus report and exact scope/identity/proof limits. It reports a scratch schema-decoder probe and no Chromium re-execution; author real-browser red/green evidence remains separately bound to the committed test hash.

Unchanged Opus round-1 report

#566 component review, round 1, Opus 5.5 MEDIUM

Verdict: APPROVE (whole component)

  • PR: test(peer): check the vault refusal error envelope #566 (OPEN, base feat/379-cross-machine-parity)
  • Base: e7a11a84f03f7022a8013aa956d8afec5d250eb3 (equals live origin/feat/379-cross-machine-parity)
  • Head: e0bbbe5ce986afd87df89e6d951334aef662317a (equals live PR head and origin/fix/379-vault-error-envelope-proof)
  • Tree: 6e5d60ba26612d66a21411b91880cf4aaf701e9c
  • Diff: one file, apps/server/src/preview/CredentialFill.test.ts, +17/-6; byte-identical to final.diff. PR files list shows only this path.

Required findings

None.

Contract check (production, unchanged)

  • preview_fill_credential is declared in apps/server/src/mcp/toolkits/preview/tools.ts:248 with failure: PreviewToolFailure, included in PreviewStandardToolkit (tools.ts:388..401), registered via toolkitRegistration(PreviewStandardToolkit, PreviewHandlers.layerStandard) (McpHttpServer.ts:1294).
  • toolkitRegistration wraps with wireToolkit (McpHttpServer.ts:1131-1155), failureMode: "return", encoder: OrchestratorMcpFailure -> its encoder, otherwise { message: error.message }. PreviewCredentialError (packages/contracts/src/previewCredential.ts:124) is a Schema.TaggedError, not an OrchestratorMcpFailure, so the wire value is exactly { message }; reason/tabId/_tag are scrubbed. The new expectation matches the intended current contract and does not invent one. Rolling back to plain text would change production for every registered toolkit and drop peer receipt fields.
  • Broker maps the remote PreviewCredentialError back to the typed error (PreviewAutomationBroker.ts:353); handler audits error.reason on failure (handlers.ts:460-487), which the unchanged audit assertions still cover (result: "originMismatch", site: null, exact key set, mode 600).

Test strength

  • Schema strictness verified empirically, not taken from the claim: disposable probe (probe.mjs here) against the worktree's locked effect@4.0.5 with the exact decoder. Results: valid {message} Success; inner excess key Failure; outer block excess key Failure; two content blocks Failure (Tuple with no rest rejects extra elements regardless of options, SchemaAST.ts:2409); plain text Failure; non-string message Failure. So onExcessProperty: "error" does propagate into fromJsonString and the tuple element struct.
  • toEqual({ message: <PreviewCredentialError(originMismatch).message> }) owns the exact message; isError === true retained; structuredContent absent added.
  • New oracles are sound: vaultCalls is reset per test (beforeEach), so ["uris:Example","password:Example","uris:Example"] proves the mismatch attempt read only URIs; #user empty in real Chromium proves no fill (the earlier fill targeted #pw). expectNoSentinel([filled, mismatch]) and audit checks are retained.
  • Secrecy is not weakened: the decoded message is a fixed server string; sentinel scan still covers the full raw result.

Proof binding

  • red-pinned (head e7a11, untouched file sha 6ccd56d1..., scoped PLAYWRIGHT_BROWSERS_PATH): 24 passed / 1 failed; diff shows plain message expected vs {"message":...} received. Matches CI job 118539645232 (1 failed | 1361 passed, only CredentialFill.test.ts failing at the same assertion).
  • green-final: 25/25 passed, file sha d4a14874..., equal to committed HEAD: blob and current worktree file. Ran as uncommitted worktree on e7a11; binding is the file hash plus the fact all other tracked files equal base (git diff stat confirms single file).
  • Typecheck not run by author; the change uses inferred standard Schema APIs and lint passed. Non-blocking: CI typecheck on the integration head covers it.

Optional (non-blocking)

  • None worth changing.

Unread / not done

No source, index, ref, or external writes. Only scratch writes: probe.mjs, this report.

@lukemaj

lukemaj commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

What: Both independent families approve the whole test-only #566 component at e0bbbe5, with no required findings.
Why: Sol confirms the real safe error-envelope contract, strict decoding and preserved vault privacy/audit behavior; Opus's matching report is comment 6287561315.
So what: Paired review is successful on this exact head. Internal merge waits for current server CI, which is still running; afterward #563 can be rebased and revalidated.

Requirements and who asked: The user requires both exact-candidate independent reviews and green CI before internal integration and final delivery.
Deleted: No pending-CI bypass, old-head approval transfer, production behavior change or rollout authority.
Bottleneck: Current server CI on this component, then #563 composition.
Checked myself: Read both complete reports and proof-binding limits; live #566 still has exact e0bbbe5 head, integration base and mergeable state. Build/typecheck, lint and package tests are green; all eight server shards remain in progress at this readback. Browser red/green remains 24/1 before and 25/0 after with zero browser skips.

Unchanged Sol round-1 whole-component report

WHOLE COMPONENT APPROVE

What: Independent whole-component review found no required correction in PR #566's one-file test repair.
Why: The candidate validates the existing safe registered MCP failure contract while preserving the exact refusal, privacy and audit requirements and strengthening the observable no-read/no-fill checks.
So what: Parent may relay this Sol verdict unchanged and combine it with the separately required Opus verdict; this is not final #379 acceptance or merge readiness.

Reviewer: GPT-6.1 Sol, Codex harness, MEDIUM, round 1. Separate reviewer, no authorship and no earlier component findings reused.

  • PR: test(peer): check the vault refusal error envelope #566
  • Exact base: e7a11a84f03f7022a8013aa956d8afec5d250eb3
  • Exact head: e0bbbe5ce986afd87df89e6d951334aef662317a
  • Exact tree: 6e5d60ba26612d66a21411b91880cf4aaf701e9c
  • Workspace: /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof
  • Branch: fix/379-vault-error-envelope-proof
  • Whole actual base-to-head diff: only apps/server/src/preview/CredentialFill.test.ts, 17 insertions / 6 deletions. Git status was clean at inspection and after source review; local tracked upstream divergence was 0/0. Live PR base/head matched the exact requested candidate.

Findings

Required: none. Optional: none. No supported reachable issue requiring a trigger/caller/location/effect finding was identified in the whole component.

Elon record

Requirements and who asked: User/parent requested independent whole review of the existing #379 compatibility microfix, preserving exact safe origin-mismatch meaning, privacy, no credential read/fill and audit behavior, with retained real isolated Chromium proof.
Deleted: No new feature, production contract rollback, ceremony tests, broad proof requirement, unrelated component review or prior approval transfer.
Bottleneck: Determine whether the old plain-text expectation contradicted the authoritative inherited registered failure contract, then establish that the replacement checks remain strict and that proof binds to these bytes.
Checked myself: Read the complete actual one-file Git diff and whole CredentialFill test; traced fill, broker error reconstruction, preview handler/audit/tool declarations, registration, Effect serializer and strict decoder source; read raw red/final-green evidence and run bindings; recomputed source, diff, configuration and browser artifact hashes.

Contract and consumer review

The exercised path is CredentialFill.test.ts's registered server.callTool(preview_fill_credential) -> McpHttpServer.layerPreviewToolkit / toolkitRegistration -> PreviewHandlers.layerStandard / preview_fill_credential -> PreviewAutomationBroker -> fixture callback invoking the real fillCredential against the synthetic Chromium page -> broker credential-error reconstruction -> audit -> registered safe failure encoding -> MCP result consumed by the test. The broker substitute is explicit and does not pretend to verify full ServerBrowser profile quarantine or live vault integration.

Production source examined:

  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/apps/server/src/preview/CredentialFill.ts, complete. Host mismatch is decided after URI lookup and before vault value read or fill. The unchanged direct-browser tests cover frame origins, HTTPS refusal, editable targets, vault refusals and caller refusal before typing.
  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/apps/server/src/mcp/PreviewAutomationBroker.ts, credential error decoder/reconstruction. A valid credential reason becomes the canonical typed PreviewCredentialError, rather than trusting a browser-supplied message.
  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/apps/server/src/mcp/toolkits/preview/handlers.ts, relevant invocation/targeting/authorization and complete fill handler. Audit success/error taps complete in the returned effect. Failure audits use null site and the typed reason.
  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/apps/server/src/preview/CredentialAudit.ts, complete. The line schema, append and mode enforcement agree with retained assertions.
  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/apps/server/src/mcp/toolkits/preview/tools.ts, shared failure declarations, presentation fields and credential tool definition. PreviewToolFailure includes both credential automation errors and Orchestrator failures.
  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/packages/contracts/src/previewCredential.ts, complete, and /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/packages/contracts/src/previewAutomation.ts, automation failure union. The exact originMismatch message is canonical, fixed and page-data-free.
  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/apps/server/src/mcp/McpHttpServer.ts, complete wireToolkit/toolkitRegistration and relevant preview registration. Lines 1131-1177 preserve declared Orchestrator fields and encode other errors as {message} in return mode. Production encoding is unchanged across this component.
  • /home/luke/.t3/worktrees/chromeria/fix-379-vault-error-envelope-proof/node_modules/.pnpm/effect@4.0.5/node_modules/effect/src/ai/McpServer.ts, relevant toolkit registration/result code, including toolResultContent and lines 2145-2187. Return-mode handler failures produce one text JSON block, isError: true, and undefined structuredContent. This independently supports the corrected test contract rather than deriving it from a red CI count.

Relevant unchanged test consumers inspected include McpHttpServer.test.ts's exact JSON capability-denial assertion and public HTTP result parsing, preview/tools.test.ts's public schemas, and preview/handlers.test.ts's registered credential/end-login completed, unresolved and legacy cases. Their receipt boundaries depend on the modern registration, so reverting production to plain-text failure mode would be inappropriate.

Decoder strictness

This conclusion is source-verified against installed Effect 4.0.5, not assumed from the option name:

  • Schema.ts:9829-9837: fromJsonString composes JsonString with decodeTo of the target object.
  • SchemaParser.ts:272-280, 981-1010, 1178: decodeUnknownEffect forwards the supplied parse options to the normal compiler/parser.
  • internal/schema/compilerRegistry.ts and internal/schema/interpreter.ts, read completely: the normal interpreted path preserves options through child parsing, encoding transformations and final parseLocal(value, options). JSON transformation does not reset onExcessProperty.
  • SchemaAST.ts:2380-2553: tuple elements get the same options; absent required elements fail and a tuple without rest rejects excess elements.
  • SchemaAST.ts:2990-3048, 3120-3155 and the inspected fallback: objects reject enumerable own excess keys when onExcessProperty is error, and pass the options to property parsers.

Therefore the candidate rejects empty/additional content blocks, wrong content kind, excess block fields, plain text or invalid JSON, non-object JSON, missing/non-string message, and extra parsed message fields. Whole-object equality then enforces the exact canonical originMismatch message. Raw sentinel exclusion still checks the original complete responses, and undefined structuredContent excludes a second payload channel. The added vault call sequence distinguishes the earlier successful password fill from the refusal's URI-only lookup, and a real Chromium input read checks the username stayed empty. Existing audit contents, key set and 0600 assertions remain intact.

No decoder mutation experiment or test was executed by this reviewer, as instructed. Duplicate JSON object keys are ordinary JSON.parse semantics and are not a new claimed protocol prohibition; no finding is manufactured from that unrelated generality.

Evidence and exact-byte binding

Evidence root: /home/luke/.local/state/chromeria-379-proof/379-vault-error-proof-repair.
Read final-binding.json, inputs.json, complete final.diff, raw red-pinned.log and green-final.log, their complete JSON bindings, browser-provision log/JSON, final lint/format log/JSON, red-default log/JSON and setup JSON. Also inspected green-pinned raw output. Read the relevant original CI failure, summary and stack in /home/luke/.local/state/chromeria-379-proof/382-idle-html-repair/ci-server7-118539645232.log.

  • red-pinned: unchanged base file SHA256 6ccd56d10e6fac3074739d11bb13f6769aab52d39d6ed44c371944e78951ebfa, empty diff, base HEAD/tree, exit 1, 24 pass / 1 fail / no skips, 20 October 2026 11:04:29-11:04:40 Warsaw. Actual failure is precisely plain message versus JSON with the identical message, agreeing with original CI, not a launch failure.
  • green-final: exit 0, all 25 pass / no skips, 11:05:27-11:05:39 Warsaw. The run JSON honestly records precommit base HEAD/tree plus the exact final working diff. Its file hash matches current committed file SHA256 d4a1487499e415ee45e76ee37572aa39f4c4f525b43defa62f712608bb09af40, recomputed independently.
  • Actual git diff --no-ext-diff BASE HEAD SHA256 is 74c99b94fbcaff7f78f457c77df0c05dc427ae96135969fe7525f13aa8f040b6, equal to final.diff and final binding. Git confirms no other tracked file differs from base.
  • Final lint: exit 0, empty raw output. Final formatting: exit 0, one matched file formatted. Both JSON records bind the same final test hash and patch.
  • Default-browser attempt: missing executable at the global cache path, exit 1 with 15 pass / 10 skipped. Correctly excluded as setup failure from red/green evidence.
  • Browser setup: locked playwright-core 1.60.0, headless Chromium revision 1223 / version 148.0.7778.96; FFmpeg 1011 companion downloaded by that installer. Provision log and JSON show task-private PLAYWRIGHT_BROWSERS_PATH and no OS dependency install. Both red and green use that identical scoped path.
  • Recomputed every hash listed in inputs.json: lockfile, root/server manifests, Vite config, Playwright browsers manifest, Chromium binary, FFmpeg companion and original CI log. All match. Browser SHA256 7b8e92dca0acf9c24b5974507b3031d6bd18cc009cd431c2595e521430ea747a; CI log SHA256 55322977db7744fc6d69036551cacb9b2a9ac0074c4b77e93194ec760af5de9c.

The missing full compiler is not essential component proof for this test-only schema/assertion change: installed API signatures and actual runtime execution cover the new code, no production interface/type changed, and targeted static checks passed. This conclusion does not replace any required current integration CI or complete #379 gate.

Scope, authority and unread ledger

Read live PR #566 body and exact base/head plus canonical decision comment 6287355811 and authority comment 6287385562 in full. Their scope agrees with this test-only component. It supports #379's existing cross-machine capability work without selecting a new feature or durable direction. No map/version change is needed for this pure test maintenance.

No source/index/ref changes, tests, installs, child agents, providers, services, browser/device sessions, live SQL, merge or deployment were performed. Only this report was written to the authorized scratch directory. The runtime-required PR thread link was registered and the list verified; no GitHub comment, review or commit-status write was performed. Parent owns publishing this unchanged report and the paired conjunction status.

Unread/unverified: remaining unrelated McpHttpServer/toolkit cases and complete broker internals were not exhaustively reviewed; no claim of whole-repository review, live ServerBrowser/vault behavior, current complete CI, Opus approval, #563 review or final #379 acceptance is made. Upstream searches were not repeated because this review ports no code and the decisive inherited source is local. No essential requested component path remains unread; no component blocker is outstanding. Both exact-head independent component verdicts remain required as a conjunction, followed by the parent's remaining repairs, final exact-head reviews and current green CI. Fleet rollout, deployment, installed restart and live userdata remain outside authority.

@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 5.0 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.9 KiB — 29.3 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.2 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: e0bbbe5 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@lukemaj
lukemaj marked this pull request as ready for review October 20, 2026 09:18
@lukemaj
lukemaj merged commit d5a52b6 into feat/379-cross-machine-parity Oct 20, 2026
29 checks passed
lukemaj added a commit that referenced this pull request Oct 20, 2026
* feat(peer): preserve authority and native returns across environments (#391)

* feat(peer): return notices and delegate onward within durable authority

* fix(peer): retain authority through queued execution and recovery

* fix(peer): preserve active run authority across native operations

* fix(peer): retain authority for every accepted run input

* fix(peer): check every contributor against the actual target

* fix(peer): validate joint work against its actual resource

* docs(peer): inventory retained consent seams

* fix(peer): remove unused authority helper re-export

* fix(peer): bound private output by effective caller modes

* fix(ci): weight the measured peer authority workflow

* fix(peer): retain effective caller modes during task cancellation

* feat(peer): continue remote delegated jobs and stop later work (#392)

* feat(peer): retain remote delegated job lifecycle and durable Stop

* docs(map): link remote lifecycle component PR

* fix(peer): preserve Stop replay and source task navigation

* fix(peer): reconcile accepted attachment and bound session expiry

* fix(server): bind delegated lifecycle routes to production runtime

* fix(peer): preserve attachment bytes and native request acceptance (#410)

* fix(peer): preserve attachment bytes and native request acceptance

* docs(peer): link request recovery component review

* docs(peer): register attachment recovery review provenance

* fix(peer): declare device receipt owner in fork inventory

* fix(server): preserve scoped retries and scheduler acceptance

* fix(peer): preserve authorized manual admission and saved snapshot replay

* fix(peer): preserve native preview capability refusal

* fix(attachments): recover exact native discard acceptance

* fix(attachments): retain bytes after keyed discard acceptance

* fix(preview): reconcile native recording claims before replay

* feat(peer): answer remote descendant requests from the source (#416)

**What**: Exact #369 candidate42051c passed real source-only web and Codex peer request acceptance, including committed replay after both full CLI servers restarted.
**Why**: Independent tests cannot establish that the production composition, real provider callback and source-only client work together.
**So what**: The planner accepts this bounded internal component for integration into #379 after a fresh head/base/gate check; combined multi-machine/client acceptance and final shipment remain pending.

Requirements and who asked: User #379 mandates native delegated lifecycle and all permitted tools with two MEDIUM reviewers and real isolated client/provider proof.
Deleted: No fake provider, direct SQL mutation, injected browser RPC, capability expansion, alternate harness or duplicate callback.
Bottleneck: Current candidate integration; #383 shared device authority/discovery and #384/#385/#386 remain outstanding.
Checked myself: Primary planner drove actual source A browser, inspected native B events/provider results, restarted both CLI products, replayed exact original request, and reopened the same source-only result.

Identity: HEAD42051c47813c354682b80677009b199d86fef1a0, treef9efef2d7df1b8b91ac64b09018386e79ccc1d45, baseab1bf53640e2a6541a2ba9f316839cedf81d4f46. Clean author workspace /Users/rocky/.t3/worktrees/chromeria/feat-369-remote-pending-requests. Both full production servers ran that source, with meaningful copied task-owned history in NEW /tmp/chromeria-369-acceptance-a and -b; old382 homes/evidence remained untouched. Node24.18, A server14247/web7663, B14248, source incognito Browser connected ONLY to A950a38f2-e2a5-4242-9171-c17e0cb8412c. Actual B is ef047b58-1edf-4ad6-a1ba-44320188325c. No live userdata write, new grant, physical device or standalone worker server.

Human source-only flow: A actual Codex gpt-6.1-sol/MEDIUM delegated real async B task369-parent-native-question-v1 in existing B project/root. B actual Codex asked request_user_input_async, persisted pending at B sequence288. Primary opened source task viewer from transcript; browser URL stayed A, no B profile. The actual card displayed369 REAL REMOTE QUESTION, ACCEPT_369/DECLINE_369 and disabled Send answer until selection. Primary selected ACCEPT_369 and sent once. B durable request resolved at sequence290, command mcp:request:385bcb2f7e0a7415a3c0d1cda8a0cabb0b7204f83949b505a9f4fe4cb6482210:0, 2026-10-18T10:10:47.347Z. Real provider consumed the answer and completed369_REMOTE_ANSWER=ACCEPT_369. Source returned exact original result and zero pending requests. Not inferred from dispatch acceptance.

Agent tool flow: Separate deliberate B task369-parent-native-agent-answer-v1, same explicit Color. Native delegate mode wait returned on real pending question with waitTimedOut:false, requestCount1, actual qualified target/revision334. Source local list{} correctly returned[]; explicit remote descendant list returned its actual request. Native qualified read returned real369 REAL AGENT QUESTION/options/revision334. Source called t3_pending_request_respond with original target/route/expectedRevision334, answers{0:AGENT_ACCEPT_369}, stable key369-parent-agent-response-v1. Initial AND exact retry both returned sequence340. B request has exactly one pending334 and one resolved336 event; real provider completed369_AGENT_RESULT=AGENT_ACCEPT_369. Two B tasks intentionally created, each ordinal1 completed, no duplicate B run.

Restart proof: Read-only query found zero preparing/queued/starting/running/waiting runs in A/B. Primary stopped only captured own sessions47643/49402 (exit130), restarted same source and same NEW homes in sessions86505/9639. A actual Codex ordinal34 called ONLY the exact original respond input/key after reconstruction: sequence340 again. Postrestart B has no additional request resolution or provider run. Source previous-agent viewer reopened after both restarts with original human result, real accepted answer and zero pending requests. Actual client screenshot inspected before upload.

Evidence: local immutable/raw read-only oracles /tmp/chromeria-369-parent-actual-question-proof.json, /tmp/chromeria-369-parent-native-agent-tool-proof.json, /tmp/chromeria-369-parent-postrestart-proof.json. Full CLI logs /tmp/chromeria-369-acceptance-{a,b}-server.log and -restart.log retained. Native Browser screenshots in existing UNPUBLISHED draft evidence-379, never a public release:

![Real source-only pending question](https://github.com/toolboxmd/chromeria/releases/download/untagged-cf149e2fe74d54191ae2/browser-screenshot-localhost-mvdnzzmy-b8c7d28b.png)

![Real source-only completed result after reconstruction](https://github.com/toolboxmd/chromeria/releases/download/untagged-cf149e2fe74d54191ae2/browser-screenshot-localhost-mvdo5woi-469c18e9.png)

Both fresh exact-candidate independent MEDIUM reviews APPROVE: Sol #416 (comment) and installed Grok4.7 #416 (comment). Full aggregate #369 (comment). Current420 CI39116640008, Fork39116640150 and final fingerprint39116844636 SUCCESS; original canceled fingerprint retained separately. Authenticated newest review/independent SUCCESS by lukemaj. Neither review substitutes for the actual proof above. Full author/R1/R2 packet #369 (comment).

Limits: These are TWO isolated Rocky environments, web/source-only browser and actual Codex provider. No physical cross-machine/tunnel/mobile/native desktop/all-provider/real live approval, durable-dismiss or secret acceptance claim. Registered native tests retain their own broader and S1/S2 race/empty-choice proof. Earlier native initialization404 remains UNKNOWN; later tests/CI/actual positives do not diagnose it. Operational verification earlier used invalid exact=true locator syntax and a stale assumed web port; corrected to supported selectors/actual dev-runner7663 without alternate browser or product changes. Cost supported publish #416 (comment) is partial task379 coverage, not complete cost; old unplaced/unpriced usage remains unknown. Background supported sync still pending at this record, not presumed complete.

States: implemented YES; current focused/native tests YES under their exact records; BOTH reviewed YES; current CI YES; bounded primary product proof YES; internal integration NOT YET at this record; main merged/build/shipped/activated/live combined acceptance NO. No package bump. All rollback/evidence/workspaces retained under explicit #379 instruction until final acceptance.

* fix(client): clarify remote requests and count pending work once

* fix(client): make remote request choices readable and accessible

* docs(peer): track the remote request client repair

* fix(peer): count initial remote work once in sparse shells

* feat(device): add typed remote device execution core (#421)

* feat(device): execute typed commands across peer links

* docs(map): link the typed device core component

* fix(device): preserve native authority and typed command semantics

* fix(device): recheck authority before native shutdown

* wip: preserve native contexts and purpose metadata after main alignment

* fix(peer): preserve current-main request answering policy (#539)

* fix(peer): preserve current-main request answering policy

* fix(compat): restore inherited CI consumers

Reuse baseline-only repairs from the preserved #383 checkpoint d892050cb97854e08ca1ca427fc762caebbd69f7 under the #379 ownership transfer. Adapt the two web test fixtures for actual Chromium collection without changing production web behavior.

* test(prism): absorb native recovery observer fixture

Transfer the exact test blob authored in cdd4780 and preserved by PR537 at fcd3162. Await the native observer marker before measuring the live batch; preserve the duplicate assertion and production source.

* fix(client): hide remote children from default navigation (#546)

* wip: hide remote children from default navigation

* wip: register destination navigation component PR

* wip: retain user forks with remote provenance

* wip: cover phone and alternate sidebar navigation

* wip: declare phone and legacy carried upstream edits

* feat(peer): keep destination automations authorized offline (#555)

* feat(peer): retain destination automation authority offline

* docs(peer): link destination authority component PR

* wip: repair destination authority recovery and acceptance findings

* wip: fence schedule acceptance and preserve live birth permissions

* wip: preserve birth permission purpose and split native proof

* wip: preserve recovery routes and birth dependency lifetime

* wip: retain paired recovery routes through repeated unlink

* wip: wake exact automation disable recovery at known expiry

* feat(remote): view and control qualified browser and device resources (#534)

* wip: combine qualified resources with destination automation

* wip: bound mobile returned-resource row height

* wip: respect native top safe area for tool resources

* wip: preserve current-main cross-machine compatibility checkpoint

* wip: preserve linked research and tool policy identity across main alignment

* wip: repair vault authority and keyed MCP configuration replay

* test(server): validate credential refusal error envelopes (#566)

* fix(peer): render HTML from idle destination contexts (#563)

* fix(server): prepare HTML in idle peer resource contexts

* docs(map): track the open idle HTML component

* fix(orchestration): wake parents for remote pending requests (#531)

* fix(orchestration): wake parents for remote pending requests

* fix(orchestration): deliver held remote requests when parent waits end

* fix(peer): wait for request content before notifying parents

* fix(orchestration): catch up requests after remote original completion

* test(web): isolate panel keyboard tests from inherited pointer (#575)

* fix(peer): attribute remote follow-ups to the completing run (#582)

* fix(peer): attribute remote follow-ups to the completing run

* docs(map): link remote completion provenance repair

* fix(peer): use observed purpose for first remote completion

* fix(scheduled-tasks): record refused keyed manual runs as terminal failures

A keyed run_scheduled_task_now whose dispatch failed with a typed error and
left no native receipt returned outcome_unknown and kept the schedule marked
running forever. Record it as the request's failed outcome, release the
running reservation, and replay the same failure for the same key.
Interrupted or defective dispatches stay outcome_unknown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(orchestration): accept blank optional answers in remote request admission

Remote pending-request answers with expectedRevision rejected a blank or
omitted optional choice-only question as an unoffered option. Skip blank
optional answers before validating options, matching the message-response
path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(fork): keep one owner for server shard weights

#581 registered shardWeights.json under run-groups while the integration
already owns it under fork-maintenance; fork-features requires one owner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(server): weight typed peer effects by their CI time

PeerAuthority.typedEffects.workflow.test.ts takes about 197s in a CI shard
but was weighted 46.4s, so Test Server 8 exceeded its 10-minute limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(peer): reopened parents follow their remote tasks again

Archiving a parent ended its remote follower, and nothing restarted it on
unarchive, so the reopened parent missed later remote results until a
server restart. The follower now stays registered and waits for the
parent's unarchive or deletion instead of exiting, so reopening resumes
observation without a new entry point or a duplicate follower.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(peer): threads read and answer their own questions again

The replacement pending-request service refused every "own" answerer, so a
thread reading or answering its own user-input question, or an ordinary
full-access MCP client doing so, got capability_denied. Own access is
restored for local, non-linked callers on threads not delegated from
another environment. Own approvals, dismiss, linked clients and remote
delegated children keep their existing refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web,mobile): remote request cards keep multiline editor answers

Remote pending-request cards rendered every custom answer as a single-line
field, so a multiline editor prefill displayed and was stored flattened.
Editor questions (those with an initialAnswer) now use the Textarea on web
and a multiline, newline-submitting field on mobile, as the local paths do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(scheduled-tasks): keyed pause and resume replay their receipt

A keyed update_scheduled_task carries clientRequestId on its input, so the
enable-only shortcut never matched: a keyed pause or resume fell through to
the full definition update and was refused without a purposeIntent. The
shortcut now ignores routing fields, and setEnabled records and replays
the keyed mutation receipt like create, update and delete. A retried
keyed pause after a later resume replays instead of retiring the newer
automation certificate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(scheduled-tasks): post-admission recheck refusals release keyed manual runs

A typed refusal from the recheck after admission, or after the dispatch
claim, now records the key as failed and frees the schedule instead of
leaving it running. The stage-guarded claim keeps uncertain dispatches
outcome_unknown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(childThreads): stop-disposed remote children stay pending background work

A parent interrupt disposes a delegated completion with disposedBy "stop"
without stopping the remote child. The sparse SQL remote arm dropped that
row while the local arm and pendingDelegatedChildTasks kept it, so shells,
auto-settlement and storage cleanup treated the parent as idle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(scheduled-tasks): final recheck refusals no longer fail a concurrent same-key dispatch

The final live recheck ran after the prepared -> dispatching claim and
terminalized a refusal from the dispatching stage. For an existing-thread
schedule a same-key retry can read dispatching and send concurrently, so
the refusal failed the request and freed the schedule while that send was
accepted. The final recheck now precedes the claim, so a refusal is only
recorded through the prepared-stage compare-and-set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(peer): finished remote jobs no longer hold back live Stops

A lifecycle-v1 follower keeps long-polling its job there after the result,
so a later Stop or follow-up is still observed. Each poll held one of the
eight shared peer permits for up to 20 s, so more than eight finished jobs
starved Stops and live observations of other jobs.

Followers whose job has nothing left to do there (result available, no
queued runs, questions or recovery wait, or a confirmed Stop) now wait on
their own semaphore. Stops, unconfirmed and acknowledged stops, live jobs
and follow-ups seen as working keep the existing eight permits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(peer): stopped remote jobs with new work there keep live permits

A confirmed Stop counted a job as settled whatever its latest snapshot
said, so fresh direct input on the destination child after the Stop
left its follower queued behind idle settled long-polls, also after a
restart.

A job is now settled only while its latest snapshot is quiet (result
available, no queued runs, questions or recovery wait); a confirmed Stop
also needs that quiet snapshot. Anything showing activity uses the
shared network permits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant