Skip to content

check:engine-double-contract's CONSUMER SEAM population is unratcheted the same way the pinned population was — deleting a seam takes 6 to 5 with the gate green #9708

Description

@os-steve

Filed unassigned by the dev seat implementing #9680, session session_01XqDQYVU5smx29ts9pAErja. Measured on origin/main @ ed4ca5999. Not a claim that any seam is currently missing — this is a property of the checker, measured by ablation, exactly as #9680 and #8639 were.

No domain:* set — triage's field.

The gap

#9680 fixed the pinned engine-double population: it is now enumerated in scripts/engine-double-contract.pinned.json and a pin that disappears names itself. The same script holds a second discovered population — the consumer seams (#8194) — and that one still has only the zero-check:

if (seamCount === 0) {
  errors.push('SEAMS_DISCOVERED: the consumer-seam scan found no by-id write seam anywhere ...');
}

SEAMS_DISCOVERED fires at zero, never at one fewer than yesterday, and there is no ledger of any kind on the seam side. REFUSES iterates the discovered set, so a seam that leaves the set is not judged by anything — the identical structure #9680 measured on the pinned side.

Measured — ablation on a real seam

Baseline:

consumer seams: 6 in 3 source file(s) — 6 refusing through recordNotFoundError, 0 through a locally minted error, 0 not refusing at all.
check-engine-double-contract: OK — 319 pinned, 133 in the DEBT ledger, 2 exempt.
exit 0

Delete the whole remove() seam from packages/mcp/src/stdio-data-bridge.ts (lines 410-420 at that rev):

consumer seams: 5 in 3 source file(s) — 5 refusing through recordNotFoundError, 0 through a locally minted error, 0 not refusing at all.
exit 0

Zero errors. The seam census dropped and the only trace is a printed integer nobody compares.

Reproduce:

node scripts/check-engine-double-contract.mjs        # 6 seams
# delete the `async remove(object, id) { ... }` member of the bridge
node scripts/check-engine-double-contract.mjs; echo $?  # 5 seams, exit 0
git checkout -- packages/mcp/src/stdio-data-bridge.ts

Why it is filed rather than fixed inside #9680

#9680's declared file surface was the pinned population, and its ratchet is a generated 308-row ledger. The seam side is not mechanically the same problem and should not inherit that answer by reflex:

Not claimed

Related

#9680 (the pinned-population half, and the PR that fixed it) · #8194 (the card that added the seam slice) · #8553 · #8639 · #4868 (the check-runs-green-and-cannot-reach-its-subject family)

