Summary
Test-suite-level housekeeping, all from the 2026-05-17 full-repo review. None are individually critical; bundled because they share one PR's worth of structural cleanup.
Helpers to extract
packages/engine/src/scan/orchestrator.test.ts:55, 75, 90, 108, 138, 164, 197, 231 — const writes: string[] = [] declared in 8 tests but never asserted on; exists only to silence the logger. Extract silentLogger() from a test helper, or pass a noop writer.
packages/engine/src/api/server.test.ts:40-50, 78-82, 129-134, 159-164, 611-616, 732-737, 898-903, 1067-1072, 1159-1164, 2095-2100 — for (let i = 0; i < 50; i++) { fetch...; await sleep(50); } polling loop duplicated in 10+ tests. Extract waitForScanStatus(handle, scanId, target, opts) so tests express intent rather than mechanism, with a deterministic timeout/error.
packages/engine/src/scan/walker.test.ts:138, 158, 176 — for await (const _ of walk(...)) { void _ } drain pattern duplicated three times. Small await drain(asyncIterable) helper.
packages/engine/src/organize/applier.test.ts:14-17, move-cross-drive.test.ts:14-17, undo.test.ts:4-7 — three vi.mock(...) calls that just re-export the actual module so a later vi.spyOn can override. Worth a single inline comment on the first occurrence explaining the Vitest-specific idiom; without it the next reader will think these mocks do something.
Missing test cases
packages/engine/src/rules/matcher.test.ts — no test exercises backslash paths or Windows-cased **/Downloads/** glob. Add one. (Pairs with M20; can ship as part of this issue or as part of the M20 fix.)
packages/engine/src/rules/template.test.ts — no test for filenames containing / or \ (legal on Linux for / if escaped in stored names; NTFS has separate constraints). Add hostile-filename tests.
packages/engine/src/throttle/scheduler.test.ts — no test for an hour-boundary crossing inside a single start()/advanceTimersByTime run. (Pairs with M15; can ship there.)
packages/engine/src/scan/metadata-video.test.ts:48-80 — writes a #!/bin/sh shim with mode 0o755; fails on Windows (README primary target). Guard with it.skipIf(process.platform === 'win32') or provide a .bat shim.
packages/engine/src/scan/walker.test.ts:76-83 — "reports size and mtime" test asserts inside for await; with zero entries it passes with no assertions. Collect into array, assert length first.
Background
From the 2026-05-17 multi-agent full-repo review. Per standards/test-patterns.md: "Verbose/slop tests" and "Tests that don't assert" — each item picks up one of those rules.
Acceptance criteria
Helpers
Tests
Files affected (likely)
packages/engine/src/test-helpers/ (new directory)
packages/engine/src/scan/orchestrator.test.ts
packages/engine/src/api/server.test.ts
packages/engine/src/scan/walker.test.ts
packages/engine/src/rules/matcher.test.ts
packages/engine/src/rules/template.test.ts
packages/engine/src/throttle/scheduler.test.ts
packages/engine/src/scan/metadata-video.test.ts
Suggested approach
Helpers first (drop-in replacements, no behavior change), then missing-test cases. The Windows-skip / it.skipIf cases are smallest.
Out of scope
- Adopting a different test framework
- Increasing coverage to a target threshold
References
- Standards:
standards/test-patterns.md
- Code: paths above
Summary
Test-suite-level housekeeping, all from the 2026-05-17 full-repo review. None are individually critical; bundled because they share one PR's worth of structural cleanup.
Helpers to extract
packages/engine/src/scan/orchestrator.test.ts:55, 75, 90, 108, 138, 164, 197, 231—const writes: string[] = []declared in 8 tests but never asserted on; exists only to silence the logger. ExtractsilentLogger()from a test helper, or pass a noop writer.packages/engine/src/api/server.test.ts:40-50, 78-82, 129-134, 159-164, 611-616, 732-737, 898-903, 1067-1072, 1159-1164, 2095-2100—for (let i = 0; i < 50; i++) { fetch...; await sleep(50); }polling loop duplicated in 10+ tests. ExtractwaitForScanStatus(handle, scanId, target, opts)so tests express intent rather than mechanism, with a deterministic timeout/error.packages/engine/src/scan/walker.test.ts:138, 158, 176—for await (const _ of walk(...)) { void _ }drain pattern duplicated three times. Smallawait drain(asyncIterable)helper.packages/engine/src/organize/applier.test.ts:14-17,move-cross-drive.test.ts:14-17,undo.test.ts:4-7— threevi.mock(...)calls that just re-export the actual module so a latervi.spyOncan override. Worth a single inline comment on the first occurrence explaining the Vitest-specific idiom; without it the next reader will think these mocks do something.Missing test cases
packages/engine/src/rules/matcher.test.ts— no test exercises backslash paths or Windows-cased**/Downloads/**glob. Add one. (Pairs with M20; can ship as part of this issue or as part of the M20 fix.)packages/engine/src/rules/template.test.ts— no test for filenames containing/or\(legal on Linux for/if escaped in stored names; NTFS has separate constraints). Add hostile-filename tests.packages/engine/src/throttle/scheduler.test.ts— no test for an hour-boundary crossing inside a singlestart()/advanceTimersByTimerun. (Pairs with M15; can ship there.)packages/engine/src/scan/metadata-video.test.ts:48-80— writes a#!/bin/shshim with mode0o755; fails on Windows (README primary target). Guard withit.skipIf(process.platform === 'win32')or provide a.batshim.packages/engine/src/scan/walker.test.ts:76-83— "reports size and mtime" test asserts insidefor await; with zero entries it passes with no assertions. Collect into array, assert length first.Background
From the 2026-05-17 multi-agent full-repo review. Per
standards/test-patterns.md: "Verbose/slop tests" and "Tests that don't assert" — each item picks up one of those rules.Acceptance criteria
Helpers
silentLogger()exported from a test-helpers module (e.g.,packages/engine/src/test-helpers/log.ts). Used inorchestrator.test.ts. Thewrites: string[] = []shim is deleted.waitForScanStatus(handle, scanId, target, opts?: { timeoutMs?: number, intervalMs?: number })exported from test-helpers. Throws a clear "timed out waiting for scan X to reach status Y after Z ms" error. Used everywhere the polling loop currently appears.drain(asyncIterable)helper. Used at the three sites.vi.mock(actual)site explaining the spy-prep idiom.Tests
matcher.test.ts.template.test.ts.scheduler.test.ts(if not covered by M15).metadata-video.test.ts.walker.test.ts:76-83collects entries into array and asserts length first.Files affected (likely)
packages/engine/src/test-helpers/(new directory)packages/engine/src/scan/orchestrator.test.tspackages/engine/src/api/server.test.tspackages/engine/src/scan/walker.test.tspackages/engine/src/rules/matcher.test.tspackages/engine/src/rules/template.test.tspackages/engine/src/throttle/scheduler.test.tspackages/engine/src/scan/metadata-video.test.tsSuggested approach
Helpers first (drop-in replacements, no behavior change), then missing-test cases. The Windows-skip /
it.skipIfcases are smallest.Out of scope
References
standards/test-patterns.md