Skip to content

fix(doctor): the rows nothing asserted, and the parser that hid them - #196

Merged
kevintseng merged 1 commit into
mainfrom
test/pin-doctor-rows
Aug 23, 2026
Merged

fix(doctor): the rows nothing asserted, and the parser that hid them#196
kevintseng merged 1 commit into
mainfrom
test/pin-doctor-rows

Conversation

@kevintseng

Copy link
Copy Markdown
Contributor

Summary

#195 pinned one doctor row after finding its diagnostic untested while the action it recommends was tested. This measures whether that was one oversight, and it was not — it was three layers. A new detector (C8) lists every createCheck/createInfo id in doctor.ts and asks whether any test names it: twelve of twenty-four appeared nowhere. Six of those twelve turned out to be the audit's own comment-stripper corrupting the corpus; seven were real (one overlaps); one row had an implementation defect found while pinning it.

Type of change

  • Feature (feat)
  • Bug fix (fix) — the comment stripper, and the install_id row's severity
  • Refactor (refactor)
  • Docs only (docs)
  • Test only (test) — the seven unpinned rows
  • Build / CI / chore
  • Release (release)

What changed

1. The audit's comment stripper was corrupting its own corpus.
stripComments (scripts/lib/reference-corpus.mjs, shared by C3, C6 and now C8) used two regexes, and the block-comment one could not tell a real opener from the same two characters inside a line comment or a string. tests/core/doctor.test.ts carries a tsconfig glob inside a // comment, as prose; the regex opened a block there and closed it at the next real terminator hundreds of lines below — fourteen openers against thirteen closers in that one file — blanking everything between. Replaced with a single-pass scanner tracking code / string / comment state. C8 went 12 → 7 hits, matching an independent hand count.

2. Seven doctor rows had no assertion anywhere. Now pinned, in tests/core/doctor.test.ts (+ one case in node-runtime-check.test.ts):

row why it matters
hooks-config a FAIL row about an install whose hooks cannot load — three failure codes, none asserted
llm_probe includes the NOT-VERIFIED branch, whose whole purpose is that an expired key and a working setup must not read the same
install-channel the warn branch, and that a healthy install carries no fix
capabilities Smart Mode vs Core, and that it cannot fail
transcript-mining off-vs-on, and that being off is not a fault
install_id the id it reports is the one on disk, and the privacy sentence
node-runtime had six tests asserting what the row SAYS, never what it IS — the id is what the dashboard and i18n catalogue key on

3. install_id was a check that could not fail. createCheck(..., 'pass', ...) with no failing branch, so it rendered [PASS] and counted toward Overall — the exact case DoctorCheck.informational exists for, whose docstring names the Capabilities row as the instance that was fixed. This one was left behind. Now createInfo. No verdict changes (the row was always pass); what changes is that "N/N PASS" stops counting a row that verified nothing. CHANGELOG entry under [Unreleased].

