Skip to content

feat(recipes): components-touching-deprecated + refactor-risk-ranking (research note § 1)#65

Merged
SutuSebastian merged 1 commit intomainfrom
feat/recipes-from-research-note
May 4, 2026
Merged

feat(recipes): components-touching-deprecated + refactor-risk-ranking (research note § 1)#65
SutuSebastian merged 1 commit intomainfrom
feat/recipes-from-research-note

Conversation

@SutuSebastian
Copy link
Copy Markdown
Contributor

Summary

Ships two new bundled recipes from the research note's § 1 capability inventory — both XS effort, both fully grilled in PR #58, both shipping against existing substrate (no schema bump, no new infra).

Recipes

components-touching-deprecated (research note § 1.1)

UNION of two evidence axes:

  1. Hook pathcomponents.hooks_used JSON contains a @deprecated symbol's name (catches deprecated hooks like useDeprecatedThing).
  2. Call pathcalls.caller_name = components.name AND callee_name is @deprecated (catches regular deprecated functions called inside components).

Why UNION: hook-only variants ship false-negatives — research note § 1.1 grill explicitly required both paths.

Action template: review-deprecation-impact — agent flags the component for migration, doesn't auto-fix.

refactor-risk-ranking (research note § 1.4)

Per-file ranking by (fan_in + 1) × (100 - avg_coverage_pct). Three correctness fixes over the naïve formula:

  1. Orphans (fan_in = 0) score on coverage alone via the +1.
  2. NULL coverage_pct treated as 0% via COALESCE (otherwise the row drops from ORDER BY).
  3. Files with no exports excluded — no public-API surface to refactor externally.

Empirical divergence from research note § 1.4 (documented in the recipe .md): the research note specified per-symbol ranking. Testing on codemap's own index produced 30 rows from src/db.ts all tied at the same score (file-level fan_in inherited from the dependencies table). Ships per-file ranking as the more useful default; per-symbol via calls is one of the documented tuning axes for project-local override.

Action template: review-refactor-impact — agent flags the file for caller-review + test coverage before signature changes.

Verification (locally pre-push)

  • bun src/index.ts query --recipe components-touching-deprecated[] on codemap's own index (no @deprecated symbols hit components — expected; SQL valid).
  • bun src/index.ts query --recipe refactor-risk-ranking → 30 distinct files ranked by score, src/db.ts top with risk_score = 4500 (44 fan_in × 100 - 0% coverage). Sensible output, no ties from inherited file-level fan_in.
  • bun run check passes — format, lint, typecheck, all 23 golden-query scenarios.

