ADR-0084: Exact strong versioned root-symbol candidate selection

Status: accepted
Date: 2026-08-11
Decision owners: NAUX architecture and x86-64 root symbol-selection boundary

Context

ADR-0079 seals the exact dynamic-symbol records, parallel version words, and System V/GNU hash topology of every accepted provider. ADR-0081 proves the exact strong root requirement-to-provider-definition compatibility relation. ADR-0082 seals every root dynamic symbol and joins each nonlocal version index to that compatibility evidence. ADR-0083 admits one reviewed ordered provider scope without granting lookup authority.

The next boundary must prove which already sealed provider symbol is the exact candidate for a supported root request. It must not trust dlsym, the host loader, a linear scan disguised as hash lookup, an unsealed name comparison, or the fact that a provider merely contains a compatible version definition. Selection must independently replay the provider’s admitted hash topology and preserve every rejected earlier-scope probe. It must also stay separate from address calculation and relocation.

Decision drivers

  • Resolve only the strong versioned subset whose semantics are already frozen.
  • Replay the exact System V/GNU lookup structures sealed by ADR-0079 rather than trusting host loader behavior or a preselected symbol ordinal.
  • Bind requester name, hashes, version namespace, compatibility evidence, provider identity, candidate definition, binding, type, visibility, and symbol evidence into one independently replayable ledger.
  • Preserve ADR-0083 scope precedence and the reason every earlier provider did not supply the selected candidate.
  • Keep lookup work explicitly bounded and deterministic under hostile tables.
  • Grant no runtime address, binding, relocation, mapping, or execution authority and make no performance claim.

Considered options

Delegate to the host loader or dlsym

Rejected. Ambient namespaces, preload state, interposition, audit modules, loader implementation details, and process-global state are not NAUX proof authority. A returned address also collapses lookup, binding, relocation, and execution into one opaque result.

Linearly scan all provider symbols

Rejected. It could prove that a same-name record exists but would not prove that NAUX understands or safely bounds the exact hash lookup structures it will eventually own. It would also permit a future consumer to claim hash-path behavior that was never exercised.

Select directly from ADR-0081’s provider ordinal

Rejected. Version compatibility identifies an allowed version-definition namespace, not a concrete dynamic-symbol definition. It would bypass the reviewed scope and fail to expose earlier same-name candidates that must be rejected for exact reasons.

Resolve weak requesters, GNU-unique, unversioned, TLS, and IFUNC together

Rejected. Those requester and candidate classes require distinct unresolved fallback, process-wide uniqueness, root-self precedence, storage, initialization, or execution semantics. Mixing them into the first selector would make absence and ambiguity nonlocal. This does not reject an exact sealed STB_WEAK provider definition satisfying an STB_GLOBAL requester; that candidate binding is explicit evidence, not weak-requester fallback.

Admit a proof-only strong versioned candidate ledger

Selected. The boundary handles only undefined STB_GLOBAL root symbols in an ADR-0080 requirement namespace. It replays every present provider hash table, filters only by explicit frozen compatibility rules, records ordered scope probes, and returns evidence rather than an address.

Decision

