Skip to content

refactor(parser): introduce AssemblyEnv with emit-time registries (U6-B1)#5573

Merged
matthewevans merged 1 commit into
mainfrom
ship/u6-b1-assemblyenv
Jul 11, 2026
Merged

refactor(parser): introduce AssemblyEnv with emit-time registries (U6-B1)#5573
matthewevans merged 1 commit into
mainfrom
ship/u6-b1-assemblyenv

Conversation

@matthewevans

Copy link
Copy Markdown
Member

Infrastructure for Unit 6's antecedent layer. Populated write-only: nothing reads
it, so this is a provable no-op. U6-C flips the consumers over, keeping population
and consumption in separate commits so a bisect can never land on the bookkeeping.

AssemblyEnv carries, per clause:

  • prov: provenance parallel to defs. origin is Option<ClauseId>, NOT
    ClauseIdapply_clause_continuation pushes nodes of its own (e.g. the
    SearchDestination ChangeZone) that belong to no clause, and
    FoldSearchIntoElse binds to exactly such a node. origin: None is that case
    made concrete, and it is why a ClauseId-only arena key is insufficient.
  • role registries: last_dig / last_destroy_like / last_cast_from_zone / last_mana /
    last_play_from_exile / last_conditional / last_optional_for /
    last_search_destination.

last_conditional is registered off the BUILT def's condition, never off
ClauseIr::condition: the Emit path deliberately leaves def.condition unset for
a GenericEffect whose condition was pushed down onto its StaticDefinitions, and
BranchOtherwise's backward scan (d.condition.is_some()) intentionally skips those
nodes. Reading the def mirrors the scan's truth exactly.

observe is called after every statement that changes defs.len(), because a pop
followed by a push in one region would otherwise let the new node silently inherit
the popped node's provenance.

NOT done, deliberately: the two iter().any(..) scans (chain_has_revealed_subject,
any_prior_publishes) are NOT converted to accumulated flags. They are not
equivalent by construction — see the report; this is a stop-and-report, not an
oversight.

Faithfulness: full engine lib 16111 passed / 0 failed, 79 snapshots zero drift and
zero .snap.new, clippy -D warnings clean, combinator gate clean. dead_code allows
are expected for exactly one increment (fields are written, consumed in U6-C).

…-B1)

Infrastructure for Unit 6's antecedent layer. Populated write-only: nothing reads
it, so this is a provable no-op. U6-C flips the consumers over, keeping population
and consumption in separate commits so a bisect can never land on the bookkeeping.

AssemblyEnv carries, per clause:
- `prov`: provenance parallel to `defs`. `origin` is `Option<ClauseId>`, NOT
  `ClauseId` — `apply_clause_continuation` pushes nodes of its own (e.g. the
  SearchDestination `ChangeZone`) that belong to no clause, and
  `FoldSearchIntoElse` binds to exactly such a node. `origin: None` is that case
  made concrete, and it is why a ClauseId-only arena key is insufficient.
- role registries: last_dig / last_destroy_like / last_cast_from_zone / last_mana /
  last_play_from_exile / last_conditional / last_optional_for /
  last_search_destination.

`last_conditional` is registered off the BUILT def's `condition`, never off
`ClauseIr::condition`: the Emit path deliberately leaves `def.condition` unset for
a `GenericEffect` whose condition was pushed down onto its `StaticDefinition`s, and
BranchOtherwise's backward scan (`d.condition.is_some()`) intentionally skips those
nodes. Reading the def mirrors the scan's truth exactly.

`observe` is called after every statement that changes `defs.len()`, because a pop
followed by a push in one region would otherwise let the new node silently inherit
the popped node's provenance.

NOT done, deliberately: the two `iter().any(..)` scans (`chain_has_revealed_subject`,
`any_prior_publishes`) are NOT converted to accumulated flags. They are not
equivalent by construction — see the report; this is a stop-and-report, not an
oversight.

Faithfulness: full engine lib 16111 passed / 0 failed, 79 snapshots zero drift and
zero .snap.new, clippy -D warnings clean, combinator gate clean. `dead_code` allows
are expected for exactly one increment (fields are written, consumed in U6-C).
@matthewevans
matthewevans enabled auto-merge July 11, 2026 11:47

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the AssemblyEnv struct and associated types (NodeRole, NodeProvenance, NodeRef) to track emit-time provenance and maintain role registries of the assembled effect chain. The AssemblyEnv::observe method is integrated throughout assemble_effect_chain to record provenance and recompute registries whenever defs is modified. This is a write-only bookkeeping increment preparing for future binding refactors. I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@matthewevans
matthewevans added this pull request to the merge queue Jul 11, 2026
@github-actions

Copy link
Copy Markdown

Parse changes introduced by this PR

✓ No card-parse changes detected.

Merged via the queue into main with commit f652394 Jul 11, 2026
13 checks passed
@matthewevans
matthewevans deleted the ship/u6-b1-assemblyenv branch July 11, 2026 12:10
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