feat(fold): @ folds execute — dual creasePattern + foldedForm output (Plan B-2b) #10

Merged
toph merged 11 commits from v0.9-fold-eval into main 2026-06-30 00:23:45 +00:00
Owner

Plan B-2b — the slice where @ actually folds. Wires the B-2a primitives into a stateful evaluator and emits a dual-frame FOLD file. Design: docs/superpowers/specs/2026-06-29-fold-evaluator-output-design.md.

Eval.eval_folded threads a Fold_state from init_square, resolving every reference against the current folded state: a bare axiom subdivides the face set (a precrease), an @ axiom reflects the moving side and restacks (fold_with_records). moving .p picks the side (defaulted to the moved point for @map .a onto .b); cross resolves a table intersection to a material paper point via the single-face rule (ambiguous in a folded overlap → error).

Fold_emit.to_json_folded builds the planar graph directly from the faces and emits two frames: creasePattern (frame 0, paper coords) and foldedForm (file_frames[0], table coords, frame_inherit, faceOrders). Mountain/valley is derived per crease edge from the orientation-parity rule, so a fold through a stack produces the correct alternating M/V (the accordion). faceOrders signs follow refs/foldformat.md. Everything stays exact in Num; floats appear only at JSON serialization.

beloch fold now routes through this path for every program. The old crease-line emit is gone; Eval.eval/Planarize/Faces stay as a tested standalone path (a later cleanup may retire them). Crease names/provenance are preserved in beloch:edges.

75/75 tests green, including a quarter-fold e2e asserting the accordion mountain and a 4-layer faceOrders set. Screenshots (this PR's new examples) below.

Out of scope (later slices): flip/rotate, unfold, maneuvers, non-flat angles, the topmost-layer reference rule, the bespoke animation client.

Plan B-2b — the slice where `@` actually folds. Wires the B-2a primitives into a stateful evaluator and emits a dual-frame FOLD file. Design: `docs/superpowers/specs/2026-06-29-fold-evaluator-output-design.md`. `Eval.eval_folded` threads a `Fold_state` from `init_square`, resolving every reference against the *current* folded state: a bare axiom subdivides the face set (a precrease), an `@` axiom reflects the moving side and restacks (`fold_with_records`). `moving .p` picks the side (defaulted to the moved point for `@map .a onto .b`); `cross` resolves a table intersection to a material paper point via the single-face rule (ambiguous in a folded overlap → error). `Fold_emit.to_json_folded` builds the planar graph directly from the faces and emits two frames: `creasePattern` (frame 0, paper coords) and `foldedForm` (`file_frames[0]`, table coords, `frame_inherit`, `faceOrders`). Mountain/valley is derived per crease edge from the orientation-parity rule, so a fold through a stack produces the correct alternating M/V (the accordion). `faceOrders` signs follow `refs/foldformat.md`. Everything stays exact in `Num`; floats appear only at JSON serialization. `beloch fold` now routes through this path for every program. The old crease-line emit is gone; `Eval.eval`/`Planarize`/`Faces` stay as a tested standalone path (a later cleanup may retire them). Crease names/provenance are preserved in `beloch:edges`. 75/75 tests green, including a quarter-fold e2e asserting the accordion mountain and a 4-layer `faceOrders` set. Screenshots (this PR's new examples) below. Out of scope (later slices): `flip`/`rotate`, `unfold`, maneuvers, non-flat angles, the topmost-layer reference rule, the bespoke animation client.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Screenshots of this PR's fold examples — crease pattern (frame 0, paper coords) and the folded state (foldedForm frame, rendered with the new fold2svg --folded). Flat folds stack layers in the same plane, so the folded view shows the silhouette, not the individual layers.

fold-half.bel — fold the right half onto the left (one valley crease at x=½).

crease pattern folded

fold-quarter.bel — two folds to a quarter; the second accordions across two layers (one valley, one mountain).

crease pattern folded

complex-fold.bel — build the bottom-edge midpoint (.mid = cross --b --v), then fold it onto .d; the flap swings out past the original square.

crease pattern folded

multiple-folds.bel — diagonal fold, then a half fold, then cross two creases on the folded stack (resolves on the top layer, Q2-B).

crease pattern folded
Screenshots of this PR's fold examples — crease pattern (frame 0, paper coords) and the folded state (`foldedForm` frame, rendered with the new `fold2svg --folded`). Flat folds stack layers in the same plane, so the folded view shows the silhouette, not the individual layers. **`fold-half.bel`** — fold the right half onto the left (one valley crease at x=½). | crease pattern | folded | |---|---| | ![](https://git.toph.so/attachments/f91e1ff0-0c48-4a57-806b-70bb2d90ada5) | ![](https://git.toph.so/attachments/dffd30b1-b69e-4863-b88e-d5ad8802e65f) | **`fold-quarter.bel`** — two folds to a quarter; the second accordions across two layers (one valley, one mountain). | crease pattern | folded | |---|---| | ![](https://git.toph.so/attachments/f8facb17-76d3-4b68-be89-b40357e828f6) | ![](https://git.toph.so/attachments/e8230d22-7b86-495f-84a8-8a0c3414fcf1) | **`complex-fold.bel`** — build the bottom-edge midpoint (`.mid = cross --b --v`), then fold it onto `.d`; the flap swings out past the original square. | crease pattern | folded | |---|---| | ![](https://git.toph.so/attachments/1b76282f-6c4c-497b-a3b8-918bf81734ba) | ![](https://git.toph.so/attachments/b420efb8-b2b8-4b01-a21c-8aabde9cce7c) | **`multiple-folds.bel`** — diagonal fold, then a half fold, then cross two creases on the folded stack (resolves on the top layer, Q2-B). | crease pattern | folded | |---|---| | ![](https://git.toph.so/attachments/c33f7c2e-cd0d-4dec-bb8b-61dc62022568) | ![](https://git.toph.so/attachments/a0d22225-8dc7-4f9c-b3f2-b0477ba74caa) |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A reference point on an already-folded stack is a normal workflow; binding the
visible top layer (what the hand touches) beats erroring on overlap. Off-paper
crossings still error. Design doc revised Q2-A -> Q2-B.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
toph merged commit 7b7959d40e into main 2026-06-30 00:23:45 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
toph/beloch!10
No description provided.