When a receiver's type is inferred from its declaration or initializer and
the method isn't on it, the matcher used to fall through to its
capitalized-name and name-overlap guesses. If the inferred name is a type
(capitalized last segment) that nothing in the project declares — JDK /
BCL / okhttp / Django types — it now stops: the method is that outside
type's. Python's initializer pattern no longer reads a keyword argument
(`prefix=IPNetwork(…),` inside a call) as a binding of `prefix`.
A/B (edges removed): commons-lang -1296 (`append` / `length` / `charAt` on
JDK types), Newtonsoft.Json -496 (`MemoryStream.ToArray`, `ToString`),
gson -367 (`List.add`, `Map.put`), retrofit -321 (okhttp `Request.headers()`
/ `method()`), jsoup -130, okio -26, pytest -44 (pathlib / io), netbox -25,
healthchecks -9 (`TimestampSigner.sign`), flask -9, zod -1.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- tree-sitter-kotlin can't read `class Name` / (comments) / `internal
constructor(…) : Super {` on separate lines — the class is dropped and its
members become loose top-level functions (okio's ByteString, Kotlin
Multiplatform's `expect` classes). The Kotlin preParse now blanks that
constructor's modifiers / annotations / keyword to spaces, so `(…) :
Super {` parses as the primary constructor; offsets and lines survive, and
preParse runs before the kernel, so both paths parse the same bytes.
- With members back on their classes, a Kotlin standard-library name on an
untyped chain link (scope functions, collection / string / conversion
methods — not names project types commonly carry) needs a receiver named
after its owner, in the exact / fuzzy filters and the unique-name guess.
A/B (edges removed / added): okio -1028/+1127, okhttp -979/+1145,
kotlinx-datetime -426/+515 (mostly re-keyed onto recovered classes),
koin -60/+4 (`msg.contains(…)` → a dependency map's `contains`).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The extractors keep one receiver level, so chain links arrive as bare names.
Read at the call site:
- bare (no `.` / `::` before it): never a method — Rust reaches one only
through `self.` / `Type::`, Go through a receiver (axum's routing
`get(handler)` went to a cookie jar's `get`, tokio's `drop(x)` to `Drop`
impls, #1861's pinned `reset()` → `Target::reset` is now the free fn);
- chained (after `.`, receiver read back through arguments, macros `name!`,
`::` paths and Go composite literals): never a free function, and a
standard-library method name (Option/Result/iterator/collection/string
methods; Go's String/Error/Header/locks/reflect/time) needs a receiver
named after its owner — project-specific names keep their match (clap's
`flag("n").short('n')` → Arg::short, cobra's `c.Root().Name()`, gin's
`c.Set(…)`).
The same std gate applies to the method-call matcher's unique-name guess.
A/B (edges removed / added): clap -1496/+93, tokio -1064/+235, axum
-695/+42, ripgrep -477/+32, cobra -167, serde -119/+1, bat -40/+4, gin
-32/+26.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
`Name.method()` where `Name` reads as a type in the language's conventions
and nothing in the project (same language family) is called `Name` — JDK /
BCL / DOM / Indy types — now leaves the method-call matcher before the
capitalized-receiver and name-overlap guesses. Not applied in Go (exported
package variables), C / C++ / Rust / CUDA / Metal; in Pascal only Delphi
type prefixes (T/E/I…) and `Exception` count, since parameters and locals
are capitalized there too.
A/B (edges removed): commons-lang -1636 (`Integer.valueOf` → StringUtils
×804, `Calendar.getInstance`, `Instant.now`), horse -89 (`Exception.Create`
→ EHorseException), retrofit -79 (OkHttp `RequestBody.create` / `HttpUrl.get`),
typeorm -74 (`Object.assign` → ObjectUtils), gson -100, zod -63,
Newtonsoft.Json -57, jsoup -18; gin and cobra byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Route tables compose nested paths: a child's `path` is relative to the
path-bearing routes around it (`children` of a data router, nested
`<Route>` elements), absolute ones reset. `lazy: () => import('./x')`
(object and JSX) renders the module's default export (`Component` export
as fallback) via a claimed `lazy-import:` ref. `path: paths.app.root.path`
keeps its parts on the node's signature and is named in postExtract from
the constant's object literal (found through the file's import). The
route keeps its extracted id; `isReactRouterRoute` accepts it. An element
wrapped in parentheses or a guard (`<ProtectedRoute>`, `<Suspense>`,
`*Provider`, `*Guard`) renders the first element inside.
- Import aliases: the tsconfig / jsconfig nearest the importing file that
declares `paths` is tried before the root's, so each monorepo app resolves
its own `@/*` / `~/*`.
A/B (edges removed / added): bulletproof-react -43/+367 (0 → 9 named,
linked routes; cross-app imports fixed), react-native-reusables -103/+193,
kit -184/+218, trpc -45/+71 (examples' `~/…` now their own), create-t3-turbo
-1/+13; excalidraw, halo, obytes, realworld byte-identical. #1348's nested
fixtures now expect composed paths (`/dashboard/settings`, `/data/prefs`).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
`const { getDefaultActivityRoute } = useDefaultActivity(); getDefaultActivityRoute()`
bound the name locally, which ruled out every cross-file candidate, so the
call resolved to nothing. A bare JS-family call through a name destructured
(`{ key: alias }` included) from a call's result now resolves the callee —
through the file's imports, else the same file, else the project's one
function of that name (Nuxt's `~/` alias) — checks its source returns the
key, and takes the function declared in its body, else the module-level one
it returns. A later declaration at the call's scope shadows the binding.
Returned object literals now count as exporting their names for #2162's
unexported-binding rule.
A/B edges added (removed): mealie +176 (-4), excalidraw +156 (`const { t } =
useI18n()`), halo +58, kit +34 (-14, `validate` now the validator's own),
elk +19; trpc byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The sealed-module rule only covered modules exporting nothing. Per symbol
now: a JS/TS top-level binding declared by its own statement (function,
const/let/var, class, interface, type, enum) in an ES module is reachable
from another file only if it's exported — the `export` keyword (node flag or
its line), an `export { a as b }` list, `export default x` or
`export default { a, b }`. Classic scripts, CommonJS, `declare global`,
`.d.ts`, qualified members, object-literal members (zustand store actions)
and `proto.x = function x()` are exempt. Applied at the reachability gate,
so the winner is rejected rather than another promoted.
A/B (edges removed / added): zod -229 (package `z` imports → a local `z`),
excalidraw -66 (DOM `Element` → a test helper's type), kit -50, typeorm -47
(`import { ColumnMetadata } from "typeorm"` → a fixture's local), trpc -26,
hono -8, axios -1; express byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
tree-sitter-javascript can't parse Flow annotations; `render(): React.Node`
ended a class early (segmented-control's component had no methods). A
`.js` / `.jsx` whose leading comments carry `@flow` (not `@noflow`) now
detects as `tsx`, and the TS extractor's offset-preserving preParse blanks
Flow-only syntax for those files: exact object `{| |}`, a maybe type's `?`,
an inexact object's bare `...`, `import typeof`, `opaque type`. preParse is
hoisted before the kernel, so both paths parse the same bytes;
kernel-parity now routes .js/.jsx through detectLanguage too (RN core
Libraries: 0 diffs over 641 files). Grammar preload adds tsx whenever
JavaScript is present.
Parse errors over 400 RN-core Flow files: 10,626 (JS grammar) → 391 (TSX).
A/B edges: RN core Libraries 29,649 → 38,194 (+12,639 / −4,094, the
removals mostly `root.render(…)` → the one DrawerLayoutAndroid::render the
old parse left, and edges re-keyed onto recovered methods);
segmented-control +35/−5; express and react-native-netinfo byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Read at the site:
- a later link of a chain (the extractor keeps one receiver level; the line
shows the dot) reaches a member whose owner the receiver chain is named
after (call / type arguments dropped: `proc("x").call()` → proc,
`checker.value.onWrite` → checker), or a same-file member; never a package
object's function unless it is a Scala 3 `extension` method;
- a name the enclosing def binds (parameter, val/var/def, lambda / for param)
is only a def inside that function;
- otherwise a member of the types around it, an anonymous subclass's bases
(`new OptionParser[C]("x") { head(…) }`), their extends/with supertypes
(source-read heads), same file, or an imported object (`import Foo._`,
`import Foo.{bar}`); a value import (`import builder._`) leaves the file
unjudged.
A/B (edges removed / added): cats -1693/+678, sttp -887/+271, munit
-265/+175, scopt -245/+78, os-lib -115/+43.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The README said every bridge hop carries `metadata.synthesizedBy`, but only
the synthesized channels (rn-event-channel, fabric-native-impl) did; a
resolver-made hop (Swift↔ObjC, RN legacy / TurboModules, Expo Modules JS)
carried only `resolvedBy: 'framework'`, and `expo-module-extract` named
nothing that exists. The framework loop now adds `metadata.framework` (the
resolver's name: swift-objc-bridge, react-native-bridge, expo-modules-js,
fabric-view, rails, laravel, …) and the README says what each kind carries.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- FastEndpoints: an endpoint class (`: Endpoint<…>`, `EndpointWithoutRequest`,
`Ep.…`) declares `Get(…)` / `Post(…)` in `Configure()`; each becomes a route
linked to the class's own HandleAsync / ExecuteAsync (the bare-member scope
from #2151 keeps two `List` endpoints apart). A constant path
(`CreateContributorRequest.Route`) is read in postExtract from wherever the
class declares it; `$"/{nameof(Project)}s"` reads as `/Projects`.
- `app.MapGet("api/todos", …)` is named `/api/todos`.
A/B: ardalis/CleanArchitecture 0 → 24 routes (+24 edges); eShopOnWeb and
eShop only re-key routes whose path gained a leading slash; realworld and
jasontaylordev/CleanArchitecture byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Detection only looked at the root (`build.sbt`, `conf/routes`,
`conf/application.conf`); playframework/play-samples keeps each project's
`conf/routes` in its own directory and had no routes. Any indexed Play routes
file now counts. play-samples 0 → 139 routes (+108 edges); root-level Play
repos are unaffected.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Route files (`routes.draw`, or under config/routes/) are read as a block
structure: `namespace` / `scope` add path + controller module, nested
`resources … do` sit under `/:parent_id`, `member` / `collection` add
`/:id/x` / `/x` actions, `root` and `resource` / `resources` options
(`only:` / `except:` across lines, `path:`, `controller:`) are honored;
`do` and `if` / `unless` / `case` / `begin` open frames an `end` closes.
- Detection accepts `gem "rails"` (double quotes), railties, and a Rails
engine's `config/routes.rb` anywhere (solidus).
- A namespaced `controller#action` only reaches controllers of its own
module path when any exist — an admin controller that inherits `index` is
not the API's `ZonesController#index`.
Route→action edges main → this branch: mastodon 221→578, solidus 0→319,
rubygems.org 108→192, maybe 127→189, lobsters 141→196; no non-route edge
lost except solidus's CamelCase refs now resolved by the Rails model
resolver (`Order` → Spree::Order model, was a state-machine module).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
`bp.add_url_rule('/path', 'name', view_func | positional view, methods=[…])`
and a project's own wrapper that hands a list of paths and a `view_func=`
over (flaskbb's `register_view(auth, routes=[…], view_func=X.as_view(…))`)
now produce route nodes linked to the view. A class-based view is ANY unless
`methods=` says; a function defaults to GET. A call whose path isn't a
string literal (the wrapper's own `add_url_rule(route, …)`) adds nothing.
flaskbb 0 → 103 routes (+104 edges); flask's own tests +27; CTFd, microblog,
bluelog byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The unique-name method guess no longer applies to a Lua/Luau call through a
standard or host library table (string, table, math, io, os, coroutine,
debug, utf8, package, bit, jit, ffi, vim, ngx, busted's assert/spy/stub/mock,
love) unless the project defines that function on the table itself (kong's
globalpatches define ngx.sleep), nor to a string method called on a value
(`s:find`, `s:match`, `s:gsub` …). Other untyped receivers keep the guess:
a word rule like Ruby's was tried and lost koreader's OO calls
(`self.ui:reloadDocument()` → ReaderUI).
A/B (edges removed / added): kong -2742, koreader -101, lazy.nvim -84,
telescope.nvim -47, Fusion -9, lua-resty-core -1.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
PHP joins the untyped-receiver languages for the unique-name method guess:
`$x->m()` takes the one project method named `m` only when the receiver
shares a word with its owner, or names a class (the whole name, or its last
camel word: `$newRole` → Role) whose ancestry — extends + trait `use`,
namespace-aware — has the method.
A/B (edges removed / added): guzzle -359, BookStack -302, console -124,
Slim -124, monica -53. Removals are PSR-7 / framework / exception calls
bound to a test double or unrelated helper; the deliberate loss is calls
through receivers named after neither (`$loaner->loansAsLoaner()`).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A bare C# name (a `calls` or `references` ref with no dot, where the line
shows no receiver) can mean a member only of the types around it (outer
classes included), their base types (read from `class X : Base, IFoo`
heads, every partial declaration), or a static using: the file's
`using static`, any `global using static`, or `<Using Include="…"
Static="true"/>` in the .csproj / Directory.Build.props files above it.
Names outside any recovered type are not judged.
A/B (edges removed / added): Newtonsoft.Json -1394/+910 (enum-valued
properties now reach the enum type), AutoMapper -135/+58, eShop -117/+5,
serilog -20/+17, CleanArchitecture 0.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(objc): a message reached by name alone must be in reach
- `[self m]` / `[super m]` / `[[self class] m]` (receiver dropped by the
extractor) reach only methods of the sender's hierarchy, read from
`@interface Name : Super` plus a small UIKit/AppKit/MapKit superclass table
for categories on system classes. When tree-sitter-objc loses an
@implementation and its methods become functions, a same-file function,
one in the file named after a hierarchy class, or any when the sender's
class itself was lost, still counts; `[super init]` never lands on another
file's function.
- C call syntax (`completionBlock()`) never means a method or property.
- Local receivers are typed from ObjC declarations (`FMResultSet *rs`,
`(nullable FMResultSet *)rs`, block params), and objc joins the untyped-
receiver languages for the unique-name guess (`weakSelf` / `strongSelf`
count as self). Shared receiver words must be 3+ letters so class prefixes
(`SD`, `NS`) don't match; Ruby/CFML unchanged but one wrong lobsters edge.
A/B (edges removed / added): SDWebImage -321/+47, fmdb -28/+85,
CocoaLumberjack -19/+10, AFNetworking -13/+1, MBProgressHUD 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(objc): a class or typed-property receiver keeps its inherited method
`[AllTypesObject objectsInRealm:…]` (a class method inherited from RLMObject)
and `[managed.anyDataObj containsObject:]` (a property declared
`RLMSet<…> *anyDataObj`) now keep the unique-name match when the receiver's
class — or one of the property's declared types — has the method's owner in
its hierarchy. realm-swift goes from -2562/+588 to -504/+529 vs main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
VB.NET's extractor keeps a call's last name only, so `Me.Panel.Controls.Add(x)`
and `New System.Drawing.Size(1, 2)` arrived as bare `Add` / `Size` and exact /
fuzzy matching took any class's member (even an enum case). The receiver is
now read from the line: a member candidate needs `Me` / `MyBase` / `MyClass`,
its own type or module as the last receiver segment, or a `(Of T)` type
argument (`GetService(Of Notifier).Notify()`). Genuinely bare names are
unchanged.
A/B (edges removed / added): SCrawler -3452/+6, remoteapptool -143/+0,
CompactGUI -31/+5, ViVeTool-GUI -1, TaskbarX 0.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- A bare call in a .cfc reaches only the component's own methods and those
of the components it extends (extends="a.b.C" read from source, matched
to indexed .cfc files by longest path suffix). Calls in .cfm templates and
multi-line chain links (name not on the ref's line) are not judged.
- The untyped-receiver rule from the Ruby fix now covers CFML too: the one
project method named `m` needs a receiver named after its owner. The word
match also accepts the receiver's whole name (`cbsecurity` → CBSecurity)
and ignores trailing digits (`executor1` → Executor); Ruby is
byte-identical to main.
A/B (edges removed / added): coldbox -2429/+295, TestBox -255/+31,
fw1 -103/+4, cbsecurity -8/+5, cfdocs 0. Deliberate losses: framework-repo
calls through conventionally named, untyped receivers (ColdBox's `event.*`
→ RequestContext, TestBox's `variables.assert.*` → Assertion).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Ruby types nothing, so two guesses produced most of a Ruby repo's wrong
call edges:
- `receiver.m()` through an untyped receiver took the project's one method
named `m`. It now also needs a word shared between the receiver and the
method's owner (`web_push_request.legacy_encrypt` → WebPushRequest);
`self` / `self.class` are exempt.
- a bare `m()` inside a class took any class's `m`. It now reaches only the
class's ancestry — superclasses and include/extend/prepend modules, read
from source and resolved against the lexical nesting. Calls in module
bodies and top-level blocks (specs, DSLs) are not judged.
A/B (edges removed / added): rubocop -4406/+262, mastodon -2642/+540,
jekyll -343/+10, lobsters -243/+4, sinatra -207/+2, devise -112/+3.
Deliberate losses: instance_eval'd DSL blocks inside a class method
(sinatra's own tests' `mock_app { get '/' }`), and helpers on a framework
class the repo reopens past an external superclass (devise setup_mailer).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A Kotlin call's top-level candidate (a function, an extension function, a
property) must be in the caller's package, imported by name, or in a
star-imported package. Class members aren't judged: a lambda's receiver can
put any type's members in scope.
A function type with a qualified receiver (`(A.Builder.() -> Unit)?`) broke
the tree-sitter-kotlin parse badly enough to drop the enclosing class;
an offset-preserving preParse blanks the qualifier (hoisted, so the kernel
parses the same bytes — parity 0 diffs on Exposed, okhttp, nowinandroid).
A/B (edges removed / added): Exposed -5370/+4256 (1,318 R2DBC assertEquals
misroutes; DatabaseTestsBase's members and 250 extends/imports edges back),
koin -965/+960, okhttp -690/+675 (567 MockResponse to the imported
mockwebserver3 class), okio -98/+44, nowinandroid -14.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A receiver-less Dart call now reaches only a method of the enclosing class,
something it extends / mixes in / implements, or an extension on one of those
types, and the nearest one wins. The hierarchy is read from each declaration's
head (comments and type arguments dropped), since supertype edges don't exist
on the first pass. Body-less abstract members (extracted as owned functions)
are scoped too.
Mixin-application classes (`class A = B with C;`) were extracted as
`<anonymous>` with no supertypes; both the wasm extractor and the Rust kernel
now name them and emit their extends/implements refs (kernel parity verified
on bloc, riverpod, shelf, dio, getx).
A/B (edges removed / added): riverpod -1945/+517, shelf -785, getx -855/+18,
bloc -178/+95, dio -78.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
testthat runs each test file in an environment of its own, so a variable a
test assigns is invisible to the package and to other tests. ggplot2's
`c <- ggplot(…)` in test-facet-grid-.R was the one node named `c`, and took
2,455 of the package's `c(…)` calls (the sweep's top-depended symbol).
isVisibleAcrossFiles rejects an R variable/constant under `tests/` from
another file — except `helper-*.R` / `setup-*.R`, which testthat sources for
every test. (A first cut that limited every R call to function nodes lost
ggplot2's factory-defined `geom_point <- make_constructor(…)`, dplyr's
`summarize <- summarise` and shiny's aliases.)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A Lua `local` (variable or function) belongs to the file that declares it,
but cross-file name matching treated it like a global. kong's spec helpers
re-bind busted's globals (`local it = it`, `local assert = require
"luassert"`), and every other spec file's `it(…)` / `assert(…)` /
`describe(…)` linked to them — 15,776 edges; koreader's `local ipairs =
ipairs` in one module took the project's `ipairs` / `pairs` / `type` /
`tonumber` (2,329).
isVisibleAcrossFiles now reads a Lua/Luau variable or function's
declaration line and rejects a `local` one from another file (the reference
stays unresolved rather than taking a runner-up). Globals stay visible.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Extraction records `$this->m()` under the bare name, so exact and fuzzy
matching took ANY same-named method: Drupal core's tests' `$this->assertEquals()`
(PHPUnit's) went to a comparator class 8,832 times, `$this->assertSession()`
to WebDriverTestBase 9,556 times, `$this->t()` to `Views::t` 6,811 times;
Laravel's `$this->assertCount()` to FilesystemAdapter 1,722 times.
A call written through `$this->` / `self::` / `static::` (or `parent::`) now
takes only a METHOD of the enclosing class's ancestry — `extends` and trait
`use`, read from source and resolved through the file's `namespace` / `use`
imports (aliases included) to fully qualified classes — or a subclass's
(a base calling what a subclass defines). Past an ancestor outside the
repository (Orchestra's TestCase) a repository trait's method still counts,
an unrelated class's never does. Inside a trait, `$this` is the using class,
so trait bodies are not scoped. Multi-line `use A,\n B;` trait lists parse.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- The name prefilter checks a case-SENSITIVE set of known names, so in PHP,
Pascal, CFML, COBOL and VB.NET — whose identifiers ignore case — a call
written in another case (`formatprice()` for `FormatPrice`, TestBox's
`ToMatchWithCase()`) was dropped before any strategy ran. Those languages
now also check a lowercase set (built lazily, only when asked).
- `isBarePhpCall` took any `>` before a name for `->`: every call after `=>`
in a PHP array (`'total' => count($items)`, `'by' => user()->id`,
`'label' => trans('…')`) was a member call, and found a same-named method
— 166 wrong edges on BookStack (`trans` → LocaleDefinition::trans,
`new Response` → ImageStorageDisk::response, `url()`, `config()`, `count()`).
It now requires `->` / `?->` / `::`.
- A fuzzy `instantiates` never names a method.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A `<script>` block goes through the TS/JS extractor, which extracts no
symbol for a method in an object literal — so every Vue 2 component, and
every Vue 3 one not on `<script setup>`, had no `handleLogin`, no
`mounted`: their calls, their `this.$router.push`, and the template's
`@click="handleLogin"` all belonged to the file.
`vue-options-api.ts` reads the options object the default export is
(directly, or via defineComponent / Vue.extend / Vue.component) and names
each function in it — `methods`, `computed` (incl. get/set objects),
`watch` (incl. `{ handler }`), `data`, `setup`, lifecycle hooks, Nuxt 2's
asyncData/fetch — as `method` nodes owned by the component; the Vue
extractor re-attributes the references and edges written inside each.
A component's own method is only reached as `this.m()` in that component:
the member-call and exact-name strategies no longer hand it
`e.preventDefault()` (ImageCropper's `preventDefault` method took every
event's call), `this.editor.setValue()`, or `this.$refs['input'].click()`.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The last-resort fuzzy match looks names up in a lowercase index — right for
PHP, Pascal/Delphi, CFML, COBOL and VB.NET, whose identifiers ignore case,
and wrong for every other language. jsoup's 1,844 `@Test` annotations
decorated a `CharPredicate.test` method; commons-lang's `new BitSet()`
instantiated a `bitSet` field accessor 64 times; mall's `new Info()` an
`info()` endpoint; gson's `Method` type a test's `method()`; fmt's
`#include <optional>` gtest's `Optional`.
This generalizes the per-language exact-case rules (Rust, Python, JS) into
one: outside CASE_INSENSITIVE_LANGUAGES a fuzzy candidate must match the
reference's exact name. The cross-language fuzzy-gate test now builds its
winner from an exact-case name.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The rn-event-channel pairs a native emit with a JS listener on the event's
LITERAL name. Most libraries name events through constants — NetInfo
listens with `addListener(PrivateTypes.DEVICE_CONNECTIVITY_EVENT, …)`, many
emit with `.emit(EVENT_NAME, …)` or `sendEventWithName:kEvent` — so their
channels were empty.
Identifier / member-chain event names are now read to the literal their
declaration holds (JS/TS const & enum, Java `static final`, Kotlin
`const val`, ObjC `NSString *const` / `#define`, Swift `let` / enum case),
scoped as the language scopes them: a bare name in the same file or behind
an import, `Owner.NAME` inside Owner or a namespace import's file. The
handler of a constant-named listener is a function in the same file, else
the enclosing one. A first cut that read constants by name alone turned a
`.emit(eventName, …)` parameter into some test's `eventName = "pong"`.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- `requireNativeComponent('X')` (Paper) now emits the same JS `component`
node a Codegen spec does, so the Fabric pass links it to the native view /
manager classes; the extractor also runs on `.js` / `.jsx` spec modules
(segmented-control's spec is Flow `.js`). react-native-maps' `AIRMap`
gains its iOS implementation.
- A JSX tag that names no node is the file's DEFAULT import of a module's
one component: `<RNCSegmentedControlNativeComponent>`, and element-plus's
test `<Autocomplete>` for `autocomplete.vue` (whose component node is
`autocomplete`). A named import never takes a barrel's one component.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Extraction keeps `super.didMoveToWindow()` under the bare method name, so
every strategy resolved it to the enclosing override itself. Across the
bridge sweep that was 139 self-edges on Charts, 142 on commons-lang, 101
on BookStack, 92 on realm-swift, 82 on react-native-svg — lifecycle
overrides and delegates drawn as recursion.
`gateSuperSelfCall` declines a `calls` result that targets the calling
node when the call site is written through `super` / `base` (C#) /
`[super …]` (Objective-C) / `parent::` (PHP) / `super().` / `super(C, self).`
(Python). Plain recursion keeps its edge.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- `app/blog/og-image/[post]+api.ts` was a screen named
`/blog/og-image/[post]+api` (evanbacon.dev). An Expo API route is now one
endpoint per exported HTTP method (`GET /blog/og-image/:post`), bound to
its handler, the way Next.js `route.ts` files are.
- The per-app framework gate (#2129) took ANY enclosing manifest's
declaration: react-native-true-sheet's root declares expo-router for its
example app, so its `docs/` Next.js app got 16 Expo screens (`/layout`,
`/page`, `/api/search/route`, …). Walking up from a file, the first
manifest that names any gated framework now decides.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Expo Modules: a JS call on a `requireNativeModule('N')` binding — typed
(`<CameraNativeModule>`) or not, local or imported (expo-camera's
`import CameraManager from './ExpoCameraManager'`) — resolves to module
N's declared function, Swift first and Kotlin beside it, else to the
member on the binding's declared type. It went to the same-named static
method making the call.
- A JS/TS member call on an import binding never picks a method declared in
the calling file, and ruling those out never manufactures a unique guess.
- `import type { X }` was parsed as a default import named `type` (every
type-only import bound `type`), and `{ a, type B }` bound `type B`.
- A name the file binds from an out-of-repo package names nothing in the
project, for every reference kind, and JS/TS fuzzy matching is exact-case:
trpc's 402 `Record<…>` references went to a `record` property, element-plus's
121 `mount` imports from @vue/test-utils to a test helper.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
From the router sweep:
- angular-spotify had 12 routes all named `/` and no navigation. Its lazy
routes are `async () => (await import('@ws/home')).HomeModule` through an
Nx library's `src/index.ts` barrel, which the mount pass never looked
through; and every lib is its own `src/`, so each routes file got its own
route table and no template's `routerLink` found the screen it names.
- jira-clone had 3 routes and no navigation: its issue route is
`issue/:${ProjectConst.IssueId}` (a class `static readonly`), its root
redirect lives in `app.routes.ts`, which only mounts, and
`navigate(['project', 'issue', id])` has no leading `/`.
Now: lazy mounts follow `export … from` barrels (and an NgModule's routing
imports); `(await import(x)).M` is read; route constants may be class
statics (strings or objects), enum members, or live behind a barrel, and a
template-literal path takes constant holes; a routes file that only mounts
contributes its redirects at its mount prefix; the route table is keyed by
the `angular.json` / `nx.json` workspace; and `router.navigate` /
`createUrlTree` without `relativeTo` resolve a bare first command from the
root, as Angular does (template `routerLink` stays relative).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
react-boilerplate's header links are `export default styled(Link)`…``,
used as `<HeaderLink to="/features">`; takenote's guards render v5's
`<Redirect to="/" />`. Neither tag was read, so both apps had routes and
no links between their screens.
The link synthesizer now reads `<Redirect to>` (navMethod `redirect`) and
any styled-components / emotion wrapper of `Link` / `NavLink` — declared in
the file, or imported from a file that declares or default-exports one.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A `(group)` directory shares a layout and is never part of the URL, and a
parameter's `=matcher` checks its value. Kept in the name, shadcn-svelte's
`src/routes/(app)/(layout)/blocks/+page.svelte` was `/(app)/(layout)/blocks`,
so no `goto('/blocks')` or `<a href="/blocks">` ever reached it and its
Screens showed no navigation at all.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
vue-element-admin, vue-admin-template and vben had no routes: their tables
are named arrays (`export const constantRoutes = [...]`, `const routes:
RouteRecordRaw[] = [...]`) or per-module objects (`const tableRouter = {…}`)
handed to `new Router(...)`, and most of their screens are `children`.
The Vue Router reader now reads those tables in any file that builds a
router, imports vue-router or lives in a router/ directory; joins children
onto their parent's path (a parent is a screen only when no child claims
its address and it doesn't redirect); binds a lazy view by the FILE it
imports (all of vue-element-admin's are `…/index.vue`), through an alias the
resolver can't follow by the one file in the app with that path; links each
screen to its parents' components as layouts; and takes `this.$router.push`.
Nuxt's file routes move into their own `nuxt` resolver, detected only in a
Nuxt app: halo's plain-Vue console got 30 made-up screens from its `pages/`
folders. A Nuxt app at the repository root now gets its routes, and a
top-level `pages/index.vue` is `/`, not `/index`.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
create-t3-turbo, tamagui's starter and react-native-reusables keep an Expo
app beside a Next.js app. Expo Router read the Next app's `app/` folder as
its own, so `layout.tsx` became a `/layout` screen, `page.tsx` a `/page`
one, `_components/posts.tsx` and `api/auth/[...all]/route.ts` screens too,
and a shared `packages/app/` library's files became screens as well.
A resolver can now name `appDependencies`; its extractor runs on a file
only when that file's package.json or an enclosing one declares one of
them. When no manifest in the project declares any, detection found the
framework by other evidence and it runs everywhere, as before. Expo Router
names `expo-router`, Next.js `next`.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Calls in `.vue`, `.svelte` and `.astro` files carry their own language, so
the JS/TS rules from #2120 never applied to them: halo's `t('…')` from
`useI18n()` went to an interface property `t` (562 callers) and `ref(…)`
from `vue` to a local `ref` (523).
"Outside the repository" is now a package the importing file's package.json
chain (or a Deno import map) declares, a Node built-in, `@std/…`, or a
framework's virtual module. An alias the resolver can't follow — SvelteKit's
`$lib/…`, a nested Nuxt app's `~/…`, a nested app's own `@/…` — stays the
project's, and a `workspace:`/`file:`/`link:` dependency is in the repo.
SFC files also get the JS built-ins (`fetch`, `Error`, `Map`), and a file's
own import of a built-in's name (`import Map from './Map.svelte'`) is the
import. Untyped three-segment chains (`api.groupReports.getAll()`) keep
resolving in SFCs, where they reach their API client class.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found by the README-wide sweep: halo's most-depended-on symbols were an
`EmailVerificationService.verify` (1,038 — Mockito's `verify(mock)`) and a
builder's `eq` (845 — ArgumentMatchers `eq`); retrofit's a test helper's
`assertThat` (1,357 — Truth); mall's a DTO's `hashCode` (Object's).
A bare Java call (`verify(x)`, `helper()`, `this.x()`, `super.x()`) now has
only method candidates declared on a class around it, on one of that class's
supertypes (read transitively from the declarations' `extends` /
`implements` — the resolved edges don't exist yet on the first pass), or
imported statically (`import static a.B.m;` / `a.B.*`). Memoized per type
and per file.
A/B vs main (edge diffs, every change classified): halo −2,103/+145,
retrofit −1,380/+18, commons-lang −202/+87, jsoup −92/+45, mall −76,
gson −7/+4. Gains are the right target where one exists: halo's `and` /
`equal` / `isNull` through `import static …Queries.*`, jsoup's `attr(…)`
through `LeafNode`, commons-lang's `addExact` on its own class instead of a
nested MathBridge, retrofit's `getRawType` through `CallAdapter.Factory`.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found by the README-wide sweep — Django/Flask/FastAPI apps' most-depended-on
lists were test and serializer methods: netbox `UserConfig.all` (3,610 from
`X.objects.all()`), `PortSerializer.create` (2,093 from `.objects.create`),
a test-local `FakeQuerySet.count` (1,910); healthchecks `AuthTestCase.get`
(880 from `Channel.objects.get()`), `ProfileAdmin.login` (702 from
`self.client.login()`); mealie `_FakeHTTPResponse.json`.
Python keeps a call through a receiver it cannot name (`User.objects.get`,
`self.client.login`, `request.POST.get`) as the bare `get` / `login`, and
exact-name matching then took any class's method by proximity. The call's
shape is now read at its column (the call's start):
- `bare` (`get(1)`): not a method — Python has no implicit self — and not a
project symbol when the file takes that name `from` a module the project
doesn't contain (`from django.shortcuts import render`);
- `chained`: only a member of what the chain names last — a method of a
class of that name (case/underscores ignored: `self.store` → `Store`,
`self.user_service` → `UserService`) or a function/class in a module of
that name (`app.helpers.slugify()` → helpers.py);
- `self.x()` / `cls.x()`, and chains split across lines: unchanged.
Fuzzy matching is case-exact for Python (`dir(…)` ≠ class `Dir`).
Lexical reachability now walks every enclosing scope, so a method of a
class declared inside a function is only reachable in there (memoized per
candidate).
A/B vs main (edge diffs, every change classified): netbox −18,091/+73
(indexes 8s → 5s), healthchecks −3,354/+361, pytest −2,950/+105,
mealie −1,802/+6, allauth −1,086/+57, DRF −943/+50, flask −167/+17,
httpx −147/+24. Gains are precise member links (`self.channel.notify` →
Channel.notify, `item.stash.get` → Stash.get, `config.cache.get` →
Cache.get, `self.provider.verify_token`); the one deliberate loss class is
calls through an instance whose type needs inference (`flask.g.setdefault`
in flask's own repo). excalidraw, typeorm, gson, okio, AutoMapper, gin and
hono byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found by the README-wide sweep: ripgrep bound 469 `Some(x)` calls to its
own `EncodingMode::Some` variant and 536 `Ok(x)` to `ParseResult::Ok`;
serde bound its `Ok(…)`/`Result<…>` to the `struct Ok` / `struct Result`
its macro-hygiene test declares (845 on one); tokio 924 `Ok` onto
`TransitionToIdle::Ok`, 290 `drop(x)` onto a `drop` method.
For a name that is bare IN THE SOURCE (a `::` path is kept by its last
segment and is not a prelude lookup — checked at the reference's column):
- an enum variant is in scope only through a `use` of it (and its enum) or
of its enum's `*`, and never names a type;
- a prelude name (Ok/Err/Some/None/Result/Option/Box/Vec/String/drop/…)
reaches a project item in another file only through a project `use` of
that name or a glob of that item's own module (`use crate::glob::*`,
`use super::*` for the parent) — `use std::…` trees don't count, and the
`use` scan runs on comment-stripped text (a doc comment's "…use the
Option…" once read as an import);
- fuzzy matching is case-exact for Rust (`Bytes` ≠ method `bytes`,
`Ok` ≠ fn `ok`).
Applied as a candidate filter (so the in-scope item can win) and at
resolveOne's seam — a Rust framework resolver's `Ok(x)` → `struct Ok`
construction bypassed name matching.
A/B vs main (edge diffs, every change classified): ripgrep −1,462/+0,
serde −2,072/+40, tokio −1,820/+2, clap −752/+7, axum −397/+4, bat −45/+0 —
losses are Ok/Some/Err/Result/Option/Vec/drop and same-named variants
pinned on project items; gains are pre-existing same-name ambiguity
(serde's two `Content` enums).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found by the README-wide sweep: cats' most-depended-on symbols were an
`implicit def A` (4,916) and a `case class B()` declared inside a test
method (3,573) — every type parameter `A`/`B`/`F` in the library bound to
them; getx's `T` to a constant `T`; serde's `E`/`T`/`D`/`S`/`F` to test
structs.
New seam gate (type-parameters.ts, applied in resolveOne so every strategy
obeys it):
- A resolved TYPE reference whose name an enclosing declaration declares as
a type parameter is that parameter: read from the heads (the index records
none) — after the declared name (`class Foo<T>`, `fn f<T>`, `func F[T any]`,
`def f[F[_]: Monad, A]`), before it detached from a type (`<T> T max(`,
`fun <T> f`), a C++ `template <…>` above; annotations (`@sp(Int) A`),
variance and keywords skipped; a `[…]` list counts only [] and () so
Scala's `B >: A` bound does not close it; lists up to 40 lines.
- Scala: a bare name a `def` takes as a value parameter (`(f: A => B)`,
`(implicit G: …)`) is that parameter — cats bound 846 `f(a)` calls to a
case class's `f` field. Class parameters are fields and are left alone.
- Scala: a BARE (in the source) type reference reaches a member of another
type only from inside it, a subtype, or a file importing its members;
otherwise the in-scope type of that name is taken when one fits (cats'
`trait FlatMap`, not `Eval`'s nested `FlatMap`; sttp's `trait Backend`).
Name matcher:
- A type (class/struct/enum/interface/trait/alias) declared inside a
function is only reachable from inside it, like nested functions (#1230).
- A capitalized Scala type position never names a method.
A/B vs main (edge diffs, every change classified; each arm's init exit code
checked — an earlier cut crashed resolution on a Scala method named `*`,
now pinned by the test): cats −25,281/+179 (the gains retargets to the
in-scope FlatMap/State; the real types Shown and IsEq kept 5/5 and
315/315), sttp −1,237/+23, getx −430, serde −446/+9, typeorm −632/+152
(`EntityTarget<Entity>`'s type parameter; codemod fixtures' function-local
classes), gson −9; okio/fmt ±2, Newtonsoft.Json and gin byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found by the README-wide sweep: vendored bundles topped "most depended on"
across many repos — delphimvcframework's bundled `Buffer` (6,162) and four
`n`s (2,386 each), retrofit's docs `main.js` `t`/`e`/`i`, TestBox's
`__webpack_require__` — because only `*.min.js` was recognized as generated.
- detectGeneratedFile (index time, persisted as files.generated) now also
flags a .js/.mjs/.cjs file whose text is mostly lines of 1,000+ chars AND
whose long lines are code (≥3% `;{}(),`) — not an ordinary file carrying
one long base64 string — and any file that defines webpack's
`__webpack_require__` loader, however readable its lines. The path rule
also matches `-min.js` (underscore-min.js).
- Entry points' hubs skip nodes in generated files, as they skip tests.
Scanned every .js file of express, axios, lodash, excalidraw, typeorm, zod,
trpc, hono, bulletproof-react: zero new flags on hand-written code; newly
caught: lodash vendor/underscore/underscore-min.js, retrofit website
main.js (754 KB) + prism.js, TestBox syntaxhighlighter.js (webpack).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found by the README-wide sweep: AutoMapper's most-depended-on list held a
test class's `List` property (519) and an attribute's `Type` property (259);
eShop's held MSTest's `TestContext` and MAUI's `Easing` as properties.
A `references`/`type_of`/`returns` ref whose SITE is a type position — read
from the source at its column: `Type name` (a declaration names its type
first), `List<`, `Type?` (not `?.`), `Type[]`, a generic argument, `new X`,
VB's `As` / `New` / `Of` — and every `instantiates` ref (its column is the
`new`) now has only type candidates in exact-name and fuzzy matching: a
property, method (a constructor is one), field or enum case sharing the name
is not one. With the member out of the way the real type wins: `TypeMap
typeMap` now links the `TypeMap` class instead of a `TypeMap` property beside
it. Anything else — `Builder.Services`, `MapGet("/x", GetItems)`, a route's
reference to its action — keeps every candidate.
A/B vs main (edge diffs, every change classified): AutoMapper −1,871/+777,
Newtonsoft.Json −3,612/+599, serilog −447/+187, eShop −78/+15,
CleanArchitecture −9. Losses are BCL/framework types that had been pinned on
project members (List, Type, DateTime, CancellationToken, Exception,
TimeSpan, Easing, TestContext…); gains are the project's own types
(TypeMap, MemberMap, LogEvent, LogEventProperty, TypeNameHandling,
JTokenReader, OrderStatus). An earlier cut that dropped every member
candidate also dropped method groups, `Builder.Services` reads and ASP.NET
route→action references — the position reading keeps all of those.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found by the README-wide sweep: the "most depended on" lists of popular
repos were topped by members that nothing actually calls.
- A member call on a NAMESPACE import (`import * as z from "zod/v4"`) calls
one of the module's exports, never some class's method; a receiver
imported from a package outside the repository names nothing in it.
matchMethodCall's name/word-overlap strategies no longer run for either.
zod: `z.string()` had bound 2,640 calls to a test helper's `string`
getter (Mocker::string topped the hub list with 3,209), `z.toJSONSchema`
371 to ZodType::toJSONSchema; trpc `z.record` to a generated SDK class.
- A receiver-less JS/TS or Go call cannot reach a PROPERTY, FIELD or enum
case either (it already excluded methods, #1714/#1857): typeorm's mocha
`it(…)` bound 2,879 calls to an interface's `it` property and `describe(…)`
1,368 to a command class's `describe` string field.
- A bare call to a name the file imports from outside the repository
(`import { useQuery } from '@tanstack/react-query'`, CommonJS
`require('supertest')`, vitest's `test`) gets no name-matched candidate.
- The React resolver leaves an imported component/hook/context to import
resolution (framework resolution runs first and picked any same-named
project hook — trpc tests' `useQuery` landed on a hook nested inside one of
trpc's factories), and never targets a nested hook; same-file hook first.
- "Outside the repository" is the coordinator's `isOutOfRepoImport`:
isExternalImport (aliases, workspace members) AND not the repo's own package
name AND unresolvable by resolveImportPath — so axios's own tests'
`import { getAdapter } from 'axios'` now resolve to lib/adapters.js instead
of the .d.ts interface member.
A/B vs main (edge diffs, every change classified): zod −5,228, typeorm
−4,318, express −700 (calls onto the `var request = require('supertest')`
binding), trpc −350/+17, excalidraw −233/+3 (props callbacks onto Props
interface members), hono −150, axios −52/+23 (the self-import upgrade),
bulletproof-react: 156 sites that pointed at ANOTHER app's component/hook in
the three-app monorepo now point at the importing app's own, 16 wrong
cross-app links dropped, 8 imports the React heuristic had guessed right lost
(per-app tsconfig paths don't resolve — separate follow-up); gin/cobra
byte-identical, react-redux-realworld byte-identical.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
`codegraph ui` re-execs itself with `--liftoff-only`; the shim the user
started blocks in spawnSync and cannot forward a signal. Killing it by pid —
a process manager, an IDE task, `kill` — left the re-exec'd server serving
its port forever (found during a sweep: servers from hours earlier were still
answering on ports 4801–4808 against deleted indexes, holding their stdout
pipes so the harness that started them never exited). Ctrl+C was unaffected
(the signal reaches the whole process group).
`index`/`init` already guard this with the #277 PPID watchdog. Factor it out
of installCommandSupervision as `watchParent(onLost)` and use it in `ui` with
the same shutdown as SIGINT/SIGTERM (close the index, then the socket). The
liveness watchdog is deliberately not installed for `ui`: a long Steps
computation can legitimately hold the event loop.
Test: POSIX end-to-end through the real relaunch (CODEGRAPH_WASM_RELAUNCHED
unset, 200ms poll) — SIGKILL the shim, the port stops answering; confirmed
failing without the fix.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
`API.PackageController.GetRoute.query(on:)` kept only `query` — the
receiver was a navigation_expression, not an identifier — and the bare
name exact-matched whichever type's `query` came first. On
SwiftPackageIndex-Server every route type has one, so health checks and
package-controller tests "called" the dependency controller (or a test's
own `query`).
Extraction (TS and the kernel's swift walker, byte-parity): a receiver that
is a path of capitalized type names, two segments or more, not led by
`Self.`, is kept: `API.PackageController.GetRoute.query`. Instance chains
(`self.store.load()`) and mixed paths (`URLSession.shared.data`) are
unchanged.
Resolution (swift-type-visibility.ts, called decisively from
matchReferenceInner so nothing falls through to name guessing): the member
on the type the path names — a method, an enum case with associated values,
or a nested type's initializer. A member's owner path is its qualified name
with the outermost extension's written path read back from its line
(`extension API.PackageController { enum ShowRoute … }` →
`API::PackageController::ShowRoute`), so twin `Feature::State`s declared in
`extension BasicsView.Feature` and `extension ObservableBasicsView.Feature`
are told apart. A path shortened inside its namespace or behind a module
qualifier fits; two owners, or none, leave the call unresolved. TCA's
`@Reducer enum Path { case detail }` generates `Path.State`/`Path.Action`,
so `Path.State.detail(…)` lands on the written case.
A/B vs main (edge diffs, every change classified): SPI 76 retargeted, all to
the type the line names, 7 dropped (Fluent `App.Version.query`, `Plot.Node.*`
— SDK members main pinned on project methods); TCA 61 retargeted, 1 dropped
(`State.StateReducer.scope` → an unrelated `Store::scope`); mastodon-ios 177
retargeted (`Mastodon.API.V2.Instance.instance`, `L10n.Plural.Count.vote`),
11 SDK drops; swift-nio 6 calls into a deprecated alias became instantiates
of `ChannelOptions.Types.*`; IceCubes 1/1, Alamofire 2 SDK drops.
Kernel/wasm parity 0 diffs over 2,752 files on six repos.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>