- scripts/lint.py: reject raw rectangles, absolute coordinates, hue-budget and callout/group/formula-order violations at the source level - tests/invalid/ + tests/lint-invalid/: negative fixtures proving the package and linter reject bad input; test.sh now runs both directions - references/fallback.md: degraded path when no LaTeX is available - tests/group-callout.tex: exercise \stgroup and \stcallout - agents/openai.yaml: agent config - Docs and .sty updated to match
73 lines
4.4 KiB
Markdown
73 lines
4.4 KiB
Markdown
# Anti-patterns
|
||
|
||
Every figure below compiles cleanly. `build.sh` is happy with all of them. They are still
|
||
wrong, because the compiler checks TeX syntax and not whether the picture is true.
|
||
|
||
Render `examples/antipatterns.tex` and look at
|
||
`examples/build/antipatterns.png` once before your first figure.
|
||
|
||
## 1. The transpose that only changed its label
|
||
|
||
A face captioned `Kᵀ` that is still `T × d_h`. The reader looks for the contracted axis,
|
||
finds two faces of the same height, and concludes the contraction runs along the wrong
|
||
dimension. **Fix:** swap the arguments — `\ststack{KT}{...}{dh}{T}{3}`. See `geometry.md` §3.
|
||
|
||
## 2. Shards that do not tile their parent
|
||
|
||
Two shards drawn with a gap, or stretched to fill a parent whose other shards were elided.
|
||
Both assert a width that the tensor does not have. **Fix:** draw the shards in one band
|
||
and give every shard after the first `gap=0pt`, which *states* that they are adjacent
|
||
instead of arranging for it; draw an ellipsis for anything omitted. See `geometry.md` §5–6.
|
||
|
||
## 3. An index drawn as a heatmap
|
||
|
||
Expert ids or token positions rendered with a lightness ramp. The ramp is a magnitude
|
||
channel, so it says `expert 3 > expert 0`, which is meaningless. **Fix:** `\stindexface`.
|
||
See `semantics.md`.
|
||
|
||
Same family: a Boolean mask drawn with graded cells (it has one level, not three), and a
|
||
score matrix drawn as flat blocks (it has magnitude, and hiding it wastes the figure).
|
||
|
||
## 4. One pale level everywhere
|
||
|
||
A whole tensor in `role!10`. At full size it looks tasteful; at thumbnail size — which is
|
||
how it will be seen on a slide — it is a blank rectangle. **Fix:** three separated levels,
|
||
`role!30 / role!55 / role!80`. Contrast comes from lightness, not saturation.
|
||
See `style.md`.
|
||
|
||
## Not in the gallery, but just as common
|
||
|
||
- **Periodic texture.** A polynomial hash reduced mod 3 repeats every 3 rows, and the eye
|
||
reads the resulting stripe as real structure. `pattern=dense` avoids it; if you write
|
||
your own filler, check that rows 1, 2, 4, 5 of a tall face are not identical.
|
||
- **A label wider than its connector.** The white underlay then covers the target tensor.
|
||
`\stlink` makes this unrepresentable: the label reserves its own width in the band and
|
||
the arrow is drawn to whatever lands beside it. See `layout.md`.
|
||
- **A new hue for a regrouped view of the same data.** `X` and the per-expert buffers
|
||
gathered out of `X` are the same object in a different order; a second hue claims they
|
||
are different tensors.
|
||
- **Captions hanging at different depths** because the faces in a row have different
|
||
heights. Use `\strow`/`\strowend`, which arms `\stlane` for you.
|
||
- **Hand-tuned offsets.** Each one is a magic number valid only for the content that was
|
||
there when you tuned it; the figure that breaks is the *next* one, when a label grows two
|
||
characters and lands on a face. Use the cursor. See `layout.md`.
|
||
- **A formula line placed first.** It can only be centered on a figure whose width is not
|
||
known yet, so it ends up visibly off-center. Call `\sttopformula` after the bands.
|
||
- **A floating commentary card between two operands.** If it is not a real operation, it
|
||
belongs in the stage subtitle, the bottom box, or a `\stcallout` beside the whole band.
|
||
A card anchored to a single face reads as a step in the computation, and two cards on one
|
||
band turn the figure into a dashboard; both are lint errors.
|
||
- **A callout that should have been the meaning box.** If the card is taller than the band
|
||
it hangs off, it is not an aside — it is the **Mechanism** row, and leaving it as a card
|
||
only opens white space, since the callout pushes the vertical cursor below itself.
|
||
- **A group border used as decoration.** `\stgroup` names its members as one composite
|
||
object; drawn around whatever happened to be adjacent, it invents a grouping the
|
||
computation does not have. If you cannot caption the outline, do not draw it.
|
||
- **A group whose hue invents a new object.** The outline around the three `q` sheets is
|
||
still `q`. A fresh hue there claims a fourth tensor exists; use the members' role, or
|
||
`neutral` when the members really are of mixed roles. See `semantics.md`.
|
||
- **A meaning box that repeats the shapes.** The shapes are already under every block. The
|
||
box is for what the axes *mean* and what the operation *does*.
|
||
- **Solving crowding by shrinking type.** The type hierarchy is a hard floor; move the
|
||
stage to another row instead.
|