Repository navigation
Conversation
Add AIDL, JNI, HAL, service, and IPC evidence tools with Java/Kotlin extraction and resolution fixes and regression coverage. Document supported analysis, evidence limits, and public reference inputs. Add contributor guidance and GitHub PR and merge-queue checks for Node 22/24 and native kernel parity.
…ct_literal Native kernel parity gaps found in Codex cross-review of the AOSP/AAOS extension rebase (upstream ba3c21e): - java.rs extract_anonymous_class pushed the truncated (bare-segment) type name as the `extends` reference instead of the full dotted name, unlike wasm's tree-sitter.ts (2026-09-11 fix). This silently broke AOSP's qualified-name AIDL Stub lookups (`IFoo.Stub`) on any file routed to the native kernel. - kotlin.rs had no `object_literal` handling at all (`object : IFoo.Stub() { ... }`), the dominant AIDL Stub idiom in Kotlin AOSP sources — wasm's extractKotlinObjectLiteral existed precisely because this idiom had 0% recall before it was added. Ported the extraction (delegation_specifier walk, extends/instantiates refs, kotlinObjectScopeDepth identity binding) verbatim from tree-sitter.ts. Verified: full suite (284 files / 4877 tests) passes, including kernel-kotlin-parity, kotlin-object-literal, and all aosp-*.test.ts.
inferJavaFieldReceiverType reads a field's type from its signature, in the Java shape `Type name`. Kotlin properties are indexed without a signature, and primary-constructor properties (`class A(private val repo: Repo)`) are not indexed at all, so every Kotlin `prop.method()` got no type and fell through to name-only guessing: the interface method, or any same-named method elsewhere (`probe.close()` on a `lateinit var probe: HttpProbe` resolved to an unrelated class's `close`). For Kotlin the type is now read from the declaration: the property's own lines (`name: Type`, or `name = Type(…)`), or the class header before its first member for a constructor property. A nested type keeps its outer type (`HardwareLock.Lease` → `HardwareLock::Lease`), so it matches that `Lease` and not another class's. resolveMethodOnType still validates the method. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion tree-sitter-kotlin has no `fun interface` (Kotlin 1.4 functional interfaces). The declaration parsed as a broken function, and when a doc comment followed it, error recovery swallowed the NEXT declaration too: an interface and its methods went missing, surfacing as top-level functions, or a class vanished with its members. The Kotlin extractor's preParse now blanks the `fun` of a `fun interface` declaration (three spaces for three letters, so offsets hold); the kernel receives the same bytes through the preParse hoist and no longer defers these files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nguessed Two more receivers the Kotlin resolver could not type: - A local or property bound to a call (`val lease = HardwareLock.tryBegin()`, `private val schema = Checker.load()`) is typed by the callee's declared return type, from its signature. A return type nested in the callee's owner keeps it (`Lease` in `HardwareLock` → `HardwareLock::Lease`). - A receiver whose type the project does not declare (`Regex`, `Properties`, a call on `Executors`) now gets no edge. The name-only fallback used to bind it to any project method of the same name: a `regex.find()` to an unrelated `find`, `socket.connect()` to a `connect` elsewhere, a `close()` to itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…railing-lambda constructors
More Kotlin receivers the resolver could not type, found on real apps:
- A `val` property is indexed as a `constant` and a companion-object
property as a `variable`; the property lookup only took `field`.
- `var mode = Mode.ON` is typed by its enum (project enums only; `Limits.MAX`
is an Int).
- `val t = Thread { … }` is a constructor too (trailing lambda, no parens).
- `val old = current ?: return` / `current!!` / `val x = current` take the
aliased value's type; `requireNotNull(x)` / `checkNotNull(x)` take x's.
- A typed parameter of the enclosing function or overridden callback
(`onOpen(webSocket: WebSocket, …)`) is used when nothing else names one.
- Known stdlib factories (`listOf`, `mutableMapOf`, `lazy`, `thread`, …)
return a library type; any other library function leaves the type unknown.
A library type still gets no edge: `thread.join()`, `process.destroy()`,
`webSocket.send()` no longer bind to project methods (or a test fake) of the
same name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Kotlin call through a receiver chain (`engine.pump.drain()`, `this.engine.drain()`, `a?.b?.c()`) was extracted as the bare method name, so it could only be name-guessed: a same-named method in the caller's file, or any project method when the chain ended in a library type (`runtime.reconnectTask?.cancel()` on a `ScheduledFuture`). The extractor (wasm path and kernel, in parity) now keeps a chain of up to four identifier segments. The resolver types the first segment as a single receiver (`this` is the enclosing class, a type name its object or companion), then each next segment as a property or enum entry declared in the class of the type before it, read from that class's own file. A typed chain resolves on its type; a chain through a library type gets no edge unless the project declares an extension of that name on a library type; an untyped chain resolves as the bare method name, exactly as before. A constructor call with type arguments (`Crate<Int>()`, `mutableListOf<T>()`) now types its value too. The alias test now picks the anonymous object's `onOpen` and ignores synthesized override edges, so it holds once object-literal members are extracted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nonymous objects A receiver (or chain segment) that the enclosing class does not declare is looked up in its project supertypes, read from each class header (breadth- first, at most four levels); a library or ambiguous supertype is not walked, so the receiver stays unknown and keeps the name-only resolution. The local declaration scan continues from a function nested in another (an anonymous object's member, a local function) into the outer function above it, skipping sibling functions whose locals are not visible. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(kotlin): resolve imported type calls by qualified name
…-calls # Conflicts: # src/resolution/name-matcher.ts
…fork fix(java): integrate static-field calls into fork main
fix: close symlinked home path gap
fix: trim idle project connections during active calls
fix(kotlin): preserve visible imported receiver extensions
…-calls-fork-followup # Conflicts: # CHANGELOG.md
…llowup Follow up on Java static field call resolution
fix(security): block symlinked sensitive home directories
…egrate-1931 # Conflicts: # CONTRIBUTING.md # docs/README.md
…egrate-1928 # Conflicts: # CHANGELOG.md # __tests__/aosp-aidl.test.ts # __tests__/aosp-common.test.ts # __tests__/aosp-content-provider.test.ts # __tests__/aosp-hal.test.ts # __tests__/aosp-jni.test.ts # __tests__/aosp-local-socket.test.ts # __tests__/aosp-messenger.test.ts # __tests__/aosp-permission-broadcast.test.ts # __tests__/aosp-system-service.test.ts # docs/design/android-platform-analysis.md # src/aosp/aidl.ts # src/aosp/common.ts # src/aosp/content_provider.ts # src/aosp/hal.ts # src/aosp/jni.ts # src/aosp/local_socket.ts # src/aosp/messenger.ts # src/aosp/permission_broadcast.ts # src/aosp/system_service.ts # src/bin/codegraph.ts # src/db/queries.ts # src/mcp/tools.ts
Integrate contributor guides from upstream colbymchenry#1931
# Conflicts: # README.md
…k/integrate-1927 # Conflicts: # __tests__/extraction.test.ts # __tests__/kotlin-object-literal.test.ts # __tests__/resolution.test.ts # codegraph-kernel/src/java.rs # codegraph-kernel/src/kotlin.rs # src/extraction/tree-sitter.ts # src/resolution/name-matcher.ts
Integrate Kotlin property receiver resolution from upstream colbymchenry#1933
Integrate Java/Kotlin anonymous inheritance follow-up from upstream colbymchenry#1927
Integrate reviewed Android platform analysis from upstream colbymchenry#1928
Sync fork with upstream main and preserve Android resolver fixes
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 77c6515d09
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| function defaultsOnlyIgnore(): Ignore { | ||
| return ignore().add(DEFAULT_IGNORE_PATTERNS); | ||
| function defaultsOnlyIgnore(allowVendor = false): Ignore { | ||
| return ignore().add(allowVendor ? DEFAULT_IGNORE_PATTERNS.filter((p) => p !== 'vendor/') : DEFAULT_IGNORE_PATTERNS); |
There was a problem hiding this comment.
Keep nested vendor dependency directories excluded
When codegraph.json includes vendor/, removing the vendor/ pattern from this matcher disables that default at every depth, so paths such as vendor/oem/tool/vendor/dependency/*.go are traversed and indexed as well. Those nested vendor directories are third-party dependency trees rather than the opted-in Android vendor implementation tree, potentially inflating and polluting the graph; exempt only the selected top-level vendor subtree while retaining the nested-directory exclusion.
AGENTS.md reference: AGENTS.md:L120-L124
Useful? React with 👍 / 👎.
| if (owner?.visibility === 'public' && | ||
| (owner.kind === 'interface' || (owner.kind === 'enum' && candidate.kind === 'enum_member'))) return true; |
There was a problem hiding this comment.
Honor implicit visibility through nested Java interfaces
For a legal declaration such as public interface Outer { interface Inner { static void api() {} } }, both Inner and api are implicitly public, but the extracted Inner node has no explicit visibility. When resolving Outer.Inner.api() from another package, this check sees the method's immediate owner as non-public and falls through to the same-package test, dropping the valid call edge. Effective interface visibility needs to account recursively for implicit-public nested interfaces rather than requiring the immediate owner to carry an explicit public modifier.
Useful? React with 👍 / 👎.
| const candidates = new Set([...gitChanges.deleted, ...gitChanges.modified, ...gitChanges.added, ...dirtyPaths!]); | ||
| const include = loadIncludeMatcher(this.rootDir); | ||
| if (include) { | ||
| for (const file of collectIncludedFilesForRoot(this.rootDir)) candidates.add(file); |
There was a problem hiding this comment.
Avoid hashing every included file on clean status checks
Whenever an include matcher exists, this adds every included file to the Git fast-path candidate set, after which the loop reads and hashes every candidate even when its recorded size and mtime are unchanged. With the intended include: ["vendor/"] on a large Android tree, a clean codegraph status becomes proportional to all vendor source bytes, while MCP status commonly reaches its 8-second measurement timeout and reports freshness as unknown; apply the same size/mtime prefilter used by sync() before reading these files.
AGENTS.md reference: AGENTS.md:L120-L124
Useful? React with 👍 / 👎.
Changes
codegraph.jsoninclude: ["vendor/"]index Android vendor Java/Kotlin/C++ implementation source, even when Git ignores it. Other built-in dependency/build skips and explicit excludes still apply. Git fast-path change detection now sees included files and their deletion.extends/implementsagainst the declared type while preserving qualified nested names, in both wasm and native extraction.@nullable IBluetoothLe getBluetoothLe()in both AIDL and HAL declaration scans. This syntax occurs in public AOSPhardware/interfacesrevision863f96ecdd628638da61a302f13615e61eec6d60.Validation
CODEGRAPH_KERNEL=0and with the rebuilt native Java kernel (getKernel()loaded andkernelSupports('java')true).npm run buildpassed;cargo checkandnpm run build:kernelpassed.