Doc-governance compliance

  • Rule 10 lockstep — both templates/agents/ (ships to npm via codemap agents init) AND .agents/ (this clone's mirror) updated:
    • Trigger-pattern table rows for both recipes
    • Quick-reference table rows for both recipes
    • Recipe-id list in SKILL.md extended
  • Recipe-as-content registry (PR feat(recipes): recipes-as-content registry — bundled .md + project-local .codemap/recipes/ #37) — both recipes ship as <id>.{sql,md} file pairs. .md carries action template via YAML frontmatter + caveats / tuning axes in the body.
  • Patch changeset — pre-v1 lesson: additive bundled recipes don't break existing .codemap/index.db; no schema change. Patch suffices.

Test plan

  • bun run format:check passes
  • bun run check passes (typecheck + 23/23 golden queries)
  • bun src/index.ts query --recipe <id> runs both recipes end-to-end
  • Recipe loader's DML/DDL deny-list + Zod schema accepts both .md frontmatter shapes
  • CodeRabbit review

Out of scope (intentional follow-ups)

  • Other low-hanging § 1 candidates deferred:
    • § 1.2 unimported-exports (S effort) — needs JOIN through re_export_source; recursive-CTE design point
    • § 1.6 unused type members (S, advisory) — needs JSON-extraction predicate; harder than naïve substrate-only
    • § 1.8 MCP resources (S) — needs new resource handler code
  • § 1.4 per-symbol variant — documented as a tuning axis in the recipe .md; not bundled.
  • Golden-query expectations for the new recipes — not added; bundled-recipe loader's own validation catches SQL errors at recipe-load time. Golden snapshots can be added in a follow-up if regression scenarios become valuable.

…nking

Two new bundled recipes from research note § 1 — both XS effort, both
ship against existing substrate (no schema bump, no new infra).

§ 1.1 components-touching-deprecated
- UNION of hook path (components.hooks_used JSON overlap) + call path
  (calls.caller_name = component, callee_name = @deprecated symbol).
- Hook-only variant would ship false-negatives — recipe spells out the
  explicit UNION per research note § 1.1 grill.
- Output: {component, component_file, deprecated_symbol, deprecated_file,
  via} where via ∈ {'hook', 'call'}.
- Action template: review-deprecation-impact.

§ 1.4 refactor-risk-ranking
- Formula: (fan_in + 1) × (100 - avg_coverage_pct), per-file.
- Three correctness fixes over the naïve "fan_in × (100 - coverage_pct)":
  - Orphans (fan_in=0) score on coverage alone via +1
  - NULL coverage treated as 0% via COALESCE (otherwise row drops)
  - Files with no exports excluded (no public-API surface to refactor)
- Empirical divergence from research note § 1.4: spec said per-symbol;
  testing on codemap's own index produced 30 rows from src/db.ts all
  tied at the same score (file-level fan_in inherited). Ships per-file
  ranking; per-symbol via calls is one of the documented tuning axes
  in the .md.
- v1 trade-off: linear-in-fan_in. Tune via project-local recipe
  override (suggested axes spelled out in .md: log-scale, visibility
  weight, LOC weight, per-symbol via calls).
- Action template: review-refactor-impact.

Verification:
- bun src/index.ts query --recipe components-touching-deprecated → []
  on codemap's own index (no @deprecated symbols hit components;
  expected). SQL valid.
- bun src/index.ts query --recipe refactor-risk-ranking → 30 distinct
  files ranked by score, src/db.ts top with risk_score=4500 (44 fan_in
  × 100 - 0% coverage). Sensible output.
- bun run check passes (format, lint, typecheck, tests, all 23 golden
  queries).

Rule 10 lockstep updates:
- templates/agents/rules/codemap.md — added trigger-pattern + quick-
  reference table rows for both recipes.
- templates/agents/skills/codemap/SKILL.md — recipe-id list extended.
- .agents/rules/codemap.md + .agents/skills/codemap/SKILL.md — same
  mirrored updates per agents-first-convention.

Patch changeset: pre-v1 lesson — additive bundled recipes don't break
existing .codemap/index.db; no schema change. Patch suffices.

Files: 5 new (2 .sql + 2 .md + 1 changeset), 4 lockstep edits.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 4, 2026

🦋 Changeset detected

Latest commit: 332063a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@stainless-code/codemap Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Warning

Rate limit exceeded

@SutuSebastian has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 2 minutes and 41 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 485817e0-3772-4534-8c27-2d6c3dcd1e72

📥 Commits

Reviewing files that changed from the base of the PR and between db27d7b and 332063a.

📒 Files selected for processing (9)
  • .agents/rules/codemap.md
  • .agents/skills/codemap/SKILL.md
  • .changeset/recipes-from-research-note.md
  • templates/agents/rules/codemap.md
  • templates/agents/skills/codemap/SKILL.md
  • templates/recipes/components-touching-deprecated.md
  • templates/recipes/components-touching-deprecated.sql
  • templates/recipes/refactor-risk-ranking.md
  • templates/recipes/refactor-risk-ranking.sql
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/recipes-from-research-note

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 2 minutes and 41 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@SutuSebastian SutuSebastian merged commit 1b7a5c7 into main May 4, 2026
10 checks passed
@SutuSebastian SutuSebastian deleted the feat/recipes-from-research-note branch May 4, 2026 12:52
SutuSebastian added a commit that referenced this pull request May 4, 2026
… on parser.ts

Fact-checking against codebase post-PR-#69-and-#70 surfaced four stale
spots; concise-comments rule re-applied to recently-authored parser.ts
comments.

DOCS LIFTED (post-FTS5 / Mermaid / complexity merge):

- README.md (root) line 113 — --format enum was missing `mermaid`.
  Updated to <text|json|sarif|annotations|mermaid> + added the
  bounded-input contract one-liner + 50-edge ceiling note.
  Added --with-fts example block alongside (was missing entirely;
  README is the canonical CLI surface per docs/README.md Single source
  of truth table).

- docs/architecture.md output-formatters paragraph — described only
  formatSarif + formatAnnotations; missing formatMermaid + bounded-
  input contract. Added formatMermaid description + MERMAID_MAX_EDGES
  reference + the no-auto-truncation reasoning (would be a verdict
  masquerading as output mode). Updated the --format CLI enum to
  include mermaid; same for the MCP tools format union.

- .agents/skills/codemap/SKILL.md + templates/agents/skills/codemap/
  SKILL.md — recipe-id list missed three coverage recipes
  (untested-and-dead, files-by-coverage, worst-covered-exports)
  shipped earlier in PR #65/#56 era. Lockstep update per Rule 10.
  Skill now lists 20 of 20 bundled recipe ids.

CONCISE-COMMENTS SWEEP on parser.ts (recently authored):

- Trimmed the 14-line complexityStack JSDoc block to 6 lines. Kept:
  the -1 sentinel rationale (non-obvious), the WeakMap rationale (the
  bug fix from PR #70 review). Cut: re-stating push/pop semantics
  obvious from method names + step-by-step "this then that" prose.

- Removed the "Defer complexity push to..." comment in the
  VariableDeclaration handler. The 4-line block restated the design
  decision documented one screen up in the complexityStack jsdoc;
  cross-ref makes it redundant. Per concise-comments § "Cut" rule:
  "Cross-references that save grep time" — keep when they actually do;
  cut when they restate.

Verification:
- bun run check: format + lint + typecheck + 23/23 golden ✓
- Recipe count: SQL files = 20, skill mentions = 20 (1:1 match) ✓
- SCHEMA_VERSION = 8 in db.ts; docs/architecture.md says 8 ✓
- complexity column documented in architecture.md + glossary.md ✓
- --with-fts in README.md + architecture.md + glossary.md +
  roadmap.md (consumer-facing surfaces all aligned) ✓
- --format mermaid in README.md + architecture.md + glossary.md +
  agent rule/skill ✓
SutuSebastian added a commit that referenced this pull request May 4, 2026
…sted recipe (research note § 1.4) (#70)

* feat(complexity): cyclomatic complexity column + high-complexity-untested recipe

Research note § 1.4 ship-pick (c) per § 5 cadence. Schema bump
SCHEMA_VERSION 7 → 8.

Schema:
- symbols.complexity REAL column. NULL for non-function kinds and
  class methods (v1 limitation documented in recipe .md).

Parser:
- complexityStack maintained alongside scopeStack. Function entry
  pushes {symbolIndex, count: 1}; branching-node visitors increment
  top.count; function exit pops + writes count into the already-
  pushed symbol row's complexity field.
- McCabe decision points counted: if, while, do-while, for, for-in,
  for-of, case X (not default:), &&/||/??, ?:, catch.

Bundled recipe high-complexity-untested:
- Joins symbols (complexity >= 10) with coverage (< 50%).
- Combines structural + runtime evidence axes — surfaces refactor-
  priority candidates that untested-and-dead and worst-covered-exports
  miss (they catch dead-or-uncalled, this catches called-but-undertested-
  AND-branchy).

Empirical sanity check on codemap's own index after reindex:
- extractFileData (parser.ts main visitor) → complexity 108 ✓
- stringifyTypeNode → 42 ✓
- All non-function kinds have NULL complexity ✓
- high-complexity-untested recipe returns 7 functions all from
  src/parser.ts (which has 0% coverage; complexity ≥ 10) ✓

Lockstep updates per Rule 10 (templates/agents + .agents):
- Trigger pattern row "What's high-complexity AND undertested?"
- Quick reference row for SELECT name, complexity FROM symbols
- Recipe-id list extended in SKILL.md

Plus architecture.md (schema version 8, complexity column docs),
glossary.md (cyclomatic complexity entry), patch changeset.

Files changed:
- src/db.ts (SCHEMA_VERSION + symbols.complexity column + insertSymbols
  bind + SymbolRow optional complexity field)
- src/parser.ts (complexityStack + branching node visitors + push/pop
  in FunctionDeclaration / VariableDeclaration arrow-fn paths)
- templates/recipes/high-complexity-untested.{sql,md}
- docs/architecture.md (schema version + symbols column doc)
- docs/glossary.md (new entry)
- templates/agents/rules/codemap.md + .agents/rules/codemap.md
  (trigger + quick-ref rows)
- templates/agents/skills/codemap/SKILL.md + .agents/skills/codemap/
  SKILL.md (recipe-id list)
- .changeset/cyclomatic-complexity.md (patch)

Verification:
- bun test: 754 pass
- bun run check passes (format, lint, typecheck, 23/23 golden queries)
- Live re-index against codemap source produces sensible complexity
  values (parser visitor itself is the highest at 108, which tracks)

* docs(skill): add complexity column to symbols schema in skill files

CodeRabbit catch on PR #70: the high-complexity-untested recipe row was
added to .agents/skills/codemap/SKILL.md but the symbols table schema
section (under "### `symbols` — Functions, types, ...") still listed
columns through `visibility` only, missing the new `complexity REAL`
column. Verified by reading the file — claim was correct.

Both lockstep mirrors (.agents/ + templates/agents/) updated with the
same row:

  | complexity | REAL | Cyclomatic complexity (`1 + decision points`)
  for function-shaped symbols. NULL for non-functions and class methods
  (v1). Powers --recipe high-complexity-untested. Decision points: if,
  while, do…while, for/for-in/for-of, case X: (not default:),
  &&/||/??/?:, catch |

Per docs/README.md Rule 10 — agent rule + skill schema docs must stay
in lockstep with code-side schema changes. The trigger-pattern row +
recipe-id list were already updated; the schema-table row was the gap.

* fix(complexity): per-function visitors fix multi-declarator misattribution + cleanups

CodeRabbit raised three valid findings on PR #70. All fact-checked
against the code; all correct.

A) docs/architecture.md symbols schema table was malformed:
- Markdown table separator row had extra `| --- | ---` segments because
  oxfmt mis-counted columns when the description contained `|` chars
  inside `&&`/`||`/`??` backtick spans.
- The complexity row's description was split across THREE cells with
  broken backtick fences.
- Fix: restored single-row layout (3 cells: Column | Type | Description)
  and rephrased the decision-point list to avoid `|` inside backticks
  ("short-circuit `&&` / `||` / `??`" instead of "`&&`/`||`/`??`").

B) src/parser.ts complexity misattribution on multi-declarator
   VariableDeclaration (e.g. `const a = () => {…}, b = () => {…};`):

   Pre-fix: VariableDeclaration enter pushed all declarators' complexity
   entries up front. Then visitor traversed `a`'s body — branches
   incremented top (= b's entry). Then `b`'s body. Exit pops in reverse
   →  symbols[1].complexity = 3 (wrong), symbols[0].complexity = 1
   (wrong). Real bug.

   Fix: push/pop complexity on the FUNCTION-shaped node visitors
   (ArrowFunctionExpression / FunctionExpression) — not on
   VariableDeclaration. The VariableDeclaration handler still creates
   the symbol row but only RECORDS the symbol → init-node mapping in a
   WeakMap. The ArrowFunctionExpression / FunctionExpression enter
   handler reads the WeakMap to know which symbol to write back to;
   anonymous arrow fns (callbacks, IIFEs) get -1 and just track count
   without persistence.

   Verified against fixture:
     const a = () => { if (1===1) {…} },
           b = () => { if (2===2) {…} },
           c = () => 5;
   → a=2, b=2, c=1 (correct; pre-fix was a=1, b=3, c=1)

C) popComplexityInto guard was a no-op (callers passed top.symbolIndex,
   so the equality check was always true). Simplified to parameterless
   popComplexityTop() that always pops + writes back if symbolIndex >= 0.
   Folds naturally into the B refactor — every push/pop pair now lives
   in a function-shaped visitor.

Also re-ran codemap query against codemap source post-fix:
  extractFileData=108, stringifyTypeNode=42, extractClassMembers=18,
  extractLiteralValue=15, extractObjectMembers=14
Same scores as pre-fix on these (no FunctionExpression / arrow nesting
in those particular functions, so the bug didn't surface) — confirms
the refactor is a strict improvement, not a regression.

* docs: audit + lift remaining stale references; concise-comments sweep on parser.ts

Fact-checking against codebase post-PR-#69-and-#70 surfaced four stale
spots; concise-comments rule re-applied to recently-authored parser.ts
comments.

DOCS LIFTED (post-FTS5 / Mermaid / complexity merge):

- README.md (root) line 113 — --format enum was missing `mermaid`.
  Updated to <text|json|sarif|annotations|mermaid> + added the
  bounded-input contract one-liner + 50-edge ceiling note.
  Added --with-fts example block alongside (was missing entirely;
  README is the canonical CLI surface per docs/README.md Single source
  of truth table).

- docs/architecture.md output-formatters paragraph — described only
  formatSarif + formatAnnotations; missing formatMermaid + bounded-
  input contract. Added formatMermaid description + MERMAID_MAX_EDGES
  reference + the no-auto-truncation reasoning (would be a verdict
  masquerading as output mode). Updated the --format CLI enum to
  include mermaid; same for the MCP tools format union.

- .agents/skills/codemap/SKILL.md + templates/agents/skills/codemap/
  SKILL.md — recipe-id list missed three coverage recipes
  (untested-and-dead, files-by-coverage, worst-covered-exports)
  shipped earlier in PR #65/#56 era. Lockstep update per Rule 10.
  Skill now lists 20 of 20 bundled recipe ids.

CONCISE-COMMENTS SWEEP on parser.ts (recently authored):

- Trimmed the 14-line complexityStack JSDoc block to 6 lines. Kept:
  the -1 sentinel rationale (non-obvious), the WeakMap rationale (the
  bug fix from PR #70 review). Cut: re-stating push/pop semantics
  obvious from method names + step-by-step "this then that" prose.

- Removed the "Defer complexity push to..." comment in the
  VariableDeclaration handler. The 4-line block restated the design
  decision documented one screen up in the complexityStack jsdoc;
  cross-ref makes it redundant. Per concise-comments § "Cut" rule:
  "Cross-references that save grep time" — keep when they actually do;
  cut when they restate.

Verification:
- bun run check: format + lint + typecheck + 23/23 golden ✓
- Recipe count: SQL files = 20, skill mentions = 20 (1:1 match) ✓
- SCHEMA_VERSION = 8 in db.ts; docs/architecture.md says 8 ✓
- complexity column documented in architecture.md + glossary.md ✓
- --with-fts in README.md + architecture.md + glossary.md +
  roadmap.md (consumer-facing surfaces all aligned) ✓
- --format mermaid in README.md + architecture.md + glossary.md +
  agent rule/skill ✓
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant