Skip to content

CONTRACT: keep interactive tool rosters stable across turns - #2073

Merged
schlessera merged 12 commits into
mainfrom
fix/2048-stable-tool-roster-p0
Oct 16, 2026
Merged

schlessera merged 12 commits into
mainfrom
fix/2048-stable-tool-roster-p0

Conversation

@schlessera

@schlessera schlessera commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Closes #2048

What changed

Ordinary PR completing #2048. Dependent context work remains in draft #2072 and will be reconstructed against delivered main after this change lands.

Interactive Claude and Pi sessions offer a complete, deterministic first-party tool roster across posture changes, strict fallback, no-grant surfaces and temporary handler loss. Unavailable calls refuse before permission cards, write locks or privileged handlers. Voice-first sessions retain later typed tools; independently available inbox handlers remain usable. Claude native Write/Edit/NotebookEdit stay registered while strict/voice execution refuses.

A trusted, session-stable StartTurnRequest.applicationAuthority: "server" declaration preserves hosted legacy-project MCP shadowing through temporary handler loss. Unhosted consumers retain their legacy writers. Autonomous membership/permission checkpoint behavior and Pi production voice refusal are preserved.

Why this shape

Implements selected A: registration is a stable deployment fact; current authority is enforced at call time. Mandatory Claude hooks/canUseTool checks and Pi gates/tool bodies preserve exclusions even through settings auto-allows. Governed typed stale-read/write-lock controls remain intact; #2022 retains its separate native auto-allow work. Authoritative MCP/package contracts, SDK API report and historical voice/governed decision records are updated. Minor changesets cover both backends, SDK and server.

Proof

  • Frozen head 364194c01375a0285c809d1b7e5224cf66acd1fd includes base 626a03af4a9db064751230a84732755b8afa961e. Current-base preflight: 864 pass / 5541 assertions, lint/leakage/env/changeset gates clean. Changed measurement/shard harness controls: 32 pass / 60 assertions. Bun 1.4.2.
  • Actual installed Claude SDK/CLI and Pi workers run under offline bwrap --unshare-net with local fake Messages/Responses endpoints and fictional credentials. Claude typed→voice→strict and voice-first→typed→missing-handler→no-grant→partial-handler requests retain byte-identical tools. A real project stdio MCP is configured; separate resumed unhosted controls retain all legacy writers and execute an allowed brain_add call. Per-tool voice/strict/missing-handler refusals survive settings/project allows, without cards, handlers or file changes. NotebookEdit is read first so its denial reaches the mandatory hook.
  • Pi real-worker no-grant→typed→missing-handler request bytes remain identical; per-call refusals precede cards/handlers and a later typed picker succeeds. Separate voice-first roster/per-tool gate and production dispatch-refusal controls preserve the supported authority boundary.
  • Failing-first, required mutations and restored regression receipts: native roster removal fails tools equality; removing mask refusal fails its exact runtime hook assertion. Partial inbox availability and autonomous checkpoint controls fail before correction and pass after. Restored affected local runtime/contract/lock/yield proof: 94 pass / 546 assertions plus 29 pass / 130 assertions.
  • Previous complete execution receipt: all 13 execution jobs pass, but the aggregate correctly rejects the externally advanced base. Its actual head/base/tree and artifacts remain historical evidence. chore(ci): admit measured layout costs for browser shards #2062 changed proof partition inputs, so fresh current-candidate confirmation is required; no old receipt is relabeled as a new combined-tree pass.
  • Current-head confirmation 38905724827, attempt 1, passes all 15 jobs, including metadata, all 13 selected execution jobs and final candidate proof. Actual checkout 2315753c3268872a5bb8bf7245b91794413f50e7, parents [626a03af4a9db064751230a84732755b8afa961e, 364194c01375a0285c809d1b7e5224cf66acd1fd], tree a4044809e1ec71cf3b262047a29b3f1ac9b61793; every selected job log/artifact and immutable API/local Git object match. Retention is empty. Units pass 13544 cases across all 963 independently discovered files; browser passes 8808, layout 1098 and endurance 1. Browser raw diagnostics preserve exactly ten approved fine-pointer nonapplicable keyboard cases, each with actual passing coarse/mixed counterparts; no other case/ownership discrepancy. Layout/endurance raw diagnostics pass. Current head-only contract run 38905976088 passes. Prior cancelled draft-push checks belong to superseded run 38905618732, not this confirmation.

