feat(map): stage 1b, each shipped build's own index and three-valued reachability - #1051
Merged
Merged
Conversation
…reachability The code map now indexes each shipped build as it is built: the Android library for the real aarch64-linux-android target with the NDK Gradle pins, the storage node for Linux (in CI), and the host test build, all with release cfgs (rust-analyzer's default debug_assertions and miri off). Every definition is reached, dead or indeterminate in each build separately, with a stable reason code and the source of every fact; reachability is never computed over two builds' edges together. - a trait impl or an outside-trait impl (Drop, Display, From) runs only with evidence: a method taking self needs a value of its Self type constructed in reached code; an associated function needs the type dispatched on (a type argument, a qualified path, a path call, a value). A type only named constructs and dispatches nothing - uncertainty (an ambiguous type or trait, an unexpanded macro body, an unresolved call, the unindexed anchor crate, a node profile not built here) is Indeterminate, never an edge - entry points: exports a Kotlin `external fun` declares, JNI_OnLoad and JNI_OnUnload, load-time constructors, a binary's main; an export nothing declares is a dead-root candidate. The Kotlin reader follows JNI naming (nested and companion classes, @JvmStatic, @JvmName, @file:JvmName, the file facade class, generic and extension natives, qualified annotations); every declaration the Android library does not export is named, with where a function of that name is written (today: the five anchor natives, in the unindexed anchor crate) - every definition occurrence is accounted for; symbols several definitions share stay several nodes, resolved by scope; async_trait extents are repaired from the source, which is parsed as Rust (syn): function extents and receivers, impl headers, how each name in a path is used (a pattern names, a literal or unit value constructs, a turbofish or qualified self type dispatches), calls, macro heads; a macro's tokens that parse as no Rust are read token by token only to add uncertainty, and counted in token-read.tsv; impl headers inside functions declare, not use; crossing extents, module-level collisions, unexplained analyzer log lines, asm, link sections and build-script cfgs stop the map - dsm_sdk's dev-dependency on itself turned test-utils on in the index: each build's real features are read from cargo tree, and what a differing feature's cfg turns off is taken out of the build. What a cfg covers is read by parsing the file as Rust (syn): the node the attribute is written on, doc comments included; a cfg a macro writes whose items do not parse is undecided - an end-to-end fixture (make requirement-map-fixture) pins static dispatch through a type argument and a qualified path, instance dispatch on a constructed value, and a type only named - `explain` and `impact` queries for agents
cryptskii
added a commit
that referenced
this pull request
Sep 29, 2026
CI sets CARGO_TERM_COLOR=always, so cargo tree wrapped its `(*)` repeat marker in terminal escape codes and the feature reader refused the line (Code map job on #1051). Every cargo tree the map runs now asks for `--color never`, and a line holding escape codes is refused by name, saying so. Reproduced locally with CARGO_TERM_COLOR=always (314 colored lines); with --color never the output is byte-identical to the uncolored run, and the full map builds with unchanged readings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This is stage 1b of the code map. Each shipped build now gets its own real index, and every definition is reached, dead or indeterminate per build, with a stable reason code and the source of every fact. Stage 1a landed in #1046.
More chunks are coming on this PR:
specs/requirements/INTENT_MANIFEST.tsvand a comparator that derives an action from intended versus actual state, per the owner's rulings of 2026-09-28.Profiles are committed configs under
ci/. They are hashed into the tree fingerprint together with the lockfile, the toolchain and the analyzer version.aarch64-linux-android, with the NDK at the Gradle pins andjni,bluetoothx86_64-unknown-linux-gnuIND_PROFILE_NOT_BUILT, never a Darwin stand-incfg(test)Reachability is computed per artifact, over that artifact's edges only.
trait-dispatchorself-typestep counts only with evidence that the impl can run:selfneeds itsSelftype constructed in reached code;IND_DISPATCH_SELF_TYPE,IND_NOT_CONSTRUCTED,IND_AMBIGUOUS_TRAIT,IND_AMBIGUOUS_SELF_TYPE,IND_UNLINKED_IMPL,IND_MACRO_GROUP,IND_SCOPE_UNDECIDED,IND_UNRESOLVED_CALL,IND_MACRO_BODY,IND_UNINDEXED_ARTIFACT,IND_CFG_UNDECIDED,IND_UNREAD_DECLARATIONandIND_PROFILE_NOT_BUILT.DEAD_NO_ROOT_PATH.NOT_IN_ARTIFACT.Uncertainty never becomes an edge.
Entry points follow one rule. An exported symbol is a root only when a Kotlin
external fundeclares it.JNI_OnLoadandJNI_OnUnloadare VM roots,ctor/dtorare load roots, and a shipped binary'smainis a main root.@JvmStatic,@JvmName,@file:JvmName/JvmPackageName, the file facade, generic and extension natives, and qualified and use-site annotations.internalmember's module suffix, a multifile part class, a Javanative. Any export it could be isIND_UNREAD_DECLARATION, never a root or a dead root.crates/dsm-android-anchor.Source is read as Rust, parsed with
syn. Tokens are scanned only where nothing parses. This covers:cfgcovers: the attributed node itself, doc comments included, withcfg_attrread asany(not(C), …), nested ones included.A macro's tokens are parsed as items, expressions or statements. Tokens that parse as none of them, such as
macro_rules!bodies, are read token by token, and only in the direction that adds uncertainty. Each such invocation is listed intoken-read.tsvwith its parse errors: 72 on Android, 76 in tests.Nothing is silently dropped or merged:
#[async_trait]extents are repaired from the parsed source. Extents that still cross, or that share an extent outside a macro invocation, stop the map.#[link_section], and cfgs set by build scripts stop the map.Found and fixed by this stage
dsm_sdk's dev-dependency on itself turnedtest-utilson in the "production" index, so stage 1a countedeconomic_fixturesand other test-only code as production. Each build's real features now come fromcargo tree, and whatever a differing feature's cfg turns off is taken out of the build: 39 definitions on Android.cfgline while the definition starts at its doc comment:reset_sdk_context_for_testing,SdkContext::reset_for_testingandCoreSDK::forget_process_startup_admissions_for_testing.Self::Invalid(_) =>) were read as constructing the type, which could have established a dispatch. 1,895 such edges are gone. Unit enum variants used as values (Err(MarketLegRefusal::NotTransferable)) were missed, and 982 edges are added.#![…]) and are removed.No reachability state moved as a result of the last three; the evidence under the states is now true.
Accounting (this Mac; CI adds the node profile)
JNI_OnLoad, onector)dsm_init_runtime)Analyzer logs, per profile (android / tests):
include!Queries for agents
Verification
cargo test -p requirement_map --release: 81 passed. Each new rule is covered by a test with a constructed input, and each fix in the last rounds was mutation-checked by removing it and watching its test go red.make requirement-map-fixture: all 12 readings as expected. This is the end-to-end dispatch fixture through the real rust-analyzer pipeline.make requirement-mapon the full tree.make lint,ci/production_safety_checks.shandscripts/real_code_guard.pyall pass.Not in this chunk