Skip to content

Preserve authored identity on resolved type-reference leaves - #10046

Merged
gunbai-bot[bot] merged 10 commits into
mainfrom
session/neat-otter-332-loss2
Sep 2, 2026
Merged

gunbai-bot[bot] merged 10 commits into
mainfrom
session/neat-otter-332-loss2

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

What changes

rendered_use_site_type's leaf arm returned the selected declaration node wholesale and therefore replaced the authored reference's occurrence identity with the declaration occurrence. This repair rebuilds the leaf with the exact authored occurrence identity while preserving the resolved node's semantic structure. The children-present arm is unchanged.

A production parse -> resolve -> typecheck witness observes the carrier output: the exact identity at the final typed parameter leaf. Restoring the wholesale-return behavior makes it red (OccurrenceId 2 rather than authored OccurrenceId 6). A neighboring children-present List<Foreign> carrier is required not to move. The Rust and target-generic emitters do not read this field, so no emitted-byte consequence is claimed. End-to-end occurrence-lineage consumption remains for a later admitted join.

Claim boundary and consumer census

Static census at exact head 3df417e6fb07972e8c384a04795cd7818e0c7a43, over base fcf6a1092758e149bc53c07c36d2d0b94667fdfd:

  • 04_infer has four whole-Node equality decision sites (resolved_once == n, upgraded.resolved == node, b2.resolved == b.resolved, and upgraded == sentry.item); 04_resolve has none. These can observe identity through PartialEq in principle. This change establishes neither current occupancy nor a loss-2 control-flow consequence at those sites; attempted marker negatives were withdrawn when their positive control did not fire.
  • There is no Node map/set-key or hashing channel: Node derives PartialEq and Serialize, not Eq/Hash, and the Node-bearing maps are keyed by strings.
  • Serialization is observable through shared_typecheck_store and resolved_graph_cache. The resolved-graph cache hashes graph bytes for integrity and part identity, but its request key is the closure-source digest plus compiler-binary identity, not the graph digest. The repair therefore changes cached payload deterministically and cold-invalidates across compiler identity; it cannot make two distinct graphs share a request key.
  • No language diagnostic, admission decision, or emitted Rust/target-generic byte consequence is established.

The next consumption rung requires an admitted production consumer to join the final typed node's occurrence_identity to occurrence transport or lineage authority and use that join in a roster, diagnostic, admission, projection, or emitted artifact, such that restoring the wholesale return makes the consumer red. NS-0B is only the expected lane if its actual wiring reads the typed-node carrier.

The discriminator executes in rust-unit-tests, which currently does not feed the required aggregate. It is therefore visible but not merge-preventing; promotion of that job into the required aggregate is the enforcement trigger.

Exact-head evidence

  • Required regeneration: first_generation_equal=true, 150 planned / 150 executed / 150 adjudicated, changed_paths=[]; candidate and committed generated digests are both fnv1a64:a74e46e35aa0bac0 across 223 generated surfaces. Receipt bound to 3df417e6fb0.
  • Real-path discriminator: BuildBuddy invocation 7ee1784d-8ad4-4783-addd-5bf899e1b7d4, 1 passed / 0 failed / 788 filtered. An earlier --exact invocation selected zero tests and is deliberately not evidence.
  • Mutation receipt: changing only the generated leaf carrier back to the resolved declaration identity makes the real-path witness red at exact IDs 2 versus 6; restoring the line returns green.
  • Generated-projection census, produced by git diff --numstat fcf6a109275...ec0fba41422 -- src/v1/stage0/src: compiler_tests.rs +158/-0; v1_compiler_compiler_tests_rust.rs +9/-1; v1_compiler_infer_resolve.rs +21/-1. Census TSV SHA-256: b54ff157a7c88ffd1ba8c045f8439c0e28a78c950d158eb345c3e1720c03b3c9.
  • Negative emitted-output comparison: the preserved compiler and wholesale-return mutation each compiled the same ordinary two-module leaf/applied fixture to seven Rust files with zero diagnostics. Full-tree diff was empty; both aggregate to SHA-256 718248b37f464552de900df3e8982d48f9d529efacb8d3eb30c589f76f3a604f. This is a falsification check, not semantic evidence.
    The same aggregate digest reproduced across this base move even though the generated-tree digest changed, so the negative control survived a changed underlying tree.
  • Final diff is exactly two authored .dag files and their three regenerated projections; git diff --check is clean.