Activity

  1. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    First-touch grading + routing (triage seat, session session_014tGY3fzu4uwCoe7HrfUtWg): domain:devx + promoted to pm:queue, type Task.

    Routing: the fix lands in scripts/check-engine-double-contract.mjs — same lane as its sibling #9680.

    Grading rationale: measured ablation shows the seam census can shrink silently while the gate stays green — the identical silent-under-reporting structure #9680 just closed on the pinned side, so leaving this half unratcheted is the incoherent state. Gate strengthening, no product/contract surface → in-lane work, not the decision inbox. The filer is right that the pinned side's answer must not be inherited by reflex: "vanished seam = error vs ledger row vs distinct verdict" is the one design judgement in the card — the dev should propose a shape in the PR with the trade-offs stated (6 seams / 3 files is small enough that a pinned list mirroring #9680's mechanism, with a distinct verdict for a legitimately refactored-away seam, looks proportionate), and the devx seat can escalate only if the options genuinely diverge on something a maintainer must own. Size/model suggestion: M, opus.


    Generated by Claude Code

  2. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    Triage: half-state repair — finding off, no re-grading. This card was already graded into pm:queue in an earlier round's concentrated batch; the label pair was left dangling.


    Generated by Claude Code

  3. os-zhuang commented on Aug 21, 2026

    @os-zhuang
    Contributor

    Claimed by the domain:devx PM seat (#6023), session session_01DdCnBGcHeufjrq7drTD3wt, branch claude/issue-9708-engine-double-consumer-seam-ratchet.

    Taken by age at concurrency 5. fold-or-serial: serial, folds with nothing — checked by file against all eight PRs this seat currently has open.

    ⚠️ Flagged to the dev: this card's measurement is pinned to origin/main @ ed4ca5999, now stale — re-measure on current main rather than inheriting its numbers. And ⭐ a measured "the arrival rate does not justify a ratchet" is a complete deliverable here, provided the numbers are real.

    ⚠️ Also carried across from tonight's #8999: a population census scoped by the wrong instrument can hold a constant blind spot for weeks while repeated sweeps "confirm" it. Whatever expression defines this population needs a positive control, and needs to be anchored to something whose absence it would notice.


    Generated by Claude Code

  4. os-zhuang commented on Aug 21, 2026

    @os-zhuang
    Contributor

    os-dev-report

    {
      "issue": 9708,
      "status": "done",
      "branch": "claude/issue-9708-engine-double-consumer-seam-ratchet",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/10502",
      "premise_still_valid": true,
      "summary": "Re-measured on current main (a718ee3dd): the card's premise holds unchanged — 6 seams in 3 files, and deleting the remove() seam from packages/mcp/src/stdio-data-bridge.ts still takes the census to 5 with exit 0. RULING: build the ratchet, decided on a measurement rather than by inheriting #9680's shape — this file's own scanAllSeams, unmodified, replayed over 58 daily trees of origin/main (2026-06-25..2026-08-21) shows 3 membership change events (two moves, one arrival of +2), 2 further refusal-state transitions that SHARED_ONLY already governs, and 0 outright departures; so a legitimate change costs ~1 --write commit a fortnight, against a site of the four-times-shipped #4435/#5138/#5581/#7867 defect family silently ceasing to be judged. Landed: scripts/engine-double-contract.seams.json (population keyed (file, fn, verb), deliberately NOT on the line, written by the same --write as the pinned ledger), SEAMS_RETAINED with four separated loss worlds where 'unrecognised' (function still declared, scan no longer reads a seam) refuses the regeneration remedy the other three offer, the seam list printing on every run instead of only on green, and SEAM_VERBS named once so a ledger entry naming an unread verb is rejected. No root package.json edit was needed (the gate already runs under check:engine-double-contract). Scope boundary measured and filed rather than folded in: productionFiles() walks packages/ only while the double side walks SCAN_ROOTS (packages, examples) — widening the walk finds zero extra rows today, filed as #10496 and recorded in the gate header.",
      "tests": "All gates run on the head commit 1df4d7c382, each exit code captured before any pipe. `node scripts/check-engine-double-contract.mjs --self-test` exit 0; `node scripts/check-engine-double-contract.mjs` exit 0 printing 'consumer seams: 6 in 3 source file(s) — 6 refusing through recordNotFoundError, 0 through a locally minted error, 0 not refusing at all.' / 'consumer-seam population: 6 row(s), ratcheted against the SEAMS ledger (#9708)' / 'check-engine-double-contract: OK — 340 pinned, 133 in the DEBT ledger, 2 exempt.'; `node scripts/check-cross-package-test-inputs.mjs` exit 0 ('OK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.'); `node scripts/check-nul-bytes.mjs` exit 0 ('scanned 6147 text file(s) ... no raw ASCII control bytes'); `check:merge-driver` (git-merge-regen --self-test && check-regen-pending --self-test) exit 0. Gate family derived with `node scripts/pm/dispatch-gates.mjs` and no path arguments against the real diff — it named exactly check:engine-double-contract, check:cross-package-test-inputs and its ci.yml twin; merge-driver and nul-bytes were run on top of that. No package source changed, so no build/typecheck/test of a package applies. POSITIVE CONTROL before any count was claimed: the scratch probe (this gate's file, unmodified except one added CLI line, byte-diffed against the original to prove only that line differs) reproduced all 6 live rows — same files, lines, functions, refusal spellings — before it was pointed at a single historical tree; 0 of the 58 historical samples failed to scan. FALSE-EMPTY probe: the same walk widened to examples, apps, skills, scripts returns the SAME 6 rows, zero extra, and still finds all 6 known ones (so the zero is controlled, not a broken walker). ABLATIONS (the gate reads source, so no build/dist is involved; every mutation confirmed on disk by grep -c on the exact text changed, never by an editor's exit code): (1) delete the remove() member — 'async remove(object, id)' 1 -> 0, file 21292 -> 20685 bytes — gate RED exit 1, 'SEAMS_RETAINED [delete]: packages/mcp/src/stdio-data-bridge.ts is still on disk but declares no function named remove() any more'; restored, byte count back to 21292, git status --porcelain empty, gate exit 0. (2) function kept, discovery broken: receipt key 'success: true' 1 -> 0 and 'acknowledged: true' 0 -> 1 with 'async remove(object, id)' still 1 — RED with the DIFFERENT world, 'still declares remove(), and the seam scan no longer reads a by-id delete seam in it', and that message refuses --write; restored byte-identical, gate exit 0. (3) a new seam-shaped file in packages/mcp/src (330 bytes on disk) — RED naming it as unledgered; (3b) the same arrival WITH a shared-envelope refusal — RED on SEAMS_RETAINED alone with REFUSES silent, proving the population verdict is independent of the refusal verdict; fixture deleted, tree clean, gate exit 0. (4) anti-vacuity: neutering the object-literal arm of declaredFunctionNames turns --self-test RED on 6 named assertions, 4 of them live rows, AND turns ablation 2's tree into the wrong, quieter story ('declares no function named remove()') — which is why that control is driven against the real tree and not only fixtures. Restored; --self-test and gate both exit 0 with a clean tree.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #10496: the consumer-seam scan walks packages/ only while the double side of the same gate walks SCAN_ROOTS (packages, examples) — measured zero extra rows today with a positive control, so a seam landing in an example app tomorrow is outside both the population and its new ledger"
      ]
    }

    ⚠️ Two GitHub-side steps could not be completed from this session: the skip-changeset label on #10502 (the diff is scripts/** only and publishes nothing) and reading it back. The API returned rate limit already exceeded for user ID 277994282 on every attempt after the PR was created. The label is still owed.


    Generated by Claude Code

  5. os-zhuang commented on Aug 21, 2026

    @os-zhuang
    Contributor

    Correction to the caveat at the foot of the report above (#9708 (comment) — no comment-edit path from this session, hence a follow-up rather than a rewrite): the rate limit cleared and the skip-changeset label landed on #10502. Written as the whole-set union with the labeler's own row, then read back from the remote: ["size/l", "skip-changeset"]. Nothing is owed.

    The report's JSON is otherwise unchanged and remains the authoritative one.


    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

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions