Skip to content

refactor(parser): typed clause provenance via ClauseIrBuilder + ClauseDisposition (U5-M1)#5551

Merged
matthewevans merged 1 commit into
mainfrom
ship/u5-clause-provenance
Jul 11, 2026
Merged

refactor(parser): typed clause provenance via ClauseIrBuilder + ClauseDisposition (U5-M1)#5551
matthewevans merged 1 commit into
mainfrom
ship/u5-clause-provenance

Conversation

@matthewevans

Copy link
Copy Markdown
Member

Replace the ad-hoc Vec<ClauseIr> accumulation in parse_effect_chain_ir
with an item-scoped ClauseIrBuilder that is the single authority for
ClauseIr construction — a _sealed field makes every external struct
literal a compile error, so the builder's one internal push is the sole
construction site. Each clause now carries a typed identity + provenance:

  • ClauseId(u32): source-order identity minted by the builder.
  • source: OracleUnitSource at the new honest SpanPrecision::ChainRelative
    tier — byte-exact within the effect chain and carrying the verbatim
    fragment, upgradeable to card-absolute once the document allocator is
    threaded through ParseContext (a later unit). The fragment-precision
    guard consults a widened carries_fragment (Exact | ChainRelative) rather
    than is_exact, so the new tier can carry its fragment without reopening
    the whole-document-fragment hole.
  • ClauseDisposition (Emit / Continue / Special): folds the former
    absorbed_by_followup + special discriminants into one typed enum. The
    two continuations are orthogonal to the discriminant, so they are exposed
    as role-named accessors that span variants: followup() (prior-patch;
    carried by Emit + Continue) and intrinsic() (self-patch; carried by
    Emit + Special).

absorb_clause re-mints a nested chain's clauses through the same
.clause(...).push() path, preserving the single-construction invariant.
The dead is_otherwise field is dropped (zero readers, verified).

Ten identical Effect::Unimplemented { description: None } placeholders (the
.parsed field of Special-disposition clauses, where the real semantics
live in the disposition) are folded into one placeholder_parsed_clause
helper — byte-identical, but DRY and distinct from the Effect::unimplemented
parse-gap constructor (which forces description: Some).

Faithful-by-intent, no behavior change: the IR snapshot parity tests hold
with zero _lowered.snap movement (63 snapshot tests + the full parser
suite green under -D warnings). locate() verbatim-fragment fallback rate:
1/4859 (0.02%) over the 568-card fixture.

…eDisposition (U5-M1)

Replace the ad-hoc `Vec<ClauseIr>` accumulation in `parse_effect_chain_ir`
with an item-scoped `ClauseIrBuilder` that is the single authority for
`ClauseIr` construction — a `_sealed` field makes every external struct
literal a compile error, so the builder's one internal `push` is the sole
construction site. Each clause now carries a typed identity + provenance:

- `ClauseId(u32)`: source-order identity minted by the builder.
- `source: OracleUnitSource` at the new honest `SpanPrecision::ChainRelative`
  tier — byte-exact within the effect chain and carrying the verbatim
  fragment, upgradeable to card-absolute once the document allocator is
  threaded through `ParseContext` (a later unit). The fragment-precision
  guard consults a widened `carries_fragment` (Exact | ChainRelative) rather
  than `is_exact`, so the new tier can carry its fragment without reopening
  the whole-document-fragment hole.
- `ClauseDisposition` (Emit / Continue / Special): folds the former
  `absorbed_by_followup` + `special` discriminants into one typed enum. The
  two continuations are orthogonal to the discriminant, so they are exposed
  as role-named accessors that span variants: `followup()` (prior-patch;
  carried by Emit + Continue) and `intrinsic()` (self-patch; carried by
  Emit + Special).

`absorb_clause` re-mints a nested chain's clauses through the same
`.clause(...).push()` path, preserving the single-construction invariant.
The dead `is_otherwise` field is dropped (zero readers, verified).

Ten identical `Effect::Unimplemented { description: None }` placeholders (the
`.parsed` field of `Special`-disposition clauses, where the real semantics
live in the disposition) are folded into one `placeholder_parsed_clause`
helper — byte-identical, but DRY and distinct from the `Effect::unimplemented`
parse-gap constructor (which forces `description: Some`).

Faithful-by-intent, no behavior change: the IR snapshot parity tests hold
with zero `_lowered.snap` movement (63 snapshot tests + the full parser
suite green under `-D warnings`). locate() verbatim-fragment fallback rate:
1/4859 (0.02%) over the 568-card fixture.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@matthewevans
matthewevans enabled auto-merge July 11, 2026 04:37
@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 00d3c2f Jul 11, 2026
13 checks passed
@matthewevans
matthewevans deleted the ship/u5-clause-provenance branch July 11, 2026 05:00
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