You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Grill-me Q14 outcome: three remaining § 1 rows had implicit gotchas
the recipe author would otherwise have to discover during impl. Each
row gets a small clarification — substrate unchanged, effort unchanged.
§ 1.1 components-touching-deprecated:
- Was: "One bundled recipe (components-touching-deprecated)"
- Now: explicit two-path UNION
- HOOK PATH: components.hooks_used JSON overlap with @deprecated
symbols (catches deprecated hooks like useDeprecatedThing)
- CALL PATH: calls.caller_name IN (SELECT name FROM components) ×
@deprecated symbols by callee_name (catches regular deprecated
functions called inside components)
- Hook-only variants would ship false-negatives — recipe author needs
the explicit UNION to avoid the trap.
§ 1.6 unused-type-members:
- Was: "Recipe (unused-type-members) — needs JSON-extraction predicate"
- Now: ADVISORY recipe with explicit caveat block in .md. Output is
"review these" candidates, NEVER "safe to delete" — TS has multiple
indirect-usage classes codemap's substrate doesn't track:
- Indexed access: T['fieldName']
- keyof T
- Type spreads: type X = T & {...}
- Mapped types: {[K in keyof T]: ...}
These produce false-positives. Recipe is useful as a candidate
surfacer; agents must verify before deletion.
§ 1.8 more MCP resources:
- Was: hand-wave "add codemap://files/{path} and codemap://symbols/
{name}"
- Now: spell out disambiguation envelope (reuses {matches,
disambiguation?} pattern from PR #39 show/snippet) — symbols with
duplicate names across files (Component, index, default, util-name
collisions) return all matches with by_kind / files / hint metadata.
Plus ?in=<path-prefix> query parameter mirroring show --in <path>.
- Without spelling this out, the implementation would have to invent
disambiguation OR ship a "first match wins" gotcha.
Net: each row's What's-needed cell now contains enough detail that
the recipe / resource author can implement without re-deriving the
JOIN structure or envelope shape. Tactical clarity layered on top of
the structural decisions made in earlier grills.
| 1.1 | **Components calling deprecated symbols** | `components.hooks_used` + `calls` + `symbols.doc_comment LIKE '%@deprecated%'` | One bundled recipe `components-touching-deprecated` — UNION of two paths: (1) **hook path** — `components.hooks_used` JSON overlap with `symbols WHERE doc_comment LIKE '%@deprecated%'` (catches deprecated _hooks_ like `useDeprecatedThing`); (2) **call path** — `calls.caller_name IN (SELECT name FROM components)` × `symbols WHERE doc_comment LIKE '%@deprecated%' AND name = calls.callee_name` (catches deprecated regular functions called inside components). Hook-only variants ship false negatives | XS |
41
41
| 1.2 | **Exports never imported anywhere** | `exports` LEFT JOIN `imports` (by `source` resolution); `exports.re_export_source` column exists for re-export chain handling | Recipe (`unimported-exports`) — re-export chains need a JOIN through `re_export_source` to avoid false positives on barrel-only exports | S |
42
42
| 1.3 | **Cyclomatic complexity per symbol** | `calls.caller_scope` already aggregates per-symbol. (Earlier draft claimed AST node-counting was already in place; corrected per § 8 — it isn't.) | Extend the AST walker in `src/parser.ts` to count branching nodes per symbol; add `complexity REAL` column on `symbols`; ship `high-complexity-untested` recipe | M |
43
43
| 1.4 | **Refactor risk ranking** | `dependencies` (fan-in) + `coverage` (test coverage) | Recipe `refactor-risk-ranking` with formula `(fan_in + 1) × (100 - COALESCE(coverage_pct, 0))`. The `+1` ensures orphans (fan_in=0) score on coverage alone (untested orphans = high risk; tested orphans = candidates for deletion review, not refactor). `COALESCE(coverage_pct, 0)` treats unmeasured coverage as untested (NULL coverage drops rows from `ORDER BY` otherwise). Bundled `refactor-risk-ranking.md` ships a caveat — formula is a starting point; users tune via project-local recipe override at `<projectRoot>/.codemap/recipes/refactor-risk-ranking.sql`. Suggested axes for tuning: log-scale `fan_in` for hub-heavy codebases (`LOG(fan_in + 1) * 30`), visibility weight (if `@public`/`@internal`/`@beta` JSDoc tags are used consistently), LOC weight (if test-density varies across files). Linear-in-fan_in and equal-weight-on-orphans are accepted v1 trade-offs vs over-design. | XS |
44
44
| 1.5 | **Boundary violations (config-driven)** | `dependencies` table + Zod config substrate (`src/config.ts`) + glob-matching primitives in `validate-engine` + index-time reconciler pattern (per `recipe_recency` item 1.9) + SARIF output formatter | New `boundaries: [{name, from_glob, to_glob, action: "deny"\|"allow", except_self?}]` field in `codemap.config.ts` (directional rules — Shape A). New `boundary_rules` table populated at index time from config (mirrors `recipe_recency` reconciler). Bundled recipe `boundary-violations.sql` JOINs `dependencies` × `boundary_rules` via SQLite `GLOB`; output rows = `{from_path, to_path, rule_name, action}`. **No new CLI flag** — `query --recipe boundary-violations [--format sarif]` is the surface (moat-A clean: recipe consumes config-as-data; SARIF mode handles CI gate). Element-type / layer-ordering shapes (`eslint-plugin-boundaries` / Nx flavors) are user-side compositions on top of directional rules; deferred to v1.x as a sugar layer if user demand emerges (compiles down to A's directional rules at index time; backwards-compat preserved) | S |
45
-
| 1.6 | **Type members consumed by external files** | `type_members` + `imports.specifiers` (JSON) | Recipe (`unused-type-members`) — needs JSON-extraction predicate on specifiers | S |
45
+
| 1.6 | **Type members consumed by external files** | `type_members` + `imports.specifiers` (JSON) | **Advisory recipe** `unused-type-members` (output is a "review these" list, NEVER a "safe to delete" list). Needs JSON-extraction predicate on specifiers (`json_each` / `json_extract`). Bundled `.md` warns about indirect-usage false-positive classes that codemap's substrate doesn't track: indexed access (`T['fieldName']`), `keyof T`, type spreads (`type X = T & {…}`), mapped types (`{[K in keyof T]: …}`). Output rows are candidates for manual review | S |
46
46
| 1.7 | **Mermaid / D2 / Graphviz output** | `dependencies` + `calls` already shape into edges; SARIF / annotations formatters demonstrate the formatter pattern | New `--format mermaid` formatter (sibling of SARIF in `output-formatters.ts`) **with bounded-input contract**: input must come from `impact` engine, a `LIMIT N`-shipped recipe (e.g. `fan-in`, `fan-out`), or ad-hoc SQL with explicit `LIMIT ≤ 50`. Unbounded inputs error with a scope-suggestion message naming the recipe + edge count + `LIMIT`/`--via`/`WHERE` knobs. Auto-truncation is out of scope — silent subset selection would be a **verdict-shaped affordance** masquerading as an output mode (violates moat A). Hairballed Mermaid renders as garbage in chat clients (MCP / Cursor / Slack); a clear error pointing at how to scope is the better DX. | S |
| 1.8 | **More MCP resources** | Schema, recipes, skill already exposed via `resource-handlers.ts` | Add `codemap://files/{path}` (file shape — symbols, imports, exports, coverage rolled up by file) and `codemap://symbols/{name}` (LSP-like reads). Both reuse the existing `{matches, disambiguation?}` envelope from PR #39 `show` / `snippet` — symbols with the same name across files (very common: `Component`, `index`, `default`, util-name collisions) return all matches with a `disambiguation` block (`{n, by_kind, files, hint}`); single-match returns `{matches: [{...}]}`. Filter via `?in=<path-prefix>` query parameter (mirrors `show --in <path>` flag) | S |
48
48
| 1.9 | **Local recipe-recency tracking** | `query_baselines` precedent (user-data table excluded from `dropAll()`) | New `recipe_recency(recipe_id PK, last_run_at, run_count)` table; reconciler at MCP / HTTP request boundary writes the row. **Rolling 90-day retention** — entries older than `last_run_at + 90d` pruned per reindex (caps unbounded growth). **Opt-out** via `codemap.config.ts` `recipe_recency: false` — skips the reconciler entirely; table stays empty. Surfaces in `--recipes-json` as `{recipe_id, last_run_at, run_count_90d}` so agents see recently-used recipes ranked first. **Local-only** — no upload primitive shipped or planned (see § 3 "No telemetry upload" floor). Naming note: not "telemetry" — the word carries upload / aggregation / surveillance connotations that don't match the actual capability (purely local recency tracking, like `query_baselines`). | M |
49
49
| 1.10 | **Symbol-rename dry-run preview** | `calls` (callers) + `symbols.line_start` / `line_end` (locations) | Bundled recipe `rename-preview.sql` with **parameter substitution** (new infra: `?`-placeholder binding via `db.ts`'s prepared-statement pattern); `--format diff` output mode (sibling of `--format mermaid` per item 1.7) converts rows to unified diff. **No new verb** — `query --recipe rename-preview --params old=foo,new=bar --format diff` is the surface. Moat-A-aligned (SQL is the API; rename's implicit choices — visibility filter, type-only re-exports, test files, aliases — live in reviewable recipe SQL, not argv). Effort drops M → S | M |
0 commit comments