Add flow layout: cursor placement, left rail, declared band heights

Figures were positioned by hand-written offsets. Every gap was a magic
number tuned against the content that happened to be there, so a label
that grew two characters landed on the next tensor, and two stages
started from two different x shared no rail. Both failures compile
cleanly.

Replace it with a cursor. Objects placed with an empty coordinate
argument reserve their own width -- including a stack's offset sheets
and a bracket's overhang -- and gaps are declared once (\stgutter,
\strowgap, \stblockgap). The gap belongs to the object that follows it
and the first object in a band gets none, so every band starts flush on
a shared rail and gap=0pt states that two shards tile exactly.

\stlink makes a connector's label a flow object, which is what removes
the label-wider-than-its-arrow failure entirely. \stcol is a vertical
sub-flow for a split along the contracted axis. \strow declares its
height, so an object that does not fit -- or a column that does not add
up to what it declared, and is therefore drawn off-center -- becomes a
package warning, which build.sh fails on.

Absolute placement is unchanged: passing a coordinate takes the original
code path, and \sttrack folds a hand-placed node back into the cursor.

All three golden examples and the new tests/flow.tex are converted and
build clean.
This commit is contained in:
dela
2026-08-05 15:55:21 +08:00
parent 7a22bef9e3
commit 7b59c81d02
11 changed files with 672 additions and 223 deletions
+8 -4
View File
@@ -29,8 +29,10 @@ A figure built from raw TikZ has to re-earn every invariant by hand and usually
- *geometry* — one `\stdim{axis}{cells}` per symbolic axis, one `\stsetrole{role}{color}`
per tensor role. Declaring these makes the invariants automatic.
See `references/geometry.md`.
4. **Pick the smallest grammar** that exposes the mechanism (see below), then reserve
stage lanes and draw. See `references/layout.md` and `references/api.md`.
4. **Pick the smallest grammar** that exposes the mechanism (see below), then draw with the
flow layout — `\ststage` / `\strow` … `\strowend`, empty coordinate arguments, gaps
declared once. Reach for an absolute coordinate only when no band can express the
placement. See `references/api.md` and `references/layout.md`.
5. **Build and audit.** `./scripts/build.sh fig.tex`. A clean build only proves TeX was
happy; then run the visual audit in `references/checklist.md` against the PNG at full
size and at thumbnail size. Redraw on any mandatory-invariant violation.
@@ -47,7 +49,8 @@ shape or convention you inferred.
| sharding, device ownership, channel groups | adjacent faces tiling a parent | two `\stface` calls, one role each |
| leading axes (`B`, `h`) | depth | `\ststack{...}{sheets}` |
| discrete choices (indices, token ids, expert ids) | symbols in cells, no ramp | `\stindexface` |
| data movement, collectives, non-linear ops | arrows and nodes | `\starrow`, `\starrowlabel`, `st comm` |
| data movement, collectives, non-linear ops | arrows and nodes | `\stlink`, `\stcomm` |
| a split along the contracted axis | a vertical pair inside one band slot | `\stcol` … `\stcolend` |
Combine grammars only when each one adds information. Known zeros stay unfilled; masks,
diagonals, sparsity and partitions must encode their exact structure.
@@ -65,7 +68,8 @@ reference file with the full statement and the failure it prevents.
from continuous score to discrete index to gathered value.
- **Layout** (`references/layout.md`) — everything is a bounding box; tangency counts as
collision. Reserved lanes for stage heading / tensors / symbols / shapes. Connectors on
the background layer, text on the foreground layer.
the background layer, text on the foreground layer. Place by cursor, not by hand-tuned
coordinate: a magic-number offset is only valid for the content it was tuned against.
- **Style** (`references/style.md`) — muted palette, one hue per role, ≤4 active hues per
row plus gray, three separated lightness levels, non-periodic texture, no decoration.