Commit Graph
2240 Commits
Author SHA1 Message Date
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
safishamsiandClaude Opus 4.8 01d23d06a7 docs(readme): cost-led Graphify Cloud headline (80% fewer tokens)
Lead the top banner with the token-saving hook, add an '80% fewer tokens'
bullet to the Graphify Cloud section, and fold the figure into the mid-page tip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 14:34:39 +01:00
safishamsiandClaude Opus 4.8 565b22bca1 docs(readme): trim to the newcomer path and strengthen the Graphify Cloud CTA
- Move the heavy reference sections (full command reference, troubleshooting,
  env vars, team setup, querying, supported inputs, ignoring files, report) to
  short stubs that link to docs.graphify.com, and add a Documentation index near
  the top. README drops from ~939 to ~480 lines; nothing is lost, only relocated.
- Condense the install caveats and the per-platform "always use the graph" table
  into pointers.
- Replace the Smithery MCP badge with a Graphify Cloud (app.graphify.com) badge.
- Strengthen the app.graphify.com CTA: free 14-day trial, and surface the Cloud
  capabilities (monorepo and cross-repo, formal verification, code review with a
  bird's-eye SDLC view, Sentry/Jira connectors) in the top note, a mid-page tip,
  and the renamed Graphify Cloud section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 14:30:48 +01:00
safishamsiandClaude Opus 4.8 e56e77a125 docs(readme): use GitHub callouts and add a Building on graphify note
- Promote the platform note and the official-package warning to GitHub
  [!NOTE] / [!IMPORTANT] callouts so they render as admonitions.
- Add a short 'Building on graphify' section asking community projects that
  use the graphify name to clarify they are unaffiliated (brand protection).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 14:18:12 +01:00
safishamsiandClaude Opus 4.8 2dbb80c44b docs(readme): reduce header logo size (480 -> 360, 25% smaller)
Applied to the English README and all 31 translated READMEs for consistency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 14:16:07 +01:00
safishamsiandClaude Opus 4.8 44560046be ci: add contributor label and PR-title standards automation
Adopt two lightweight OSS governance practices (metadata-only, never runs PR
code):

- contributor-label: tag a PR whose author_association is CONTRIBUTOR, so
  returning community contributions are visible at a glance. Works with our
  authorship-preserving cherry-pick flow (the author shows as CONTRIBUTOR once a
  prior commit of theirs has landed).
- pr-standards: a non-blocking nudge toward conventional-commit PR titles (the
  format the changelog and release notes are built from) via a one-time comment
  plus a `needs:title` label that clears when the title is fixed.

Both exempt maintainers listed in the new .github/TEAM_MEMBERS and all bots.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 14:06:14 +01:00
safishamsiandClaude Opus 4.8 2cb81c6fd5 docs(changelog): fold #4039/#4261/#4269/#4247/#4262 into 0.9.84
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v0.9.84
2026-10-10 01:34:41 +01:00
safishamsiandClaude Opus 4.8 2ca713fc86 test(python): lock in cross-module type-reference binding (#4262)
#4262 reported that a type defined exactly once never bound across modules,
leaving hundreds of per-file stubs. It no longer reproduces on v8: the
reference binds through the re-export chain (and, absent any import, through the
unique-stub rewire). Add regression coverage matching the reporter's node
layout (config/settings/_models.py -> config_settings_models_settings) plus an
import-free inheritance control, so the resolved behavior cannot silently
regress. No production change required.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:33:40 +01:00
safishamsiandClaude Opus 4.8 77276583e0 fix(csharp): coalesce an undeclared type onto one shared placeholder (#4247)
An external type the corpus references but never declares (`List<T>`,
`System.Type`, Unity's `VisualElement`) got a separate sourceless placeholder
in every file that mentioned it, with the file's name baked into the id
(`a_cs_list`, `b_cs_list`). Queries returned a dozen identical nodes and the
files sharing the type stayed unconnected.

`_resolve_csharp_type_references` minted/kept a per-file stub because the arbiter
short-circuited on whichever placeholder each edge already pointed at. It now
routes every undeclared same-name reference to a single canonical, name-keyed
stub (mirroring Go's external-type treatment), still shadowing no real or
differently-labelled node. The now-unreferenced per-file placeholders are pruned
by the existing sweep.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:31:15 +01:00
safishamsiandClaude Opus 4.8 162159dbd6 fix(python): stop a qualified external annotation binding to a private local class (#4269)
`def read_body(response: httpx.Response)` names an external type, but a private
`class _Response` in a test file absorbed the reference, producing a fabricated
EXTRACTED-confidence edge from production code to test code.

The stub-rewire key (`_node_label_key`) stripped ALL non-alphanumeric
characters, including underscores, so `_Response` and `Response` collapsed to
the same key and the lone local `_Response` was chosen as the unique match.
Underscores are significant identifier characters, so the key now preserves
them (only `()`, `<>`, `.`, and whitespace are dropped); `Foo()` still matches
`Foo`, but `_Response` no longer matches `Response`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:28:39 +01:00
safishamsiandClaude Opus 4.8 289aa41284 fix(python): stop a stdlib-named loose module from capturing a bare import (#4261)
A non-package directory with a file named like a stdlib module (e.g.
`scripts/logging.py`) wrongly captured a bare `import logging` from a
sibling, binding the import — and member calls like `logging.getLogger()` —
to the local file instead of the stdlib module.

The false binding arose at three independent layers, all now guarded by a
vendored, deterministic `_PYTHON_STDLIB_MODULE_NAMES` frozenset (union of
3.10 and 3.13 `sys.stdlib_module_names`, NOT the host's live set):

- `_resolve_python_module_path`: an absolute import whose top-level name is
  a stdlib module no longer resolves to a loose same-named `.py` file or
  namespace dir. A deliberate package shadow (`logging/__init__.py`) still
  resolves — only loose modules/namespaces are refused.
- `_repoint_python_sibling_imports`: stdlib-named loose siblings are no
  longer indexed as repoint targets.
- build.py #1504 pre-migration stem-alias index: a stdlib-named Python file
  no longer claims the collapsed bare-stem alias ("logging"), which would
  otherwise re-capture the external edge. The directory-scoped alias
  ("scripts_logging") is still registered, so genuine stale-id references to
  the file keep healing.

Adds a stdlib-shadow regression plus a non-stdlib positive control.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:24:41 +01:00
berce 652020e9db fix(opencode): load the plugin on OpenCode 2 and refresh installed copies (#3554, #3732)
`graphify opencode install` wrote a plugin with only a named export, the
OpenCode 1 shape. OpenCode 2 rejects it ("Plugin must export a default
definition with an id and an effect or setup function") and reads the bare
path registered in opencode.json as an npm package name, so it fails twice
on every start.

The plugin is now one default export with `id`, `setup()` for OpenCode 2
and `server()` for OpenCode 1 (1.3.4 and later). The installer no longer
writes the opencode.json entry, because both runtimes discover
.opencode/plugins/ on their own, and it removes the entry older releases
wrote.

OpenCode loads .opencode/plugins/ from the project and from every directory
above it, and OpenCode 2 fails a second plugin with the same id ("Duplicate
plugin ID"). An install in ~ and one in a project are both normal, so the id
carries the file's location and the copies share one record of who was
reminded: both load, and a command still gets a single reminder.

Upgrading graphify does not touch a plugin already on disk. So the CLI now
rewrites an old-shape plugin in the working directory or in the home
directory on its next run, and drops the stale entry there, next to the
stale-skill refresh from #1805. It does so only when the `opencode` on PATH
reports 1.3.4 or later, because older OpenCode 1 releases cannot load the
new plugin and the one they have still works. The rewrite takes the same
per-directory lock as the skill refresh and replaces both files atomically,
because OpenCode watches them. GRAPHIFY_NO_AUTO_REFRESH=1 turns it off.

(cherry picked from commit 0e539e1f7a)
2026-10-10 01:13:46 +01:00
safishamsiandClaude Opus 4.8 effee34d33 release: 0.9.84
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:01:40 +01:00
safishamsiandClaude Opus 4.8 e72af53c37 fix(path): fail closed on a file::symbol endpoint the file does not define (#4264)
A file-scoped path endpoint that matched no symbol in that file fell through to
bag-of-words scoring, which then answered from a same-named symbol in another
file. Refuse like explain does (listing the files that do define the symbol)
instead of guessing across files; fixes the CLI path and the MCP shortest_path
tool via the shared resolver. Native Rust/C++ :: labels resolve via the exact
tier and are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:01:10 +01:00
safishamsiandClaude Opus 4.8 90d9245c6b fix(r): give every backtick-quoted binding a collision-free id (#4253)
A partially-symbolic backtick name (`%foo%`, S3 `[.cls`, dotted `my.op`)
normalized to the same _make_id suffix as an ordinary identifier, so the second
node was silently dropped by the seen_ids merge. Route every backtick-quoted
name through the reserved __operator__<hex> namespace, not only empty-suffix
operators; #4171's existing ids are unchanged. (The #4253 hang itself was
already fixed by #4171's resolve_local visited guard.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:01:10 +01:00
safishamsiandClaude Opus 4.8 da287edfb5 fix(powershell): extract functions inside file-scope begin/process/end blocks (#4270)
File-scope begin/process/end/dynamicparam/clean parse as pseudo-commands
(command_name 'begin'), not named_block, so the command branch returned before
the child walk and any function/class defined inside was dropped. Descend into
those five block keywords' children; ids stay name-based and stable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-10 01:01:10 +01:00
safishamsiandClaude Opus 4.8 cf5978e4fb release: 0.9.83 — include #4235, #4239
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v0.9.83
2026-10-09 19:48:34 +01:00
himanshupatro-334 8f029d28b7 fix(csharp): resolve nested types from using static
(cherry picked from commit b66040d902)
2026-10-09 19:48:13 +01:00
nothariharan 0778755e81 fix(cache): namespace AST cache by tree-sitter grammar versions (#4236)
(cherry picked from commit 90fadbd5e1)
2026-10-09 19:46:57 +01:00
safishamsiandClaude Opus 4.8 89db93508b release: 0.9.83
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-09 19:20:04 +01:00
YyunozorandClaude Opus 4.8 089939197f fix(extract): bind an unqualified call to the caller's own class in Java/C#/Scala/C++ (#4252)
An unqualified call fell through to a file-wide last-writer-wins label map, so
it bound to the last-declared same-named method. Walk the caller's class chain
(own class + in-file bases nearest-first, then enclosing classes) and bind a
single hit; fail-closed on a tie; free functions/constructors still resolve.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-09 19:19:15 +01:00
Mahaboob pashaandClaude Opus 4.8 0b94e3767f fix(csharp): resolve calls through member chains, element access and constructors (#4258, #4246)
Resolve a.b.C(), xs[i].M(), and calls inside constructor bodies: a fail-closed
chain/element-type resolver (one declared type per hop, collection element only
for T[]/List<T>, bail on ambiguity) plus a ctor-body walk attributing calls to
the type node. Reuses the existing C# scoping; avoids same-pair method/calls
duplicates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-09 19:19:15 +01:00
ayushcodes10andClaude Opus 4.8 230bbd2d92 fix(csharp): never let a call bind to a same-named enum member (#4254)
Exclude case_of targets from the per-file label map and apply the cross-file
_member_nids exclusion to all C# calls (not only new X()), so a bare call like
Delegate(t) no longer binds to a same-named enum case. Methods are method/
contains targets, not defines, so real call targets survive; fail-closed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-09 19:19:01 +01:00
ayushcodes10andClaude Opus 4.8 41b2a7f6f9 fix(csharp): give a generic and a non-generic type distinct ids (#4255, #4249)
Fold the type-parameter arity into the C# type node id (Effect`1), so Effect
and Effect<T> no longer collapse to one node and Effect<T> : Effect stops
producing an inherits self-loop. Arity 0 keeps the current id (back-compat);
backtick is collision-free and deterministic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-09 19:18:16 +01:00
SoloDrex52andClaude Opus 4.8 f949947003 fix: make the test suite pass on Windows (#4260)
Refuse a read-only destination in _atomic_replace on Windows (nt-only guard;
os.replace there raises PermissionError and the fallback would silently clobber
it), plus test-only guards: utf-8 encoding kwargs, posix-shape path assertions,
FIFO/AF_UNIX/symlink skips, and a replace-retry for AV/indexer locks. No POSIX
behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-09 19:18:06 +01:00
Deepanshu Pal 68e0e9bbac fix(skill): preserve persisted scan options across skill runs
Read existing CLI build-config options in fresh and incremental skill
scan fragments, keeping corpus boundaries consistent without changing
standalone detection API defaults. Regenerate all host artifacts and
snapshots. Add rendered-snippet regressions and explicit-override tests.

Fixes #4240.
AI-Assisted-By: AI coding assistant

(cherry picked from commit 3f68952d80)
2026-10-09 19:17:53 +01:00