Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .agents/rules/codemap.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ alwaysApply: true

> **STOP.** Before you call Grep, Glob, SemanticSearch, or Read to answer a **structural** question about this repository — query the Codemap SQLite index first. This is not optional when the question matches a trigger pattern below.

A local database (default **`.codemap/index.db`**) indexes structure: symbols, imports, exports, components, dependencies, markers, CSS variables, CSS classes, CSS keyframes. The `.codemap/` directory holds every codemap-managed file (`index.db` + WAL/SHM, `audit-cache/`, project `recipes/`, `config.{ts,js,json}`, self-managed `.gitignore`); override the dir with `--state-dir <path>` or `CODEMAP_STATE_DIR`. The `.codemap/.gitignore` is **codemap-managed and reconciled on every boot** (`ensureStateGitignore`) — bumping its canonical body in a PR auto-applies on every consumer's next run.
A local database (default **`.codemap/index.db`**) indexes structure: symbols, imports, exports, components, dependencies, markers, CSS variables, CSS classes, CSS keyframes, and (after `bun src/index.ts ingest-coverage <path>`) static coverage from Istanbul JSON or LCOV. The `.codemap/` directory holds every codemap-managed file (`index.db` + WAL/SHM, `audit-cache/`, project `recipes/`, `config.{ts,js,json}`, self-managed `.gitignore`); override the dir with `--state-dir <path>` or `CODEMAP_STATE_DIR`. The `.codemap/.gitignore` is **codemap-managed and reconciled on every boot** (`ensureStateGitignore`) — bumping its canonical body in a PR auto-applies on every consumer's next run.

**This file** is for **developing Codemap** in this clone. **End users** of the published package get the agent rule from **`templates/agents/`** (via **`codemap agents init`**). **Generic defaults:** SQL and triggers stay project-agnostic — **edit** this rule for repo-specific paths and queries.

Expand All @@ -32,6 +32,7 @@ A local database (default **`.codemap/index.db`**) indexes structure: symbols, i
| Targeted read (metadata) | — | `bun src/index.ts show <name> [--kind <k>] [--in <path>] [--json]` — file:line + signature |
| Targeted read (source text) | — | `bun src/index.ts snippet <name> [--kind <k>] [--in <path>] [--json]` — same lookup + source from disk + stale flag |
| Impact (blast-radius walker) | — | `bun src/index.ts impact <target> [--direction up\|down\|both] [--depth N] [--via <b>] [--limit N] [--summary] [--json]` — replaces hand-composed `WITH RECURSIVE` queries |
| Coverage ingest | — | `bun src/index.ts ingest-coverage <path> [--json]` — Istanbul (`coverage-final.json`) or LCOV (`lcov.info`); format auto-detected. Joinable to `symbols` for "untested AND dead" queries. |
| SARIF / GH annotations | — | `bun src/index.ts query --recipe deprecated-symbols --format sarif` · `… --format annotations` |

**Recipe `actions`:** with **`--json`**, recipes that define an `actions` template append it to every row (kebab-case verb + description — e.g. `fan-out` → `review-coupling`). Under `--baseline`, actions attach to the **`added`** rows only. Inspect via **`--recipes-json`**. Ad-hoc SQL never carries actions.
Expand Down Expand Up @@ -109,6 +110,10 @@ If the question looks like any of these → use the index:
| "Is symbol X deprecated?" / "What does X do?" | `symbols` (`doc_comment`) |
| "What's `@internal` / `@beta` / `@alpha` / `@private`?" | `symbols.visibility` (parsed JSDoc tag — not regex) |
| "Who calls X?" / "What does X call?" | `calls` |
| "Is symbol X tested?" / "What's the coverage of file Y?" | `coverage` (after `ingest-coverage`) |
| "What's structurally dead AND untested?" | `--recipe untested-and-dead` |
| "Rank files by test coverage" | `--recipe files-by-coverage` |
| "Worst-covered exported functions" | `--recipe worst-covered-exports` |

## When Grep / Read IS appropriate

Expand Down Expand Up @@ -156,6 +161,8 @@ bun src/index.ts query --json "<SQL>"
| Who calls X? | `SELECT DISTINCT caller_name, file_path FROM calls WHERE callee_name = '...'` |
| What does X call? | `SELECT DISTINCT callee_name FROM calls WHERE caller_name = '...'` |
| Call hotspots | `SELECT callee_name, COUNT(*) as fan_in FROM calls GROUP BY callee_name ORDER BY fan_in DESC LIMIT 10` |
| Symbol coverage | `SELECT name, hit_statements, total_statements, coverage_pct FROM coverage WHERE file_path = '...'` |
| Untested + dead exports | `bun src/index.ts query --json --recipe untested-and-dead` |

**Use `DISTINCT`** on dependency and import queries — a file importing multiple specifiers from the same module produces duplicate rows.

Expand Down
15 changes: 15 additions & 0 deletions .agents/skills/codemap/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,21 @@ User-facing baselines saved by `codemap query --save-baseline`, replayed by `cod
| git_ref | TEXT | `git rev-parse HEAD` at save time, or NULL when not a git working tree |
| created_at | INTEGER | `Date.now()` at save time (epoch ms) |

### `coverage` — Statement coverage (user data, ingested via `codemap ingest-coverage`)

Static coverage from Istanbul JSON or LCOV. Joinable to `symbols` for "what's untested?" queries. **Survives `--full` and SCHEMA bumps** — intentionally absent from `dropAll()`. Empty until first ingest.

| Column | Type | Description |
| ---------------- | ------- | -------------------------------------------------------------------------------------------------------- |
| file_path | TEXT PK | Project-relative path; matches `symbols.file_path`. Forward-slashed (Windows paths normalised on ingest) |
| name | TEXT PK | Symbol name (matches `symbols.name`). Same `(file_path, name, line_start)` is unique by construction |
| line_start | INT PK | Symbol's starting line (matches `symbols.line_start`). Disambiguates re-declared names |
| coverage_pct | REAL | Percentage 0.0–100.0; `NULL` when `total_statements = 0` (zero-statement scope; not the same as 0%) |
| hit_statements | INTEGER | Count of statements with non-zero hit count after innermost-wins projection |
| total_statements | INTEGER | Count of statements that projected onto this symbol |

Three meta keys (`coverage_last_ingested_at` / `_path` / `_format`) record freshness — single ingest at a time, format is meta-level.

## Query patterns

### Basic lookups
Expand Down
36 changes: 36 additions & 0 deletions .changeset/coverage-ingestion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
"@stainless-code/codemap": minor
---

`codemap ingest-coverage <path>` — static coverage ingestion. Reads Istanbul JSON (`coverage-final.json`) or LCOV (`lcov.info`) into a new `coverage` table joinable to `symbols`, so structural queries can compose coverage filters in pure SQL — no runtime tracer, no paid coverage stack.

**Both formats land in v1** (Istanbul + LCOV) so every test runner is a first-class consumer on day one — `vitest --coverage`, `jest --coverage`, `c8`, `nyc` (Istanbul JSON), and `bun test --coverage` (LCOV) all work without waiting on a follow-up release.

**Bundled recipes (auto-discovered, no opt-in needed):**

- `untested-and-dead` — exported functions with no callers AND zero coverage; the killer recipe combining structural and runtime evidence axes.
- `files-by-coverage` — files ranked ascending by statement coverage.
- `worst-covered-exports` — top-20 worst-covered exported functions.

Each recipe ships a frontmatter `actions` block so agents see per-row follow-up hints in `--json` output.

**Schema:**

- New `coverage` table with natural-key PK `(file_path, name, line_start)` — intentionally not a FK to `symbols.id` so coverage rows survive the `symbols` drop-recreate cycle on every `--full` reindex.
- `idx_coverage_file_name` covers the typical join shape and the `GROUP BY file_path` scan used by the `files-by-coverage` recipe.
- Three new `meta` keys (`coverage_last_ingested_at` / `_path` / `_format`) record ingest freshness.
- `SCHEMA_VERSION` 5 → 6 — auto-rebuilds on next `codemap` run; the new table is empty until first `ingest-coverage` invocation. Subsequent bumps preserve coverage data via the `dropAll()` exclusion.

**CLI:**

```bash
codemap ingest-coverage coverage/coverage-final.json # Istanbul (auto-detected)
codemap ingest-coverage coverage/lcov.info # LCOV (auto-detected)
codemap ingest-coverage coverage --json # directory probe (errors if both files present)

codemap query --json --recipe untested-and-dead # the killer query
```

No `--source` flag — format is auto-detected from extension. No MCP / HTTP transport in v1 — coverage exposes as a SQL column, composable with every existing recipe and ad-hoc query through the existing `query` / `query_recipe` tools (no parallel surface).

Plan: PR #56 (merged). Implementation: this PR.
Loading
Loading