Commit Graph

684 Commits

Author SHA1 Message Date
Skyler Southern 58efcebd83 fix: resolve_seed matches bare names against ()-decorated callable labels
Callable nodes are labeled with a trailing "()" (e.g. classifyProperty()),
so a bare-name query like "classifyProperty" falls through the exact-label
pass and then ties with any prefix sibling (classifyPropertySafe()) in the
contains pass, returning "No unique node match" even though exactly one
callable with that name exists.

Add a bare-name pass between exact-label and exact-source matching that
compares query and label with the trailing "()" stripped from each. Bare
queries now resolve decorated labels and vice versa; genuine duplicates
still return None.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:14:28 -04:00
Safi cce2673021 fix: LLM calls-edge direction reversal and ghost-node merge
llm.py: add explicit edge direction rule to extraction system prompt —
source = actor (caller/importer/subclass), target = acted-upon (callee/
imported/base). LLM was systematically emitting callee->caller for calls
edges because the schema never stated direction semantics.

build.py: extend ghost-node merge to catch LLM nodes that populate
source_location (bypassing the old None check). Now uses _origin=="ast"
as the canonical signal — AST nodes always win; any non-AST node sharing
(basename, label) with an AST node is collapsed into the AST canonical.
Fixes LLM bare-stem IDs (bpe_get_pairs) surviving alongside AST
parent-qualified IDs (mingpt_bpe_get_pairs) and carrying reversed edges.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 12:03:59 +01:00
Safi 565026d3d1 fix(ci): add cluster-only step to generate GRAPH_REPORT.md in release-graph
extract intentionally stops at graph.json; GRAPH_REPORT.md requires cluster-only.
Use --no-label to skip LLM community naming (no API key needed in CI).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 22:01:12 +01:00
Safi ba1921fe76 fix(ci): skip .md/.txt files in release-graph to avoid LLM API key requirement
graphify/skills/ contains 126 markdown files that trigger semantic extraction.
Add a temporary .graphifyignore entry during CI to keep the build pure AST.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 21:55:16 +01:00
Safi e6d2dc4d6f release 0.8.37 v0.8.37 2026-06-10 21:45:02 +01:00
Safi 1513e6271a fix(ci): correct three bugs in release-graph workflow
- extract graphify/ (code only) instead of . to avoid LLM API key requirement;
  the repo root contains docs/skills/.md files that trigger semantic extraction
- use --out . so output writes to ./graphify-out/ not ./graphify/graphify-out/
- remove --out from export html (flag does not exist; HTML auto-written next to graph)
- drop nonexistent --code-only flag from extract command
- add comments explaining each flag's behavior

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 21:15:00 +01:00
Safi 7182b18c35 ci: add release-graph workflow to ship self-graph as release asset
Runs graphify against its own source on every GitHub release (AST-only,
no API cost) and attaches graph.json + graph.html + GRAPH_REPORT.md as
graphify-self-graph.tar.gz to the release. Also supports manual runs via
workflow_dispatch, uploading the bundle as a 7-day workflow artifact.

Closes #1238

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 21:07:38 +01:00
Safi a37672f25f fix: obsidian crash, NFC/NFD dedup, JSON data nodes, OpenAI temperature, JSON config detection
- export.py: guard to_obsidian/to_canvas against dangling community member IDs
  (KeyError crash when a node in communities dict is absent from graph, #1236)
- detect.py: NFC-normalize path before hashing Office sidecar filename to fix
  macOS NFC/NFD mismatch causing --update to re-extract all Office files (#1226)
- extract.py: add _is_config_json() to skip data JSON files (only extract
  package.json, tsconfig.json, eslint, deno, JSON Schema etc.) eliminating
  561 orphan key-nodes on large repos (#1224)
- llm.py: add GRAPHIFY_LLM_TEMPERATURE env var + _resolve_temperature() helper;
  auto-omit temperature for o1/o3/o4/gpt-5 reasoning models that reject temp=0;
  mirrors GRAPHIFY_MAX_OUTPUT_TOKENS precedence pattern (#1191)
- tests: 20 new regression tests across obsidian, detect, extract, llm_backends

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 19:31:47 +01:00
Safi 5504c84324 perf/fix: replace datasketch with pure-numpy MinHash; memoize detect ignore checks
- graphify/_minhash.py: self-contained MinHash/MinHashLSH using pure numpy,
  byte-identical hash math to datasketch (sha1_hash32, Mersenne-prime permutation).
  Drops datasketch + scipy transitive dep — eliminates EDR hang on Windows where
  numpy.testing platform.machine() subprocess spawn was intercepted at import time
- dedup.py: import from graphify._minhash instead of datasketch
- pyproject.toml: replace datasketch>=1.6 with numpy>=1.21
- detect.py: memoize _is_ignored/_eval results in a dict[Path,bool] cache per
  detect() call; each unique ancestor dir evaluated once across all sibling files,
  eliminating ~42M redundant fnmatch calls on large repos (~34% whole-run speedup)
- tests/test_minhash.py: 11 tests including import-isolation guard asserting scipy
  and numpy.testing are not loaded after import graphify.dedup
- tests/test_detect.py: 2 cache tests — correctness (cached==uncached with negation
  patterns) and hit-count (each dir evaluated exactly once across siblings)

Closes #1234, closes #1235

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 15:50:38 +01:00
Safi 6695f0aefd fix: security hardening, dedup correctness, and large-graph support
- security.py: replace global socket.getaddrinfo monkey-patch with per-connection
  _SSRFGuardedHTTPConnection/HTTPSConnection subclasses (thread-safe, closes TOCTOU)
- security.py: add GRAPHIFY_MAX_GRAPH_BYTES env var override for 512MB cap (MB/GB suffix
  supported); improve cap error message to cite the env var
- llm.py: wrap untrusted source files in XML delimiters with sha256 fingerprint;
  neutralise jailbreak sentinel tokens to mitigate prompt injection
- dedup.py: skip code nodes in label-based dedup passes; code symbols now deduplicated
  by ID only, preventing distinct same-named symbols from merging
- extract.py: cross-file calls resolution now consults import evidence before bailing
  on ambiguous callee names; emits EXTRACTED edges when named import is unambiguous
- analyze.py: extend _BUILTIN_NOISE_LABELS with stdlib types and modules
- __main__.py: CLAUDE.md template uses MANDATORY language for graphify-first rule;
  PreToolUse hook message hardened to imperative; graphify export html auto-falls
  back to community-aggregation view when graph.json exceeds size cap
- tests/test_pg_introspect.py: add importorskip guard for tree_sitter_sql

Closes #1211, #1210, #1205, #1219, #1227; resolves discussion #1019

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:45:20 +01:00
Safi 137bc2d951 release 0.8.36
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.36
2026-06-08 23:58:08 +01:00
Safi e477825a97 fix: three correctness bugs — cycle hang, label token budget, fuzzy dedup prefix merge
- analyze.py: pass length_bound=max_cycle_length to nx.simple_cycles() so
  networkx prunes during enumeration instead of post-filtering; drops report
  generation from never-returns to ~0.1s on dense graphs (#1196)

- llm.py: replace hardcoded min(40+16*n,4096) label_communities token budget
  with _resolve_max_tokens(min(64+24*n,8192)) — 24 tok/community covers 5-word
  JSON entries; 8192 cap fits 16k-context models; env var now honoured (#1200)

- dedup.py: add prefix-extension guard in Pass 2 and _llm_tiebreak — skip merge
  when one normalised label is a strict prefix of the other (getActiveSession /
  getActiveSessions, parseConfig / parseConfigFile). Option (a) rejected: dropping
  the >=12 early-out from _short_label_blocked breaks test_typo_merged (#1201)

- tests/test_dedup.py: two new regression tests verifying prefix guard fires for
  extension pairs and does not fire for same-length typo pairs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 23:49:16 +01:00
freiit 3602c8031e fix: guard label/text normalizers against None node labels (#1195)
Guards _norm, _norm_label, and _strip_diacritics against None node labels that cause TypeError in unicodedata.normalize(). Fixes #1194. Consistent with existing security.py:270 precedent.

Co-authored-by: freiit <freiit@users.noreply.github.com>
2026-06-08 23:22:15 +01:00
EirikWolf 7477b469ee feat: extra_body for custom providers + multi-batch label_communities (#1197)
Adds extra_body parameter support for custom/OpenAI-compat providers so users can pass provider-specific params (e.g. thinking budget for Claude via Bedrock compat). Adds multi-batch label_communities for 16k-context models — batches multiple community descriptions into a single LLM call instead of one per community. Partial batch failures are handled gracefully.

Co-authored-by: EirikWolf <EirikWolf@users.noreply.github.com>
2026-06-08 23:22:00 +01:00
Rasmus Bækgaard 29e57cd295 feat: add .slnx solution file support (#1189)
Adds support for the XML-based `.slnx` solution format (VS 2022 17.13+ replacement for `.sln`). Extracts project references as `contains` edges and build dependencies as `imports` edges. XXE-protected XML parsing with size cap. Wired into `_DISPATCH` and `CODE_EXTENSIONS`. 6 new tests passing.

Co-authored-by: bakgaard <bakgaard@users.noreply.github.com>
2026-06-08 10:35:32 +01:00
Jan 42d1b8d02f feat: add graphify-mcp console script entry point (#1190)
Adds `graphify-mcp` as a named console script pointing to `graphify.serve:_main`, making the MCP stdio server directly invocable as a first-class CLI command from uv tool / pipx installs. MCP client configs can now use `"command": "graphify-mcp"` instead of `python -m graphify.serve`.

Co-authored-by: jr2804 <jr2804@users.noreply.github.com>
2026-06-08 10:35:21 +01:00
Safi 8a04560bf5 fix: remove non-spec trigger: field from skill frontmatter (#1180)
The Agent Skills spec only defines name, description, license,
compatibility, metadata, and allowed-tools as valid frontmatter fields.
The trigger: /graphify line was non-spec, silently ignored by spec-
following hosts, and flagged by agentskills validate CI checks.

- gen.py: removed trigger emission from _render_frontmatter; added
  _is_trigger_line() helper for roundtrip allow-list
- fragments/core/aider.md: removed hardcoded trigger: /graphify
- platforms.toml: removed trigger doc comment and trigger="" entries
- test_skillgen.py: replaced trigger-assertion tests with a single
  test asserting no host has trigger: in frontmatter
- Regenerated all 125 skill artifacts

Routing intent is preserved: the description field already contains
"treated as a graphify query first" and "graphify-out/ exists".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 15:49:52 +01:00
Safi 6dbcb89f3d release 0.8.35
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.35
2026-06-07 14:42:30 +01:00
Safi 660d2d32cf fix(codebuddy): install SKILL.md in codebuddy install subcommand + fix README hook description
graphify codebuddy install was writing CODEBUDDY.md and settings.json
but not copying the SKILL.md. Added _copy_skill_file("codebuddy") call
to match the --platform codebuddy path. README hook description updated
from "Glob and Grep" to "Bash search and file reads" to match actual
hook matchers (Bash + Read|Glob).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:39:16 +01:00
Safi 9e1ad425a9 feat: add CodeBuddy platform support (#1136)
Adds graphify skill installation for CodeBuddy (https://www.codebuddy.ai/).
CodeBuddy uses the same agent+hook mechanism as Claude Code.

- graphify codebuddy install — writes ~/.codebuddy/skills/graphify/SKILL.md
  and a CODEBUDDY.md always-on section
- graphify codebuddy uninstall — removes both cleanly
- graphify install --platform codebuddy — same as above
- Registers Bash + Read|Glob PreToolUse hooks in .codebuddy/settings.json
- Full install/uninstall roundtrip tests (35 tests)

Co-authored-by: studyzy <studyzy@gmail.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:34:13 +01:00
Safi 12a9b5e812 fix: prevent fuzzy dedup from collapsing distinct same-named symbols on --update (#1178)
Three-part fix:

dedup.py: Pass 1 exact-merge now skips nodes with an empty source_file.
Previously all no-source_file nodes with the same label landed in one
bucket and were merged, destroying distinct symbols (third-party deps,
standalone functions) that happened to share a short name.

update.md (skillgen + all 13 host variants): the --update merge now
passes both deleted AND changed files to prune_sources, mirroring what
watch._rebuild_code already does correctly. Old nodes for re-extracted
files are pruned before fresh AST is inserted — no fuzzy reconciliation
needed, no cross-file collapse possible.

export.py: anti-shrink guard message now names fuzzy dedup as a
possible cause (not only "missing chunk files"), and advises a full
rebuild as the safe recovery path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:26:14 +01:00
Safi 3744e6e220 release 0.8.34
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.34
2026-06-07 12:51:33 +01:00
Safi 6a549e42d5 fix: four bugs — affected direction, hook root, glob fish/zsh, manifest drift (#1174 #1173 #1172 #1163)
#1174: affected.py load_graph now forces directed=True before
node_link_graph, matching the identical fix in serve.py and __main__.py.
Undirected graphs (directed:false in graph.json) were causing in_edges
to fall back to a direction-blind scan, missing true callers and
reporting false positives. Regression test added.

#1173: post-commit and post-checkout hook bodies now read
graphify-out/.graphify_root before calling _rebuild_code, falling back
to Path('.') if absent. A scoped build (graphify src/) no longer gets
silently expanded to the full repo on the next commit. Tests added.

#1172: Step 9 cleanup split into rm -f for fixed files and
find -maxdepth 1 -delete for the chunk glob. Under fish/zsh an
unmatched glob aborts the entire rm -f line, leaving temp files on disk.
Fixed in the three skillgen source fragments and regenerated.

#1163: detect_incremental type guard on stored mtime — if the manifest
contains a dict-valued mtime (schema drift from older versions), coerce
to None rather than propagating a non-numeric into comparisons.
Regression test added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 12:40:44 +01:00
Safi a8dbbe59cf fix: land PRs #1170 #1169 #1165 (hooks, sensitive filter, score_nodes)
#1170 — replace nohup with cross-platform Python detach in git hooks.
Git for Windows MSYS has no nohup so post-commit/post-checkout hooks
silently failed. Now uses subprocess.Popen with DETACHED_PROCESS |
CREATE_NEW_PROCESS_GROUP on Windows, start_new_session=True on POSIX.
Quoting-safe (argv list). Fixes #1161.

#1169 — fix _is_sensitive false positives on topic-mentioning filenames.
token-economics-of-recall.md and password-policy-discussion.md were
silently dropped as secrets. Generic keywords (token/secret/password)
now only fire when the keyword ends the filename stem or the stem is
≤2 words. Specific patterns (.env/.pem/id_rsa etc.) remain unconditional.

#1165 — fix multi-word endpoint resolution in _score_nodes.
graphify path "AuthService" "UserRepo" never fired the exact-match bonus
because per-token comparison never equalled the full label. Now joins
normalized tokens and compares against the full label and its tokenized
form. O(1) per node, affects query_graph and shortest_path uniformly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 12:20:36 +01:00
Safi f146be3ea2 fix: numpy Python 3.13 pin + codex skill dir (#1154 #1160)
#1154: scope numpy>=2.0 constraint to python_version>='3.13' only.
numpy 1.26.4 ships no cp313 wheel so uv sync falls back to a source
build requiring a C compiler. The marker avoids forcing numpy 2.x on
3.10-3.12 users who have working 1.x environments.

#1160: codex platform skill now installs to .codex/skills/graphify/
instead of .agents/skills/graphify/. The hook already wrote to .codex/
so the skill destination was inconsistent. Propagates automatically
through install/uninstall (both read _PLATFORM_CONFIG dynamically).
Updated all codex-specific test assertions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 12:11:34 +01:00
Safi 079b34da78 docs: update README for Apex, Azure, and PostgreSQL additions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 01:39:54 +01:00
Safi 7467c1b6a4 feat/fix: land PRs #1118 #1110 #1159 #1107 #1103 (graph quality + new features)
#1118 — prune stale AST nodes on full re-extraction (#1116)
Stamps every AST-extracted node with _origin="ast" in extract(). On a
full rebuild _rebuild_code drops any AST-marked node absent from the
fresh output even when its source file survives, fixing stale symbols.
Backward-compat: marker-less nodes from pre-1118 graphs survive one
cycle then self-heal.

#1110 — stop reading images and PDFs as garbage in headless extract
Images route through per-backend vision payloads (base64/data-URI/bytes
for claude/openai/bedrock); non-vision backends get _strip_pixels for
graceful degradation. PDFs reuse pypdf. 5MB cap, 20-image chunk limit.

#1159 — Salesforce Apex extractor (.cls, .trigger)
Regex-based extractor: classes, interfaces, enums, methods, triggers,
SOQL/DML edges. No new dependency. Dispatched as .cls and .trigger.

#1107 — Azure OpenAI Service backend (--backend azure)
Uses AzureOpenAI SDK client (from existing openai package). Auto-detects
when AZURE_OPENAI_API_KEY + AZURE_OPENAI_ENDPOINT both set. Uses
max_completion_tokens (not deprecated max_tokens).

#1103 — live PostgreSQL introspection (--postgres DSN)
graphify extract --postgres "postgresql://..." introspects tables, views,
routines, and FK relations via information_schema (SERIALIZABLE READ ONLY).
Credentials sanitized on error. New graphify[postgres] extra (psycopg3).

Union-resolved llm.py conflict: Azure functions + bedrock images= param.
Fixed test_image_vision.py mock to accept timeout= kwarg (our #1112).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 01:20:38 +01:00
Safi 7b4c8df6e9 docs: add Streamable HTTP transport section to README (#1155)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:47:29 +01:00
Safi 2a683aac2e feat(serve): add Streamable HTTP transport to MCP server (#1143)
python -m graphify.serve graph.json --transport http --port 8080 serves
the same MCP tools over the Streamable HTTP transport (spec 2025-03-26)
so a single shared process can serve the graph for a whole team.

- _build_server() refactors server registration into a shared factory
  (stdio behavior is byte-for-byte unchanged — all 52 existing tests pass)
- _ApiKeyMiddleware: raw ASGI (not BaseHTTPMiddleware) preserves SSE
  streaming; constant-time compare; RFC-6750 case-insensitive Bearer;
  blank-key normalized to no-auth
- DNS-rebinding protection via TransportSecuritySettings; wildcard binds
  disable it and print an exposure warning when no api-key is set
- session_idle_timeout reaps idle stateful sessions (default 3600s) so a
  long-running shared server does not leak memory on client disconnect
- Dockerfile + .dockerignore for containerized team deployment
- 16 new tests via in-process ASGI test client (importorskip-guarded)
- stdio remains the default; no change for existing setups

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:43:40 +01:00
Safi 4b06fd7bf7 release 0.8.33
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.33
2026-06-06 09:40:14 +01:00
Safi a380b34739 fix(extract): three graph quality fixes (#1145 #1146 #1147)
#1147 — builtin annotation nodes inflate god-node rankings:
Add _PYTHON_ANNOTATION_NOISE frozenset (str/int/bool/float/bytes/
MagicMock/Mock/AsyncMock/...) and apply it alongside
_PYTHON_TYPE_CONTAINERS in the annotation walker so scalar builtins
and test mocks are never created as nodes or emitted as edges.
Defense-in-depth guard in analyze.god_nodes filters _BUILTIN_NOISE_LABELS
so pre-existing graphs are also protected.

#1146 — package-form imports create disconnected islands:
from pkg import submod is now resolved to a file-level imports_from
edge when submod.py or submod/__init__.py exists on disk. Fix lives
in _collect_python_symbol_resolution_facts: when target resolves to
a __init__.py, each imported name is checked as a potential submodule
file and stored in _SymbolResolutionFacts.module_imports. Applied in
_apply_symbol_resolution_facts using stem-based canonical IDs.

#1145 — AST vs semantic node ID ghost duplicates:
build_from_json now runs a two-pass merge after adding all nodes:
collect AST nodes (source_location set) then find semantic ghosts
(same basename+label, no source_location). Ghosts are removed and
their IDs added to norm_to_id so all edges re-point to the AST node.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 09:35:59 +01:00
Safi 3405c1fb96 feat(install): add amber brain banner on graphify install
TTY-only (suppressed in CI/pipes). Windows ANSI enabled via ctypes.
Wrapped in try/except so it can never crash the install.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 23:46:15 +01:00
Safi ec1a3bc9e9 release 0.8.32
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.8.32
2026-06-05 22:50:47 +01:00
Safi 23acb41910 docs: bump grammar count to 28 (tree-sitter-hcl added in #1129)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:41:19 +01:00
Safi e3499e069c docs: add Terraform/HCL to file types table and optional extras (#1129)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:37:42 +01:00
Safi 9c2f2f5663 docs: clarify code-only extract needs no API key (#1122)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:34:34 +01:00
Safi f85339bcb1 fix(extract): don't require LLM API key for code-only corpus (#1122)
Backend resolution now defers until after file detection. A code-only
corpus (pure AST, zero LLM calls) runs without any API key.
Key validation only fires when needs_llm=True (semantic_files non-empty
or --dedup-llm passed). Error message now names why a key is needed and
notes that code-only corpora need none.

Applied from PR #1123 with one fix: _clear_backend_keys in tests now
also clears AWS_PROFILE/REGION, OLLAMA_BASE_URL to prevent CI flakes
on machines with ambient credentials.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:28:57 +01:00
Safi 3a4bdf54cc fix(install): route kiro install/uninstall through shared progressive helper (#1142)
_kiro_install was using a bare write_text that bypassed _copy_skill_file,
so the references/ sidecar and .graphify_version stamp were never written
despite kiro declaring skill_refs: "kiro". This left SKILL.md with 8 dead
references/*.md pointers on every install.

Fix: call _copy_skill_file("kiro", project=True) for the skill+sidecar+stamp,
keep the steering-file block inline. Uninstall now calls _remove_skill_file
which also cleans .graphify_version and references/.

Adds regression test asserting SKILL.md + references/ + .graphify_version +
no references.tmp + steering file, and that uninstall removes all of them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:15:09 +01:00
Safi 6e860e018a docs: clarify .graphifyignore vs .gitignore fallback behaviour (#1137)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:06:02 +01:00
Safi b368c0eb25 revert: remove importorskip now that uv.lock includes tree-sitter-hcl
CI installs --all-extras so all 8 Terraform tests run fully.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:46:25 +01:00
Safi 78e70ea194 chore: update uv.lock with tree-sitter-hcl in all and terraform extras
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:45:34 +01:00
Safi 30f6f6fb85 fix(tests): skip Terraform tests when tree-sitter-hcl not installed
pytest.importorskip at module level matches the pattern used for other
optional extras (sql, dm) so CI passes without the optional dep.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:43:30 +01:00
Safi 200edecea5 feat(extract): add Terraform/HCL AST extraction via tree-sitter-hcl (#1129)
Adds extract_terraform() for .tf/.tfvars/.hcl files. Nodes: resources,
data sources, modules, variables, outputs, providers, locals. Edges:
contains, references (interpolation), depends_on. Node IDs are
directory-scoped for cross-file resolution. tree-sitter-hcl added as
optional extra (graphify[terraform]) matching sql/dm precedent.
8 tests including .tfvars documented no-op behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:38:56 +01:00
Safi fff1c980ac fix: correct language grammar count to 27 tree-sitter grammars in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 13:15:20 +01:00
Safi 75c4de7759 honour GRAPHIFY_API_TIMEOUT in claude-cli and Anthropic SDK backends (#1112)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 10:45:01 +01:00
William Mcgrann 830f0396d8 build: add version floors to networkx, datasketch, rapidfuzz
Adds lower-bound version constraints matching tested versions in uv.lock. networkx>=3.4 is the binding constraint (edges= kwarg on node_link_data introduced in 3.4). rapidfuzz>=3.0 guards against the 2.x→3.x API break in rapidfuzz.distance. datasketch>=1.6 is conservative but correct. Also fixes stale uv.lock version metadata (0.8.30→0.8.31).
2026-06-05 10:14:46 +01:00
Safi 863f0c1e9f update README: manifest.json is now portable, safe to commit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 23:08:55 +01:00
Safi 7a588fb1d2 release 0.8.31 v0.8.31 2026-06-03 21:04:01 +01:00
Safi b7a9b8158c document query logging and hook interpreter pinning in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 21:04:01 +01:00
Safi 3a90ac2784 add query logging to ~/.cache/graphify-queries.log (#1128)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 21:04:01 +01:00