Skip to content

docs(gate): contradictsWrapperResolution's docblock still described the flat bare-name index #13474 replaced - #13846

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13787-wrapper-resolution-docblock
Aug 31, 2026
Merged

docs(gate): contradictsWrapperResolution's docblock still described the flat bare-name index #13474 replaced#13846
os-project-manager merged 1 commit into
mainfrom
claude/issue-13787-wrapper-resolution-docblock

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes #13787

Prose only. contradictsWrapperResolution's predicate is byte-identical to origin/main — 1128 characters, sha256 dccdd2b341d10650… on both sides — and the whole diff is comment lines: 0 non-comment lines added, 0 removed, in 3 hunks that all sit inside that one docblock. The fence #13474 put on the predicate is intact; this card is its docblock, and nothing else.

The corrected clause — before / after

The card is one sentence, and it wraps across two lines, which is why a single-string grep for it returns zero. Before (the only clause in the file that asserted the flat index in the present tense):

 * `contradictsDriverReadShape` asks it of `IDataDriver`. The wrapper hop in
 * `isReadCall` asked nothing at all. `functionBodies` is a flat, file-scoped
 * index keyed by BARE NAME, so any call whose `calleeName` happens to equal a
 * function declared in the same file was followed into that function's body —
 * whatever it was called ON, and whatever it was passed.

After:

 * `contradictsDriverReadShape` asks it of `IDataDriver`. The wrapper hop in
 * `isReadCall` asked nothing at all. `functionBodies` WAS a flat, file-scoped
 * index keyed by BARE NAME, so any call whose `calleeName` happened to equal a
 * function declared in the same file was followed into that function's body —
 * whatever it was called ON, and whatever it was passed. (That index is no
 * longer flat: #13474 made it scope-aware. It did not close THIS question —
 * see the last block of this docblock.)

The paragraph is kept whole. It narrates the historical defect that motivates the predicate, and asked nothing at all / was followed were already past tense on purpose; only the functionBodies clause was wrongly in the present. Two words move (is to WAS, happens to happened) plus a three-line forward pointer. Flattening the whole paragraph to a description of today's index would have deleted the motivation.

The second hunk adds a closing block to the same docblock, next to the existing zero-cost statement, so the reader who lands on the predicate is told what #13474 did and why this predicate survives it:

 * WHY #13474 DID NOT SUBSUME THIS, stated here because the paragraph at the
 * top narrates an index shape the file no longer has. `indexFunctionBodies`
 * now resolves a name through the CALL SITE's lexical scope chain, which
 * settles a collision between same-named BODIES — a different collision from
 * the one asked about here, which is across RECEIVERS. Its ONE DECLARATION
 * ⇒ UNCHANGED rule keeps it that way on purpose: a name with exactly one body
 * in the file is answered from any call site, so a unique name reached on a
 * compound receiver is admitted there and refused only here.
 * `indexFunctionBodies`' own docblock records the same from its side, and this
 * is the near half of that pair. Re-measured on this tree after the resolver
 * changed, with this predicate ablated: the two #12358 cases in the self-test
 * report 1 seam each instead of 0, and `--list` over the scan root is
 * byte-identical either way — the zero-seam cost stated just above, still
 * zero.

That pointer is deliberate and it is the pair's near half: indexFunctionBodies' docblock already points at this predicate from ~900 lines away, and now this one points back.

Is the predicate's motivation still sound after #13474? — measured, and yes

#13784's docblock claims the predicate stays load-bearing (a unique name reached on a compound receiver is admitted by the one-declaration rule and refused by that predicate). Verified on this tree by ablation rather than by reading: return false; injected as the first statement of contradictsWrapperResolution, mutation confirmed on disk before the run (marker count 0 to 1, 335171 to 335207 bytes, git diff --stat one insertion), restored afterwards with git checkout HEAD -- ... and the restore proved by hash (d0dc23ff… before and after) plus an empty git diff HEAD. No build step exists between edit and run — the gate is an .mjs executed from source, not from a dist/.

measurement predicate live predicate ablated
--self-test, read-seam rule 57 cases pass 2 fail
--list, whole scan root 66 seams 66 seams, byte-identical output

The two failures are exactly the two #12358 fixtures, one per clause:

✗ passes: #12358 — a compound receiver does not resolve to the same-file method it collides with: expected violation=false seams=0, got violation=false count=0 seams=1
✗ passes: #12358 — a call that cannot satisfy the resolved declaration is not that declaration: expected violation=false seams=0, got violation=false count=0 seams=1

Both fixtures declare delete exactly once, so indexFunctionBodies' one-declaration rule answers the name from any call site and hands the hop straight to this predicate. The scope-aware resolver does not and cannot refuse them — it settles same-name collisions, and there is no collision here. ⇒ the motivation is unchanged in force, narrower in wording: the docblock should no longer say the index is flat, but the reason the predicate exists is untouched, and the file's zero-seam cost figure for it is still zero after the resolver changed.

Census — every bare name / flat index mention in the file, classified

Censused by mechanism (functionBodies, BARE NAME, bare name, flat, LAST-WINS, scope-aware, 13474 as separate terms), never as one contiguous string.

line text verdict
433 helper resolution is file-scoped by construction (functionBodies is built per source file) legitimate — about file scoping, not keying. Still true: the index is built per source file.
1379–1390 functionBodies WAS keyed by bare name and LAST-WINS … #13474 replaced the flat index legitimate — explicitly past tense and already reconciled to #13474 in the same block.
1529–1530 functionBodies is a flat, file-scoped index keyed by BARE NAME STALE — the one this card fixes. Present tense asserting the replaced shape.
2133–2137 Only const/let declarations with an initializer are indexed, keyed by bare name and LAST-WINS. That is deliberately NOT the scope-aware model indexFunctionBodies moved to for #13474 legitimate — a different index (indexLogAliases), still bare-name last-wins on purpose, with the departure measured and stated.
2422–2436 ## Why this is not keyed by bare name alone (#13474) — It was, and it was LAST-WINS … the flat index answered with the THIRD legitimateindexFunctionBodies' own docblock, historical narration, the far half of the pair.
2509 the tie-break the flat index already made legitimate — describes the deliberate within-one-scope tie-break the new resolver kept.
2950 indexFunctionBodies keys by BARE NAME, so an unrelated close() in another class in the same file could supply that licence legitimate, and worth saying why it is not the same defect. The map key is still the bare name (a Map of name to a list of declarations); what changed is that resolution is no longer by key alone. The hazard it warns about also survives, through the one-declaration rule: a close declared once in the file is still answered from any call site, including from another class. True as written, so it is untouched.
6111–6124, 6186 Before it, the index was one flat Map … (1) the flat index DROPS a real seam … The flat index answered with the third legitimate — the #13474 regression-control block, describing the model the four fixtures exist to keep out.

Nothing was changed on grounds of resemblance: 1529–1530 is the only present-tense assertion of the replaced shape.

Verification

Every gate run explicitly, exit code captured before any pipe. Final commit for all of it: de44eb1b9.

command result
pnpm check:durability-log-level exit=0✓ self-test (log-level rule): 63 case(s) passed · ✓ self-test (read-seam invention rule): 57 case(s) passed · ✓ read-seam invention …: 66 read seam(s), none invents an unreported answer
pnpm check:ratchet-remedy-authority exit=0OK check-ratchet-remedy-authority: 176 scripts swept (scripts/*.{mjs,mts}); 11 mark the expanding remedy ⛔ MAINTAINER-ONLY, 5 turn it down outright, 160 hand out no ratchet-expanding remedy.
node scripts/check-ratchet-remedy-authority.mjs --self-test exit=0OK self-test: the lexer holds, messages are bounded, …
pnpm check:nul-bytes exit=0
pnpm lint (repo-wide eslint . --no-inline-config, not narrowed) exit=0, no findings
pnpm check:agent-test-spelling, check:bash32-floor, check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard, check:pnpm-filter-targets, check:watch-hint-literal all exit=0
node scripts/check-ci-filter-parity.mjs, check-cross-package-test-inputs.mjs, check-shard-attestation.mjs all exit=0
node scripts/check-test-completeness.mjs exit=3NOT MEASURED, not a red: the gate grades a saved turbo run test log and none was named. Its own text says to record it as NOT MEASURED when run from the derived family.
node scripts/pm/bare-root-worklist.mjs --self-test exit=0 — convention-triggered (this edits a gate script)
pnpm check:pm-dispatch-gates exit=0 — same convention trigger
pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 src/sys-metadata-repository.draft-drain.test.ts src/protocol.metadata-store-outage.test.ts exit=0Test Files 2 passed (2), Tests 44 passed (44). These are the pin tests that read this script by path, so they are owed on top of the path-derived family.

The family was re-derived from the real diff with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths passed), which also surfaced the two convention-triggered obligations above.

Why there is no changeset

The dispatch order asked for one. This diff publishes nothing: it is comment lines in scripts/check-durability-degradation-log-level.mjs, a repo-root gate script that belongs to no published package, so a changeset would have to name a package and fabricate a CHANGELOG entry for a comment. An empty-frontmatter changeset is not the alternative — scripts/check-empty-changeset.mjs rejects newly added ones outright, and its header records why. Precedent on this exact file is uniform: of the last 12 commits touching it, the 10 that were script-only carried zero changeset files, #13474's own PR (6207c9ecc) among them. skip-changeset is applied to this PR instead, and read back after applying.


Generated by Claude Code

…he flat bare-name index

#13474 replaced indexFunctionBodies' flat last-wins map with call-site
lexical resolution, which made one clause of this predicate's docblock
false: the paragraph narrates the historical defect in the past tense but
asserted the flat index in the PRESENT. The paragraph is kept — it is why
the predicate exists — and only that clause moves to the past tense.

A closing block states what #13474 did and why this predicate survives it:
the resolver settles collisions between same-named BODIES, this one asks
about a collision across RECEIVERS, and the ONE DECLARATION => UNCHANGED
rule routes a unique name reached on a compound receiver straight here.
Re-measured on this tree, ablating the predicate: the two #12358 self-test
cases report 1 seam each instead of 0, and --list over the scan root is
byte-identical (66 seams either way).

Prose only. The predicate's body is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 15:43
@os-project-manager
os-project-manager added this pull request to the merge queue Aug 31, 2026
Merged via the queue into main with commit 36cf8d8 Aug 31, 2026
34 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-13787-wrapper-resolution-docblock branch August 31, 2026 16:00
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

contradictsWrapperResolution's docblock still calls functionBodies a flat bare-name index — #13474 made it scope-aware

2 participants