[#199] chore: resolve audit findings T1-T10 (tech-debt ledger)#311
Conversation
- ci.yml: drop `|| echo` on ts:check/build/lint (fail loudly) - knowledge-hub: `vitest || check:links` -> `&&` (both real gates), drop `--coverage || true` - content-ops: adm-zip + @types/adm-zip -> catalog: - Task: T1 (P0.1 + P0.2 + P1.1) Refs: #199
- copy-file.ts: single-file copy path - copy-directory.ts: non-transform directory copy path - copy-directory-transforms.ts: flatten/prefix transform copy path - copy-types.ts: shared CopyPathOpsResult/TransformOpts - copyPathOps.ts: slim orchestrator, re-exports public API (unchanged) - Public API (copyPathOps, copyDirectoryWithTransforms, CopyPathOpsResult) preserved - Task: T4 (P0.5) Refs: #199
- Replace `Partial<...>` MoveCtx + ctx.source!/ctx.normSource! with a total context type built once after setup (all fields required) - Discriminated union not applicable: branch unknown at ctx-build time - Task: T6 (P1.3) Refs: #199
- Convert 13 static methods to module-level named functions; private statics become module-private functions (no behavior change) - extractLinks/detectLinkStyle collapse duplicate standalone wrappers - applyReplacements/processFileWithLinks re-exported from replacement-applier - Update callers: replacement-applier, replacement-generator (aliased), link-rewriter, link-batch-processor; barrels src/index + markdown/index - Update tests to named imports (LinkProcessor was content-ops-internal) - Task: T3 (P0.4) Refs: #199
- in-memory-fs-state.ts: shared mutable state + path primitives - in-memory-fs-seed.ts: constructor seeding - in-memory-fs-read.ts / in-memory-fs-write.ts: operation groups - in-memory-fs.ts: thin InMemoryFileSystemService delegating to the above - Public API unchanged; test's private resolvePath access repointed to state - Task: T9 (P2.3) Refs: #199
- brand: 80% global thresholds (measures 84.5% with tested dev harness) - website: realistic baseline floors (9/9/40/60), not 80% — Playwright-tested Next.js app; documented via ADL 2026-07-12-website-coverage-baseline - both: coverage block extends coverageConfigDefaults.exclude + json-summary - reports/coverage-baseline.json: committed baseline for trend tracking (P1.4) - Task: T5 (P1.2 + P1.4) Refs: #199
- add jscpd v5 (root dev dep) + .jscpd.json (threshold 5%, ts/tsx, src-scoped) - `dup:check` script (jscpd apps packages) appended to quality-gate - current duplication ~1.4% lines / ~2.2% tokens (17 clones) — well under gate - note jscpd in tech-stack.md - Task: T10 (P2.4) Refs: #199
- 11 showcase sections + Header moved to dev/sections/*.tsx - shared helpers (Section/LogoVariant/ColorSwatch/TypoBlock/UtilityCard) in dev/sections/primitives.tsx; barrel dev/sections/index.ts - App.tsx now a slim shell (456 -> 51 LOC); dev/App.test.tsx unchanged, green - brand coverage 85% (still >= 80%) - Task: T8 (P2.2) Refs: #199
- extract shared fixtures to cli-e2e-helpers.ts - cli.e2e.test.ts (1507 LOC) -> 7 focused files: validate-config, install, update, link, errors, packaging, kb-validate - behavior-preserving; full pair-cli suite green (869 tests, 77 files) - Task: T2 (P0.3) Refs: #199
Code Review — PR #311Review Information
Review SummaryOverall Assessment
Key ChangesResolves all 10 catalogued audit findings (T1–T10) in one PR: silent-failure removal (T1), monster-e2e split (T2), Business ValueClears the tracked debt so #199 can close as the single source of truth. No functional/product surface changed. Independent Verification (gates re-run on the pushed head)
The behavior-preservation claim for the T3/T4/T6/T9 refactors is corroborated: content-ops public barrels ( Acceptance Criteria
Detailed Review CommentsPositive
Minor Issues
Risk Assessment
DecisionApproved with Comments. No critical or major issues; all AC met (website-80% consciously deferred via ADL); all quality gates independently verified green. The listed Minor items are non-blocking cleanups. 🤖 Independent review generated with Claude Code |
…le DR doc) - jscpd -> workspace catalog + catalog: ref in root (kills catalog drift) - CI: add hygiene:check / docs:staleness / dup:check discrete steps - design-rules.md: reframe DR-1/DR-2/DR-3 evidence + migration plan as historical (all originating instances resolved in #199) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remediation — round 1 (commit
|
Code Review — PR #311 (Re-review, round 2)Review Information
Review SummaryOverall Assessment
Key Changes SummaryRe-review of the remediation commit Prior Findings — Resolution Verification
Independent Verification (re-confirmed on
|
…sion CI now runs test:coverage for brand+website after the test step, so their vitest coverage.thresholds actually gate PRs instead of biting only on explicit runs. Amends the 2026-07-12 ADL to record the reversal per explicit user direction.
Story #199's T1-T10 batched into a single PR was flagged by review as a batching deviation; user confirmed this is intentional and should be the default. Adds the convention to way-of-working.md (consulted convention) and an ADL recording the why (historical record).
…review) ADL exemption for *.e2e.test.ts co-location was descriptive, not mechanically verifiable. Add 3 checkable criteria (named after a real flow, additive not sole coverage, genuine cross-module interaction) to the ADL and mirror into file-structure.md (root + dataset copies).
…s (PR #311 review) Both were split (#199 T4/T9) into sibling files, but only one entry point is externally consumed in each case (copyPathOps / copyDirectoryWithTransforms; InMemoryFileSystemService). Group each split under its own folder with an index.ts barrel so the directory signals public surface vs internal collaborators: - content-ops/src/ops/copyPathOps.ts + copy-{file,directory, directory-transforms,types}.ts -> ops/copy/ + index.ts - content-ops/src/test-utils/in-memory-fs.ts + in-memory-fs-{state, read,write,seed}.ts -> test-utils/in-memory-fs/ + index.ts Public API unchanged (same import specifiers, now resolving through the folder). package.json's "./test-utils/in-memory-fs" subpath export updated to the new dist path. content-ops (618) + pair-cli (869) tests green.
…idelines (PR #311 review) KB guideline files ship to every adopting project via pair install/update; they must never cite this repo's own paths or issue numbers as "evidence" (meaningless/stale for external consumers). - design-rules.md: remove the 3 "Evidence (historical — #199)" paragraphs (DR-1/2/3) and the whole "Migration Plan" section (also now factually stale re: scan-mode removed by #224/#310); Recognition + Don't + Do already fully define each rule without a citation. Overview's rule enumeration updated accordingly. - Add DR-4 "Split Files Without a Barrel" (companion rule to this PR's ops/copy/ and test-utils/in-memory-fs/ folder-module refactors), generic illustrative snippets only, no repo citation. - shared-config-packages.md: genericize the apps/pair-cli, apps/website, packages/brand code-comment examples to placeholder project names (apps/api, apps/web, packages/ui-lib) so the guideline doesn't imply the reader's project has those directories. Repo-wide grep confirms these were the only two guideline files with this pattern.
…ps to module tests, consolidate to single cli.e2e.test.ts Per-test classification of the 7-file cli.e2e split found only 1/51 tests genuinely e2e (real cross-command state hand-off); the rest were single-module tests wearing e2e clothing. Deletes 35 exact/near duplicates, moves 15 genuine gaps into install/update/kb-validate handler.test.ts and registry/validation.test.ts, keeps the 1 genuine e2e test in a new cli.e2e.test.ts, and removes the now-unused cli-e2e-helpers.ts.
…-entry-point rule The PR #311 checkable-criteria amendment was satisfiable on paper without genuine cross-module flows, as proven by the pair-cli 7-file split it approved (only 1/51 tests were actually e2e). Replace it with the rule confirmed with the user: e2e defaults to one file per entry point; splitting requires the production code itself to be refactored into isolated modules with true unit tests, not just moved test files. Cites the #199 reorg as precedent.
…uideline The strategy-level e2e-testing guideline already said e2e should focus on critical paths, not every scenario, but didn't point to the concrete file-organization consequence (one file per entry point, split only with genuine module isolation) landed by this story's test reorg. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Remediation update — all 11 review comments now reflected in the pushed diffPushed Summary of what changed since
|
…oom sentinel (PR #311 review) Split copyPathOps.test.ts (5 describes, 1 file) into per-production-file tests: copy-file.test.ts, copy-directory.test.ts, copy-directory-transforms.test.ts; copyPathOps.test.ts keeps only its own dispatch-level concerns (absolute-path validation, source-existence check). Reuses existing createTestFileService helper to simplify repeated fs setup in the transforms file. Also removes the dead err.message.includes('boom') test-sentinel from copy-file.ts and copy-directory.ts — no test references it anymore, so the catch blocks now always wrap via createError.
… review) Split in-memory-fs.test.ts (16 describes, 1 file) into per-production-file tests: in-memory-fs-state.test.ts, in-memory-fs-read.test.ts, in-memory-fs-write.test.ts, in-memory-fs-seed.test.ts. in-memory-fs.test.ts keeps only the class's own constructor wiring, accessSync (no-op), and one end-to-end complex-scenario smoke test. Extracts test-fixtures.ts (createFs/DEFAULT_DIR) to remove the repeated moduleDir/workingDir='/app' boilerplate across the split files.
Summary
What Changed
Resolves all findings T1–T10 from the 2026-04-17 codebase audit in a single PR, per maintainer directive (overrides the issue's "incremental small PRs" wording). Includes the two non-trivial refactors T3 (LinkProcessor) and T4 (copyPathOps) inline — not split into separate cards.
Closes #199.
Why This Change
#199 is the audit resolution ledger. Clearing the catalogued debt in one pass lets the ledger be closed as the single source of truth, with no dangling audit doc and no card-per-finding pollution of the backlog.
Story Context
Story: #199 — Tech-debt resolution ledger (2026-04-17 audit). Parent epic #209 (Code Quality & Testing foundations). P1, XL.
Findings resolved (T1–T10)
ci.yml|| echodropped; knowledge-hubvitest || check:links→&&and dropped--coverage || true; content-opsadm-zip+@types/adm-zipmoved tocatalog:(drift fix)5afead2cli.e2e.test.tsmonster file (1507 LOC)cli-e2e-helpers.ts; full pair-cli suite green (869 tests)f671afcLinkProcessorstatic-only classe3fdbb6copyPathOpsgod-modulecopy-file/copy-directory/copy-directory-transforms/copy-types+ a slim orchestrator. Public API preserved4444fbcreports/coverage-baseline.json050dfd3MoveCtxmade a total type; droppedctx.source!. Discriminated union N/A (branch unknown at ctx-build time) — documented in codee1831e5:anyusage:anyinsrc; the audit's match was a string literal. Noted for the ledgerdev/App.tsxoversizeddev/sections/*+ primitives + barrel;App.tsx456 → 51 LOC;dev/App.test.tsxgreen050dfd3..range)in-memory-fstest util oversizedresolvePathtest access repointed to state64aa83ddup:check+.jscpd.json(threshold 5%, current ~1.42%); noted intech-stack.md0327ef6Key decisions (reviewer: these are the load-bearing calls)
reports/coverage-baseline.jsonand rationale in ADL.pair/adoption/decision-log/2026-07-12-website-coverage-baseline.md. brand stays at 80% (its dev harness is unit-tested, measures ~85%).Testing
Not run in this gate: Playwright ct/e2e (requires
playwright install chromium) — out of scope for these changes.Reviewer Guide
src/index.ts,src/markdown/index.ts) is unchanged after T3/T4; (b) the website coverage baseline + ADL is a reasonable call; (c)ci.ymlno longer swallows failures.Follow-up
🤖 Generated with Claude Code