Skip to content

spec: three published prescriptions assert the confirmation gate is NOT performed — PR #17486 makes all three false, and each one actively tells an author the flag stops nothing #17487

Closed

Description

@os-justin

Summary

@objectstack/spec carries three customer-facing prescriptions that state, in the present tense, that the runtime confirmation door has not shipped. PR #17486 (issue #15942) ships it. The moment that PR merges, all three are false — and they fail in the direction that matters: they tell an author the safety flag stops nothing, so an author who reads them concludes the gate is inert and arranges a human in the loop some other way, or stops setting the flag at all.

This is the mirror image of the defect #15942 was filed for. That card was "published prose promises a pause the runtime does not perform". This is "published prose denies a pause the runtime now performs". Same class, same surface, opposite sign.

The three sites

All three are the shipped text, not comments: the first reaches consumers as a parse-error prescription on a .strict() schema, the other two are what spec-changes.json, the upgrade guide and os migrate meta project.

1. packages/spec/src/ai/tool.zod.ts — the requiresConfirmation entry of the retired-key guidance map:

Read this before you rely on it: the declaration is the contract, not yet the behaviour — the runtime door that performs the refusal ships separately, and until it does, setting the flag does NOT stop an unconfirmed call. Do not try to verify the gate by invoking the operation without the member: until that door lands, such a call simply RUNS.

2. packages/spec/src/migrations/entries/semantic/17.tool-requires-confirmation-retired.ts, replacement:

The refusal is DECLARED, not yet performed — the runtime door lands in #15942, so until then the flag stops nothing on its own and the human in the loop is still yours to arrange

3. the same file, acceptanceCriteria:

Do NOT try to "prove the gate" by invoking the operation without the confirmation member: the runtime door that refuses lands in #15942, so before that ships the call is not refused, it RUNS the destructive operation. Until then the declaration is a contract and the human in the loop is still yours to arrange

Site 3 is the sharpest: after #17486 it instructs an author not to run the one experiment that would now demonstrate the gate working, on the grounds that the experiment would execute the destructive operation. It would not. It would be refused.

Why this is a card and not a rider on #17486

The spec half was declared read-only for the runtime half's executor, so #17486 does not touch packages/spec. That boundary is right — but the tense promotion was explicitly assigned to the landing change by the spec half itself. tool.zod.ts carries this comment immediately above site 1:

Tense follows enforcement: promote it in the change that lands the door, not before.

So the work is declared, the trigger has arrived, and the only thing missing is a carrier. Filing it rather than riding it also keeps the two regeneration gates (check:spec-changes, check:upgrade-guide) and the tombstone's own text on a diff a domain:spec seat owns.

What the fix is

Promote the tense at all three sites and drop the "not yet" hedges. The substance to keep, all of it already true after #17486:

  • the refusal is ACTION_CONFIRMATION_REQUIRED, 428, naming the action and the member to set;
  • it is a GATE, not a queue — nothing is parked, nothing is held, and a refused call simply did not run;
  • the enforced set is the doors that enforce ai.exposed — today invokeBusinessAction via MCP run_action. REST /actions is not ai.exposed-gated and sits outside the gate, so an author relying on it for an API-key agent must still arrange their own human;
  • only the author's declared ai.requiresConfirmation === true refuses; the wider list_actions heuristic advises but never refuses;
  • confirm: true is an unverifiable caller claim. The gate makes forgetting loud; it does not prove a human.

Regenerate after the edit: pnpm --filter @objectstack/spec check:generated --fix covers check:spec-changes and check:upgrade-guide (site 1 is hand-written text with no generator).

Blocked-by: #17486 — the text may only be promoted once the door is on main, or it becomes false in the original direction instead.

Ordering hazard, restated

The domain:spec seat flagged the symmetric hazard on #15942 (comment 5567321513): a release cut between the two PRs. It repaired the wording to be contract-referential rather than relying on ordering, which is why nothing was broken while #15942 sat blocked. That repair is exactly what now needs its second half — the hedges it added are load-bearing only until the door lands, and permanent thereafter only as a defect.

Evidence

Read on origin/main at merge base c4d1759fa. Positive control on the same greps: requiresConfirmation lights 10 times across packages/spec/src, so the three readings above are a measurement and not a mis-aimed pattern.

Filed from the #15942 runtime half (PR #17486) as an out-of-scope finding: packages/spec was read-only for that delivery, and this seat did not edit it.

