Skip to content

feat(map): the intent layer: the specifications' intent against the map, and the conformance it found - #1055

Merged
cryptskii merged 5 commits into
mainfrom
feat/code-map-intent-layer
Sep 29, 2026
Merged

cryptskii merged 5 commits into
mainfrom
feat/code-map-intent-layer

Conversation

@cryptskii

Copy link
Copy Markdown
Collaborator

The intent layer: what the specifications say the code must do, against what it does

The map establishes what the code does, and never decides what it ought to do. specs/requirements/INTENT_MANIFEST.tsv, your authorized home for it, now says that. ci/intent_comparator.py compares the two through one outcome table and derives an action. The adversarial layer can challenge rows, but never write them.

1 · The comparator (d2e3484c0)

Outcomes and policy.

  • Outcomes: SATISFIED / CORRECT; WIRING_GAP, ARTIFACT_GAP, UNDECIDED, DIRECT_PATH_GAP and ROOT_MISMATCH; UNEXPECTED_LIVE_PATH and PRODUCTION_LEAK; REMOVAL_CANDIDATE and DELETE; MISSING_SYMBOL and AMBIGUOUS_SYMBOL; UNSPECIFIED.
  • What fails CI: a gap under a Met requirement. Under Partial, Missing or Violated it is reported as the known hole.
  • Report only: REMOVAL_CANDIDATE, DELETE and UNSPECIFIED.

Reachability intents (your ruling).

  • MUST_REACH is satisfied by REACHED and REACHED_VIA_DISPATCH alike.
  • The spec-only MUST_REACH_DIRECT rejects a dispatch-only path, as DIRECT_PATH_GAP.

Malformed rows are refused, never guessed at. The comparator refuses:

  • unknown values;
  • a requirement MASTER doesn't define;
  • a missing exception for an exclusion, a deprecation or a row with no requirement;
  • a row with no requirement that demands reach;
  • test-only code that isn't MUST_NOT_REACH;
  • a missing citation;
  • a duplicate row;
  • a root that isn't an entry point.

root is the map's fact. requirement_map --root-queries answers "is this symbol reached from this entry point?" with the same rules the map uses. A path must start at the root. A dispatch on it may rest on a value any entry point made, because the process holds it: the app router is built at startup, and every request dispatches to it.

Tests.

  • A fixture manifest with a row for every outcome.
  • Seven manifest mutation cases.
  • The outcome kind in rules.tsv, checked by its test.
  • A fixture router installed by one entry point and called by another (mutation-checked).
  • CI runs the comparator with both builds required.

2 · The conformance it found (7e99c7a3e, CONFORMANCE §6.39)

Read against CI's Linux map, 16 Met rows over 14 requirements cited code no shipped build reaches. Each was traced again from its requirement's text:

  • 12 stay Met, with citations corrected to the production code:
    • leader selection: position_seed / storage_seed → RoutedCell::new → Route::of → Route::leader;
    • SoFi signatures: verify_precommit / verify_fulfillment;
    • a setup's identity: setup_ref;
    • the conjunction: validate's Verdict;
    • liveness: evaluate;
    • determinism: dsm_domain_hasher.
  • MR-STOR-0156 is now Partial. Completion proofs are built and kept, but none is ever read back or checked.
  • MR-DSM-0100 is now Partial. The uniform CanonicalEncode is never called; only per-type encodings exist.

§7 totals: Met 327 → 325, Partial 234 → 236.

3 · The manifest (7e99c7a3e, 330525c67): 1,062 rows

  • Requirement rows. 539 MUST_REACH rows from §8's canonical code references.
    • 468 Android rows are bound to dispatchIngress, which reaches the code of 208 of the 213 Android symbols the manifest names; the other 5 are known holes. The node's 72 are bound to main.
    • Node MUST_NOT_REACH rows pin "a storage node never computes a route or its leader" (MR-SOFI-0070, MR-STOR-0042).
  • Entry points (from a read-only trace, verified). 67 rows say why each root exists: 36 BLE, 6 NFC recovery and 7 dBTC, under the scope exception, and 18 infrastructure.
  • Unreached production code, by conservative class rules.
    • Out-of-scope subsystems are MAY_REACH with the scope exception, and stay active, never deprecated: dBTC, emissions, recovery, hardware anchors and offline BLE.
    • The testing-tags module, which declares itself unused by production, is test-only.
    • Everything else stays UNSPECIFIED, with its reading's action reported: removal candidate, undecided, or declare intent. No intent is inferred from reachability.

Result. Against CI's Linux map (main at 20f63cb), with the root column cleared (that map holds no root answers):

  • Android: 468 SATISFIED, 376 CORRECT, 5 known holes;
  • node: 71 SATISFIED, 141 CORRECT, 1 known hole;
  • 0 failing rows.

