Skip to content

finding: with the ledger empty, check:published-readme-exports' green line ends in "0 of the findings are call sites" — a ratio over an empty set, in the clause that has to say "clean, not unmeasured" #9767

Description

@os-steve

Observation only — no gate is red.

Now that scripts/published-readme-exports.baseline.json holds entries: [], the success branch of scripts/check-published-readme-exports.mjs (lines 824-829) prints:

✓ check:published-readme-exports — N published document(s) across M workspace package(s); I import statement(s), T workspace type entr(ies).
  0 known instance(s) still in scripts/published-readme-exports.baseline.json; 0 of the findings are call sites.

The first clause is fine at zero. "0 known instance(s) still in ..." carries the shrink-only direction in the word "still", and the header line immediately above reports the population that was actually read — so zero reads as "none left to repair", not as "nothing was scanned".

The second clause is the weak half. memberChecks counts call sites among ALL findings, baselined ones included, so with an empty baseline on a clean tree it is structurally always 0 of the findings are call sites — a ratio over an empty set. It was informative while the ledger was populated: it said how much of the baseline the call-site half accounted for. With the ledger empty it is the one place in an otherwise careful green line where a reader can hear "the call-site half measured nothing" — the #4690 ambiguity this gate is elsewhere emphatic about, and the call-site half is the half most likely to quietly stop matching, being an AST/text scan over prose.

Suggested shape, if triaged as worth doing

When findings.length === 0, report what the call-site half measured rather than what it found — for instance the number of resolved workspace-import names it checked members on, alongside the existing import-statement and type-entry counts. That distinguishes "ran and found nothing" from "matched nothing" without adding a second line. Whatever the shape, it changes author-facing output and should land with a self-test pin next to the ones already there (the gate pins its remedy text for exactly this reason: the token is interpolated, so a source scan proves nothing about the message).

Scale check before anyone spends much on it: this is one clause in one green line, and the reader it protects is the next person auditing whether the call-site half still works. A one-line change with a pin, not a project.

Found while landing #9649, which is scoped to the baseline's $comment by ruling and does not touch gate output. The card asked for a judgement on this line rather than an automatic build; this is that judgement, filed so the judgement is not lost.

