Repository navigation
feat(orbit64): V2 picture-model facelet bridge - #43
Merged
Merged
Conversation
The snapshot of a cube read its array lengths as given, so an array with a hostile length (a Proxy or array-like reporting 1e9 entries) cost seconds or exhausted memory before validation could reject it. A length that was an object with a valueOf, or a bigint or symbol, was coerced more than once or threw. Entries and the frame were copied as they were, so an object with a valueOf passed validation and then answered differently when it was written. The length is now read once, only a non-negative integer counts, and at most 65 entries are copied: no array of a cube has more than 42 entries, so a longer one is no state either way and the reason is unchanged. Only a primitive number is kept as a number; anything else becomes undefined and fails validation without any caller code running on it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The picture model writes one base64url symbol per facelet, the sticker's index within its class (corner 3p+j, midge and wing 2p+j, center orbit p, fixed center 4p+r), so a picture string is as long as a color string. The bridge now accepts the picture model for n = 3..15, canonical and framed, through the existing functions: toFacelets, fromFacelets, encodeFacelets and decodeFacelets. The color API is unchanged except that a picture type is no longer an error; the 2x2x2 has no picture entry and says so. Reading validates in the order of FORMAT-V2.md, with the reference's reasons: symbols before the count, then per class (corner, midge, wings outermost first, centers in orbit order, fixed centers) a range error before a repeat, then each slot's pieces, then the pose, then the laws. A fixed center's rotation is carried through whole-cube turns by the same geometry that turns the stickers. The string is now walked once and only its first 6 n^2 values are kept, so a huge string costs time but no memory, for both models; the first bad character is still reported before the length. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…rator The generator now also copies the 174 picture rows of TestV2FaceletPictureData.flix (generated in flix-orbit64 by facelet_picture_vectors.jl) into orbit64V2FaceletPictures.json. It fails on dropped, duplicated and unparsed rows, on a picture entry other than the two of a size, on a character outside the base64url alphabet and on tokens of unequal length, and pins the 174 rows and the move sequences per size. Both files regenerate byte for byte; the color file changes only its source revision. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The reference rows encode and decode exactly, in both poses, and read back as the same cube in any orientation. Invalid pictures give the reference's exact reasons in the order of FORMAT-V2.md, including which failure wins when several happen in one step. A hostile cube (index getters, Proxy arrays that change between reads, hostile lengths, valueOf tricks) is copied once and never yields a picture of an unreachable cube; huge strings and lengths cost bounded work; nothing throws. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… on stray lines The architecture note said huge strings cost bounded work; the walk is linear in time and bounded in memory, and now says so. The picture test named "returns an error for every mutated row" only checks that nothing throws and that results are well formed, and is renamed accordingly. The fixture generator now fails on any line of TestV2FaceletPictureData.flix that is neither a row nor one of the file's known structural lines. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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.
Scope
Adds the Orbit64 V2 picture-model facelet bridge next to the merged color-model bridge, following
FORMAT-V2.md("Picture facelets") and the Flix referencesrc/Orbit64/V2/Facelets.flixof flix-orbit64a046e34.3p+j, midge and wing2p+j, center orbitp, fixed center4p+r). It is as long as a color string, six fields separated by one space.toFacelets,fromFacelets,encodeFaceletsanddecodeFaceletsnow accept the picture model for n = 3..15, canonical and framed (all 26 picture registry entries). The color API is unchanged except that a picture type is no longer an error. The 2x2x2 has no picture entry and reports the reference's text.rotatePicture/unrotatePicture), ported from the reference.Hardening (also benefits the color model and the state codec):
Orbit64V2.snapshotreads each array length once, accepts only a non-negative integer length, copies at most 65 entries (no array of a cube has more than 42), and keeps only primitive numbers (everything else becomesundefined, so no callervalueOfruns and a Number object no longer passes). A hostilelengthpreviously took seconds or exhausted memory.Array.fromof the whole string); the first bad character is still reported before the length.String()of caller values; only a single code point of the caller string is quoted, as in the color port and the reference (the reference quotes a UTF-16 unit; for a character outside the BMP this port quotes the whole code point, as the color port already does).Fixture and generator:
scripts/orbit64V2FaceletFixture.jl(Julia stdlib only) now also writestest/cube/notation/orbit64V2FaceletPictures.jsonfromtest/TestV2FaceletPictureData.flix. It fails on dropped, duplicated and unparsed rows, on entries other than the two of a size, on characters outside base64url and on tokens of unequal length, and pins 174 rows and the move sequences per size (3: 41, 4: 4, 5: 5, 6: 4, 7: 5, 8: 3, 9: 4, 10: 3, 11: 4, 12: 3, 13: 4, 14: 3, 15: 4). Both JSON files regenerate byte for byte (checked twice); the color file changes only its source revision (d701008->a046e34, the color rows are identical).Verification
npm run typecheck,npm run lint,npm run format:check,typos,npm run build: clean.vitest run --testTimeout=60000: all 83 test files pass (aftergit lfs pull; without LFS objectsfixtures.test.ts,gridAlignmentRealCrops.test.tsandliveFaceAppearance.test.tsfail on JPEG pointers, independent of this change).4f + rfrom the definition; hostile cubes (flip-flopping Proxy arrays and getters,lengthtricks,valueOf/Number/bigint entries, huge lengths and strings) never yield an unreachable cube and never throw.Orbit64.V2.Facelets.encode/decode) over about 37,000 cases: 174 reference rows mutated (single and compound: random symbol, in-class symbol, swaps within and across classes, whole-slot swaps, twists, fixed-center rotations, deleted/inserted characters, bad characters, other entry id) plus random valid and mutated tokens of all picture entries. 0 disagreements in reason or result. The only differences seen are the reference's non-ASCII output being printed as?when the JVM runs without UTF-8 stdout; with UTF-8 there are none.Oktext of a hostile cube reads back as a state that writes the same text.perof fixed centers, order of checks, rotation direction, pose handling, snapshot guards): all killed by the new tests except two that change no behavior (the surrogate-pair step of the string walk, which stops at the first non-BMP character anyway, and an identity edit).Risks
snapshotreads more strictly than main. An object with avalueOf(or a Number object) as an entry or frame was already rejected on main, but main ran the caller'svalueOf(through the globalisFinite/Math.floor, several times per entry) before rejecting it; now no caller code runs and the errors are the same. Alengththat is not a primitive non-negative integer (an object with avalueOf, a Number object) was coerced and accepted on main (an array-like reporting such a length passed) and is now rejected with the usual shape reason; the same guard stops the hostile-length cost. A bigint or symbol entry moves frommalformed stateto a normal layout error. Arrays longer than 64 entries read as 65 entries; the reasons are unchanged since no valid layout is that long.https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz
Generated by Claude Code