Skip to content

Commit 1323b49

Browse files
committed
feat(recipes): unresolved_import_blind_spot; ship deferred complements
unimported-exports third reason + evidence; alias-blind-spot fixture; MCP/glossary/rule parity for CRAP and evidence; no-defer convention in wave + harden-pr.
1 parent 98ffbf7 commit 1323b49

16 files changed

Lines changed: 195 additions & 107 deletions

.agents/skills/harden-pr/SKILL.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ Reviewers treat the anchor as contract. Findings that would violate it → **rep
8080

8181
**Fix:** bugs, missing tests, docs/changeset drift, lint/type/format, error-handling gaps, edge cases, **behavior-preserving refactors in touched files**, in-scope nits (naming, comment hygiene, cheap lint fixes).
8282

83-
**Report only:** redesign, new capabilities, semantic API changes, nits outside the diff, refactors unrelated to a flagged issue.
83+
**Report only:** redesign, semantic API changes, nits outside the diff, refactors unrelated to a flagged issue.
84+
85+
**Do not defer complements:** agent-surface parity (rule/skill/MCP), glossary/architecture/golden-queries contracts, script/golden tests for acceptance criteria, and cross-links named in the plan ship in the **same PR** — not "optional v2" or post-merge unless the plan **Out of scope** section explicitly excludes them.
8486

8587
## Reviewer roster
8688

@@ -122,7 +124,7 @@ loop:
122124
pass += 1
123125
goto loop
124126
capped:
125-
emit deferred-nits list
127+
emit deferred-nits list (each nit must cite plan Out of scope or cross-PR blocker — not "optional")
126128
done:
127129
if uncommitted fixes → git commit -m "harden: …"
128130
emit final report (include babysit one-liner if full mode)

docs/glossary.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ Opt-in FTS5 virtual table over file content (`tokenize='porter unicode61'`). Alw
151151

152152
Output mode rendering `{from, to, label?, kind?}` rows as a Mermaid `flowchart LR` diagram. Sibling of `--format sarif` / `--format annotations` in `application/output-formatters.ts`. **Bounded-input contract** (50-edge ceiling; `MERMAID_MAX_EDGES`) — unbounded inputs reject with a scope-suggestion error naming the recipe + count + scoping knobs (`LIMIT` / `--via` / `WHERE`). Auto-truncation explicitly out of scope (would be a verdict masquerading as output mode, violating the predicate-as-API moat). Recipes / ad-hoc SQL must alias columns to the `{from, to}` shape (e.g. `SELECT from_path AS "from", to_path AS "to" FROM dependencies LIMIT 50`).
153153

154+
### CRAP score / `high-crap-score` / `coverage_source` / `effective_coverage_pct`
155+
156+
Change Risk Anti-Patterns score per published formula: `CC² × (1 - effective_coverage/100)³ + CC` where `CC = symbols.complexity`. Bundled recipe **`high-crap-score`** ranks symbols at or above `min_crap` (default 30). **`effective_coverage_pct`** uses ingested **`coverage.coverage_pct`** when a row exists (**`coverage_source: measured`**), else graph-estimated tiers from test reachability (**`coverage_source: estimated`**: 85% direct test reference, 40% file reachable from tests via value-only **`dependencies`**, 0% otherwise). Heuristic only — not execution coverage; prefer **`codemap ingest-coverage`** before CI gates. Complements **`high-complexity-untested`** when coverage is not ingested.
157+
154158
### `coverage` (table)
155159

156160
Statement coverage ingested from Istanbul JSON, LCOV, or V8 runtime (`NODE_V8_COVERAGE=...` directory via `--runtime`) via `codemap ingest-coverage <path>`. Natural-key PK `(file_path, name, line_start)` — intentionally **not** a FK to `symbols.id` because `symbols` re-creates with fresh AUTOINCREMENT ids on every `--full` reindex; the natural-key approach lets coverage rows survive that churn (`coverage` is also intentionally absent from `dropAll()`, joins the `query_baselines` precedent). Columns: `coverage_pct REAL` (`NULL` when `total_statements = 0` — "untested" and "no testable code" are different signals), `hit_statements`, `total_statements`. Orphan rows (file deleted from project) are cleaned by an explicit `DELETE FROM coverage WHERE file_path NOT IN (SELECT path FROM files)` at the end of every ingest. Three meta keys (`coverage_last_ingested_at` / `_path` / `_format`) record freshness — single ingest at a time, so format is meta-level not per-row.

