16 KiB
Test Coverage Gap Report
1. Methodology
The repo's vitest.config.ts declares a coverage block with provider v8, but the corresponding package @vitest/coverage-v8 is not in node_modules. Running npx vitest run --coverage returns:
MISSING DEPENDENCY Cannot find dependency '@vitest/coverage-v8'
Attempting npx --package=@vitest/coverage-v8 -- vitest run --coverage fails because the local vitest install can't resolve a package outside its own node_modules. The PM constraint "DO NOT modify package.json" forbids the obvious fix (npm install --no-save -D @vitest/coverage-v8 would persist a lockfile change).
Fallback methodology used here: static source-to-test mapping via filename stem matching, with test-file-LoC-to-source-file-LoC ratio as a coverage proxy.
For each .ts file in packages/agent/src/ and packages/core/src/ (excluding .d.ts), the scan:
- Counts non-comment, non-empty LoC (
srcLoc) - Searches
tests/(recursive) for*.test.tsfiles matching one of:<stem>.test.tsexact match<dir-parts-joined-with-dash>-<stem>.test.ts(waggle-os convention:long-task-checkpoint.test.tsforsrc/long-task/checkpoint.ts)- Loose match: filename contains stem AND path contains all dir parts
- Sums matched test files' LoC (
testLoc) - Computes
ratio = testLoc / srcLoc - Estimates coverage bucket: 0 (no tests) /
<50(ratio < 0.3) /50-80(0.3–0.7) />=80(>= 0.7) - Classifies priority:
- P1: critical agent-loop / substrate path (agent-loop, retrieval-agent-loop, orchestrator, personas, behavioral-spec, output-normalize, run-meta, prompt-shapes/, long-task/, mind/* core, vault, harvest pipeline, injection-scanner, cost-tracker, tool-filter, permissions)
- P3: barrel / type-only (
index.ts,types.ts,*-types.ts,constants.ts) - P2: everything else
Caveats (honest disclosure):
- The heuristic does NOT measure actual line coverage. A test file that imports the source but exercises only one function will still register a high
testLoc/srcLocratio and read as "well-covered." - The heuristic FALSE-POSITIVES on multi-source-per-test conventions:
tests/prompt-shapes.test.ts(a single 1100-LoC test file covering all 7 prompt-shape source files) only matchesprompt-shapes/types.tsvia stem, so the other 6 prompt-shape files report as "zero tests." A correction pass below resolves the most obvious cases. - Pure-data files (
persona-data.ts, declarative arrays) are flagged as zero-test even when their data is exercised indirectly through the logic file's tests (personas.test.ts). index.tsbarrel files are typed as P3 and excluded from priority analysis.
Net interpretation: the report is a directional signal, not a measurement. P1 gaps surfaced by this heuristic should be cross-checked manually before booking work. P2/P3 gaps are useful for backlog priority discussion.
2. Per-package summary
| Package | Modules total | With tests | Without tests | Est. ≥80% | Est. <80% | Rough cov% by LoC |
|---|---|---|---|---|---|---|
packages/agent |
156 | 100 | 56 | 74 | 82 | 46% |
packages/core |
64 | 37 | 27 | 32 | 32 | 56% |
The <80% count is inflated by the false-positive class noted above. Genuine gaps after correction: see §3.
Distribution of <80% modules across priority buckets (heuristic, pre-correction):
- P1: 15 (mostly false positives — see §3 correction pass)
- P2: 93 (real signal: connectors + heavy utility files)
- P3: 6 (barrel files + types — out of scope per §5)
3. Module-by-module gap list
P1 — critical path (correction pass applied)
The heuristic flagged 15 P1 modules. Cross-checking against the actual test directory shows most are covered through multi-source-per-test files. The corrected list:
| Module | LoC | Heuristic verdict | Corrected status | Action |
|---|---|---|---|---|
agent/persona-data.ts |
911 | 0 tests | covered indirectly by personas.test.ts (PERSONAS array iterated via logic file). Pure data; not directly testable in isolation. |
None — false positive |
agent/retrieval-agent-loop.ts |
828 | ratio 0.55 / 50-80 |
Likely well-covered: retrieval-agent-loop.test.ts (455 LoC, 25 tests) + long-task-loop-integration.test.ts (847 LoC, 34 tests including Phase 4.7 assertion suite). Combined test LoC ≈ 1300 against 828 src LoC → ratio ≈1.6. |
None — heuristic missed cross-file integration test |
agent/behavioral-spec.ts |
338 | ratio 0.19 / <50 |
Real gap. Only behavioral-spec-overrides.test.ts (65 LoC) tests the override mechanism. The main BEHAVIORAL_SPEC constant + section structure + COMPACTION_PROMPT export aren't directly verified by a dedicated suite. Mitigated by indirect testing through orchestrator, but no lock-in test. |
Sprint 12 candidate: add a structural-shape test for the spec (sections present, COMPACTION_PROMPT non-empty, etc.) — small effort, high pin-value |
core/harvest/pipeline.ts |
283 | ratio 0.53 / 50-80 |
pipeline-injection.test.ts (66 LoC) + pipeline-progress.test.ts (83 LoC) cover injection scanning + progress reporting. End-to-end harvest flow not exercised. |
Sprint 12 candidate: end-to-end harvest test against fixture data |
agent/cost-tracker.ts |
123 | ratio 0.40 / <50 |
cost-tracker.test.ts exists but thin. CostTracker class methods have partial coverage. |
Sprint 12 candidate: complete CostTracker method matrix (record / get / reset / aggregate) |
agent/prompt-shapes/selector.ts |
116 | 0 tests | covered by prompt-shapes.test.ts (1100+ LoC, 65 tests including selector dispatch tests). |
None — false positive |
agent/prompt-shapes/claude.ts |
90 | 0 tests | covered by prompt-shapes.test.ts |
None — false positive |
agent/prompt-shapes/types.ts |
83 | 0 tests | Type-only module; no testable runtime behavior. Indirectly verified by tsc strict on consumers. | None — out of scope per §5 |
agent/prompt-shapes/qwen-thinking.ts |
81 | 0 tests | covered by prompt-shapes.test.ts |
None — false positive |
agent/prompt-shapes/qwen-non-thinking.ts |
79 | 0 tests | covered by prompt-shapes.test.ts |
None — false positive |
agent/prompt-shapes/generic-simple.ts |
73 | 0 tests | covered by prompt-shapes.test.ts |
None — false positive |
core/injection-scanner.ts |
71 | 0 tests | Real gap. agent/src/injection-scanner.ts has a dedicated test (agent/tests/injection-scanner.test.ts); the duplicate core/src/injection-scanner.ts does NOT have a core/tests/injection-scanner.test.ts. Substantively the same scanning logic. Either dedupe (Sprint 12 cleanup candidate) or add core-side test. |
Sprint 12 candidate: investigate dedup vs add test |
agent/prompt-shapes/gpt.ts |
62 | 0 tests | covered by prompt-shapes.test.ts |
None — false positive |
agent/prompt-shapes/index.ts |
44 | 0 tests | Barrel. P3. | None — out of scope |
agent/custom-personas.ts |
40 | 0 tests | Borderline gap. loadCustomPersonas() reads from disk; not exercised by personas.test.ts (which uses static PERSONAS). Small file. |
Sprint 12 candidate: minimal test for loadCustomPersonas with fixture |
Genuine P1 gaps after correction: 4 modules (behavioral-spec, harvest/pipeline, cost-tracker, custom-personas) plus 1 dedup-or-test investigation (core/injection-scanner). All small / focused.
P2 — supporting (top 25 by LoC)
These are real gap signals. Connector files are dominant — a known cluster of test debt that has accumulated as new connectors were added without test scaffolding.
| Module | LoC | Coverage est. | Notes |
|---|---|---|---|
agent/system-tools.ts |
831 | 50-80 |
2 test files (system-tools + bash-sandboxing). Big surface; partial. |
agent/skill-tools.ts |
777 | <50 |
1 test file. 28 tools defined; thin coverage of CRUD paths. |
agent/evolve-schema.ts |
734 | 50-80 |
evolve-schema.test.ts covers main path; mutation kinds may be partial. |
agent/document-tools.ts |
559 | <50 |
Document generation (docx/pdf/pptx) thin on output validation. |
agent/commands/workflow-commands.ts |
537 | 50-80 |
Command-registry handlers; partial. |
agent/lsp-tools.ts |
406 | <50 |
LSP integration; partial. |
agent/workflow-harness.ts |
406 | 0 tests | Multi-phase harness; not tested directly. Real gap. |
core/file-store.ts |
398 | 50-80 |
File-store abstraction. |
core/mind/embedding-provider.ts |
386 | <50 |
Embedding-provider switching (api / inprocess / litellm / ollama); likely thin. |
agent/subagent-tools.ts |
333 | 50-80 |
Subagent spawn/coord; partial. |
agent/workflow-tools.ts |
319 | 50-80 |
Workflow CRUD tools. |
agent/compliance-pdf.ts |
315 | 50-80 |
EU AI Act compliance PDF rendering. |
agent/browser-tools.ts |
306 | 50-80 |
Playwright browser tools. |
agent/connectors/obsidian-connector.ts |
300 | 0 tests | Connector cluster, no tests. |
core/harvest/claude-code-adapter.ts |
300 | 0 tests | Harvest adapter for Claude Code. |
agent/cross-workspace-tools.ts |
294 | 0 tests | Cross-workspace file ops. |
agent/git-tools.ts |
274 | 50-80 |
Git operations. |
core/telemetry.ts |
273 | 50-80 |
Telemetry pipeline. |
core/cron-store.ts |
270 | 50-80 |
Cron job persistence. |
agent/connectors/gdrive-connector.ts |
266 | 0 tests | Connector cluster. |
agent/connectors/notion-connector.ts |
262 | 0 tests | Connector cluster. |
agent/connector-search.ts |
248 | 50-80 |
Connector search (also exercised by harvest pipeline tests indirectly). |
agent/connectors/confluence-connector.ts |
247 | 0 tests | Connector cluster. |
agent/connectors/trello-connector.ts |
247 | 0 tests | Connector cluster. |
agent/connectors/outlook-connector.ts |
244 | 0 tests | Connector cluster. |
Connector cluster: 30+ connector files in packages/agent/src/connectors/ are each ~100-300 LoC, mostly without dedicated tests. They share a common base class (BaseConnector) which IS tested (connector-sdk.test.ts). Argument for low-priority: connectors are mostly thin adapters around external APIs; integration testing each one requires real auth and external services. Argument for higher-priority: pre-launch product surface; P1 customer impact if a connector breaks silently.
P3 — barrel / type-only
Out of scope per §5. Listed for completeness:
| Module | LoC | Reason |
|---|---|---|
agent/index.ts |
409 | Barrel re-exports |
core/compliance/types.ts |
161 | Type-only |
core/harvest/types.ts |
103 | Type-only |
agent/connectors/index.ts |
30 | Barrel |
core/harvest/index.ts |
14 | Barrel |
core/compliance/index.ts |
5 | Barrel |
4. Recommended Sprint 12 additions
Small focused list — not a wholesale test-debt cleanup. The 23-item Sprint 12 backlog from Phase 4.4/4.5 already exists; adding ~8 high-value test items here would bring Sprint 12 to ~31 items, still tractable.
P1 — critical path test gaps (5 items, ~12-16 hours):
agent/behavioral-spec.ts— structural-shape test (sections present, COMPACTION_PROMPT non-empty, BEHAVIORAL_SPEC_SECTIONS export consistent). Estimate: 2 hours.core/injection-scanner.ts— investigate dedup vs add test againstagent/injection-scanner.ts. Estimate: 1-2 hours (most of which is decision, not coding).core/harvest/pipeline.ts— end-to-end harvest test against fixture data covering at least one adapter (chatgpt or claude-code). Estimate: 4 hours.agent/cost-tracker.ts— completeCostTrackermethod matrix. Estimate: 2 hours.agent/custom-personas.ts—loadCustomPersonastest with fixture directory. Estimate: 2 hours.
P2 — biggest real gaps (top 3 by impact, ~16-20 hours):
agent/workflow-harness.ts—createHarnessRun/advancePhase/canRetrynot tested. 406 LoC of orchestration code. Estimate: 6 hours.agent/skill-tools.ts— round-trip tests forcreate_skill+discover_skills+auto_extract_skills. 777 LoC; current coverage thin. Estimate: 6 hours.agent/document-tools.ts— output-shape validation tests for docx/pdf/pptx generation. 559 LoC. Estimate: 4 hours.
Connector cluster — discuss separately: The 6+ untested connector files (gdrive / obsidian / notion / confluence / trello / outlook + ~25 more) form a coherent gap. PM recommendation needed on whether to tackle as a single Sprint 12 work-item or spread across sprints. Each connector is ~100-300 LoC and ~3-5 hours to test against mocked HTTP. If all 30+ connectors → ~90-150 hours. Large effort; likely deferred to a dedicated "connector-test-debt" sprint rather than bundled into Sprint 12 cleanup.
5. Out-of-scope notes
The following modules are correctly NOT booked for test additions:
- Type-only files (
prompt-shapes/types.ts,compliance/types.ts,harvest/types.ts): no runtime behavior; tsc strict on consumers verifies type correctness. - Barrel files (
index.tsat every level): re-exports only; tested transitively when consumers import them. - Persona data array (
persona-data.ts, 911 LoC): pure declarative data; iterated throughpersonas.test.tsvia the logic file. - Generated/legacy connectors if any exist (none confirmed in this audit).
- Files with multi-source-per-test coverage:
prompt-shapes/*.ts(covered byprompt-shapes.test.ts), thepersonas.test.tsfamily. The static heuristic mis-flags these but they have substantive coverage through their shared test files.
6. Audit chain
| Item | Value |
|---|---|
| Branch HEAD | c9bda3d (Phase 4.7, unchanged) |
| Coverage tool | NOT installed (@vitest/coverage-v8 absent); fallback static heuristic used |
| Scan script | D:\Projects\waggle-os\tmp\coverage-gap-scan.mjs |
| Scan output | D:\Projects\waggle-os\tmp\coverage-gap-output.json |
| Modules scanned | 220 (156 agent + 64 core) |
| Modules flagged <80% (heuristic) | 114 (82 agent + 32 core) |
| Genuine P1 gaps after correction | 4-5 (behavioral-spec / harvest pipeline / cost-tracker / custom-personas / core injection-scanner dedup-or-test) |
| Genuine P2 gaps prioritized | top 3 (workflow-harness / skill-tools / document-tools) |
| Connector cluster | flagged for separate PM decision (30+ files, large effort) |
| Cost | $0 |
| Code modified | 0 |
| Tests added | 0 |
7. PM ratification asks
- Accept the heuristic methodology disclaimer — true coverage instrumentation requires installing
@vitest/coverage-v8which violates the package.json constraint. Static src→test mapping is the next-best signal but has known false-positive class. - Authorize a one-time install of
@vitest/coverage-v8for a future precise-measurement pass? (Optional follow-up; if approved would yield definitive numbers but requires lockfile change.) - Add the 8 recommended Sprint 12 items (5 P1 + 3 P2-top) to the existing 23-item Sprint 12 backlog → total Sprint 12 = ~31 items?
- Decide separately on the connector cluster — single Sprint 12 work-item (~90-150 hours, dedicated focus) vs distributed across multiple sprints vs deferred to post-launch?
End of test coverage gap report. Resuming Phase 5 standby.