37 Commits

Author SHA1 Message Date
Safi 23f598f3a0 fix MultiGraph crash, hollow LLM response retry, and skill --help (#796, #795, #792)
#796: add edge_data()/edge_datas() helpers in build.py that tolerate
MultiGraph/MultiDiGraph; replace all G.edges[u,v] 2-tuple call sites in
__main__.py, serve.py, wiki.py, export.py, analyze.py, benchmark.py;
fix same pattern in 10 skill file inline heredocs

#795: all 12 skill files now short-circuit on /graphify --help or -h
and print the Usage block without running any pipeline steps

#792 (hollow response): add _response_is_hollow() predicate in llm.py;
when Ollama (or any backend) returns empty/null/whitespace content or a
parsed result with no nodes/edges, rewrite finish_reason="length" so
_extract_with_adaptive_retry bisects the chunk instead of silently
dropping it; applied to _call_openai_compat, _call_claude, _call_bedrock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 21:17:25 +01:00
Safi 0656ec62a4 security hardening: F-002/F-005/F-007/F-008/F-009/F-010/F-016/F-031/F-035/F-038/PR747-NEW-2 2026-05-07 16:32:26 +01:00
Safi b1ea93586b add .qmd to to_obsidian_canvas safe_name regex 2026-05-07 11:03:42 +01:00
shym 1026695da7 feat: add .qmd file extension support
Adds support for Quarto markdown (.qmd) files by:
- Adding '.qmd' to document file extensions in detection
- Updating export logic to handle .qmd in filename sanitization
- Adding .qmd extractor dispatch using the existing markdown extractor
- Updating watch comments to include .qmd files
2026-05-07 11:13:14 +09:00
Safi b6ffdbb8dd v0.7.2: Fortran support + export CLI subcommands + skill.md size reduction
- Add Fortran support (26th language): .f/.F/.f90/.F90/.f95/.F95/.f03/.F03/.f08/.F08
  via tree-sitter-fortran; capital-F files preprocessed with cpp -w -P
- Add graphify export {html,obsidian,wiki,svg,graphml,neo4j} CLI subcommands
- Add graphify query/path/explain CLI subcommands
- Reduce skill.md from 63KB to 47KB by replacing Python heredocs with CLI calls
- Extend to_html() with node_limit param for auto-aggregation on large graphs
- Add integration tests for all export/query/path/explain subcommands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 11:17:06 +01:00
Safi 36e894aa62 v0.6.6: Windows skill bash rewrite, wiki fixes, rationale-node fix, hidden allowlist, --no-viz cluster-only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 14:25:26 +01:00
Hanzala Sohrab 8e01d686f7 feat: replace show/hide buttons with checkbox-based multi-select controls (#647) 2026-05-02 13:49:45 +01:00
Safi 4563b043f2 Fix 6 bugs: ID collisions, path portability, alias resolution, HTML controls, desync guard, rationale prompt
- #550: _file_stem() includes parent dir to prevent node ID collisions for same-named files
- #555: extract() relativizes source_file paths before returning for cross-machine portability
- #562: to_json() returns bool; _rebuild_code() writes report/html only if json succeeded
- #563: skill prompts store rationale as node attribute, not separate node; enforce calls direction
- #566: Show All / Hide All buttons added to HTML community panel
- #575: _import_js() resolves tsconfig.json compilerOptions.paths aliases before external fallback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 21:44:22 +01:00
Safi 6175e0a8ea fix #547 #559 #570: expand ~ in hooksPath, fix gitignore inline comments, nosec on write sinks 2026-04-27 21:27:26 +01:00
Safi df9b7ec54f fix #479 #451: build_merge(), pre-write shrink guard, label dedup, chunk-suffix prompt block 2026-04-23 20:04:43 +01:00
Safi 64f38acf3e implement #488 #482 #472 #490: legacy schema canonicalization, Java inheritance, aggregated HTML viz, check-update subcommand 2026-04-22 23:28:09 +01:00
Safi 4bc20527c3 fix #513 #514: skip head -1 on .exe hook binary, fix to_canvas() hardcoded obsidian path 2026-04-22 23:01:53 +01:00
Safi 81b6e7d7b4 fix #455 #448 IsADirectoryError in file_hash and save_semantic_cache, fix #454 sanitize_label crash on None source_file 2026-04-21 21:25:13 +01:00
Safi b85184002c v0.4.13: Verilog support, HiDPI hyperedge fix, null label guards, AGENTS.md python3 fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 09:28:01 +01:00
Safi 1fbcaf840f release: v0.4.9 — PHP extractor improvements, Dart, diacritics, Hermes, fixes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 08:39:28 +01:00
Safi 8c17230586 cherry-pick PRs #212, #220, #204, #221 into 0.4.2
- build/validate: accept NetworkX <=3.1 "links" key alongside "edges" (#212)
- __main__: skip version check during install/uninstall, deduplicate paths (#220)
- all file IO: explicit encoding="utf-8" to prevent crashes on Windows CJK locales (#204)
- hooks: add newline="\n" on write to prevent CRLF shebang breakage on Windows (#204)
- export: strip trailing .md from safe_name so "CLAUDE.md" doesn't become "CLAUDE.md.md" (#221)
- report: add Community Hubs navigation block so Obsidian vault stays connected (#221)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 21:07:39 +01:00
Safi 1cb882a156 fix bugs #211, #216, #217, #222 and bump to 0.4.2
- extract.py: use str(path) for node IDs to prevent same-basename collision (#211)
- build.py: normalize from/to edge keys before KeyError (#216)
- export.py: guard ZeroDivisionError when graph has no edges (#217)
- hooks.py: remove stale CODE_EXTS filter, rebuild on any changed file (#222)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 20:53:08 +01:00
Safi 74cb9ce197 Security: fix YAML injection in ingest.py, </script> injection in export.py, bound collision loop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 16:07:51 +01:00
Safi e3adc0417a fix hook reinstall, CRLF labels, skill-windows missing commands (0.3.28) 2026-04-10 10:07:11 +01:00
Safi df77d5f8ce Add Cursor support, fix _rebuild_code KeyError and node_link_data crash (#137, #148, #149)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 17:19:40 +01:00
Safi bb2049cec1 Fix XSS in HTML viz: escape node labels, types, source files, and edge relations in innerHTML (#sec)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 09:06:02 +01:00
Safi c3817d6144 Apply PRs #82 #93 #102 #109: extension drift, click detection, skill coverage, .graphify_python persistence
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 08:22:01 +01:00
Safi 2b3accfe66 fix: XSS in legend innerHTML and shebang allowlist in hooks 2026-04-08 19:53:10 +01:00
Safi ffd8906c6c fix: ensure Cypher node label always starts with a letter (#84) 2026-04-08 19:02:05 +01:00
Safi 92b70ce5f4 fix: sanitize_label double-encoding and --wiki missing from skill (#66, #55) 2026-04-08 09:40:21 +01:00
Safi c529e2217f Fix 8 bugs: SSRF in tweet fetch, Cypher injection, XSS in community labels, graph_diff edge ordering, cache key collision, hook uninstall correctness, watch mode set, rebuild word count 2026-04-06 22:23:55 +01:00
Safi 148e247662 Fix 6 bugs: hook exit code, token budget, file node detection, duplicate function, atomic cache writes, deleted file tracking 2026-04-06 22:23:55 +01:00
Safi 404674a24a security: SSRF private IP blocking and Neo4j Cypher injection fix
Two targeted security hardening changes:

1. SSRF: validate_url() now resolves hostnames and blocks private/reserved
   IP ranges (127.x, 10.x, 169.254.x, etc.) and cloud metadata endpoints.
   Prevents SSRF attacks in cloud environments where a URL like
   http://169.254.169.254/latest/meta-data/ could leak instance credentials.

2. Neo4j Cypher injection: Node labels (file_type) are now sanitized to
   alphanumeric + underscore before interpolation into Cypher queries.
   Previously, attacker-controlled file_type metadata could inject
   arbitrary Cypher in team/shared graph scenarios.

Both changes are zero-impact on normal UX - no new config, no new flags,
no behavioral changes for legitimate use.
2026-04-06 21:59:38 +01:00
Safi 3a117c93e8 v2: hypergraph support - hyperedges in graph.json, shaded regions in HTML, report section 2026-04-06 16:06:31 +01:00
Safi dafe6c9f03 v2: confidence scores on INFERRED edges, avg shown in report 2026-04-06 16:06:31 +01:00
Safi d8b1e82079 fix: 5 skill gaps - graphml usage, manifest timing, graph existence checks, no-viz clarity
- Add --graphml to Usage table (was implemented but undocumented there)
- Remove early manifest save from --update merge step (Step 9 owns it; saving early meant failed pipelines left manifest ahead of graph)
- query/path/explain now check graph.json exists before running, with clear "run /graphify first" message
- --no-viz: clarify it skips both Obsidian vault and HTML (was contradictory)
2026-04-06 16:06:31 +01:00
Safi d4b24d8609 feat: vis.js HTML graph, token reduction benchmark, repo cleanup
- Replace pyvis with custom vis.js renderer: node size by degree,
  click-to-inspect panel with clickable neighbors, search box,
  community filter, physics clustering by community
- HTML graph generated by default on every run (no --html flag needed)
- Token reduction benchmark auto-runs after every /graphify on corpora >5k words
- Fix 292 edge warnings: silently skip stdlib/external edges in build.py
- Fix build() to merge extractions before building (cross-extraction edges were dropped)
- Add 5 HTML renderer tests (223 total)
- Remove unnecessary files: lib/, tests/eval_attention.py, misplaced eval reports
- Add graphify-out/ and .graphify_*.json to .gitignore
- Bump version to 0.1.4, remove pyvis dependency
- README: token reduction as top-level selling point, vis.js in tech stack,
  graph.html in output listing, correct test count and install command
2026-04-06 16:06:31 +01:00
Safi 5db8f7ce39 docs: update surprising connections description, test count
style: replace all em dashes with hyphens

fix: explain hidden .graphify/ folder in skill output and README

fix: rename .graphify/ to graphify-out/ so output is visible by default
2026-04-06 16:06:31 +01:00
Safi 7e82212304 feat: GraphML export (--graphml flag) for Gephi and yEd 2026-04-06 16:06:31 +01:00
Safi 41e4e3576a security: SSRF protection, HTML escaping, path guards, encoding hardening
- graphify/security.py (new): centralised security module
    - validate_url(): blocks file://, ftp://, data:, any non-http/https scheme
    - _NoFileRedirectHandler: re-validates redirect targets, blocks file:// redirects
    - safe_fetch(): streams response, 50MB hard cap, non-2xx raises, timeout
    - safe_fetch_text(): safe_fetch + UTF-8 decode with errors=replace
    - validate_graph_path(): resolves path, requires inside .graphify/, base must exist
    - sanitize_label(): strip control chars, cap 256, html.escape() — mirrors
      code-review-graph's _sanitize_name pattern
- graphify/ingest.py: _fetch_html() and _download_binary() now use safe_fetch*;
  ingest() validates URL scheme and wraps network calls in try/except;
  YAML frontmatter: newlines stripped from question before embedding
- graphify/extract.py: all 33 bare .decode() → .decode("utf-8", errors="replace")
  — non-UTF-8 source files degrade gracefully instead of crashing extraction
- graphify/export.py: sanitize_label() on all node labels and edge titles
  before pyvis embeds them in HTML output
- graphify/serve.py: _load_graph() validates graph_path via validate_graph_path()
  and wraps JSONDecodeError with recovery message; sanitize_label() on MCP
  text output
- graphify/detect.py: os.walk(..., followlinks=False) made explicit
- SECURITY.md (new): threat model, mitigations table, reporting process
- tests/test_security.py (new): 20 tests covering all security.py functions
2026-04-04 18:56:38 +01:00
Safi e7a03a0539 feat: cache, multi-language extraction, MCP, memory feedback
call-graph INFERRED edges, multi-language semantic extraction, SHA256 cache,
MCP stdio server with shortest_path, Q&A memory feedback loop
2026-04-04 18:56:38 +01:00
Safi ce47198be1 feat: Claude Code skill, Obsidian vault, install, tests
skill.md with full pipeline steps, Obsidian as default output (canvas, tags,
dataview, graph colors), two-command install, 71 tests, .gitignore, deps
2026-04-04 18:53:43 +01:00