…9 refusal-sentence row
The pending `.changeset/22719-rest-write-hook-refusal-sentence.md` listed
`POST /security/permission-sets/:id/discard-overlay` among the routes that now
answer a sandboxed hook's refusal with `400 VALIDATION_ERROR`. That route was
retired by the ADR-0131 cutover (stage 7-pre) after the changeset was written,
and no route on main serves it (`packages/rest/src/rest-route-ledger.ts`
RETIRED note), so the sentence would publish a false claim. One table cell is
corrected; the rest of the row and the file are byte-identical.
Claude-Session: https://claude.ai/code/session_01Rerax7QTjKMPCUZxQUtPFR
Co-authored-by: Claude <noreply@anthropic.com>
Part of #15204
Clause-②: no
This PR corrects one cell in a pending release note. The maintainer authorized the edit, and the PR changes no shipped code. It edits the first cell of line 16 in
.changeset/22719-rest-write-hook-refusal-sentence.md. The maintainer authorized exactly this edit, and the seat recorded the ruling and the claim amendment in comment 6117174845 on #15204 (item (e), point 2).The note, and what changed under it
.changeset/22719-rest-write-hook-refusal-sentence.mdis still pending..changeset/pre.jsonispre/nextand lists no consumed changeset, andpackages/rest/CHANGELOG.mdhas no entry for it. Line 16 listsPOST /security/permission-sets/:id/discard-overlayamong the routes that now answer a sandboxed hook's refusal with400 VALIDATION_ERRORand the hook's own sentence.9859e4ec, 2026-10-11T04:22Z), while that route was still live. Then feat(plugin-security,rest,spec)!: retire the permission-set overlay discard (ADR-0131 cutover stage 7-pre) #22776 (60bcfe72, 2026-10-11T09:03Z, ADR-0131 cutover stage 7-pre) retired the route. Its own pending changeset,.changeset/15204-s7pre-overlay-discard-retired.md, lists the route as removed. If both notes publish unchanged, they contradict each other: one says the route now answers400, and the other says the route is gone.main(85b4ac63):packages/rest/src/rest-route-ledger.ts:421-425reads: "RETIRED (ADR-0131 cutover):POST /api/v1/security/permission-sets/:id/discard-overlayleft with the "Discard Overlay" Setup action. [...] no row, no route."rest-route-ledger.conformance.test.tsbootsRestServerthe way production does (registerRoutes()plusmountAndRecordDirectRoutes). It fails on any mounted route that has no ledger row, and the ledger has no row for this route. Run on this branch:Test Files 2 passed (2),Tests 584 passed (584), together withrest-write-route-hook-refusal-sentence.ledger.test.ts. That second test pins "names exactly the nineteen repaired rows" and carries the comment "the overlay-discard row retired with its route".git grep -i discard-overlayfinds only two places: that ledger comment and the migration entrypackages/spec/src/migrations/entries/semantic/18.security-permission-set-overlay-discard-retired.ts. The dispatcher's/securitydomain (packages/runtime/src/domains/security.ts) serves one route underpermission-sets, which isPOST /security/permission-sets/:name/clone, andpackages/runtime/src/route-ledger.tshas no discard-overlay row.The edit
Line 16, first cell only:
POST /security/suggested-bindings/:id/confirmand/dismiss,POST /security/permission-sets/:id/discard-overlayPOST /security/suggested-bindings/:id/confirmand/dismissThe frontmatter, the rest of the row and every other line of the file are unchanged byte for byte. A line-by-line comparison against the base finds line 16 as the only difference, and the old row with the new cell swapped in equals the new row. This PR adds no changeset and changes no other one. It does not touch
CHANGELOG.mdorcontent/docs/releases/.Check Changesetstays red, by designThis PR changes a changeset it did not add. That puts it in the DELIBERATE CORRECTION class of the foreign changeset rule (rule 2 of
scripts/check-empty-changeset.mjs, #17712). The PR also adds no changeset of its own, soRequire a changeset(route 0) goes red first.skip-changesetis deliberately not applied: that label would declare that this PR releases nothing, but the note it corrects is still a pending release.Check Changesetis not a required context.This section is the written confirmation that route 0 asks for. It names the note and what changed under it (above), and the authorization is the maintainer's, recorded in comment 6117174845. One difference from the usual shape: the behaviour change that made the sentence false came from an earlier PR (#22776), not from this one.
Gates (local, at head
02ad7dcc, merge base85b4ac63)The set is derived by
node scripts/pm/dispatch-gates.mjs --commands: 20 commands, all run, and--ranreconciles 20 of 20.node scripts/check-empty-changeset.mjs --base origin/main✓ No empty-frontmatter changeset introduced by this diff.node scripts/check-empty-changeset.mjs --self-testpnpm check:nul-bytes(the control-byte gate)OK (scanned 10963 text file(s) [...] no raw ASCII control bytes)node scripts/check-adr-0087-registration.mjs --base origin/main/--self-testnode scripts/check-changeset-no-major.mjs --base origin/main/--self-testpnpm check:changeset-gate-self-testspnpm check:objectui-changeset,check:pm-changeset-deadline-census,check:published-files,check:gitlink-declared,check:driver-memory-census,check:refd-timer-probe,check:watch-hint-literalnode scripts/check-closing-keyword-parity.mjs/--self-test,check-comment-mask-corpus.mjs,pm/release-rehearsal-clone.mjs --self-test,release-pending-publish.mjs --self-testAcceptance notes
The same retirement made two more fragments of this note inaccurate. The authorization covers one cell, so this PR leaves both unchanged and names them for a decision:
500 SUGGESTION_*_FAILED/500 INTERNAL, the wrapper".500 INTERNALwas the retired route's answer: its handler ended inhandleError(err, res, 'INTERNAL')(60bcfe72^:packages/rest/src/rest-server.ts). The two routes left in the row answer500 SUGGESTION_CONFIRM_FAILEDand500 SUGGESTION_DISMISS_FAILED(rest-server.ts:12441,:12459), so neither of them produces the500 INTERNALthe cell still names.500before. The refusal ledger test onmainalready pins nineteen.Generated by Claude Code