Introduce one candidate-selection evidence ledger with these rules:

  1. full ADR-0079, ADR-0081, ADR-0082, and ADR-0083 evidence is independently verified before any request or provider field is trusted;
  2. eligible requesters are exactly undefined STB_GLOBAL root symbols with a non-reserved ADR-0080 requirement version, default visibility, a supported non-TLS/non-IFUNC symbol type, and a unique ADR-0081 compatibility binding;
  3. lookup visits providers only in ADR-0083 order and records a bounded result for every visited provider before the selected provider;
  4. System V lookup uses the sealed bucket and chain topology, GNU lookup uses the sealed bloom, bucket, and chain topology, and every array access and chain step is checked against exact hard limits;
  5. name comparison occurs only after the relevant sealed hash admits the candidate; requester and provider stored name hashes must recompute exactly;
  6. when both hash tables are present, their eligible candidate sets must agree; a malformed, cyclic, over-budget, contradictory, or out-of-range topology fails closed rather than falling back to a scan;
  7. a concrete candidate must be defined, supported, visibility- and type-compatible, in the exact provider named by ADR-0081, and its version namespace evidence must bind the exact ADR-0081 definition evidence; candidate binding is explicitly STB_GLOBAL or STB_WEAK, while STB_GNU_UNIQUE and every other binding fail closed;
  8. zero or more than one eligible concrete candidate for a supported request fails closed; unsupported requester categories emit no partial selection evidence and cannot be silently treated as resolved;
  9. each selected record seals the root symbol ordinal and evidence hash, name and hashes, requirement and compatibility identities, ordered provider probes, selected scope/provider/symbol ordinals, provider-symbol evidence hash, and the exact rejection/selection reason codes;
  10. verification preflights bounded canonical encoding, regenerates every hash probe and filter decision from predecessor evidence, and requires exact aggregate equality;
  11. production selection reads no path or ELF byte and performs no address calculation, load-bias application, final binding, relocation write, mapping, initialization, TLS/IFUNC execution, native call, or timing.

The precise supported type-compatibility matrix and the exact number of eligible frozen-root requests are acceptance facts. A non-authoritative diagnostic over the reviewed fixture predicts 96 undefined STB_GLOBAL versioned requesters: 90 exact candidates (89 FUNC, one OBJECT) and six refused GNU IFUNC candidates (memcpy, memcmp, memset, memmove, strlen, and bcmp). The implementation must derive these facts from the sealed inventories, review them explicitly, and lock them before this decision can be accepted; it may not trust the diagnostic or widen the matrix by inference.

Frozen limits

  • exactly one ADR-0082 root requester and one ADR-0083 scope;
  • at most 108 root dynamic-symbol records;
  • exactly three currently accepted providers and at most 65 scope entries;
  • at most 3,455 current provider-symbol records and the existing ADR-0079 hard maximum for future admitted inventories;
  • no more provider visits than the admitted scope length for one request;
  • no more hash-chain steps than the selected provider’s sealed symbol count;
  • names at most 256 bytes and all counts/ordinals represented canonically;
  • frozen coverage is 96 strong versioned requesters, 90 exact candidates, and six explicit IFUNC refusals;
  • one feature-invariant candidate/probe topology root must be locked after canonical ordering by semantic request key; the topology excludes feature-local root-symbol and decision ordinals plus the root ELF’s local numeric version index; semantic version requirement names remain covered, while each aggregate evidence root preserves the exact ordinals and numeric indices and remains bound to its exact worker artifact identity;
  • frozen candidate/probe topology root 1e9d41d8497bb8a30e82e92ce424ee02b3fa117fe63635405d8a3136d458631e, confirmed across focused and workspace-built worker artifacts whose local root-version numeric indices differ;
  • unsupported requesters produce no candidate evidence;
  • proof-only selection; encoder policy remains 1.4.0.

Consequences

  • Positive: a later binder can consume exact symbol identities without asking the host loader to choose a name/version candidate.
  • Positive: the evidence explains scope precedence and every rejected earlier provider rather than sealing only the winning ordinal.
  • Positive: exact bounded hash replay prepares a self-owned lookup path without opening address or relocation authority.
  • Positive: weak-requester fallback, GNU-unique, TLS, IFUNC, and root-self semantics remain visibly closed instead of receiving accidental behavior; exact weak provider definitions remain observable rather than silently discarded.
  • Negative: full predecessor replay and adversarial hash mutation testing are expensive proof-debug operations.
  • Negative: supporting additional binding/type classes requires a new reviewed decision or an explicit superseding policy version.
  • Open: unversioned and weak-requester lookup, root-self precedence, GNU-unique process identity, TLS/IFUNC semantics, final binding, address calculation, relocation, mapping, initialization, and execution remain later decisions.

