Skip to content

Commit 5bdd0ca

Browse files
committed
docs(research): § 1.1, 1.6, 1.8 sanity sharpening (gotchas + envelopes)
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 parent 983c67f commit 5bdd0ca

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

docs/research/non-goals-reassessment-2026-05.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ The data and pipeline exist. Each row needs only a recipe / formatter / verb to
3737

3838
| # | Capability | What's already in place | What's needed | Effort |
3939
| ---- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
40-
| 1.1 | **Components calling deprecated symbols** | `components.hooks_used` + `calls` + `symbols.doc_comment LIKE '%@deprecated%'` | One bundled recipe (`components-touching-deprecated`) | XS |
40+
| 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 |
4141
| 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 |
4242
| 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 |
4343
| 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 |
4444
| 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 |
4646
| 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 |
47-
| 1.8 | **More MCP resources** | Schema, recipes, skill already exposed via `resource-handlers.ts` | Add `codemap://files/{path}` (file shape — symbols, imports, exports, coverage) and `codemap://symbols/{name}` (LSP-like reads) | S |
47+
| 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 |
4848
| 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 |
4949
| 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 |
5050

0 commit comments

Comments
 (0)