Checklist

  • Complete selected current-candidate hosted proof passes with actual head/base/tree evidence.
  • Acceptance behavior implemented; Pi voice proof limit is explicit below.
  • PR and issue use release milestone 0.44.0, assigned and read back.
  • Minor changesets and SDK API report cover the supported additions.
  • Leakage gate passes; authoritative contracts and moved citations updated.

Anything left open

Current-candidate hosted proof remains pending. Pi declares no production voice posture and rejects it before session acquisition; its real worker no-grant/missing-handler requests, voice assembly/gate controls and dispatch-refusal control state that proof limit honestly. Offline requests prove assembly and effective refusal, not first-party provider cache hits, subscription eligibility or savings. No paid provider calls were made.

Ordinary integration recovery

Native grouping #2136 was removed after #2141 reproduced incompatible native CI event/checkout semantics. Dependent PRs remain drafts and will be reconstructed with only their own changes after each actual parent lands. Current ordinary head is 364194c01375a0285c809d1b7e5224cf66acd1fd, incorporating live main 626a03af4a9db064751230a84732755b8afa961e; local preflight passes 864 tests / 5541 assertions. Only the upstream continuity test and process guidance changed; product roster/enforcement sources are unchanged from the preceding implementation.

Prior run 38902174935 passed all 13 execution jobs, including 13543 unit cases across all 963 independently discovered files, 8808 browser cases, 1098 layout cases, captures, native runtime and endurance. Its aggregate correctly rejected the external main advance from 3fc6fea5e22304df2810348074c32b1983fbea46 to 626a03af4a9db064751230a84732755b8afa961e. The original head c40f533e5f2277b961acb1d48b7b3742dd7ac11c, checkout ff8cecd806cf17987c1fea05ce084c9cf8b8fbef, tree 125491a2dc2407dbc042bc36975b94ed1621467c and artifacts retain that historical identity. No stale execution result authorizes merge. Current-candidate confirmation now passes as recorded above; eventual integrated-main verification remains required.

Merge reconciliation

Merged as 8822aedeeac8b824bafe120c20a9b58c4cd1f4e6, an ancestor of fetched main. Actual parent 626a03af4a9db064751230a84732755b8afa961e and tree a4044809e1ec71cf3b262047a29b3f1ac9b61793 exactly match the fully passing candidate. Issue #2048 closed automatically; both release milestones remain 0.44.0. Automatic main-push CI 38909289786 is running on the actual squash; its result is pending and separately monitored. No post-merge branch push will occur.

@schlessera schlessera added this to the 0.44.0 milestone Oct 16, 2026
@schlessera schlessera added type: fix Something is broken and must behave the way it is documented. area: ui-server Hono app factory: turn coordinator, auth, session catalog, routes, cron. area: backends AgentBackend implementations and the seam they share. contract Touches the integration contract: CONTRACT: commit, contract doc updated in the same commit. labels Oct 16, 2026
@schlessera
schlessera marked this pull request as ready for review October 16, 2026 11:16
@schlessera
schlessera marked this pull request as draft October 16, 2026 11:44
@schlessera
schlessera marked this pull request as ready for review October 16, 2026 11:44
@schlessera
schlessera marked this pull request as draft October 16, 2026 11:44
@schlessera
schlessera marked this pull request as ready for review October 16, 2026 11:48
@schlessera

Copy link
Copy Markdown
Owner Author

Historical failing-first and mutation receipts for #2048. These are diagnostic history, not current-head merge proof.

  • Original-tree MCP enumeration fails FULL_ROSTER_voice_request_image_mask (expected true, received false). Actual installed Claude runtime fails RUNTIME_HOOK_REFUSAL_voice_mcp__brain-ui__request_image_mask; missing registration and voice inbox handler execution are observed. Pi's actual worker invokes inboxAdd/resolveAction/completeShare on a no-grant turn before the correction.
  • A real project stdio MCP probe fails BYTE_IDENTICAL_PROVIDER_TOOLS_missing when legacy writer exclusions depend on a temporary applyBrain handler. The trusted session-stable applicationAuthority declaration fixes hosted shadowing while resumed unhosted controls retain all three legacy writers and execute an allowed brain_add call.
  • A partial inbox bridge first fails TYPED_AVAILABLE_HANDLER_partial: missing inboxList discarded an independently available inboxAdd. Individual binding/allow checks restore it. Restored runtime/schema/citation proof: 79 pass / 430 assertions.
  • Required final-fixture mutations: reintroducing voice-only disallowedTools: [Write] fails BYTE_IDENTICAL_PROVIDER_TOOLS_voice; removing the request_image_mask availability refusal fails RUNTIME_HOOK_REFUSAL_voice_mcp__brain-ui__request_image_mask. Both sources restored byte-identically before passing controls.
  • The broad local backend/server run records 3942 pass / 1 obsolete absent-native adapter expectation across 340 files (993.67 seconds). The corrected complete adapter file and actual strict/voice refusal proof pass.
  • First complete hosted confirmation 38892730942, head 04b6d2765cea8c5da0a78d7abbd140bc168530fe, exposes 11 unit failures. Ten are fixture/expectation drift: three lock controls, five contract assertions, one foreground-yield control and one installed 14→22 tool-count assertion. Native approval/lock controls now explicitly declare a governed turn and retain their original oracles.
  • The eleventh is a real regression: Pi autonomous permission checkpoint fails checkpoint before no-grant denial (expected 1, received 0). The unavailable application-route refusal is now interactive-only. All new availability guards were audited for autonomous exclusion. Restored complete real-runtime/contract/lock/yield/installed-surface local proof: 94 pass / 546 assertions; Pi stable-roster runtime/gate and yield proof: 29 pass / 130 assertions. Final current-base preflight passes 862 tests / 5534 assertions; the newly merged inherited-pipe cleanup file passes 13 tests / 89 assertions.
  • Short-lived b5c02d9 confirmation was returned to draft after detecting an external base advance; it is not proof. Final confirmation uses head 227a62efafb8a01610cf2cac39708ea4c97642f8 and base b67b1b84e8ceacf8f0df3aee8f23f8bf32a91703; its current results are recorded separately.

@schlessera
schlessera marked this pull request as draft October 16, 2026 12:14
@schlessera

Copy link
Copy Markdown
Owner Author

Historical green execution receipt; rejected stale candidate, not merge authorization.

Confirmation 38896175604, attempt 1, head 227a62efafb8a01610cf2cac39708ea4c97642f8, base b67b1b84e8ceacf8f0df3aee8f23f8bf32a91703, actual merge checkout 9d16993b6d617dd568639e5bdc16016dd70bc6de, tree a6c9fd11d966244e3bc4d1eb2ffb50f8ada85d97.

All 13 selected execution jobs pass: strict types, packaging, 4 units, 2 browser shards, 2 layout shards, native runtime, capture verification and endurance. Hosted units pass 13,516 cases; all 962 independently discovered files execute exactly once. The 24 live-provider opt-ins remain excluded from keyless proof, and four skipped inverse-capability placeholder cases belong to the vector-present lane rather than a missing sqlite-vec runtime. The actual vector tests pass. All corrected native lock/approval controls and the real Pi autonomous checkpoint control pass.

Browser: 8808 passes, with exactly ten approved conditional fine-pointer keyboard cells. Both raw case diagnostics exit 1 only for those ten cells; each exact file/case identity has passing coarse and mixed counterparts (20 actual positives), with no other ownership/error issue. Matrix/checker source is unchanged from approved #1862. Independent current discovery and installed partition reconcile 297 project/file instances (219/78). Layout: 56 files exactly once, 1098 passes, both raw diagnostics pass. Endurance: one case and raw diagnostic pass. Every execution checkout log, immutable commit evidence and retained artifact identity matches the candidate above. Retention ledger is empty.

The aggregate correctly refuses at 12:14 UTC because external #2062 advanced main to 2e362cc12aa3d2bda38145b6da23d0ac232281b2. That commit changes browser measurement/partition inputs; it has no product-roster or authority source changes. Old execution evidence remains attributed to the old candidate. It will not be relabeled as proof of the next combined tree, and the validator determines fresh execution/retention eligibility.

