|
1 | 1 | # jcodemunch-mcp — Project Brief |
2 | 2 |
|
3 | 3 | ## Current State |
| 4 | +- **Version:** 1.108.111 — **New tool `get_parity_map` (migration parity map; F-15 #2 from the tokensave review, clean-room per [[feedback_clean_room_innovation]] — competitor unnamed in shipped artifacts).** Correspondence-aware port parity between a SOURCE and TARGET symbol tree (two subpaths of one repo, or two repos). Per source function/method/class: **ported** (equivalent counterpart), **ported_diverged** (counterpart exists but signature/body drifted — the failure a name-only "exists in both trees" check reports as done), **unported** (no counterpart, still referenced by source), **orphaned** (unmatched with no in-scope caller — entry point or possible drop), **added** (target-only). **Rename-aware:** unmatched source symbols matched to same-kind target candidates by a structural+behavioral blend (`_signature_tokens`/`_callee_set`/`_jaccard`/`_byte_ratio` reused from `find_similar_symbols`), so a ported-and-renamed symbol isn't a false unported+added pair. **Port plan** (`include_port_plan`): dependency-ordered over ALL unmatched source (adjacency from `_callee_set`), Kosaraju SCC grouping via `get_dependency_cycles._find_cycles` (cycles → one `scc_group`, ported together), Kahn topo over the condensed graph → `order_index`, per-symbol `unblocked`/`blocking_deps`. **Read-only / plan-only** (never edits or ports — [[feedback_jcm_read_only_charter]]); `parity_pct = ported/(ported+ported_diverged+unported+orphaned)`, labelled estimate, `added` excluded. Divergence policy `signature` (default, compares param_count + name-stripped signature tokens so a pure rename isn't flagged) / `signature+body` (also content_hash) / `name_only`. New `tools/get_parity_map.py` + `cli/parity.py` + `parity` CLI subcommand; standard tier (**core_compact unchanged 3969**), registered on all surfaces, `schema_baseline.json` refreshed, tool count **88** full. `parity_axes` reserved slot for P3 suite axes (jdoc doc-parity / jdata schema-parity, [[feedback_suite_parity_for_agent_contracts]]). NO INDEX_VERSION bump (pure read). New `tests/test_parity_map.py` (17). Design note: initial "orphaned = no *ported* caller" starved the port plan (swallowed the pending graph); corrected to "no *in-scope* caller" with the plan spanning all unmatched. See `docs/prd-parity-map.md`. |
4 | 5 | - **Version:** 1.108.110 — **`check_embedding_drift` flipped to `readOnlyHint=False` — closes the suite readOnlyHint divergence.** jcm was the outlier: jdoc v1.93.0 / jdata v1.17.0 already marked it mutating (`force=true` re-pins the drift canary = a write); jcm reported it read-only, so Claude Code plan mode ran `check_embedding_drift(force=true)` silently. Fix: new `_ANNOTATION_ONLY_WRITERS` frozenset (`{check_embedding_drift}`) unioned into `_NON_READONLY_TOOLS` on top of `counter.STATE_CHANGING_ACTIONS | {order, route}`. **Deliberately NOT added to STATE_CHANGING_ACTIONS** — that set gates the counter's `order()` allow_state_change opt-in, and the tool's DEFAULT path is a pure drift report; adding it there would break `order("check_embedding_drift")` reads. So the annotation write-set and the order-gate write-set now diverge by exactly this one dual-mode tool (documented at the def). Purely an annotation change; NO INDEX_VERSION bump, no wire/behavior change. New `tests/test_v1_108_110.py` (4: marked mutating / not in STATE_CHANGING / order allows read without opt-in / in annotation write-set) + extended `test_readonly_annotations.py` (check_embedding_drift in write spot-check + annotation-only-writers-not-in-STATE_CHANGING guard); updated `test_v1_108_104.py` exact-equality assert to account for the new union member. **Suite readOnlyHint parity now fully CLOSED across jcm/jdoc/jdata.** |
5 | 6 | - **Version:** 1.108.109 — **Svelte (.svelte) language support (community PR #362, @thomasmodeneis).** `.svelte` files were dropped at discovery as `wrong_extension`; infra was already ~60% wired (JS-family ext set, `$lib`/`.svelte-kit` aliases, hook nudge), the gap was the parser layer. New `_parse_svelte_symbols` (extractor.py) mirrors the tree-sitter Vue parser `_parse_vue_symbols` — bundled `svelte` grammar produces the same `document -> script_element -> raw_text` shape as Vue, so each `<script>` block's raw_text is re-parsed with the JS/TS grammar. Surfaces: synthetic component symbol (kind=class, from filename), top-level fn/class/interface/type, **Svelte 5 runes** (`let x = $state(...)`/`$derived(...)`, incl. `$derived.by` member form + destructured `let {a,b} = $props()`), **Svelte 4 props** (`export let`/`export const`), **Svelte 4 reactive labels** (`$: doubled = ...`) — last three as kind=constant, all parented to the component. Instance + module (`context="module"`) blocks both parsed, each with its own line offset. `language="svelte"` (Vue parity). New `_extract_svelte_imports` (imports.py) mirrors `_extract_astro_imports`: whole-file ESM scan + PascalCase component-usage edges over HTML-comment-masked body, with `<script>`/`<style>` bodies stripped first so TS generics (`identity<T>`/`Array<Item>`) aren't misread as component tags. Registration: `.svelte`->`svelte` in LANGUAGE_EXTENSIONS + new `SVELTE_SPEC`/LANGUAGE_REGISTRY entry (auto-flows into the MCP language enum + config validation); svelte added to package_registry.py JS-family tuples + plan_refactoring.py import/decl patterns. **NO INDEX_VERSION bump** — additive, previously-skipped files just gain symbols on re-index (Astro/template precedent). New `tests/test_svelte.py` (14) + `tests/fixtures/svelte/`. Verified: grammar bundled, PR branch based on current HEAD (no rebase needed), scope reconciled (8 files, no hidden CI edits), read-only charter respected, full suite **5137 passed / 7 skipped**. Second contributor language feature after Astro (#311) / templates (#337). |
6 | 7 | - **Version:** 1.108.108 — **Audit WS-5 tail (atomic content writes + 4-path persistence test) — WS-5 COMPLETE.** `_write_cached_text` (sqlite_store.py) wrote bodies straight to the final path → a crash mid-write left a truncated body that `_SOURCE_DUMP_TOOLS` would serve as source. Now writes to a `.tmp.<pid>` sibling + `os.replace` (same-dir → atomic on all platforms), cleans temp on failure, leaves existing body intact; covers all 3 content-write sites (full/incremental/migrate) via the single chokepoint. **4-path test:** one parametrized `tests/test_v1_108_108.py` asserts save_index/incremental_save/save_branch_delta/scip-ingest ALL take the `indexwrite` lock keyed on the repo (the V9 invariant) — a future write path added without the lock now fails loudly. Plus atomic-write regression tests (roundtrip, no temp leftover, overwrite-clean, failure-leaves-original). NO INDEX_VERSION bump. **WS-5 fully done (V9 + W7 + W1 + atomic + 4-path).** Remaining audit P2s: WS-8 V12-license transport (backend coord), WS-7 benchmark V1 (jjg's canonical number). Open parity follow-up: jdoc/jdata readOnlyHint. |
|
105 | 106 | - **INDEX_VERSION:** 17 |
106 | 107 | - **Tests:** 4432 passed, 10 skipped (1.108.25 — full count varies by optional-dep availability) |
107 | 108 | - **Python:** >=3.10 |
108 | | -- **Tool count:** 86 in `full` (front door hidden; +1 v1.108.69 `get_delivery_metrics`, +1 v1.108.90 `get_endpoint_impact`); `tool_surface=counter` exposes a 3-tool front door (`order`/`menu`/`route`) instead |
| 109 | +- **Tool count:** 88 in `full` (front door hidden; +1 v1.108.90 `get_endpoint_impact`, +1 v1.108.94 `index_dependency`, +1 v1.108.111 `get_parity_map`); `tool_surface=counter` exposes a 3-tool front door (`order`/`menu`/`route`) instead |
109 | 110 |
|
110 | 111 | ## Key Files |
111 | 112 | ``` |
@@ -174,6 +175,7 @@ src/jcodemunch_mcp/ |
174 | 175 | get_delivery_metrics.py # (v1.108.69) get_delivery_metrics: durable-change delivery over a window. Classifies each non-merge commit into one bucket (revert_authored/reverted/reworked/durable) via _run_git; commits_durable is the numerator for cost-per-outcome (the `delivery` CLI's --cost divides AI spend by it). Hub files (CHANGELOG/version/monolithic dispatch, co-touched by >=max(4,20%) of commits) excluded from the rework signal (auditable via _meta.hub_files_excluded); commits_provisional flags the trailing tail. Reuses get_symbol_provenance._classify_commit for by_category. Read-only, no new tables |
175 | 176 | get_symbol_provenance.py # get_symbol_provenance: full git archaeology per symbol — authorship lineage, semantic commit classification, evolution narrative. Phase 5: optional stack_frequency block reading runtime_stack_events over a 30-day window — per-severity counts + first/last seen; narrative gains an appended sentence when error count >= 3 |
176 | 177 | get_pr_risk_profile.py # get_pr_risk_profile: unified PR/branch risk assessment — fuses blast radius + complexity + churn + test gaps + volume into composite score. Phase 7: when runtime traces have been ingested, adds a 6th signal (runtime_traffic; W=0.15 with the static five rebalanced to 0.85 of their original weights) plus a runtime_dark_code_introduced flag for PRs that add code in files with zero runtime evidence. Static-only callers (no traces) keep the historical 5-signal mix bit-for-bit. |
| 178 | + get_parity_map.py # (v1.108.111) get_parity_map: correspondence-aware migration parity between a SOURCE and TARGET symbol tree (two subpaths of one repo, or two repos). Exact + rename matching (reuses find_similar_symbols _signature_tokens/_callee_set/_jaccard/_byte_ratio), status per source symbol (ported/ported_diverged/unported/orphaned/added), dependency-ordered port_plan (adjacency from _callee_set, SCC grouping via get_dependency_cycles._find_cycles, Kahn topo, unblocked/blocking_deps). Read-only/plan-only; parity_axes reserved for P3 suite axes. Standard tier |
177 | 179 | get_hotspots.py # get_hotspots: top-N high-risk symbols by complexity x churn |
178 | 180 | get_repo_map.py # get_repo_map: query-less, token-budgeted, signature-level repo overview ranked by PageRank — cold-start orientation. Reuses cached PageRank, emits signatures only (no bodies), greedy-packs per-file under token_budget |
179 | 181 | find_similar_symbols.py # find_similar_symbols: multi-signal consolidation detection — semantic (embeddings) + structural (signature/size) + behavioral (callee Jaccard); union-find clustering, verdict tier (near_duplicate / similar_logic / parallel_implementation), canonical pick by PageRank, differs_by breakdown. BM25 inverted-index pre-filter for sub-N^2 cost. Skips tests/dunders/generated by default. |
@@ -259,6 +261,7 @@ src/jcodemunch_mcp/ |
259 | 261 | | `digest` | Agent stand-up briefing — composes since-last-session delta + risk surface + dead-code candidates; tracks per-repo last-seen SHA at `~/.code-index/digest_state/`; also exposed as MCP tool `digest`. v1.108.68 adds a one-line retrieval-regret summary when the ledger has clusters | |
260 | 262 | | `reflect` | (v1.108.68) Surface retrieval regret as SUGGESTED config corrections — `reflect [repo] [--project-path] [--window-days N] [--all] [--apply-weights] [--json]`. Thin CLI over the `suggest_corrections` tool; read-only (only `--apply-weights` writes, and only the tuning.jsonc sidecar) | |
261 | 263 | | `delivery` | (v1.108.69) Print durable-change delivery metrics for a window — `delivery [repo] [--window-days N] [--rework-horizon-days N] [--cost DOLLARS] [--json]`. Thin CLI over `get_delivery_metrics`; `--cost` prints the headline cost-per-durable-change (how much got done for how little). Read-only git archaeology | |
| 264 | +| `parity` | (v1.108.111) Map migration parity between two symbol trees — `parity <source> <target> [--source-path P] [--target-path P] [--match-threshold F] [--divergence signature\|signature+body\|name_only] [--no-rename] [--no-port-plan] [--json]`. Thin CLI over `get_parity_map`: ported/diverged/unported/orphaned/added counts + dependency-ordered port plan. Read-only/plan-only | |
262 | 265 | | `health` | Print `get_repo_health` JSON to stdout (includes six-axis radar). For CI/scripting; `--radar-only` for just the radar sub-field. Used by the v1.88.0 health-radar GitHub Action | |
263 | 266 | | `file-risk` | Print per-symbol risk JSON for a file (composite score + four-axis breakdown). Used by the v0.2.0 VS Code risk-density gutter | |
264 | 267 | | `observatory build\|init` | Public OSS code-health observatory pipeline — clones, indexes, scores a configured repo list; writes static HTML + RSS + JSON to an output dir. v1.90.0; CI repo-id bug fixed in v1.90.1. Live at https://jgravelle.github.io/jcodemunch-observatory/ | |
|
0 commit comments