Add source linter, negative test fixtures, and fallback guidance

- 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
This commit is contained in:
dela
2026-08-05 16:41:22 +08:00
parent 7b59c81d02
commit 866173a831
34 changed files with 786 additions and 54 deletions
+18 -3
View File
@@ -34,6 +34,7 @@ Overlap is allowed only inside one declared composite:
- shards tiling a parent,
- outline sheets in one `\ststack`,
- a bracket around its own tensor,
- a `\stgroup` outline around its own members,
- a connector endpoint touching its source/target border.
Every other intersection or occlusion is forbidden.
@@ -68,9 +69,23 @@ Stage headings share one left rail. `\ststage` puts them there: the rail is a si
`x` (`\stleftrail` to move it), and the `y` is derived from the lowest ink drawn so far, so
a heading can neither drift right nor collide with the row above it.
Explanatory prose belongs in the stage subtitle, the bottom box, or above its own
connector. Never drop a floating commentary card between two operands unless it is a real
operation node (`st comm`).
Explanatory prose belongs in the stage subtitle, the bottom box, above its own connector,
or on a `\stcallout` card hanging off the right edge of a band. Never drop a floating
commentary card between two operands unless it is a real operation node (`st comm`).
`\stcallout` is that rule made structural: it refuses to open inside a band, the linter
rejects it unless it is anchored to a `\strow` name, and a second card on one band is an
error — side-by-side cards are a dashboard, not a figure. A card that ends up much taller
than its band is telling you the same thing the overflow warning does: that text is not an
aside, it is the **Mechanism** row of `\stmeaningbox`.
## Composites
`\stcol` and `\stgroup` are the two sub-flows, and both exist so that a *relationship* can
be stated rather than arranged for. A group wraps its members from the inside, which is
what makes an arrow attach to the outline rather than end inside it — a connector whose
endpoint is a member but which crosses the group border is the ordinary version of "a
connector may not cross a box that is not its endpoint".
## Layers