This PR's own CI runs the full comparison, the node's root answers included.

For your review (§6.39 Open)

  • removeContact and dsm_init_runtime have no stated purpose. Both are left unspecified for you to decide on.
  • _dsm_builtins_guard can abort the Android library's load if the parked dBTC policy's bytes and commit ever disagree.
  • dsm_sdk/include/dsm_sdk.h is stale: it declares nine functions, none of which exists in Rust.
  • Three §8 rows are stale the other way. They say Missing, though code exists, and are left until traced and tested:
    • MR-SOFI-0255: sofi_routes.rs exists.
    • MR-DSM-0272 and MR-STOR-0146: spool payloads are sealed with ML-KEM and XChaCha20-Poly1305.
  • 101 §8 code references name no definition. They are module paths, method shorthand, or deleted code (process_online_transfer_logic). Stage 3 canonicalizes them.

Verification (local, macOS; the node is indexed only on Linux)

  • requirement_map unit tests: 97/97 (--release). Clippy -D warnings, fmt, the real-code guard and ci/conformance_evidence.py all pass.
  • make requirement-map-fixture: the fixture builds and its test passes, 90/90 readings, and all 21 intent rows give their expected outcome.
  • make requirement-map + -check: 0 contradictions; 25 sentinels, 70 entry points and the counts unchanged.
  • make requirement-map-intent (local): Android rows 468 SATISFIED, 494 CORRECT, 5 known holes. The node's 92 rows read not-built, and CI evaluates them.
  • make requirement-map-mutations: 40/40.
  • Mutation-checked:
    • evidence seeding for root queries;
    • dispatch acceptance under MUST_REACH;
    • the outcome citation check;
    • the harness's crash detection.
  • Gemini gate: satisfied for each chunk.

…the map

The map establishes what the code does. It never decides what the code ought
to do. The intent manifest (specs/requirements/INTENT_MANIFEST.tsv, the
owner-authorized home) says that, one row per requirement, symbol and build.
ci/intent_comparator.py maps each row's intent and the map's reading to an
outcome through one table, and the outcome to an action. The owner's policy
says which outcomes fail.

- MUST_REACH is satisfied by REACHED and REACHED_VIA_DISPATCH alike: dispatch
  is evidence provenance, not a correctness level (owner ruling). The
  spec-only MUST_REACH_DIRECT accepts a direct path alone, and a
  dispatch-only reading is DIRECT_PATH_GAP.
- The outcomes:
  - SATISFIED and CORRECT;
  - WIRING_GAP, ARTIFACT_GAP, UNDECIDED, DIRECT_PATH_GAP and ROOT_MISMATCH;
  - UNEXPECTED_LIVE_PATH and PRODUCTION_LEAK;
  - REMOVAL_CANDIDATE and DELETE;
  - MISSING_SYMBOL, and AMBIGUOUS_SYMBOL for a path several definitions
    share (two `From` impls on one type);
  - UNSPECIFIED, every production definition no row names.

  A gap fails unless its requirement is Partial, Missing or Violated in
  CONFORMANCE §8, where it is reported as the known hole. REMOVAL_CANDIDATE,
  DELETE and UNSPECIFIED are only reported.
- A manifest that cannot be read is refused, never guessed at. It is refused
  for:
  - an unknown value;
  - a requirement MASTER does not define;
  - a missing exception for an exclusion, a deprecation or a row with no
    requirement;
  - a row with no requirement that demands reach;
  - test-only code that is not MUST_NOT_REACH;
  - a missing citation;
  - a duplicate row;
  - a root that is not an entry point.
- `root` is the map's fact, never the comparator's. `requirement_map index`
  and `fixture` answer `--root-queries` (is this symbol reached from this one
  entry point?) with the same reach, direct-path and classify rules, and
  write root-queries.tsv. Asking nothing is `None`, never an empty answer.
- The requirements come from MASTER and CONFORMANCE §8 through
  ci/conformance_evidence.py, still the only Markdown parser. It now exposes
  canonical_ids, status_rows and requirement_statuses, which its own checks
  use.

Tests and gates:
- The fixture gains an intent manifest with a row for every outcome, and the
  outcome each must produce (intent.tsv, requirements.tsv,
  intent-expected.tsv), run by `make requirement-map-fixture`. It also gains
  two `From` impls on one type.
- Seven `manifest` mutation cases each change one thing in a copy of the
  manifest. The comparator must refuse the row, or move exactly the outcomes
  named, with every other row held to its expected outcome.
