Commit Graph
1788 Commits
Author SHA1 Message Date
oleksii-tumanov 7e857e020b fix: guard Ruby namespace rebinding
(cherry picked from commit 1a7262e2a8)
2026-09-15 18:03:49 +01:00
oleksii-tumanov 436a735f7f fix: guard Ruby constant rebindings
(cherry picked from commit 5f28f2bb3e)
2026-09-15 18:03:49 +01:00
oleksii-tumanov ff75ca1029 fix: reject ambiguous Ruby constant mutations
(cherry picked from commit 891ebfae53)
2026-09-15 18:03:49 +01:00
oleksii-tumanov dd0b95d18a fix: harden Ruby inherited lookup proof
(cherry picked from commit 43f56f8633)
2026-09-15 18:03:12 +01:00
oleksii-tumanov bf28196db9 fix: promote inherited Ruby call confidence
(cherry picked from commit aec5c32000)
2026-09-15 18:03:12 +01:00
vstepko 161e5f2ef5 feat(terraform): resolve local module sources and directory topology
(cherry picked from commit e00593d10e)
2026-09-15 18:01:35 +01:00
Ryan Peterson c805c6fb9d feat(markdown): resolve code-span mentions into references edges
The markdown extractor's docstring promised a heading --references--> node edge
when a backtick Name matches a known pattern, but nothing implemented it, so an
AST build produced no document-to-code edge at all.

extract_markdown now collects inline code spans outside fences and frontmatter as
raw_calls tagged language "markdown", owned by the heading they sit under (the
page before the first heading). A new markdown_mentions language resolver runs
after the id-remap passes and turns them into references edges: the explicit
path::Symbol[::member] form resolves through the cited file's symbols and is
EXTRACTED 1.0; a bare or dotted name resolves only when exactly one callable code
node carries that label and is INFERRED 0.95. Ambiguous names, builtins, missing
files and non-callable matches emit nothing. The shared cross-file call pass
skips markdown raw_calls so prose never emits calls edges.

Tests cover span classification, raw_call ownership, end-to-end resolution,
ambiguity, and cache round-tripping.

(cherry picked from commit 2d833a0a3c)
2026-09-15 18:01:28 +01:00
safishamsi d4b704fa05 test(cluster): add the self-loop cohesion_score regressions #3558 described
#3558's fix landed but its diff omitted the 3 tests its description claimed;
add them (self-loop ignored, self-loops-only is 0, 0..1 bound holds). Also drop
a changelog line the #3559 cherry-pick injected into the released 0.9.61 section.
2026-09-14 18:55:31 +01:00
ayushcodes10 9b1db672fb Add regression test for dangling edge pruning consistency
group_skipped feeds the dangling reference pruning pass and the write
loop must agree with it on whether a recovered group is written or
skipped. This proves an edge between two nodes inside the same
recovered group survives instead of being pruned as referencing a
supposedly skipped id.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 8a23b305fe)
2026-09-14 18:52:06 +01:00
ayushcodes10 6694f65465 Add regression test for unscoped callers with no allowlist
Confirms recovery never runs when allowed_source_files is omitted: a
genuinely bogus path is skipped exactly as before this fix, and a
normal well formed path in the same batch still saves and loads back.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 12999a80f6)
2026-09-14 18:52:06 +01:00
ayushcodes10 cf8ac5d035 Add regression test for an ambiguous basename staying skipped
Two allowed files sharing a basename must not let recovery guess
between them: an unresolvable source_file with an ambiguous basename
still falls through to the previous skip behavior unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit f59acf7c36)
2026-09-14 18:52:06 +01:00
ayushcodes10 a442031291 Correct recovered groups own source_file before writing them
A recovered group's write KEY pointed at the right file, but every
node, edge, and hyperedge inside it still carried the original
unresolvable source_file string. load_cached rejects an entry on read
if any item's source_file does not match the path it was loaded
under, so the previous commit alone wrote a group that reported as
saved but could never actually be read back, silently reproducing the
exact loss this fix exists for.

This corrects every item's source_file to the recovered path's
portable form before the group is written, only when recovery
actually redirected the key, so an unrecovered group stays byte
identical to before.

Includes the regression test proving the full round trip: a group
recovered by basename now survives a subsequent load_cached call.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 4b91dcd462)
2026-09-14 18:52:06 +01:00
ayushcodes10 796a3595a4 Recover malformed semantic cache paths by basename
Fixes issue #2973.

group_skipped and the save_semantic_cache write loop now call
_recover_group_path instead of resolving fpath directly, so a group
whose reported source_file never resolves to a real file gets one more
chance: an unambiguous basename match against the already dispatched
allowlist. An ambiguous or genuinely bogus basename still falls
through to the previous skip behavior unchanged, and unscoped callers
(no allowed_source_files) are byte identical to before since recovery
only runs when an allowlist is available.

This stops an incremental run from silently redoing already processed
chunks every time the adaptive retry split path reports a source_file
that a weak or local backend lost track of.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 73f5a66370)
2026-09-14 18:52:06 +01:00
ayushcodes10 6cf7b98d64 Add basename recovery helper for semantic cache groups
save_semantic_cache groups nodes and edges by source_file, then skips
any group whose path does not resolve to a real file. A weak or local
backend's adaptive retry split path sometimes reports a source_file
for a group that never resolves at all, silently dropping that
group's nodes and edges from the cache on every incremental run.

This adds a helper that recovers such a group by an unambiguous
basename match against the known good, already dispatched allowlist,
with no behavior change yet since nothing calls it. The write loop is
switched over in the next commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 4528666ba6)
2026-09-14 18:52:06 +01:00
ayushcodes10 5d858ad37a Add regression test for the clustered path replace fallback
Same #2689 fallback requirement as the no_cluster test, exercised
against the default clustered rebuild path, the second of the two
watch.py call sites the issue reports.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 366ec5ef1f)
2026-09-14 18:52:05 +01:00
ayushcodes10 0da4fe68db Add regression test for the no_cluster path replace fallback
Simulates the VMware HGFS PermissionError this issue reports by
monkeypatching os.replace to always raise it, then confirms an
incremental no_cluster rebuild still succeeds and lands the new
content instead of aborting the whole run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 9e75593b02)
2026-09-14 18:52:05 +01:00
ayushcodes10 dd5141df2b Route the rebuild path graph.json replace through the fallback
Fixes issue 2689 for the main rebuild write site, the second of the
two watch.py call sites reported.

Same reasoning as the reconcile path: existing_graph was read a few
lines earlier in this same process for the same_graph comparison, so
a plain Path.replace can hit the VMware HGFS PermissionError this
issue reports. Both call sites in watch.py now route through the
shared os_replace_with_fallback helper that export.py, cache.py, and
install.py already use.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit b01622eb9f)
2026-09-14 18:52:05 +01:00
ayushcodes10 c9d8123b9d Route the reconcile path graph.json replace through the fallback
Fixes issue 2689 for the reconcile existing graph write site.

