Skip to content

fix(pm): dispatch-gates names check:error-status-conformance for a file that binds an HTTP status, judged from content - #22329

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-22320-error-status-derivation
Oct 8, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-22320-error-status-derivation

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #22320
Clause-②: no

What

scripts/pm/dispatch-gates.mjs now names check:error-status-conformance for a file that binds an HTTP status to an error response, judged from the file's CONTENT. That is the route the seat verdict on the card chose: the CHANGE_KIND_GATES content trigger that already reaches check:dispatcher-error-vocabulary, another REFUSE-WIDE gate.

  • scripts/pm/dispatch-gates.mjs has three changes:
    • A new exported predicate, emitsAnHttpStatus, with three limbs. (1) status/statusCode bound to a 4xx/5xx literal or a SCREAMING_SNAKE name. (2) The positional sendError(res, STATUS, …) door. (3) A SCREAMING_SNAKE constant bound to a 4xx/5xx literal.
    • A sibling CHANGE_KIND_GATES entry naming the gate, with its deletion criterion.
    • 35 new self-test cases, plus a census-guard pin that the family is live.
  • scripts/check-error-status-conformance.mjs and scripts/pm/bare-root-worklist.mjs are back to their main bytes. The round-1 ROOT_DIR_WATCH_HINTS declaration, its self-test battery and the REFUSE-WIDE to DECLARED-NARROWER re-decision are reverted by a new commit (11e2a5299b); history is not rewritten. git diff origin/main on both files is empty, so neither needed a touch, and the gate's REFUSE-WIDE row stands as recorded.
  • The extractor's bare-word refusal is untouched. No gate is added.

Sibling entry or join? Measured

Measured at 11e2a5299b, whose bytes equal main 28bff18d0c. Each file was run through the gate's own deriver (deriveRuntimeStatuses) one at a time:

files
carry a derived (code, status) producer 128 (418 sites)
producers the existing ADR-0112 code predicate (stampsAnErrorCodeLiteral) misses 19 (86 sites)
producers emitsAnHttpStatus misses 0

The two questions diverge, so the gate gets a sibling entry with its own predicate rather than joining the code entry. All 19 misses fall into two shapes:

  • The positional four-argument door. For example, settings-routes.ts and share-link-routes.ts call sendError(res, 403, 'SETTINGS_FORBIDDEN', …), with no code token near the code.
  • An assignment pair whose code is an enum member. For example, turso-driver.ts and filter-refusal.ts write err.code = StandardErrorCode.enum.X; err.status = 400.

Precision and residues on the same tree:

  • Precision: emitsAnHttpStatus matches 185 of the 3247 non-test TypeScript files, every one inside the gate's own scanned population, and 128 of them carry a producer (69%). The code predicate names 283 files for its own gate.
  • Residue 1, unresolved-only files: 9 files hold only UNRESOLVED pairs (a status read from a runtime value), and 6 of them do not match. The gate reports those and never fails on them, so as written they cannot red it.
  • Residue 2, cross-file constants: 4 files resolve a producer elsewhere through a constant they declare. The status-constant limb reaches 3 of them: anonymous-deny.ts, upload-ownership.ts and webhook-secret.ts. The fourth, packages/mcp/src/metadata-completeness.ts, declares only a CODE constant, so the code entry reaches it and this one does not. A code-constant limb would have cost 45 more matches (185 to 230) for that one file, and the entry declines that trade. The docblock records both residues.

The harm, reproduced on the same paths

Command: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack PATH. Before is 11e2a5299b (the bytes of main 28bff18d0c); after is head 28bf1d4448. Every run exited 0.