- rules.tsv gains the `outcome` kind. src/rules.rs reads OUTCOMES from Python
  (as it reads CHECK_RULES) and checks that each outcome's positive fixture
  row has it and its negative does not.
- `make requirement-map` asks the manifest's root questions. `make
  requirement-map-intent` runs the comparator, and CI runs it with both
  builds required. intent.tsv, unspecified.tsv and root-queries.tsv are kept.

The manifest holds its header only. Its rows are the next chunk.

From the gate:
- The root answers come back in the order asked, whatever the builds' order.
- A root is checked to be an entry point in each build this host indexed.
- The harness checks every table's header and cell count, and tells a
  comparator crash (stderr) from a failing row. It writes the changed
  manifest and the report to separate places.
…tations traced (§6.39)

The manifest's first rows declare the specifications' intent for the code §8
cites.
- **What is covered.** Every canonical code reference of a Met or Partial
  row (Violated rows cite violating code, not code that must run) becomes a
  MUST_REACH row.
- **Build.** A row goes in the build that reaches its code, preferring its
  requirement's family (storage to node, the rest to Android). It goes in
  the family's build only when nothing reaches the code, since
  storage-spec obligations the client carries run in the Android build.
- **Evidence and source.** Each row names the §8 row's tests as its evidence
  and cites the §8 row.
- **Node pins.** MR-SOFI-0070 and MR-STOR-0042 add node MUST_NOT_REACH rows
  for Route::of and Route::leader: a storage node never computes a cell's
  route or its leader, and the map shows the node's build reaches neither.

Before landing, the comparator read those citations against the canonical
Linux map (CI's map of main at 20f63cb). Sixteen Met rows, over fourteen
requirements, cited code that no shipped build reaches. Each was traced again
from the requirement's text (owner ruling):
- 12 stay Met, citing the production code:
  - a leader comes from position_seed or storage_seed, through
    RoutedCell::new, Route::of (permute) and Route::leader;
  - SoFi signatures: verify_precommit and verify_fulfillment;
  - a setup's identity: setup_ref and verify_setup;
  - the conjunction: validate's Verdict;
  - waiting on an unread leader: evaluate;
  - determinism: dsm_domain_hasher.

  The dead helpers cited before (position_leader, first_member,
  verify_signed_object, SignedSofiBody::object_id, Validation::and/all,
  CanonicalEncode) are named in each note.
- MR-STOR-0156 is now Partial. No shipped build checks a completion proof:
  production builds one and keeps its digest, and nothing reads a kept proof
  back or checks it.
- MR-DSM-0100 is now Partial. The uniform CanonicalEncode is never called,
  and only per-type canonical encodings exist.

CONFORMANCE §6.39 records all of it. Also recorded there: 101 references that
name no definition the map holds (module paths, method shorthand, deleted
code), which are Stage 3's to canonicalize and are not rows yet. The §7 totals
are regenerated: Met 325, Partial 236.

Against the canonical map the manifest reads 539 SATISFIED, 4 CORRECT, and 6
WIRING_GAPs that are Partial requirements' known holes: 0 failing rows. On a
host that cannot index the node, its 76 rows read not-built (UNDECIDED), and
CI requires both builds. ci/conformance_evidence.py passes.

Also: ci/intent_comparator.py loses an unused `import csv` (it reads its tables
with its own strict reader).
… test-only fates

The manifest gains the owner's remaining first scope. Entry points are bound
to what they serve, and production symbols no build reaches get the
conservative class fates. The map's uncertainty never becomes intent.

Root queries follow the process, not one call.
- A path must start at the named entry point. A dispatch on it may rest on
  a value any entry point made, since the process holds it: the app router
  is built at startup (JNI_OnLoad, SDK start) and every later request
  dispatches to it through dispatchIngress.
- `reach::reached_with` starts from known type evidence and returns what it
  gathered. A build's reach starts from none; a root query starts from the
  whole build's.
- `reached` had no production caller left and is gone.
- New unit test: a_root_query_dispatches_on_a_value_another_entry_point_made.
- New fixture shape: a router JNI_OnLoad installs in a global and
  `Probe.query()` calls through a trait object (installed.rs). Its manifest
  row is SATISFIED from `query`. It reads UNDECIDED if the query starts from
  no evidence (mutation-checked).

Entry points (owner ruling: bind each root to the requirements it serves).
- A read-only trace of all 71, confirmed by the map:
  - dispatchIngress reaches the code of 208 of the 213 Android symbols the
    manifest names; the other 5 are known holes that no entry point reaches.
  - Those rows, 468 of them, take dispatchIngress as their root.
  - The node's 72 requirement rows take dsm_storage_node::main, its only
    entry point.
- 67 more entry points get rows saying why each exists:
  - 36 offline BLE, 6 NFC recovery and 7 dBTC (the six undeclared bitcoin*
    exports and the builtins guard), as MAY_REACH with the scope exception;
  - 18 infrastructure (library load, SDK start, UI state and status), as
    MAY_REACH with its reason.
- removeContact and dsm_init_runtime stay unspecified, with no stated
  purpose, for the owner.

Unreached production symbols (owner ruling: conservative class rules).
- Dead code in out-of-scope subsystems is MAY_REACH with the scope exception
  and stays active, never deprecated. That covers dBTC (§8.3 Deferred),
  emissions, recovery, the hardware anchor crates and the offline BLE
  transport.
- The testing tags module, which declares itself never used by production
  protocol paths, is test-only MUST_NOT_REACH.
- Everything else stays UNSPECIFIED. The comparator's report now gives the
  action by reading:
  - dead: a removal candidate pending review;
  - indeterminate: undecided;
  - reached: declare its intent.

  It is reported only. 83 paths that name several definitions in a build
  stay unspecified rather than become ambiguous rows.

CONFORMANCE §6.39 records the rest of what the trace found:
- the two ingress points, and removeContact and dsm_init_runtime;
- the parked dBTC policy's load-time assert, which can abort the Android
  library's load;
- a committed C header whose nine declarations have no Rust definition;
- three §8 rows stale the other way: MR-SOFI-0255's sofi_routes.rs exists,
  and spool payloads are sealed (MR-DSM-0272, MR-STOR-0146). They are left
  until traced.

Found while verifying:
- The comparator counted a definition the build does not compile (another
  profile's host-only twin of the same path, which reads not-in-artifact)
  as a candidate. On macOS that made three anchor rows AMBIGUOUS_SYMBOL.
- Only compiled definitions are candidates now. With none compiled, a row
  reads not-in-artifact: ARTIFACT_GAP under MUST_REACH, CORRECT under
  MUST_NOT_REACH.

Against CI's Linux map of main, all 1,062 rows read 0 failing:
- Android: 468 SATISFIED, 376 CORRECT, 5 known holes;
- node: 71 SATISFIED, 141 CORRECT, 1 known hole.

Locally the Android rows read the same, and the node's 92 read not-built,
which CI's --built android,node evaluates.

From the gate: the fixture's Probe.query() expects its installed router (JNI_OnLoad
installs it first) instead of turning a missing one into 0.
…als reach the terminal

Owner ruling (2026-09-29): a finding the investigation established stays in §6
even when its remediation is outside the change that found it, marked
deferred. Unfinished implementations of active requirements are never deleted
as dead code, and what awaits the owner is recorded as open, not settled.
§6.39's Open list now says which each item is:
- *confirmed, remediation deferred*: MR-STOR-0156, whose check_completion_proof
  and completion_proofs::get are kept to be wired; MR-DSM-0100, whose
  CanonicalEncode is kept; the stale C header; the 101 unresolved references
  (Stage 3);
- *owner decision*: removeContact and dsm_init_runtime (keep, wire or delete),
  and whether the parked dBTC policy's mismatch should stop the library
  loading;
- *unconfirmed*: the three Missing rows whose code exists, until traced;
- *recorded, not a defect*: the entry points, which the manifest binds.

ci/intent_comparator.py prints a refusal to stderr. `make` redirects
`root-queries`' stdout into a file, and a malformed manifest's refusal
disappeared into it while make aborted. ci/requirement_map_mutations.py reads
an expected refusal from stderr, and fails a case on any other stderr.
CI's first run of #1055 (the first to index the node with the manifest's root
questions) refused: `a root query's entry point dsm_storage_node::main names 2
definitions the node build compiles`. The node's index also holds its build
script's `main`, which shares the binary's path and is not in the build. That
is the class #1054 fixed for sentinel and fixture lookups. A root query now
looks paths up only among definitions in the build's own crates.

- The fixture gains the question: MR-FIX-0008 asks whether probe::main, a path
  the fixture's build script shares, is reached from the entry point. Before
  the fix the fixture refused with CI's exact error; it now reads SATISFIED.
- ci/conformance_evidence.py requirement_statuses refuses a canonical ID §8
  gives no row, where it used to map the ID to None. The comparator reports
  that refusal on stderr.

A macOS host cannot index the node, which is why the local run missed this.
The Android root answers are byte-identical before and after. The map check
is clean, 40/40 mutation cases pass, and the fixture reads 90/90 with 0
unexpected intent outcomes.
@cryptskii
cryptskii merged commit 16f3d71 into main Sep 29, 2026
23 checks passed
@cryptskii
cryptskii deleted the feat/code-map-intent-layer branch September 29, 2026 06:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant