Repository navigation
SPATIAL-2b: carried coordinate-frame identity and operational frame refusal - #8156
Merged
Merged
Conversation
…efusal #8091 claimed that a phantom frame parameter made cross-frame subtraction fail to typecheck, and called that the stronger of the two available options. Measured on the production compile-and-run path 2026-08-11, that program compiles clean and returns 9 -- a plausible number for a question with no answer, which is the fabricated output DESIGN 5 forbids. The cause is a v1 seed limitation, not a modelling slip: the argument-position judge compares nominal HEAD NAMES, and applied type arguments live in the type node's children where every name-level comparison discards them. Point3 matched Point3, so the frames were never compared. A separate compiler PR closes the call boundary; it cannot close the producer side, because return-position conformance declines to judge record types at all pending feature:conformance-produced-type-identity. So the carried identity is the authority and the honest claim is frame consistency BY CHECKED DERIVATION, not by construction: - std.coordinate_frame mints CoordinateFrameIdentity, declaration-owned and never derived from a name or from contents (the HostResourceIdentity precedent). Recorded as the third minted-occurrence carrier in the corpus, which is evidence the subject-parameterized extraction is due -- left as a trigger rather than built here. - Phantom <F> is removed rather than demoted. Two authorities for one fact is the DESIGN 3 violation whichever is right, and the weaker one is the one the compiler cannot enforce end to end. - SpatialResult carries three arms: ready, arithmetic refusal, frame refusal. One coproduct rather than nested result types -- there is one question at the operation boundary and the causes are what differ. - The refusal names ROLES, not expected/observed: for a symmetric operation neither frame is normatively expected, so an operation identity and the required relation replace a report of argument order. - The frame check precedes the arithmetic everywhere, because operands in different frames pose no question to overflow. Green by execution, with discriminating controls: cross-frame subtraction, addition, subtraction, translation and transform application each refuse and name both frames; same-frame operations still answer (the positive sibling a refusal-only control cannot see); frame and overflow are asserted distinct in both directions; a transform's translation must be in its destination frame. The decisive one is the lying-producer control: a function handing back a room-frame value under a building-frame annotation cannot rewrite the carried frame, and the next operation refuses. Mutation-tested -- disabling a single frame guard reds the suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 11, 2026
Closed
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.
What this corrects
#8091 merged claiming that a phantom frame parameter made cross-frame subtraction fail to typecheck — "the stronger of the two options, available here rather than merely preferable."
Measured on the production compile-and-run path (no test harness involved) 2026-08-11:
Compiles clean. Returns
9. A plausible number for a question with no answer — the fabricated output DESIGN §5 forbids.Why the phantom could never have worked
Not a modelling slip.
v1.compiler.infer's argument-position judge compares nominal head names; applied type arguments live inNode.childrenand every name-level comparison discards them.Point3matchedPoint3, so the frames were never looked at. A probe matrix isolated the axis — a primitive mismatch firesTypeMismatch:Primitive(String), while wrong type argument, wrong nominal record type, and a record returned asIntall produce zero diagnostics.A separate compiler PR closes the call boundary. It cannot close the producer side: return-position conformance is a different relation that declines to judge record types at all, blocked on
feature:conformance-produced-type-identity. So this stays writable regardless:A consumer sees only the declared type. It cannot reconstruct an identity the producer erased. Therefore the carried identity is the authority.
The change
std.coordinate_framemintsCoordinateFrameIdentity— declaration-owned, never derived from a name or from contents (theHostResourceIdentityprecedent; a content-derived key makes two coincidentally-identical frames one frame). Recorded as the corpus's third minted-occurrence carrier, which is evidence the subject-parameterized extraction is due — left as a trigger, not built here.<F>removed, not demoted. Two authorities for one fact is the §3 violation whichever is right, and the weaker one is the one the compiler cannot enforce end to end.SpatialResulthas three arms — ready, arithmetic refusal, frame refusal. One coproduct rather than nested result types: there is one question at the operation boundary and the causes are what differ.add_vector3(a, b)neither frame is normatively expected — the first operand merely establishes the result's frame, so "expected" would report argument order as a requirement. It carries an operation identity and the relation required.Guarantee rung, stated honestly
Frame consistency by checked derivation — not by construction. It is not true that cross-frame programs are unwritable.
std.coordinate_framecarries the full account and the dissolve-on: whenfeature:conformance-produced-type-identitycloses, a static projection can be reintroduced above this carrier, and the carried check remains as the serialization / external-input boundary a static guarantee cannot reach.Evidence (green by execution)
Cross-frame subtraction, addition, subtraction, translation and transform application each refuse and name both frames · same-frame operations still answer (the positive sibling a refusal-only control cannot see) · frame and overflow asserted distinct in both directions · a transform's translation must be in its destination frame.
The decisive one is the lying-producer control: a function handing back a room-frame value under a building-frame annotation cannot rewrite the carried frame, and the next operation refuses.
Mutation-tested — disabling a single frame guard turns the suite red.
Sequencing
Independent of the compiler PR; repairs the current-main operational guarantee on its own. Whichever merges second should merge main and regenerate rather than hand-resolve generated artifacts. SPATIAL-3A resumes after both are in CI.