Skip to content

Latest commit

 

History

History
1201 lines (735 loc) · 130 KB

File metadata and controls

1201 lines (735 loc) · 130 KB

@stainless-code/codemap

0.11.1

Patch Changes

  • 3aff237 Thanks @SutuSebastian! - Refresh runtime and toolchain dependencies (better-sqlite3, oxc-parser, oxfmt, oxlint, and related dev tooling) to latest compatible releases. Pin transitive hono and js-yaml to patched versions so dependency audits report no known vulnerabilities.

0.11.0

Minor Changes

  • #178 36106ff Thanks @SutuSebastian! - Add structural duplicate detection: symbols.body_hash at index time (canonical function body AST) and bundled duplicates recipe. Schema version 39 — existing indexes rebuild on next codemap run. Function-shaped symbols only; trivial one-line bodies skipped. Triage collisions with snippet — shared control-flow skeletons can false-positive.

  • #179 8595173 Thanks @SutuSebastian! - Add churn × complexity hotspot ranking: file_churn refreshed on every index from git history, with codemap ingest-churn, MCP/HTTP ingest_churn, and config churn.file for non-git repos. Schema version 40 — existing indexes rebuild on next codemap run. New churn-complexity-hotspots recipe ranks files or symbols (by_symbol) by change frequency × complexity with normalized 0–100 scores and churn_trend. Outcome alias hotspots still maps to fan-in.

  • #173 d4982c4 Thanks @SutuSebastian! - Add SonarSource cognitive complexity on symbols (same function-shaped coverage as cyclomatic, including class methods). Schema version 38 — existing indexes rebuild on next codemap run. New recipe high-cognitive-complexity; high-complexity-untested rows include cognitive_complexity.

Patch Changes

  • #177 bb8bae9 Thanks @SutuSebastian! - On audit --base <ref> (CLI / MCP / HTTP), each added row carries attribution: introduced | inherited (branch-new vs pre-existing at merge base). --summary adds added_introduced / added_inherited per delta.

  • #172 cf7df2f Thanks @SutuSebastian! - Add query --format codeclimate (GitLab Code Quality JSON) and query --format badge (markdown issue-count line or codemap-badge/v1 JSON via --badge-style json). Available on CLI, MCP, and HTTP query tools.

  • #183 b509e4c Thanks @SutuSebastian! - Add hash-stable map_id and codebase_map routing hints to context responses (CLI, MCP, HTTP). MCP initialize instructions now include map_id and top hub paths. Opt out with --no-codebase-map or include_codebase_map: false; omitted when compact.

  • #176 16687a0 Thanks @SutuSebastian! - Add coverage-confirmed-dead recipe: static dead exports with confidence (high when ingested 0% coverage, medium when unmeasured), plus reason and caller_count.

  • #174 a11242e Thanks @SutuSebastian! - Add reason and evidence_json columns on high-judgment recipe rows (boundary-violations, deprecated-symbols, unimported-exports) so agents can cite detection path before apply or manual edits.

  • #175 af86d10 Thanks @SutuSebastian! - Add high-crap-score recipe: CRAP ranking with measured coverage when ingested, or graph-estimated 85/40/0% tiers from test reachability otherwise.

    Extend unimported-exports with unresolved_import_blind_spot reason and evidence_json (unresolved import hop) so dead-export / high-CRAP triage does not over-trust the graph past alias blind spots.

  • #181 aae172f Thanks @SutuSebastian! - Scope codemap impact and MCP/HTTP impact homonym symbols: --in / in disambiguates by defining file (same prefix/exact rules as codemap show --in); unscoped homonyms union per-defining-file call graphs instead of merging by name only. Mismatched scope returns empty matches with skipped_scope.

  • #170 e74410c Thanks @SutuSebastian! - MCP tools/list and HTTP GET /tools expose advisory readOnlyHint, destructiveHint, and idempotentHint per tool so clients can gate auto-approval. Apply tools carry destructiveHint; read-only query tools carry readOnlyHint.

  • #180 a5caca8 Thanks @SutuSebastian! - Harden read surfaces: codemap query --format … blocks index mutations via the same read-only guard as --json; codemap serve requires --token when --host is not loopback (any 127.0.0.0/8 address counts as loopback, so --token stays optional on 127.0.0.2 and similar); codemap validate (and MCP/HTTP validate) can return rejected rows with optional reason (path escapes project root | path escapes via symlink | path resolves outside project root) — output path keys are always project-relative POSIX paths.

  • #182 3568c5f Thanks @SutuSebastian! - createCodemap() and the CLI now reject invalid project config at load time. A second createCodemap() with a different project root in the same process throws (audit --base worktree reindex is exempt).

  • #184 fb73e0d Thanks @SutuSebastian! - show and snippet now use fast equality lookup for exact name and lone name:Token queries (no wildcards); substring, multi-field, and FTS paths stay on the broader slow tier. CLI help, MCP tool descriptions, and bundled agent guidance document the two tiers.

0.10.1

Patch Changes

  • #169 1632bdd Thanks @SutuSebastian! - Refresh runtime and toolchain dependencies (oxc-parser, oxc-resolver, oxfmt, oxlint, @clack/prompts, tinyglobby, and related dev tooling) to latest compatible releases.

  • #166 4bfb067 Thanks @SutuSebastian! - Add codemap rename CLI alias for homonym-safe renames via apply rename-preview (--define-in, --in-file, --kind).

  • #167 231d6cc Thanks @SutuSebastian! - Add MCP/HTTP transport parity for coverage ingest and query baselines: new ingest_coverage tool (CLI twin codemap ingest-coverage --json) and optional baseline param on query / query_recipe (same diff envelope as codemap query --baseline). Tool count 19 → 20.

0.10.0

Minor Changes

  • #164 8c7064a Thanks @SutuSebastian! - Add optional heuristic call edges (calls.provenance) for JSX parent→child composition. Schema rebuild to v37. Enable via .codemap/config synthesis.heuristicCalls: true (default off). Bundled recipe calls-including-heuristic; call-path excludes heuristics by default.

  • #162 6e50d77 Thanks @SutuSebastian! - Add two-phase call resolution (unresolved_calls staging, calls.callee_symbol_id / callee_resolution_kind). Schema version 36 — existing indexes rebuild on next codemap run.

Patch Changes

  • 7b0406a Thanks @SutuSebastian! - Ship the apply substrate: recipe-driven codemap apply for stale imports, deprecated migrations, import-source moves, JSX prop renames, and scoped rename-preview (define_in homonyms). Add --rows, --diff-input, fixpoint --until-empty, optional --commit, auto_fixable/--force, and apply.autoApplyRecipes allowlist. MCP/HTTP twins: apply, apply_rows, apply_diff_input.

0.9.5

Patch Changes

  • #160 b1e3d58 Thanks @SutuSebastian! - Add CLI twins for MCP query composers and resources so shell-only consumers get the same JSON payloads: codemap query batch, trace, explore, node, file, schema, symbols, and context --include-snippets.

0.9.4

Patch Changes

  • #158 e8ea640 Thanks @SutuSebastian! - Add codemap agents init --targets and --link-mode for non-interactive IDE wiring. Combine with --mcp to write MCP config only for selected integrations (e.g. Cursor + Copilot without Continue/Cline). Mutually exclusive with --interactive.

0.9.3

Patch Changes

  • #156 ae4a143 Thanks @SutuSebastian! - codemap agents init --mcp now includes --root ${workspaceFolder} in the VS Code / Copilot MCP config (.vscode/mcp.json), same as Cursor. Re-run codemap agents init --mcp to upgrade an existing .vscode/mcp.json from older init output (or --interactive and select Copilot only).

0.9.2

Patch Changes

  • #152 150c6c6 Thanks @SutuSebastian! - Adaptive snippet budgets for trace, explore, and node scale with indexed file count when budget_chars is omitted (explicit override unchanged). explore also applies adaptive row limits internally (no transport override).

  • #155 450ca2e Thanks @SutuSebastian! - codemap agents init is safer on re-run: IDE mirrors sync bundled template paths only; --force overwrites IDE mirrors only when they carry codemap-init:managed or match the legacy mirror heuristic (pre-marker bundled copies); invalid MCP JSON shapes are rejected instead of reset (even with --force).

  • #149 41a4184 Thanks @SutuSebastian! - Add index_freshness metadata on context, MCP tool responses, HTTP headers, and boot stderr warnings so agents can detect commit drift, pending watcher sync, and disk-ahead-of-index states before trusting structural queries.

  • #154 1bcca3a Thanks @SutuSebastian! - codemap agents init --mcp writes PM-aware MCP spawn commands (e.g. npx codemap, pnpm exec codemap, yarn exec codemap, bunx codemap, or dlx @stainless-code/codemap@latest) instead of assuming global codemap on PATH.

  • #153 048278b Thanks @SutuSebastian! - MCP session lifecycle hygiene: stdio disconnect detection (stdin EOF, stdout EPIPE, parent-PID poll) with graceful watcher shutdown on client exit; HTTP serve --watch refcount-gates the watcher per request (5s release grace, /health excluded). No MCP idle shutdown.

  • #151 e717652 Thanks @SutuSebastian! - Rich context bootstrap: start_here with intent-ranked recipe cards, inline index summary, budget-capped hub leaders with export signatures (adaptive caps by repo size), debug-biased marker samples, and optional include_snippets on MCP/HTTP context (no-op when compact: true). Legacy hubs keeps the bundled fan-in recipe default limit; prefer start_here.hub_leaders for signatures.

0.9.1

Patch Changes

  • #146 7afc9eb Thanks @SutuSebastian! - Fix codemap --full (and other worker-pool parses) appearing to hang ~120s after stats print — clear parse timeout timers when workers respond instead of leaving orphaned setTimeout handles on the event loop.

0.9.0

Minor Changes

  • #129 6648add Thanks @SutuSebastian! - Add cross-process index lock with codemap unlock, and append parse failures to <state-dir>/errors.log.

  • #130 f5374b8 Thanks @SutuSebastian! - Add per-file parse timeouts with worker recycle during full and incremental indexing; failures log to errors.log and appear in the index summary.

Patch Changes

  • #132 8a1de53 Thanks @SutuSebastian! - Add affected-tests recipe and codemap affected CLI for reverse-dependency test selection from changed files.

  • #135 c4b4b36 Thanks @SutuSebastian! - Add codemap agents init --mcp — project-level MCP config for Cursor, Claude Code, VS Code, Continue, Cline, Amazon Q (workspace .amazonq/default.json + legacy .amazonq/mcp.json), and Gemini CLI (Windsurf when that integration is selected), with idempotent JSON merge and Claude mcp__codemap__* permissions.

  • #138 829075c Thanks @SutuSebastian! - Add field-qualified symbol discovery on codemap show --query and MCP/HTTP show / snippet via a query argument (kind:, name:, path:, in: + optional free text). Includes parameterized SQL engine, optional FTS join, --print-sql Moat-A transparency, and {matches, disambiguation?, warning?} envelope parity across CLI, MCP, and HTTP.

  • #124 04c4aa7 Thanks @SutuSebastian! - Honor --state-dir for project recipes; populate function_params.owner_kind; register MCP files/symbols resource templates with optional ?in= filter; watcher fixes for custom state dirs.

  • #133 386ffa6 Thanks @SutuSebastian! - Add MCP/HTTP affected tool — same preprocessor as codemap affected, composes the affected-tests recipe. Respects CODEMAP_MCP_TOOLS allowlist.

  • #126 ed4ca6b Thanks @SutuSebastian! - Add MCP initialize server instructions (tool-selection playbook) and CODEMAP_MCP_TOOLS env for subset tool registration.

  • ee9f6b2 Thanks @SutuSebastian! - Bump oxc-parser to ^0.133.0 and @typescript/native-preview to the latest 7.0 dev build.

  • 9fa1e9d Thanks @SutuSebastian! - Pin runtime and dev dependencies to exact versions in package.json (drop carets) and refresh bun.lock. Dev tooling: oxfmt 0.52, oxlint 1.67, @typescript/native-preview 20260526. Oxlint 1.67 drops a redundant escape in show-search-mode.ts glob regex (no behavior change).

  • #131 a8cf25b Thanks @SutuSebastian! - Add call-path and symbol-neighborhood query recipes for cycle-safe call-graph tracing and bidirectional symbol exploration.

  • #143 e475d20 Thanks @SutuSebastian! - Fix type heritage resolve edge cases: default-import bases, re-export barrel incremental scope, homonym dedupe in ancestor walks, and (expression) complex extends handling.

  • #142 a085ec6 Thanks @SutuSebastian! - Add type_heritage substrate and rewire type-ancestors / type-descendants recipes to JOIN indexed heritage edges instead of parsing symbols.signature.

  • #141 bd5a1fa Thanks @SutuSebastian! - Add type-ancestors and type-descendants query recipes for extends/implements hierarchy walks (backed by the type_heritage substrate after #142).

  • #127 4318cc4 Thanks @SutuSebastian! - Add WSL watch policy (auto-disable on /mnt/* mounts) and opt-in git hooks for background incremental index when the watcher is off.

0.8.0

Minor Changes

  • #107 f24f8b6 Thanks @SutuSebastian! - Substrate tiers 1–6 remainder (excludes C.9 / files.is_entry). Schema bump SCHEMA_VERSION 27 → 34 — first run after upgrade auto-rebuilds .codemap/index.db via the existing version-mismatch path.

    Tier 1 — call + import precision

    • calls.{args_count,is_method_call,is_constructor_call,is_optional_chain}; constructor vs call dedup key fix
    • symbols.{return_type,is_async,is_generator}
    • Side-effect import_specifiers rows (kind='side-effect') + import_id FK to imports

    Tier 2 — bindings

    • bindings.resolution_kind='re-exported' when resolution walks a re-export chain

    Tier 3 — JSX

    • New tables jsx_elements / jsx_attributes; extractor with per-file parent linking post-pass

    Tier 5 — behavioral

    • New tables async_calls, try_catch, decorators, jsdoc_tags; context stack for in_loop / in_try

    Tier 6 — module graph (no entry points)

    • dynamic_imports table + extractor
    • Post-pass files.is_barrel and parse-time files.has_side_effects

    Recipes + goldens: find-call-sites (extended), find-async-functions, find-dynamic-imports, find-barrel-files, find-side-effect-files, find-re-exported-bindings, find-side-effect-imports, find-jsx-usages, find-await-in-loop, find-swallowed-errors, find-decorator-usage, find-throws-jsdoc, plus golden coverage for fan-out-sample / fan-out-sample-json and substrate regression tests.

    Read-only CLI hardening: printQueryResult (ad-hoc codemap query "<SQL>") now sets PRAGMA query_only = 1, closing the last gap vs queryRows / executeQuery (#107).

    Out of scope: C.9 plugin layer (files.is_entry, reachability-from-entry); tiers 7–13.

    Migration: No in-place DDL — rebuild on schema mismatch preserves user-data tables (coverage, query_baselines, recipe_recency). Re-run codemap --full (or any index) after upgrade.

Patch Changes

  • #118 665c19a Thanks @SutuSebastian! - Reject apply targets that are symlinks so phase-2 rename cannot replace a link with a regular file.

  • #117 5ee5f2e Thanks @SutuSebastian! - Fail benchmark reindex runs when the spawned indexer exits non-zero instead of recording misleading timings.

  • #109 02a628f Thanks @SutuSebastian! - Validate codemap --files operands before indexing starts.

  • #110 7767a97 Thanks @SutuSebastian! - Validate VERSION output in detect-pm before writing GitHub Actions outputs.

  • #112 ec31949 Thanks @SutuSebastian! - Harden apply and diff-json path containment against traversal outside the project root.

  • #123 54ad25a Thanks @SutuSebastian! - Fix high-severity bugs (describe.each parent stack, git porcelain -z paths, CLI symlink entry, pr-comment TTY stdin), medium bugs (changed-since -z paths, perf baseline RUNS guard, qualified typeof, decorator args_text, for-of binding refs, HTTP body drain, benchmark regex validation, jsx INSERT RETURNING id, sqlite stmt cache on close), and low bugs (CLI parse guards, incremental delete transaction, apply summary.files, extension case, pnpm # paths, coverage db.transaction, impact walk delimiter, worker errors, pointer dedup, benchmark readAll visibility).

  • #114 ae54ce0 Thanks @SutuSebastian! - Fix diff preview deletions, config empty-array overrides, resolver path containment, impact call-site selection, and FTS cleanup on file delete.

  • #122 4e191ba Thanks @SutuSebastian! - Run full check (not build-only) in prepublishOnly so npm publish cannot skip tests or typecheck.

  • #113 126066d Thanks @SutuSebastian! - Reject opaque Origin: null in codemap serve CSRF checks.

  • #120 17dcbd1 Thanks @SutuSebastian! - Reject unexpected arguments on codemap skill and codemap rule instead of silently printing bundled content.

  • #119 cf0532b Thanks @SutuSebastian! - Print symbol signature in codemap snippet terminal output, matching codemap show and the documented contract.

  • #116 a444c40 Thanks @SutuSebastian! - Fix V8 coverage ingest so innermost-wins applies across all FunctionCoverage entries in a script, not per-function iteration order.

  • #115 eb18750 Thanks @SutuSebastian! - Fix watcher priming race, parse-worker stat errors, incremental rename cleanup, and several indexer extractor gaps (scopes, references, tests.each, process.env, CSS imports).

  • #121 f5d013c Thanks @SutuSebastian! - Reject malformed CODEMAP_PARSE_WORKERS values (e.g. 2abc, 1.5) instead of silently truncating with parseInt.

0.7.5

Patch Changes

  • #96 cc8daed Thanks @SutuSebastian! - Performance: full-rebuild wall down ~21% on small trees and ~18% on a real-world ~2k-file external corpus. Headline contributor: collectFiles switched to a single tinyglobby call with ignore patterns (collect_ms -93%, file set bit-identical via followSymbolicLinks: false). Bindings/cycles/re-exports phase now keeps the bulk-INSERT PRAGMA-OFF window open through full rebuild (bindings_ms -33% on the 2k corpus). Plus query_batch single connection, incremental double-read kill, shared countLines helper, stmtCache placeholder memo, SQLite busy_timeout, adapter Map lookup, byte-order sort, FTS5 batched delete, and getAllFileHashes hoist.

    Instrumentation: IndexPerformanceReport now surfaces bindings_ms, module_cycles_ms, re_export_chains_ms (previously rolled into total_ms with no breakdown). Set CODEMAP_PERFORMANCE_JSON=<path> to dump the report as JSON post-run (no new CLI flag added).

    Knobs: CODEMAP_PARSE_WORKERS=N (clamped [1, 32]) overrides the default max(2, min(cpus, 6)) worker count. bun run check:perf-baseline + a non-blocking CI job (📈 Perf baseline (self-index)) guard against per-phase regressions vs fixtures/benchmark/perf-baseline.json; CODEMAP_PERF_RUNS / CODEMAP_PERF_REGRESSION_PCT / CODEMAP_PERF_NOISE_FLOOR_MS tune the checker.

    Behavior change (correctness hardening): queryRows (the implementation behind Codemap.query(), codemap apply recipe SQL execution, and bun run test:golden) now sets PRAGMA query_only = 1 to mirror executeQuery's read-only enforcement. DML / DDL slipping through these paths now errors at SQLite instead of mutating the database. All these call sites are contractually read-only; this turns a contract into an enforceable boundary. Anyone who relied on undocumented mutation through Codemap.query("DELETE FROM ...") would now get an error — but that was always API abuse. (Ad-hoc CLI SQL via printQueryResult was a separate path; it gained the same guard in 0.8.0 — see that release entry.)

    Full design context: docs/plans/perf-triangulation-rollout.md (synthesis + execution rollout of 5 independent perf/architecture audits authored 2026-05-17).

0.7.4

Patch Changes

  • #93 d92b917 Thanks @SutuSebastian! - Fix: project recipes (<root>/.codemap/recipes/<id>.sql) are now visible via the CLI.

    parseQueryRest validates --recipe <id> / --recipes-json / --print-sql <id> BEFORE runQueryCmd calls bootstrapCodemap, so the recipe registry hit getProjectRoot() pre-init, the throw was silently caught, and the loader fell back to bundled-only. The MCP and HTTP transports always bootstrap before reaching the loader, so project recipes worked there throughout — only the CLI path was affected.

    Fix is surgical:

    • New setQueryRecipesProjectRoot(root) API in application/query-recipes.ts — caller-supplied root takes precedence over the runtime config (which isn't initialised yet during argv parse).
    • cli/main.ts calls it once right after parseBootstrapArgs returns root, so every subsequent verb (parser-side and post-bootstrap) sees the same value.

    Single source of truth: the override is the same root bootstrapCodemap resolves to — no parallel walk-up heuristic, no new env var, no second resolution path. The registry cache invalidates when the override changes.

    Adds regression tests (query-recipes.pre-bootstrap.test.ts) exercising the override-only path (no initCodemap) plus a dogfood project recipe (.codemap/recipes/src-deprecated.sql) that scopes the bundled deprecated-symbols audit to src/ only — useful for codemap's own deprecation lifecycle, and a permanent regression case against this bug recurring.

    Consumers with project recipes authored on 0.6.x–0.7.2 didn't need to wait — recipes worked via MCP / HTTP throughout. After upgrading, the CLI auto-picks them up.

0.7.3

Patch Changes

  • #91 82bca4b Thanks @SutuSebastian! - Slim the auto-generated <state-dir>/.gitignore header for consumer clarity:

    • Drop the internal function-name reference (ensureStateGitignore) — consumers can't look it up.
    • Drop the "Rule 9 analogue" / "bump alongside any new cache" line — it was guidance for codemap contributors, leaking into every consumer's checkout.
    • Reframe "blacklist" / parenthetical mention of tracked files in plainer language.

    Existing two-line header (# codemap-managed — edits will be overwritten by ensureStateGitignore. / # Blacklist of generated artifacts...) becomes:

    # Managed by codemap — overwritten on next run.
    # Generated artifacts only; user-authored config (config.*, recipes/) stays tracked.
    

    One-time rewrite on consumer side. The reconciler matches the canonical body via exact string comparison, so every consumer's next codemap run rewrites <state-dir>/.gitignore to the new shape (no entries change — only the comment lines). Harmless; the blacklist entries (index.db, index.db-shm, index.db-wal, audit-cache/) are unchanged.

0.7.2

Patch Changes

  • #89 6e53458 Thanks @SutuSebastian! - codemap audit --base <ref> now materialises the sha-keyed cache via git archive | tar -x instead of git worktree add. The cache entry at .codemap/audit-cache/<sha>/ is a plain extracted tree with no .git pointer file and no registered git worktree, so:

    • git clean -xdf sweeps it without needing -ff (which used to also nuke unrelated nested repos).
    • Plain rm -rf works — no more dangling registrations under <repo>/.git/worktrees/ that needed git worktree prune.

    All other invariants preserved: cache path layout, hit detection (<sha>/.codemap/index.db exists), atomic populate (per-pid temp + POSIX rename), LRU eviction (5 entries / 500 MiB), error code names (worktree-add-failed etc. kept for API stability — external consumers discriminate on code, not the underlying primitive).

    Also: the cache reindex now stamps meta.last_indexed_commit with the resolved sha directly instead of shelling out to git rev-parse HEAD inside the cache dir — silences a fatal: not a git repository stderr line that older revisions leaked.

    Migration — existing consumers with .codemap/audit-cache/<sha>/ worktrees from earlier versions can run git worktree prune once after upgrade to clear dangling registrations. The registrations are inert when the path is gone, so skipping the prune is harmless.

0.7.1

Patch Changes

  • 904e4a5 Thanks @SutuSebastian! - Two skill / docs clarifications that ship in the live-served skill (codemap skill / codemap://skill / GET /resources/<encoded-skill-uri>):

    • parent_name vs scope_local_id (#86). parent_name is the nearest named enclosing scope — it walks past anonymous arrows / IIFEs / callbacks, so parent_name IS NULL matches both true module-scope symbols and symbols inside top-level anonymous IIFEs. For a strict "module-scope only" filter use scope_local_id = 0. docs/architecture.md symbols.parent_name column doc + 40-query-patterns.md mutability example updated accordingly.

    • imports.source vs imports.resolved_path (#87). The single most common cause of empty imports result sets on alias-using codebases (TS paths, Webpack / Vite aliases, Node subpath imports #internal/…, monorepo workspaces) is picking the wrong column. The skill now explicitly teaches: filter source for "via alias / package name", filter resolved_path for "via on-disk path", and WHERE resolved_path IS NULL for "external packages only".

    No schema change, no CLI / API change. Patch bump; existing .codemap/index.db unaffected.

0.7.0

Minor Changes

  • #84 e003218 Thanks @SutuSebastian! - symbols.kind distinguishes const / let / var instead of collapsing all three into 'const'. Schema bump SCHEMA_VERSION 26 → 27 — first run after upgrade auto-rebuilds .codemap/index.db via the existing version-mismatch path; consumer queries see the new values immediately.

    What changes:

    • let x = 1 now emits kind = 'let' + signature = 'let x'.
    • var y = 2 now emits kind = 'var' + signature = 'var y'.
    • const z = 3 unchanged (kind = 'const' + signature = 'const z').
    • Destructuring patterns inherit the declaration keyword: let { a, b } = obj → both a and b are kind = 'let'.
    • for (let x of arr) { ... } body bindings inherit the keyword (kind = 'let').
    • Arrow / function init still wins over the keyword: const handler = () => 1 and let handler = () => 1 both emit kind = 'function'.

    Breaking — but pre-v1 the breakage IS the fix. Any query that filtered WHERE kind = 'const' to mean "all variable bindings" was silently over-matching every let and var. Post-upgrade the filter is precise; queries that wanted the over-match should widen to WHERE kind IN ('const', 'let', 'var'). Affected paths in this PR: the 40-query-patterns.md const-values example (now demonstrates the precise filter + adds two new patterns that depend on it — "lets that should be const" and "consts that get illegally written"), and find-write-sites.md prose where the recipe's documented JOIN trick now works as described.

    Mutability filters that finally work:

    -- bindings declared `let` but never reassigned — candidates to tighten to `const`
    SELECT s.name, s.file_path, s.line_start FROM symbols s
    WHERE s.kind = 'let'
      AND NOT EXISTS (
        SELECT 1 FROM "references" r
        WHERE r.name = s.name
          AND r.file_path = s.file_path
          AND r.is_write = 1
          AND r.line_start > s.line_start
      );
    
    -- `const`s that get reassigned anyway (TypeScript usually catches it; queryable here for completeness)
    SELECT s.name, s.file_path, s.line_start FROM symbols s
    JOIN "references" r ON r.name = s.name AND r.file_path = s.file_path
    WHERE s.kind = 'const' AND r.is_write = 1 AND r.line_start > s.line_start;

    find-symbol-by-kind recipe params updated to enumerate the new values explicitly.

    file_metrics keyword counts populate toolet_count / const_count / var_count were previously hardcoded to 0 (// let/const/var distinction not yet tracked per the in-source TODO). They now reflect the actual per-file counts. docs/architecture.md § file_metrics drops the "Reserved (parser-keyword variant TBD)" notes.

0.6.1

Patch Changes

  • #82 8e8aae0 Thanks @SutuSebastian! - Fix resolveBundledRecipesDir() path resolution — the 40 bundled recipes were unreachable at runtime in 0.6.0's published artifact. The resolver had one extra .. segment relative to where the bundler emits the dist chunk; bunx codemap query --recipes-json returned [] and bunx codemap query --recipe <id> rejected every bundled id with unknown recipe.

    The fix derives the bundled-recipes path off resolveAgentsTemplateDir() (same pattern used by resolveAgentContentDir()) so a single resolver handles both source-mode (bun src/index.ts) and dist-mode (node dist/index.mjs) without environment-specific branching — every chunk lands flat in dist/ regardless of the source file's nested depth.

    Discovered by a downstream consumer immediately after bun install @stainless-code/codemap@0.6.0. Regression guard: new src/application/query-recipes.dist.test.ts asserts existsSync(resolveBundledRecipesDir()) + catalog populates; CI gains a node dist/index.mjs query --recipes-json smoke step that exits non-zero on an empty catalog.

0.6.0

Minor Changes

  • #80 7c3ba71 Thanks @SutuSebastian! - codemap skill / codemap rule — live-served agent content. Consumer-disk .agents/skills/codemap/SKILL.md and .agents/rules/codemap.md are now thin pointer files (~16-22 lines); the full content is served live by the installed binary, so bun update @stainless-code/codemap automatically refreshes what agents see without re-running agents init.

    Three transports, one engine:

    • CLI: codemap skill / codemap rule
    • MCP: resources codemap://skill / codemap://rule
    • HTTP: GET /resources/{encoded-uri} against codemap serve

    All three resolve through the same assembleAgentContent(kind) function. MCP and HTTP share a lazy per-process cache.

    Section assembler with *.gen.md renderers: templates/agent-content/<kind>/*.md files concatenate in lexical name order. Files ending in .gen.md route through RENDERERS in src/application/agent-content.ts — today, 20-recipes.gen.md regenerates the recipe catalog from listQueryRecipeCatalog() on every fetch, and 30-schema.gen.md regenerates table DDL from createTables(). Adding a recipe under templates/recipes/ or a column in src/db.ts now surfaces in the served skill automatically with zero template edits.

    Pointer protocol + staleness detection: every consumer-disk pointer carries <!-- codemap-pointer-version: N -->. On startup, codemap scans the consumer's .agents/{skills/codemap/SKILL,rules/codemap}.md; if the stamp is < EXPECTED_POINTER_VERSION (or absent on a fat legacy file > 50 lines), a one-line stderr nag prints with the fix command (codemap agents init --force). Warning is stderr-only so codemap skill > file.md stays clean.

    Rule trimmed to priming surface: the always-on rule shrank from 248 → 102 lines (~70% token reduction per turn) — STOP banner + trigger patterns table + top-11 quick reference queries + pointer to the skill for full reference. CLI command table / MCP narrative / audit + apply detail moved into the skill where they belong (on-demand, not every-turn).

    Migration: existing consumers re-run codemap agents init --force to swap their fat .agents/ files for the new pointer templates (the staleness nag prompts them on first invocation).

  • #78 84f9b97 Thanks @SutuSebastian! - codemap apply <recipe-id> — substrate-shaped fix executor over the existing --format diff-json row contract. The recipe SQL describes the transformation ({file_path, line_start, before_pattern, after_pattern} rows); codemap is the executor. Floor "No fix engine" preserved — codemap doesn't synthesise edits, it only executes the hunks the recipe row described.

    Three transports, one engine:

    • CLI: codemap apply <recipe-id> [--params k=v[,k=v]] [--dry-run] [--yes] [--json]
    • MCP tool: apply (registered alongside impact / show / snippet)
    • HTTP: POST /tool/apply

    All three dispatch the same pure applyDiffPayload engine in application/apply-engine.ts.

    Decisions worth knowing (Q1–Q10 locked in docs/plans/codemap-apply.md, lifted into docs/architecture.md § Apply wiring on this PR):

    • Apply-by-default, --dry-run opts into preview. Verb-name semantics + git apply / terraform apply precedent.
    • Per-recipe-run all-or-nothing (Q2 (c)). Phase 1 validates every row first; any conflict aborts phase 2 entirely before any file is touched. Cross-file invariants matter — rename-preview produces a definition row + N import rows, and partial application leaves the project syntactically broken.
    • Scan-and-collect conflicts (Q3 (b)). Phase 1 walks every row and collects all conflicts in one pass — better remediation UX than fail-fast.
    • TTY prompt + --yes gate (Q6 (a)). Interactive contexts (TTY) get a Proceed? [y/N] prompt with default-N; non-interactive contexts (CI / agents / MCP / HTTP) require --yes (or yes: true) explicitly. --dry-run + --yes mutually exclusive.
    • Substring match per row, single-line (Q8 (a)). Mirrors buildDiffJson's contract verbatim — actual.includes(before_pattern) + actual.replace(before, after) with $-pre-escape per String.prototype.replace's GetSubstitution rule. Exemplar: templates/recipes/rename-preview.sql emits before_pattern = old_name (the bare identifier). When before_pattern appears more than once on the line (e.g. const foo = foo();), only the leftmost is replaced — same shape --format diff previews; recipe authors normalise their SQL if they need a different occurrence.
    • Path-containment guard. Every file_path is rejected with a path escapes project root conflict if it's absolute or if path.resolve(projectRoot, file_path) lands outside the project root. Defends the CLI + MCP + HTTP write paths against malicious or malformed recipe rows.
    • Overlap detection. Two rows targeting the same (file_path, line_start) are rejected with a duplicate edit on same line conflict during phase 1. Without it, the second row's substring assertion would fail mid-phase-2 (after earlier files in alphabetical order had already been renamed) — that would leave the project in a partial-write state and violate Q2 (c).
    • Atomic per-file writes via temp + rename. Sibling <file>.codemap-apply-<rand>.tmp then renameSync — POSIX-atomic so concurrent readers see either pre-rename or post-rename content, never a torn write.
    • Q7 idempotency (conflict-only path). Re-running on already-applied code reports line content drifted with actual_at_line showing the post-rename content; user re-runs codemap to refresh the index → next run produces 0 rows → vacuous clean apply.
    • Single envelope shape across modes (Q5). {mode, applied, files, conflicts, summary} — same shape for dry-run and apply; consumers pattern-match on mode + applied.
    • No SARIF / annotations. Apply is a write action, not a findings list.

    Boundary discipline (Q10): only cli/cmd-apply.ts + application/tool-handlers.ts may import the apply engine — re-runnable kit at docs/architecture.md § Boundary verification — apply write path.

    Plan: PR #77 (merged). Implementation: this PR.

  • #79 ec91bdf Thanks @SutuSebastian! - codemap-richer-index — substrate extraction across 12 tiers. Schema bump (SCHEMA_VERSION 10 → 26) — first run after upgrade rebuilds .codemap/index.db from source.

    10 new substrate tables: import_specifiers, scopes, references, bindings, function_params, file_metrics, re_export_chains, module_cycles, runtime_markers, test_suites.

    Column additions: symbols.{name_column_start, name_column_end, scope_local_id, body_line_count, param_count, nesting_depth} · calls.{line_start, column_start, column_end} · exports.{is_re_export, line_start, line_end, column_start, column_end} · markers.{column_start, column_end}.

    12 new recipes: find-references · find-symbol-references · find-write-sites · find-by-param-type · large-functions · deeply-nested-functions · circular-imports · barrel-chains · find-leftover-console · env-var-audit · find-skipped-tests · tests-by-file.

    Architecture: modular extractor pattern (R.17) splits parser.ts into per-tier extractors under src/extractors/ with a shared ExtractContext. Targeted reindex stays sub-100ms; full reindex includes bindings resolution + Tarjan SCC + re-export chain materialisation.

    Reference precision: references table emits every identifier USE with column-precise positions; kind='member' rows distinguish non-computed property access from bindings. Native JSX tags + JSXAttribute names + long-hand object-literal keys are suppressed. TSQualifiedName (e.g. React.ReactNode) splits into namespace head (kind='type') + member tail (kind='member'). Bindings resolver (full-rebuild only) walks same-file scope → imports → globals → unresolved with deduped TypeScript / DOM / Node / ES global sets. Re-export chains followed up to 10 hops with cycle detection.

    Dependency bumps: oxc-parser 0.127 → 0.130 · zod 4.3 → 4.4 (dedupe override added so the MCP SDK keeps a single $ZodType identity) · tsdown 0.21 → 0.22 (declared unrun as devDep to unblock CI build under Node's tsdown binstub).

    Docs sync: docs/architecture.md § Schema reflects every new table + column; docs/glossary.md gains 10 new entries; docs/golden-queries.md + fixtures/golden/ regenerated. Templates (templates/agents/) updated with the new schema overview + trigger patterns.

0.5.0

Minor Changes

  • #35 119db38 Thanks @SutuSebastian! - feat(mcp): codemap mcp — Model Context Protocol server (agent-transports v1)

    Adds the codemap mcp top-level command — boots an MCP server over stdio so agent hosts (Claude Code, Cursor, Codex, generic MCP clients) call codemap as JSON-RPC tools instead of shelling out per query. Eliminates the bash round-trip on every agent invocation.

    Surface (one tool per CLI verb plus query_batch, all snake_case):

    • query, query_batch, query_recipe, audit, save_baseline, list_baselines, drop_baseline, context, validate
    • Resources: codemap://recipes, codemap://recipes/{id}, codemap://schema, codemap://skill (lazy-cached)

    query_batch is MCP-only — N statements in one round-trip with batch-wide-defaults + per-statement-overrides (items are string | {sql, summary?, changed_since?, group_by?}). Per-statement errors are isolated. save_baseline ships as one polymorphic tool ({name, sql? | recipe?} with runtime exclusivity check) mirroring the CLI's single --save-baseline=<name> verb.

    Output shape is verbatim from each tool's CLI counterpart's --json envelope (no re-mapping). Bootstrap once at server boot; tool handlers reuse existing engine entry-points (executeQuery, runAudit, etc.) — no duplicate business logic.

    New dep: @modelcontextprotocol/sdk.

    HTTP API (codemap serve) stays in roadmap backlog; design points (tool taxonomy + output shape) are reserved in docs/architecture.md § MCP wiring so HTTP inherits them when a concrete consumer asks.

  • #74 7889fed Thanks @SutuSebastian! - codemap audit --format <text|json|sarif> — emit a SARIF 2.1.0 doc directly from the audit envelope, no JSON→SARIF transform step needed. One rule per delta key (codemap.audit.files-added, codemap.audit.dependencies-added, codemap.audit.deprecated-added); one result per added row; severity = warning (audit deltas are more actionable than per-recipe note). Locations auto-detected via the same file_path / path / to_path / from_path priority list that query --format sarif uses; line ranges (line_start / line_end) populate the SARIF region. Pure output-formatter addition on top of the existing audit envelope; no schema impact.

    --json stays as the shortcut for --format json (backward-compatible). --json + --format <other> rejected as a contradiction. --summary is a no-op with --format sarif (SARIF results are per-row, not counts) and surfaces a stderr warning.

    removed rows are intentionally excluded from SARIF output — SARIF surfaces findings to act on, not cleanups. Location-only rows (e.g. files-added has only path) get a "new files: src/foo.ts" message instead of the generic "(no message)" fallback.

    This is the first half of Slice 1 from the GitHub Marketplace Action plan — independently useful for any CI consumer running codemap audit who wants Code Scanning surface without a translation layer; required for the upcoming Marketplace Action's headline default command.

  • #72 2c3045d Thanks @SutuSebastian! - feat(boundaries): config-driven architecture-boundary rules + boundary-violations recipe

    Adds the smallest substrate for first-class architecture boundary checks. Schema bump 8 → 9.

    Configure

    import { defineConfig } from "@stainless-code/codemap";
    
    export default defineConfig({
      boundaries: [
        {
          name: "ui-cant-touch-server",
          from_glob: "src/ui/**",
          to_glob: "src/server/**",
        },
      ],
    });

    action defaults to "deny" (the only shape v1 surfaces); "allow" reserves the slot for future whitelist semantics.

    Substrate

    • New config field boundaries: BoundaryRule[] on the Zod user-config schema (src/config.ts); validated at config-load time.
    • New table boundary_rules(name PK, from_glob, to_glob, action CHECK IN ('deny','allow')) (STRICT, WITHOUT ROWID) — fully derived from config, dropped on --full / SCHEMA_VERSION rebuilds and re-filled by the next index pass.
    • New helper reconcileBoundaryRules(db, rules) in src/db.ts; called from runCodemapIndex after createSchema so the table tracks config exactly.
    • New runtime accessor getBoundaryRules().

    Recipe

    templates/recipes/boundary-violations.{sql,md} joins dependencies × boundary_rules via SQLite GLOB and surfaces violating import edges as locatable rows. --format sarif and --format annotations light up automatically (the recipe aliases dependencies.from_path to file_path). Use as a CI gate:

    codemap query --recipe boundary-violations --format sarif > findings.sarif

    Lockstep

    • docs/architecture.md § Schema gains a boundary_rules subsection.
    • docs/glossary.md adds boundaries / boundary_rules / boundary-violations entry.
    • docs/roadmap.md § Backlog removes the now-shipped item per Rule 2.
    • templates/agents/rules/codemap.md, .agents/rules/codemap.md, templates/agents/skills/codemap/SKILL.md, .agents/skills/codemap/SKILL.md, and README.md all document the new shape.

    Tests

    src/application/boundary-rules.test.ts covers schema creation, idempotent reconciliation, CHECK constraint, and the recipe SQL against a synthetic dependency graph. src/config.test.ts covers Zod validation including default-action filling and unknown-action rejection.

  • #52 fe5a355 Thanks @SutuSebastian! - codemap audit --base <ref> — ad-hoc structural-drift audit against any git committish (origin/main, HEAD~5, <sha>, tag, …). Closes the highest-frequency post-watch agent loop: "what changed structurally between this branch and origin/main?". Replaces today's 3-step --baseline dance (switch branches, reindex, save baselines, switch back) with one verb.

    Three transports, one engine:

    • CLI: codemap audit --base <ref> [--<delta>-baseline <name>] [--summary] [--json] [--no-index]
    • MCP tool: audit with new base?: string arg
    • HTTP: POST /tool/audit (auto-wired via the existing dispatcher)

    All three dispatch the same pure runAuditFromRef engine in application/audit-engine.ts.

    How it works:

    1. git rev-parse --verify "<ref>^{commit}" resolves <ref> to a sha (clean error on non-git or unresolvable ref).
    2. Cache lookup at <projectRoot>/.codemap/audit-cache/<sha>/.codemap.db. Hit → sub-100ms; miss → continue.
    3. Atomic populategit worktree add to a per-pid temp dir + runCodemapIndex({mode: "full"}) against the worktree's .codemap.db + POSIX rename claims the final <sha>/ slot. Concurrent CI matrix runs against the same sha race-safely without lock files (loser's rename fails with EEXIST → falls through to cache hit).
    4. Run each delta's canonical SQL on the cached DB vs the live DB; diffRows (existing helper) computes {added, removed}.
    5. Compose AuditEnvelope with per-delta base.source: "ref" (new value) + base.ref (user-supplied string) + base.sha (resolved).

    Decisions worth knowing:

    • AuditBase is now a discriminated union — existing {source: "baseline", name, sha, indexed_at} rows untouched; new {source: "ref", ref, sha, indexed_at} arm. Consumers narrowing on base.source keep compiling.
    • Mutually exclusive with --baseline <prefix>. Parser + handler both guard. Per-delta --<key>-baseline overrides compose orthogonally with both, so --base origin/main --files-baseline pre-refactor-files is valid (mixed sources).
    • Eviction: hardcoded LRU 5 entries / 500 MiB; git worktree remove --force + rm -rf for each victim. Orphan .tmp.* dirs older than 10 min get swept on the next cycle. No config knobs in v1; defer to v1.x+ if real consumers ask.
    • Hard error on non-git projects. No graceful fallback — there's no meaningful "ref" without git. The other audit modes (--baseline, --<delta>-baseline) still work without git.
    • Env hygiene. All git spawns in audit-worktree.ts strip inherited GIT_* env vars so a containing git operation (e.g. running codemap from a husky hook) doesn't route worktree calls at the wrong index.

    Auto-.gitignore: codemap agents init now adds .codemap/audit-cache/ alongside .codemap.* so cached worktrees never get committed. .codemap/recipes/ stays git-tracked.

    Plan: PR #51 (merged). Implementation: PR #52.

  • #54 1313fc2 Thanks @SutuSebastian! - .codemap/ directory consolidation + self-healing files. Every codemap-managed path lives under a single configurable state directory (default .codemap/, override via --state-dir <path> or CODEMAP_STATE_DIR). Cleans up the dual-pattern surface (<root>/.codemap.db + <root>/.codemap/<thing>/) that's been growing with every cache PR; collapses the user .gitignore patching surface to zero.

    New layout:

    <root>/
    └── .codemap/                 ← override via --state-dir / CODEMAP_STATE_DIR
        ├── .gitignore            ← codemap-managed (self-healing); tracked
        ├── config.{ts,js,json}   ← was <root>/codemap.config.*; tracked
        ├── recipes/              ← user-authored SQL; tracked (existing)
        ├── index.db              ← was .codemap.db
        ├── index.db-shm          ← was .codemap.db-shm
        ├── index.db-wal          ← was .codemap.db-wal
        └── audit-cache/          ← was .codemap/audit-cache/ (existing)
    

    Self-healing files (D11): <state-dir>/.gitignore and <state-dir>/config.json are owned by idempotent ensure* reconcilers (src/application/state-dir.ts, src/application/state-config.ts) that run on every codemap boot — read → validate → reconcile → write only on drift. The setup logic IS the migration: future codemap versions add new generated artifacts to STATE_GITIGNORE_BODY (or extend the Zod schema), and every consumer's project repairs itself on the next codemap invocation. No more per-feature .gitignore patching in agents-init.ts.

    Pre-v1 — no migration shim:

    • <root>/.codemap.db<state-dir>/index.db (rename basename)
    • <root>/codemap.config.{ts,json}<state-dir>/config.{ts,js,json} (move file)
    • Existing dev clones: rm .codemap.db .codemap.db-shm .codemap.db-wal once and re-index; move codemap.config.* into .codemap/ (or set --config <old-path> to keep using the legacy location explicitly).

    New flags + env:

    • --state-dir <path> — override the state directory (resolves relative to project root).
    • CODEMAP_STATE_DIR — same, env-var form.

    Internal refactor: new src/cli/bootstrap-codemap.ts extracts the loadUserConfig + resolveCodemapConfig + initCodemap + configureResolver dance from 9 cmd-* files into one helper that also runs the self-healing reconcilers. Adding a new self-healing file is now a one-line addition there.

    Inspired by flowbite-react's .flowbite-react/.gitignore + setup-* pattern; expressed in codemap's own conventions (ensure* reconcilers, Zod schema as z.infer source of truth, pure {before, after, written} return shapes for testability).

    Plan: PR #53 (merged). Implementation: PR #54.

  • #50 90092ae Thanks @SutuSebastian! - codemap impact <target> — symbol/file blast-radius walker. Replaces hand-composed WITH RECURSIVE queries that agents struggle to write reliably with a single verb that walks the calls / dependencies / imports graphs (callers, callees, dependents, dependencies). Depth- and limit-bounded, cycle-detected.

    Three transports, one engine:

    • CLI: codemap impact <target> [--direction up|down|both] [--depth N] [--via dependencies|calls|imports|all] [--limit N] [--summary] [--json]
    • MCP tool: impact (registered alongside show / snippet)
    • HTTP: POST /tool/impact

    All three dispatch the same pure findImpact engine in application/impact-engine.ts per the post-PR #41 layering — adding tools never duplicates business logic.

    Decisions worth knowing:

    • Target auto-resolution. Contains / or matches files.path → file target; otherwise symbol (case-sensitive, exact). Symbol targets walk calls; file targets walk dependencies + imports (resolved_path only). Mismatched explicit --via choices land in skipped_backends (no error — agent sees why their selection yielded fewer rows than expected).
    • Cycle detection. SQLite has no native cycle predicate; we materialise a comma-bounded path string per row and instr it to break re-entry. Bounded depth + --limit (default 500) keep cyclic graphs cheap regardless. --depth 0 walks unbounded but stays cycle-detected and limit-capped.
    • Termination classification. summary.terminated_by: limit > depth > exhausted. CI gates can branch on it.
    • --summary shape. Trims the matches array but preserves summary.nodes — the jq '.summary.nodes' consumption pattern still works.
    • No SARIF / annotations. Impact rows are graph traversals, not findings — wrong shape for those formats.

    Engine sketch: one WITH RECURSIVE query per (direction, backend) combo, JS-side merge + dedup by (direction, kind, name?, file_path) keeping the shallowest depth, then summary.by_kind + terminated_by classification.

    Plan: PR #49 (merged). Implementation: PR #50.

  • #44 4ec51d8 Thanks @SutuSebastian! - codemap serve — HTTP server exposing the same tool taxonomy as codemap mcp over POST /tool/{name}. For non-MCP consumers (CI scripts, simple curl, IDE plugins that don't speak MCP).

    Default bind 127.0.0.1:7878 (loopback only — refuse 0.0.0.0 unless explicitly opted in via --host 0.0.0.0). Optional --token <secret> requires Authorization: Bearer <secret> on every request; GET /health is auth-exempt so liveness probes work without leaking the token. Bare node:http (no Express / Fastify dep) — runs on Bun + Node.

    Routes:

    • POST /tool/{name} — every MCP tool (query, query_recipe, query_batch, audit, context, validate, show, snippet, save_baseline, list_baselines, drop_baseline). Body {<args>}; response = same codemap query --json envelope (NOT MCP's {content: [...]} wrapper). format: "sarif" payloads ship as application/sarif+json; format: "annotations" as text/plain.
    • GET /resources/{encoded-uri} — mirror of MCP resources (codemap://recipes, codemap://recipes/{id}, codemap://schema, codemap://skill).
    • GET /health — liveness (auth-exempt); GET /tools / GET /resources — catalogs.
    • Errors: {"error": "..."} with HTTP status 400 / 401 / 404 / 500.
    • Every response carries X-Codemap-Version: <semver> so consumers can pin / detect upgrades.

    Internals: Tool bodies (application/tool-handlers.ts) and resource fetchers (application/resource-handlers.ts) are pure transport-agnostic — same handlers codemap mcp dispatches. No engine duplication; mcp-server.ts and http-server.ts both wrap the same ToolResult discriminated union.

    Security: CSRF + DNS-rebinding guard rejects requests with Sec-Fetch-Site: cross-site / same-site (modern-browser CSRF), any Origin header that isn't null (older-browser CSRF), and Host header mismatch on loopback bind (DNS rebinding) — runs on every request including auth-exempt /health. Defends against a malicious local webpage fetch-ing the API while the developer is browsing. Non-browser clients (curl, MCP hosts, CI scripts) don't send those headers and pass through. SIGINT / SIGTERM → graceful drain. 1 MiB request-body cap (DoS protection). SQLite reader concurrency handles parallel requests; PRAGMA query_only = 1 set per connection.

  • #47 5ef9ce4 Thanks @SutuSebastian! - codemap watch — long-running process that re-indexes changed files in real time so every CLI / MCP / HTTP query reads live data without a per-query reindex prelude. Eliminates the single biggest source of agent-side friction: "is the index stale right now?"

    Three shapes:

    • Standalone: codemap watch [--debounce 250] [--quiet] — foreground process; logs reindex N file(s) in Mms per batch unless --quiet. SIGINT / SIGTERM drains pending edits.
    • MCP killer combo: codemap mcp --watch [--debounce <ms>] — boots stdio MCP server + watcher in one process. Long Cursor / Claude Code sessions never hit a stale index; agents stop having to remember to reindex between edit + query.
    • HTTP killer combo: codemap serve --watch [--debounce <ms>] — same shape for non-MCP consumers (CI scripts, IDE plugins, simple curl).

    Audit prelude optimization: when watch is active, mcp audit's default incremental-index prelude becomes a no-op (the watcher already keeps the index fresh — saves the per-request reindex cost). Explicit no_index: false still forces the prelude.

    Env shortcut: CODEMAP_WATCH=1 (or "true") implies --watch for mcp / serve — useful for IDE / CI launches that can't easily edit the spawn command.

    Backend: chokidar v5 (selected via 6-watcher audit in PR #46). Pure JS — runs identically on Bun + Node, no per-runtime branching, no native compile matrix on top of bun:sqlite / better-sqlite3. Cross-platform (macOS / Linux / Windows / WSL). Atomic-write + chunked-write detection out of the box. 1 dep (readdirp), 82 KB.

    Filtering: Only paths the indexer cares about trigger a reindex (TS / TSX / JS / JSX / CSS + project-local recipes under <root>/.codemap/recipes/). node_modules / .git / dist / configured excludeDirNames are skipped.

  • #57 b5679a6 Thanks @SutuSebastian! - 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:

    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.

  • #71 fc6790b Thanks @SutuSebastian! - feat(query): add --format diff and --format diff-json

    Adds transport-agnostic diff formatters for query row sets shaped as:

    SELECT
      'src/file.ts' AS file_path,
      42 AS line_start,
      'oldName' AS before_pattern,
      'newName' AS after_pattern
    • --format diff emits plain unified diff text, ready for git apply --check.
    • --format diff-json emits {files, warnings, summary} for agents that need structured hunks.
    • Source files are read at format time. If a file is missing or the indexed line no longer contains before_pattern, the formatter marks it missing / stale in diff-json and emits # WARNING: comments at the top of plain diff output.
    • Same formatter support is exposed through MCP / HTTP format: "diff" | "diff-json" on query and query_recipe.

    This is read-only preview infrastructure — codemap never writes files.

  • #74 7889fed Thanks @SutuSebastian! - GitHub Marketplace Action — Slices 1b-4 of docs/plans/github-marketplace-action.md. v1.0 readiness; action.yml is now installable via - uses: stainless-code/codemap@v1 once the corresponding tag is published.

    --ci aggregate flag (Slice 1b) on query + audit. Aliases --format sarif + process.exitCode = 1 on findings/additions + suppresses no-locatable-rows stderr warning. Mutually exclusive with --json and --format <other>. Parser rejects contradictions with helpful errors.

    action.yml + scripts/detect-pm.mjs (Slice 2). Composite Action wrapping the codemap CLI. ~16 declarative inputs across 3 categories (where to run / what to run / what to do with output); Q1 resolution. Default α command on pull_request events: audit --base ${{ github.base_ref }} --ci; no-op on other events unless an explicit command: input is passed. Package-manager autodetection delegates to package-manager-detector (antfu/userquin, MIT, 0 transitive deps); CLI invocation resolution via the library's 'execute-local' / 'execute' intents.

    codemap pr-comment (Slice 3). New CLI verb that renders a markdown PR-summary comment from a codemap-audit-JSON envelope or a SARIF doc. Auto-detects input shape; --shape audit|sarif overrides. Reads from a file or stdin (-). --json envelope emits { markdown, findings_count, kind } for action.yml steps. Closes the SARIF→Code-Scanning gap for: private repos without GHAS, repos that haven't enabled Code Scanning, aggregate audit deltas without a single file:line anchor, trend / delta narratives, and bot-context seeding (review bots read PR conversation, not workflow artifacts). v1.0 ships the (b) summary-comment shape per Q4 resolution; (c) inline-review comments deferred to v1.x.

    Dogfood (Slice 4). New action-smoke job in .github/workflows/ci.yml runs uses: ./ on every PR with command: --version to validate the composite-step flow + npm-pulled codemap binary. Non-blocking until v1.0.0 ships (at which point the smoke gates the build).

    Engine + CLI separation discipline preserved: pr-comment-engine.ts is pure; cmd-pr-comment.ts wraps it. Tests cover the engine (12 cases) and the CLI parser (4 audit + 4 query tests for --ci).

    Lockstep agent updates (per docs/README.md Rule 10): .agents/rules/codemap.md + templates/agents/rules/codemap.md gain rows for --ci and pr-comment so installed agents and this clone's session view stay in lockstep.

    Slice 5 (Marketplace publish + listing metadata) is post-merge — gated on a v1.0.0 tag.

  • 31479a5 Thanks @SutuSebastian! - feat(mcp/serve): default-ON watcher for codemap mcp and codemap serve

    Stale-index friction is empirically the most-frequent agent UX issue under codemap mcp (driving the watch-mode planning in PR #46) and the most-frequent CI/IDE-plugin friction under codemap serve. Both modes are inherently long-running, so the chokidar co-process pays for itself immediately. Decision originally resolved 2026-05 (research note § 6 Q1); this PR ships it.

    New defaults.

    • codemap mcp — watcher boots automatically; tools always read a live index.
    • codemap serve — same.
    • One-shot CLI defaults preserved: codemap query / codemap show / codemap snippet / etc. still spawn no watcher.

    Opt out.

    • --no-watch flag (new) — explicit opt-out for ephemeral-index workflows, fire-and-forget CI scripts, etc.
    • CODEMAP_WATCH=0 / CODEMAP_WATCH="false" — env-shortcut mirroring --no-watch for IDE / CI launches that can't easily edit the spawn command.

    Backwards-compat preserved.

    • --watch flag still parses and is honored (no-op since it matches the new default; kept so existing scripts and launch commands don't break).
    • CODEMAP_WATCH=1 / CODEMAP_WATCH="true" still parses (redundant after the flip, kept for backwards-compat).
    • --no-watch wins over --watch when both passed (last-write semantics).

    Tradeoffs accepted.

    • Slightly slower mcp/serve startup (~chokidar boot cost, validated tiny on Bun + Node by PR #46's 6-watcher audit).
    • Spawns a second process — visible to users running htop / Activity Monitor. Worth it for the live-index correctness gain.

    Tests: 12 new tests across cmd-mcp.test.ts and cmd-serve.test.ts cover default-ON behavior, --no-watch opt-out, env opt-out (CODEMAP_WATCH=0 / "false"), env opt-in still honored (CODEMAP_WATCH=1), and --no-watch wins over --watch.

    Lockstep updates: templates/agents/rules/codemap.md, templates/agents/skills/codemap/SKILL.md, .agents/rules/codemap.md, .agents/skills/codemap/SKILL.md, and README.md all updated to reflect the new defaults + opt-out shape per docs/README.md Rule 10.

  • #71 fc6790b Thanks @SutuSebastian! - feat(recipes): parametrised recipe support + find-symbol-by-kind

    Recipes may now declare params in sibling <id>.md frontmatter and consume values through positional ? placeholders in SQL. Values validate before SQL binding and support string, number, and boolean types.

    CLI

    • codemap query --recipe <id> --params key=value[,key=value]
    • --params may be repeated; duplicate keys use last-write semantics.
    • Values may contain = (split on first equals). Values containing literal commas should use repeated --params.
    • Param validation is strict: missing required, unknown, and malformed values return {error}.

    MCP / HTTP

    • query_recipe accepts params: {key: value}.
    • HTTP POST /tool/query_recipe uses the same shape.

    Catalog

    • --recipes-json, codemap://recipes, and codemap://recipes/{id} expose the params declaration for each parametrised recipe.

    Example bundled recipe

    • find-symbol-by-kind demonstrates the new path: codemap query --json --recipe find-symbol-by-kind --params kind=function,name_pattern=%Query%

    No schema bump. Runtime remains read-only via PRAGMA query_only=1; params are bound through SQLite placeholders, not string interpolation.

  • #30 a309d52 Thanks @SutuSebastian! - codemap query --save-baseline / --baseline — snapshot a query result set and diff against it later. Stored in the new query_baselines table inside .codemap.db (no parallel JSON files). --baselines lists saved snapshots, --drop-baseline <name> deletes one. Diff identity is per-row JSON.stringify equality; --summary collapses to {added: N, removed: N}. Recipe actions attach to the added rows when running under --baseline. Baselines survive --full and SCHEMA rebuilds. SCHEMA_VERSION bumps from 4 to 5.

  • #37 5110b1a Thanks @SutuSebastian! - feat(recipes): recipes-as-content registry — bundled .md siblings + project-local recipes

    Two complementary capabilities:

    1. Bundled recipes get richer descriptions. Every bundled recipe in templates/recipes/ is now a <id>.sql file paired with an optional <id>.md description body (replaces the inline TypeScript map in src/cli/query-recipes.ts). Per-row actions templates live in YAML frontmatter on the .md instead of code. Same surface for end users (--recipe <id> / --recipes-json / codemap://recipes); single storage shape across bundled + project recipes.

    2. Project-local recipes — drop <id>.{sql,md} files into <projectRoot>/.codemap/recipes/ to ship team-internal SQL as first- class recipes. Auto-discovered via --recipe <id>, surfaced in --recipes-json and the codemap://recipes MCP resource alongside bundled. Project recipes win on id collision; the catalog entry carries shadows: true on overrides so agents reading the catalog at session start see when a recipe behaves differently from the documented bundled version (per-execution response shape stays unchanged — uniformity contract preserved).

    Catalog entries (--recipes-json output, codemap://recipes payload) gain three additive fields: body (full Markdown body), source ("bundled" | "project"), and shadows? (true on project entries that override a bundled id). Existing consumers that destructure {id, description, sql, actions?} keep working.

    Validation: load-time lexical scan rejects DML / DDL keywords (INSERT / UPDATE / DELETE / DROP / CREATE / ALTER / ATTACH / DETACH / REPLACE / TRUNCATE / VACUUM / PRAGMA) in recipe SQL with recipe-aware error messages — defence in depth alongside the runtime PRAGMA query_only=1 backstop in query-engine.ts shipped in the previous release.

    Implementation: pure transport-agnostic loader in src/application/recipes-loader.ts; thin shim in src/cli/query-recipes.ts preserves backwards-compat exports (QUERY_RECIPES, getQueryRecipeSql, etc.). Hand-rolled YAML frontmatter parser scoped to the actions shape (no js-yaml dependency).

    .codemap.db is gitignored as before; .codemap/recipes/ is NOT (verified via git check-ignore) — recipes are git-tracked source code authored for human review.

  • #71 fc6790b Thanks @SutuSebastian! - feat(recipes): add read-only rename-preview recipe

    Adds a conservative rename-preview bundled recipe that composes the new parametrised recipe infrastructure with the new diff formatters:

    codemap query --recipe rename-preview \
      --params old=usePermissions,new=useAccess,kind=function \
      --format diff

    The v1 recipe emits rows shaped for --format diff / diff-json and covers:

    • symbol definition lines from symbols
    • direct named import specifier lines from imports.specifiers when imports.resolved_path points at the target symbol file

    It intentionally does not cover call sites, re-export alias chains, string literals, comments, dynamic dispatch, or template-literal property access yet. Those require more precise source-location substrate (for calls / exports) or non-structural search. The recipe .md documents the caveats clearly and repeats the key product-floor rule: codemap never writes files; this is a preview for review / git apply --check.

    Parameters:

    • old (required string)
    • new (required string)
    • kind (optional string)
    • in_file (optional string path prefix)
    • include_tests (optional boolean, default true)
    • include_re_exports (optional boolean, default true; reserved until export locations are indexed)
  • #43 4061ac3 Thanks @SutuSebastian! - codemap query --format <text|json|sarif|annotations> — pipe any recipe row-set into GitHub Code Scanning (SARIF 2.1.0) or surface findings inline on PRs (GH Actions ::notice file=…,line=…::msg). Pure output-formatter additions on top of the existing JSON pipeline; no schema impact.

    Auto-detects file-path columns (file_path / path / to_path / from_path priority) and line_start (+ optional line_end) for SARIF region. Aggregate recipes without locations (index-summary, markers-by-kind) emit results: [] + a stderr warning. Rule id is codemap.<recipe-id> for --recipe, codemap.adhoc for ad-hoc SQL. Default result.level is "note"; per-recipe overrides via <id>.md frontmatter (sarifLevel, sarifMessage, sarifRuleId) deferred to v1.x.

    --format overrides --json when both passed; --json stays as the alias for --format json. Incompatible with --summary / --group-by / baseline (different output shapes — sarif/annotations only support flat row lists).

    MCP query and query_recipe tools accept the same format: "sarif" | "annotations" argument; query_batch deferred to v1.x.

  • #75 ba01d81 Thanks @SutuSebastian! - suppressions substrate — opt-in recipe-suppression markers parsed from source comments. The markers parser now recognises // codemap-ignore-next-line <recipe-id> and // codemap-ignore-file <recipe-id> (also #, --, <!--, /* leaders for non-JS files) and writes them to a new suppressions(file_path, line_number, recipe_id) table. Two scopes encoded by line_number: positive = next-line (the directive sits one line above; line_number points at the suppressed line), 0 = file scope.

    Recipe authors opt in via LEFT JOIN suppressions s ON s.file_path = … AND s.recipe_id = '<id>' AND (s.line_number = 0 OR s.line_number = <row's line>) WHERE s.id IS NULL. Ad-hoc SQL is unaffected. Bundled recipes that opt in today: untested-and-dead (line + file) and unimported-exports (file only — exports has no line_number column, so per-line suppression isn't expressible there).

    Stays consistent with the "no opinionated rule engine" Floor — no severity, no suppression-by-default, no universal-honor model. The suppression is consumer-chosen substrate: recipe authors choose whether to honor it; consumers can override per recipe by writing project-local SQL that ignores suppressions or filters differently. The leader regex requires the directive to start a line (modulo whitespace) so directives never match inside string literals — both this clone's tests and recipe .md examples use the directive text in prose without polluting the index.

    Schema bumps to 10--full rebuild auto-runs on next index pass. dropAll() includes suppressions (index-data table, not user data). Surfaced in agent rules + skills + glossary + architecture schema docs per Rule 10.

  • #39 7460b46 Thanks @SutuSebastian! - feat(show + snippet): targeted-read CLI verbs + MCP tools

    Two sibling verbs that close the "agent wants to read this thing" loop without composing SQL:

    • codemap show <name> — returns metadata (file_path:line_start-line_end + signature + kind) for the symbol(s) matching the exact name (case-sensitive).
    • codemap snippet <name> — same lookup; each match also carries source (file lines from disk), stale (true when content_hash drifted since indexing), missing (true when file is gone).

    Both share the same flag set (--kind <k> filter, --in <path> file scope — directory prefix or exact file, normalized via the existing toProjectRelative helper for cross-platform consistency).

    Output is the agent-friendly {matches, disambiguation?} envelope on both CLI --json and MCP responses (uniformity contract per the MCP plan). Single match → {matches: [{...}]}; multi-match adds disambiguation: {n, by_kind, files, hint} — structured aids so the agent narrows without scanning every row. Forward-extensible (future nearest_to_cursor / most_recently_modified / caller_count fields land as additive keys).

    MCP tools show and snippet register parallel to the CLI verbs and auto-inherit the same envelope shape.

    Stale-file behavior on snippet: source is always returned when the file exists; stale: true is metadata the agent reads. No refusal, no auto-reindex side-effects — read tool stays read-only.

    Architecturally: pure transport-agnostic engine in src/application/show-engine.ts (mirrors the cmd-_ ↔ _-engine seam from PRs #33 / #35 / #37); thin CLI verbs in src/cli/cmd-show.ts

    • src/cli/cmd-snippet.ts. Reuses findSymbolsByName, hashContent (from src/hash.ts), toProjectRelative (now exported from cmd-validate.ts), and files.content_hash — same primitives the existing validate command already uses for stale detection. No schema change.

    Test coverage: 19 engine tests (lookup variants, line slicing, stale detection, missing files), 13 cmd-show parser/envelope tests, 11 cmd-snippet parser/envelope/stale tests, 8 in-process MCP integration tests via @modelcontextprotocol/sdk's InMemoryTransport.

  • #75 ba01d81 Thanks @SutuSebastian! - codemap ingest-coverage --runtime <dir> — V8 runtime coverage parser. Reads a NODE_V8_COVERAGE=...-style directory (one or more coverage-<pid>-<ts>-<seq>.json files) and dispatches to the existing upsertCoverageRows core through a new ingestV8 parser. Each script's byte-offset ranges are converted to per-line hit counts via innermost-wins range walking (smaller, more specific ranges override the function-as-a-whole count — matches V8's documented semantics). Skips non-file:// URLs (Node internals, evalmachine.<anonymous>); merges duplicate-URL scripts across dumps so multi-process test runs don't inflate total_statements.

    Format auto-detection is unchanged for files (.json → istanbul, .info → lcov, directory of either → probe both with explicit-error on ambiguity); --runtime is the explicit opt-in for V8 directories. The coverage table schema doesn't move — V8 rows write through the same (file_path, name, line_start, hit_statements, total_statements, coverage_pct) projection, so every existing JOIN (untested-and-dead, files-by-coverage, worst-covered-exports) works unchanged.

    Useful for "delete cold code with stronger evidence" agent flows: production-style traces from real test runs feed the same recipes that consume Istanbul/LCOV today. Local-only — SaaS aggregation explicitly out of scope (different product class). The parser stays in-process; no aggregation server, no upload primitive. New format: "v8" arm on the result envelope; existing "istanbul" | "lcov" consumers don't break.

    Engine module: application/coverage-engine.ts (added ingestV8, V8ScriptCoverage, V8FunctionCoverage, V8CoveragePayload exports). CLI module: cli/cmd-ingest-coverage.ts (added --runtime flag, resolveV8Directory helper that reads every top-level *.json in the directory and merges their result arrays). Pure additive — --json output gains "format": "v8" as a possible value.

Patch Changes

  • #33 114303f Thanks @SutuSebastian! - codemap audit (B.5 v1) — structural-drift command emitting {head, deltas} where each deltas[<key>] carries {base, added, removed}. Three v1 deltas: files, dependencies, deprecated. Two snapshot-source shapes — --baseline <prefix> (auto-resolves <prefix>-files / <prefix>-dependencies / <prefix>-deprecated in query_baselines) and --<delta>-baseline <name> (explicit per-delta override; composes with --baseline). Reuses B.6 baselines; no schema bump. --summary collapses to per-delta counts; --no-index skips the auto-incremental-index prelude. v1 ships no verdict / threshold config — consumers compose --json + jq for CI exit codes (v1.x slice). --base <ref> (worktree+reindex snapshot) defers to v1.x.

  • #70 db2f27a Thanks @SutuSebastian! - feat(complexity): cyclomatic complexity column on symbols + bundled recipe (research note § 1.4 ship-pick (c))

    Adds per-function cyclomatic complexity computed during AST walking. Schema bump SCHEMA_VERSION 7 → 8 — first reindex after upgrade triggers a full rebuild via the existing version-mismatch path.

    What lands:

    • New complexity REAL column on symbols. Computed via McCabe formula (1 + decision points) for function-shaped symbols (top-level function declarations + arrow-function consts). NULL for non-functions (interfaces, types, enums, plain consts) and class methods (v1 limitation; documented in the recipe .md).
    • Decision points counted: if, while, do…while, for, for…in, for…of, case X: arms (not default: fall-through), && / || / ?? short-circuit operators, ?: ternary, catch clauses.
    • New bundled recipe high-complexity-untested — function-shaped symbols with complexity ≥ 10 AND measured coverage < 50%. Combines structural + runtime evidence axes; surfaces refactor-priority candidates that single-axis recipes (untested-and-dead, worst-covered-exports) miss because they're "called but undertested."

    Implementation:

    • Parser visitor (src/parser.ts) maintains a complexityStack keyed by symbol index. On function entry, pushes counter at 1 + symbol index. Branching-node visitors increment the top counter. On function exit, pops and writes complexity into the symbol row already pushed during entry.
    • Nested function declarations get their own stack entries — inner branches don't count toward the outer function. (Standard McCabe — each function counted independently.)

    Pre-v1 patch per .agents/lessons.md "changesets bump policy": schema-bumping changes are minor in semver but pre-v1 we default to patch unless the bump forces a .codemap.db rebuild. This one does (column added; auto-detected by createSchema() mismatch path) — every consumer's first run after upgrade re-indexes from scratch.

    Agent rule + skill lockstep updated per docs/README.md Rule 10 — both templates/agents/ and .agents/ codemap rule + skill mention the complexity column, the new recipe, and the cyclomatic-complexity definition.

    Out of scope:

    • Class method complexityMethodDefinition visitor currently doesn't push to the complexity stack. Documented in high-complexity-untested.md v1 limitation; refactor opportunity for class-heavy projects.
    • Per-class / per-file rollupscomplexity is per-symbol; project-local recipes can SUM / AVG it as needed.
  • #69 560390b Thanks @SutuSebastian! - feat(fts5+mermaid): opt-in FTS5 virtual table + Mermaid output formatter

    Implements the FTS5+Mermaid plan (docs/plans/fts5-mermaid.md) — two non-goal flips in one PR.

    FTS5 (opt-in, default OFF):

    • New source_fts virtual table — (file_path UNINDEXED, content) columns, tokenize='porter unicode61'. Always created; populated only when toggle is on.
    • Toggle via codemap.config.ts fts5: true OR --with-fts CLI flag at index time. CLI overrides config (logs stderr line on override).
    • Indexer tees file content into source_fts in same transaction as files row insert (atomic). Worker → main serialization cost is zero on default-OFF path.
    • Toggle-change auto-detect via meta.fts5_enabled — flipping fts5: false → true auto-upgrades incremental → full rebuild so source_fts is consistently populated.
    • DB-size telemetry on first FTS5 populate: [fts5] source_fts populated: <N> files / <X> KB.
    • Bundled demo recipe text-in-deprecated-functions@deprecated functions in files containing TODO/FIXME/HACK markers AND coverage <50%. Demonstrates FTS5 ⨯ symbolscoverage JOIN composability that ripgrep can't match.

    Mermaid output formatter:

    • New --format mermaid output mode. Renders {from, to, label?, kind?} row-shape as flowchart LR.
    • 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 deliberately out of scope (would be a verdict masquerading as an output mode).
    • Available across CLI, MCP query / query_recipe tools, HTTP POST /tool/query (text/plain content type).

    Schema bump: SCHEMA_VERSION 6 → 7. First reindex after upgrade triggers a full rebuild via the existing version-mismatch path; existing .codemap/index.db is preserved (only schema-managed tables get dropped + recreated).

    Pre-v1 patch per .agents/lessons.md "changesets bump policy" — additive feature, default-OFF for FTS5, behaviour-preserving for existing users (--with-fts is opt-in; Mermaid is a new output mode).

    Agent rule + skill lockstep updated per docs/README.md Rule 10 — both templates/agents/ and .agents/ mention --with-fts, --format mermaid, the new bundled recipe, and the bounded-input contract.

  • #41 0134944 Thanks @SutuSebastian! - Internal refactor — lift cli/* envelope builders + path helpers into application/* engines so application/mcp-server.ts no longer reaches sideways into cli/. Affected modules: audit-engine (added resolveAuditBaselines), new context-engine (buildContextEnvelope, classifyIntent, ContextEnvelope), new validate-engine (computeValidateRows, toProjectRelative), show-engine (added buildShowResult, buildSnippetResult, ShowResult, SnippetResult, SnippetMatch), query-recipes moved from cli/ to application/. CLI verbs stay shells (parse / help / run / render). No behavior change, no public API change — cli/cmd-* and application/* are internal modules; the published surface (api.ts, the codemap binary, the MCP server) is untouched.

  • #67 3e03db7 Thanks @SutuSebastian! - feat(mcp): add codemap://files/{path} + codemap://symbols/{name} resources (research note § 1.8)

    Two new MCP / HTTP resources for direct agent reads — saves the recipe-compose round-trip when the agent just wants "everything about this file" or "where is this symbol?".

    • codemap://files/{path} — per-file roll-up. Returns {path, language, line_count, symbols, imports, exports, coverage}. imports.specifiers parsed inline (callers don't have to JSON.parse). coverage is {measured_symbols, avg_coverage_pct, per_symbol} when coverage was ingested, else null. URI-encode the path.
    • codemap://symbols/{name} — symbol lookup by exact name. Returns {matches, disambiguation?} envelope (same shape as the show verb per PR #39). Optional ?in=<path-prefix> query parameter mirrors show --in <path> (directory prefix or exact file).

    Both reuse existing infrastructure (no schema bump): codemap://files/ queries the existing tables; codemap://symbols/ reuses findSymbolsByName + buildShowResult from application/show-engine.ts.

    Caching policy: catalog-style resources (recipes, schema, skill) lazy-cache as before. Data-shaped resources (files/, symbols/) read live every call — no caching, since the index can change between requests under --watch.

    Both available over MCP read_resource and HTTP GET /resources/{encoded-uri} via the existing dispatcher (no new transport plumbing).

    Agent rule + skill lockstep updated per docs/README.md Rule 10 — both templates/agents/ and .agents/ codemap rule + skill mention the new resource templates + caching policy.

  • 8da7f3d Thanks @SutuSebastian! - docs(cli): mcp --help and serve --help now list every shipped tool + resource

    Stale help text in src/cli/cmd-mcp.ts and src/cli/cmd-serve.ts listed the original v1 tool / resource taxonomy. Updated to match what's registered today (verified against src/application/mcp-server.ts):

    • mcp --help Tools section now includes show, snippet, impact (was missing all three).
    • mcp --help Resources section now distinguishes lazy-cached catalog resources (recipes, recipes/{id}, schema, skill) from live read-per-call resources (files/{path}, symbols/{name}) — was listing only the original four.
    • serve --help Routes section now includes POST /tool/impact (was missing) and lists every mirrored MCP resource explicitly under GET /resources/{encoded-uri} (was a ... ellipsis).

    No behavior change — purely a documentation accuracy fix. Bundled agent rule + skill (templates/agents/ and .agents/) already enumerate the six resources correctly.

  • #75 ba01d81 Thanks @SutuSebastian! - Outcome-shaped CLI aliases — five thin top-level verbs that wrap query --recipe <id>:

    • codemap dead-codequery --recipe untested-and-dead
    • codemap deprecatedquery --recipe deprecated-symbols
    • codemap boundariesquery --recipe boundary-violations
    • codemap hotspotsquery --recipe fan-in
    • codemap coverage-gapsquery --recipe worst-covered-exports

    Every query flag passes through (--json, --format sarif|annotations|mermaid|diff|diff-json, --ci, --summary, --changed-since <ref>, --group-by owner|directory|package, --params key=value, --save-baseline, --baseline). Run codemap <alias> --help for the wrapped recipe id.

    Closes the verb-obviousness gap — codemap dead-code is more discoverable than codemap query --recipe untested-and-dead. Capped at five to avoid alias-sprawl per roadmap.md; promote a sixth only when the recipe becomes a headline outcome.

    Mapping lives in src/cli/aliases.ts (OUTCOME_ALIASES); rewrite happens before dispatch in src/cli/main.ts. Pure CLI surface; no schema, no engine, no new substrate. Moat-A clean — the alias is a one-line query --recipe <id> rewrite, not a new primitive; the recipe IS the SQL.

  • #76 dfbf4e1 Thanks @SutuSebastian! - Recipe-recency tracking — every successful --recipe call now writes to a new recipe_recency(recipe_id PK, last_run_at, run_count) table. --recipes-json and the matching codemap://recipes / codemap://recipes/{id} MCP resources gain inline last_run_at: number | null + run_count: number fields per entry, so agent hosts can rank live recipes ahead of historic ones via jq 'sort_by(.last_run_at // 0) | reverse'. Default ON; opt-out via .codemap/config recipeRecency: false (short-circuits before any DB write — no rows ever land).

    Two write sites both call tryRecordRecipeRun (the failure-isolated wrapper around recordRecipeRun) from application/recipe-recency.ts: handleQueryRecipe in application/tool-handlers.ts (covers MCP + HTTP — both flow through it) and runQueryCmd in cli/cmd-query.ts (CLI — finally block keys off a local recipeQuerySucceeded flag, NOT process.exitCode, so --ci's deliberate exit-1-on-findings is recognised as success). Counts only successful runs; recency-write failures are swallowed with a stderr [recency] write failed: <reason> warning so they NEVER block the recipe response. The 90-day rolling window is enforced eagerly on the write path (single indexed DELETE inside recordRecipeRun before the upsert); reads filter at SELECT time (WHERE last_run_at >= cutoff) and never mutate the DB so the catalog stays side-effect free for --recipes-json and the MCP codemap://recipes resources.

    The MCP/HTTP catalog cache was dropped — caching the JSON.stringify result alongside recency would freeze last_run_at at first-read forever per long-running codemap mcp / codemap serve lifetime. The underlying listQueryRecipeCatalog() is itself module-cached upstream, so the extra cost is one DB-read + one JSON.stringify per call. Schema / skill resources stay cached.

    Local-only — no upload primitive ever ships. The Floor exists to resist accumulation pressure. Sibling to query_baselines / coverage: intentionally absent from dropAll() so --full and SCHEMA_VERSION rebuilds preserve user-activity history. No SCHEMA_VERSION bump — the new table is purely additive and lands on existing DBs via CREATE TABLE IF NOT EXISTS on next boot.

    Schema docs: architecture.md § recipe_recency. Term entry: glossary.md. Bundled agent rule + skill (templates/agents/) + dev-side mirror (.agents/) updated in lockstep per Rule 10.

  • #65 1b7a5c7 Thanks @SutuSebastian! - feat(recipes): ship two new bundled recipes from research note § 1

    • components-touching-deprecated (research note § 1.1) — UNION of two paths surfacing components that touch @deprecated symbols: hook path (components.hooks_used JSON overlap) + call path (calls.caller_name = component, callee_name is @deprecated). Hook-only variants ship false negatives — recipe spells out the explicit UNION. Action template review-deprecation-impact.
    • refactor-risk-ranking (research note § 1.4) — per-file ranking by (fan_in + 1) × (100 - avg_coverage_pct). Three correctness fixes vs the naïve formula: orphans (fan_in = 0) score on coverage alone via +1; NULL coverage_pct treated as 0% via COALESCE (otherwise the row drops from ORDER BY); files with no exports excluded (no public-API surface to refactor externally). Output is per-file (not per-symbol) — empirical test showed per-symbol ranking ties on file-level fan_in. Per-symbol via calls is a documented tuning axis for project-local override. Action template review-refactor-impact.

    Both recipes use only existing substrate (components, calls, symbols, dependencies, coverage, files) — no schema bump. Bundled recipe content follows the existing recipe-as-content registry pattern (PR #37); project-local overrides live at <projectRoot>/.codemap/recipes/<id>.{sql,md}.

    Agent rule + skill lockstep updated per docs/README.md Rule 10 — both templates/agents/ (ships to npm via codemap agents init) and .agents/ (this clone's mirror) gain trigger-pattern entries, quick-reference rows, and recipe-id list updates.

  • #66 f121d84 Thanks @SutuSebastian! - feat(recipes): ship unimported-exports recipe (research note § 1.2)

    Surfaces exports that have no detectable import. Useful as a starting candidate list for "what's unused?" — explicitly NOT a "safe to delete" list.

    V1 limitations documented in the recipe .md:

    1. Re-export chains not followed — false positives if A re-exports bar from B and consumers import bar from A. Tracked under research note § 1.2; future recipe with recursive CTE walking re_export_source will close the gap.
    2. Unresolved imports ignored — when imports.resolved_path IS NULL (codemap's resolver couldn't resolve a tsconfig.json path alias or external package), those rows don't count toward "used" matching.
    3. Default exports skipped — common framework entry points (Next.js page.tsx, Storybook stories, vite.config.ts) skipped to reduce noise. Override in project-local recipe if you want to include them.

    Action template review-for-deletion (auto_fixable: false) — agents flag for manual verification before deletion.

    Agent rule + skill lockstep updated per docs/README.md Rule 10 — both templates/agents/ and .agents/ codemap rule + skill gain trigger-pattern row, quick-reference row, and recipe-id list update.

  • #75 ba01d81 Thanks @SutuSebastian! - unused-type-members recipe — field-level enumeration of type_members whose owning type has no detectable importer in the project. Sister recipe to unimported-exports: same upstream signal at the type level, but JOINed against type_members so each row carries the field's name, type annotation, optionality, and readonly flag. Useful when planning a deletion of an interface and you need the full field inventory before drafting the codemod.

    Strictly advisory. Codemap doesn't track property access, so the recipe inherits all of unimported-exports's false-positive classes plus the per-field opaqueness of indexed access (T['field']), keyof T, mapped types, type spreads, destructuring, and re-export chains. Output is a STARTING POINT for human review, never a "safe to delete" list. Bundled .md documents every caveat and includes tuning axes for project-local overrides.

    unused-type-members joins the standard recipe taxonomy and ships in templates/recipes/unused-type-members.{sql,md}. Reachable as codemap query --recipe unused-type-members (or via the --format sarif / --format annotations / --ci aggregate flags); rule id is codemap.unused-type-members. Golden-query expectation lives at fixtures/golden/minimal/unused-type-members.json. Pure recipe addition — no schema impact, no engine change.

0.4.0

Minor Changes

  • #28 91598bc Thanks @SutuSebastian! - symbols.visibility column — JSDoc visibility tag (@public / @private / @internal / @alpha / @beta) extracted at parse time and stored as a real column. Replaces the LIKE '%@beta%' regex in the visibility-tags recipe. SCHEMA_VERSION bumps from 3 to 4 — .codemap.db rebuilds automatically on next index. Helper extractVisibility(doc) exported from parser.ts. New partial index idx_symbols_visibility covers WHERE visibility IS NOT NULL queries.

Patch Changes

  • #29 03fbddf Thanks @SutuSebastian! - Update bundled templates/agents/ rule and skill to cover the recent CLI surface — codemap query --summary / --changed-since <ref> / --group-by owner|directory|package, per-row recipe actions, and the new symbols.visibility column. The dev-side .agents/ mirror is updated in lockstep so this clone stays self-consistent.

  • #26 c32f052 Thanks @SutuSebastian! - codemap query Tier A flags — --summary, --changed-since <ref>, --group-by owner|directory|package, plus per-row actions templates on bundled recipes. All output filters; the SQL still executes against the index. Ad-hoc SQL and the cm.query() programmatic API stay unchanged.

0.3.0

Minor Changes

  • #23 ebd4c34 Thanks @SutuSebastian! - Agent-friendly CLI surface plus a schema v3 bump that tightens NOT NULL invariants. Existing .codemap.db files auto-rebuild on first open.
    • New: codemap validate [--json] [paths...] — diffs the on-disk SHA-256 of indexed files against files.content_hash and prints stale / missing / unindexed rows. Lets agents skip re-reads they don't need; exits 1 on any drift (git-status semantics)
    • New: codemap context [--compact] [--for "<intent>"] — emits a stable JSON envelope (project metadata, top hubs, recent markers, recipe catalog) for any agent or editor that wants the index in one cheap shot. --for runs lightweight intent classification (refactor / debug / test / feature / explore / other) and returns matched recipe ids plus a hint
    • New: codemap --performance flag — prints a per-phase timing breakdown (collect / parse / insert / index_create) and the top-10 slowest files by parse time during full rebuilds, for triaging giant or pathological inputs
    • New: -r short alias for codemap query --recipe + cleaner organized codemap query --help (sectioned flags, dynamic recipe-id padding, examples for both forms)
    • New recipes: deprecated-symbols (@deprecated JSDoc tag scan), visibility-tags (@internal / @private / @alpha / @beta), files-hashes (powers validate), barrel-files (top files by export count)
    • Friendlier no-.codemap.db error: no such table: <X> now rewrites to an actionable hint pointing at codemap / codemap --full, on both the JSON and human paths
    • Public type surface: new IndexPerformanceReport; IndexRunStats.performance? field; per-field JSDoc coverage on IndexResult, IndexRunStats, ResolvedCodemapConfig, all db.ts row interfaces (FileRow, SymbolRow, ImportRow, ExportRow, ComponentRow, DependencyRow, MarkerRow, CssVariableRow, CssClassRow, CssKeyframeRow, CallRow, TypeMemberRow), and ParsedFile
    • Documentation: README now leads with a "What you get" Grep/Read vs Codemap capability table and a "Daily commands" stripe; docs/why-codemap.md adds a "What Codemap is not" anti-pitch section and a scenario-keyed token-savings table (single lookup → 50-turn session) replacing the earlier hand-wave
    • Stricter lint baseline: enabled prefer-const, consistent-type-specifier-style, consistent-type-definitions, no-confusing-non-null-assertion, no-unnecessary-{boolean-literal-compare,template-expression,type-assertion}, prefer-{includes,nullish-coalescing,optional-chain}, and unicorn/switch-case-braces
    • Schema v3 — tighter NOT NULL invariants: every column whose Row-interface type was non-nullable is now NOT NULL in the SQLite DDL (files.size/line_count/language/last_modified/indexed_at, symbols.line_start/line_end/signature/is_exported/is_default_export, imports.specifiers/is_type_only/line_number, exports.kind/is_default, components.hooks_used/is_default_export, markers.line_number/content, css_variables.scope/line_number, css_classes.is_module/line_number, css_keyframes.line_number, type_members.is_optional/is_readonly). Existing v2 databases auto-rebuild via createSchema()'s version-mismatch detector — no manual action needed

0.2.2

Patch Changes

  • 5f65c33 Thanks @SutuSebastian! - Use vendor-neutral .md extension for agent rules in templates; Cursor integration remaps to .mdc at wiring time
    • codemap agents init now writes .md rule files to .agents/rules/ (plain Markdown with YAML frontmatter)
    • Cursor target automatically renames rules to .mdc (required for frontmatter parsing); all other targets (Windsurf, Continue, Cline, Amazon Q) keep .md
    • SKILL.md now includes name and description frontmatter per the Agent Skills spec

0.2.1

Patch Changes

  • 7f663be Thanks @SutuSebastian! - Sync bundled agent rule template with schema v2: add type_members, calls, and doc_comment trigger patterns and query rows. Add golden scenarios and fixture coverage for both new tables.

0.2.0

Minor Changes

  • #19 53b2c52 Thanks @SutuSebastian! - Richer symbol metadata: generics, return types, JSDoc, type members, const values, symbol nesting, call graph
    • Signatures now include generic type parameters, return type annotations, and heritage clauses (extends/implements)
    • New doc_comment column on symbols extracts leading JSDoc comments
    • New type_members table indexes properties and methods of interfaces and object-literal types
    • New value column on symbols captures const literal values (strings, numbers, booleans, null)
    • New parent_name column on symbols tracks scope nesting; class methods/properties/getters extracted as individual symbols
    • New calls table tracks function-scoped call edges with caller_scope for qualified disambiguation (deduped per file)
    • Enum members extracted into members column as JSON
    • Performance: cached scope strings, hoisted hot-path regex, batch deletes, reduced redundant I/O, BATCH_SIZE 100→500
    • SCHEMA_VERSION bumped to 2

0.1.9

Patch Changes

  • #17 e962326 Thanks @SutuSebastian! - Fix incremental detection reporting unchanged files as "changed" on every run when the working tree has uncommitted modifications. getChangedFiles now compares content hashes against the index before including candidates, so only truly modified files enter the indexing pipeline.

0.1.8

Patch Changes

  • #15 f2362f9 Thanks @SutuSebastian! - Fix three HIGH-severity bugs found via cross-audit triangulation, plus performance and docs improvements.

    Bug fixes

    • Add missing onerror handler on Bun Worker — prevents silent promise hang when a parse worker crashes
    • Require JSX return or hook usage for component detection — eliminates false positives (e.g. FormatCurrency() in .tsx files no longer indexed as a component)
    • Include previously-indexed files in incremental and --files modes — custom-extension files indexed during --full no longer silently go stale

    Performance

    • Batch CSS imports instead of inserting one-at-a-time (both full-rebuild and incremental paths)
    • Add Map<string, Statement> cache for better-sqlite3 run()/query() — avoids ~2,000+ redundant prepare() calls on large projects
    • Hoist inner.query() in wrap() to prepare once per call instead of per .get()/.all()
    • Skip PRAGMA optimize on closeDb for read-only query paths

    Docs

    • Fix Wyhash → SHA-256 in architecture.md and SKILL.md (3 locations)
    • Correct symbols.kind values (variableconst, type_aliastype) and exports.kind values
    • Clarify Database.query() caching is Bun-only; Node statement cache via wrapper
    • Update architecture.md: component heuristic, statement cache, closeDb readonly, incremental/--files custom extensions
    • Update benchmark.md and golden-queries.md for enriched fixture

    Testing

    • Enrich fixtures/minimal/ to cover all 10 indexed tables (CSS module, @keyframes, @import, non-component PascalCase export, FIXME marker)
    • Add 7 new golden scenarios (exports, css_variables, css_classes, css_keyframes, css_imports, markers-all-kinds, components-no-false-positives)

    Cleanup

    • Remove unused analyzeDependencies: true from CSS parser
    • Deduplicate fetchTableStats (was duplicated across index-engine.ts and run-index.ts)
    • Remove dead eslint-disable-next-line directives (oxlint doesn't enforce those rules)
    • Fix SCHEMA_VERSION comment (said "2", value is 1)

0.1.7

Patch Changes

  • #13 13a2c14 Thanks @SutuSebastian! - Replace fast-glob with tinyglobby for Node include globs. Smaller dependency footprint; expandDirectories: false keeps matching aligned with the previous behavior.

0.1.6

Patch Changes

  • ca4b47a Thanks @SutuSebastian! - Shipped agent rules and skills now lead with codemap query --json (optional table output when --json is omitted). Add bun run benchmark:query to compare console.table vs JSON stdout size, plus integration tests for --json vs default output when .codemap.db is present. README and docs/ (including benchmark.md § Query stdout) updated to match.

0.1.5

Patch Changes

  • #10 9d37bd5 Thanks @SutuSebastian! - Agent templates (templates/agents/)
    • Align codemap.mdc and skills/codemap/SKILL.md with the current codemap query --json contract (bootstrap / DB / SQL failures, process.exitCode).
    • SKILL: QUERY_RECIPES-aligned fan-out SQL examples and bundled-recipe determinism note.

0.1.4

Patch Changes

  • #8 889ed5b Thanks @SutuSebastian! - Query CLI

    • codemap query --json: print a JSON array of result rows to stdout (and {"error":"…"} on SQL errors) for agents and automation. Document that the query subcommand does not cap rows — use SQL LIMIT for bounded results. Update bundled agent rule and skill with --json preference, verbatim structural answers, and generic SQL recipes (fan-out + sample targets).

    • codemap query --recipe <id> for bundled read-only SQL so agents can run common structural queries without embedding SQL on the command line. --json works with recipes the same way as ad-hoc SQL. Bundled ids include dependency fan-out / fan-out-sample / fan-out-sample-json (JSON1 json_group_array) / fan-in, index index-summary, files-largest, React components-by-hooks (comma-based hook count, no JSON1), and markers-by-kind. The benchmark suite uses the fan-out recipe SQL for an indexed-path scenario; docs clarify that recipes add no extra query cost vs pasting the same SQL.

    • Recipe discovery (no index / DB): codemap query --recipes-json prints all bundled recipes (id, description, sql) as JSON. codemap query --print-sql <id> prints one recipe’s SQL. listQueryRecipeCatalog() in src/cli/query-recipes.ts is the single derived view of QUERY_RECIPES for the JSON output.

    Golden tests

    • bun run test:golden: index fixtures/minimal, run scenarios from fixtures/golden/scenarios.json, and compare query JSON to fixtures/golden/minimal/. Use bun scripts/query-golden.ts --update after intentional fixture or schema changes. Documented in benchmark.md and CONTRIBUTING.

    Query robustness

    • With --json, {"error":"…"} is printed for invalid SQL, database open failures, and codemap query bootstrap failures (config / resolver setup), not only bad SQL. The CLI sets process.exitCode instead of process.exit so piped stdout is not cut off mid-stream.

    Benchmark & CODEMAP_BENCHMARK_CONFIG

    • Each indexedSql in custom scenario JSON is validated as a single read-only SELECT (or WITHSELECT) — DDL/DML and RETURNING are rejected before execution.
    • Config file paths are resolved from process.cwd() (see benchmark.md). traditional.regex strings are developer-controlled (local JSON); files mode compiles the regex once per scenario.
    • Overlapping globs in the traditional path are deduplicated so Files read / Bytes read count each path once.
    • The default components in shop/ scenario uses a LIKE filter aligned with the traditional globs under components/shop/ (*.tsx and *.jsx, matching components rows from the parser) and avoids unrelated paths such as workshop.

    Recipes (determinism)

    • Bundled recipe SQL adds stable secondary ORDER BY columns (and orders inner LIMIT samples) so --recipe / --json output does not vary on aggregate ties.

    External QA

    • bun run qa:external: --max-files and --max-symbols must be positive integers (invalid values throw before indexing).

0.1.3

Patch Changes

  • #6 ad29694 Thanks @SutuSebastian! - Align shipped agent templates with the published CLI (codemap, npx @stainless-code/codemap, …). Keep this repository’s .agents/ rule and skill dev-oriented (bun src/index.ts). Remove the redundant agents-first-convention template. Document the dev vs templates/agents/ split in templates/agents/README.md and docs/agents.md.

0.1.2

Patch Changes

  • #4 0a9d829 Thanks @SutuSebastian! - codemap agents init: For Git repos, ensure .codemap.* is in .gitignore (create the file or append the line once). --force removes only template file paths (same relpaths under .agents/rules/ and .agents/skills/ as templates/agents) before merging; other files under .agents/, rules/, or skills/ are kept. --interactive / -i — pick IDE integrations (Cursor, GitHub Copilot, Windsurf, Continue, Cline, Amazon Q, CLAUDE.md, AGENTS.md, GEMINI.md) and symlink vs copy for rule mirrors; requires a TTY. Unknown positional arguments (e.g. interactive without --interactive) are rejected. Depends on @clack/prompts.

    Docs: docs/agents.md; docs/README.md index updated. Root .gitignore uses a single .codemap.* line.

0.1.1

Patch Changes

  • #1 b366c53 Thanks @SutuSebastian! - Consolidate docs (index hub, packaging/Releases, benchmark vs external root), point .changeset/README at packaging, and add clean / check-updates npm scripts.

0.1.0

Minor Changes

  • Initial release (0.1.0): structural SQLite index, CLI (codemap, query), programmatic API, Zod-validated codemap.config, Bun and Node support.