Subagent-public floor: the no-entitlement spawn+dispatch fixture + entitlement-freedom guards (#826) - #827
Subagent-public floor: the no-entitlement spawn+dispatch fixture + entitlement-freedom guards (#826)#827aarontrowbridge wants to merge 2 commits into
Conversation
…patch fixture + entitlement-freedom guards (#826)
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Foreign-red record for the merge decision: the first |
|
Green update (supersedes the foreign-red record above): main absorbed the owner's fix (#830 → #831, merged) for the H4 teardown race; this branch was updated onto it and all 9 checks are now green, including |
Implements #826.
Acceptance criteria
amicissimo/premium codes), theamicode_sessiontool registers and a spawn executes end-to-end (double/mock client, honest counts + metadata stamps) — PASS with zero entitlement presenceWhat landed
One focused fixture file,
packages/extension/test/session_public_floor.test.ts(14 tests), three layers:entitlements.toml(codes = [], present file, zero codes) resolved through the realreadLocalEntitlementspath; the plugin twin registersamicode_sessionunconditionally; a spawn executes end-to-end through the mock engine (double pattern fromsession_spawn_double_create.test.ts, extended to record bodies): honest counts (one create + one prompt per child; fan-outcount=3→ exactly three, titled(i/3)), honest{spawned_by, spawned_depth}stamps (child-of-child chains to depth 2; the soft cap refuses at depth 2 withoutforce, zero creates), fork-mode stamps viasession.update, and the CORE twin (the one implementation both transports project) spawns identically.stageModCardsstages the implementer worker card complete (byte-identical base,overlay_id: null, emptymerged_fields, zero rejections — composingmode_cards_staging.test.ts's base-alone test, which pins the all-cards half; this pins the dispatch half through the real fixture-dir resolution), and a spawned child is cast through it: the create/promptAsync bodies carryagent: "implementer"against the staged base card.["entitlement", "premium", "amicissimo"], non-emptiness asserted so the lens can't go vacuous) over the spawn policy (session_spawn.ts, whole file) and each transport'samicode_sessionsection (extracted as the window betweenamicode_report_fallback:andamicode_veloce:so a conditional wrapper around the registration lands in the lens). Verified to fire: a temporary// entitlementmutation insession_spawn.tsgoes RED with "ADR-0004 decision 1 (amicode#826): the subagent surface is pre-pay product, never premium — …an entitlement read on the spawn/dispatch path violates the boundary ruling" (mutation reverted; no production file changed).No production code touched — the fixture pins the audit, it does not change behavior.
The audit record (ADR-0004 decision 1)
What was audited — the full staging path of the subagent surface: tool registration (
opencode-plugin/amicode_tools.tsAmicodeTools— theamicode_sessionkey registers unconditionally, ~line 1869, no entitlement gate anywhere on the registration), the spawn policy (opencode-plugin/session_spawn.ts— pure, no imports, no entitlement coupling), the card staging split (src/mode_cards.tsstageModCards— base cards ALWAYS stage complete; overlays resolve ONLY with theamicissimopremium entitlement, which is the correct split and is pinned, not changed), and theissimoentitlement surface (src/amicode_service/solver_mode.tsapplyEntitlementForMode— grants/revokes the HP solver tier, gates solving not subagents; out of scope by design).What was found clean — everything. The audit's central finding held under fixture construction: zero entitlement residue on the spawn/dispatch path. The plugin registers the tool with no entitlement consult; the spawn policy's caps (count 4, soft depth 2, model precedence) are pure policy; base worker cards stage complete with no entitlement; the MCP-floor refusal (spawn refuses on non-opencode harnesses) is harness coupling, not entitlement gating — already honest, out of scope. No behavioral change was needed or made.
What the fixture pins — the public floor end-to-end: registration + spawn + stamps + caps under zero entitlement; dispatch through a staged worker base card under zero entitlement (even with a premium overlay source sitting present and unreached); and the source-level tripwires so a future entitlement read hung on the spawn/dispatch path goes RED naming the ruling. Sources that are SUPPOSED to read entitlements (
mode_cards.ts's overlay gate,solver_mode.ts's HP tier) are deliberately outside the guard — the ruling splits subagents from those.Lineage — ADR-0004 (amicissimo, decision 1 — the subagent surface is pre-pay product, never premium); #641 (the
amicode_sessiontool's landing + lineage); #761 (the card staging + its base-alone test, composed here); the blocklist/proprietary-strings floor tests (the grep discipline reused);session_spawn.test.ts/session_spawn_double_create.test.ts(the policy suite + double patterns reused). Campaign slice 2 per the fleet-amicissimo-forksplit work order.Verification
pnpm --filter amicode typecheck— cleanenv -u OPENCODE_DB pnpm --filter amicode test— 148 files passed (1 skipped), 2303 passed / 40 skipped / 0 failed