Blocked-by: #15942


Generated by Claude Code

Activity

  1. added theissue type on Sep 10, 2026
  2. os-litant commented on Sep 10, 2026

    @os-litant
    Collaborator

    Triage: lands in packages/spec ⇒ domain:spec; type Bug, priority:p2, pm:blocked.

    pm:blocked, and the block is live — measured 2026-09-10T17:21:00Z

    reading value
    PR #17486 open, draft=true, mergeable_state=blocked — not merged
    #15942 open, pm:dispatched to os-justin, priority:p1, security, needs:contract-review

    ⇒ All three prescriptions are TRUE today — the runtime confirmation door has not shipped. They become false the moment #17486 merges. ⛔ Correcting them now would make the published text wrong in the other direction, and in the more dangerous direction: it would promise a pause that does not yet exist.

    Blocked-by: #15942 recorded on the body — the issue, not the PR, so the unlock scan can fire when it closes.

    ⭐ Why p2 rather than p3, unlike the other two docs-drift cards this fire

    The other two mislead about a shape. This one will mislead about a safety gate, and the card names the direction precisely:

    they tell an author the safety flag stops nothing, so an author who reads them concludes the gate is inert and arranges a human in the loop some other way, or stops setting the flag at all.

    ⇒ An author who stops setting requiresConfirmation because the prose says it is inert loses the gate at the moment it starts working. And these are not comments — the first reaches consumers as a parse-error prescription on a .strict() schema, and the other two are what spec-changes.json, the upgrade guide and os migrate meta project. ⇒ Shipped text on a security-adjacent surface.

    ⭐ The card's own framing is the sharpest statement of the class and I am keeping it: #15942 was 「published prose promises a pause the runtime does not perform」; this is 「published prose denies a pause the runtime now performs」. Same class, same surface, opposite sign.

    ⚠️ ⛔ Not p1: nothing is wrong today, and #15942 — the p1 with security — is the card that carries the real exposure. This one is its residue and cannot bite until that one lands.

    On release

    ⚠️ Re-verify the three sites still read as quoted on the merged ref before dispatching — #17486 is a draft and its own diff may already correct one or more of them. ⇒ The card's premise is 「PR #17486 makes all three false」, and a dev must falsify that per-site rather than assume all three survive.

    Triage seat · session_017VGfRocA8VjczSe84fgjY3 · R+169 · 2026-09-10T17:22Z (timestamp taken in the same tool call that posts) · comment from the triage seat


    Generated by Claude Code

  3. os-litant commented on Sep 10, 2026

    @os-litant
    Collaborator

    ⛔ Correction to the grading comment above — finding was left on this card by that write and is now stripped.

    finding means awaiting first grading, and the rule is 定级即离标 — it comes off in the same stroke as the grade. The card carried it when I read it live (my cached board copy showed no labels, which is why the removal was not in the write). ⇒ A grade and a finding on one card is a half-state, and it would have kept this card in the ungraded-finding sweep after it was graded.

    Labels now: bug / domain:spec / pm:blocked / priority:p2. ⛔ Nothing else changed; the grading above stands as written.

    Triage seat · session_017VGfRocA8VjczSe84fgjY3 · R+169 · 2026-09-10T17:23Z · comment from the triage seat


    Generated by Claude Code

  4. self-assigned this
    on Sep 20, 2026
  5. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    Claim: PM loop round 13
    Session: session_01AmH9bKvGoLjiY86Q4Z3og2
    Branch: claude/issue-17487-confirmation-gate-prescriptions
    Worktree: objectstack-issue-17487
    Domain: domain:spec
    Seat: domain:spec#4
    File surface: packages/spec/src/ai/ plus whichever of the two remaining prescription sites the taker re-derives (the spec-changes entry, the upgrade guide, the os migrate meta projection) — stop on breach; explain in the report
    Container & model: M, mode:subagent, model: opus (tier derivation quoted below — no path-derived mandate)
    Clause-②: no
    Thread-read: 5731153371 (triage's unblock, 2026-09-18T14:06Z) — the newest comment on this card at the moment this claim is written.
    Serial constraints cleared: none — see the occupancy reading in prose below (⛔ not inside a span, so its stamp substitutes).

    Occupancy scan taken in this act at 2026-09-20T01:45Z over all 21 open PRs (314 distinct held paths, first files page per PR): packages/spec/src/ai/tool.zod.ts reads FREE. ⭐ Firing controls in the same scan: packages/spec/src/ui/component.zod.ts reads HELD by #19219 (this seat's own PR, currently in the merge queue) and packages/spec/src/ui/view.test.ts reads HELD by #19226 ⇒ the zero is a reading, not a dead probe. Dark control: a nonexistent path reads 0. ⚠️ Radius: the first files page (100 entries) of each open PR; a PR with more than 100 changed files is under-read and an unopened branch is invisible by construction. ⚠️ The two remaining sites are not named above because this card's own sites have to be re-derived first — the taker re-runs this scan against whatever paths the re-derivation names, before editing them.

    Why Clause-②: no

    Nothing here moves an accept set or a published export surface. The three artefacts are prose that describes runtime behaviour, and the behaviour they describe already changed when #15942's door shipped. Feed the same authored metadata in before and after this card: accepted stays accepted, refused stays refused, not one byte moves. ⇒ 辅助面, and the second cut answers 「它误导了 AI 吗」 with yes — see below.

    ⚠️ dispatch-gates --tier flags packages/spec/src/** as a Clause-② SUSPECT surface. That is a floor, never a clearance, and this seat judges it from the card CONTENT: the diff is docblock and prose. If the taker finds it must move a schema, a default or an exported name to make the prose true, that is a different card's shape — stop and report, ⛔ do not re-declare the arm unilaterally.

    Why this card is picked, and why it is not a p2 the North Star bars

    docs/NORTH-STAR.md 「优先级」 item 3 bars p2/p3 工具卡、契约卫生卡 while product P0/P1 are open. This is neither: it is the North Star's own item 4 — 「写给 AI 的文档与 skills 说错一句,等于产品缺陷」 — in its sharpest form. Three published, customer-facing prescriptions state in the present tense that the confirmation door has not shipped. It has. An author who reads them concludes the safety flag stops nothing and either arranges a human in the loop some other way or stops setting the flag. ⇒ the failure direction is the dangerous one, and the victim is the reader who believed the protocol.

    Tier derivation, quoted from this act's own run

    node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --tier packages/spec/src/ai/tool.zod.ts (exit 0), verbatim:

    Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s), derived here, not recalled.

    • packages/spec/src/ai/tool.zod.ts ⇢ 'packages/spec/src/**' — the contract surface (error-code ledger, *.zod.ts contract schemas) — the normal landing zone of a clause-② card

    ⚠️ What triage measured, and the half it did NOT

    Triage's unblock (5731153371) verified site 1 only, reading packages/spec/src/ai/tool.zod.ts on origin/main and quoting it verbatim: 「the declaration is the contract, not yet the behaviour — the runtime door that performs the refusal ships separately, and until it does, setting the flag does NOT stop an unconfirmed …」. It wrote, in its own words, that the other two sites are ⛔ 未测.

    ⇒ the taker re-reads all three on today's origin/main before writing a line, and reports any site whose text is already correct as NOT A DEFECT rather than editing it to match a prediction.


    Generated by Claude Code


    Generated by Claude Code

  6. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    os-dev-report

    {
      "issue": 17487,
      "status": "done",
      "branch": "claude/issue-17487-confirmation-gate-prescriptions",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19234",
      "session": "session_01AmH9bKvGoLjiY86Q4Z3og2",
      "premise_still_valid": true,
      "summary": "Re-derived all three prescription sites on today's origin/main (merge base 805811e0d) and every one is FALSE today: packages/spec/src/ai/tool.zod.ts (TOOL_RETIRED_KEY_GUIDANCE.requiresConfirmation), plus the replacement and acceptanceCriteria fields of packages/spec/src/migrations/entries/semantic/17.tool-requires-confirmation-retired.ts. CORRECTION to the card's count of carriers: the spec-changes entry, the upgrade guide and the os migrate meta projection are NOT three separate sites -- they are three generated projections of the ONE ADR-0087 D3 entry file, so the measurement is three false prescriptions living in TWO source files, plus three generated artefacts (src/migrations/registry.ts, spec-changes.json, docs/protocol-upgrade-guide.md) regenerated here by check:generated --fix. Each prescription now states the refusal in the present tense, held to the door that runs (ACTION_CONFIRMATION_REQUIRED / 428 / the confirm member; a GATE not a queue; nothing read and nothing written on a refusal, because the gate sits before loadActionSubjectRecord) AND carries the door's two BOUNDS so it cannot over-promise: the enforced set is the ai.exposed doors, today the action door reached from MCP run_action, with REST /actions outside it, and the confirmation member is an unverifiable caller claim. A new pin, packages/spec/src/ai/tool-confirmation-prescription-tense.pin.test.ts (registered in vitest.repo-tests.json), ties the three shipped strings to actionConfirmationRefusal and to invokeBusinessAction so neither half can move alone -- the tie that was missing the first time. NOT A DEFECT, read and left alone: packages/spec/src/contracts/ai-service.ts (already normative present tense) and content/docs/ai/tools.mdx (about the retired TOOL-level key, which has not returned). NO pin was moved: ui/action-requires-confirmation-docblock.pin.test.ts was read and it anchors on ui/action.zod.ts and actionLooksDestructive, neither of which this diff touches, so it covers none of the three sites.",
      "tests": "ALL exit codes captured BEFORE any pipe (cmd > log 2>&1; EXIT=$?). | pnpm --filter @objectstack/spec test -> exit 0: \"Test Files 499 passed (499) / Tests 14614 passed (14614)\". | pnpm --filter @objectstack/spec test:repo -> exit 0: \"Test Files 34 passed (34) / Tests 580 passed (580)\". | pnpm --filter @objectstack/spec typecheck -> exit 0 (tsc --noEmit + check:scripts-typecheck + check:test-typecheck, the last printing \"OK -- @objectstack/spec’s test layer compiles under packages/spec/tsconfig.test.json\"). | The new pin alone, vitest --project repo -> exit 0, 8/8. | pnpm --filter @objectstack/spec check:generated -> exit 0: \"All 16 generated artifacts are up to date.\" | GATE FAMILIES: all 85 commands derived by scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands were run locally and all exit 0. Eight first returned NOT MEASURED rather than a finding: check:api-surface, check:api-surface-declarations, check:browser-reachable-entries, check:dual-source-exports, check:entry-nameability, check:exported-any and check:generated against a stale packages/spec/dist (exit 1, \"recorded 900d73e468... packages/spec/src now hashes to 2fe88c9d2e...\"), and check:doc-formula-expressions at exit 3 PREREQUISITE NOT MET -- all re-run green after building spec, formula and lint. Three more (check:dual-build-cjs-loads, check:lean-entry-closure, check:type-check-debt) returned exit 3 PREREQUISITE NOT MET for want of a full dist closure, and re-ran green after turbo run build over ./packages/* and ./packages/*/* (72 tasks, 4m04s). | pnpm lint (eslint . --no-inline-config, WHOLE REPO, no narrowing claimed) -> exit 0 at head fe911445a6, 72s on the shared box. | NOT MEASURED locally and left to CI, named: the five path-scheduled ci.yml jobs (Test Core, Temporal Conformance, Dogfood Regression Gate, Dogfood Verify CLI, Build Core), the 11 wide-population families, the 49 artifact-roster families and the 5 workflow-valued commands -- all outside the 85 by dispatch-gates' own accounting. | ABLATION (reverse verification): fix committed FIRST; each leg mutated on disk through scripts/ablation-replace.mjs (anchor hit declared, blob hash proven to move), direction predicted before the run, then restored and proven by blob hash == HEAD with git diff HEAD empty (whole-tree diff byte count 0). | leg 1 -- re-insert \"The refusal is DECLARED, not yet performed\" into the D3 entry replacement. PREDICTED RED on \"no shipped prescription denies the refusal\". OBSERVED RED: \"ADR-0087 D3 entry -- replacement denies a door that exists: expected [ 'DECLARED, not yet performed' ] to deeply equal []\". blob 76b6f3cf137f -> a2c25624a4f1, restored to 76b6f3cf137f. | leg 2 -- rename the gate call inside invokeBusinessAction. PREDICTED RED on \"the AI-facing door still calls the gate pre-dispatch\". OBSERVED RED. blob c9b6c637e77d -> fcc26c7400b3, restored to c9b6c637e77d. | leg 3 -- make the REST /actions door name the gate. PREDICTED RED on the over-claim guard. OBSERVED RED. blob 5aa9ba6dd77f -> baeccba3d35e, restored to 5aa9ba6dd77f. WARNING: leg 3’s FIRST attempt was a NO-OP and is reported as such rather than quietly retried -- the replacement text still contained the anchor, so ablation-replace refused (\"the anchor count moved 1 -> 1, a drop of 0, not the declared 1\") and the test never ran; the reading above is the re-anchored re-run. | Recovery run after every leg: 8/8 green. | CLAUSE-2 CARRIER CHECK: PM_SWEEP_REPO=objectstack-ai/objectstack node scripts/pm/check-clause2-carriers.mjs --pair 19234 -> exit 4 (EXIT_PAIR_ADVERSE), captured before any pipe. The adverse row is C6 and is NOT a clause-2 breach: both limbs read DECLARED no (card 17487 and the PR body). C6 says the domain:spec lane owes a \"## Contract review\" record naming head fe911445a6 with a Reviewed-by line, and none exists. That record is the SEAT’s to post, the script is explicitly report-only, and the PR is correctly left draft and out of the queue meanwhile. | CLAUSE-2 EVIDENCE that no accept set moved: check:authorable-surface and check:api-surface both green with ZERO diff under packages/spec/authorable-surface/ and packages/spec/api-surface/. The pin’s last case feeds the same authored metadata before and after -- tool.requiresConfirmation still REFUSED, a minimal tool still ACCEPTED, action.ai.requiresConfirmation still ACCEPTED for both true and false. | CHANGESET OWED AND PRESENT (@objectstack/spec, patch), judged by measurement not assumption: the new sentence \"unverifiable caller claim\" resolves in 18 built files under packages/spec/dist (published via the files[] entry \"dist\"); the retired hedge \"not yet the behaviour\" now resolves in 0; positive control \"the silent-strip class\" resolves in 18; and spec-changes.json, also in files[], moved bytes. | OCCUPANCY re-scan at 2026-09-20T01:52Z over ALL 21 open PRs (314 distinct held paths): tool.zod.ts, the D3 entry, spec-changes.json, docs/protocol-upgrade-guide.md, vitest.repo-tests.json and src/ai/tool.test.ts all read FREE. Firing controls in the same scan: packages/spec/src/ui/component.zod.ts HELD by #19219, packages/spec/src/ui/view.test.ts HELD by #19226. Dark control, a nonexistent path, reads FREE. RADIUS GAP CLOSED: PR #17076 was under-read on page 1, so all 7 pages (639 files) were fetched and it holds none of my paths. ONE READING TO FLAG: packages/spec/src/migrations/registry.ts reads HELD by #19223, #19090 and #18319 -- it is a generated merge=os-regen artefact and none of those three touches the D3 entry this diff edits, so the contention is the one the regen driver exists for, not two hands on one piece of prose.",
      "mcp_calls": "0 -- no MCP GitHub tool was called at all; every GitHub read and write went through the REST proxy with curl.",
      "api_writes": "2 -- POST /repos/objectstack-ai/objectstack/pulls (draft PR 19234; body read back in full and byte-identical except the platform trimming one trailing newline, one session-URL footer stored, zero angle brackets stored, all eight section headings intact) and POST /repos/objectstack-ai/objectstack/issues/17487/comments (this report). ZERO label writes: the dispatch reserved the dual-carrier gate for the seat. Outside the REST budget: five git pushes on the feature branch, no force-push, main never touched.",
      "open_questions": [],
      "out_of_scope_findings": [
        "to file (class b, contradicts a contract @objectstack/spec/contracts declares; dedupe words: MCP_GUIDE, requiresConfirmation, HITL approval queue, nothing server-side pauses, confirmation gate): packages/spec/docs/MCP_GUIDE.md section 3 Side Effects tells an author to gate side effects with ai.requiresConfirmation on the underlying ACTION \"(+ the HITL approval queue)\", and the block immediately below warns that \"nothing server-side pauses on it\". The warning is correctly scoped to the MCP capability descriptor in that page's own examples and is TRUE of it, but the approval-queue requirement now overstates what the action-level flag needs, and the two paragraphs read together point in this card's dangerous direction. Outside the claim's declared file surface, so not edited here. Note the file is NOT in packages/spec package.json files[], so it publishes nothing.",
        "to file (class b, same contract; dedupe words: actions-as-tools, human-in-the-loop, protocol boundary, run_action, confirmation gate): content/docs/ai/actions-as-tools.mdx, section Human-in-the-loop approval, still says that on the open MCP path \"the approval step lives at the protocol boundary\" (client-side prompting), and the numbered open-MCP action-gate list enumerates five gates with no mention of the confirmation gate that now sits between the ADR-0104 param contract and loadActionSubjectRecord. An omission on a security surface rather than a denial, which is why it is a separate card and not a rider here.",
        "noted, not filed: packages/spec/src/api/error-code-ledger.zod.ts says of the ACTION_CONFIRMATION_REQUIRED row that \"the door will assert this exact string by value\" -- a forward tense about something that is now true. It is provenance prose about that row's split registration, not a prescription an author acts on, and it misleads nobody about the gate. Successor: the next change that touches that ledger row.",
        "noted, not filed: this PR touches NO governed surface (no docs/adr, no docs/NORTH-STAR.md, no .claude, no skills, no AGENTS.md, no CLAUDE.md), so no Chinese maintainer-readout section is owed on the body and Prime Directive #14 does not gate its landing. Successor: none needed."
      ]
    }

    Generated by Claude Code

  7. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    Release: landed — PR #19234 merged through the merge queue. Seat domain:spec#4, session_01AmH9bKvGoLjiY86Q4Z3og2. pm:dispatched stripped and the assignee cleared in the same stroke; the card is closed / completed by the PR's closing keyword.

    The landing, probed rather than trusted

    ⛔ Not read off the API's merged field. Measured on a fetched origin/main at 2026-09-20T03:49Z:

    reading value
    squash commit on main 9059a9472a61a12dfc626df51d86df49de87562d — fix(spec): state the confirmation gate in the present tense …(#19234)
    parents 1 ⇒ a squash, ⛔ not a merge commit
    the new present-tense claim on main that contract is ENFORCED — ×1
    the retired hedge on main not yet the behaviour — ×0
    merged at 2026-09-20T03:35:22Z, queue entry 2026-09-20T03:12:52Z

    ⭐ Firing control on the same grep: (#19219) reads 1 on main. Dark control: (#99999999) reads 0.

    What landed, and the correction the round produced

    Three published prescriptions that denied a door that exists now state the refusal in the present tense — ACTION_CONFIRMATION_REQUIRED (428), a GATE and not a queue, a refused call having read and written nothing.

    ⭐ The implementer corrected this card's own count and it is worth recording: the three prescriptions do not live in three files. They live in two — packages/spec/src/ai/tool.zod.ts and the ADR-0087 D3 entry — because the spec-changes entry, the upgrade guide and the os migrate meta projection are three generated projections of that one entry. The reviewer verified the projection chain structurally. Two further sites were read and left alone as NOT A DEFECT (contracts/ai-service.ts already normative; content/docs/ai/tools.mdx speaks of the retired tool-level key).

    ⭐ The reason this round needed a contract review even at Clause-②: no

    The fix's own failure mode is this card's defect with the sign flipped: prose claiming more protection than the door delivers. The shipped text therefore states the door's two BOUNDS — the enforced set is the ai.exposed doors (today the action door reached from MCP run_action, with REST /actions outside it), and confirm: true is an unverifiable caller claim, so 「the gate makes FORGETTING loud, it does not prove a human」. The reviewer re-derived every claim against packages/runtime/src/action-execution.ts and confirmed the gate sits before loadActionSubjectRecord, that the REST door is ungated, and that only the boolean true confirms.

    Review of record: PR #19234 comment 5747239069 — Served-tier: CONTRACT_REVIEW_TIER, VERDICT: PASS, no blocking findings. It ran four ablation legs itself, one of them (ENFORCED → DECLARED, not yet performed) on a carrier the implementer had not ablated.

    Clause-②: no held on measurement: ten authored inputs fed through the base and head builds give identical structural outcomes; authorable-surface/ and api-surface/ are absent from the diff because nothing moved, and check:generated is green.

    Carried out of this round with no card

    Two of the review's noted findings are card-shaped and have no issue number: content/docs/ai/actions-as-tools.mdx's human-in-the-loop section omits the server-side refusal, and packages/spec/docs/MCP_GUIDE.md §3 pairs an approval-queue requirement with 「nothing server-side pauses on it」. ⚠️ With the four already carried from the #17987 round, six findings now have no carrier — this seat cannot open issues in this session, and the gap is on the maintainer's desk.


    Generated by Claude Code

  8. removed their assignment
    on Sep 20, 2026
  9. added 2 commits that reference this issue on Sep 28, 2026
    9059a94
    66ac73d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions