spine-rigc 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +21 -0
- package/README.md +323 -224
- package/bin/rigc.cjs +40 -0
- package/cli.ts +558 -49
- package/docs/AUTHORING.md +60 -23
- package/docs/PROMPTING.md +106 -0
- package/docs/SPEC_COVERAGE.md +16 -14
- package/package.json +4 -2
- package/src/compile.ts +189 -142
- package/src/emit.ts +88 -0
- package/src/json-position.ts +253 -0
- package/src/png.ts +72 -7
- package/src/preview.ts +243 -0
- package/src/render.ts +58 -0
- package/src/types.ts +8 -0
- package/src/validate.ts +58 -13
- package/tools/plate.ts +164 -21
package/docs/AUTHORING.md
CHANGED
|
@@ -29,22 +29,27 @@ that can see that, and a run that skips it has verified nothing about the motion
|
|
|
29
29
|
attachment, keying practice, curve kind, draw order — sourced from Spine's own
|
|
30
30
|
public documentation: **§10**
|
|
31
31
|
|
|
32
|
+
If you were given no brief and no reference frames, this section does not apply to
|
|
33
|
+
you — skip to **§0**. You are rigging somebody's own art rather than reproducing a
|
|
34
|
+
measured shot, so none of what follows applies: it is the ladder's protocol, not a
|
|
35
|
+
property of the tool.
|
|
36
|
+
|
|
32
37
|
🔒 **A ladder run reads this guide in full and does not follow its references out of
|
|
33
38
|
it.** The guide is allowed reading; not everything it cites is. Citations here are
|
|
34
39
|
provenance for a reader of record — the loop that hit a trap, the issue that closed it —
|
|
35
40
|
and following one can arrive at a stored candidate's own spec, at the corpus inventory,
|
|
36
|
-
or at the gate a verdict is read against, none of which a run may
|
|
41
|
+
or at the **derivation** of the gate a verdict is read against, none of which a run may
|
|
42
|
+
open. ⭐ The gate's **clause statements** are a different matter and a run may read them:
|
|
43
|
+
they are in `docs/GATE.md`, item 11 of the allowed list (owner ruling 2026-08-29) — the
|
|
44
|
+
measure, the comparator, the number and the SKIP semantics, with no recorded figure in it.
|
|
45
|
+
So: read the
|
|
37
46
|
document, take its numbered sections as the input, and leave its footprints to whoever
|
|
38
47
|
is maintaining it. The rule this states is that an **allowed-reading surface has to be
|
|
39
48
|
closed under reading**; the criterion behind it is under *The honesty rule* in
|
|
40
|
-
[LADDER.md](LADDER.md), and the enumerated allowed and forbidden lists are in
|
|
49
|
+
[LADDER.md](https://github.com/firejune/rigc/blob/main/docs/LADDER.md), and the enumerated allowed and forbidden lists are in
|
|
41
50
|
`bench/runs/README.md`, *What a run may read* — the prompt that starts a run quotes them
|
|
42
51
|
outright, which is the copy that binds.
|
|
43
52
|
|
|
44
|
-
If you were given no brief and no frames — you are rigging somebody's own art rather
|
|
45
|
-
than reproducing a measured shot — none of this applies to you. It is the ladder's
|
|
46
|
-
protocol, not a property of the tool.
|
|
47
|
-
|
|
48
53
|
## The vocabulary is Spine's
|
|
49
54
|
|
|
50
55
|
Wherever rigc has no better abstraction it uses **Spine 4.3's own concept, its own
|
|
@@ -80,6 +85,10 @@ bun cli.ts check \
|
|
|
80
85
|
|
|
81
86
|
# read the table → fix the spec → build again → check again
|
|
82
87
|
# ↳ read its per-frame column before its MAE — §9.2
|
|
88
|
+
|
|
89
|
+
# …and if nobody gave you frames, LOOK at it instead — neither needs a reference:
|
|
90
|
+
bun cli.ts render --candidate path/to/spine # PNG frames + a contact sheet grid
|
|
91
|
+
bun cli.ts preview --candidate path/to/spine # one .html that plays it in Spine's own player
|
|
83
92
|
```
|
|
84
93
|
|
|
85
94
|
`build` compiles, round-trips the result through `@esotericsoftware/spine-core`,
|
|
@@ -112,16 +121,26 @@ What the flags mean:
|
|
|
112
121
|
| `--rig` | the rig spec — skeleton structure |
|
|
113
122
|
| `--motion` | the motion spec — time |
|
|
114
123
|
| `--out` | directory for `skeleton.json` + `skeleton.atlas`; atlas page paths are written relative to it |
|
|
124
|
+
| `--copy-images` | `build` only: also copies every referenced page PNG into `--out` and rewrites the atlas to the copies, so the directory is self-contained enough to zip or commit on its own. Default is unchanged — page paths still point at the source art (issue #217) |
|
|
115
125
|
| `--images` | where the rig spec's `image` names resolve (overrides the rig's own `images` field, and is relative to your working directory) |
|
|
116
126
|
| `--manifest` | a cut manifest. Only for a rig with **measured art** behind it; a foreign skeleton has none |
|
|
117
|
-
| `--profile` | `spine` = the 20 validity rules · `spine-html` = all 34
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
| `--profile` | `spine` = the 20 validity rules (**the default**) · `spine-html` = all 34, opt-in |
|
|
128
|
+
| `--candidate` | `check`, `bench`, `render` and `preview` only: a **compiled** artifact — the directory `build --out` wrote, or a `skeleton.json` path. `--atlas <path>` names the atlas when it does not sit beside the skeleton |
|
|
129
|
+
| `--animation` | `render` and `preview` only: which animation to show. The default is **every** one for `render` and the **first** for `preview`. A name the skeleton does not have is refused, with the ones it does have listed |
|
|
130
|
+
|
|
131
|
+
`render` also takes `--fps <n>` (the rate it samples at, default 12 — the same
|
|
132
|
+
protocol rate the reference frames use) and `--max <px>` (the long side of a
|
|
133
|
+
frame, default 256). Both commands take `--out`: a directory for `render`
|
|
134
|
+
(default `render/`), the `.html` file for `preview` (default `preview.html`).
|
|
135
|
+
|
|
136
|
+
Pick the profile deliberately, and know which one you got by saying nothing. The
|
|
137
|
+
default is `spine`: "is this valid Spine 4.3 that any runtime plays correctly",
|
|
138
|
+
which is the question a rig authored anywhere is asking. `--profile spine-html`
|
|
139
|
+
adds one renderer's policy and one project's canvas budget on top, and those
|
|
140
|
+
extra rules fire on perfectly correct Spine data (clipping attachments,
|
|
141
|
+
unweighted meshes, packed atlases) — reach for it when you are shipping into
|
|
142
|
+
*that* project, not to be thorough. A report always prints which profile ran and
|
|
143
|
+
lists what that profile left out, on `PROF` lines.
|
|
125
144
|
|
|
126
145
|
The other commands:
|
|
127
146
|
|
|
@@ -131,6 +150,8 @@ bun cli.ts validate path/to/spine # re-gate artifacts already on
|
|
|
131
150
|
bun cli.ts diff candidate.json reference.json
|
|
132
151
|
bun cli.ts check --candidate path/to/spine --frames path/to/frames
|
|
133
152
|
bun cli.ts bench 3 --candidate path/to/spine [--frames path/to/frames]
|
|
153
|
+
bun cli.ts render --candidate path/to/spine [--animation …] [--fps 12] [--max 256]
|
|
154
|
+
bun cli.ts preview --candidate path/to/spine [--animation …] [--out preview.html]
|
|
134
155
|
```
|
|
135
156
|
|
|
136
157
|
- **`explain`** is the one to reach for when a rig compiles but looks wrong. It
|
|
@@ -144,12 +165,26 @@ bun cli.ts bench 3 --candidate path/to/spine [--frames path/to/frames]
|
|
|
144
165
|
for opposite fixes. A measure with nothing to compare says `0/0` and says so.
|
|
145
166
|
- **`check`** renders your candidate into the reference frames' own pixel grid and
|
|
146
167
|
compares pixels — the only thing here that can see a wrong animation. **§9.**
|
|
147
|
-
- **`bench <rung>`** runs one rung of [the benchmark ladder](LADDER.md): validate
|
|
168
|
+
- **`bench <rung>`** runs one rung of [the benchmark ladder](https://github.com/firejune/rigc/blob/main/docs/LADDER.md): validate
|
|
148
169
|
under `--profile spine`, then diff against that rung's reference export, and with
|
|
149
170
|
`--frames` the `check` table as well. Unlike the three above it is a **finish
|
|
150
171
|
line, not a loop**: it opens the reference export, so a run that consults it and
|
|
151
172
|
then edits is no longer an authoring run. `check` carries no such restriction —
|
|
152
173
|
see §9.
|
|
174
|
+
- 🚨 **`render` and `preview` are how you LOOK at what you built**, and they are
|
|
175
|
+
the two that need no reference at all. Reach for them the moment a rig compiles
|
|
176
|
+
green, because green says nothing about the picture: a head that sits visibly
|
|
177
|
+
off its torso passes every assertion, loads in `spine-core` and steps
|
|
178
|
+
numerically clean — the offsets are the ones you asked for, and nothing in the
|
|
179
|
+
gate can know you did not mean them. `render` writes
|
|
180
|
+
`render/<animation>/f0000.png…` with a `contact.png` grid of **every** frame
|
|
181
|
+
beside them (open that one first — spacing is a comparison across frames) and a
|
|
182
|
+
`frames.json` sidecar naming the world box they are pictures of. `preview`
|
|
183
|
+
writes one self-contained `.html`: your skeleton, atlas and page PNGs are
|
|
184
|
+
embedded in it as data URIs and played by the official **Spine Web Player**, so
|
|
185
|
+
double-clicking it is also the interop proof — what plays there was played by
|
|
186
|
+
Esoteric Software's runtime, not by rigc's. The player is loaded from a CDN
|
|
187
|
+
rather than copied into the file, so the first open needs a network.
|
|
153
188
|
|
|
154
189
|
---
|
|
155
190
|
|
|
@@ -294,7 +329,7 @@ must be non-empty. `slots` must be present (it may be empty).
|
|
|
294
329
|
payloads in this guide are written to illustrate a field, never copied out of a
|
|
295
330
|
reference export — an example lifted from one would be handing an authoring agent an
|
|
296
331
|
answer to the rung it is standing on, which is the rule §10.6 states and the honesty
|
|
297
|
-
rule in [LADDER.md](LADDER.md) turns on. If a snippet here matches a reference file,
|
|
332
|
+
rule in [LADDER.md](https://github.com/firejune/rigc/blob/main/docs/LADDER.md) turns on. If a snippet here matches a reference file,
|
|
298
333
|
that is a defect in this guide: report it. (It has happened — 2026-08-23; the incident
|
|
299
334
|
is recorded in `bench/runs/README.md`, *What a run may read*.)
|
|
300
335
|
|
|
@@ -482,10 +517,10 @@ and takes every slot below it out of the frame. rigc refuses a name the rig does
|
|
|
482
517
|
not declare. Omitting `end` entirely is the format's own way of saying "clip
|
|
483
518
|
everything after this one", and is left alone.
|
|
484
519
|
|
|
485
|
-
🚫 Under
|
|
520
|
+
🚫 Under `--profile spine-html` a clipping attachment is refused by
|
|
486
521
|
`A11_NO_CLIPPING_ATTACHMENTS` — that renderer skips them silently, so a mask that
|
|
487
|
-
was supposed to hide something would not. It is valid Spine and
|
|
488
|
-
accepts it; the refusal is policy, not validity.
|
|
522
|
+
was supposed to hide something would not. It is valid Spine and the default
|
|
523
|
+
`--profile spine` accepts it; the refusal is policy, not validity.
|
|
489
524
|
|
|
490
525
|
### 3.5 `constraints` — 4.3's single typed array
|
|
491
526
|
|
|
@@ -650,7 +685,7 @@ stepped.
|
|
|
650
685
|
declared duration `6.5` never fired at all against an accumulated
|
|
651
686
|
`6.499999999999994` — which read as a frame-change disagreement the pose series had
|
|
652
687
|
already fixed, and cost that run three builds
|
|
653
|
-
([`2026-08-26-rung5-1`](
|
|
688
|
+
([`2026-08-26-rung5-1`](https://github.com/firejune/rigc/blob/main/bench/runs/2026-08-26-rung5-1/LOOP.md), §8). ⇒ **For a
|
|
654
689
|
stepped timeline, write `T − 1e-6` rather than `T`.** One grid step early cannot
|
|
655
690
|
reach the previous sample — 83,333 µs away at 12 fps — and is always seen by the
|
|
656
691
|
sample it was written for; one ULP late loses the frame. This is the same asymmetry
|
|
@@ -867,7 +902,7 @@ The report prints one line per assertion:
|
|
|
867
902
|
| `A16_SKELETON_VERSION_4_3` | both | the `skeleton.spine` label is not on the 4.3 line (`4.3`, `4.3.N`, `4.3.N-suffix`) |
|
|
868
903
|
| `A17_ATLAS_PAGE_FILES_EXIST` | both | a page the atlas declares is not a file. Check `--images` and `--out` |
|
|
869
904
|
| `A18_DETERMINISTIC_EMIT` | both | a second compile of the same inputs differed. That is a compiler bug, not a spec bug — report it |
|
|
870
|
-
| `A19_OVERLAY_PNGS_HAVE_ALPHA` | renderer | an overlay
|
|
905
|
+
| `A19_OVERLAY_PNGS_HAVE_ALPHA` | renderer | an overlay part image can never be transparent: no alpha channel (colour type 4 or 6) and no `tRNS` chunk either, so it would paint a solid rectangle over what is behind it. Re-export it as RGBA, or as an indexed / greyscale PNG that keeps its `tRNS`. Only the full-stage base plate may be opaque. Indexed-with-`tRNS` — the usual output of ImageMagick, "Export as PNG-8", GIMP's indexed mode, aseprite and pngquant — **passes**: it is transparent art |
|
|
871
906
|
| `A20_MESH_WEIGHTS_COHERENT` | both ◑ | a weighted vertex with no bone, a negative weight, a bone index out of range, or weights that do not sum to 1. Under `spine-html` also: an unweighted mesh, or a binding at weight 0 |
|
|
872
907
|
| `A21_MESH_RIM_PINNED` | archetype | a generated ring's rim, or a ribbon's entry row, is not pinned to its anchor bone at weight 1 |
|
|
873
908
|
| `A22_MESH_UVS_IN_UNIT_RANGE` | both | a mesh UV outside its region, or a UV array that disagrees with the vertex count |
|
|
@@ -922,6 +957,8 @@ Two more limits that are not errors but will shape what you can attempt:
|
|
|
922
957
|
## 7. Before you call it done
|
|
923
958
|
|
|
924
959
|
1. `build --profile <the one you meant>` exits 0 and the report has **no FAIL**.
|
|
960
|
+
Saying nothing means `spine`, so "the one you meant" is a decision either way —
|
|
961
|
+
the report's first line names the profile that judged it.
|
|
925
962
|
2. Read the `SKIP` lines. Each one is a check that did *not* run — make sure none of
|
|
926
963
|
them is a check you were relying on.
|
|
927
964
|
⚠️ Under `--profile spine` a foreign skeleton usually produces **no SKIP lines
|
|
@@ -1557,13 +1594,13 @@ that drew the reference frames, onto the same pixel grid, and reports what diffe
|
|
|
1557
1594
|
you specifically: it means **you may run `check` as often as you like** without
|
|
1558
1595
|
your run ceasing to be an honest authoring run. It is a loop, in the way `build` is
|
|
1559
1596
|
a loop. `bench` and `diff` against a rung's export are not — they read the answer,
|
|
1560
|
-
and [the ladder's honesty rule](LADDER.md) makes them a finish line you reach once.
|
|
1597
|
+
and [the ladder's honesty rule](https://github.com/firejune/rigc/blob/main/docs/LADDER.md) makes them a finish line you reach once.
|
|
1561
1598
|
|
|
1562
1599
|
📌 **That is also why the MAE figures quoted through this section stay.** Every one of
|
|
1563
1600
|
them is a candidate's own reading against rendered frames — the exam question, not the
|
|
1564
1601
|
answer key — so none of them narrows a reference-side measure, and a guide that censored
|
|
1565
1602
|
them would be teaching less for no gain in honesty. The criterion is under *The honesty
|
|
1566
|
-
rule* in [LADDER.md](LADDER.md) (issue #158); what it *does* seal is a score written
|
|
1603
|
+
rule* in [LADDER.md](https://github.com/firejune/rigc/blob/main/docs/LADDER.md) (issue #158); what it *does* seal is a score written
|
|
1567
1604
|
over a reference's own count, and no such figure appears here.
|
|
1568
1605
|
|
|
1569
1606
|
🚨 **If you drive the runtime yourself, a bone's local transform lives on
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Prompting an AI to author with rigc
|
|
2
|
+
|
|
3
|
+
This page is for the person **operating** an AI agent — any AI agent — that will
|
|
4
|
+
author a rig with rigc. It is not authoring guidance; that is
|
|
5
|
+
[AUTHORING.md](AUTHORING.md), and the agent should read that file, not this one.
|
|
6
|
+
This page tells you what to put in the prompt, and it earns its claims from a
|
|
7
|
+
measured case: in August 2026 a deliberately small model — Gemini 3.7 Flash on
|
|
8
|
+
the Antigravity harness — authored a benchmark rung unattended for three hours,
|
|
9
|
+
and every stumble below is one it actually made, priced by the instruments in
|
|
10
|
+
[PILOT.md](https://github.com/firejune/rigc/blob/main/docs/PILOT.md)'s protocol. A large model makes fewer of these mistakes
|
|
11
|
+
unprompted; the clauses cost you three lines and make the small model's run
|
|
12
|
+
land and the large model's run land cleaner.
|
|
13
|
+
|
|
14
|
+
## The prompt skeleton
|
|
15
|
+
|
|
16
|
+
For ordinary use (not a benchmark), the whole prompt is short:
|
|
17
|
+
|
|
18
|
+
> Author a Spine rig with rigc for <what you want>. The images are in
|
|
19
|
+
> `<dir>`. Read `docs/AUTHORING.md` in full before writing either spec —
|
|
20
|
+
> sections 1–5 are the two file formats and the failure map, section 8 is how
|
|
21
|
+
> to fit poses against picture references, section 10 is the editor's
|
|
22
|
+
> conventions. Build with `rigc build`, keep going until `rigc validate` is
|
|
23
|
+
> green, and treat every named failure as pointing at the file to change.
|
|
24
|
+
|
|
25
|
+
Then add the clauses below. If you are running the **benchmark**, do not
|
|
26
|
+
improvise a prompt at all — hand the agent
|
|
27
|
+
[pilot/rung3-runner-prompt.md](https://github.com/firejune/rigc/blob/main/docs/pilot/rung3-runner-prompt.md) verbatim; it
|
|
28
|
+
carries the honesty rule, and an improvised summary of that rule is how a run
|
|
29
|
+
stops being scorable.
|
|
30
|
+
|
|
31
|
+
## Five clauses the pilot paid for
|
|
32
|
+
|
|
33
|
+
**1. Any search loop must print progress and carry a time-box.**
|
|
34
|
+
The pilot wrote a pose-fitting script with no output and no bound, and its
|
|
35
|
+
operator spent part of the evening deciding whether a silent 99 %-CPU process
|
|
36
|
+
was working or hung. (It was working — but nobody could tell.) Say:
|
|
37
|
+
|
|
38
|
+
> Long-running scripts must print one progress line per unit of work and state
|
|
39
|
+
> an expected total up front. If a search would exceed ten minutes, stop and
|
|
40
|
+
> narrow it instead.
|
|
41
|
+
|
|
42
|
+
**2. Intermediate results go to files, not scrollback.**
|
|
43
|
+
The pilot's first fitters printed results to stdout; a crashed step would have
|
|
44
|
+
lost the lot. It later switched to JSON files on its own — start there. Say:
|
|
45
|
+
|
|
46
|
+
> Write measured values (placements, angles, fitted poses) to files in the
|
|
47
|
+
> working directory as you go. Treat your transcript as disposable.
|
|
48
|
+
|
|
49
|
+
**3. Point the fitting method at AUTHORING §8, by number.**
|
|
50
|
+
Given frames to match, the pilot's first instinct was a nested grid over every
|
|
51
|
+
knob at once — tens of thousands of renders per frame. §8 describes the cheap
|
|
52
|
+
loop (one knob at a time, render back, keep what the measurement keeps). The
|
|
53
|
+
pilot had the file "in hand" and did not apply the section until it had burned
|
|
54
|
+
hours. Say:
|
|
55
|
+
|
|
56
|
+
> Fit poses the way AUTHORING §8 does — one variable at a time against a
|
|
57
|
+
> render-back measurement. Do not grid-search several knobs jointly.
|
|
58
|
+
|
|
59
|
+
**4. Keys are structure, not samples.**
|
|
60
|
+
A fitter produces one pose per frame, and the pilot keyed nearly every one of
|
|
61
|
+
them. The result *placed* its parts well — and still scored poorly on every
|
|
62
|
+
timing measure, because animation data is sparse keys plus interpolation
|
|
63
|
+
(AUTHORING §10.3–§10.4), and a key on every frame is a pixel transcription
|
|
64
|
+
wearing a skeleton. Say:
|
|
65
|
+
|
|
66
|
+
> Key extremes and contacts, then let curves carry the in-betweens, per
|
|
67
|
+
> AUTHORING §10.3–10.4. If your fitted poses disagree with a curve, move the
|
|
68
|
+
> curve, not key count. Also §4.4: when a bone's two axes need different
|
|
69
|
+
> timing or easing, key the single-axis timelines, not the paired one.
|
|
70
|
+
|
|
71
|
+
**5. Keep the loop log live.**
|
|
72
|
+
The pilot wrote its `LOOP.md` at the end, from memory — two entries for a
|
|
73
|
+
three-hour session, with eight generations of fitting scripts invisible
|
|
74
|
+
between them. A log written afterwards records the story, not the work. Say:
|
|
75
|
+
|
|
76
|
+
> Append to `LOOP.md` at the moment each build/measure/change step happens,
|
|
77
|
+
> not at the end. One line per step is enough.
|
|
78
|
+
|
|
79
|
+
**6. Make the agent typecheck its own helper scripts.**
|
|
80
|
+
Bun strips types and runs, so an agent can call methods that do not exist and
|
|
81
|
+
watch the script fail — or worse, silently misbehave — without ever learning
|
|
82
|
+
the API was imagined. The pilot left behind a helper written against
|
|
83
|
+
spine-core methods that were never real; the repository's `typecheck` gate
|
|
84
|
+
caught it at landing, hours too late to help the run. Say:
|
|
85
|
+
|
|
86
|
+
> After writing any helper script, run `bunx tsc --noEmit <file>` (or the
|
|
87
|
+
> project's `typecheck` task) before trusting its output.
|
|
88
|
+
|
|
89
|
+
## What you do not need to say
|
|
90
|
+
|
|
91
|
+
The same pilot, unprompted, did all of this correctly: it looped
|
|
92
|
+
`build → validate` until green and read the named failures as pointers; it ran
|
|
93
|
+
the whole thing without a human answer for three hours; it killed its own
|
|
94
|
+
stray processes; it recorded its model name honestly; and under the benchmark
|
|
95
|
+
protocol it ran the scored diff exactly once, at the end, editing nothing
|
|
96
|
+
after. The tool's own error surface carries that part of the conversation —
|
|
97
|
+
prompt for the five clauses above and then let the agent work.
|
|
98
|
+
|
|
99
|
+
## If you are scoring the run
|
|
100
|
+
|
|
101
|
+
That is a different document: [PILOT.md](https://github.com/firejune/rigc/blob/main/docs/PILOT.md) is the protocol,
|
|
102
|
+
`pilot/rung3-runner-prompt.md` is the exact prompt, and the evaluator sheet it
|
|
103
|
+
names is for the judge only. The one rule that reaches this page: **never put
|
|
104
|
+
baseline figures, reference structure, or previous runs' measures into the
|
|
105
|
+
runner's prompt** — a number in the prompt is a target, and a run that aimed
|
|
106
|
+
at a target measured nothing.
|
package/docs/SPEC_COVERAGE.md
CHANGED
|
@@ -5,18 +5,20 @@ what rigc emits today, and what the official example projects actually use — s
|
|
|
5
5
|
ordered by what the benchmark ladder needs rather than by the spec's alphabet.
|
|
6
6
|
|
|
7
7
|
Reproduce the measurements with `bun run fetch-examples && bun run bench:usage`
|
|
8
|
-
([`bench/count_features.ts`](
|
|
9
|
-
[`feature_matrix.json`](feature_matrix.json)).
|
|
8
|
+
([`bench/count_features.ts`](https://github.com/firejune/rigc/blob/main/bench/count_features.ts) → [`feature_matrix.csv`](https://github.com/firejune/rigc/blob/main/docs/feature_matrix.csv),
|
|
9
|
+
[`feature_matrix.json`](https://github.com/firejune/rigc/blob/main/docs/feature_matrix.json)).
|
|
10
10
|
|
|
11
11
|
> 🔼 **This note is dated and does not move; the measurements below are the corpus as it
|
|
12
12
|
> stood on 2026-08-22 and stay as written. Its statements about what rigc *does* have gone
|
|
13
|
-
> stale in five places, and the live ledger is [LADDER.md](LADDER.md):**
|
|
13
|
+
> stale in five places, and the live ledger is [LADDER.md](https://github.com/firejune/rigc/blob/main/docs/LADDER.md):**
|
|
14
14
|
>
|
|
15
15
|
> - **B2 is fixed** — A16 accepts `4.3`, `4.3.N` and `4.3.N-<suffix>`, so all twelve example
|
|
16
16
|
> exports pass it.
|
|
17
|
-
> - **The profile split exists** — `--profile spine | spine-html`, default `spine
|
|
18
|
-
>
|
|
19
|
-
>
|
|
17
|
+
> - **The profile split exists** — `--profile spine | spine-html`, **default `spine` since
|
|
18
|
+
> 2026-08-29** (issue #221; it was `spine-html` when this survey was written), so the nine
|
|
19
|
+
> renderer-policy assertions of §2.2 no longer apply to foreign data, and no longer apply
|
|
20
|
+
> unasked. That closes the validator half of B3; the emitter half (no packer, no atlas
|
|
21
|
+
> importer) is untouched.
|
|
20
22
|
> - **`walkTimelines` reaches all eleven groups** — §2.3 item 1 and §4.3 item 4 are done, so
|
|
21
23
|
> A05 is no longer blind to `ik` / `transform` / `path` / `slider` / `drawOrder` /
|
|
22
24
|
> `drawOrderFolder` / `events`.
|
|
@@ -25,7 +27,7 @@ Reproduce the measurements with `bun run fetch-examples && bun run bench:usage`
|
|
|
25
27
|
> attachments, the 4.3 typed constraint array and the invariants, all as data. So §2.4's
|
|
26
28
|
> "the bone tree is code, not data", §4.0's B1 row and executive-summary item 7 describe a
|
|
27
29
|
> state that no longer exists. Rung 3 transcribed into that format scores 1.000 on every
|
|
28
|
-
> measure of every section — figures in [LADDER.md](LADDER.md).
|
|
30
|
+
> measure of every section — figures in [LADDER.md](https://github.com/firejune/rigc/blob/main/docs/LADDER.md).
|
|
29
31
|
> - Since that change rigc also emits **ik and transform constraints**, the **single-axis bone
|
|
30
32
|
> timelines** (`translatex`/`translatey`/`scalex`/`scaley`/`shear`/`shearx`/`sheary`), bone
|
|
31
33
|
> `length`/`scale`/`shear`/`inherit`/`skin`/`color` setup fields, slot `dark`/`blend`, region
|
|
@@ -659,7 +661,7 @@ This is the split Part 4(c) needs. **Spine-validity** = the file is wrong for an
|
|
|
659
661
|
| `A12_NO_DARK_COLOR` | **renderer-profile** | slot `dark`, `rgba2`/`rgb2` timelines — "parsed, then ignored" |
|
|
660
662
|
| `A13_MESH_BUDGET` | **renderer-profile** | >4 mesh slots, >80 triangles per mesh |
|
|
661
663
|
| `A14_NO_FULL_FRAME_MESH` | **renderer-profile** | a mesh spanning the whole stage |
|
|
662
|
-
| `A19_OVERLAY_PNGS_HAVE_ALPHA` | **renderer-profile** | an overlay page
|
|
664
|
+
| `A19_OVERLAY_PNGS_HAVE_ALPHA` | **renderer-profile** | an overlay page that can never be transparent — no alpha channel and no `tRNS` chunk |
|
|
663
665
|
| `A20_MESH_WEIGHTS_COHERENT` | **renderer-profile / archetype** | **unweighted meshes**, weights not summing to 1, out-of-range bone indices |
|
|
664
666
|
| `A21_MESH_RIM_PINNED` | archetype | ring/ribbon rim not pinned |
|
|
665
667
|
| `A22_MESH_UVS_IN_UNIT_RANGE` | validity-ish | UVs outside 0..1 |
|
|
@@ -716,7 +718,7 @@ one.
|
|
|
716
718
|
|
|
717
719
|
> 🔼 Both halves of that paragraph are now stale. The walker reaches all eleven groups and the
|
|
718
720
|
> mutants that prove it exist; the suite runs on fixtures it **generates**, so it needs no
|
|
719
|
-
> project's art. Current shape: [CLAUDE.md](
|
|
721
|
+
> project's art. Current shape: [CLAUDE.md](https://github.com/firejune/rigc/blob/main/CLAUDE.md), *The selftest and its fixtures*.
|
|
720
722
|
|
|
721
723
|
### 2.4 The input model — where the rig actually comes from
|
|
722
724
|
|
|
@@ -751,10 +753,10 @@ The manifest supplies *positions* for those bones (`anchors`), never their *name
|
|
|
751
753
|
## Part 3 — what the example ladder actually uses
|
|
752
754
|
|
|
753
755
|
Corpus: the nine official example projects on branch `4.3`, fetched by
|
|
754
|
-
[`scripts/fetch-examples.sh`](
|
|
756
|
+
[`scripts/fetch-examples.sh`](https://github.com/firejune/rigc/blob/main/scripts/fetch-examples.sh) into the gitignored `examples/<name>/`
|
|
755
757
|
(**12 skeleton JSON files** — some examples ship more than one — **10 `.atlas` files**, 8 `license.txt`).
|
|
756
|
-
Counted by [`bench/count_features.ts`](
|
|
757
|
-
[`feature_matrix.json`](feature_matrix.json) and [`feature_matrix.csv`](feature_matrix.csv)
|
|
758
|
+
Counted by [`bench/count_features.ts`](https://github.com/firejune/rigc/blob/main/bench/count_features.ts); full output in
|
|
759
|
+
[`feature_matrix.json`](https://github.com/firejune/rigc/blob/main/docs/feature_matrix.json) and [`feature_matrix.csv`](https://github.com/firejune/rigc/blob/main/docs/feature_matrix.csv)
|
|
758
760
|
(12 rows × 135 columns), both regenerated by `bun run bench:usage`.
|
|
759
761
|
|
|
760
762
|
> ⚠️ **Verification note.** The timeline columns below were re-derived independently from the raw JSON
|
|
@@ -913,7 +915,7 @@ Crossing Part 2 with Part 3. Categories, as requested:
|
|
|
913
915
|
**(d) JSON-inexpressible** — things the format genuinely cannot hold.
|
|
914
916
|
|
|
915
917
|
**Nothing below was implemented when this was written. This is a survey.** Three of its items
|
|
916
|
-
have been built since — see the banner at the top of this document and [LADDER.md](LADDER.md) for
|
|
918
|
+
have been built since — see the banner at the top of this document and [LADDER.md](https://github.com/firejune/rigc/blob/main/docs/LADDER.md) for
|
|
917
919
|
which; the requirement text itself is left exactly as surveyed.
|
|
918
920
|
|
|
919
921
|
### 4.0 Three blockers that precede rung 1
|
|
@@ -977,7 +979,7 @@ Nothing structurally new (attachment timeline, blend, inherit all arrived by run
|
|
|
977
979
|
#### Rung 6 — `6-arcs`
|
|
978
980
|
|
|
979
981
|
> ✅ **Measured, 2026-08-23.** The rows below were written as predictions; the
|
|
980
|
-
> transcription in [`bench/transcriptions/6-arcs/`](
|
|
982
|
+
> transcription in [`bench/transcriptions/6-arcs/`](https://github.com/firejune/rigc/tree/main/bench/transcriptions/6-arcs/)
|
|
981
983
|
> settled them. It compiles green under `--profile spine` and `bench 6` reports
|
|
982
984
|
> **1.000 on all 44 measures in all six sections**, so the rig spec expresses this
|
|
983
985
|
> skeleton — weighted meshes, `edges` and the 4.3 transform constraints alike. A
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spine-rigc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Rig compiler for Spine — declarative rig specs in, Spine 4.3 skeleton data out, verified by a spine-core round-trip. Built so AI agents can author rigs and check their own work; the output imports into the Spine editor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"rigc": "./
|
|
7
|
+
"rigc": "./bin/rigc.cjs"
|
|
8
8
|
},
|
|
9
9
|
"engines": {
|
|
10
10
|
"bun": ">=1.2.0"
|
|
@@ -31,12 +31,14 @@
|
|
|
31
31
|
"cli"
|
|
32
32
|
],
|
|
33
33
|
"files": [
|
|
34
|
+
"bin/rigc.cjs",
|
|
34
35
|
"cli.ts",
|
|
35
36
|
"src",
|
|
36
37
|
"tools/plate.ts",
|
|
37
38
|
"tools/font5x7.ts",
|
|
38
39
|
"docs/AUTHORING.md",
|
|
39
40
|
"docs/SPEC_COVERAGE.md",
|
|
41
|
+
"docs/PROMPTING.md",
|
|
40
42
|
"NOTICE.md"
|
|
41
43
|
],
|
|
42
44
|
"publishConfig": {
|