591 Commits

Author SHA1 Message Date
Safi 55d7dadb63 bump to 0.8.26
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.26
2026-05-30 21:40:52 +01:00
Manoj Mishra c066511bf2 feat: detect circular import dependencies at file level (#961)
* feat: detect circular import dependencies at file level

- Add find_import_cycles() to analyze.py
- Collapses symbol nodes to parent files, builds directed file graph
- Uses nx.simple_cycles() bounded by max_cycle_length (default 5)
- Deduplicates rotations, returns shortest cycles first
- Considers both imports_from and re_exports edges

Tested on a 976-file Next.js codebase: found 4 cycles including
a known utils↔barrel circular dependency and a 4-file API cycle.

* fix: resolve import-cycle merge blockers

- use source_file-only endpoint resolution (no label fallback)
- support Graph/DiGraph orientation via edge source_file
- return structured cycle records and include self-loops
- integrate Import Cycles section into GRAPH_REPORT.md
- expand cycle tests for real-schema IDs, undirected input,
  missing source_file nodes, and non-import relations
2026-05-30 21:37:47 +01:00
Safi cca13aa8fd fix anchored gitignore pattern leaking basename match into subtree (closes #1087)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 18:16:01 +01:00
Safi a9d6be6537 add custom LLM provider registry via providers.json (closes #1084)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 13:25:02 +01:00
Safi 006e1594eb fix extract_files_direct backend default: auto-detect instead of kimi (closes #1086)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 13:17:13 +01:00
Safi d4e1d4b553 fix pnpm-workspace.yaml packages:'.' crash on Python 3.10 (closes #1083)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 13:13:23 +01:00
Alexis Valentino 5056c72e67 docs: add Filipino (fil-PH) README translation
Co-authored-by: alexisvalentino <alexisvalentino@users.noreply.github.com>
2026-05-29 23:43:56 +01:00
Safi a7a732290c release 0.8.25: JS/TS phantom nodes, Lua imports, Windows cli, hook lock, antigravity path
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.25 v0.8.24 v0.8.23
2026-05-29 16:59:17 +01:00
Safi 998594091b fix antigravity global install path to ~/.gemini/config/skills/ and uninstall symmetry (#1079)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:15:26 +01:00
Safi 9db86942bd warn against pip install on Mac/Windows due to env path mismatch (#1074)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 14:13:05 +01:00
Safi 282afaac7d add missing test coverage for #1077 scope guard and markdown fence fixes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 14:07:03 +01:00
Safi 925eb81ec1 fix JS/TS phantom god-nodes from arrow-fn locals and drop markdown code-block orphan nodes (#1077)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 13:46:30 +01:00
Safi 5642c1b533 fix Lua require() import edges lost due to wrong target ID resolution (#1075)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 13:36:04 +01:00
Safi f0badd9899 fix Windows claude-cli WinError 2 and post-commit hook silent drop on rapid commits
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:41:42 +01:00
Safi fd1aca480f release 0.8.24: cross-language semantics, claude-cli fix, edge direction fix, security audit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 02:28:52 +01:00
Safi 8a308519f9 Merge pull request #1063 from christophepub/fix/claude-cli-hollow-responses-v2
Fix hollow-response loop in claude-cli backend (re-targeted to v8, clean diff, with tests)
2026-05-29 01:54:37 +01:00
Safi aae027f7e6 Merge pull request #1071 from TheFedaikin/v8
Fix CI and ddd semantic contexts for ObjC, Julia, C, C++, Scala, Fortran, and PowerShell
2026-05-29 01:54:30 +01:00
Danil Tarasov 0080fbd13c feat: add objc, julia, c, c++, scala, fortran, powershell semantic contexts 2026-05-29 00:05:28 +03:00
Safi 66acfd81aa fix calls edge direction flipping on bidirectional pairs in undirected build (#1061)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:40:04 +01:00
Safi c2de9fa72f add uv-aware install detection to all skill files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:07:24 +01:00
Safi 8e179736ce fix .graphify_python path missing graphify-out/ prefix in skill files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:55:07 +01:00
christophepub 379d35e088 fix(claude-cli): eliminate hollow-response loop from system-prompt conflict
Three compounding bugs caused ~30-50% of semantic chunks to come back
as 'hollow responses' on the claude-cli backend, triggering adaptive
bisection that doubled or tripled the number of subprocess calls.

Root causes
-----------
1. _parse_llm_json only stripped markdown fences when raw.startswith('```').
   Claude frequently prepends a short preamble before the fence
   ('Here are the extracted entities:\n\n```json\n{...}```'), making
   the check fail. json.loads then drops the chunk. Each bisected half
   may exhibit the same failure, so cost compounds.

2. _call_claude_cli used --append-system-prompt, which layers graphify's
   extraction prompt on top of Claude Code's default interactive-agent
   prompt ('use markdown formatting', 'output text to communicate with
   the user'). The conflicting instructions explain ~50% of the
   preambles and fences from (1). Switching to --system-prompt (replace)
   eliminates the conflict at the source.

3. claude-cli defaults to Opus, which is overkill for the structured
   JSON extraction graphify performs. New GRAPHIFY_CLAUDE_CLI_MODEL env
   var lets users opt into haiku / sonnet for big builds. Default
   behaviour unchanged when the env var is unset.

Fix
---
- Robust _parse_llm_json: strips fences regardless of position, with a
  balanced-brace fallback that scans for the first complete JSON object
  in the response. Handles preambles, trailing prose, prose-wrapped
  JSON without fences. Diagnostic log on terminal failure includes the
  first 200 chars of the response.
- _call_claude_cli switches to --system-prompt.
- _call_claude_cli respects GRAPHIFY_CLAUDE_CLI_MODEL when set.

Tests (tests/test_llm_parser.py)
--------------------------------
- The four PR-body failure modes: preamble+fence, prose+JSON, raw JSON,
  total refusal.
- Bonus: uppercase fence tag, unclosed fence, empty response.
- argv shape: --system-prompt present, --append-system-prompt absent.
- argv shape: --model added iff GRAPHIFY_CLAUDE_CLI_MODEL is set.

19/19 tests pass (9 pre-existing in test_claude_cli_backend.py +
10 new). Verified end-to-end on a 800-file repo: 0 hollow responses
after, vs ~30-50% before; output tokens -93%; wall time 44 min -> 4 min.
2026-05-28 17:44:35 +02:00
Safi 7c12499783 chore: install all extras in CI to catch test gaps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:53:45 +01:00
Safi ffbe425c2f release 0.8.23
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:52:01 +01:00
TheFedaikin 32aa053e6c feat: semantic type-reference edges for Swift, Kotlin, PHP, Rust, and Go (#1015) 2026-05-28 14:46:03 +01:00
Safi cddf47d3a0 chore: commit uv.lock (regenerated for 0.8.22 with tree-sitter-dm)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:38:59 +01:00
Brian K 244a266c06 chore: switch CI to uv, remove uv.lock from gitignore (#885)
* chore: declare pytest as a uv dev dependency

The contributing guide currently tells contributors `pip install pytest`
as a separate step, and CI does the same. Move pytest into PEP 735
`[dependency-groups]` so it's declared in pyproject.toml and `uv sync`
installs it by default (no `--with` workaround, no separate install
line). Update CI to use astral-sh/setup-uv + `uv sync` + `uv run pytest`,
and refresh the Contributing section of the README to match.

`[dependency-groups]` is the right home (vs `[project.optional-dependencies]`)
because pytest is dev-only and shouldn't appear in the published wheel's
optional features list alongside things like `pdf` or `mcp`.

* remove uv.lock from gitignore
2026-05-28 14:38:31 +01:00
Safi a1706ff7fd docs: add --mode deep to graphify extract CLI reference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:30:36 +01:00
Safi 43bf3c2371 release 0.8.22
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.22
2026-05-28 00:26:31 +01:00
Safi cfc945a507 fix: cap zlib decompression in extract_dmi, add size guard in extract_dmm
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:08:55 +01:00
Safi dacbdb539a feat: BYOND DreamMaker support, --mode deep flag, changelog fixes (#884, #1030)
- Feat: extract_dm (tree-sitter-dm), extract_dmi (PNG icon states),
  extract_dmm (tile dict uses edges), extract_dmf (window/elem hierarchy)
  for .dm .dme .dmi .dmm .dmf; 26 tests, fixtures, pyproject.toml dep
- Feat: graphify extract --mode deep flag; deep_mode threaded through all
  four LLM backends via extract_corpus_parallel
- Fix: CHANGELOG 0.8.21 entries for #1050, #1046, #1047 that were missing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 23:55:12 +01:00
Aadi c09fbef401 fix: remap hyperedges in community-aggregated meta-graph view (#1006)
When a graph exceeds the viz node limit, to_html() builds a
community-aggregated meta-graph and recursively calls itself.
The recursive call never carried hyperedges onto the meta-graph,
so graph.html always emitted const hyperedges = [] even when
graph.json contained plenty.

This fix remaps hyperedge node references from semantic node IDs
to community IDs before the recursive call, so hyperedge regions
render correctly in the aggregated view. Hyperedges that collapse
to fewer than 2 distinct communities are dropped (they wouldn't
render as a polygon anyway).

Fixes #1005
2026-05-27 22:39:01 +01:00
Safi 9f73400cbc fix: memory-dir gitignore leak, Pass 2 dedup cross-file identical merge, decorated method node ID mismatch (#1047, #1046, #1050)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 22:30:08 +01:00
Safi 740382af51 docs: add Amp platform, .svh extension, fix opencode uninstall in README 2026-05-27 13:04:50 +01:00
Safi 80301a06bf fix: OpenCode project path, hook loop guard, deterministic output, Amp platform, punctuation search, builtin god-node filter, .svh Verilog (#1040, #1018, #1037, #948, #994, #916, #1042)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.21
2026-05-27 12:39:22 +01:00
Aleksandr Tarutin a54a542b6c fix: make graph output deterministic (stop graphify-out churn) (#1010)
graphify-out regenerates differently on every `graphify update` even
when no source changed, so the committed graph is perpetually dirty and
the post-commit/post-checkout hooks fight every commit. Two independent
nondeterminism sources, each fixed here:

1. Edge direction flips. build.py builds an undirected graph and stores
   direction in _src/_tgt; collapsing two edges onto the same node pair
   is last-write-wins, and unstable edge iteration order flips them
   run-to-run. Fixed by sorting edges by (source, target, relation)
   before the add loop.

2. Clustering churn. The networkx Louvain fallback iterates string-keyed
   sets whose order is randomized per-process by PYTHONHASHSEED, so
   community assignments differ run-to-run even with seed=42. Fixed by
   exporting PYTHONHASHSEED=0 in the generated post-commit and
   post-checkout hook scripts.

With both fixes, `graphify update` is idempotent: rebuilding an
already-converged graphify-out reproduces graph.json and GRAPH_REPORT.md
byte-for-byte.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 12:20:31 +01:00
Safi d1d5751fa4 fix(watch): evict stale nodes in full re-extraction path when changed_paths is None (#1007)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 11:21:55 +01:00
Safi b07f0eb6a7 bump version to 0.8.20 v0.8.20 2026-05-26 20:34:22 +01:00
Safi ad3f3b2d9e harden XML parsing against billion-laughs DoS in extract_csproj and extract_lpk
stdlib ET does not cap entity expansion — a crafted .csproj or .lpk with nested
internal entities can exhaust memory. Pre-screen input bytes for <!DOCTYPE and
<!ENTITY before parsing (legitimate MSBuild/Lazarus files never contain these).
Also adds the missing 2 MiB size cap to extract_lpk (csproj already had one).
No new dependencies required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 20:32:14 +01:00
Safi e5313e73b2 add MCP config files to README file types table 2026-05-26 20:24:14 +01:00
Alexey Z baaab5f2a9 fix(extract_dart): use _file_stem instead of str(path) for child node IDs to prevent machine-specific absolute paths in graph.json (#999) 2026-05-26 20:21:27 +01:00
Safi 2c01a89b28 feat: MCP config extractor (.mcp.json, claude_desktop_config.json, mcp.json)
Adds graphify/mcp_ingest.py — extracts MCP server configurations into the
knowledge graph. Captures server nodes, NuGet/npm/pip package refs, commands,
env var requirements, and inter-server edges. Dispatched by filename before
the suffix lookup so generic .json extraction is unaffected. Env values are
discarded to prevent secret leakage. File size capped at 1 MiB. 29 tests.

Fixes: server_count budget now checked after validity guard so invalid entries
don't consume capacity; removed misleading uv run docstring example.

Co-Authored-By: adityachaudhary99 <adityachaudhary99@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 20:16:41 +01:00
Leon GyeongMan Baek 9abaa77c62 fix(cli): apply remap_communities_to_previous in cluster-only path (#1028)
cluster-only re-runs Leiden clustering and then re-applies the existing
.graphify_labels.json by raw cid index, which causes labels to attach to
clusters whose members are unrelated to the label's original meaning
whenever the graph has changed between labeling and re-clustering.

Mirror the safety net already present in watch.py:_rebuild_code added in
#822 for the watch/update paths.

Adds a regression test that fails without the fix (label cids become
orphaned from graph.json community attributes after re-clustering).

Refs: #1027

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 20:12:02 +01:00
Safi 3f8efaebc2 fix graphify update ghost nodes: as_posix() and relativize existing graph before eviction
Three issues in _rebuild_code (watch.py):
1. _relativize_source_files was called on result after eviction list was built,
   so existing nodes with absolute source_file were never normalized before comparison
2. deleted_paths and evict_sources used str() (backslashes on Windows) while
   graph.json stores forward-slash paths via _norm_source_file
3. _relativize_source_files itself used str() instead of as_posix()

Also fix extract.py source_file relativization to use as_posix(). Closes #1007.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 20:05:31 +01:00
Safi eef623a54a improve #1007 fix: use _norm_source_file with resolve() for symlink safety
Replace inlined path normalisation with _norm_source_file (the same function
that builds node source_file keys) so prune_set and node attrs are normalised
identically. resolve() on root handles symlinked scan roots. Keep both raw and
normalised forms in prune_set so nodes with absolute source_file also match.
Add edge pruning and Windows backslash path tests per Opus review.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 14:59:13 +01:00
Safi a26f24ef7b fix stale nodes persisting after file deletion when manifest uses absolute paths
prune_set in build_merge now includes relative-path variants of each deleted file
so manifest absolute paths (e.g. /home/user/corpus/module_b/utils.py) match graph
node source_file values (e.g. module_b/utils.py) regardless of OS or run context.
Fixes #1007.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 14:53:36 +01:00
Safi d9debdf39a bump version to 0.8.19 v0.8.19 2026-05-26 12:52:04 +01:00
Safi 903fa9c141 add chinese extra to README optional extras table 2026-05-26 12:39:16 +01:00
Safi 8bcfffdf62 add .NET project file support (.sln, .csproj, .fsproj, .vbproj, .razor, .cshtml)
Adds extract_sln, extract_csproj, and extract_razor extractors. Captures NuGet
package refs, project-to-project dependencies, target frameworks, SDK attribute,
@using/@inject/@inherits/@model directives, Blazor component refs, and @code
methods. Resolves relative project paths to absolute paths so sln/csproj nodes
link correctly when the graph is assembled. Closes #515.

Co-Authored-By: aksrathore <aksrathore@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 12:27:28 +01:00
Candy c7a05d67a1 Clarify Chinese query segmentation scope (#1026)
Keep Graphify query segmentation focused on Chinese terms: rename the CJK helpers and extra to Chinese scope, cache the optional jieba import at module load, and keep a bigram fallback when jieba is unavailable.

Constraint: Reviewer asked either to broaden Hiragana/Katakana/Hangul support or rename CJK helpers; user chose Chinese-only because Japanese segmentation accuracy is uncertain.

Rejected: Broaden to Japanese and Korean segmentation | jieba is Chinese-oriented and the user explicitly limited scope to Chinese.

Confidence: high

Scope-risk: narrow

Directive: Do not label this path as CJK unless Hiragana/Katakana/Hangul segmentation is intentionally supported and tested.

Tested: uv run --with pytest pytest tests/test_serve.py tests/test_query_cli.py tests/test_benchmark.py

Tested: uv run --with pytest --with jieba pytest tests/test_serve.py -k "chinese or non_chinese"

Tested: graphify update .

Not-tested: Full test suite.

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-26 12:24:04 +01:00