chore: close a batch of quality-gate & tidy gaps (#1785 #1787 #1789 #1790 #1767)#1792
Conversation
…1790 #1767) Bundles five small, related tidy/gate items into one PR: - #1785: delete the dead src/types/navigation.ts InspectorTab (0 importers; duplicated/drifted from utils/inspectorTabs InspectorTabId). src/types/ now holds only ambient .d.ts stubs. - #1787: add src/hooks/** to the web coverage `include` (it was silently outside the ≥90 gate) and add tests for the two untested hooks, useServerJsonImport and useImportClientConfig, bringing every hook to ≥90 on lines/statements/functions/branches. - #1789: widen clients/{cli,tui,launcher} format/format:check to their top-level configs; add root format:shared / format:check:shared covering test-servers/src/**, vitest.shared.mts, and the repo-root eslint.config.js. - #1790: pin prettier to an exact version (3.8.4, dropping the ^3.8.1 caret) in all five package.json files so the format gate's verdict can't shift with an in-range patch bump; lockfiles synced. - #1767: its root-file format+lint gap is closed here (format:shared + a new lint:shared via a second files block in the root eslint.config.js; web/server/ was already gated in #1788). Its larger cli/tui __tests__ typecheck piece (76 type errors) is split out to #1791. Prettier-normalized the newly-covered files (pure formatting). No runtime behavior change. `npm run ci` green. Closes #1785 Closes #1787 Closes #1789 Closes #1790 Closes #1767 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
@claude review |
|
Claude finished @cliffhall's task in 3m 54s —— View job Review — PR #1792
Verdict: LGTM. The five items land cleanly and the "no runtime behavior change" claim holds — I verified every non-test, non- Verified good#1790 lockfile coherence. This was the one thing that could have silently broken #1785 dead-code removal. #1787 coverage include. Prettier-only reformats. Timer hygiene in the new tests. Findings1. #1789 doesn't quite reach "the remaining ungated first-party TS/JS" — 4 files are still outside every format glob (minor). I enumerated all 885 tracked TS/JS/MJS files against the post-PR glob set. These fall through:
This isn't hypothetical: all three 2. #1790's premise applies equally to the lint toolchain (optional follow-up). Pinning prettier exactly so "the gate's verdict can't shift with an in-range patch bump" is right, but 3. // Each rename sees the other's target already claimed.
expect(result.current.renameErrors["beta"]).toContain("already in use");The 4. "renames to the original id when the rename target is blank" covers the 5. Timer constants duplicated between hook and test (minor maintainability).
6. Doc staleness in AGENTS.md was correctly moved to past tense, but Notes (no action needed)
|
- #1789 gap: widen clients/web format to include .storybook and clients/ launcher format to include scripts/; reformat the 3 .storybook files (were non-conforming under the pinned prettier 3.8.4). Audited all 885 tracked source files — now fully prettier-clean. - Export VALIDATE_DEBOUNCE_MS / COLLAPSE_DELAY_MS / HIGHLIGHT_DURATION_MS from useServerJsonImport and use them in the test instead of hardcoded 300/1000/250 (so a tuned constant can't silently desync the test). - Assert the symmetric renameErrors["alpha"] alongside ["beta"] so a one-directional collision-check regression fails. - Comment the blank-rename test as exercising a UI-unreachable defensive branch (canImport gates submit). - Un-stale the two specification/v2_ux_interfaces_plan.md references to the now-removed navigation.ts InspectorTab. npm run ci green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
Thanks — thorough as always, especially catching that the 1 — 4 files still ungated: Fixed. Widened 3 — asymmetric assertion: Fixed. Now asserts 4 — UI-unreachable branch: Added a comment noting the blank-rename test hits the 5 — duplicated timer constants: Exported 6 — stale spec doc: Un-staled both 2 — eslint/typescript-eslint also caret: Deliberately not expanding this PR for it, and holding off on a ticket to avoid sprawl. The exact-pin here was the prettier-specific fix from #1790; if we want it to be a policy across the lint toolchain that's a separate decision — happy to file it if you'd like.
|
|
@claude review |
|
Claude finished @cliffhall's task in 2m 41s —— View job Review — PR #1792 (round 2)
Verdict: LGTM — ship it. All five findings from round 1 are addressed (or, for #2, deliberately deferred with a reasonable rationale). One doc-sync nit below, non-blocking. Re-verification of the round-1 findings1 — ungated first-party files: independently confirmed closed. I re-ran the audit against the post-fix glob set rather than taking the claim on faith: enumerated all 885 tracked
And the three 3 — symmetric assertion. 4 — UI-unreachable branch documented. The comment at 5 — timer constants. 6 — spec doc. Both 2 — eslint/typescript-eslint carets. Declining to expand scope here is the right call; the policy question is genuinely separable from #1790's prettier-specific fix. No objection to leaving it unfiled. Also re-verified
Findings1. AGENTS.md now under-describes the format surface it just widened (nit, doc-sync).
That was accurate before 2. PR body's #1789 section describes the pre-fix state (nit). The body lists only the cli/tui/launcher top-level-config widening and Notes (no action needed)
|
#1792 review r2) 1ce3b64 added .storybook to clients/web's format glob and scripts/ to clients/launcher's, but AGENTS.md:222 still described the pre-fix scope. Bring it in line and note the non-recursive top-level glob is why nested dirs are named explicitly. Docs only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
Both round-2 nits fixed: 1 — AGENTS.md stale: Updated the format-surface sentence (line 222) to include 2 — PR body: Updated the #1789 section to describe what actually landed (the Thanks for the re-audit against the post-fix glob set — appreciate not taking the "0 ungated" claim on faith. |
|
@claude review |
|
Claude finished @cliffhall's task in 3m 21s —— View job Review — PR #1792 (round 3)
Verdict: LGTM — ship it. Re-verifiedAGENTS.md:222 now matches the globs. The sentence names
0-ungated audit reproduced independently. I enumerated all 885 tracked
Exported timer constants. Coverage Root Spec doc + README. Both Follow-up observations (not for this PR)1. The 885-file audit has no durable guard — it's a point-in-time check. #1789's value is "0 ungated," but nothing keeps it at 0. The repo already has the right pattern for this exact problem: 2. The client top-level globs cover a narrower extension set than the root's. Root 3.
Same "whitelist include silently drops a directory" shape #1787 fixed for 4. eslint asymmetry (noted, no action). The four Note on verification limitsThis checkout has no |
|
Thanks for the three rounds — and for independently reproducing the 885-file / 0-ungated audit rather than taking it on faith. All four round-3 observations are follow-up-shaped (you flagged each as "not for this PR"), and they're good ideas — a standing Considering the review converged (three rounds, last two "ship it", no outstanding change-requests on this PR). |
…uard, uniform globs, theme gate)
Rather than defer these to tickets, fold them into this PR:
- Obs 2: widen every client + root format glob to a uniform
*.{ts,tsx,mts,cts,js,jsx,mjs,cjs} so a future .mts/.cjs/.tsx top-level
file can't silently slip the gate.
- Obs 1: add scripts/verify-format-coverage.mjs (wired into `validate`) —
it parses the format:check globs out of every package.json, enumerates
all tracked source files, and fails listing any not covered by a glob.
The durable, standing version of #1789's one-shot audit; negative-tested.
- Obs 3: bring src/theme/** under the coverage gate (21/23 files were
already ≥90 transitively; add Paper.test.tsx for the one laggard,
Paper.ts). src/App.tsx (~4.5k lines, ~42% branches) is converted from a
silent omission into an explicit, documented exclusion (comment on the
coverage `include` + AGENTS.md) — gating it is a dedicated effort, not a
whitelist tweak.
npm run ci green (the new guard reports 885/885 tracked source files gated).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
Rather than leave the round-3 observations as follow-ups, handled all three in-place (55ad7ab): Obs 1 — no durable guard for the audit: Added Obs 2 — narrow extension set: Widened all client + root format globs to a uniform Obs 3 — App.tsx / theme/ outside include:** Measured it —
|
|
@claude review |
|
Claude finished @cliffhall's task in 5m 23s —— View job Review — PR #1792 (round 4)
Verdict: LGTM. The new guard is sound and I verified it empirically rather than by inspection — it runs clean (887/887 tracked source files gated) and it fails correctly when a glob narrows. Three findings below: one doc-sync (real, same class as the r2/r3 nits), one blind spot in the guard I confirmed by experiment, one comment-accuracy nit. None blocking.
Verified — the guard actually guardsUnlike previous rounds, this one is runnable without Passes on the current tree. Negative test: narrowing is caught. I removed So the guard genuinely reproduces the round-1 finding it was written to prevent. ✅ Glob→RegExp translation is correct for all four shapes actually in use. I traced
No Failure direction on a new client is safe.
Uniform extension widening is a genuine no-op today — guard still reports 887/887 after it, confirming nothing new was pulled in and nothing dropped. And it's wired where it belongs: first in
Findings1. The docs didn't follow the code — including the sentence round 2 fixed (moderate; same class as the r2/r3 nits). This commit changed the glob strings and added a script; AGENTS.md/README weren't updated, and AGENTS.md's own maintenance rule covers exactly this ("when adding new commands … update the relevant sections"). Four concrete staleness points:
2. The guard trusts a
That's the same "a gate silently stops gating" failure mode the script was written to close, one level up. Cheapest fix that closes it: resolve 3.
Both are legitimate exclusions — they're the exact analog of Notes (no action needed)
|
…usion list)
- Harden verify-format-coverage: only harvest format:check globs from
scripts transitively reachable from `validate` (via npm run refs), so an
unwired/renamed format:check no longer counts as coverage. Negative-tested
— renaming clients/web format:check to an unreferenced name now fails the
guard (627 files flagged) instead of passing.
- Name src/main.tsx and src/index.ts (browser + bin bootstraps) alongside
src/App.tsx in the coverage-include comment and AGENTS.md, so the
documented exclusion list is complete rather than claiming App.tsx is the
only one.
- Doc sync: document verify:format-coverage (AGENTS.md + README script table
+ scripts/ layout line), fix the `validate` ordering (verify:format-
coverage now runs before validate:core) in AGENTS.md and README, and
update the quoted globs to the uniform *.{ts,tsx,mts,cts,js,jsx,mjs,cjs} /
test-servers *.{ts,tsx,mts,cts}.
npm run ci green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
All three round-4 findings addressed (0fa0f1b): 2 — guard trusted an unwired 3 — comment claimed App.tsx was the only ungated src file: Added 1 — doc staleness: Fixed all four points — documented Also noted your CI-timing caveat: the run for this commit is green (coverage gate incl. the new Re-requesting review. |
|
@claude review |
|
Claude finished @cliffhall's task in 3m 28s —— View job Review — PR #1792 (round 5)
Verdict: LGTM — ship it. All three round-4 findings are addressed, and I re-ran the exploit rather than trusting the claim: the round-4 blind spot is genuinely closed. Two small findings below (one eslint/config asymmetry, one doc overstatement) plus one residual guard edge — none blocking.
Round-4 findings — re-verifiedFinding 2 (guard trusted an unwired Previously this exited 0. The guard now asserts "checked by CI", not "a glob exists." On the clean tree it still passes — 887/887. ✅ I also traced the
Finding 3 (incomplete exclusion list) — closed. Finding 1 (doc staleness) — all four points closed. Verified each against the actual scripts: Also re-verified: Findings1.
"lint:shared": "eslint \"test-servers/src/**/*.{ts,tsx,mts,cts}\" vitest.shared.mts eslint.config.js"but files: ["test-servers/src/**/*.ts", "vitest.shared.mts", "eslint.config.js"],So a future 2. AGENTS.md now claims every format glob uses the uniform extension set — two don't (nit). AGENTS.md:216 reads:
But 3. Residual guard edge, one level up from finding 2 (optional; the realistic case is now covered).
So web's whole surface can be dropped from the root chain and the guard still reports full coverage. This is much less likely than the round-4 case (dropping a whole client from Notes (no action needed)
Verification limitsThis checkout has no |
… sync)
- verify-format-coverage: assert the root `validate` chain invokes each
client's `validate` (cd <dir> && npm run validate), closing the last
reachability edge — a client dropped from the root chain now fails the
guard even though its own globs still exist. Negative-tested.
- eslint.config.js: widen the shared `files` block to
test-servers/src/**/*.{ts,tsx,mts,cts} to match the widened lint:shared
glob, so a future .mts/.cts there is lint-gated, not just prettier-gated.
- AGENTS.md: scope the "uniform extension set" claim to client globs
(core stays {ts,tsx}, shared {ts,tsx,mts,cts}), with verify:format-coverage
as the backstop — removing the self-contradiction with the line below.
npm run ci green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
All three round-5 findings fixed (332eb61): 1 — 2 — AGENTS.md overstated "every format glob uniform": Scoped the claim to client globs and noted 3 — residual guard edge (root → client reachability): Added the assertion — the guard now verifies the root
|
|
@claude review |
|
Claude finished @cliffhall's task in 2m 59s —— View job Review — PR #1792 (round 6)
Verdict: LGTM — ship it. All three round-5 findings are closed, and I re-ran the exploits rather than reading the diff and trusting it: the root→client assertion genuinely fires. One residual (symmetric to the one just fixed, on the write side) that I confirmed by experiment — optional, and not a reason to hold this PR after six rounds.
Round-5 findings — re-verified empiricallyFinding 3 (root → client reachability) — closed. Exploit re-run: Previously this exited 0. And the round-4 exploit still fails correctly (renaming web's I also traced Finding 1 ( Finding 2 (self-contradicting AGENTS.md claim) — closed. Line 217 now scopes the uniform set to client globs, names Findings1. The guard checks only the Rounds 4–5 hardened the check side into a real invariant, but The consequence is a DX trap rather than a coverage hole: CI still flags the file, but 2. The lint side has no equivalent guard, and the r5 fix was a hand-maintained mirror (note, no action). Finding 1 above's fix in 3.
Notes (no action needed)
Verification limitsNo |
|
Thanks for six rounds. Round 6 verified all round-5 fixes by re-running the exploits — appreciate that. The remaining items are all follow-up/no-action by your own framing:
Considering the review converged — three consecutive "ship it" verdicts (r4/r5/r6), no outstanding change-requests on this PR, and every prior finding re-verified closed. |
Closes #1785
Closes #1787
Closes #1789
Closes #1790
Closes #1767
Bundles five small, related tidy / quality-gate items into one PR (per request, to reduce ticket sprawl). All prettier-only / gate-coverage / dead-code — no runtime behavior change.
npm run ciis green.What's in it
#1785 — remove dead
src/types/navigation.tsInspectorTabhad zero importers and had drifted from the liveInspectorTabIdinutils/inspectorTabs.ts(different case + missingNetwork). Deleted.src/types/now holds only ambient.d.tsstubs, making the "#1776 no-domain-types-in-src/types/" framing exactly true.#1787 — gate
src/hooks/**+ test the two untested hookssrc/hooks/was not in the web coverageinclude, so its four modules were outside the ≥90 gate silently, and two had no tests. Addedsrc/hooks/**/*.{ts,tsx}toincludeand wrote dedicated tests:useServerJsonImport— 94.4% branches, 100% lines/functions/statementsuseImportClientConfig— 90.6% branches, 100% lines/functions/statements#1789 — format-gate the remaining ungated first-party TS/JS
clients/{cli,tui,launcher}format/format:checkto include their top-level configs (*.{ts,js}/*.{ts,tsx,js}), matching whatclients/webdoes; also widenedclients/webto include.storybookandclients/launcherto include its nestedscripts/(the*.top-level glob is non-recursive, so nested dirs are named explicitly).format:shared/format:check:sharedcoveringtest-servers/src/**,vitest.shared.mts, and the repo-rooteslint.config.js.#1790 — pin prettier exactly
Dropped the
^3.8.1caret for an exact3.8.4in all fivepackage.jsons so the gate's verdict can't shift with an in-range patch bump (3.9.x reformats 10 already-gated files). Lockfiles synced — prettier-only, verified no other dep changed.#1767 — root-file format and lint gate
Its web-
server/bullet shipped in #1788; its root-files bullet is closed here — both prettier (format:shared) and eslint (lint:shared, via a secondfilesblock in the rooteslint.config.jsscoped to Node globals). Its third bullet — cli/tui__tests__typecheck — surfaces 76 type errors (mostly partial-mock casts) and is materially larger, so it's split out to #1791 rather than bloating this tidy bundle.Verification
npm run cigreen (validate → coverage ≥90 per-file gate → verify:build-gate → smoke → Storybook, 460 tests). The newly-covered files wereprettier --write-normalized (pure formatting).🤖 Generated with Claude Code