docs/golden-queries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Scenarios live in **`fixtures/golden/scenarios.json`** (Tier A) or optional **`s
6868

6969
### Evidence columns (high-judgment recipes)
7070

71-
Some bundled recipes add optional **`reason`** (TEXT) and **`evidence_json`** (TEXT, JSON array) columns on each row — factual detection path for agents, not engine verdicts (Moat A — not pass/fail verdicts). Bounded subqueries cap evidence at three hops; list caps append `{"truncated":true}`. Goldens assert these columns when the recipe ships evidence (`boundary-violations`, `deprecated-symbols`, `unimported-exports`).
71+
Some bundled recipes add optional **`reason`** (TEXT) and **`evidence_json`** (TEXT, JSON array) columns on each row — factual detection path for agents, not engine verdicts (Moat A — not pass/fail verdicts). Bounded subqueries cap evidence at three hops; list caps append `{"truncated":true}`. `unimported-exports` reasons: `no_direct_import`, `reexport_chain_possible`, `unresolved_import_blind_spot`. Goldens assert these columns when the recipe ships evidence (`boundary-violations`, `deprecated-symbols`, `unimported-exports`).
7272

7373
### Coverage columns (CRAP / enrichment recipes)
7474

docs/plans/agent-enrichment-wave.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,16 @@
1212

1313
## Shared conventions (locked)
1414

15-
| Convention | Applies to |
16-
| ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
17-
| **Moat A** — no `pass`/`fail` engine verdict; extra columns only | All |
18-
| **`reason` TEXT** — machine code + short clause where useful | #3 |
19-
| **`evidence_json` TEXT** — bounded JSON array (≤3 hops) | shipped #1 |
20-
| **`confidence` / `coverage_source` / `attribution`** — recipe-specific enums | #3, #4 |
21-
| **Golden update per slice**`fixtures/golden/minimal/*.json` + `scenarios.json` | All |
22-
| **`/harden-pr lite`** after each tracer commit; **`/harden-pr full`** before PR merge | All |
23-
| **Retire plan on merge** — delete `docs/plans/<topic>.md` + lift to reference docs/roadmap in the **same PR** (never leave shipped plans as leftovers) | All |
15+
| Convention | Applies to |
16+
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
17+
| **Moat A** — no `pass`/`fail` engine verdict; extra columns only | All |
18+
| **`reason` TEXT** — machine code + short clause where useful | #3 |
19+
| **`evidence_json` TEXT** — bounded JSON array (≤3 hops) | shipped #1 |
20+
| **`confidence` / `coverage_source` / `attribution`** — recipe-specific enums | #3, #4 |
21+
| **Golden update per slice**`fixtures/golden/minimal/*.json` + `scenarios.json` | All |
22+
| **`/harden-pr lite`** after each tracer commit; **`/harden-pr full`** before PR merge | All |
23+
| **Retire plan on merge** — delete `docs/plans/<topic>.md` + lift to reference docs/roadmap in the **same PR** (never leave shipped plans as leftovers) | All |
24+
| **No deferring complements** — agent surfaces (rule/skill/MCP), glossary, golden/script tests, and plan acceptance items ship **in the same PR** unless explicitly listed under plan **Out of scope** | All |
2425

2526
**Cross-plan synergy:** shipped evidence `reason` complements #4 `attribution` on audit `added` rows. CRAP `coverage_source` (#175) ships before #3 so deletion-confidence can narrow rows with coverage semantics.
2627

docs/roadmap.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Long-running MCP / HTTP sessions dominate agent workflows; one-shot CLI keeps th
8787
Predicate-as-API only — enrich row shape and audit deltas; no standalone pass/fail verdict primitive ([Moat A](./roadmap.md#moats-load-bearing)).
8888

8989
- [ ] **Audit delta attribution** — on `audit --base <ref>` (and matching MCP/HTTP audit), tag each `added` row with **`attribution: introduced | inherited`** via stable finding keys (`requiredColumns` → deterministic key) diffed against the sha-keyed audit-cache index at the merge base. Per-delta `summary` counts (`added_introduced`, `added_inherited`) optional when `summary: true`. Reuses shipped `audit-worktree` / `git archive` cache — no new verdict primitive ([Moat A](./roadmap.md#moats-load-bearing)). Complements deferred **`codemap audit` verdict + thresholds** (consumer filters `introduced` via `jq`). Plan: [`plans/audit-delta-attribution.md`](./plans/audit-delta-attribution.md). Effort: M.
90-
- [x] **Evidence chains on recipe rows**v1 shipped on `boundary-violations`, `deprecated-symbols`, `unimported-exports` (`reason` + `evidence_json`; SQL-only). Contract: [golden-queries.md § Evidence columns](./golden-queries.md#evidence-columns-high-judgment-recipes). v2 optional: `unresolved_import_blind_spot` on `unimported-exports`; audit `added` attribution merge ([Moat A](./roadmap.md#moats-load-bearing)).
90+
- [x] **Evidence chains on recipe rows** — shipped on `boundary-violations`, `deprecated-symbols`, `unimported-exports` (`reason` + `evidence_json`; includes `reexport_chain_possible` and `unresolved_import_blind_spot`). Contract: [golden-queries.md § Evidence columns](./golden-queries.md#evidence-columns-high-judgment-recipes). v2 optional: audit `added` attribution merge ([Moat A](./roadmap.md#moats-load-bearing)).
9191
- [ ] **Tiered lookup fast paths**`show` / exact-name recipe paths hit covering indexes first; document latency expectations in MCP tool descriptions. FTS and broad scans remain explicit fallbacks. Effort: S–M.
9292
- [x] **Graph-estimated CRAP recipe** — bundled `high-crap-score`: CRAP = `CC² × (1 - coverage/100)³ + CC` using `symbols.complexity`; **measured** `coverage` when ingested, else **graph-estimated** tiers (85% / 40% / 0% from test-file reachability over `dependencies` / `calls` / `test_suites`). Rows expose `coverage_source: measured | estimated`. Contract: [golden-queries.md § Coverage columns](./golden-queries.md#coverage-columns-crap--enrichment-recipes). Complements `high-complexity-untested` when no coverage file exists.
9393
- [ ] **Coverage-confirmed dead recipe** — bundled `coverage-confirmed-dead`: JOIN static dead-code predicate (uncalled exports, suppression-aware) with ingested `coverage` — rows carry `confidence: high` when callers = 0 and `coverage_pct = 0`, `medium` when coverage not ingested. Predicate columns only, no verdict primitive ([Moat A](./roadmap.md#moats-load-bearing)). Plan: [`plans/coverage-deletion-confidence.md`](./plans/coverage-deletion-confidence.md). Effort: L–M.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[
22
{
3-
"n": 42
3+
"n": 43
44
}
55
]

fixtures/golden/minimal/files-hashes.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@
149149
"language": "ts",
150150
"line_count": 4
151151
},
152+
{
153+
"path": "src/lib/alias-blind-spot.ts",
154+
"content_hash": "34f2847180126455a500387ae3b2f49f67cc4e13290cc677c3e148827a6564ff",
155+
"language": "ts",
156+
"line_count": 6
157+
},
152158
{
153159
"path": "src/lib/cache.ts",
154160
"content_hash": "964f6d3ddb8a7782b1273a38ed0bbde8cd886eb672c1f20466f0aa88ff49205f",

fixtures/golden/minimal/index-summary.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[
22
{
3-
"files": 42,
3+
"files": 43,
44
"symbols": 106,
5-
"imports": 25,
5+
"imports": 26,
66
"components": 5,
77
"dependencies": 23
88
}

fixtures/golden/minimal/index-table-stats.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[
22
{
3-
"files": 42,
3+
"files": 43,
44
"symbols": 106,
5-
"imports": 25,
5+
"imports": 26,
66
"exports": 62,
77
"components": 5,
88
"dependencies": 23,
@@ -13,17 +13,17 @@
1313
"css_vars": 2,
1414
"css_classes": 2,
1515
"css_keyframes": 1,
16-
"scopes": 107,
17-
"ref_count": 317,
18-
"bindings": 274,
19-
"import_specifiers": 30,
16+
"scopes": 108,
17+
"ref_count": 319,
18+
"bindings": 276,
19+
"import_specifiers": 31,
2020
"function_params": 18,
2121
"runtime_markers": 6,
2222
"test_suites": 7,
2323
"re_export_chains": 4,
2424
"module_cycles": 2,
2525
"dynamic_imports": 1,
26-
"file_metrics": 34,
26+
"file_metrics": 35,
2727
"unresolved_calls": 1,
2828
"jsx_elements": 10,
2929
"async_calls": 1,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[
22
{
3-
"n": 42
3+
"n": 43
44
}
55
]

0 commit comments

Comments
 (0)