This site reads existing_graph a few lines earlier in the same
process, then replaced graph_tmp onto it with a plain Path.replace.
On a VMware HGFS shared folder, os.replace over a destination that
was read earlier in the same process raises PermissionError even
though src and dst are on the same drive; deleting then renaming
succeeds in that exact situation. os_replace_with_fallback already
implements that fallback for PermissionError generally, so this
switches the call over to it instead of duplicating the recovery here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 3214e8ee03)
2026-09-14 18:52:05 +01:00
ayushcodes10 a15e7bb4e2 Import the shared atomic replace fallback into watch.py
watch.py writes graph.json via a plain Path.replace() at two call
sites instead of the shared os_replace_with_fallback helper that
export.py, cache.py, and install.py already route through. This adds
the import with no behavior change yet; both call sites are switched
over in the next two commits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit f3694aea49)
2026-09-14 18:52:05 +01:00
breken df9f37612f fix(hooks): resolve the output dir from GRAPHIFY_OUT in the sh gates, not a literal graphify-out/
#1423 moved the Python rebuild bodies onto GRAPHIFY_OUT, but the shell that
runs BEFORE them still hardcoded graphify-out/. With the documented override
(#686, e.g. GRAPHIFY_OUT=custom-out for worktree/shared-output setups):

- post-checkout exited at `[ ! -d "graphify-out" ]`, so a branch switch never
  launched the rebuild - a silent no-op with nothing in the log.
- post-commit's "only graph artifacts changed" filter only recognised
  graphify-out/ paths, so a commit touching only custom-out/graph.json
  launched a full rebuild - the loop the filter exists to prevent.

Both gates now read ${GRAPHIFY_OUT:-graphify-out}, the same source the rebuild
body reads. The commit filter is a POSIX case loop instead of grep so the dir
name is matched literally (no regex metacharacters); the leading ( on each
pattern keeps bash 3.2 (macOS /bin/sh) from mis-parsing the pattern's ) inside
the $(...) substitution.

Regression: tests/test_hooks.py runs the emitted scripts under sh with the
launcher stubbed and asserts whether the hook reaches the launch line.

Claude-Session: https://claude.ai/code/session_0134ujLF81GyXsCByibLcYsz
(cherry picked from commit 9efd052de4)
2026-09-14 18:49:21 +01:00
jordanalexanderp18-rgb 97d523a681 fix(cluster): exclude self-loops from cohesion_score so the ratio stays in 0..1
cohesion_score() counts self-loops in the numerator (number_of_edges) but
not in the denominator (n * (n - 1) / 2, distinct node pairs), so the ratio
its docstring defines over 0..1 can exceed 1.0. Recursive `calls` self-edges
are deliberately preserved by build_from_json, so they reach this code in
ordinary graphs: a two-node community holding one recursive function scored
2.0, and report.py prints the value unclamped.

(cherry picked from commit 5d66b992ac)
2026-09-14 18:49:21 +01:00
ayushcodes10 bf5769585a Update thin community tests for the corrected count
Three existing tests pinned the old, undercounting behavior directly,
including one whose own docstring asserted the exact shape this fix
corrects. Updates all three to the now correct figures and adds a
dedicated test asserting the two invariants the issue itself
suggested, shown equals what actually renders and shown plus thin
equals the total, at both thresholds already exercised in this file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit dd056ab9a8)
2026-09-14 18:49:20 +01:00
ayushcodes10 3d8d4e08ee Count an all file node community as thin, not invisible
Number 3148 fixed shown to be computed directly instead of total
minus thin, since the old formula counted a community with zero real
nodes as shown even though the render loop skips it. That fix left
thin itself under a zero real guard from before it, so a zero real
community was excluded from both figures at once and went uncounted
anywhere the report prints about itself, and shown plus thin no
longer summed to the total community count. Both counting sites drop
that guard so a community the render loop skips for having too few
real nodes, zero included, is now always reflected in the thin
figure next to it. Fixes #3548.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit d616c330e3)
2026-09-14 18:49:20 +01:00
ayushcodes10 c5ad8d6852 Add a regression test for unexported require destructures
Pins the exact interaction the fix commit already describes: a
CommonJS const equals require of a module destructure must still
resolve to exactly one EXTRACTED calls edge, not zero, confirming
the export only gate keeps it out of the per name split entirely.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit e9c10258a7)
2026-09-14 18:49:19 +01:00
ayushcodes10 93820c9c01 Add a test for rest pattern skip in destructured exports
A rest element does not correspond to one discrete exported name, so
it must be skipped rather than mangled into a bogus node, and its
sibling names must still extract cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 7091925a3a)
2026-09-14 18:49:19 +01:00
ayushcodes10 7be28b1ca7 Add a test for renamed property export naming
A renamed destructured property must export under its property key,
never under the local alias it is bound to, since that alias is not
what an importer would ever bind by.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 8fae543236)
2026-09-14 18:49:19 +01:00
ayushcodes10 37b3db9654 Add a test for cross file resolution through a split export
A single name import must resolve to its own split node, and a call
made through it must resolve too, not just the import edge on its
own.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 78a3ca4bf7)
2026-09-14 18:49:19 +01:00
ayushcodes10 025caeaa93 Add a test for the per name destructured export split
Four destructured names on one export statement must each get their
own node, and the old combined pattern syntax label must not survive
anywhere in the output.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 3f62c3d85c)
2026-09-14 18:49:19 +01:00
ayushcodes10 fd9b1cdb40 Emit one node per exported destructured name
export const { auth, handlers, signIn, signOut } = NextAuth(config)
is NextAuth version five's own documented boilerplate, and
createNavigation from next intl follows the exact same shape. The
extractor collapsed the whole pattern into one combined node, id
joining every destructured name and label the literal pattern
syntax, so a single name import elsewhere could never find a node
named just auth and the edge, and any call resolved through it,
dangled. Each shorthand and renamed property in the pattern now
becomes its own node sharing the statement's line, exactly what the
export would have produced had it been written as N separate
statements. A renamed property exports under its key, since that is
what an importer binds by, never its local alias. A rest element or
a default valued entry does not correspond to one discrete exported
name and is skipped rather than guessed at.