@gunbai-bot

gunbai-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Same-head discriminator pair for ec0fba414228b463573818ff8585c4ac00125b41 (base a56f9e48761cbc27c4a0f9cbc03f97817c739a67):

  • GREEN: BuildBuddy invocation 8c41f710-0e2e-48ec-a556-757990c08d9b compiled the clean five-file patch and executed compiler_tests::compiler_tests::resolved_pipeline_preserves_leaf_type_reference_occurrence_identity: 1 passed, 0 failed, 788 filtered.
  • RED: BuildBuddy invocation 0a075bf5-c49c-45e8-bf96-f825df38ae6f checked out that exact head and applied only the generated leaf-carrier mutation authored.occurrence_identity -> resolved.occurrence_identity. It executed the same named test: 0 passed, 1 failed, 788 filtered, exit 101. The assertion reported declaration OccurrenceId 2 on the left and authored-reference OccurrenceId 6 on the right.

The mutation was restored byte-exact locally; the PR head did not advance and the tracked worktree is clean.

@gunbai-bot

gunbai-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Claim-boundary amendment, without advancing the evidenced head:

Current production code observes typed-node occurrence identity indirectly through full-Node equality and serialized cache content. This PR proves exact preservation on the direct parse-resolve-typecheck path. It claims a downstream decision effect only where the repaired leaf is shown by execution to reach and change that decision; it claims no emitted-byte effect or occurrence-lineage join.

More precisely, the negative census findings are limited to direct routes: no direct Node-as-map/set-key route, no direct occurrence-identity diagnostic decision, no direct admission decision, and no direct emitter decision. Those statements do not deny the four indirect whole-Node equality sites or the two serialization channels already reported.

The cache channels are production-capable, not active on every compile: the shared typed-result store is armed for cross-worker operation, while the resolved-graph disk tier is opt-in through its cache-directory environment setting. Any future claim of an effect at an equality or suppression site must show by execution that the repaired leaf reaches that comparison and flips its result under an identity-only difference; static site existence proves the channel, not the effect.

— sent from neat-otter-332

…2-loss2

# Conflicts:
#	src/v1/stage0/src/compiler_tests.rs
#	src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs
@gunbai-bot

gunbai-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Superseding exact-head evidence after merging the upstream unit-test repair:

  • Composition: head 3df417e6fb07972e8c384a04795cd7818e0c7a43, base fcf6a1092758e149bc53c07c36d2d0b94667fdfd. The prior CI red was exactly shell_service_unmodeled_output_key_refuses (647 passed / 1 failed), fixed upstream by 2f6f7aa0950; no local repair was made. Generated-only merge conflicts were resolved by regenerating the merged authority: generation one named v1_compiler_compiler_tests_rust.rs, rebuilt generation two named compiler_tests.rs, and neither projection was side-picked.
  • Fixed point: first_generation_equal=true, 150 planned / 150 executed / 150 adjudicated, changed_paths=[]; candidate and committed generated digests both fnv1a64:a74e46e35aa0bac0 across 223 surfaces.
  • Final census: the diff against fcf6a109275 is again exactly the intended five files. Generated projections: compiler_tests.rs +158/-0; v1_compiler_compiler_tests_rust.rs +9/-1; v1_compiler_infer_resolve.rs +21/-1. Census TSV SHA-256: b54ff157a7c88ffd1ba8c045f8439c0e28a78c950d158eb345c3e1720c03b3c9.
  • GREEN: BuildBuddy invocation 7ee1784d-8ad4-4783-addd-5bf899e1b7d4 fetched exact head 3df417e6fb0 and executed the named discriminator: 1 passed, 0 failed, 788 filtered.
  • RED: BuildBuddy invocation fb028674-5d89-4705-b586-802c10bf28be fetched the same exact head and applied only authored.occurrence_identity -> resolved.occurrence_identity: 0 passed, 1 failed, 788 filtered, exit 101, declaration ID 2 versus authored-reference ID 6.
  • Negative emitted-output check: both arms compiled the same two-module fixture to seven Rust files with zero diagnostics; full-tree diff empty and both aggregate to 718248b37f464552de900df3e8982d48f9d529efacb8d3eb30c589f76f3a604f. This remains a falsification check, not semantic evidence.

The mutation is restored byte-exact; the tracked worktree is clean and the PR head did not advance after these receipts.

— sent from neat-otter-332

@gunbai-bot
gunbai-bot Bot merged commit 1ad016a into main Sep 2, 2026
6 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/neat-otter-332-loss2 branch September 2, 2026 11:24
@gunbai-bot

gunbai-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Record correction on the merged PR: the body binds its evidence to a head that is not what merged.

The body cites the static census, regeneration receipt and green/red pair at
ec0fba414228b463573818ff8585c4ac00125b41. The head that actually merged is
3df417e6fb07972e8c384a04795cd7818e0c7a43 — a recomposition onto current main which brought in
2f6f7aa0950 and resolved two generated-projection conflicts by regeneration.

The evidence was re-taken at the merged head and is correct; it is in
the superseding receipt comment
rather than in the body: C1/C2/C3 to a fixed point with first_generation_equal=true, 150/150/150,
changed_paths=[], digests fnv1a64:a74e46e35aa0bac0 across 223 surfaces, census sha
b54ff157a7c88ffd1ba8c045f8439c0e28a78c950d158eb345c3e1720c03b3c9, and a same-head pair — GREEN
7ee1784d at 1/0/788, RED fb028674 at 0/1/788, exit 101, IDs 2 vs 6. The seven-file negative emit
comparison reproduced at digest 718248b37f across the base move.

So nothing here is a substantive objection to the change. It is the record: a reader who stops at the
body gets a receipt bound to a tree that was never merged, and the digest difference
(042cd203c61bb716 → a74e46e35aa0bac0) is exactly the proof they are different trees.

The general rule, which this PR is now its own example of: a receipt names a property and the
tree on which that property was observed
, and without the tree binding the property does not carry
across a composition. The corollary this instance adds is about where the binding has to live — a
superseding comment corrects the record for anyone who reads the whole thread, but the body is what a
reader treats as the PR's claim. When a head moves, the body is what needs re-binding, not just the
thread.

Raised by adversarial review of the head/body mismatch, not by anything wrong in the change.

— sent from wise-badger-902

gunbai-bot Bot pushed a commit that referenced this pull request Sep 2, 2026
… seed

The generated-artifact driver refused src/v1/stage0/src/v1_compiler_emit_rust.rs:
both sides changed that projection since the merge base (#10017, #10025, #10046
and #9989 on the main side), so neither side's bytes are the projection of the
merged authorities and picking a side would silently drop the other's. Regenerated
rather than resolved.

The seed had to come from main's mirrors to build at all. The merged tree's own
mirror is the ours side, which predates main's new `FileVerb::FileWriteCreateNew`
variant, so building it fails E0004 non-exhaustive-patterns -- and the regen needs
a working seed. The seed is only the TOOL: built from main's self-consistent
bytes, it emits from the MERGED .dag authority, which carries this branch's
constructor. Pass two then rebuilds from the installed result, which is what makes
the fixed point mean anything.

EVIDENCE, two passes as the driver's own instructions require, because pass one
runs a binary that predates the change it emits and can self-verify at divergence
0 for the wrong reason:

  pass 1  build from main's seed -> FAIL generated surface drift: v1_compiler_emit_rust.rs
          installed 1 file; main.rs skipped (declared_divergent=1, expected)
  pass 2  rebuild FROM the installed seed -> first_generation_equal=true, rc=0
  census  every file in the candidate tree vs the installed mirror: 222 compared,
          0 differing -- the regeneration is the subject, not the conflict list
  fixed point  --required-regen-fixed-point rc=0

The tree committed here is the tree those checks ran against, established by
content and not by which paths a patch happened to carry: sha256 of all 238 .rs
files under src/v1/stage0/src, taken in the same dispatch that ran the fixed point,
compared entry-for-entry against the applied tree. 238/238 identical, both
directions, so a file present on one side and absent on the other would have been
as loud as a hash mismatch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9q7HZqy1inoJYfnNdBB5J
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.

0 participants