Skip to content

Commit 86b7f69

Browse files
committed
docs(plan): tighten Bun-native API references (file read + perf note)
Plan correctly inherits the established Node vs Bun runtime split, but the single tracer-3 reference understated it. Now: - Tracer 3 cites `packaging.md § Node vs Bun` as the canonical pattern source instead of pointing at config.ts in passing. - Performance section calls out the actual lever — `Bun.file(path).json()` uses Bun's native JSON parser, materially faster than V8 `JSON.parse` on multi-MB Istanbul payloads (real coverage files for medium codebases routinely hit several MB). No new Bun-native API surfaces are added — the feature doesn't need globbing, file writes, spawn, or hashing beyond what the existing engines already use through their abstractions.
1 parent 3e796f8 commit 86b7f69

1 file changed

Lines changed: 2 additions & 2 deletions

File tree

docs/plans/coverage-ingestion.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@ Per [`tracer-bullets.mdc`](../../.cursor/rules/tracer-bullets.mdc) — vertical
110110
| --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
111111
| 1 | **Schema + bump** in `src/db.ts`. Add the `coverage` table DDL (natural-key PK per D6 — no FK to `symbols.id`); bump `SCHEMA_VERSION`; add `coverage` to the `query_baselines`-style "preserve across `--full`" exclusion in `dropAll()`. Add `idx_coverage_file_name`. New `meta` keys (`coverage_last_ingested_at` / `_path` / `_source`) need no DDL — `meta` is `(key, value)` already. Unit test (`src/db.test.ts`) inserts + reads back one row; verifies the table survives a `dropAll()` + `createSchema()` round-trip; verifies the orphan-cleanup DELETE removes rows whose `file_path` is no longer in `files`. | Table exists; survives `--full`; orphan sweep works. |
112112
| 2 | **Istanbul ingester engine** in `src/application/coverage-engine.ts` (new). `ingestCoverage({db, payload, projectRoot}) → {ingested, skipped, pruned_orphans, source}`. Pure: parses the Istanbul JSON shape (`{ [absPath]: {statementMap, s, fnMap, f, branchMap, b, path} }`); maps each statement to the **innermost** enclosing symbol via the SQL `(line_end - line_start) ASC LIMIT 1` projection (D7); upserts `coverage` keyed on `(file_path, name, line_start)`; writes the three meta keys; runs the orphan-cleanup DELETE. Computes `coverage_pct = total_statements > 0 ? hit / total * 100 : NULL`. Reuses `toProjectRelative` from `validate-engine` (D8). Unit tests cover: fresh ingest; re-ingest (UPSERT idempotence); unmatched file → `skipped.unmatched_files`; statement outside every symbol → `skipped.statements_no_symbol`; symbol with 0 statements → no row; nested closure → innermost wins; `total_statements = 0` → `coverage_pct IS NULL`; orphan cleanup after a file deletion. | Pure engine; deterministic upsert; no FS / process side effects beyond `db.run`. |
113-
| 3 | **CLI verb** `cli/cmd-ingest-coverage.ts` — parses `<path>` + `--source` (auto-detect default) + `--json`, reads the file (`Bun.file` on Bun, `readFile` on Node — same split as `config.ts`), dispatches to `coverage-engine`, renders the result. `main.ts` dispatcher gains the verb between existing entries. Help text in `bootstrap.ts` lists the new command. Unit tests cover: file-not-found, malformed JSON, source-mismatch error (`--source lcov` reserved for v1.x → v1 returns "lcov ingester not yet implemented"), `--json` envelope shape (including `pruned_orphans`). | `bun src/index.ts ingest-coverage fixtures/coverage/coverage-final.json` writes rows; `--help` lists the verb. |
113+
| 3 | **CLI verb** `cli/cmd-ingest-coverage.ts` — parses `<path>` + `--source` (auto-detect default) + `--json`, reads the JSON via the established runtime split (`Bun.file(path).json()` on Bun for the native-parser perf win on large coverage payloads; `readFile + JSON.parse` on Node) — see [`packaging.md § Node vs Bun`](../packaging.md#node-vs-bun) for the canonical pattern, mirrors `config.ts`. Dispatches to `coverage-engine`, renders the result. `main.ts` dispatcher gains the verb between existing entries. Help text in `bootstrap.ts` lists the new command. Unit tests cover: file-not-found, malformed JSON, source-mismatch error (`--source lcov` reserved for v1.x → v1 returns "lcov ingester not yet implemented"), `--json` envelope shape (including `pruned_orphans`). | `bun src/index.ts ingest-coverage fixtures/coverage/coverage-final.json` writes rows; `--help` lists the verb. |
114114
| 4 | **Fixture coverage data** — `fixtures/minimal/coverage/coverage-final.json` (small Istanbul shape covering the existing fixture symbols partially: e.g. `usePermissions` 100%, `legacyClient` 0%, `now` 50%). Golden query under `fixtures/golden/minimal/coverage-deprecated.json` exercises the killer recipe ("`@deprecated` symbols with `coverage_pct = 0`"). Adds the fixture row to `fixtures/minimal/README.md` "What's exercised" table. The pre-enriched `legacyClient` / `now` / `epochMs` deprecated symbols (PR #55) directly test the join axis — no new fixture symbols needed beyond the coverage JSON itself. | Golden recipe passes; documents how a real consumer wires `bun test --coverage` into the workflow. |
115115
| 5 | **Doc + agent rule + skill + changeset + plan deletion** — `docs/architecture.md` § Persistence wiring (new tables, ingester engine, CLI verb), `docs/glossary.md` (`coverage_pct`, `file_coverage`, "Istanbul JSON", "static coverage ingestion"), `.agents/rules/codemap.md` + `templates/agents/rules/codemap.md` (Rule 10 lockstep — new trigger pattern: "What's untested AND structurally dead?", new SQL example), skill SKILL.md `coverage` table row, README.md "What's exercised" + Use section. Minor changeset noting the `SCHEMA_VERSION` bump + the explicit re-ingest needed after upgrade. Plan deleted per `docs/README.md` Rule 3. | All docs consistent; agents see the new tables on next `codemap agents init`. |
116116

117117
## Performance considerations
118118

119-
- **Ingest cost** — one `JSON.parse` + linear scan of statement maps + one symbol-projection SQL per statement. Per-statement projection is the hot path; backed by `idx_symbols_file` it's an index-bounded lookup. No published benchmark yet — call out as a measurement target during tracer 2.
119+
- **Ingest cost** — one JSON parse + linear scan of statement maps + one symbol-projection SQL per statement. Per-statement projection is the hot path; backed by `idx_symbols_file` it's an index-bounded lookup. On Bun, the JSON parse uses `Bun.file(path).json()` (native parser, materially faster than V8 `JSON.parse` on multi-MB Istanbul payloads); on Node it's `readFile + JSON.parse`. No published benchmark yet — measurement target during tracer 2.
120120
- **Read cost**`coverage` is `WITHOUT ROWID` on `(file_path, name, line_start)`. The killer recipe's `LEFT JOIN coverage ON file_path AND name AND line_start` is a 3-column composite-PK lookup per row; `idx_coverage_file_name` covers the prefix.
121121
- **Storage** — three INTEGER + one REAL + two short TEXT per row; small. Real disk impact dominated by symbol count, not coverage shape.
122122
- **No background worker.** Ingest is single-pass; reindex is unaffected.

0 commit comments

Comments
 (0)