Skip to content

test(rest): re-point the publish-classification sentinel at ThrownHttpError.declaredStatus - #8814

Merged
qq9340100 merged 1 commit into
mainfrom
claude/issue-8634-declared-status-sentinel-delegation
Aug 15, 2026
Merged

test(rest): re-point the publish-classification sentinel at ThrownHttpError.declaredStatus#8814
qq9340100 merged 1 commit into
mainfrom
claude/issue-8634-declared-status-sentinel-delegation

Conversation

@qq9340100

@qq9340100 qq9340100 commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Fixes #8634

What changed

packages/rest/src/package-publish-status-classification.test.ts asked the shared #8016 rule "did this throw declare a status of its own?" by hand-probing resolveThrownHttpError with a sentinel fallbackStatus (0) no producer declares. PR #8633 gave the resolver a field that states this fact directly — ThrownHttpError.declaredStatus, present exactly when the throw declared a status, absent when it did not. This PR re-points both hand-spelled call sites at that field:

  • declaredStatus helper: resolveThrownHttpError(error, 0).status !== 0resolveThrownHttpError(error).declaredStatus !== undefined
  • the driver-code case: resolveThrownHttpError(driverError, 0) / expect(resolved.status).toBe(0)resolveThrownHttpError(driverError) / expect(resolved.declaredStatus).toBeUndefined()

The case's own unrelated claim — resolved.declaredCode and the re-thrown 500/INTERNAL_ERROR answer — is untouched.

This is not a defect fix: the sentinel spelling was not wrong for any producer in this repo today. It is the same question spelled twice, and the hand-spelled copy fails silently in exactly the one case the field cannot — a producer that declares status 0. Test file only, no production change (ThrownHttpError.declaredStatus already landed in #8633).

Verification

An ad-hoc equivalence check (resolveThrownHttpError(e, 0).status !== 0 vs resolveThrownHttpError(e).declaredStatus !== undefined) against every shape this suite exercises — .status, .statusCode, a declared 5xx, a bare Error, a string throw, null, and the driver-code case — showed full agreement. The one constructed divergence, a producer declaring status: 0, showed the old sentinel silently answering false ("not declared") while the new field-based check correctly answers true — confirming the exact failure mode the card describes and that this PR removes it.

Tests

At HEAD a8aca740c:

  • pnpm --filter @objectstack/rest test (full package suite, --maxWorkers=2): Test Files 117 passed (117), Tests 1942 passed (1942), exit 0.
  • pnpm check:nul-bytes: OK.
  • pnpm check:cross-package-test-inputs (both the pnpm run and direct-script forms): OK, 9 declared packages, nothing undeclared.
  • pnpm check:query-options-erasure: ratchet holds, no files added against baseline d09d0fd.
  • pnpm check:type-check-coverage (structural half): OK, unaffected by this change.
  • pnpm check:type-check-debt (--re-measure, the ratchet half — @objectstack/rest carries a TEST_DEBT ledger entry since its tsconfig.json excludes *.test.ts): OK. 33 ledger entries re-measured, 1926 raw tsc errors total, none above its recorded number. @objectstack/rest re-measured to exactly its recorded 155 (unchanged — this edit introduced no new tsc diagnostic in the hidden test layer). The one entry that moved (@objectstack/lint, -1) is unrelated to this PR.

Generated by Claude Code

…pError.declaredStatus

`package-publish-status-classification.test.ts` asked the shared #8016 rule
whether a throw declared a status of its own by hand-probing
`resolveThrownHttpError` with a sentinel `fallbackStatus` (0) no producer
declares. PR #8633 gave the resolver a field that states this fact directly
-- `ThrownHttpError.declaredStatus`, present exactly when the throw declared
a status, absent when it did not. Re-point both call sites at that field
instead of the hand-spelled sentinel:

- the `declaredStatus` helper: `resolveThrownHttpError(error, 0).status !== 0`
  -> `resolveThrownHttpError(error).declaredStatus !== undefined`
- the driver-`code` case: `resolveThrownHttpError(driverError, 0)` /
  `expect(resolved.status).toBe(0)` ->
  `resolveThrownHttpError(driverError)` /
  `expect(resolved.declaredStatus).toBeUndefined()`

The case's own unrelated claim -- `declaredCode` and the re-thrown 500 /
INTERNAL_ERROR answer -- is untouched. Test file only, no production change
(`ThrownHttpError.declaredStatus` already landed in #8633).

Fixes #8634

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NaS1PAHJcPfAA2acnV53Tn
@qq9340100 qq9340100 added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 15, 2026 — with Claude
@vercel

vercel Bot commented Aug 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 15, 2026 4:08am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 0 changed package(s). ✅

@github-actions github-actions Bot added the tests label Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author

ACCEPT (conditional) — PM review, domain:cli seat

One file, +10/−7, three functional lines and a doc-comment rewrite. All four rulings verified from the diff.

Ruling 2 — the case's unrelated claim survives: VERIFIED structurally. declaredCode and the 500/INTERNAL_ERROR assertions do not appear in the diff at all. Scope creep was the only realistic failure mode for this card and it did not happen.

The verification did the thing I said I would accept "cannot be done" as an answer to. I asked for a case distinguishing the two spellings, and said to say so plainly if none could be constructed. It was constructed: a producer declaring status: 0, where the old sentinel silently answers false ("not declared") and the field-based check correctly answers true. That is the card's stated failure mode demonstrated rather than described — and for a refactor whose whole justification is "these two are equivalent except in one case", exhibiting that case is the only evidence that means anything. Equivalence was also checked across every shape the suite exercises (.status, .statusCode, a declared 5xx, a bare Error, a string throw, null, the driver-code case) with full agreement.

The doc comment was updated to describe the new mechanism, including the 0-declaring case, rather than left describing the sentinel trick that is no longer there. That matters more than usual on this card: a stale comment above a correctness predicate is exactly the hazard #8734 spent a whole card mechanising away tonight.

Flip held on two conditions, not one:

  1. every gate job concluding success on its own reading; and
  2. the outstanding check:type-check-debt --re-measure reading. The PR discloses it as still running at draft time. That is the one gate that can genuinely move here — @objectstack/rest carries a TEST_DEBT ledger entry precisely because its tsconfig.json excludes *.test.ts, so a test-file edit is exactly the change class that can shift it, and the package typecheck is structurally blind to it. I will not flip on the assumption it passed.

Disclosing it as pending rather than quoting a stale or piped reading is the right call, and it is the second time tonight that discipline has caught something a green-looking summary would have hidden.


Generated by Claude Code

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The sentinel spelling of &quot;did this throw declare a status?&quot; can now delegate to ThrownHttpError.declaredStatus

2 participants