Skip to content

feat(orbit64): add the Orbit64 V2 state token codec - #40

Merged
wstein merged 6 commits into
mainfrom
orbit64-v2
Oct 31, 2026
Merged

wstein merged 6 commits into
mainfrom
orbit64-v2

Conversation

@wstein

@wstein wstein commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

What

Adds an Orbit64 V2 state token codec in coordinates only, next to the V1 code in src/cube/notation/. There is no facelet bridge, and V1 behavior and the UI are unchanged.

  • Orbit64V2.res / .resi: registry allocation of the 54 entries (n = 2..15) with exact BigInt counts, lengths and offsets; ranking and unranking by the FORMAT-V2.md digit layout (even-canonical corner relabeling, parity-reduced midge and picture-center digits, forced components); encodeOrbit64V2State(id, cube) and decodeOrbit64V2State(token) returning Ok/Error, never throwing.
  • orbit64V2.ts: thin typed adapter re-exporting the generated functions.
  • Orbit64.resi: exposes the existing V1 permutation, orientation, center multiset and base64 helpers so V2 reuses them. No V1 code changed.
  • scripts/orbit64V2Fixture.mjs generates test/cube/notation/orbit64V2Vectors.json (registry table of FORMAT-V2.md and the 195 reference vectors of flix-orbit64@8dc17fb; the header fields say where it came from).

Format and reference: flix-orbit64@8dc17fb, FORMAT-V2.md and src/Orbit64/V2/ (Apache-2.0). Draft format, so this is draft too.

Tests

test/cube/notation/orbit64V2.test.ts (30 tests):

  • registry lengths, offsets, state counts and bits against the table in FORMAT-V2.md; disjoint ranges; shortest-length rule
  • all 195 reference vectors: encode == token and decode == state
  • solved states, and first/middle/last rank of every entry round-trip
  • V1 state tokens for n = 2, 3, 4, 6, 7 read as the V2 color framed entry, re-encode to themselves and have the same corner digit as V1; the 43-character V1 5x5 token is rejected
  • malformed input: unknown tokens, short/long/missing arrays, out-of-range values, broken orientation laws and parities, non-cubes, non-strings; all return Error without throwing

Local results:

  • npm run lint, npm run format:check, npm run typecheck, typos: pass
  • npx vitest run test/cube/notation: pass
  • full npm test: 1112 passed; 52 failed, none in code this PR touches. 47 (fixtures, liveFaceAppearance, gridAlignmentRealCrops) fail with jpeg-js SOI not found because the fixture photos in this clone are Git LFS pointer files; 5 (syntheticFixture, syntheticFaceReal) hit the 5000 ms test timeout on a 2-core machine.
  • npm run test:e2e was not run.

https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz


Generated by Claude Code

The V2 codec reuses the permutation, orientation, center multiset and
base64 helpers. Exposing them changes no V1 behavior.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz
Copies the registry table of FORMAT-V2.md and the 195 reference vectors
of flix-orbit64@8dc17fb into test/cube/notation.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz
Allocates the 54 entries n = 2..15 with exact BigInt state counts, token
lengths and offsets, checked against the table of FORMAT-V2.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz
Ranks and unranks cube states by the digit layout of FORMAT-V2.md with
validation (even canonical corner relabeling, parity relations, forced
components) and encodes and decodes tokens by registry entry. Tests check
all 195 reference vectors in both directions.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz
V1 state tokens of 2x2, 3x3, 4x4, 6x6 and 7x7 read as the V2 color framed
entry with the same corner state; the 43-character V1 5x5 token and
malformed tokens and states are rejected without throwing.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz
Snapshot input arrays by index (holes become invalid), freeze the registry
and hand out copies, catch non-numeric entry IDs, check the alphabet
before the length like the reference, and derive the registry test counts
from the format's radix product.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz

wstein commented Oct 31, 2026

Copy link
Copy Markdown
Owner Author

Opus review: nothing blocking for correctness. The codec matches FORMAT-V2.md and the Flix reference on every rule checked (digit layout, radixes, even-canonical corners, rotation digit, forced parities, allocation). The JSON fixture is byte-identical to the Flix vector file, mutation tests show the vectors pin the center-orbit relation, V1 behavior is unchanged, and each of the commits builds on its own. The 47 failures in the full local npm test (Git LFS pointer images) are identical on a clean main; CI is green.

Fixed after review: arrays with holes are rejected, the registry is frozen and no longer leaks mutable entries, a null or undefined entry id returns an Error, input is read once so hostile getters cannot change values between validation and ranking, decode checks the alphabet before length as the Flix reference does, and the registry tests no longer derive their expectations from the implementation's own counts.

Open question for the maintainer, so this stays a draft: AGENTS.md assigns notation and codecs to PuzlWerk and asks for explicit approval before codec primitives are expanded. Should the V2 codec live here or in PuzlWerk?

🤖 Generated with Claude Code

https://claude.ai/code/session_01VB53JGakrcQ5QAU95yXdMz


Generated by Claude Code

@wstein
wstein marked this pull request as ready for review October 31, 2026 15:51
@wstein
wstein merged commit 3778ea1 into main Oct 31, 2026
2 checks passed
@wstein
wstein deleted the orbit64-v2 branch October 31, 2026 15:52
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.

2 participants