Commit Graph
785 Commits
Author SHA1 Message Date
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
nucleusjay 39afb2d8ef Wire bandit and pip-audit into CI
bandit, pip-audit, and safety are already declared in the dev dependency
group but nothing in CI invokes them, so a new HIGH-severity finding or
a newly-disclosed CVE in a pinned dep can land without anyone noticing
until the next manual audit.

Add a security-scan job that runs bandit (-ll, HIGH-severity only) and
pip-audit (--strict) on every push and PR. Marked continue-on-error so
this doesn't block PRs on pre-existing findings -- a follow-up should
do the cleanup pass and flip the flag.

safety intentionally omitted: it requires a free-tier API key for the
new commercial backend, which is a setup burden for forks. pip-audit
covers the same ground using the PyPI JSON advisory feed and OSV.
2026-06-09 03:36:44 -04:00
nucleusjay 524289fb66 Fix two latent bugs: merge-chunks output and manifest data loss
1. graphify merge-chunks dumped the entire node list to the terminal
   instead of the node count. __main__.py concatenated merged['nodes']
   (a list of dicts) into an f-string where it clearly meant
   len(merged['nodes']) -- the other two values in the same line use
   len() correctly.

2. global_graph._load_manifest silently returned a fresh empty manifest
   on any JSON parse error. That is reachable through normal interrupted
   writes (the manifest is rewritten in full on every global_add /
   global_remove, with no fsync or atomic rename), and the failure mode
   is total data loss: every tracked repo disappears from
   ~/.graphify/global-manifest.json on the next read.

   Back the corrupt file up to <path>.corrupt.<unix_ts> and print to
   stderr before returning the empty default. Users can then recover
   manually and the failure is visible rather than silent.
2026-06-09 03:36:19 -04:00
nucleusjay 6f6d74d42d Pin tree-sitter dependency version ranges
All 27 tree-sitter-* deps were unversioned in pyproject.toml. Users
installing via 'pip install graphifyy' (the README's primary install
path) bypass uv.lock entirely and resolve whatever tree-sitter-*
versions PyPI happens to serve. A breaking minor bump in any grammar
package can land in user installs without notice.

Add explicit lower bounds (matching uv.lock) and upper bounds one
minor above (or one major above for 0.x packages with frequent breaks).
Ranges chosen to allow patch updates without re-pinning while blocking
incompatible major/minor jumps.
2026-06-09 03:35:45 -04:00
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
EirikWolfandEirikWolf 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
Gal Shubeli 418604f32a refactor: rename neo4j_* push vars to push_* (shared by neo4j + falkordb)
The --push/--user/--password export flags feed both the neo4j and falkordb
dispatch branches, so the neo4j_ prefix was misleading - a neo4j_password that
reads FALKORDB_PASSWORD made no sense. Renamed to push_uri/push_user/
push_password, and the password env lookup now reads the backend-specific var
(FALKORDB_PASSWORD for falkordb, NEO4J_PASSWORD otherwise) instead of OR-ing both.
2026-06-08 13:05:24 +03:00
Gal Shubeli 12615226e4 fix: correct FalkorDB cypher.txt import guidance
The no-push 'graphify export falkordb' path advertised
'redis-cli -x GRAPH.QUERY graphify < cypher.txt', but FalkorDB rejects that
with 'query with more than one statement is not supported' - cypher.txt is a
multi-statement Neo4j script. The individual statements ARE valid OpenCypher
(verified by loading them one at a time), only bulk script import is unsupported.

Message + skill docs now say so and point to --push (the verified load path).
2026-06-08 12:59:26 +03:00
Gal Shubeli bf0ace1759 feat: add --falkordb/--falkordb-push skill shorthands, use falkordb:// URI
Makes the FalkorDB option a first-class sibling of Neo4j in the agent skill,
not just the export CLI:

- --falkordb / --falkordb-push shorthands documented in core.md + the shared
  exports.md reference, so they render into all modular platform skills and
  read exactly like --neo4j / --neo4j-push. (The aider/devin monoliths are
  diff-frozen vs v8 by skillgen's roundtrip guard, so they are left untouched.)
- README command reference switched to the /graphify ./raw --falkordb-push form.
- Documented URI scheme is now falkordb://localhost:6379; the scheme is only
  informational (host/port are parsed out), so redis:// or a bare host:port
  remain equivalent. Regenerated skill artifacts + expected/ snapshots.
2026-06-08 12:56:20 +03:00
Rasmus Bækgaardandbakgaard 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
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
SafiandClaude Sonnet 4.6 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
Gal Shubeli 7aa300709f feat: add FalkorDB export backend (#1175)
Adds FalkorDB as a sibling option to the existing Neo4j sink, selected via
`graphify export falkordb [--push redis://localhost:6379]`.

- New push_to_falkordb() in graphify/export.py mirrors push_to_neo4j; FalkorDB
  is OpenCypher-compatible so the MERGE/SET upsert queries are identical.
- export falkordb subcommand wired in graphify/__main__.py (cypher.txt when no
  --push, direct push otherwise). Auth is optional; target graph defaults to
  "graphify".
- falkordb optional extra in pyproject.toml (and in the all extra).
- Tests: CLI cypher generation (CI-safe) + real-FalkorDB integration tests that
  skip when no instance is reachable.
- README extras table + command reference and CHANGELOG updated.
2026-06-07 15:03:49 +03:00
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
Leon Aburime 3e8afc9192 docs: detail proposed node summary contents 2026-06-06 20:36:30 -07:00
Leon Aburime 1ad47ec05e docs: add RFC for file-level node summaries 2026-06-06 20:33:35 -07:00
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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
SafiandClaude Sonnet 4.6 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