The split only applies to an actually exported statement. An
unexported destructure of the identical shape, const doWork equals
require of lib being the common one, is a local import binding, not
a module export, and giving it a bare named node in the importing
file would collide with the real definition it only imports, turning
a clean resolution into a false ambiguous name. Caught this against
the existing suite before it ever reached a commit. Fixes #2604's
class 2.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit b1614da58a)
2026-09-14 18:49:19 +01:00
ayushcodes10 13fef586d3 Add changelog entry for issue 3352
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 68c6eafddb)
2026-09-14 18:49:17 +01:00
ayushcodes10 61316e80b6 Add negative control test for an ordinary ASCII path
Confirms the reconstructed prefix set for an ASCII path is byte for
byte identical to what the old ASCII only regex produced, so the fix
changes behavior only for paths the old code was already getting
wrong.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 97bd1f37f0)
2026-09-14 18:49:17 +01:00
ayushcodes10 0ea296e9ba Add end to end regression test for the issue own repro shape
Runs deduplicate_entities on the defining and referencing Korean
node pair in both arrival orders and asserts the defining file own
node survives either way, matching the concrete case the issue
reports: a page whose filename equals the concept name losing its own
node to a page that merely mentions it in passing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 852c61098f)
2026-09-14 18:49:17 +01:00
ayushcodes10 ff6707a015 Add regression test for defines_id on a non Latin path
Confirms the layer above _id_prefixes actually benefits from the
fix: a node whose id and source_file both encode a Korean path is
recognized as defining that id, and a node sharing that id from a
different file is correctly recognized as merely referencing it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 7d15c1bb26)
2026-09-14 18:49:17 +01:00
ayushcodes10 48380444b1 Add regression test for non Latin segments in id prefixes
Confirms the exact repro shape from the issue: the reconstructed
prefix set for a Korean file path preserves every segment instead of
collapsing them to nothing, matching what the file's own id is
actually minted as.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit ab4bde5413)
2026-09-14 18:49:17 +01:00
ayushcodes10 c46241a751 Use the canonical Unicode aware slugifier for id prefixes
Fixes issue 3352.

_id_prefixes reimplemented id segment slugification with its own
ASCII only regex, so any path segment made of non Latin characters
(Korean, CJK, Cyrillic and so on) collapsed to nothing instead of
being preserved. _defines_id, the only real caller, uses these
prefixes to recognize when a node's own source_file is the file its
id encodes, and _collision_rank already implements the definer wins
rule this issue asks for. With the wrong prefixes, a node minted from
a non ASCII path never matched, so a genuine defining page lost the
definer wins tiebreak and the survivor fell through to plain arrival
order, exactly the symptom this issue reports.

Swapping to normalize_id, the same recipe every real extractor mints
an id with, makes the reconstructed prefixes match the ids that are
actually minted for such a file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit e618f332f6)
2026-09-14 18:49:17 +01:00
ayushcodes10 b5247b5a88 Import the canonical Unicode aware id normalizer into dedup.py
Toward issue 3352: _id_prefixes reimplements id slugification with
its own ASCII only regex instead of the canonical normalize_id every
real extractor uses to mint an id, so it silently drops non Latin
characters. This adds the import with no behavior change yet; the
swap lands in the next commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 237f02d135)
2026-09-14 18:49:17 +01:00
safishamsi e4399cb9ca release: 0.9.62 — sourceless-stub calls, module-level closure calls, C# cross-repo scoping, lua bare require, tokens secret FP, guard-hook timeout 2026-09-13 22:53:43 +01:00
safishamsi 9335cee627 docs(changelog): drop entries the #3529/#3519 cherry-picks injected into released sections
These belong in the next release and will be re-added at the bump with correct
credit (@HARSHAVARDHAN-RAJU5 for #3529) and wording.
2026-09-13 17:49:49 +01:00
A.Levin 9e0ae2cf0b docs(changelog): note the Lua bare-require fix (#3320)
(cherry picked from commit c7c03253e2)
2026-09-13 17:47:57 +01:00
A.Levin 08f5bdf20f fix(lua): emit imports edge for bare require() statements (#3320)
A bare require("mod") with no assignment - the dominant idiom in
Neovim configs - never reached the import handler: only
variable_declaration was in the Lua import dispatch set, so
require(...) used as a standalone statement produced no edge at
all. Detect the require call ahead of the generic import_types
check instead of widening it to function_call, which would have
swallowed every plain call and skipped the walker's recursion into
its arguments (e.g. a require() nested inside a callback passed to
vim.keymap.set).

(cherry picked from commit 2a208bbbb0)
2026-09-13 17:47:57 +01:00
A.Levin 6cebd67d3a test: cover bare require() imports edges for Lua (#3320)
A bare `require("mod")` statement with no assignment produces no imports
edge, while `local x = require("mod")` does. Cover the bare form in the
flattened and lua/config layouts, with and without parentheses, plus
guards for the callback recursion a fix must preserve and for method-style
calls that must not fabricate an edge.

(cherry picked from commit c87586c343)
2026-09-13 17:47:57 +01:00
Dev Chiniwala 46c93444b9 fix(merge): respect C# type visibility across repos
(cherry picked from commit cf6b7f7b68)
2026-09-13 17:47:56 +01:00
ayushcodes10 737db3ac05 Add regression tests for module level anonymous calls
Covers the same file case, the doubly nested repro shape from the
report itself, confirms the number 1740 named enclosing function
case is unaffected, and documents the direct import collision gap
called out in the fix commit as a pin rather than a silent
assumption.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 7983186f2f)
2026-09-13 17:47:55 +01:00
ayushcodes10 75427e5722 Attribute calls in a module level anonymous closure to the file node
Number 1740 fixed calls inside an anonymous callback by attributing
them to the enclosing named function, but that only works when a
named function actually encloses it. it("...", async () => { ... })
has no such enclosing function anywhere, and that shape hits test
files hardest since it is the idiomatic way to write one. The
original report already named the intended fallback, attribute to
the module node when no named function encloses the call, but that
half was never built. A topmost closure argument to a module level
call statement now gets its own function_bodies entry keyed by the
file node, mirroring the existing fix for this.X assignments found
in the exact same statement shape, so the ordinary call walking
machinery, including its own descent into further nested closures,
picks it up from there. Toward #3124.

Known gap left open, described in the new test module's own
docstring: a callee that is both directly imported by the same file
and only called from a module level anonymous closure still does not
resolve, because the cross file resolution pass dedupes purely by
source and target regardless of relation, so the file node's own
import edge to that target pre-empts the calls edge. Fixing that
dedup properly reaches far beyond this one case and is left for a
separate change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 8a0367c505)
2026-09-13 17:47:55 +01:00
Dev Chiniwala 50c9c7d895 fix(extract): skip calls to sourceless stubs
(cherry picked from commit 9f0ad48259)
2026-09-13 17:47:54 +01:00
ayushcodes10 fc33e2ccbd Add regression tests for the guard hook timeouts
One per hook, matching the existing matcher tests, checking the
timeout key is present and stays within a small bounded range rather
than pinning the exact value.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 59535b3e01)
2026-09-13 17:47:54 +01:00
ayushcodes10 575f829f46 Bound the search and read guard hooks with a timeout
An unset command hook defaults to Claude Code's 600 second timeout,
so a single wedged guard, a stuck filesystem or a hung subprocess,
stalls the surrounding tool call for ten minutes on Bash, Grep, Read
and Glob, the four highest frequency tools an agent uses. The guard
itself measures around 170 milliseconds warm, so both generated
entries now carry a 10 second timeout, generous headroom over the
measured cost while still two orders of magnitude below the unset
default. Toward #3314.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit fd08017d22)
2026-09-13 17:47:54 +01:00
HARSHAVARDHAN-RAJU5 3eb2486803 fix: bare plural "tokens" in a prose file is no longer treated as a secret
TOKENS.md / tokens.md read as design-token reference docs, not credential
dumps, unlike singular "token.md" or another keyword's bare plural
("secrets.md"), which still exclude. The .dart/.ts design-token source
files from the original report are already covered by the existing
graphable-source exemption; this closes the remaining prose-note gap.

Fixes #3527

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A6anVY9hgp5ph5qLXRmc2p
(cherry picked from commit 64e85524ef)
2026-09-13 17:47:53 +01:00
safishamsi fe66389083 release: 0.9.61 — fix Python 3.12/3.13 breakage from 0.9.60
- 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).
v0.9.61
2026-09-12 22:23:00 +01:00
safishamsi 7464f5b125 release: 0.9.60 — Windows os.replace fallback, unclassified-file surfacing, C/C++ newline parse, Office sidecar fix, exported-function call resolution, workspace export conditions, Python 3.14 support v0.9.60 2026-09-12 21:54:14 +01:00