- chinese extra: pin jieba-py from 3.12 (was 3.14); jieba's invalid escapes are
a hard error on 3.12+ and broke graphify.serve import.
- serve.py: suppress the tokenizer SyntaxWarning by category so -W error can't
escalate it; catch SyntaxError as a fallback.
- hooks.py: harden the #3492 rebuild-root guard for 3.13, whose resolve() no
longer raises on a symlink loop — require a real directory.
Verified full suite green on both 3.10 (5628) and 3.13 (5627).
The #3490 lock predated its own setuptools>=83 / pypdf / yt-dlp floor bumps, so
a frozen sync resolved setuptools 82.0.1 and the no-isolation wheel-build test
failed. Regenerate the lock so it honors the floors. Also update the windows
skill test: the troubleshooting item is now 'Skip Leiden' (graspologic ->
graspologic-native gating), which #3490 changed in the fragment but not the test.
Ships two batches: the robot/defang/watch/semantic-guard set — Robot Framework extractor
(#3192), generalized control-token defang (#3183), watch unresolved-link preservation
(#3190), unverified-semantic-loss guard (#3203), hook-guard search detection (#3121),
stale-SKILL.md backup (#3144), report/wiki count fixes (#3148/#3127); and a rescued batch of
@Synvoya cross-language inheritance-edge corrections (JS #1790, PHP #1791, Scala #1792/#1794,
Kotlin #1793, C# #1817, Go #1818) that had been buried in the backlog for ~7 weeks.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships three batches: the leiden-direct perf win (#3104) and git-workflow docs; TS new_expression
constructor calls (#3116), elixir when-guard-only clauses (#3111), commonlisp path-qualified
ids, and the FalkorDB wrong-service test skip; and the correctness set — shrink guard armed on
hollow/unparseable/omitting chunks (#3105), --force --code-only full rescan (#3125), carried
hyperedge survivor remap (#3102), atexit stat-index no-resurrect (#2974), and Leiden
edge-endpoint determinism.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships two batches: the detect ignore-perf rewrite (#2226) with the globstar cycle fix and
bounded pattern cache; C#/TypeScript enum-member nodes (#3063/#3064); watch read-only
inotify filtering; the postgres tree-sitter-sql extra; Ruby suffixed-method-id preservation
(#3077) and qualified-receiver matching (#3078); HOF-wrapped CommonJS export capture
(#3035); per-input community-id offset in merge-graphs (#3014); and the Windows PowerShell
BOM fix across all .graphify_root readers (#3028).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships this cycle: the LLM-resilience batch — hollow-response same-chunk retry (#2880),
reasoning-first JSON recovery (#2882), deliberately-declined data JSON not counted as
failed (#2879); extractor fixes — C++ nested types + C++/CLI (#2876), markdown vault-wide
wikilinks (#2875); export fixes — control-char no longer aborts export (#2897), graph.html
restored for large graphs (#2853); and the --no-dedup opt-out (#2881).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tree-sitter-commonlisp-backed extractor for packages, classes, functions,
methods, generics, macros, variable definers, and same-file calls. Handles the
grammar's dedicated defun node (defun/defmacro/defmethod/defgeneric via
defun_header) and the generic list_lit + leading-symbol forms (defvar/defclass/
defpackage), recurses into wrapper macros (eval-when/progn) and reader
conditionals, and maps CL operator chars (= < > ? ! + *) to readable id
suffixes. Wired into detect/extract dispatch, the extractor registry, a
[commonlisp] optional extra, and the README; ships a fixture and a 23-test suite
behind an importorskip guard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships: id-less hyperedge load tolerance (#2775), per-platform version stamp
completing #2694, Go case-only symbol collision (#2779), and .graphify_root
anchor validation (#2603).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cuts a 0.9.43 section (OCaml extractor + #2652/#2653/#2596/#2597/#2655) and
dates the released 0.9.42.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New graphify/extractors/ocaml.py handles both the implementation grammar
(language_ocaml, .ml) and the interface grammar (language_ocaml_interface,
.mli). Emits nodes for modules, top-level/module-level values and functions,
types and their variant constructors; edges for defines/contains, open ->
imports_from, and application -> calls. Qualified paths (Geo.area) resolve to
the final value name, not the module qualifier; local let ... in bindings do
not mint nodes or steal call attribution. Cross-file open/call targets are
sourceless stubs so the corpus rewire collapses them onto the unique real
definition (no #1402 sourced-stub leak).
Wired into detect.py (CODE_EXTENSIONS), extract.py (dispatch +
_EXTRA_FOR_EXTENSION), pyproject.toml ([ocaml] extra + all + dev dep), and
README. Adds tests/test_ocaml.py (behind importorskip).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mcp 2.0.0 dropped mcp.types.AnyUrl and the Server decorator-registration
API graphify/serve.py relies on, so an unpinned resolve broke graphify-mcp
on every fresh graphifyy[mcp]/[all] install. Cap mcp>=1,<2 (resolves 1.29.0)
and starlette>=1.3.1,<2 in both extras; re-lock. Bump to 0.9.30. Porting to
the mcp 2.x API is a tracked follow-up.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The .graphifyinclude loader and its two matcher helpers had no consumers:
commit df40e4d (#873, index dot dirs) removed the blanket dot-prefix
exclusion and with it the only call sites, leaving detect() parsing the
file on every run and then discarding the result. A .graphifyinclude was
silently a no-op.
Delete _load_graphifyinclude, _is_included, _could_contain_included_path
and the orphaned assignment; add .graphifyinclude to _SKIP_FILES so a
leftover file no longer lands in unclassified; and print a one-time
stderr note when one is present at the scan root, pointing to ! negation
patterns in .graphifyignore. Bump to 0.9.25.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
extract_pascal() already imports tree-sitter-pascal for AST-quality
extraction and falls back to a regex extractor when it is absent (#781),
but the grammar was not declared anywhere in the package metadata, so it
was never installed and the AST path never ran out of the box.
Declare a `pascal` extra (and add it to `all`) so users can opt into the
AST extractor with `uv tool install "graphifyy[pascal]"`. tree-sitter-pascal
publishes prebuilt wheels for every platform (win/macOS/Linux), so unlike
the `dm` extra it needs no C toolchain.
On a mid-size Delphi codebase the AST path yields notably more accurate
relationship edges than the regex fallback (calls and inherits both up
~25%). README extras table and uv.lock updated accordingly.
Cross-file member-call resolution for C++/ObjC (#1547/#1556) and
namespace-aware C# type resolution (#1562), the work-memory overlay
(#1441), test-mock call-graph fix (#1553), hyperedge member-key aliases
(#1561), plus the TS/JS/ObjC resolution fixes (#1316/#1544/#1552/#1475).
See CHANGELOG.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ruby type-aware member-call resolution and workspace exports-map
resolution, the #1529 alias/workspace import-edge regression fix, tsconfig
paths fallbacks, semantic-cache pruning, three ObjC extractor fixes, Swift
static-call confidence, the secondary LLM timeout, GraphML null coercion,
host-generic install wording, and Dependabot dep bumps. See CHANGELOG.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`safety` was declared in the dev group but never invoked — the CI
security-scan job only runs bandit and pip-audit, and pip-audit already
provides the same dependency-CVE scanning. Its only practical effect was
pulling in nltk, which carries an unpatched HIGH path-traversal advisory
(GHSA-p4gq-832x-fm9v) with no fix available.
Removing safety drops nltk (and safety-schemas/typer/tenacity/tomlkit)
from the lockfile entirely, closing the alert with no loss of coverage.
Updated the stale CI comment that referenced safety. Full suite green
(2537 passed); pip-audit and bandit unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve two Dependabot alerts in transitive deps:
- msgpack 1.1.2 -> 1.2.1 (HIGH, GHSA-6v7p-g79w-8964): out-of-bounds
read / crash on Unpacker reuse after a caught error. Pulled only via
cachecontrol -> pip-audit (dev group), so not in the published wheel's
closure, but a fix is available so we take it.
- pydantic-settings 2.14.1 -> 2.14.2 (MEDIUM, GHSA-4xgf-cpjx-pc3j):
NestedSecretsSettingsSource follows symlinks outside secrets_dir.
Pulled via mcp (the [mcp]/[all] extra); graphify does not use the
affected secrets-dir source, but the fix is free.
Lockfile-only; both are transitive. Full suite green (2537 passed),
MCP/serve tests pass on the bumped versions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Generated install/skill guidance told agents to invoke a literal `skill`
tool with `skill: "graphify"`, which is host-specific and not valid in
every environment. The always-on AGENTS fragment, packaged artifact,
expected snapshot, and _skill_registration() output now use host-generic
wording: "use the installed graphify skill or instructions". Also decodes
skillgen git blob reads as UTF-8 for Windows and replaces stale English
code-block examples in the translated READMEs.
The always-on roundtrip guard deliberately freezes the v8 baseline, so an
intentional wording change would otherwise fail it. Rather than only
patching the pytest mirror (which left the blocking CLI guard
--always-on-roundtrip red, as the original PR did), this adds an explicit,
reviewable ALWAYS_ON_SANCTIONED_EDITS registry: the guard applies the
approved old->new substitution to the baseline before the byte-for-byte
compare, so this exact sentence is allowed while any other drift still
fails. CLI guard and pytest test now agree and CI passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0.8.48 added graphify/extractors/ (the per-language split, #1212) but
[tool.setuptools] packages listed only "graphify", so the subpackage was
omitted from the wheel and `graphify extract` raised ModuleNotFoundError on a
fresh install. Editable/dev installs and the test suite import from the source
tree, so it passed CI and local smoke but broke the published package. Add
graphify.extractors to packages; verified the rebuilt wheel imports and extracts
in a clean venv. 0.8.48 is yanked.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>