path before after
packages/services/service-storage/src/storage-routes.ts (the PR #22311 emit site) 53 commands, family absent 54; the only added line is pnpm check:error-status-conformance
content/docs/ai/agents.mdx (docs-only control) 41, absent 41, absent
packages/services/service-storage/README.md 46, absent 46, absent
packages/services/service-storage/src/index.ts (a .ts with no status and no code) 51, absent 51, absent

discoverFamilies() gives byte-identical records, at main and at head, for every family whose files include dispatch-gates.mjs or check-dispatch-gates.mjs. So none of the new path strings in the self-test, or in the module-body why, became a hint.

Pins (dispatch-gates self-test, 1976 to 2011 cases)

  • Limbs, through an injected reader:
    • Hits: a status-and-body terminal, an error class declaring its status, an enum-member assignment pair, the positional door, a SCREAMING status name, and a status constant.
    • The enum-pair and door cases are each paired with the code predicate missing the same text. That divergence is the reason for a sibling entry.
    • Misses: a quoted status word, a 2xx status, a comparison, a runtime-value status, a comment, a .ts with no status and no code, a test file, a .d.ts, a non-TS file, and an unreadable path.
  • Live tree: the fix(service-storage)!: enforce the storage settings Limits group (max_upload_mb, presigned_ttl, session_ttl) at the upload doors #22311 emit site is reached. The docs-only page, the package README and the package barrel index.ts are not reached; the barrel is reached by neither content entry. Discrimination holds at 185 of 3247.
  • Rendered: exactly one entry names the gate. The emit-site path renders the section and the runnable line. The why states REFUSE-WIDE, DOCUMENTING as the repair, the ⛔ MAINTAINER-ONLY baseline remedy, and "needs NO build". Through the whole table, the specimen derives the gate and the docs-only, README and barrel paths do not. An undiscoverable name renders STALE.
  • Census guard: check:error-status-conformance is a live family.

Ablations

All three ran through scripts/ablation-replace.mjs against committed head 28bf1d4448, with the dispatch-gates self-test as the wrapped command. Each run was stopped once the status section and the first case after it had streamed, by killing only the wrapper's own descendants. Each mutation was proven on disk (anchor 1 to 0, blob changed). Each restore was proven by blob == HEAD (5447f770ee5c) and an empty git diff HEAD.

  1. Door limb removed: exactly 1 red, "the positional four-argument sendError door is a hit".
  2. Entry made inert (matches: () => false, the base behaviour): 7 red, the rendered half. Those are the section, the runnable line, the three why pins, "through the whole table, the specimen derives the status gate", and STALE. The negatives stay green.
  3. Predicate widened to every TS file:
    • The 8 content negatives red: quoted word, 2xx, comparison, runtime value, comment, no-status .ts, live barrel, and barrel through the table. The discrimination case also reds, at 3247 of 3247.
    • The population filter holds: test, .d.ts, non-TS, docs and README stay green.
    • Collateral: three existing exact-count pins went red, because a widened entry adds a line to their specimen paths. They are the root-program, i18n and metadata-form section counts. With the real predicate they are green.

Gates (all at head 28bf1d4448)

  • Derived list: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; change set from the merge base 28bff18d0, one file) derived 29 commands. All 29 exited 0, with exit codes captured before any pipe.
  • --ran reconciliation: "29 derived famil(ies) accounted for — 29 run, 0 NOT-MEASURED (a DERIVED zero — all 29 recorded an exit code and none of them is 3)".
  • pnpm check:pm-dispatch-gates: "dispatch-gates self-test: 2011 cases pass", exit 0. It ran detached, 1111s, before the ablations, on the clean tree.
  • The other 28 derived commands: all exit 0. The list: ci-filter-parity, closing-keyword-parity (+self-test), comment-mask-corpus, declaration-mirrors (+self-test), scripts-symbol-anchors (+self-test), self-test-wired (+self-test), self-test-workflow-commands (+self-test), whole-set-label-write (+self-test), agent-test-spelling, bash32-floor, cli-command-ids, cross-package-test-inputs, declared-population-live, driver-memory-census, entry-guard, gitlink-declared, nul-bytes, parse-guard, pnpm-filter-targets, ratchet-remedy-authority, refd-timer-probe, watch-hint-literal.
  • Not derived, run anyway: node scripts/pm/bare-root-worklist.mjs --self-test (it imports the derivation's predicates) passed with OK. pnpm check:error-status-conformance passed.
  • Lint, narrowed and declared as narrowed: eslint --no-inline-config --format json scripts/pm/dispatch-gates.mjs returned 1 file, 0 errors and 0 warnings. eslint.config.mjs enables no type-aware linting (no parserOptions.project), so this diff cannot move the verdict on any untouched file. The full pnpm lint is left to CI.

Acceptance notes

  • main was merged once (591dc5ad2a, to 28bff18d0c). It has since moved one commit, to e36ee5351b (fix(service-storage)!: the chunked completion assembles the parts the upload holds, and a re-sent chunk is counted once (#22313) #22330). That commit touches nothing under scripts/. It does edit the live specimen, and on its bytes the specimen still matches emitsAnHttpStatus and the barrel index.ts still matches neither predicate, so the branch was not merged again. CI runs the merge ref.
  • Three other roster-silent REFUSE-WIDE families stay as recorded. At 4e4111ca0, for the storage-routes path, check:error-code-casing, check:engine-double-contract and check:authz-resolver were also roster-silent and underived. None has a measured consumer, so none is touched or filed. If one gains a consumer, the same content-trigger route applies.
  • A side observation, not acted on: the code predicate misses the StandardErrorCode.enum.X assignment form, because its SCREAMING_SNAKE limb requires the name to start the value. Whether check:dispatcher-error-vocabulary can fail on that form is not measured here.
  • skip-changeset: root scripts/ publishes nothing.

Generated by Claude Code

claude added 3 commits October 8, 2026 16:42
…e to the dispatch derivation

Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q
Co-authored-by: Claude <noreply@anthropic.com>
…ow to DECLARED-NARROWER

Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q
Co-authored-by: Claude <noreply@anthropic.com>
…, so a rename elsewhere cannot red this gate

Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q
Co-authored-by: Claude <noreply@anthropic.com>
claude added 2 commits October 8, 2026 17:36
…oot worklist to their main bytes

The ROOT_DIR_WATCH_HINTS declaration, its self-test battery 29 and the
REFUSE-WIDE to DECLARED-NARROWER re-decision are withdrawn: the seat
verdict on the card routes the family through the content trigger in
dispatch-gates instead, so the REFUSE-WIDE row stands as recorded.

Reverts 21b4403, 38eaa64 and 9903181.

Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/xs and removed size/m labels Oct 8, 2026
…le that binds an HTTP status, judged from content

A sibling CHANGE_KIND_GATES entry with its own predicate, emitsAnHttpStatus:
a status or statusCode bound to a 4xx/5xx value, the positional sendError
door, or a SCREAMING_SNAKE status constant. Measured at the bytes of main
28bff18, it reaches all 128 files that carry a derived producer, while
the ADR-0112 code predicate misses 19 of them (86 sites), so the gate does
not simply join the vocabulary entry. The gate's REFUSE-WIDE bare-root row
stands as recorded. Self-test cases pin the PR #22311 emit site, the
docs-only, README and no-emission controls, and the rendered line.

Claude-Session: https://claude.ai/code/session_0115N1oNnQS5WqofZ2DzaT3q
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m and removed size/xs labels Oct 8, 2026
@objectstack-fleet objectstack-fleet Bot changed the title fix(scripts): check:error-status-conformance declares its scan surface to the dispatch derivation fix(pm): dispatch-gates names check:error-status-conformance for a file that binds an HTTP status, judged from content Oct 8, 2026
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 8, 2026 19:03
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 8, 2026 19:03
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 8, 2026
Merged via the queue into main with commit 5ff7cbe Oct 8, 2026
40 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-22320-error-status-derivation branch October 8, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants