fix(parser): bind a copy-retarget grant printed under an "if you do" gate (CR 707.10c)#5716
Merged
Merged
Conversation
…gate (CR 707.10c)
Spider-Verse prints its retarget grant as the CONSEQUENT of a reflexive gate —
"you may copy it. IF YOU DO, you may choose new targets for the copy." — rather
than as its own sentence. The copy was modeled, but its controller could never
retarget it: CR 707.10c silently unhonored.
The asymmetry that caused it: the followup-continuation recognizer sees the chunk
BEFORE the condition machinery runs, so it was handed "if you do, you may choose
new targets for the copy" and `recognize_copy_retarget_clause` (an
`all_consuming` grammar with no gate axis) rejected it. The clause then fell
through to the normal path, where `strip_if_you_do_conditional` DID peel the
prefix — so by the time it reached the effect parser the text was bare, the same
recognizer now matched, and it lowered to an honest `orphaned_copy_retarget`
residual. One recognizer, two different inputs, depending on which side of the
condition strip it ran on.
Give `parse_copy_retarget_clause` an optional leading affirmative-reflexive-gate
axis. Compare Spinerock Tyrant, which prints the identical grant as a standalone
sentence and always bound correctly — the two are the same clause wearing
different grammar, so this is one more axis on an existing combinator, not a new
parser.
Folding the gate away is sound BECAUSE it is affirmative and the copy it rides is
itself optional: "if you do" means "if you made the copy", and a retarget
permission on a copy that was never made is unreachable. The gate carries no
information the `CopySpell`'s own optionality does not already carry.
That reasoning does NOT extend to the negated connectors ("if they don't, …"
gates a branch that runs precisely when the antecedent did NOT happen), so
matching the whole connector set and discarding the condition would silently
invert those clauses. `parse_reflexive_conditional_connector` is therefore split
into its affirmative and negated halves, and the retarget clause consumes only
the affirmative one. The two halves are disjoint by construction, not by luck —
every negated tag ends in `n't, ` and every affirmative tag requires `, `
immediately after the verb — so splitting the original single `alt` preserves its
behavior exactly.
Measured full-pool, dual export (35,396 faces). Because this change touches a
combinator shared with `strip_if_you_do_conditional` and the chunk-splitter, the
copy-retarget ledger alone would be blind to collateral on other channels, so the
invariant is checked by diffing every face's ENTIRE tree:
faces with ANY structural change, on ANY channel: 1
spider-verse retargets=[Keep] orphans=1 -> retargets=[May] orphans=0
Zero regressions. Zero faces outside the set touched. The connector split is
behavior-preserving for all 35,395 other faces.
matthewevans
enabled auto-merge
July 13, 2026 03:25
Contributor
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
Parse changes introduced by this PRBaseline pending for |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spider-Verse prints its retarget grant as the CONSEQUENT of a reflexive gate —
"you may copy it. IF YOU DO, you may choose new targets for the copy." — rather
than as its own sentence. The copy was modeled, but its controller could never
retarget it: CR 707.10c silently unhonored.
The asymmetry that caused it: the followup-continuation recognizer sees the chunk
BEFORE the condition machinery runs, so it was handed "if you do, you may choose
new targets for the copy" and
recognize_copy_retarget_clause(anall_consuminggrammar with no gate axis) rejected it. The clause then fellthrough to the normal path, where
strip_if_you_do_conditionalDID peel theprefix — so by the time it reached the effect parser the text was bare, the same
recognizer now matched, and it lowered to an honest
orphaned_copy_retargetresidual. One recognizer, two different inputs, depending on which side of the
condition strip it ran on.
Give
parse_copy_retarget_clausean optional leading affirmative-reflexive-gateaxis. Compare Spinerock Tyrant, which prints the identical grant as a standalone
sentence and always bound correctly — the two are the same clause wearing
different grammar, so this is one more axis on an existing combinator, not a new
parser.
Folding the gate away is sound BECAUSE it is affirmative and the copy it rides is
itself optional: "if you do" means "if you made the copy", and a retarget
permission on a copy that was never made is unreachable. The gate carries no
information the
CopySpell's own optionality does not already carry.That reasoning does NOT extend to the negated connectors ("if they don't, …"
gates a branch that runs precisely when the antecedent did NOT happen), so
matching the whole connector set and discarding the condition would silently
invert those clauses.
parse_reflexive_conditional_connectoris therefore splitinto its affirmative and negated halves, and the retarget clause consumes only
the affirmative one. The two halves are disjoint by construction, not by luck —
every negated tag ends in
n't,and every affirmative tag requires,immediately after the verb — so splitting the original single
altpreserves itsbehavior exactly.
Measured full-pool, dual export (35,396 faces). Because this change touches a
combinator shared with
strip_if_you_do_conditionaland the chunk-splitter, thecopy-retarget ledger alone would be blind to collateral on other channels, so the
invariant is checked by diffing every face's ENTIRE tree:
faces with ANY structural change, on ANY channel: 1
spider-verse retargets=[Keep] orphans=1 -> retargets=[May] orphans=0
Zero regressions. Zero faces outside the set touched. The connector split is
behavior-preserving for all 35,395 other faces.