Commit Graph
2265 Commits
Author SHA1 Message Date
shazeb d611afbee9 fix(skill): stop --update from printing the whole corpus
The incremental step dumped every file path into the agent context even
though later steps read the sidecar from disk. Print a short summary
and leave the full result in .graphify_incremental.json.

(cherry picked from commit d23d1c618a)
2026-10-12 13:01:00 +01:00
Mahaboob pasha 07f3d0fc3c fix(csharp): type a var from the called method's return type (#4266)
Co-Authored-By: Grok Bot <noreply@x.ai>
(cherry picked from commit 816dcf5927)
2026-10-12 13:01:00 +01:00
devkancheti4-design d3f8687c00 fix(query): order the per-term guaranteed seeds by match strength (#4357)
_pick_seeds appended the per-term guaranteed seeds (#1445) in sorted(best_seed_by_term), alphabetical term order,
and the renderer prints seeds first, so a weak match on an early-alphabet term led a specific term's exact match.
_score_query now returns term_order: the per-term winners by their existing key (-singleton score, which carries
the term's IDF weight, then -degree, label length, node id), the term breaking ties. _query_graph_text passes it to
_pick_seeds. The same seeds are picked and the order is deterministic; without term_order the sorted order is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 7bcbc60ac1)
2026-10-12 13:01:00 +01:00
safishamsiandClaude Opus 4.8 c8d769f95c test(dedup): stamp _origin on the shrink-guard fixture (post-#3110)
#3110 makes the semantic tier carry _origin:"semantic" explicitly, so a real
graph.json's semantic nodes are no longer tier-guessed from the L-shape of
source_location. This fixture wrote a baseline graph with no _origin, which
backfilled to AST and mixed with the re-extracted (now semantic) nodes, so the
pair no longer merged and the shrink guard had nothing to catch. Stamp the
fixture nodes semantic to reflect what real post-#3110 graphs contain; the guard
correctly fires again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-12 12:29:39 +01:00
abhay-codes07andClaude Opus 4.8 4fff67d219 fix(skill): stamp _origin on the semantic tier so update cannot delete it (#2843)
build._is_ast_tier reads _origin when present and otherwise guesses the tier
from the shape of source_location (L<line> means AST). extract() stamps its AST
items _origin:"ast", but nothing stamped the semantic side, so a semantic node
whose location happened to look like "L12" read as AST — and the next
`graphify update` deleted it along with the re-extracted code file it seemed to
belong to. Part C, extract_corpus_parallel, and the CLI merge now setdefault
_origin:"semantic" on every semantic node/edge before the merge, so a semantic
item is never mistaken for an AST one. AST items (stamped "ast") are untouched;
setdefault preserves any existing stamp.

Landed from PR #3110. Skill artifacts regenerated fresh from the updated
fragments (not the PR's stale committed blobs); all five skillgen validators
pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-12 12:18:15 +01:00
9c66fd30dc feat(config): declare languages for ambiguous extensions via .graphifyrc (#2961)
An ambiguous extension (`.inc`, `.h`, TS-family, ...) is hard-mapped to one
global default; when that is wrong the file does not error — it parses as the
wrong language and yields a few incidental nodes, so the graph looks populated
while the real symbols are missing. A project can now declare what an extension
means via `language.<ext>=<language|.ext>` lines in `.graphifyrc` (which already
holds `viz_node_limit`). The declaration flows through file classification,
extractor selection, grammar/resolution, imports, watch, and the AST cache
(salt + manifest language field + incremental invalidation), is thread-local
per scan root, and is forwarded to the worker pool. Default detection is
byte-for-byte unchanged when no declaration is present.

Landed from PR #3789 (squashed), which carried @abhay-codes07's original #3075
forward with reviewed follow-ups. Authorship credited to both contributors.

Co-Authored-By: Andre Brait <andrebrait@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-12 12:16:17 +01:00
41418864aa fix(hook): bound the soft read/search nudge per session (#3435)
The read/search nudge was re-injected on every qualifying Read/Glob/Grep/Bash
call with no dedup or session cap (issue #3435 measured ~8,348 injections,
~651k tokens, for 339 graphify calls), and an agent that just ran
`graphify query` was still nudged on its very next read. `_nudge_allowed`
now gates all three soft-nudge sites with a per-session + per-agent counter
(first nudge always fires; later ones suppressed while the query stamp is
fresh; hard cap via GRAPHIFY_HOOK_NUDGE_CAP, default 5), with 24h GC and
fail-open preserved. Subagents get independent budgets. The strict deny path
is unchanged.

Landed from PR #3443 (squashed). The README strict-mode note is omitted here
because that prose moved to docs.graphify.com in the README trim.

Co-Authored-By: Andre Brait <andrebrait@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-12 12:15:19 +01:00
safishamsiandClaude Opus 4.8 a5ba60ddf6 release: 0.9.86
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v0.9.86
2026-10-11 21:17:07 +01:00
Andre Brait ceff3e215d fix: write graph.json as one line of compact JSON (#3413)
graph.json was pretty-printed (indent=2), so every PR that commits a
rebuilt graph reports tens of thousands of changed lines. GitHub's PR
line counts ignore .gitattributes (-diff, binary), so only the file's
content can fix it: one line of compact JSON is +1 -1.

Every writer of a project graph.json now emits separators=(",", ":")
with no indent: to_json, the `update` raw/no-cluster candidate text,
prune, merge-driver, merge-graphs, `extract --no-cluster` and the global
graph. Readers are unaffected.

`update` compares parsed data, not bytes, so an existing indented graph
would have been "unchanged" forever. It is now rewritten compact once,
then left alone.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 4c31235c37)
2026-10-11 21:07:15 +01:00
Krish Garg c68d167ee4 fix(rust): expand grouped use declarations into import bindings
Give each binding of a use tree the import edge that v8 produces for
its equivalent plain use declaration. Preserve aliases, path comments,
separator whitespace, nested prefixes and self/glob binding behavior.

Keep the old group edge as call evidence until the call pass finishes;
exclude per-binding edges from that pass, then remove private markers.
Plain imports and all call edges retain their current-v8 behavior.
AST cache schema 6 -> 7 rejects results written before expansion.

Replace the earlier broad resolver in #4135 with this syntax-only fix.
The resolver is preserved on local branch wip/rust-use-resolver.

On current v8, all 30 new tests and the full 6642-test suite pass.
Fresh ripgrep builds have 864 import edges instead of 247, with every
call unchanged. Existing name-based import rewiring can still produce
wrong matches, just as it does for equivalent plain declarations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex <noreply@openai.com>
(cherry picked from commit 2669ee4f11)
2026-10-11 21:07:09 +01:00
oleksii-tumanov 5d92f1ec08 feat: support a sampling seed for built-in Ollama requests
AI-Assistance: OpenAI Codex
(cherry picked from commit 4907979e77)
2026-10-11 21:06:27 +01:00
Tivonsico 4e98b51c5c docs: distinguish local CLI guidance from MCP instructions
Co-Authored-By: OpenAI Codex <noreply@openai.com>
(cherry picked from commit cac64a0c22)
2026-10-11 21:06:10 +01:00
Andre Brait 51bd59731a docs(always-on): say large graph.json diffs in pull requests are expected
A committed graphify-out/graph.json is rewritten whole on every build, so
its pull-request diffs are large by design. Assistants reviewing such PRs
flagged them as churn and proposed skipping the rebuild or its hooks. The
Claude, AGENTS.md and Gemini blocks now say the diff is expected.

(cherry picked from commit e6cf17c171)
2026-10-11 21:06:10 +01:00
Vibhanshu Mishra 7a8dfff3db fix(codex): preserve semantic chunks through B3 merge
Persist validated Codex extraction responses as chunk files so the shared B3 merge preserves semantic nodes and edges.

Fail before cache and graph updates when extraction responses are missing or invalid.

Add regression coverage for chunk merging, cached reruns, and failure handling.

Fixes #4311

Co-authored-by: OpenAI Codex <codex@openai.com>
(cherry picked from commit da5850f0ac)
2026-10-11 21:06:10 +01:00
Mahaboob pasha bcf9624477 feat(scala): link classes to typeclasses in derives clauses (#2048)
`case class Point(x: Int) derives Show, Eq` (and the same on enums) now
emits a `references` edge with the `derives` context from the type to each
derived typeclass, next to the class-level context bounds it resembles. A
qualified name (`derives cats.Show`) links by its last segment.

Co-Authored-By: Grok Bot <noreply@x.ai>
(cherry picked from commit e6ccd59f20)
2026-10-11 21:06:10 +01:00
raditha dissanayake 1adadc7f79 fix(global): preserve stored edge direction in global add (#4066)
global add loaded graph.json with a plain undirected node_link_graph, so
every link whose target precedes its source in the node list was written
to ~/.graphify/global-graph.json reversed. Stamp _src/_tgt with
restore_arc_direction before the load, as the export loader and
load_node_link_graph do since #4088.

The external-node dedup rewired edge endpoints but not the markers, so a
deduplicated repo's markers named a node that no longer exists. Remap
_src/_tgt along with the endpoints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 477848390e)
2026-10-11 21:06:09 +01:00
Allionix 25452a63b8 fix(explain,query): say how to get the full answer when output is cut
explain listed the 20 most connected neighbors and "... and N more" with
no option to see the rest, and the token-budget notices of query,
get_neighbors and get_community said "raise the token budget" without
the value that would return everything, so a caller retried with a guess.

explain gets --all, and its cut line names the total and the option.
The budget notices now give the smallest budget that returns the whole
output, computed with the same rule that does the cut.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 769184dc9a)
2026-10-11 20:49:48 +01:00
Allionix ddc24c76d8 fix(cli): give lookups distinct exit codes for ambiguous and missing names
explain and query exited 0 when no node matched, the same status as an
answer, and path exited 1 for an ambiguous endpoint, a missing one and a
missing graph file alike. A script or an agent could not tell a refusal
from an answer without parsing the text.

explain, path and query now exit 3 when a name is ambiguous (the
candidates are listed) and 4 when no node matches. Messages and output
streams are unchanged; "no path found" between two existing nodes is
still an answer. The codes are documented in --help and the README.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 13dc2400e1)
2026-10-11 20:49:42 +01:00
Allionix 7c4bf5671b fix(explain): refuse a name that several nodes of one file carry (#4320)
Landed from PR #4320 (squashed, authorship preserved).
2026-10-11 20:49:37 +01:00
Deepjyoti-Sarmah f5300d5490 test(dedup): pin edge rename when built from a subdirectory of the root (#4281)
Run from a subdirectory of the scan root, a root-relative node path is resolved
against the CWD, so the renamed node's key stops matching its edges' and the
edges stay on the survivor. Fails on v8; fixed in the next commit.

Co-authored-by: Gijs Mos <1526544+gmos@users.noreply.github.com>
(cherry picked from commit f3697420c4)

# Conflicts:
#	tests/test_dedup.py
2026-10-11 20:49:25 +01:00
Deepjyoti-Sarmah f905db770d fix(dedup): rank a relative source_file against the scan root, not the CWD (#4281)
Nodes are root-relative by dedup time, but _rank_path resolved them, which
prepends the CWD. From root/firmware, a node keyed as
firmware/firmware/lib/portal.html and its edge as firmware/lib/portal.html,
so the edge never followed the renamed node.

Resolve only absolute paths. _source_key is unchanged: at extraction time
relative paths are CWD-relative.

Co-authored-by: Gijs Mos <1526544+gmos@users.noreply.github.com>
(cherry picked from commit 22f87c266a)
2026-10-11 20:48:53 +01:00
rohit-jsfreaky 22bc4c6ab4 fix(affected): walk callers of the supertype member an overriding method overrides (#4330)
Landed from PR #4331 (squashed, authorship preserved).
2026-10-11 20:47:55 +01:00
smngvlkz ff88388aaa fix(detect): respect git's global ignore file (core.excludesFile) (#4335)
Landed from PR #4339 (squashed, authorship preserved).
2026-10-11 20:47:55 +01:00
SurajPanda 2417f05f2d fix(dedup): keep combining marks in label normalization
_norm built the dedup key with re.sub(r"[\W_]+", " ", ...). \w does not
match Unicode combining marks (Mn/Mc: vowel signs, viramas), so they were
deleted like punctuation: "हिंदी" became "ह द", and "कि", "की", "के" all
collapsed to "क", merging three distinct nodes in Pass 1.

Treat a character as part of a word when it is alphanumeric or a combining
mark; everything else still collapses to a single space. Output is
unchanged for strings without combining marks (checked against the old
implementation on ~190k random strings).

Known gaps: ZWJ/ZWNJ still act as separators; ids.normalize_id and the
dormant build.deduplicate_by_label keep the old recipe.

(cherry picked from commit ccd81ce818)
2026-10-11 20:47:44 +01:00
ayarodionov e1892efd29 fix(julia): extract return-typed, qualified, operator and functor methods; broadcast/pipe calls
- Unwrap `::RetType` (alongside `where`) around a definition's call head, so
  `function f(x)::Float64` is no longer dropped.
- Name method definitions via `_def_name`: `Base.show`, `Base.:+`, bare
  operators, and functors `(c::Circle)(x)`. The id uses the bare name so all
  methods of a generic function share one node; the label keeps the qualifier.
- Emit `calls` edges for broadcast calls (`f.(xs)`) and pipes (`x |> f`, `.|>`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit cf3648e762)
2026-10-11 20:47:44 +01:00
Raphael Malikian 1b21e04aed fix(llm): coerce null token counts to 0 across backends
Some OpenAI-compatible gateways return a usage object whose token-count
fields are null. Reading them verbatim left None in result["input_tokens"] /
result["output_tokens"], which crashed extraction for the whole chunk
(TypeError: '<' not supported between 'NoneType' and 'int' in the ollama
low-token warning; None also propagated through the per-chunk merge).

Coerce null counts to 0 at read time in _call_openai_compat, _call_azure,
_call_claude, and _call_bedrock, matching the existing `or 0` idiom already
used on the claude-cli path.

Fixes #4325

Signed-off-by: Raphael Malikian <rtmalikian@gmail.com>
(cherry picked from commit 640005fdb7)
2026-10-11 20:47:44 +01:00
Hassan Zidan 97a938f990 fix(install): never let uninstall --purge delete the project when GRAPHIFY_OUT is empty or "."
A set-but-empty GRAPHIFY_OUT (a blank .env / docker-compose / CI entry)
or GRAPHIFY_OUT=. made the purge target <project>/"" == the project
itself, and rmtree deleted the whole project.

- paths: treat a blank GRAPHIFY_OUT as unset; "." / ".." fall back to
  graphify-out with a warning. GRAPHIFY_OUT_NAME and out_path() follow.
- install: before any uninstaller runs, refuse --purge (exit 1, nothing
  changed) when the target is the project, a parent of it, the home
  folder or a filesystem root. This also covers an absolute GRAPHIFY_OUT.
- hooks: the rebuild bodies resolve the output dir via graphify.paths
  instead of reading the env var directly.

Fixes #4328

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 7d6befbb9c)
2026-10-11 20:47:44 +01:00
safishamsiandClaude Opus 4.8 b4e6307bf1 docs(changelog): correct 0.9.85 PR count (nine -> fourteen)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v0.9.85
2026-10-10 22:27:37 +01:00
safishamsiandClaude Opus 4.8 842ca78374 docs(changelog): add #4290/#4169/#4178/#4301/#4302 and credit #4142 to 0.9.85
Also fix the #4288 reference in the affected-defines test docstring.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 22:13:39 +01:00
Bastien NOËL d184e5d28e fix(extract): don't crash resolution on a huge export default literal (#4166)
Landed from PR #4169 (squashed, authorship preserved).
2026-10-10 22:11:03 +01:00
Pini Vaknin 74d784f943 perf(resolution): walk each JS/TS tree once when collecting symbol facts
_collect_js_symbol_resolution_facts walked every parsed tree in full four
times, and each pass kept only a few node types.

The first pass now walks once and keeps the nodes of the six types the
whole-tree passes filter on, in walk order. Later passes iterate that
list. Each fact list is filled by a single pass, so fact order does not
change.

_walk_js_tree now uses a TreeCursor instead of reading .children at every
node. A cursor is bounded by its start node, so the walks that start
inside a tree (function bodies, and the import and export nodes passed to
_js_named_specifiers) stay inside that subtree.

Overlaps #3353, which also indexes JS nodes once and frees each tree
after use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 243deb39e7)
2026-10-10 22:11:03 +01:00
Pini Vaknin 16378b4846 perf(resolution): skip os.getcwd() in the path-memo key for absolute paths
_source_key and _resolve_cached key their lru_cache on the path and the
cwd, and call os.getcwd() on every lookup, hit or miss. On a 900-file
repo an extract makes about 215k of those calls. os.getcwd() is a
syscall that costs 30 to 40us on macOS, so building the key cost more
than the resolution the memo saved.

An absolute path resolves the same from any cwd, so it now keys with an
empty cwd. A relative path still keys on the cwd, so a chdir still misses
the cache. Path.is_absolute() applies host rules, which is what local
resolution needs: a driveless path on Windows depends on the drive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 2228f80804)
2026-10-10 22:11:03 +01:00
Dan Caldr 289e870962 fix(affected): add defines to DEFAULT_AFFECTED_RELATIONS
Dart/Flutter (and Python, Go, and other file-module languages) extract a
class or function as a symbol node with a defines edge from its source
file. Without defines in DEFAULT_AFFECTED_RELATIONS the reverse walk
stops at depth 0 because the only incoming edge is invisible.

Measured on a real Flutter project (12 104 nodes, 12 420 edges):
- 4 793 symbols defined via defines edges
- 4 691 of them (97.9 %) had zero incoming edges from any whitelisted
  relation — affected returned 'No affected nodes found' for each one
- After adding defines: 100 % of symbols reachable through at minimum
  their defining file

Tests: 10 new regression tests in test_affected_defines.py.
All pass post-fix, all fail pre-fix.

(cherry picked from commit c695fdf8eb)
2026-10-10 22:11:03 +01:00
rajatnagda45 b28c2c5368 fix(fortran): extract named generic interfaces as callable nodes
A named generic interface (`interface area; module procedure area_circle,
area_square; end interface`) names a callable that dispatches to its
specific procedures by argument type. The interface block was never turned
into a node, so a call to the generic name dangled — a Fortran function
call_expression only resolves to an in-file node — and the dispatch set
was invisible, even though the specific procedures were extracted. Generic
interfaces (and operator overload sets) are routine in scientific Fortran.

Emit a node for the generic name, link it to the procedures it groups with
`dispatches_to` edges (resolved after the walk, like type-bound
procedures, so a procedure from another module becomes a collapsible
sourceless stub), and the existing call resolution then binds `area(x)`
to it. Unnamed abstract/explicit interfaces keep recursing so their
procedure declarations are still extracted.

(cherry picked from commit ccfb4018fb)
2026-10-10 22:10:52 +01:00
safishamsiandClaude Opus 4.8 a009ce7131 revert(fortran): drop re-implementation of #4141 in favor of PR #4142
My #4141 fix used a one-off calls/generic_dispatch relation; PR #4142
(@rajatnagda45) implements the same fix with the codebase-standard
dispatches_to relation and earns author-preserving credit. Reverting the
Fortran hunk here so #4142 can be cherry-picked; the Julia fixes from the
same original commit are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 22:10:34 +01:00
safishamsiandClaude Opus 4.8 3f8260fcc3 release: 0.9.85
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 21:53:48 +01:00
Alin1233 033b678e6d fix(extract): bind Rust stubs past impl blocks to the single declaration (#4283)
Landed from PR #4284 (squashed, authorship preserved).
2026-10-10 21:39:00 +01:00
ayushcodes10 9dafae2acc fix(extract): parse TS 5 export type star re-exports (#3942)
Landed from PR #4303 (squashed, authorship preserved).
2026-10-10 21:38:54 +01:00
rbtech-hap fb6e7c7888 fix(dedup): keep distinct files that mint the same node id (#4281)
Landed from PR #4282 (squashed, authorship preserved). Covers the extension-drop
collision (x.py vs x.html); the path-dropped doc-id case in #4281 remains open.
2026-10-10 21:38:45 +01:00
Yyunozor 4b8be21cad fix(detect): match unanchored ignore patterns against the entry name only (#4242)
Landed from PR #4251 (squashed, authorship preserved). The PR's README note on
re-inclusion semantics is omitted here since the README's Ignoring files section
now links to docs.graphify.com/reference/configuration.
2026-10-10 21:38:38 +01:00
ayushcodes10 e4667c10c5 fix(watch): close the rebuild lock unlink-vs-flock race (#4273)
Landed from PR #4277 (squashed, authorship preserved).
2026-10-10 21:37:47 +01:00
smngvlkz 7ddda57784 fix(hooks): pick up changed files with non-ASCII names (#4278)
Landed from PR #4279 (squashed, authorship preserved).
2026-10-10 21:37:47 +01:00
ayushcodes10 1088605003 fix(extract): explain a semantic omission that was not a truncation (#4101)
Landed from PR #4280 (squashed, authorship preserved).
2026-10-10 21:37:39 +01:00
Eóin Forker 8a8977cac6 skill: tell the user graphify-out/ is in their working tree (#3941)
Step 9's report never mentioned that graphify-out/ was written into the
working tree, so a repository that does not ignore it was left with
untracked machine-local files in git status and no explanation. The report
now adds one sentence in a git repository, with the two ways to handle it.

The note goes in the three core fragments (core, aider, devin); the devin
monolith change is sanctioned by a new round-trip predicate.

(cherry picked from commit b4e6769371)
2026-10-10 21:37:07 +01:00
Raphael Malikian bd20e4c31a fix(hook-guard): fire the Read nudge for PowerShell source files
hook-guard read returned early for .ps1/.psm1/.psd1 targets because the
extension gate (_HOOK_SOURCE_EXTS in graphify/cli.py) did not list them,
even though detect.py classifies those extensions as code and they are
extracted into the graph. In a PowerShell repo the Read/Glob nudge never
fired, only the search one.

Fixes Graphify-Labs/graphify#4271.

Signed-off-by: Raphael Malikian <rtmalikian@gmail.com>
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 1ee08e70ba)
2026-10-10 21:37:04 +01:00
safishamsiandClaude Opus 4.8 aa4564378a fix(scala): scope given...with members to the given instance (#4130)
A Scala 3 `given ... with` instance's `def`s leaked to file scope, where `show`
(cased to `_show`) collided with the trait TYPE node `Show`, so the given's
call/reference edges landed on the trait. Treat `given_definition` as a
class-like container with a `with_template_body`, and synthesize a stable name
for an anonymous given (`given Show[Int] with`) from its implemented type so its
members are scoped instead of dropped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 21:20:29 +01:00
safishamsiandClaude Opus 4.8 177d2071e5 fix(html): stop a node label from breaking out of the embedded script block (#4124)
Node data is embedded as JSON inside a <script> element, but the serializers
escaped only `</`. An unclosed `<!--` in one label followed by a later `<script`
drove the HTML tokenizer into script-data-double-escaped state, where the real
</script> no longer closed the tag and graph.html rendered blank. Escape every
`<` as < in both exporters/html.py and tree_html.py; labels still render
because `<` round-trips through JSON.parse.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 21:20:29 +01:00
safishamsiandClaude Opus 4.8 93de0d4aea fix(elixir): extract defdelegate as a function definition (#4132)
`defdelegate name(args), to: Mod` declares an invocable function with the same
`call` head shape as `def`, but was missing from the def-family recognizer, so no
node was minted and same-module calls to the delegated name dangled. Add
`defdelegate` to the def-family tuple and to the call-pass skip set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 21:20:29 +01:00
safishamsiandClaude Opus 4.8 a041facc84 fix(julia,fortran): extract where-clause funcs, parametric types, and named generic interfaces (#4126, #4128, #4141)
- Julia: a `where` clause wraps the call head in a `where_expression` and a
  parametric type name sits inside a `parametrized_type_expression`, so the
  name-lookup helpers missed both and dropped the method/type entirely. Unwrap
  the wrapper nodes in `_func_name_from_signature`, the short-function assignment
  branch, and `_type_head_names`. Declared type parameters (`value::T`) no longer
  leak as phantom field-type reference nodes (#4126, #4128).
- Fortran: a named generic `interface` had no walk branch, so the generic name
  was dropped and a call to it dangled. Emit a node for the generic name and
  defer-resolve a `generic_dispatch` edge to each listed specific procedure,
  mirroring the type-bound-procedure pattern; unnamed/operator interfaces are
  untouched and their bodies still extracted (#4141).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 21:20:29 +01:00
safishamsiandClaude Opus 4.8 1d1e03b4c8 docs(readme): regenerate all 31 translations from the trimmed English README
Each translation is rebuilt from the current English README (trim + docs.graphify.com
links + Graphify Cloud CTA). Prose is translated into the native script while code,
commands, URLs, relative link targets, badges, the language switcher, GitHub callout
markers, numbers/metrics, and structure are preserved verbatim. Relative links are
adjusted for the docs/translations/ location, and the Install heading is kept in
English so the in-page #install anchor resolves in every language.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 14:57:14 +01:00