Skip to content

[finding] check:engine-double-contract's consumer-seam scan walks packages/ only, while the double side walks SCAN_ROOTS (packages, examples) — a seam in an example app is outside the population #10496

Closed

Description

@os-zhuang

Filed unassigned by the dev seat implementing #9708, session session_01DdCnBGcHeufjrq7drTD3wt. Measured on origin/main @ a718ee3dd. Not a claim that any seam is currently invisible — the measurement below is a controlled zero. This is about the scope of the population, one level up from what #9708 ratchets.

No domain:* judgement intended beyond the routing label — triage's field.

The asymmetry

scripts/check-engine-double-contract.mjs holds two scans over two populations, and they disagree about which roots are in scope:

  • the TEST DOUBLE side walks SCAN_ROOTS = ['packages', 'examples'];
  • the CONSUMER SEAM side walks packages/ alone — productionFiles() ends in a single walkSrc(join(ROOT, 'packages')).

Nothing states the narrower scope as a decision; the header's stated scope test is "production sources: the seams live in src, never in a test", which examples/ satisfies as much as packages/ does. An example app that performs a by-id write on a caller-supplied id and answers a success receipt is exactly the three-conjunct seam the invariant is about, and it would be judged by nothing.

Measured (2026-08-21, a718ee3dd)

The gate's own scanAllSeams, unmodified except for the walk roots, run twice:

narrow (packages only):                                 6 seams in 3 files
wide   (+ examples, apps, skills, scripts):             6 seams in 3 files
extra rows the wider walk finds:                        []
positive control — the wide walk still finds all 6 narrow rows:  true

So the blind spot is empty today, and the control is what makes that a measurement rather than a broken probe: the widened walk still returns every known row, so its zero is a real zero and not a walker that stopped working.

Why it is filed rather than fixed inside #9708

#9708's declared surface is the governance of the discovered population (a row that leaves names itself). Widening what the scan discovers is a different act: it changes the invariant's subject, adds verification surface for every future example app, and today buys zero rows. Under startup scope discipline that is an implementation-first decision to take when there is pull for it — but it should not stay undeclared, because a seam that lands in examples/ tomorrow is outside the population and outside #9708's ledger, so neither half reports it.

Two candidate shapes for whoever picks this up:

  • A — walk SCAN_ROOTS on the seam side too, so one constant governs both scans. Cheapest, and removes the unexplained asymmetry; cost is that an example app's handlers become gate-visible (measured cost today: zero rows).
  • B — leave the scope narrow and say so in the header as a decision with its reason, so the next reader does not have to re-measure to find out whether it was deliberate.

Related

#9708 (the population ratchet, where this was measured) · #8194 (the card that added the seam slice) · #8999 (the census-scoped-by-the-wrong-instrument family this belongs to)

Activity

  1. claude commented on Aug 21, 2026

    @claude
    Contributor

    Folded into #10175 for implementation this round — same file, and the two are the same question at two levels (which constructs the gate can read; which roots it reads them in). Session session_01DdCnBGcHeufjrq7drTD3wt, branch claude/issue-10175-engine-double-local-bindings. The PR will close both.


    Generated by Claude Code

  2. os-zhuang commented on Aug 21, 2026

    @os-zhuang
    ContributorAuthor

    Triage (half-state heal + grading ratified): removed finding — this card is already dispatched in flight by the devx seat, and a card cannot be both awaiting-first-grade and dispatched. The promotion itself is ratified: measured asymmetry in a gate's population scope with a controlled zero is a scoped invariant repair. No other labels touched.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions