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.
98 lines
4.3 KiB
Markdown
98 lines
4.3 KiB
Markdown
# supertensor
|
||
|
||
A shape-aware toolkit for drawing tensor formulas: a LaTeX/TikZ macro package, a build
|
||
pipeline that fails on silent corruption, worked examples, and an agent skill that ties
|
||
them together.
|
||
|
||
It exists because figures of this kind fail in a specific way — they compile, they look
|
||
clean, and they tell the reader something false. A face captioned `Kᵀ` that was never
|
||
transposed; shards that do not tile their parent; an index tensor drawn with a lightness
|
||
ramp. The package's job is to make the correct thing the easy thing.
|
||
|
||
```
|
||
SKILL.md the skill entry point (lean; loads references on demand)
|
||
references/ geometry, semantics, layout, style, api, checklist, antipatterns
|
||
assets/supertensor.sty the macro package
|
||
scripts/preflight.sh is the TikZ + CJK path available?
|
||
scripts/build.sh compile, audit the log, export pdf/svg/png/thumb
|
||
examples/ three golden examples + an anti-pattern gallery
|
||
```
|
||
|
||
## Quick start
|
||
|
||
```bash
|
||
./scripts/preflight.sh # 0 = full path, 1 = degraded, 2 = no LaTeX
|
||
./scripts/build.sh examples/mha-causal.tex # -> examples/build/mha-causal.{pdf,svg,png}
|
||
```
|
||
|
||
A minimal figure:
|
||
|
||
```tex
|
||
\documentclass[border=10pt]{standalone}
|
||
\usepackage[cjk]{supertensor}
|
||
|
||
\stsetrole{act}{stTeal} % one hue per tensor role, held across every stage
|
||
\stsetrole{w}{stOrange}
|
||
\stdim{T}{6} % one symbolic axis -> one physical edge length
|
||
\stdim{d}{4}
|
||
|
||
\begin{document}\begin{tikzpicture}
|
||
\ststage{S1}{one band, placed by cursor}
|
||
\strow{row}{T} % band height, declared once
|
||
\stface[role=act, bracket=true]{X}{}{T}{d} % empty coord = at the cursor
|
||
\stglyph{m}{$\times$}
|
||
\stface[role=w]{W}{}{d}{d}
|
||
\strowend
|
||
\stcaption{X}{$\mathbf X$}{$T\times d$}
|
||
\stcaption{W}{$\mathbf W$}{$d\times d$}
|
||
\end{tikzpicture}\end{document}
|
||
```
|
||
|
||
Because `T` and `d` come from the ledger, the contracted axis is automatically one edge
|
||
length in both operands, `d×d` is automatically square, and any other face of shape `T×d`
|
||
in the figure is automatically identical to `X`.
|
||
|
||
Because the coordinates are empty, each object reserves its own width and the gap between
|
||
them is `\stgutter`, declared once. Nothing here is a tuned offset, so growing a label can
|
||
only push its neighbours apart — it can never land on top of one. And the band declares its
|
||
height, so an object that does not fit is a failed build rather than something the reader
|
||
discovers.
|
||
|
||
See `references/api.md` for the full macro list.
|
||
|
||
## Examples
|
||
|
||
| file | shows |
|
||
|---|---|
|
||
| `tp-ffn-allreduce.tex` | column-then-row sharding, exact tiling, one hue per TP rank, a collective as a real node, a `\stcol` split along the contracted axis |
|
||
| `mha-causal.tex` | leading axes as stack depth, a physically swapped `Kᵀ`, a mask in a different grammar from the scores it gates |
|
||
| `moe-topk-gather.tex` | scores → indices → Boolean support → gather, with all three cell grammars side by side |
|
||
| `antipatterns.tex` | four figures that compile cleanly and still teach something false |
|
||
|
||
## Using it as an agent skill
|
||
|
||
`SKILL.md` is the entry point; the `references/` files are loaded on demand. Point your
|
||
agent runtime at this directory (for Claude Code, symlink or copy it under
|
||
`~/.claude/skills/`). The skill assumes `scripts/` and `assets/` sit beside it.
|
||
|
||
## Why the build script fails on warnings
|
||
|
||
Two LaTeX warnings produce a figure that is quietly wrong rather than visibly broken:
|
||
`Missing character` (a CJK glyph silently dropped — the label just is not there) and
|
||
`Overfull \hbox` (text escaping its reserved lane and landing on a tensor). `build.sh`
|
||
greps for both and exits non-zero. A `Package supertensor Warning` — an undeclared role
|
||
falling back to gray — is treated the same way.
|
||
|
||
The flow layout adds two of its own: an object that overflows its band, and a `\stcol`
|
||
whose contents do not add up to the height it declared (which means it is drawn
|
||
off-center). Both are things a reader would have to notice for you.
|
||
|
||
A clean build still proves nothing about collisions, hue budget or whether the math is
|
||
right. That is what `references/checklist.md` is for.
|
||
|
||
## Provenance
|
||
|
||
Extracted from the `tensor-formula-viz` skill in `wdkns-skills`, which remains in place
|
||
unchanged. The prose rules that could be enforced mechanically became macros; the rest
|
||
became `references/`.
|