Acceptance gates

  1. Freeze the exact eligible requester set and explicit type-compatibility matrix from the accepted sealed inventories.
  2. Every selected candidate replays through the exact present System V/GNU topology and binds the exact ADR-0081 definition namespace evidence.
  3. Scope reorder, skipped earlier provider, direct winner injection, name/hash, bloom, bucket, chain, version, type, visibility, requester/candidate binding, definition, provider, ordinal, count, and evidence mutations fail closed.
  4. Coherently resealed alternate candidates and probe paths still fail independent regeneration.
  5. Exact evidence replays after source-object and root-artifact paths are removed.
  6. Production source has no filesystem, ELF decoder, host loader, address, binding, relocation, mapping, native, timing, or claim authority.
  7. Focused default/all-feature, full workspace, strict lint, governance, refinement, format, shell, link, static-authority, and predecessor replay gates pass before acceptance.
  • ADR-0079 supplies exact provider symbol records and hash topology.
  • ADR-0081 supplies exact strong requirement-to-definition compatibility.
  • ADR-0082 supplies exact requester records, names, hashes, and version joins.
  • ADR-0083 supplies the only admitted provider lookup order.

Acceptance record

Accepted on 2026-08-11 under policy root 261495db47cb5d4c568eb88633e9b60739f86113c20c0e1e224f4af007017c21 and feature-invariant topology root 1e9d41d8497bb8a30e82e92ce424ee02b3fa117fe63635405d8a3136d458631e. The exact reviewed root contains 108 dynamic symbols. The selector derives 96 strong versioned requests, visits 181 bounded provider hash paths, selects 90 exact definitions, and refuses six GNU IFUNC definitions. Selected definitions partition into 89 FUNC and one OBJECT, with 40 STB_GLOBAL and 50 STB_WEAK provider bindings. The refused IFUNC set is exactly bcmp, memcmp, memcpy, memmove, memset, and strlen.

Every present System V/GNU provider lookup structure is replayed from sealed ADR-0079 evidence. Dual tables must agree, every earlier scope probe is preserved, and the selected symbol must join the exact ADR-0081 definition namespace. Shallow mutations and coherently resealed alternate candidate or probe paths fail independent regeneration. Exact evidence continues to verify after source paths are removed. Production selection imports no filesystem, path, ELF decoder, host-loader, address, relocation, mapping, native, timing, or performance-claim authority.

Cross-build verification exposed and corrected two non-semantic linker serialization effects: root dynamic-symbol/decision order and the local numeric .gnu.version assignment can differ while the semantic name, provider, version requirement, selected definition, and probe path are the same. The common topology therefore canonicalizes by semantic request key and excludes those root-local ordinals and numeric version aliases. Each aggregate evidence root still preserves all exact artifact-local fields. Final focused default and all-feature replays pass in 1196.28 and 1312.01 seconds; their artifact-specific aggregate roots are respectively a9302ea60756e327b8aa5f0ea7996501d62da23f7c94b4be8840f3dfde3f934a and 79545a913ba1d08a6bba7a4871b4c22b9face912ff8f96bedbb9f69a7fb8981f.

The final all-feature workspace exits successfully. The library suite reports 421 passed, zero failed, and six intentionally ignored tests in 441.29 seconds; process isolation reports three passed in 298.23 seconds; the ADR-0073 through ADR-0084 carrier reports two passed in 1310.27 seconds; and the independent ADR-0071 carrier reports two passed in 139.22 seconds. Strict Clippy and cargo check across the workspace/features, 22/22 governance, 8/8 strict refinement, all nine shell syntax checks, format/diff, static authority, predecessor regeneration, and a local audit of 152 Markdown files and 445 links pass.

Acceptance grants no weak-requester fallback, GNU-unique, unversioned, root-self, TLS, IFUNC execution, runtime address, final binding, relocation, mapping, initialization, execution, sandbox, standalone, timing, performance claim, or global encoder-policy authority.