Activity

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

    @os-support-ai
    Collaborator

    Triage: grading = de-label — finding off; confirmed pm:queue · domain:devx · Task. One clause in one green line plus a self-test pin, per the card's own scale check.


    Generated by Claude Code

  2. os-steve commented on Aug 19, 2026

    @os-steve
    CollaboratorAuthor

    Claiming this card.

    • Session: session_01XqDQYVU5smx29ts9pAErja
    • Branch: claude/issue-9767-empty-ledger-green-line
    • Container & model: S, mode:subagent, model: opus

    Scope per dispatch: output wording only — the scan, population, exit codes and baseline handling stay exactly as they are.

    Generated by Claude Code


    Generated by Claude Code

  3. os-steve commented on Aug 19, 2026

    @os-steve
    CollaboratorAuthor
    {
      "issue": 9767,
      "status": "done",
      "branch": "claude/issue-9767-empty-ledger-green-line",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/9815",
      "premise_still_valid": true,
      "summary": "RESUME of a dead dispatch, not a restart: inherited commit 71a90d2e7b verified, merged current main (45 commits) as 0600163f68, re-derived every reading, pushed to the existing draft PR #9815. I changed NOTHING in the inherited code — I could not find anything wrong with it, and per ruling 1 did not restyle what was merely not my phrasing. The one thing I did change is the PR body, whose figures were factually stale after the merge (see below); stale evidence in the reviewable artifact is wrong, not a preference. H4: premise still holds — main's copy of the gate, run against this same built tree, still prints the vacuous clause, and no commit since has touched the gate or its baseline. RULING 3 SCOPE VERDICT: EARNED. The +111 breaks down as 48 comment / 3 blank / 60 code; of the 60 code lines, 21 are production (one optional trailing param defaulting to null, three accumulator increments, a 14-line successSummary(), three wiring lines) and 39 are the self-test pin the card itself asked for ('should land with a self-test pin next to the ones already there'). So the card's 'one clause in one green line plus a self-test pin' maps to 21 + 39 exactly. Verdict, population, exit codes and baseline handling are untouched, and all pre-existing analyzeDocument callers pass two args and are unaffected by the null default. The only place the hunk runs rich is comments at 43% vs the file's own 28% norm, and that is the rationale block on successSummary, matching the file's existing convention of documenting freshRemedy() for the identical reason (interpolated text a source scan cannot verify). Not overshoot.",
      "tests": "All on the final commit 0600163f68 (git rev-parse --short HEAD), after merging origin/main; full workspace build first (71/71, under the shared /tmp/os-heavy-verify.lock) because this gate reads dist/*.d.ts.\n\nH1 — the actual green line now printed, verbatim:\n  ✓ check:published-readme-exports — 60 published document(s) across 77 workspace package(s); 190 import statement(s), 49 workspace type entr(ies).\n    0 known instance(s) still in scripts/published-readme-exports.baseline.json.\n    Import half: 289 documented symbol(s) checked against the exports their package publishes.\n    Call-site half: 8 documented `X.y(…)` call(s) checked, on 231 import-bound name(s).\nIt states a LIMIT-free RESULT per half: input volumes, not a ratio. The card's distinction is met — 'baseline empty because the debt was paid' now reads as 0 ledger + 289/8 checked, whereas 'I read nothing' would read as 0 ledger + 0/0 checked. Ruling 4: these are the CURRENT readings; the pre-merge run reported 283/225/189, moved by #9868 and the plugin-dev / service-storage README rewrites. main's copy of the gate on this same built tree still prints the defect: '0 known instance(s) still in ...; 0 of the findings are call sites.'\n\nH2 — ablation, the bad case demonstrated. Broke the call-site half so it matches nothing (member-call regex \\s*\\.\\s* -> \\s*\\.\\.\\s*, a text scan quietly ceasing to match — the exact drift the card names). NOTE: my first attempt with perl matched zero and silently changed nothing; caught it because git diff --stat was empty, which is the H3 'matched zero, reported success' trap. Redone by line number with assertions and confirmed on disk. Results:\n  NEW wording: 'Call-site half: 0 documented `X.y(…)` call(s) checked, on 231 import-bound name(s).' — 231 receivers bound, 0 calls read: a self-contradiction a reader can act on.\n  OLD wording, same broken tree: '0 known instance(s) still in ...; 0 of the findings are call sites.' — BYTE-IDENTICAL to the healthy run.\nRestored via git checkout <branch> -- <path> (never stash); tree verified clean.\n\nH3 — the pin is real. Flipped it by restoring the old clause inside successSummary(); anchor asserted to match exactly once and the edit confirmed on disk via git diff --stat before running. --self-test goes RED with 4 failure(s), exit 1, naming each case: the two text pins, PLUS — independently of any wording — the two behavioural pins ('the GREEN body renders IDENTICALLY for a tree that was scanned and one that was not' and 'must state each half's INPUT VOLUME, never a ratio over the findings'). That second pair is what makes the pin durable rather than a transcription of the current sentence. Restored; --self-test green, exit 0.\n\nGates (re-derived on the merged tree with node scripts/pm/dispatch-gates.mjs scripts/check-published-readme-exports.mjs, which named exactly these two):\n  pnpm check:published-readme-exports              EXIT=0 (self-test + gate)\n  node scripts/check-cross-package-test-inputs.mjs EXIT=0  OK: 12 package(s) read outside themselves\n  node scripts/check-nul-bytes.mjs                 EXIT=0  OK (6297 text file(s), no raw ASCII control bytes)\n  pnpm check:published-readme-links                EXIT=0  151 outbound link(s) across 60 published markdown file(s)\n  npx eslint scripts/check-published-readme-exports.mjs --no-inline-config  EXIT=0\n  grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]' on the changed file — no hits.\nNo changeset: scripts-only, publishes nothing; skip-changeset label read back as present on the PR alongside size/m. Rulings 5 and 6 hold — my branch's own diff vs main is 1 file, scripts/check-published-readme-exports.mjs, nothing under docs/adr, .claude, skills, AGENTS.md, CLAUDE.md, .changeset.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #9910: check-role-word's green line counts only the LEDGER, so once its debt is paid a total scan failure and a clean repo both print 'OK (0 baselined file(s), no new occurrences)' — the #9767 shape one debt-payment away; demonstrated by ablating ROOTS to non-existent dirs AND emptying the baseline (both confirmed on disk), which greens at exit 0. Today it is protected only incidentally, by the stale/ratchet-down branch firing on a non-empty ledger.",
        "filed as #9911: check:published-readme-exports greens when documents and imports exist but nothing resolves to a workspace member (targets.size === 0) — the one no-population shape it does not refuse, unlike the two it hard-refuses with (#4690). Left alone deliberately: adding a refusal is a verdict change, outside this wording card."
      ]
    }

    Generated by Claude Code


    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