@schlessera
schlessera marked this pull request as draft October 16, 2026 13:08
@schlessera

Copy link
Copy Markdown
Owner Author

Historical passing execution, rejected stale candidate: run 38902174935, attempt 1, head c40f533e5f2277b961acb1d48b7b3742dd7ac11c, base 3fc6fea5e22304df2810348074c32b1983fbea46, actual checkout ff8cecd806cf17987c1fea05ce084c9cf8b8fbef, tree 125491a2dc2407dbc042bc36975b94ed1621467c.

All 13 execution jobs passed. Units: 13543 passes across all 963 independently discovered files exactly once (partitions 231/243/243/246); 24 paid live-provider opt-ins and four inverse-capability placeholders retain their intended exclusions. Pi's actual autonomous permission checkpoint passes. Browser: 8808 passes; ten exact approved fine-pointer keyboard nonapplicable cases each have passing coarse/mixed counterparts, 20 actual positive controls. Raw case diagnostics retain their exit 1 for those ten cells only; ownership reconciles. Matrix/case/checker sources are unchanged from approved #1862. Layout: 56 files exactly once, 1098 passes (450/648 under the current cost partition), both raw diagnostics pass. Endurance's sole case and raw diagnostic pass. Captures, strict verification, packaging and native runtime pass. The runtime's deliberately retained index-namespace negative case is independently verified as expected; all four healthy cells and cleanup qualify.

Every selected job's actual checkout log and all artifacts match the identity above, independently reconciled with immutable GitHub commit evidence and the fetched local Git object. No retained domain was substituted. Aggregate job 116987587971 correctly rejects the changed live base at 13:07:24 UTC after external #2132 advanced main to 626a03af4a9db064751230a84732755b8afa961e. That change touches only a native continuity test and process guidance. Product roster/enforcement sources are unchanged; the current conservative domain validator nevertheless requires fresh proof. These receipts remain historical, not authorization to merge a different combined candidate.

@schlessera
schlessera marked this pull request as ready for review October 16, 2026 13:09
@schlessera

Copy link
Copy Markdown
Owner Author

Current exact candidate is fully passing: confirmation 38905724827, attempt 1, head 364194c01375a0285c809d1b7e5224cf66acd1fd, live base 626a03af4a9db064751230a84732755b8afa961e, actual checkout 2315753c3268872a5bb8bf7245b91794413f50e7, tree a4044809e1ec71cf3b262047a29b3f1ac9b61793. All 15 jobs pass: metadata, 13 selected execution jobs and aggregate 116999582583. The aggregate records this exact ready-for-review candidate and validates freshness, selections and outcomes. No retained proof is substituted.

All selected checkout logs, artifacts, immutable GitHub commit evidence and the fetched local object reconcile. Units: 13544 passes across all 963 discovered files (231/243/243/246); the explicit isolated external-speech child re-executes its own fixture by design and does not duplicate partition assignment. Twenty-four paid provider opt-ins and four inverse-capability placeholders retain their intended exclusions. The actual Pi autonomous permission checkpoint passes. Browser: 8808 passes and exactly the ten approved fine-pointer keyboard nonapplicable cases, with 20 actual passing coarse/mixed counterparts and unchanged approved case/matrix/checker sources. Raw diagnostics preserve exit 1 only for those ten cases; ownership reconciles. Layout: 1098 passes across all 56 files, both raw diagnostics pass. Endurance: its case and raw diagnostic pass. Native runtime verifies all four healthy cells, the intentional retained-index negative case and owned cleanup. Captures, strict verification and packaging pass. Current head-only contract run 38905976088 passes separately.

PR/issue milestone 0.44.0 is verified; no review finding is outstanding. Earlier cancelled draft-push checks belong to superseded run 38905618732. Earlier stale candidates retain their original identities and are not reused as current proof. Final matching-head merge and integrated-main reconciliation follow separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backends AgentBackend implementations and the seam they share. area: ui-server Hono app factory: turn coordinator, auth, session catalog, routes, cron. contract Touches the integration contract: CONTRACT: commit, contract doc updated in the same commit. type: fix Something is broken and must behave the way it is documented.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

backends: the tool list changes with posture and sandbox profile, so a posture switch mid-session misses the whole prompt cache

1 participant