Uh oh!
There was an error while loading. Please reload this page.
docs(rest-test): three production seams plus one test-only injection, not four (#12537) - #12646
Merged
Merged
Conversation
… not four (#12537) The `/api/v1/packages` direct-mount door's suite described its `SITES` table as the door's "four seams". Three of the four are production producers; the fourth, `resolveExecutionContext`, is a test-only injection point. A production resolver cannot throw synchronously — `resolvePackageRouteExecutionContext` is a non-`async` wrapper whose only call is to a `private async` method — and its rejections are swallowed twice, at `rest-server.ts:1483` and again at `package-routes.ts:81`, landing on the 401 anonymous-deny floor instead of `sendThrownError`. Corrects six sites, states the reason once in a `Seam census` block and cites it from the others, and retires the falsifier limb that named a synchronously throwing `resolveExecutionContext`: unreachable by construction, so not a falsifier. The `resolveExecutionContext` test case itself is KEPT and relabelled, never deleted — it still pins how the door answers an injected resolver that throws. Comment/prose only: both blobs transpile to a byte-identical program under `removeComments`, with the instrument reverse-checked in both directions (a code token moves the hash, a comment token does not). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjujZN219uFzBhSYfMykCd
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This was referenced Aug 27, 2026
os-litant
marked this pull request as ready for review
August 27, 2026 03:07
This was referenced Aug 27, 2026
Open
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #12537
packages/rest/src/package-door-declared-code.test.tsdescribes itsSITEStable as the
/api/v1/packagesdirect-mount door's "four seams". Three of thefour are production producers. The fourth —
resolveExecutionContext— is atest-only injection point: no production throw of any kind can reach
sendThrownErrorthrough it.This PR corrects the record in that one file. It is comment/prose only — no
test removed, no assertion touched, no behaviour changed.
What I measured
Read on
origin/main@aa5994e17, from the composition rather than inferredfrom the card:
rest-api-plugin.ts:471resolveExecutionContext: (req) => restServer.resolvePackageRouteExecutionContext(req)rest-server.ts:1481resolvePackageRouteExecutionContext(req: any), declared to return a promise of context-or-undefined— and notasync. Whole body: an optional-chainedreq?.params?.environmentIdread, thenreturn this.resolveExecCtx(environmentId, req).catch(() => undefined)rest-server.ts:1453private async resolveExecCtx(...)— beingasync, calling it cannot throw synchronously; it always returns a promisepackage-routes.ts:81awaitsoptions.resolveExecutionContext(req).catch(() => undefined)— a second swallow⇒ A production resolver delivers exactly two things: a context, or
undefined.Its rejections are swallowed twice and land on the anonymous-deny floor as a
401 — they never reach
sendThrownError. The only route from this seam tosendThrownErroris a synchronous throw (it happens before.catchisattached, so it rejects
refusePackageRequestitself and the handler'strycatches it) — and the production wrapper above has no statement that can make
one.
"
private asyncbehind.catch(() => undefined)". Those are two guards doingtwo different jobs:
resolveExecCtxbeingasyncdenies the sync limb, andthe
.catch()denies the rejection limb. Because the wrapperresolvePackageRouteExecutionContextis notasync, the sync question isgenuinely live at that seam and had to be measured rather than assumed. Same
conclusion, different argument.
registerPackageRoutesandPackageRoutesOptionsare not exported frompackages/rest/src/index.ts(the package publishes a single
.entry, anddirect-mount-composition.tsistheir only importer). That zero was reverse-checked against terms known present
in the same file —
export(17 hits) andRestServer— never a substring ofthe term under test.
Reverse-check: the other three ARE production-reachable
Not assumed.
publish/get/deletearePackageServicemethods resolvedfrom the service registry per request (#7563) and awaited inside each handler's
try, so a rejection reachessendThrownError. The live implementation ispackages/services/service-package/src/index.ts, which throws (throw errorfor
declaresHttpAnswer,throw packageSeamUnreadableError()) and carries itsown
publish-driver-fault.test.ts/delete-driver-fault.test.ts. Section 5 ofthis suite already drives that path end-to-end with a real
ObjectQL, a realprotocol and a failing driver.
The tell was already in the file, unremarked: the three production seams inject
async () => { throw error; }— a rejection. The resolver seam injects anon-
async() => { throw error; }— a sync throw. It has to, because arejection would be swallowed at
package-routes.ts:81and answer 401 instead.The census, re-derived
Six sites corrected. I did not inherit the dispatch's list.
:55:61:197-198package-routes-coded-error-mapping.test.ts":262// 1. The demote reaches the wire, at every seam this door has:481declaredCode":505Counted and deliberately left as-is:
:87— "six shapes, four of which demote". Not about seams at all.:91-92— "package-routes-coded-error-mapping.test.tscontributed 4 of the30 … at the four seams". This is a record of a past ablation measurement,
and its "four seams" refers to that other file's four test seams, which
really are four. True as written, and measured numbers are not rewritten to
fit a later census.
The sharp site: a falsifier that cannot be reached
:505-511states a falsifier "so the next reader inherits a measurement insteadof an argument", and lists three ways to reach it. The third was "or a
resolveExecutionContextthat throws one synchronously". Under the measurementabove that limb is unreachable by construction, not merely unobserved — so
it was not a falsifier, and a reader who tried it would have spent the time to
discover it cannot happen.
It is retired rather than reworded, and the block now says so and says why,
with a note that if the swallow at
rest-server.ts:1483is ever un-done the limbbecomes real again and belongs back on the list. The other two limbs are
untouched: both are genuinely reachable.
The
resolveExecutionContexttest case is KEPT⛔ Not deleted. It still pins something real — how this door answers when an
injected resolver throws synchronously — and
reached()keeps it from goingvacuous. It is simply not evidence about a production path, so it is labelled
as a test-only injection point and nothing in the file cites it as one. Deleting
a test to make a census true would be the census lying in the other direction.
The reason is stated once, in a
Seam censusblock in the module docblock,and cited from the five other sites — not restated at each.
ℹ️ One judgement call worth flagging: the site's
namestring(
'GET /packages — the capability gate resolver throws') is unchanged,because a string literal is code and changing it would break the comment-only
proof below. It is accurate as it stands. If you would rather the test output
also carry the "test-only" marker, that is a one-line follow-up.
Comment-only, proven with a calibrated instrument
Both blobs transpiled with
removeComments: true(typescript 6.0.3), emittedprogram hashed:
An equality from an uncalibrated instrument is not evidence, so the instrument
was reverse-checked in both directions against the same head blob:
A code token moves the hash; a comment token does not.
git diff --stat:1 file changed, 91 insertions(+), 14 deletions(-).
Tests and gates
All heavy runs serialized through
scripts/pm/os-verify-lock.sh(slotissue-12537). Every verdict quoted below is the tool's own printed line,never a
$?read through a pipe.Build — the dependency closure a fresh worktree needs before its tests mean
anything:
pnpm --filter '@objectstack/rest^...' build→
os-verify-lock: VERDICT command-exit 0 · held the lock 310s (5m10s) · waited 0sSuite —
pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/package-door-declared-code.test.ts src/package-routes-coded-error-mapping.test.ts→
os-verify-lock: VERDICT command-exit 0 · held the lock 11s · waited 1sThe edited file on its own:
Test Files 1 passed (1)/Tests 58 passed (58).reconciled. This file carries 58 cases, not 155, and 5 numbered
sections (banners
1.–5.at:328,:392,:459,:525,:625), not 4.The 155 traces to this file's own docblock at
:137— "Measured: 30 failed /125 passed of 155" — which is the total of a multi-file ablation run (the
same paragraph records that
package-routes-coded-error-mapping.test.tscontributed 4 of those 30), not this file's case count. ⛔ That prose is
untouched: it is a correct record of a past measurement, and measured numbers do
not get rewritten to fit a later census.
Gate families — derived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, whichtook the change set from git itself (it reported 1 path: this file). Each ran to
its own verdict line:
check:nul-bytesOK (scanned 6987 text file(s) … no raw ASCII control bytes)scripts/check-comment-mask-adoption.mjsOK — 20 private comment-stripper(s) … all 20 recorded and every recorded row still reachedcheck:cross-package-test-inputsOK: 20 package(s) read outside themselves, all declaredcheck:dispatcher-error-vocabularypackages/rest/src/error-response.tscheck:test-source-aliasOK — 72 packages with tests scannedcheck:engine-double-contract632 (file, verb) row(s) held by the RETAINED ledgercheck:where-matcher0 silently-wrong and 0 unjudged matcher(s) … none newcheck:objectql-double-limit… none new@objectstack/resttypecheck→
os-verify-lock: VERDICT command-exit 0 · held the lock 107s (1m47s) · waited 0sRe-run on the final commit. The gate batch above ran on the working tree, so
the ratchet families were re-run after the last commit and are quoted from that
run — a green measured on a tree that is no longer HEAD is not a green:
build program does not read this file:
tsc --noEmit --listFilesreturns0 hits for
package-door-declared-code.test.ts. The half that does read itis
check:test-typecheck(tsconfig.test.json), where--listFilesreturns1 hit, and it passed:
check:test-typecheck: OK — @objectstack/rest's test layer compiles under packages/rest/tsconfig.test.json.So "typecheck is green" is a claim about the test program here, not about the
build program.
Narrowing, declared: I ran the targeted families above plus the two affected
suites — not the full 176-family farm, and not a repo-wide
pnpm lint. CI runsthose on every pull request regardless, and the full-farm result is CI's to
report.
No changeset:
packages/restpublishes["dist", "README.md", "CHANGELOG.md"],the edit is comments inside a
src/**test file thatdistdoes not carry, andthe emitted-program hash above shows nothing published can differ. Labelled
skip-changeset.Scope
⛔ Nothing outside
packages/rest/src/package-door-declared-code.test.tswasedited.
packages/rest/src/rest-server.tswas read only — it is held byPR #12421.
Part of #12537, not a closing keyword: the other half of that card — whether.catch(() => undefined)atrest-server.ts:1483should swallow a door'srejections at all — is untouched here and stays open. It is not a question
this diff can answer: it would change what a public door emits, and the file is
fenced. I checked the conditional the claim raised, and it does not fire —
the swallow is documented at neither site (
rest-server.ts:1483norpackage-routes.ts:81; the nearby docblocks explain why the wrapper exists andwhat an absent resolver means, never what a failing one means). So
"deliberate" is not established by the code as it stands, and a closing keyword
would be wrong.
Generated by Claude Code