4. C8 had the shape it was written to catch. denominator=24 was unguarded: reformat doctor.ts until id-extraction misses half the call sites and it prints denominator=12 hits=0, exit 0 — clean-looking coverage over twelve unexamined rows. A call site whose id cannot be read is now its own hit. (Verified in passing: the first version of that guard produced four hits, all of them prose mentioning createCheck( — including the comment I had just written next to install_id.)

Verification

Run in an isolated worktree at 3b921a2a + this change, so the numbers are not affected by unrelated edits in the main working tree:

npm run typecheck                     exit=0
node scripts/run-tests-isolated.mjs   158 files, 2335 tests passed, exit=0
npm run build                         exit=0  (dist/core/doctor.* regenerated)
node scripts/audit/verification-audit.mjs     exit=0  (C8: denominator=24 hits=0)
  • npx tsc --noEmit clean (via npm run typecheck)
  • npm run build clean — required here: the release gate caught dist/core/doctor.* stale after the install_id change, and plugin-marketplace installs run dist/ as committed rather than building. The regenerated files are in this commit.
  • npm run verify:releasenot quoted as green. Its only run in this tree is the one that FAILED on the stale dist; the rebuild has not been put back through it. CI runs it on this branch.
  • npm test -- --run passing — as scripts/run-tests-isolated.mjs (throwaway HOME)
  • Hooks untouched
  • LLM flows untouched — llm_probe's tests inject probeProviderImpl and assert zero live calls without --probe

Break-test, four mutants, isolated worktree, restoration by writing the original string back (never git checkout):

mutant result
comment stripper back to the two regexes KILLED
install_id back to a hardcoded pass KILLED
hooks-config stops noticing a missing hook type KILLED
llm_probe probes without --probe KILLED

The first one SURVIVED on the initial run. The fixture built the glob from a closing sequence instead of an opening one, producing a string with no opener in it at all — which both stripper versions handled identically. The test was green and proved nothing; only the mutation showed it. Fixed, with the reason written beside the fixture.

Test plan

  • npx vitest run tests/core/doctor.test.ts tests/core/node-runtime-check.test.ts tests/reference-corpus.test.ts
  • node scripts/audit/verification-audit.mjsC8: denominator=24 hits=0
  • Revert stripJsComments to the two regexes → the glob-in-a-line-comment case goes red
  • memesh doctor — the Install ID row now prints [INFO], not [PASS]

Known limitations / follow-ups

  • C8 counts a row as pinned when its id or an i18n code appears in test code at all. It cannot tell an assertion from a fixture seed — vector_generation itself passed that bar for months while only ever being seeded. It finds rows nobody has named; reading the hit is still the job. Written down in the detector.
  • The scanner is not a JS parser: regex literals are not tracked, so a /pattern/ containing a quote can still confuse the string states. Same failure direction as before (over-strip, which fails loudly), and doing it properly needs the preceding-token analysis a real lexer does.
  • Only doctor.ts is covered. The same "the fix is tested, the diagnostic is not" shape can exist wherever code emits user-facing findings; nothing here measures that.

Follows #195, which pinned one doctor row — `vector-generation.open` — after
finding that the ACTION it recommends was tested and the row itself was not.
That looked like one oversight. Measuring it turned up three layers.

**The measurement.** A new detector (C8 in `verification-audit.mjs`) lists
every `createCheck`/`createInfo` id in `doctor.ts` and asks whether it appears
anywhere in test code. Twelve of twenty-four appeared nowhere.

**Layer two: six of those twelve were the detector lying.** `stripComments` in
`scripts/lib/reference-corpus.mjs` — shared by C3, C6 and now C8 — removed
comments with two regexes, and the block-comment one could not tell a real
opener from the same two characters inside a line comment or a string.
`tests/core/doctor.test.ts` carries the tsconfig glob `**` + opener +
`.test.ts` inside a `//` comment, as prose. The regex opened a block there and
closed it at the next real terminator hundreds of lines below, blanking every
line between: fourteen openers against thirteen closers in that one file. Every
id in that hole read as referenced by nothing. Replaced with a single-pass
scanner that tracks code / string / comment state; C8 went 12 → 7, matching an
independent hand count of the same file.

**Layer one: the remaining seven were real.** Now pinned:

  - `hooks-config` — a FAIL row about an install whose hooks cannot load, with
    three distinct failure codes and none of them asserted
  - `llm_probe` — including the NOT-VERIFIED branch, whose entire purpose is
    that an expired key and a working setup must not read the same
  - `install-channel`, `capabilities`, `transcript-mining`, `install_id`
  - `node-runtime` had six tests that asserted what the row SAYS and never
    what it IS; the id is what the dashboard and the i18n catalogue key on, so
    renaming it would have broken both with the suite green

**A defect found while pinning them.** `install_id` was
`createCheck(..., 'pass', ...)` with no branch that could fail, so it rendered
as `[PASS]` and counted toward `Overall` — the exact case the `informational`
flag exists for, whose docstring names the Capabilities row as the instance
that was fixed. This one was left behind. Now `createInfo`. No verdict moves
(the row was always `pass`); what changes is that "N/N PASS" stops counting a
row that verified nothing. In CHANGELOG under `[Unreleased]`.

**Layer three: the detector had the same shape it was written to catch.**
`denominator=24` was unguarded, so reformatting `doctor.ts` until the
id-extraction missed half the call sites would print `denominator=12 hits=0`
and exit 0 — clean-looking coverage over twelve unexamined rows. A call site
whose id cannot be read is now its own hit.

Break-tested in an isolated worktree, four mutants:

  comment stripper back to the two regexes            KILLED
  install_id back to a hardcoded pass                 KILLED
  hooks-config stops noticing a missing hook type     KILLED
  llm_probe probes without --probe                    KILLED

The first SURVIVED on the initial run: the fixture built the glob from a
closing sequence instead of an opening one, producing a string that contained
no opener at all, which both stripper versions handled identically. The test
proved nothing until the mutation showed it. Fixture fixed, and the reason is
written beside it.

Verification, in a clean worktree at 3b921a2 + this change — isolated because
the main working tree carries an unrelated in-progress edit that would have
moved the numbers:
  npm run typecheck                    exit=0
  node scripts/run-tests-isolated.mjs  158 files, 2335 tests passed, exit=0
  npm run build                        exit=0 (dist/core/doctor.* regenerated
                                       and committed here — the release gate
                                       caught them stale, and plugin-marketplace
                                       installs run dist/ as committed)
  node scripts/audit/verification-audit.mjs   exit=0

`verify:release` is not quoted as green: its last run in this tree was the one
that FAILED on the stale dist, and the rebuild has not been put back through
it. CI runs it on this branch.
@kevintseng
kevintseng merged commit 7bc3e3c into main Aug 23, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant