You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#338 — check_edit_safe / check_delete_safe called check_references in singular
mode (identifier=, flat response) but iterated the batch-only `results` key, so
identifier content-references were always counted as zero and a still-referenced
symbol could come back safe_to_delete. Both call sites now use identifiers=[...].
#339 — find_importers(file_paths=[...], cross_repo=true) passed an empty path
into the package-level cross-repo helper for multi-file batches. The combination
now fails closed with a clear error; single-element batches stay honored.
Bump to 1.108.63. New tests/test_v1_108_63.py (7 cases).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CLAUDE.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
# jcodemunch-mcp — Project Brief
2
2
3
3
## Current State
4
+
- **Version:** 1.108.63 — Two composite/contract correctness fixes (both reported by @mmashwani, source-cited). **#338**: `check_edit_safe` + `check_delete_safe` called `check_references(identifier=...)` (singular → flat `import_references`/`content_references`, no `results` key) then iterated the batch-only `ref_out.get("results", [])`, so the identifier content-reference signal (Signal 2/3) was ALWAYS zero — a symbol still referenced by a duck-typed/string-dispatch call site (no import edge, so `find_importers`/Signal 1 misses it too) could return `safe_to_delete`. Fix = both call sites switch to the batch form `identifiers=[target_name]`, producing the grouped `results` shape the loops already expect (external preflight response shape unchanged). **#339**: `find_importers(file_paths=[...], cross_repo=true)` passed `""` into `_find_cross_repo_importers` for multi-file batches. That helper is **package-level** (it resolves the repo's package importers and ignores its `file_path` arg entirely), so a multi-file batch either dropped the evidence or implied per-file precision that doesn't exist; now **fails closed** with a clear error (`_meta.cross_repo_scope=package`, `file_count`) pointing at singular calls, while a single-element `file_paths` batch is still honored (== singular path). Docstring + `server.py` schema for `find_importers.cross_repo` document the constraint. New `tests/test_v1_108_63.py` (7): content-reference blocking on delete/edit + no-false-positive orphan guard + cross-repo batch contract (multi-file errors, single-file allowed, no-cross-repo + singular unaffected). 165 passed across the four affected suites + new file. Shipped to PyPI. See [[project_community_mmashwani]]. **#340 (bounded-source mode for `get_symbol_source`) accepted-in-principle, deferred to a follow-up — enhancement w/ API-surface design choices.**
4
5
- **Version:** 1.108.62 — Index templating-language files over a supported underlying source language (#336, PR #337 by @horknfbr). Files of the form `name.<underlying-ext>.<engine-ext>` (Jinja2 template of TypeScript `foo.ts.j2`, Jinja of Python `service.py.jinja`, Twig of TS `widget.ts.twig`) were dropped at discovery as `wrong_extension` (`get_language_for_path` resolved the compound from the first dot → `.ts.j2` unregistered → `None`), so every real source symbol inside went unindexed. Now recognized: engine constructs are **masked offset-preserving** (each `{{ }}`/`{% %}`/`{# #}` hole → same-length `_` filler, newlines kept) and the body is re-parsed as its underlying language via recursive `parse_file()`, so symbols/signatures/imports/line+byte positions all resolve with **no block re-wrapping** (simpler than the Astro/Razor sub-block extractors). **Engines:** Jinja2 (`.j2`/`.jinja`/`.jinja2`) + Twig (`.twig`); pluggable `TemplateEngine` registry in new `parser/template_shared.py` (single-extension HTML-bodied engines can be added on demand). Underlying language inferred from the **middle extension** by stripping the engine suffix and resolving the remainder recursively — so every supported language works as the body with no per-language work. **Discovery guard:** the strip/recurse step in `get_language_for_path` sits *after* the compound + last-extension checks and fires only for registered engine extensions, so it can only ever turn `None` into a language, never re-resolve a `.d.ts`/`.test.ts`/`.blade.php` (non-collision tests included). `{% macro %}`/`{% block %}` definitions additionally surfaced as symbols, **reusing** `sql_preprocessor.extract_dbt_directives` (generalized to take a `directive_keywords` set; the default dbt set stays byte-identical) rather than a parallel regex. `repo` forwarded into the recursive body parse so the underlying language honors per-project `.jcodemunch.jsonc` gating. **Purely additive — previously-skipped files only add symbols, no `INDEX_VERSION` bump** (a re-index picks up the now-recognized files). New `parser/template_shared.py`; `extractor.py` `_parse_template_symbols`; `imports.py` template branch; `languages.py` `template_underlying_language` + `_TEMPLATE_LANG_SPEC`. New `tests/test_templates.py` (17 cases) + fixtures; `LANGUAGE_SUPPORT.md` updated. Verified pre-merge against the PR branch: 17/17 template tests + 607-case parser/sql/dbt/astro/razor/languages/importers sweep all green, dbt path byte-identical. Shipped to PyPI (first contributor template-language feature). See [[project_jcm_336_template_indexing]].
5
6
- **Version:** 1.108.61 — Config-template completeness. 13 keys lived in `DEFAULTS`/`CONFIG_TYPES` but were never added to the JSONC template that `config_report` parses for `group`+`description`, so `config --json` emitted them under the `Other` catch-all with an empty description (surfaced via the jMunch Console's grouped config screen showing blank rows). Added all 13 to `generate_template()` under proper `=== Section ===` headers + inline comments: `watch_paths`/`watch_extra_ignore`/`watch_follow_symlinks`/`watch_idle_timeout`/`watch_log` → **Watcher**; `runtime_ingest_enabled`/`org_ingest_enabled`/`runtime_ingest_max_body_bytes` → new **Runtime & Org HTTP Ingest**; `license_key` → new **Licensing**; `cross_repo_default`/`discovery_hint` → **Identity & Indexing Behavior**; `agent_selector` → new **Agent Selector (model routing)**; `enrichment` → new **Enrichment (LSP)**. `Other` is now empty. Metadata is parsed from the template (not the user's on-disk config) so descriptions appear immediately on upgrade — no `config --upgrade` needed. New regression test `TestConfigReportGrouping::test_no_key_falls_into_other_or_missing_description` fails if any future `DEFAULTS` key ships template-less. No config *value* behavior change. See [[project_jmunch_console]].
6
7
- **Version:** 1.108.60 — #335 (reported by @mmashwani). `config --check` treated *every* index-storage probe exception as a confirmed `storage` failure (exit 1), so a sandboxed agent shell that can read the index but can't write the index root (`PermissionError` EPERM/EACCES on the `.jcm_probe` write) reported a healthy install as broken — exactly the false-failure an agent might "repair." Fix (his suggested shape): split the probe's `except` — a `PermissionError` with `errno` ∈ {EPERM, EACCES} is **host-confirmation-needed** (`⚠ index storage writability needs host confirmation` + a "rerun outside a sandbox/restricted shell" hint, recorded in a new `host_confirmation` list), NOT a confirmed failure; any other exception (e.g. `EROFS` read-only FS) stays a confirmed `✗ index storage not writable` issue. Exit contract: confirmed `issues` → exit 1 (unchanged); host-confirmation-only (no confirmed issues) → **exit 0** so an agent client doesn't mistake a healthy install for a broken one (a new nonzero exit code would risk the same false-failure, so deliberately not introduced). `import errno` added to server.py. 4 tests `tests/test_config.py::TestServerConfigCheckStorageProbe` (writable→pass/exit0; EROFS→confirmed/exit1; EPERM→host-confirmation/no-exit; output names sandbox + rerun).
"file_path": {"type": "string", "description": "Target file path within the repo (e.g. 'src/features/intake/IntakeService.js'). Use for single-file queries. Cannot be used together with file_paths."},
1392
1392
"file_paths": {"type": "array", "items": {"type": "string"}, "description": "List of target file paths for batch queries. Returns a results array. Cannot be used together with file_path."},
1393
1393
"max_results": {"type": "integer", "default": 50, "description": "Maximum results per file"},
1394
-
"cross_repo": {"type": "boolean", "default": False, "description": "When true, also search other indexed repos for cross-repo importers. Default: false (or JCODEMUNCH_CROSS_REPO_DEFAULT env var)."},
1394
+
"cross_repo": {"type": "boolean", "default": False, "description": "When true, also search other indexed repos for cross-repo importers (package-level scope). Default: false (or JCODEMUNCH_CROSS_REPO_DEFAULT env var). Only valid with singular file_path or a single-element file_paths batch; combined with a multi-file file_paths batch it returns an error (use singular calls for cross-repo evidence)."},
0 commit comments