Uh oh!
There was an error while loading. Please reload this page.
docs(rest-test): the resolver seam is a test-only injection point, in both sibling suites (#12647) - #12653
Merged
os-litant merged 1 commit intoAug 27, 2026
Conversation
… both sibling suites Both suites asserted that the `/api/v1/packages` door's `resolveExecutionContext` seam is production-reachable. Re-measured on this tree: it is not. The only production supplier is `rest-api-plugin.ts:471`, whose wrapper (`rest-server.ts:1481`) is not `async` and holds no statement that can throw synchronously; the `async` `resolveExecCtx` it delegates to can only reject, and that rejection is swallowed at `rest-server.ts:1483` and again at `package-routes.ts:81`, landing on the 401 anonymous-deny floor. Comment/prose only — no test removed, no assertion touched, no behaviour changed. The derivation is cited, not restated a third time. 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): |
os-litant
marked this pull request as ready for review
August 27, 2026 03:37
Uh oh!
There was an error while loading. Please reload this page.
os-litant
deleted the
claude/issue-12647-sibling-seam-reachability-notes
branch
August 27, 2026 04:12
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.
Fixes#12647
Two sibling suites asserted that the
/api/v1/packagesdirect-mount door'sresolveExecutionContextseam is production-reachable. Re-measured here: it isnot. Both sites are relabelled as test-only injection points. No test
removed, no assertion touched, no behaviour changed — comment/prose only, proven
below.
What I measured — re-derived, not inherited
Read from the composition on this branch's base,
2db1293c1. I took neither thecard's derivation nor PR #12646's.
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 is two statements:const environmentId = req?.params?.environmentId ?? undefined;thenreturn this.resolveExecCtx(environmentId, req).catch(() => undefined);rest-server.ts:1453private async resolveExecCtx(...)— beingasync, calling it cannot throw synchronously; it returns a promisepackage-routes.ts:81awaitsoptions.resolveExecutionContext(req).catch(() => undefined)— a second swallowNeither statement in the wrapper can throw synchronously: the first is an
optional-chained read with
??(safe for anyreq,nullincluded), and thesecond calls an
asyncmethod and attaches.catchto the promise it returns.So a production resolver delivers exactly two things — a context, or
undefined. Its rejections are swallowed atrest-server.ts:1483and again atpackage-routes.ts:81, and the request lands on the anonymous-deny 401 floor.The
only supplierzero, reverse-checked.git grep -n resolvePackageRouteExecutionContextreturns one production definition (
rest-server.ts:1481) and one productioncall site (
rest-api-plugin.ts:471); every other hit is aCHANGELOG.mdline ora test comment. Reverse-checked against
mountAndRecordDirectRoutes— a termknown present in the same file and not a substring of the term under test —
which returns
rest-api-plugin.ts:6and:463plus four test callers. Theoption value flows only
rest-api-plugin.ts:471→direct-mount-composition.ts:89→
:126 registerPackageRoutes; the composition is a pass-through and declares novalue of its own.
The derivation, turned into an observation
Rather than leave this as an argument, I drove both limbs through the real
registrar with one throwing resolver each and read the wire answer. Scratch test,
run and then deleted — not committed.
The swallow is not inferred from the source shape — it is the answer on the
wire, verbatim.
The tell, confirmed independently
Every one of the four suites that drives this seam injects a non-
asyncvi.fn(() => { throw error; }), while all twelve production-seam injectorsbeside them are
async. Twelveasync, four sync — and all four sync ones arethe resolver:
They had to be sync: as measured above, a rejection answers 401 instead of
reaching the catch at all. The files were recording the difference before anyone
read it that way.
The census, re-derived — and it disagrees with the card in both directions
⛔ I did not sweep for the phrases the card quotes. I swept for statements this
measurement makes false, wrap-tolerantly (
grep -rPzowith(?s)overmulti-line spans, so a phrase broken across a line still matches), then read every
seam-mentioning file in
packages/rest/srcfor realism / reachability claims.The driver population is four files, not two. The card names two. The sweep
found four, and each needed a different disposition:
package-routes-coded-error-mapping.test.tspackage-door-5xx-message-sanitization.test.tspackage-door-user-message.test.ts:73-81already reads "One seam below is drivable here but NOT production-reachable, and it is named so nobody reads it as evidence of the opposite", with the sameasync/ swallow reasoning. It landed with #12502package-door-declared-code.test.tsSo the conclusion matches the card (two files to repair) while the
population does not. That third file is also independent in-tree corroboration
of the measurement, arrived at by a different author on a different card.
A second falsified statement at site 1, which the card does not name. The
same block gave a second reason for driving the gate:
That is stale.
package-routes.tsnow marks the list door's registry read[#11130] NOT wrapped in a catch, deliberately(:672) and its durable read[#11063] NOT wrapped in a catch, deliberately(:738) — read in the productionfile, not taken from the sibling's prose. Both arms do reach this outer catch
and are pinned in
package-list-durable-read-refusal.test.tsandpackage-list-registry-read-refusal.test.ts. Repairing only the realism clausewould have left a second false sentence in the paragraph I was correcting, so it
is corrected in the same block and named here rather than left silent. The
sibling file I am also editing already carries the corrected form at
:333-339.Counted and deliberately left alone.
package-routes-coded-error-mapping.test.ts:26— "This file pins the four SITES" — is a claim about this file's own four
test seams, which really are four. True as written; a census claim is not
repaired by making it disagree with what the file does. Same for
:9and:330in the sibling ("all four handlers" — handlers, not seams).Sites checked and found NOT falsified, so untouched:
direct-mount-base-follows-apipath.test.ts:229-236,discovery-advertised-direct-mounts.parity.test.ts:138-145andpackage-envelope.conformance.test.ts:70-74each say production wires theresolver here — which is true, and none of them claims a throw from it
arrives anywhere.
packages/runtime/src/package-door-error-parity.test.tsmakesno claim about this seam.
package-routes.ts:66-70and:341-349describe anabsent resolver failing closed, never a failing one.
The repairs
⛔ Neither test case is deleted. Both still pin real door behaviour and
reached()keeps them from going vacuous. What changed is what the prose claimsthey are evidence of.
Site 1 —
package-routes-coded-error-mapping.test.ts:30-43, the sharp one.It did not merely count the seam; it defended its realism:
The first clause is true; the conclusion does not follow, so the inference is
what is repaired, not the count. Precisely because that resolution is reached
through an
asyncmethod, the coded 401/403s it raises are rejections —swallowed twice, answering 401. The block now says the lever is exactly as
contrived as that sentence denied, quotes the sentence it is retiring so the
correction is legible, and names the case a TEST-ONLY INJECTION POINT.
Site 2 —
package-door-5xx-message-sanitization.test.ts:341-347, milder, samefamily."so it keeps proving the DOOR rather than one source" reads as a claim
about a production path. It is now "exercises the CATCH SITE rather than one
source", with the test-only label beside it. The
:356back-reference ("keepsdriving the GATE for the reason above") still resolves, now to the corrected
reason.
⛔ The derivation is not restated a third time. Both sites cite it — the
Seam censusblock ofpackage-door-declared-code.test.ts, pluspackage-door-user-message.test.ts's reachability section — with #12537 and#12647 as the stable anchors. Restating it at each site is the exact defect these
cards exist to end.
ℹ️ PR #12646 had not merged when this was written, so per the card the issues
carry the authority and the
Seam censusblock is named as where the derivationlives. An issue reference does not dangle.
ℹ️ The
SITES[].namestring'GET /packages — the capability gate resolver throws'is unchanged in both files. It is a string literal, not a comment; it is
accurate as it stands (the injected resolver does throw); and changing it would
break the comment-only proof below. Same judgement PR #12646 recorded for the
same string.
Comment-only, proven with an instrument calibrated in both directions
Both blobs transpiled with
removeComments: true(typescript 6.0.3), emittedprogram hashed. Neither edit turned out to be a string literal or a test title —
both are pure comments (a
/** */docblock and a//block), so Ruling 5'sconditional does not fire.
An equality from an uncalibrated instrument is not evidence, so each mutant was
asserted to be a real edit before hashing (a no-op mutation throws rather than
reporting a hash). A code token moves the hash; a comment token does not.
git diff --stat: 2 files changed, 58 insertions(+), 14 deletions(-).Tests and gates
Every heavy run — builds and typechecks included — went through
scripts/pm/os-verify-lock.sh(slotissue-12647). Every verdict below is thetool's own printed line. Exit codes were captured before any pipe
(
cmd > file 2>&1; ec=$?), never through| tail.Build — the dependency closure a fresh worktree needs first:
pnpm --filter '@objectstack/rest^...' build→
os-verify-lock: VERDICT command-exit 0 · held the lock 297s (4m57s) · waited 0sGates and suites, all at the final commit. The whole batch ran in one
acquisition after the last commit, so nothing here is a green measured on a
tree that is no longer HEAD:
check:nul-bytesOK (scanned 6987 text file(s) … no raw ASCII control bytes)check:cross-package-test-inputsOK: 20 package(s) read outside themselves, all declaredcheck:dispatcher-error-vocabularyOK — 21 unregistered code-stamping site(s), all classifiedcheck:objectql-double-limit… none new·baseline key set verified against 2db1293: no files addedcheck:page-declaration-shapeOK — 34 page entries across 2223 sources … all reach the kernelcheck:published-files✓ 69 publishable package(s) … admits no test, test-harness config or build scriptcheck:slot-lookupratchet holds: 107 unswept site(s) in 25 file(s), none newcheck:test-source-aliasOK — 72 packages with tests scannedcheck:type-source-resolutionOK — 94 tsc program(s) across 77 packages scannedscripts/check-ci-filter-parity.mjsOK: all 109 declared cross-package glob(s) … coveredscripts/check-comment-mask-adoption.mjsOK — 20 private comment-stripper(s) … all 20 recordedscripts/check-plugin-teardown-shape.mjs✓ 63 Plugin implementation(s) … baseline fully burned downcheck:engine-double-contractOK — 689 pinned, 134 in the DEBT ledger, 3 exemptcheck:where-matcher0 silently-wrong and 0 unjudged matcher(s) … none newcheck:query-options-erasureratchet holds: 67 unswept non-test site(s) in 17 file(s), none newcheck:type-check-coverageOK — 65/78 workspace packages type-checked (plus the root), 13 in the DEBT ledger@objectstack/resttypecheckcheck:test-typecheck: OK — @objectstack/rest's test layer compiles under packages/rest/tsconfig.test.json→
os-verify-lock: VERDICT command-exit 0 · held the lock 366s (6m06s) · waited 0sThe two suites, in that same run:
--listFilesover both of the package's tsc programs:
The build program does not read either edited file. The half that does is
check:test-typecheck(tsconfig.test.json), which passed. So "typecheck isgreen" here is a claim about the test program, not the build program.
Narrowing, declared — not implied. I ran the families
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackderivedfrom the real change set (it reported 2 paths, from git itself), plus the
edits a test fileconvention families, plus the two affected suites. I didnot run the full 176-family farm and did not run a repo-wide
pnpm lint.One family is deliberately NOT MEASURED rather than reported green:
check:type-check-debtrefuses on a worktree without the whole workspaceclosure built, and I built only
@objectstack/rest^...; a refusal is not a pass,so it is named here instead of quietly counted. It cannot move on this diff
anyway — the emitted-program hashes above show nothing compiled changed. CI runs
the full farm on every pull request regardless, and that result is CI's to report.
No changeset
packages/restdeclaresfiles: ["dist","README.md","CHANGELOG.md"]. This diffis comments inside two
src/**test files, whichdistdoes not carry, and theemitted-program hashes above show that nothing compiled — published or not — can
differ. Nothing ships, so there is no user-visible change to describe. Labelled
skip-changeset.Scope
⛔ Nothing outside the two named test files was edited.
packages/rest/src/rest-server.tswas read only — it is held by PR #12421.packages/rest/src/package-door-declared-code.test.tswas read only — heldby PR #12646.
Fixes #12647, notPart of: the sweep found no site it could not repair.package-door-user-message.test.tsneeded none, and the only other driver isfenced to a PR already repairing it. This card has no fenced or maintainer-facing
half.
both stated above and neither smoothed over: the driver population is four
files, not two (same conclusion, different census), and site 1 carried a
second falsified statement the card does not name (the stale inner-
catchreason at
:33-36). Everything else I re-derived — the four line anchors, theonly supplierzero, the double swallow — matched what I was handed, measured on2db1293c1rather than the card'saa5994e17.Generated by Claude Code