rig-parts 1.5.3 → 1.5.5

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 CHANGED
@@ -69,7 +69,7 @@ only as a development dependency, and an install of rig-c gates a build with
69
69
  its own validator. rig-parts does not install it either; it is this repository's
70
70
  development dependency, at the version rig-c develops against, for the round
71
71
  trip in the selftest and CI and the selftest's posing oracle.
72
- rig-c's [NOTICE.md](https://github.com/firejune/rigc/blob/main/NOTICE.md)
72
+ rig-c's [NOTICE.md](https://github.com/rig-c/core/blob/main/NOTICE.md)
73
73
  sets out the chain in full; briefly, as a restatement of Esoteric Software's
74
74
  terms and not a term of this project:
75
75
 
@@ -96,16 +96,29 @@ ships none and downloads none, and the terms that govern an image they produce
96
96
  are the terms of those models. A painting from any other source works the same
97
97
  way.
98
98
 
99
- The images this repository ships — `assets/demo-*` and `assets/sample-parts.png`
100
- — and the public examples' paintings were generated with
101
- `ponyDiffusionV6XL_v6StartWithThisOne.safetensors`,
102
- [Pony Diffusion V6 XL](https://civitai.com/models/257749), with no LoRA. The
103
- checkpoint itself is not redistributed. **[observed 2026-09-27]** CivitAI's model
104
- API reported for it `allowCommercialUse: ["Image", "RentCivit"]`,
105
- `allowNoCredit: false`, `allowDerivatives: true` and
106
- `allowDifferentLicense: false`: generated images may be used commercially and
107
- the model must be credited, which this line and the
108
- [spine-parts-examples](https://github.com/firejune/spine-parts-examples) README do.
99
+ The images this repository ships, and the public examples' paintings, were
100
+ generated with one of two checkpoints, with no LoRA; neither checkpoint is
101
+ redistributed.
102
+
103
+ - `assets/demo-*` and the `demo` example's painting (since issue #227):
104
+ `hassakuXLIllustrious_v13StyleA.safetensors`,
105
+ [Hassaku XL (Illustrious)](https://civitai.com/models/140272) v1.3 Style A, by
106
+ Ikena. Credit, as sharing it requires: *Painted with Hassaku XL (Illustrious)
107
+ v1.3 Style A by Ikena (https://civitai.com/models/140272), Fair AI Public
108
+ License 1.0-SD.* **[observed 2026-10-11]** The model page's version and licence
109
+ section reads "All Models using the Fair AI Public License 1.0-SD license", and
110
+ CivitAI's model API reported `allowCommercialUse: ["RentCivit", "Rent", "Image"]`,
111
+ `allowNoCredit: false`, `allowDerivatives: true` and `allowDifferentLicense: false`.
112
+ - `assets/sample-parts.png` and the `scarf`, `reference-sample` and `reference-demo`
113
+ paintings: `ponyDiffusionV6XL_v6StartWithThisOne.safetensors`,
114
+ [Pony Diffusion V6 XL](https://civitai.com/models/257749). **[observed
115
+ 2026-09-27]** CivitAI's model API reported for it `allowCommercialUse: ["Image",
116
+ "RentCivit"]`, `allowNoCredit: false`, `allowDerivatives: true` and
117
+ `allowDifferentLicense: false`: generated images may be used commercially and
118
+ the model must be credited, which this line does.
119
+
120
+ The [parts-examples](https://github.com/rig-c/parts-examples) README records
121
+ both, beside each character's generation record.
109
122
 
110
123
  ## 4. Behaviour reimplemented, not code copied
111
124
 
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  are written.** rig-parts takes a single character painting and the layers
5
5
  [See-through](https://github.com/shitagaki-lab/see-through) decomposed it into,
6
6
  merges them into measured rig-space parts, authors weighted meshes, bone chains
7
- and a looping idle over them in [rig-c](https://github.com/firejune/rigc)'s
7
+ and a looping idle over them in [rig-c](https://github.com/rig-c/core)'s
8
8
  spec, and hands that spec to rig-c to compile, gate, pack, render and check.
9
9
  It is built for agents that cannot see the image: every stage prints named,
10
10
  numeric findings, a refusal names the object, the value found and the value
@@ -14,57 +14,45 @@ input is silent.
14
14
  ## What you get
15
15
 
16
16
  <p align="center">
17
- <img src="https://raw.githubusercontent.com/firejune/rig-parts/main/assets/demo-source.png" alt="The demo painting: a generated full-body character in a white and pink frilled dress with long pink twin tails, standing with her hands clasped" height="420" />
18
- <img src="https://raw.githubusercontent.com/firejune/rig-parts/main/assets/demo-idle.png" alt="The same character rigged, breathing, blinking once and swaying her hair, sleeves and skirt in a four-second loop" height="420" />
17
+ <img src="https://raw.githubusercontent.com/rig-c/parts/main/assets/demo-source.png" alt="The demo painting: a generated full-body character in a white and pink idol dress with a layered skirt and long pink twin tails, standing with her arms held away from her body and her hands open" height="420" />
18
+ <img src="https://raw.githubusercontent.com/rig-c/parts/main/assets/demo-idle.png" alt="The same character rigged, breathing, blinking once and swaying her hair, sleeves and skirt in a four-second loop" height="420" />
19
19
  </p>
20
20
 
21
21
  <p align="center">
22
- <img src="https://raw.githubusercontent.com/firejune/rig-parts/main/assets/demo-parts.png" alt="Contact sheet of the painting and the 22 assembled parts it was split into: hair, dress, sleeves, shoes, face, eyes, brows, mouth and ornaments" width="100%" />
22
+ <img src="https://raw.githubusercontent.com/rig-c/parts/main/assets/demo-parts.png" alt="Contact sheet of the painting and the 23 assembled parts it was split into: hair, sleeves, legs, boots, neck, skirt, bodice, earrings, hair ornaments, ears, face, brows, mouth and eyes" width="100%" />
23
23
  </p>
24
24
 
25
25
  <p align="center"><em>
26
- The painting was generated for this repository with a public checkpoint (Pony
27
- Diffusion V6 XL) and no LoRA; its generation record, See-through layers and licence
28
- are in <a href="https://github.com/firejune/spine-parts-examples">spine-parts-examples</a>
29
- (that repository keeps the name it was published under before this package's rename).
26
+ The painting was generated for this repository with a public checkpoint (Hassaku XL
27
+ (Illustrious) v1.3 Style A, by Ikena, Fair AI Public License 1.0-SD) and no LoRA, on a
28
+ pose that holds the hands apart, then given one hand-detailer pass; its generation
29
+ record, See-through layers and licence are in
30
+ <a href="https://github.com/rig-c/parts-examples">parts-examples</a>.
30
31
  See-through ran twice, once on the whole figure and once on a square head crop.
31
- Then one command: <code>rig-parts build --seam silhouette --loop</code>. The
32
- proposer's bones, meshes, regions and motion were used <b>unedited</b>. Two input-stage
33
- edits were made by hand for the reference run this example reproduces: the head box
34
- was shifted down into the canvas (its proposal ran 118 px above the top edge;
35
- <code>propose --head-box</code> now makes that shift itself), and <code>hair_back</code>
36
- is taken from the full run, because the twin tails leave the head crop sideways
37
- (a plan edit). <code>check</code> printed, verbatim:<br/>
32
+ Then one command: <code>rig-parts build --loop</code>. The proposer's bones, meshes,
33
+ regions and motion were used as proposed but for one correction, written in the
34
+ config beside the values it replaced: the two outer skirt chains were moved out to
35
+ 0.8 of the skirt's half-width (the proposal's, within 90 px of the centre of a skirt
36
+ 449 px wide, swung it about its middle and failed <code>TIP_OVER_ROOT</code>, 0.442
37
+ against 1.4725; moved, 2.425). One input-stage edit: <code>hair_back</code> is taken
38
+ from the full run, because the twin tails leave the head crop sideways (a plan edit).
39
+ <code>check</code> printed, verbatim:<br/>
38
40
  <code>50 assertions: 24 measured (24 passed, 0 failed), 26 skipped, 0 not in profile "spine-html"</code><br/>
39
41
  <code>loop: idle 49 frame(s) at 12 fps, f0000 vs f0048 (t = 4s): max |d| 0 (0 required)</code><br/>
40
- <code>seam: setup pose at 714x1216, scale 0.9422: mean |d| 0.234 (&lt;= 1.0), 2 px over 40, 2.25 rig px (the count / s²; &lt;= 50), 0 px over 80 (reported)</code><br/>
41
- <code>pack: skeleton.png 922x1348, 22 region(s), 94.9% covered, padding 2, page edges free, shape polygon</code><br/>
42
- <code>--seam silhouette</code> repaired the navy blobs the default rule leaves on the white
43
- blouse (recomposite error pixels 10,340 → 8,644); the default stays
44
- <code>near-white</code>, the reference implementation's rule, so the examples stay
45
- comparable with it. The loop is <code>rig-parts loop --palette</code>'s indexed APNG, 48 frames at
46
- 12 fps, 1,706,719 bytes, one 256-entry palette at a measured error of max 57, mean 1.601
42
+ <code>seam: setup pose at 654x1216, scale 0.9438: mean |d| 0.147 (&lt;= 1.0), 0 px over 40, 0.00 rig px (the count / s²; &lt;= 50), 0 px over 80 (reported)</code><br/>
43
+ <code>pack: skeleton.png 1051x972, 23 region(s), 96.9% covered, padding 2, page edges free, shape polygon</code><br/>
44
+ The loop is <code>rig-parts loop --palette</code>'s indexed APNG, 48 frames at
45
+ 12 fps, 827,857 bytes, one 256-entry palette at a measured error of max 65, mean 0.879
47
46
  per channel over every frame (the lossless APNG beside it, the exactness record, is
48
- 13,645,503 bytes; the GIF, at the same error, 1,812,288). Frame 29 (2.417 s) is the
49
- closed eye: the blink holds for 0.084 s, one 12 fps frame rounded up, where the
50
- reference implementation held 0.04 s and no frame of its loop showed the eyes shut
51
- (issue #32); the painting is shown at half size, resampled and written
52
- by this package's PNG codec (nothing here encodes JPEG). <code>rig-parts sheet</code>
53
- made the contact sheet.
47
+ 5,832,634 bytes; the GIF, at the same error, 889,063). Frame 29 (2.417 s) is the
48
+ closed eye: the blink holds for 0.084 s, one 12 fps frame rounded up; the painting is
49
+ shown at half size, resampled and written by this package's PNG codec (nothing here
50
+ encodes JPEG). <code>rig-parts sheet</code> made the contact sheet. Its
51
+ <code>expected/</code> is this port's own build (<a href="examples/demo/README.md">examples/demo</a>).
54
52
  </em></p>
55
53
 
56
- <p align="center">
57
- <img src="https://raw.githubusercontent.com/firejune/rig-parts/main/assets/sample-parts.png" alt="Contact sheet of the sample character's painting and its 20 parts" width="560" />
58
- </p>
59
-
60
54
  <p align="center"><em>
61
- The plain fixture, <code>examples/sample</code>: same checkpoint, no LoRA, and a rig
62
- built from its own proposal with no hand edit at all —
63
- <code>seam: setup pose at 379x1216, scale 1.0116: mean |d| 0.204 (&lt;= 1.0), 2 px over 40, 1.95 rig px (the count / s²; &lt;= 50), 0 px over 80 (reported)</code>, loop max |d| 0.
64
- </em></p>
65
-
66
- <p align="center"><em>
67
- The hanging element, <code>examples/scarf</code>: same checkpoint, no LoRA, a very long
55
+ The hanging element, <code>examples/scarf</code>: Pony Diffusion V6 XL, no LoRA, a very long
68
56
  red scarf whose ends hang free, and the first character run through this pipeline
69
57
  with its proposal used unedited — the only hand corrections are four
70
58
  <code>assemble.patches</code>, each answering an <code>uncovered hole</code> line.
@@ -73,6 +61,15 @@ switched to the contour mode. It has no reference output: its <code>expected/</c
73
61
  is this port's own build (<a href="examples/scarf/README.md">examples/scarf</a>).
74
62
  </em></p>
75
63
 
64
+ <p align="center"><em>
65
+ Two more characters are tracked as fixtures and not shown:
66
+ <code>examples/reference-demo</code> and <code>examples/reference-sample</code>, the two
67
+ the reference implementation ran (published as <code>demo</code> and <code>sample</code>
68
+ until issue #227, which took the clasped-hands painting off display). Their
69
+ <code>expected/</code> is that implementation's own output, which the selftest holds
70
+ this port to.
71
+ </em></p>
72
+
76
73
  ## What it takes in
77
74
 
78
75
  - **One painting** — a PNG of one character, front-facing, full body, taller than
@@ -102,7 +99,7 @@ page** (issue #2):
102
99
 
103
100
  | path under `--out` | what |
104
101
  | --- | --- |
105
- | `check/build/skeleton.json`, `skeleton.atlas`, `skeleton.png` | **the artifact** — Spine 4.3 skeleton data and one packed page, written by `rigc build --pack --page-edges free --pack-shape polygon` and gated under `spine-html`, which holds every rule `spine` measures (on the demo, rigc 2.1.3 and 2.10.1: the 14 rules `validate --profile spine` measures are among the build's 24; 16 are not in `spine`) |
102
+ | `check/build/skeleton.json`, `skeleton.atlas`, `skeleton.png` | **the artifact** — Spine 4.3 skeleton data and one packed page, written by `rigc build --pack --page-edges free --pack-shape polygon` and gated under `spine-html`, which holds every rule `spine` measures (on reference-demo, rigc 2.1.3 and 2.10.1: the 14 rules `validate --profile spine` measures are among the build's 24; 16 are not in `spine`) |
106
103
  | `parts/*.png`, `parts.json`, `recomposite_rig.png`, `recomposite_error_rig.png` | the loose parts, each cropped to its alpha box; the record of where every part came from, how many of its pixels were re-taken from the painting, and the recomposite's uncovered holes with their boxes; the flat stack of parts; its error map — red where no part covers a pixel the painting has, blue where a part covers it in the wrong colour |
107
104
  | `rig/` | `rig.json` and `motion.json` in rig-c's spec, `mesh_report.json`, the padded `images/` |
108
105
  | `check/` | both gate files verbatim, the idle's frames and their `geometry.json` (skinned vertices per frame), `contact.png`, `motion_heat.png`, `check.json` (with `pack_mode`, the `--page-edges` and `--pack-shape` the page was packed under) |
@@ -110,7 +107,7 @@ page** (issue #2):
110
107
 
111
108
  The last lines of a green build are the pack line, printed beside the Spine example
112
109
  export's `spineboy.png` as a yardstick (a reference, not a bar), and the three
113
- artifact paths — here for `examples/sample`:
110
+ artifact paths — here for `examples/reference-sample`:
114
111
 
115
112
  ```
116
113
  build: PASS — the packed atlas is the artifact; parts/ and rig/ are the intermediates it was made from
@@ -121,7 +118,7 @@ build: PASS — the packed atlas is the artifact; parts/ and rig/ are the interm
121
118
  ```
122
119
 
123
120
  The page's edges are free by default: rigc picks the least-area page the parts need,
124
- not the next power of two. On the two examples, packed by rectangles, that is 967x1338
121
+ not the next power of two. On the two reference examples, packed by rectangles, that is 967x1338
125
122
  and 479x1166, where a power-of-two page is 1024x2048 and 512x2048, and covered goes from 56.3 % to 91.2 % and
126
123
  from 49.7 % to 93.4 %. The cost is the one rigc's help states: *"region attachments
127
124
  sampling within 1 LSB of the loose build rather than exactly"*. Measured on both
@@ -148,9 +145,9 @@ atlas written by anything else would have no oracle behind it.
148
145
 
149
146
  | stage | tool | what it owns |
150
147
  | --- | --- | --- |
151
- | painting + See-through layers → parts and specs | **rig-parts** | the merge of two runs, the measurements, the rig spec and motion spec |
152
- | specs → Spine skeleton data | **[rig-c](https://github.com/firejune/rigc)** | compile, the gate (rigc's own validator in an install; the round trip through `spine-core` where the runtime is beside it, as in this repository's CI), the named assertions, the packer, the renderer |
153
- | skeleton data → a page | **[rig-play](https://github.com/firejune/rig-play)** (formerly spine-html), a sibling project | a DOM renderer; rigc's `spine-html` profile is its policy, and every build here is gated under that profile as well as under `spine` |
148
+ | painting + See-through layers → parts and specs | **rig-parts** (npm `@rig-c/parts`) | the merge of two runs, the measurements, the rig spec and motion spec |
149
+ | specs → Spine skeleton data | **[rig-c](https://github.com/rig-c/core)** (npm `rig-c`) | compile, the gate (rigc's own validator in an install; the round trip through `spine-core` where the runtime is beside it, as in this repository's CI), the named assertions, the packer, the renderer |
150
+ | skeleton data → a page | **[rig-play](https://github.com/rig-c/play)** (npm `@rig-c/play`; formerly spine-html), a sibling project | a DOM renderer; rigc's `spine-html` profile is its policy, and every build here is gated under that profile as well as under `spine` |
154
151
 
155
152
  rig-parts never writes Spine data itself. Everything on disk under `check/build/`
156
153
  was written by rig-c after its own gate passed.
@@ -192,8 +189,8 @@ head run on `st_input_head.png` is what gives the eyes more pixels
192
189
  **See-through is required; ComfyUI is not.** The wrapper is one route among
193
190
  four, and `rig-parts comfy` is only a convenience for that route: every
194
191
  stage after See-through reads files, whichever route wrote them. On the two
195
- public examples each run took 171–199 s through the wrapper (each run's
196
- `meta.json`, in [spine-parts-examples](https://github.com/firejune/spine-parts-examples)).
192
+ reference examples each run took 171–199 s through the wrapper, and on the demo 179 s (each run's
193
+ `meta.json`, in [parts-examples](https://github.com/rig-c/parts-examples)).
197
194
 
198
195
  ### The two images See-through is fed: `inputs`
199
196
 
@@ -346,9 +343,9 @@ for each — a config fragment, the `check` lines it passes with, and its limit:
346
343
  image; `check` measures the idle alone.
347
344
  - [**A soft region driven by physics**](docs/AUTHORING.md#recipe-a-soft-region-driven-by-physics)
348
345
  (a bust, the hips): a bone the config authors, a contour-mode region that hands it the patch,
349
- and a `physics` constraint on it; `examples/sample` carries one. Under the sample's slow
346
+ and a `physics` constraint on it; `examples/reference-sample` carries one. Under its slow
350
347
  4 s idle the bust moves at most 0.066 rig px and the hips not at all: the spring answers
351
- faster keys on the body. The sample's `hop`, a named animation keying only `hip`, moves the
348
+ faster keys on the body. Its `hop`, a named animation keying only `hip`, moves the
352
349
  bust up to 6.583 and the hips up to 4.432 rig px; the region's `band` caps how far a patch may
353
350
  go before the texture-stretch ceiling, and `check` measures the idle alone.
354
351
 
@@ -357,15 +354,16 @@ for each — a config fragment, the `check` lines it passes with, and its limit:
357
354
  `parts.json` splits each part's opaque pixels (`opaque_px`) into `visible_px` — no
358
355
  later layer of its See-through run is opaque in front of them — and `occluded_px`,
359
356
  and counts the visible ones whose colour was not taken from the painting
360
- (`visible_not_projected_px`). On the three public examples, from the totals of their
357
+ (`visible_not_projected_px`). On the four examples, from the totals of their
361
358
  `expected/parts.json` (the default `--project core`; `scarf`'s painting patches are
362
359
  whole painting pixels, so they count as taken):
363
360
 
364
361
  | | opaque px | occluded | visible, not projected | taken from the painting |
365
362
  | --- | --- | --- | --- | --- |
366
- | `sample` | 298,363 | 79,122 (26.5 %) | 35,979 (12.1 %) | 183,262 (61.4 %) |
367
- | `demo` | 765,924 | 202,343 (26.4 %) | 75,626 (9.9 %) | 487,955 (63.7 %) |
363
+ | `demo` | 362,441 | 69,098 (19.1 %) | 67,164 (18.5 %) | 226,179 (62.4 %) |
368
364
  | `scarf` | 283,813 | 78,503 (27.7 %) | 56,699 (20.0 %) | 148,611 (52.4 %) |
365
+ | `reference-sample` | 298,363 | 79,122 (26.5 %) | 35,979 (12.1 %) | 183,262 (61.4 %) |
366
+ | `reference-demo` | 765,924 | 202,343 (26.4 %) | 75,626 (9.9 %) | 487,955 (63.7 %) |
369
367
 
370
368
  The occluded share is art the painting does not show — a back-hair layer, a neck, the
371
369
  parts of an ear under the hair — and is See-through's synthesis by necessity; it is
@@ -373,30 +371,33 @@ what the decomposition is for. The visible-but-not-projected share is synthesis
373
371
  the painting was there to be taken: a part too thin for the reference rule's 5x5
374
372
  eroded core, an anti-aliased fringe below alpha 250, a rim beside a layer in front, a
375
373
  pixel refused for drift. `--project visible` keeps the erosion only along a rim with a
376
- layer in front, which takes that share to 22,476 (7.5 %) on `sample` and 49,672 (6.5 %)
377
- on `demo` (from the `parts.json` of a `--project visible` build). On the eleven thin
374
+ layer in front, which takes that share to 22,476 (7.5 %) on `reference-sample` and 49,672 (6.5 %)
375
+ on `reference-demo` (from the `parts.json` of a `--project visible` build). On the eleven thin
378
376
  head parts — brows, lashes, irises, eye whites, ears, mouth — it takes 296 of
379
- `sample`'s 1,289 visible pixels where `core` takes 110, and 824 of `demo`'s 2,162
377
+ `reference-sample`'s 1,289 visible pixels where `core` takes 110, and 824 of `reference-demo`'s 2,162
380
378
  where `core` takes 343. What neither rule takes is the fringe: a per-pixel
381
379
  classification of those parts under `visible`, recorded with the change that added
382
- the flag, puts 813 of `sample`'s 993 still-unprojected pixels and 879 of `demo`'s
380
+ the flag, puts 813 of `reference-sample`'s 993 still-unprojected pixels and 879 of `reference-demo`'s
383
381
  1,338 below alpha 250. Where such a fringe keeps the stack off the painting and a part
384
382
  beneath holds the pixel in the painting's colour, `assemble` clears it instead, and
385
383
  the assemble line and `parts.json` say how many pixels, of which part, over which
386
384
  (AUTHORING §5, *The fringe push-back*; the figures in this section were measured
387
- before it, at v0.14.0).
385
+ before it, at v0.14.0, but for the `demo` row, which is its `expected/parts.json`
386
+ as this port wrote it in issue #227).
388
387
 
389
388
  ## Requirements
390
389
 
391
- [Bun](https://bun.sh) 1.2 or later. `npm install -g rig-parts` installs the
392
- `rig-parts` command; it hands off to Bun and says so in one sentence if Bun is not
393
- on `PATH`. **`rig-parts` is the package's name; versions up to 0.16.0 were published
390
+ [Bun](https://bun.sh) 1.2 or later. `npm i -D @rig-c/parts` installs the
391
+ `rig-parts` command (`npm install -g @rig-c/parts` puts it on `PATH`); it hands off
392
+ to Bun and says so in one sentence if Bun is not on `PATH`. **`@rig-c/parts` is the
393
+ package's name; versions 1.0.0-rc.1 to 1.5.3 were published as `rig-parts`, and
394
+ versions up to 0.16.0
394
395
  as `spine-parts`, its former name**, and the install keeps a `spine-parts` command
395
396
  beside `rig-parts` for the transition, the same launcher under both names. On npm
396
- the alias `spine-parts` stays published beside `rig-parts` at every version,
397
+ both former names stay published beside `@rig-c/parts` at every version, as aliases
397
398
  carrying the same files with only the `name` in `package.json` changed, so a
398
- project that depends on the former name keeps receiving every release; a new
399
- install names `rig-parts` ([RELEASING.md](RELEASING.md), *The registry side*). rig-c
399
+ project that depends on either keeps receiving every release; a new
400
+ install names `@rig-c/parts` ([RELEASING.md](RELEASING.md), *The registry side*). rig-c
400
401
  comes with it as a dependency. No Spine runtime does: since
401
402
  rig-c 2.0 the installed `rigc` gates every build with its own validator over the
402
403
  compiled model document, and `rigc --version` says `entry: cli_core.ts —
package/docs/AUTHORING.md CHANGED
@@ -6,18 +6,25 @@ the files it writes. Every refusal the tool prints names a rule, an object, the
6
6
  value found and the value required — §6 maps each rule to the field or input that
7
7
  has to change.
8
8
 
9
- The worked example throughout is [`examples/sample`](../examples/sample): its
9
+ The worked example throughout is [`examples/reference-sample`](../examples/reference-sample): its
10
10
  `config.json` is a complete, loading config, `proposal.json` is what the proposer
11
11
  wrote for it, and `expected/` is what the reference implementation produced from
12
12
  the same inputs — except `check.json`, which this port's `build` regenerates since
13
13
  the reference has no judgement lines (§7). `bun run fetch-examples` puts its painting and See-through layers
14
- into `examples/sample/inputs/`.
14
+ into `examples/reference-sample/inputs/`.
15
+
16
+ The examples' names: `reference-sample` and `reference-demo` are the two characters
17
+ the reference implementation ran (published as `sample` and `demo` until issue #227),
18
+ kept as fixtures because their `expected/` is that implementation's own output; every
19
+ figure this guide quotes for them was measured on them. `demo` is the painting the
20
+ README shows since issue #227 and `scarf` the hanging-element example; both have
21
+ `expected/` from this port's own build, and a figure quoted for them says so.
15
22
 
16
23
  ## 1. Prerequisites
17
24
 
18
25
  | what | why | how |
19
26
  | --- | --- | --- |
20
- | [Bun](https://bun.sh) 1.2 or later | rig-parts and rig-c are Bun programs | `npm install -g rig-parts` installs the command; it says so if Bun is missing |
27
+ | [Bun](https://bun.sh) 1.2 or later | rig-parts and rig-c are Bun programs | `npm install -g @rig-c/parts` installs the command; it says so if Bun is missing |
21
28
  | [rig-c](https://www.npmjs.com/package/rig-c) | compiles, gates, packs and renders every rig; rig-parts writes no Spine data itself | installed with rig-parts as a dependency (`node_modules/.bin/rigc`); with no Spine runtime beside it, it gates with its own validator, and `rigc --version` says `entry: cli_core.ts` |
22
29
  | [See-through](https://github.com/shitagaki-lab/see-through), somewhere | the layer decomposition is the input | any route in README *Getting See-through layers*; it runs twice per character, outside this tool |
23
30
  | a GPU, wherever See-through runs | See-through is a diffusion model | nothing in rig-parts itself uses a GPU |
@@ -244,8 +251,8 @@ box every rule scales by is derived from the head run's hair (`front hair`,
244
251
  `back hair`: their highest top) and its `neck` (its top, and its centre x for the
245
252
  axis): with `L` the span from the hair's top to the neck's top, the face is
246
253
  1.067 `L` tall, its top 0.131 `L` below the hair's, its width 0.798 of its height.
247
- Those ratios are the means of the two public examples (`demo` 1.073 / 0.105 /
248
- 0.820, `sample` 1.061 / 0.158 / 0.777) — a sample of two. On each example
254
+ Those ratios are the means of the two public examples (`reference-demo` 1.073 / 0.105 /
255
+ 0.820, `reference-sample` 1.061 / 0.158 / 0.777) — a sample of two. On each example
249
256
  re-assembled without its face, the derived box put `head` and `neck` within
250
257
  5.0 px (0.038 face heights) of the with-face proposal's, `chest` and `hip` at
251
258
  the same pixel. The first note says so —
@@ -270,7 +277,7 @@ Two rules read the figure rather than one tag, and each says so in a note:
270
277
  0.8 of the shoulders — or `hip from 0.32 of figure height (no waist found: …)`,
271
278
  naming why. Without `bottomwear` the hip is 0.32 of the figure height, as before
272
279
  (`no bottomwear: hip from 0.32 of figure height`). Neither published example
273
- meets either branch: their hips sit at 0.436 (`demo`) and 0.342 (`sample`) of
280
+ meets either branch: their hips sit at 0.436 (`reference-demo`) and 0.342 (`reference-sample`) of
274
281
  their figures.
275
282
  - **Clasped hands.** When every `handwear` part together is one blob (over
276
283
  500 px) at most half the shoulders' width and centred within a quarter of it
@@ -289,7 +296,7 @@ sub-shape of the layer's **pendant rows** (the run of rows at the bottom narrowe
289
296
  than 35 % of its widest row; the whole layer for `earwear` or a layer that is over
290
297
  80 % pendant) that is at least **3×** as tall as wide, at least **0.2** of the
291
298
  layer's height and at least **10** rows. On the public examples nothing is one: the
292
- demo's hairpin pendant sub-shapes measure 0.54 and 0.89 tall-per-wide and its
299
+ reference-demo's hairpin pendant sub-shapes measure 0.54 and 0.89 tall-per-wide and its
293
300
  earrings 1.04 and 1.08, so both proposals are unchanged. Every layer with strands
294
301
  gets exactly one note carrying each strand's column centroid, first–last row and
295
302
  width, and what became of it (two of the selftest's fixtures, PR12 and PR15):
@@ -323,7 +330,7 @@ the eyewhite's top with no art across its whole width, the lowest such row is pr
323
330
  `motion.blink.still` on `head`, and the rows above it stop blinking; when it has none, the
324
331
  note says so and nothing is cut — clear a row between the crease and the lash line in the
325
332
  part, or leave the crease to blink. The cut has to be a clear row: two pieces cut through
326
- art are each resampled against their own transparent edge, and on the demo example a cut
333
+ art are each resampled against their own transparent edge, and on the reference-demo example a cut
327
334
  through its lash line changed 36 px of the setup-pose render (up to 7 levels, at render
328
335
  scale 0.942) and up to 21 levels in the idle frames where the head rolls; a clear-row cut
329
336
  changed none, at rest or rolled. The eye bone is not moved: scaling about the eyewhite's
@@ -442,23 +449,23 @@ crescent; the other four 1.5 or less). No cell refused overshoot, and along each
442
449
  a margin passed every larger one passed — where the offset this replaced moved an acute corner
443
450
  up to 4 × margin and closed the window from above. That is the generated shapes: on a real part
444
451
  a larger margin can close a gap whose enclosed pocket lies further from the art than the bound,
445
- which the overshoot check refuses (the demo's hairpin builds at margin 1 and refuses at 1.5, 2
452
+ which the overshoot check refuses (reference-demo's hairpin builds at margin 1 and refuses at 1.5, 2
446
453
  and 3: 5.39 px). On the public examples at tolerance 1, margin 1, `stray` 4 and spacing = the
447
- part's grid, 13 of the 14 mesh parts build; the 14th is the demo's earring, two pieces.
454
+ part's grid, 13 of the 14 mesh parts build; the 14th is reference-demo's earring, two pieces.
448
455
 
449
- **When not to use it.** A part that is two pieces (the demo's earring: 411 and 358 px) — keep
456
+ **When not to use it.** A part that is two pieces (reference-demo's earring: 411 and 358 px) — keep
450
457
  the lattice, which bridges islands, or split the part. And a part nothing deforms locally: at
451
458
  tolerance 1 the contour outline is dense, and on the examples' 13 parts the contour mesh used
452
- more vertices than the lattice at the same spacing (demo 1785 against 1431, sample 974 against
453
- 852) while enclosing 5.8 and 9.8 times less transparent area (demo 25078 against 144782 px², sample
459
+ more vertices than the lattice at the same spacing (reference-demo 1785 against 1431, reference-sample 974 against
460
+ 852) while enclosing 5.8 and 9.8 times less transparent area (reference-demo 25078 against 144782 px², reference-sample
454
461
  6563 against 64445), with thinner triangles — smallest angles 2.46°–11.31° against the lattice's
455
- 12.09°–45° (#106). Switched, every part that builds: the sample passes `check` (9 of 9;
456
- `TEXTURE_STRETCH` 1.227 → 1.384, ceiling 1.927); the demo's gate is green but `check` refuses
462
+ 12.09°–45° (#106). Switched, every part that builds: reference-sample passes `check` (9 of 9;
463
+ `TEXTURE_STRETCH` 1.227 → 1.384, ceiling 1.927); reference-demo's gate is green but `check` refuses
457
464
  `TEXTURE_STRETCH` on its back hair (2.535: an edge of a contour triangle squeezed to 0.394 of
458
465
  its length in the idle), and with the back hair left on the lattice it passes 9 of 9 (1.388 →
459
466
  1.68).
460
467
 
461
- **Why the demo's back hair fails, and what passes** (issue #115). The squeezed edge is an
468
+ **Why reference-demo's back hair fails, and what passes** (issue #115). The squeezed edge is an
462
469
  outline edge 2 px long, near the hair's tip, whose two ends sit either side of a step in the
463
470
  weight field: one end keeps `hairback_l1` at 0.031, the other drops it, because a weight under
464
471
  0.03 is dropped (`src/weights.ts`, the reference's `>= 0.03`). `hairback_l1` and `hairback_r2`
@@ -469,7 +476,7 @@ gives 1.316 on the contour mesh and 1.336 on the lattice: the lattice's 36 px ed
469
476
  step, the outline's 2 px edges show it. Interior vertices cannot change it — an outline edge is
470
477
  in every triangulation — so the background spacing does not move the figure (36, 24, 18 and
471
478
  12 px all give 2.535). Raising `tolerance` to 1.5 removes every short edge across a step (the
472
- shortest is then 8.2 px) and the part passes (1.345; with every buildable demo part switched,
479
+ shortest is then 8.2 px) and the part passes (1.345; with every buildable reference-demo part switched,
473
480
  `check` passes 9 of 9 at 1.68), at 313 vertices against the lattice's 268 and 18155.5 px²
474
481
  enclosed against 58346. The window is one value wide on this part: 1.25 keeps the same 2 px
475
482
  edge (2.535) and 1.75 leaves art uncovered at margin 1. No other switched part of either
@@ -481,7 +488,7 @@ generated fixture of `tools/local_compare.ts` it reached a local shape error (0.
481
488
  in #106, the same figures).
482
489
 
483
490
  **On real parts the generated result did not carry over unchanged** (issues #107 and #110,
484
- `bun tools/real_compare.ts --work <dir> --examples demo,sample --builds --sweep`, a declared test region on two demo
491
+ `bun tools/real_compare.ts --work <dir> --examples reference-demo,reference-sample --builds --sweep`, a declared test region on two reference-demo
485
492
  parts — a place to measure, not a claim about the painting; the region spacing chosen by vertex
486
493
  count alone). On `bottomwear` (a region of radius 65 px inside the part) the contour mesh passes
487
494
  the same rule: 336 vertices against the lattice's 352, largest local shape error 1.535 px against
@@ -922,7 +929,7 @@ that crosses the region with no point of it inside to split at — is still stop
922
929
  ### Recipe: expressions and other named animations
923
930
 
924
931
  The package proposes no expression and keys nothing but the idle; what it gives is a rig whose
925
- face is bones (`eye_r`, `eye_l`, `brow_r`, `brow_l`, `mouth` on `sample`) and one door for
932
+ face is bones (`eye_r`, `eye_l`, `brow_r`, `brow_l`, `mouth` on `reference-sample`) and one door for
926
933
  animations you write over them, `motion.animations_from` (the row above, issue #183). Write a
927
934
  file in rig-c's motion-spec shape beside the config and name it:
928
935
 
@@ -941,8 +948,8 @@ file in rig-c's motion-spec shape beside the config and name it:
941
948
  ```
942
949
 
943
950
  `build` writes `surprised` into `rig/motion.json` after `idle`, gates it with the rig, and
944
- `check` names it on a line of its own (`examples/sample` carries one, `animations.json` with `hop`, the
945
- recipe below). With exactly this file beside `examples/sample`'s config in its place,
951
+ `check` names it on a line of its own (`examples/reference-sample` carries one, `animations.json` with `hop`, the
952
+ recipe below). With exactly this file beside `examples/reference-sample`'s config in its place,
946
953
  `build` printed (this tree, rig-c as `package.json` pins it):
947
954
 
948
955
  ```
@@ -963,7 +970,7 @@ passed rigc's gate and nothing else — no seam, stretch or hole bar has read it
963
970
 
964
971
  A jiggle (a bust, the hips) is a patch of one part that lags behind the body. The package
965
972
  proposes none and judges none; what it gives is the three pieces to build one, all in the
966
- config. `examples/sample` carries a worked one (issue #183, PR #187), and its config is the
973
+ config. `examples/reference-sample` carries a worked one (issue #183, PR #187), and its config is the
967
974
  fragment below, cut to the bust:
968
975
 
969
976
  ```jsonc
@@ -983,14 +990,14 @@ fragment below, cut to the bust:
983
990
  bone and no constraint; it is yours, and nothing keys it — the constraint moves it.
984
991
  - **A region in a `contour` (or `auto`) mesh** that hands the patch to that bone: weight 1
985
992
  inside the shape, falling to 0 across `band` (*A contour mesh*, above). A `grid` mesh carries
986
- no region, so the part moves from the lattice to the outline mode first; `sample` traced
993
+ no region, so the part moves from the lattice to the outline mode first; `reference-sample` traced
987
994
  `topwear` at its former grid spacing (18) and `bottomwear` at 28. Place the shape on the
988
- patch alone: on `sample` one circle at the hip centre reached the clasped hands, painted
995
+ patch alone: on `reference-sample` one circle at the hip centre reached the clasped hands, painted
989
996
  inside `bottomwear`, so the hips are two side circles (`hip_r`, `hip_l`) on one bone.
990
997
  - **A `physics` constraint** on that bone in `constraints`, in rig-c's shape; every field but
991
998
  the bone is rigc's to accept.
992
999
 
993
- `build` on `sample` as tracked (PR #187; the values above are the ones tuned for its `hop`, issue #183):
1000
+ `build` on `reference-sample` as tracked (PR #187; the values above are the ones tuned for its `hop`, issue #183):
994
1001
 
995
1002
  ```
996
1003
  check: PASS; 9 of 9 bar(s) measured, 0 skipped
@@ -1004,7 +1011,7 @@ by whatever the spring is still doing; the bar is read off the same rig with eve
1004
1011
  constraint left out, and the constraints left out are listed, reported and not judged
1005
1012
  (`check.json`'s `loop_physics`, PR #184). It is not a measure of the jiggle.
1006
1013
 
1007
- **Limits.** The idle drives the spring, and a slow idle barely moves it. Measured on `sample`
1014
+ **Limits.** The idle drives the spring, and a slow idle barely moves it. Measured on `reference-sample`
1008
1015
  (PR #187, rig-c `render --geometry`, the physics build against the same build with
1009
1016
  `constraints` removed): under its 4 s breath (`chest` `translatey` amplitude 1.3 px), the bust
1010
1017
  moves at most 0.155 rig px (idle frame 3, t 0.25 s); the hips move 0.000 at all 49 frames,
@@ -1014,7 +1021,7 @@ frequency, about 0.2 px (PR #187, from the definition): no setting makes a 4 s b
1014
1021
  jiggle (with the values tracked now, `bust_phys` inertia 0.25, strength 120, damping 0.92, the
1015
1022
  idle moves the bust at most 0.066 rig px, idle frame 2). Faster keys on the parent bone — a hop,
1016
1023
  a turn, in a named animation (the recipe above) or a consumer's own — are what the spring
1017
- answers. `sample`'s `animations.json` holds one, `hop` (1 s: `hip` `translate` y down 5, up 24,
1024
+ answers. `reference-sample`'s `animations.json` holds one, `hop` (1 s: `hip` `translate` y down 5, up 24,
1018
1025
  landing at -6 at 0.45 s, settling at 0.55 s; nothing keys the jiggle bones): rendered at 30 fps
1019
1026
  against the same build without its constraints, the bust moves at most 6.583 rig px and the hips
1020
1027
  (`hip_phys` inertia 0.2, strength 160, damping 0.88, mass 1.5) at most 4.432 (frame 13, the fall
@@ -1059,7 +1066,7 @@ not run through. Raising the bound is the author's choice, not the package's; mo
1059
1066
  is the fix.
1060
1067
  - **An added animation can move the idle's figures.** The render's viewport is fitted over
1061
1068
  every animation, and the idle frames share it, so an animation that travels further than the
1062
- idle redraws the idle at another size: adding `hop` to `sample` narrowed the idle render from
1069
+ idle redraws the idle at another size: adding `hop` to `reference-sample` narrowed the idle render from
1063
1070
  201 to 198 px wide and moved `check.json`'s `BREATH_VISIBLE` `torso_heat_mean` from 7.8 to
1064
1071
  7.705, every status unchanged, although `check` reads the idle alone.
1065
1072
 
@@ -1109,7 +1116,7 @@ full loader before its assemble stage writes anything.
1109
1116
  5. **See-through, head run** (external), on that crop. See-through's own second,
1110
1117
  head stage does not replace it: that stage's layers are pasted back at the full
1111
1118
  run's scale on every route that was read (README *Getting See-through layers*),
1112
- so the full run's eyes stay at its density — 22×13 px for the demo's right eye
1119
+ so the full run's eyes stay at its density — 22×13 px for reference-demo's right eye
1113
1120
  white at `resolution` 1024, against 60×38 px in the head run.
1114
1121
  6. `rig-parts assemble --propose-plan --source … --full … --head … --config config.json`
1115
1122
  → paste `plan` and `extend_below_crop` into `config.assemble`. Config: the
@@ -1197,8 +1204,8 @@ proposal in as the steps above say (`RL01`); every step must exit 0.
1197
1204
  | --- | --- | --- | --- |
1198
1205
  | `layers` | the table, then the `WARN` lines | every tag the plan will need has opaque pixels; one `face` in the head run; `0 WARN line(s)` | a run whose layer PNG is not its box's size (`LAYERS_PNG_MATCHES_BBOX`); a `WARN PLAN_LAYER_…` line (§6, *Plausibility*) |
1199
1206
  | `sheet` of both runs | the tile list (and the sheet, if you can see) | eyes, irises, lashes and brows as left/right pairs in the head run | a head box that cut off an ornament: move `head_box`, re-run the head crop |
1200
- | `assemble` | one line per part, the `pixels:` totals (opaque = visible + occluded; taken; visible but not projected), then `recomposite vs source: mean \|d\|, within 8, error px > 40, uncovered error px`, then `uncovered holes (8-connected): N` and the largest five as `uncovered hole K: <px> px at x,y wxh (between "<part>" <px> px, …)`; and look at `render/recomposite_error_rig.png`. Between the part lines and the totals, one `cut: "<part>" opaque <n> = "<part>" <kept> + "<piece>" <taken> …` line per part an `assemble.cuts` entry cut (below; it ends `; under <n> px filled, <m> px left empty` when a cut of that part has `under`), then one `fringe pushed back: "<part>" <px> px, where the painting shows "<holder>" <px> px, …` line per part whose fringe was cleared (below) | on the examples: `sample` 0.83 / 98.0 % / 4,359 / 1,185, 259 holes, the largest 94 px; `demo` 2.34 / 95.8 % / 10,340 / 1,564, 453 holes, the largest 70 px (default rule) — many slivers along part edges, no hole a region could hide | one large hole: part of the figure is in no layer — a plan entry is missing, hair left the head crop sideways (the demo's `hair_back` is taken from the full run for that reason), or See-through split one garment into two and left the space between them in neither (a skirt as two trouser legs); the `between` parts say where. When neither run holds it at all, an `assemble.patches` entry cuts it from the painting (below) |
1201
- | `propose` | `note:` lines, `LINT` lines, the `coverage` lines, `landmarks.png`, `basis.json` | no LINT line: every chain link lies on its mesh's art, and the hip is below the chest and the figure's top quarter; the `coverage:` summary says how many bones that verdict covers — a `not checked` bone was read by no check (its line says why), and a `ratio` or `fallback` bone in `basis.json` is a guess | a link off the art (a bone on the background) — move it onto the layer; `LINT hip at [x, y] is not below chest at [x, y]: …` or `LINT hip at [x, y] is above 0.25 of the figure height (figure y T..B, so hip y must be at least L): a hip at the shoulders` — move `hip` down to the waist (and `chest` between it and the neck); a `hanging strand … -- no chain proposed` note — that strand hangs stiff until you add a chain down the x and rows it names (§3); a `no blink: …` or `blink without brows: …` note — the idle will not blink (or its brows will not drop), because no part came from an `eyewhite` (or `eyebrow`) layer; the note names the tags looked for; a `no eyewhite part for eye_<s> …` note — the iris and lash parts it names ride `head` and do not blink, because no `eyewhite-<s>` part made that side's eye bone: take the eyewhite from the other run, or keep them on `head`; a `no face part: face box derived from …` note (always the first) — `head`, `neck` and every face-height scale come from a box guessed off the hair and neck (§3): check `head` and `neck` on `landmarks_head.png` and move them; when it adds `the blink shuts the eyes over no face part`, read `BLINK_NO_HOLE` after `check` — an eye with no face under it can open a hole (the `sample` with only its face removed: 587 px). Under `--keypoints`: the `lint rule set:` line first (joints, or screen and why), then the joint notes — `missing: the rule "…" placed bone X instead` is a bone still guessed; `not used — …` names why an arm's joints did not place its sleeve (for a wrist on no part, the nearest part and the `--wrist-snap` that would bind it); a `wrist snap: …` note is a wrist bound past 15 px by the flag — check that chain's tip on `landmarks.png`; a `one handwear part holds both wrists` note is two chains on one mesh — cut the part with `assemble.cuts` to separate them; `LINT chest at … is not between the neck joint …`, `LINT hip at … is not past chest …`, `LINT hip at … is nearer the neck joint …` and `LINT <chain><i> at … does not advance from <s>_shoulder toward <s>_wrist` are the joint-frame lines: move that bone between, past or along the joints they name |
1207
+ | `assemble` | one line per part, the `pixels:` totals (opaque = visible + occluded; taken; visible but not projected), then `recomposite vs source: mean \|d\|, within 8, error px > 40, uncovered error px`, then `uncovered holes (8-connected): N` and the largest five as `uncovered hole K: <px> px at x,y wxh (between "<part>" <px> px, …)`; and look at `render/recomposite_error_rig.png`. Between the part lines and the totals, one `cut: "<part>" opaque <n> = "<part>" <kept> + "<piece>" <taken> …` line per part an `assemble.cuts` entry cut (below; it ends `; under <n> px filled, <m> px left empty` when a cut of that part has `under`), then one `fringe pushed back: "<part>" <px> px, where the painting shows "<holder>" <px> px, …` line per part whose fringe was cleared (below) | on the examples: `reference-sample` 0.83 / 98.0 % / 4,359 / 1,185, 259 holes, the largest 94 px; `reference-demo` 2.34 / 95.8 % / 10,340 / 1,564, 453 holes, the largest 70 px (default rule) — many slivers along part edges, no hole a region could hide | one large hole: part of the figure is in no layer — a plan entry is missing, hair left the head crop sideways (reference-demo's `hair_back` is taken from the full run for that reason), or See-through split one garment into two and left the space between them in neither (a skirt as two trouser legs); the `between` parts say where. When neither run holds it at all, an `assemble.patches` entry cuts it from the painting (below) |
1208
+ | `propose` | `note:` lines, `LINT` lines, the `coverage` lines, `landmarks.png`, `basis.json` | no LINT line: every chain link lies on its mesh's art, and the hip is below the chest and the figure's top quarter; the `coverage:` summary says how many bones that verdict covers — a `not checked` bone was read by no check (its line says why), and a `ratio` or `fallback` bone in `basis.json` is a guess | a link off the art (a bone on the background) — move it onto the layer; `LINT hip at [x, y] is not below chest at [x, y]: …` or `LINT hip at [x, y] is above 0.25 of the figure height (figure y T..B, so hip y must be at least L): a hip at the shoulders` — move `hip` down to the waist (and `chest` between it and the neck); a `hanging strand … -- no chain proposed` note — that strand hangs stiff until you add a chain down the x and rows it names (§3); a `no blink: …` or `blink without brows: …` note — the idle will not blink (or its brows will not drop), because no part came from an `eyewhite` (or `eyebrow`) layer; the note names the tags looked for; a `no eyewhite part for eye_<s> …` note — the iris and lash parts it names ride `head` and do not blink, because no `eyewhite-<s>` part made that side's eye bone: take the eyewhite from the other run, or keep them on `head`; a `no face part: face box derived from …` note (always the first) — `head`, `neck` and every face-height scale come from a box guessed off the hair and neck (§3): check `head` and `neck` on `landmarks_head.png` and move them; when it adds `the blink shuts the eyes over no face part`, read `BLINK_NO_HOLE` after `check` — an eye with no face under it can open a hole (the `reference-sample` with only its face removed: 587 px). Under `--keypoints`: the `lint rule set:` line first (joints, or screen and why), then the joint notes — `missing: the rule "…" placed bone X instead` is a bone still guessed; `not used — …` names why an arm's joints did not place its sleeve (for a wrist on no part, the nearest part and the `--wrist-snap` that would bind it); a `wrist snap: …` note is a wrist bound past 15 px by the flag — check that chain's tip on `landmarks.png`; a `one handwear part holds both wrists` note is two chains on one mesh — cut the part with `assemble.cuts` to separate them; `LINT chest at … is not between the neck joint …`, `LINT hip at … is not past chest …`, `LINT hip at … is nearer the neck joint …` and `LINT <chain><i> at … does not advance from <s>_shoulder toward <s>_wrist` are the joint-frame lines: move that bone between, past or along the joints they name |
1202
1209
  | `compare` | one line per pair (origin, parent, tip, length, direction — or SKIP and why), then the per-row summary, the unmapped bones of each side, `required:`, each side's roles and the `controls:` line | proposal against the config you corrected: the rows you changed and no others. Config against the `rig.json` `build` writes for it: measured on both examples, every origin within 6.19e-7 px (the rig's offsets are written to 6 places) and every chain link's tip and length within 4.99e-4 px (`length` is written to 3), printed to three places as `0.000` (a signed figure as `+0.000` or `-0.000`); `parent … is the right's ancestor at depth 2, <bone>_ctl between` for every keyed mesh bone, no `DIFFERENT` and no `NOT MAPPED` | `parent DIFFERENT: left a, right b` — a bone hangs from another parent than the other side's; `frames not related` — a rig with no stage (`skeleton.width`/`height`), two configs at different `rig_scale`: the distance rows SKIP, so declare the frame in a `--map` file if the author knows it; `FAIL STRUCTURE_REQUIRED_PRESENT` — a bone the map requires is missing through its pairs |
1203
1210
  | `rig` (inside `build`) | one line per mesh: vertices, triangles, bones, influences, `cover`; the `bones` line; the `idle keys` line; then rigc's gate lines (with A15's declared SKIP under `--idle-keys direct`); in `rig.json`, each chain link's (or its `_ctl`'s) `length` and `rotation` | `cover 1.00000` on every mesh, both gate summaries `0 failed` (the compile and the packed pages); every link's `length` the distance to the next link and `rotation` its direction (Spine degrees, counter-clockwise, y up, local to the parent), every offset under it — a child bone's `x, y`, a weight's bind `x, y`, a region's `x, y` — in that turned frame, and a region on a link carrying `rotation` that turns it back upright. Nothing moved: `flattenRig` (`src/rig.ts`) turns every offset back and gives the unturned numbers | `RIG_LATTICE_ONE_LOOP`: change that mesh's `grid` |
1204
1211
  | `check` (inside `build`) | the gate lines verbatim, the pack line, `loop:` (and `loop physics:` when the rig declares a physics constraint, §7), `seam:`, the six judgement lines, `RECOMPOSITE_HOLES` and, under `--source`, `SETUP_POSE_VS_SOURCE` (§7), `check.json`; the last line says how many of the nine bars measured and names the ones that said SKIP | `check: PASS; 9 of 9 bar(s) measured, 0 skipped` on the examples, and a judgement line SKIP only where the character lacks what it reads; on a rig spec with no `parts.json` or no `idle` (a merged rig, §7 *Measuring a rig rig-parts did not assemble*), PASS with the skipped bars named | `CHECK_SEAM_WITHIN_BAR` or `CHECK_LOOP_CLOSES` (§6) |
@@ -1214,25 +1221,27 @@ every frame (255 median-cut colours and one transparent entry, alpha graded per
1214
1221
  entry, no dithering, filter None) — and is the small file to show. `idle.gif`
1215
1222
  (`loop --out x.gif`) is the same median cut in a GIF. The indexed APNG and the GIF
1216
1223
  print their palette error, per channel over R, G and B of every frame (and alpha's
1217
- max for the APNG); a figure is a measurement of the file, not a bar. On the demo:
1218
- 13,645,503 B lossless, 1,706,719 B indexed and 1,812,288 B GIF, both palette files at
1219
- max 57, mean 1.601 — the two share one quantiser, so their error is the same by
1220
- construction and the size is the difference. That is `--seam silhouette` (the README's
1221
- animation, rig-c 2.1.3, and 2.10.1 to the byte); with `--pack-shape rect` the same
1222
- build writes 13,645,350, 1,706,520 and 1,812,238 B, and with `--page-edges pot
1223
- --pack-shape rect` 13,645,519, 1,706,785 and 1,812,625 B, all at the same error (2.10.1
1224
- reproduces both). The loop shows the blink closed: the
1224
+ max for the APNG); a figure is a measurement of the file, not a bar. On the demo
1225
+ (the README's animation since issue #227: `build --loop`, default flags, rig-c 2.33.0):
1226
+ 5,832,634 B lossless, 827,857 B indexed and 889,063 B GIF, both palette files at
1227
+ max 65, mean 0.879 — the two share one quantiser, so their error is the same by
1228
+ construction and the size is the difference. On reference-demo with `--seam silhouette`
1229
+ (the README's animation until issue #227, rig-c 2.1.3, and 2.10.1 to the byte):
1230
+ 13,645,503 B lossless, 1,706,719 B indexed and 1,812,288 B GIF at max 57, mean 1.601;
1231
+ with `--pack-shape rect` the same build writes 13,645,350, 1,706,520 and 1,812,238 B,
1232
+ and with `--page-edges pot --pack-shape rect` 13,645,519, 1,706,785 and 1,812,625 B,
1233
+ all at the same error (2.10.1 reproduces both). The loop shows the blink closed: the
1225
1234
  eyes' hold is at least one 12 fps frame (below), so whatever `motion.blink.t` is, one
1226
1235
  idle frame lands inside it, and `check.json`'s `BLINK_NO_HOLE.idle_frames_closed`
1227
- names it — `[29]` on both examples.
1236
+ names it — `[29]` on the two reference examples and on the demo.
1228
1237
 
1229
1238
  `--seam near-white` (the default) is the reference implementation's rule: where the
1230
1239
  flat stack of parts differs from the painting by more than 60, the top part takes the
1231
1240
  painting's colour — except where the painting is near-white, which protects the page
1232
1241
  and also every white garment. `--seam silhouette` protects near-white pixels only
1233
- outside the figure. On the demo it lowers recomposite error pixels from 10,340 to
1234
- 8,644 (`assemble`'s `error px > 40`, at v1.5.2); on the sample it changes nothing
1235
- (4,359 under both). At v0.14.0 the demo's were 11,050 and 9,540, and no check bar
1242
+ outside the figure. On reference-demo it lowers recomposite error pixels from 10,340 to
1243
+ 8,644 (`assemble`'s `error px > 40`, at v1.5.2); on reference-sample it changes nothing
1244
+ (4,359 under both). At v0.14.0 reference-demo's were 11,050 and 9,540, and no check bar
1236
1245
  changed. The default stays
1237
1246
  the reference's so the examples stay comparable with it.
1238
1247
 
@@ -1253,8 +1262,8 @@ and a cleared bridge to opaque art is put back, so no part gains an island
1253
1262
  (`CONTOUR_ONE_ISLAND` reads the islands it read before). `parts.json` records each part's cleared pixels by holder
1254
1263
  (`fringe_pushed_back`), the counts in it are taken after, and the assemble line above
1255
1264
  names them. On the examples (default flags, measured against the v0.14.0 build of
1256
- the same inputs): `demo` 1,193 px over 16 parts, recomposite error pixels 11,050 →
1257
- 10,340; `sample` 276 px over 15 parts, 4,512 → 4,359; uncovered error pixels and
1265
+ the same inputs): `reference-demo` 1,193 px over 16 parts, recomposite error pixels 11,050 →
1266
+ 10,340; `reference-sample` 276 px over 15 parts, 4,512 → 4,359; uncovered error pixels and
1258
1267
  holes unchanged on both, `check` 9 of 9 on both. The `--project` comparison in
1259
1268
  this section and the `SETUP_POSE_VS_SOURCE` example figures in §7 were measured
1260
1269
  before it, at v0.14.0; the `--seam` figures above are v1.5.2's.
@@ -1272,10 +1281,10 @@ to 2.1.3's):
1272
1281
 
1273
1282
  | build | page | covered | page opaque | page / figure |
1274
1283
  | --- | --- | --- | --- | --- |
1275
- | demo, `pot` | 1024x2048 | 56.3 % | 36.8 % | 2.651 |
1276
- | demo, `free` | 967x1338 | 91.2 % | 59.7 % | 1.636 |
1277
- | sample, `pot` | 512x2048 | 49.7 % | 28.7 % | 3.294 |
1278
- | sample, `free` | 479x1166 | 93.4 % | 53.9 % | 1.755 |
1284
+ | reference-demo, `pot` | 1024x2048 | 56.3 % | 36.8 % | 2.651 |
1285
+ | reference-demo, `free` | 967x1338 | 91.2 % | 59.7 % | 1.636 |
1286
+ | reference-sample, `pot` | 512x2048 | 49.7 % | 28.7 % | 3.294 |
1287
+ | reference-sample, `free` | 479x1166 | 93.4 % | 53.9 % | 1.755 |
1279
1288
 
1280
1289
  rigc's help states the cost: *"a smaller page, at the cost of region attachments
1281
1290
  sampling within 1 LSB of the loose build rather than exactly"*. On these builds
@@ -1284,10 +1293,10 @@ in any channel:
1284
1293
 
1285
1294
  | example | idle frames that differ | pixels that differ (all 49 frames) | max \|d\| |
1286
1295
  | --- | --- | --- | --- |
1287
- | demo | 49 of 49 | 2,373 | 1 |
1288
- | sample | 49 of 49 | 651 | 1 |
1296
+ | reference-demo | 49 of 49 | 2,373 | 1 |
1297
+ | reference-sample | 49 of 49 | 651 | 1 |
1289
1298
 
1290
- Only one check figure moved. It had no bar: sample's reported screen-space face
1299
+ Only one check figure moved. It had no bar: reference-sample's reported screen-space face
1291
1300
  mean in `STILL_REGIONS_DARK`, 11.475 under `pot` and 11.472 under `free` (a pixel
1292
1301
  figure the line no longer reports since issue #123; it reads geometry, which the page
1293
1302
  does not enter). Every
@@ -1312,10 +1321,10 @@ both shapes and both edges (the full entry, spine-core 4.3.13 beside it),
1312
1321
 
1313
1322
  | build | page | page area | covered | page opaque | page / figure |
1314
1323
  | --- | --- | --- | --- | --- | --- |
1315
- | demo, `rect` | 967x1338 | 1,293,846 | 91.2 % | 59.7 % | 1.636 |
1316
- | demo, `polygon` | 922x1348 | 1,242,856 (−3.9 %) | 95.0 % | 62.1 % | 1.571 |
1317
- | sample, `rect` | 479x1166 | 558,514 | 93.4 % | 53.9 % | 1.755 |
1318
- | sample, `polygon` | 477x1151 | 549,027 (−1.7 %) | 95.0 % | 54.8 % | 1.725 |
1324
+ | reference-demo, `rect` | 967x1338 | 1,293,846 | 91.2 % | 59.7 % | 1.636 |
1325
+ | reference-demo, `polygon` | 922x1348 | 1,242,856 (−3.9 %) | 95.0 % | 62.1 % | 1.571 |
1326
+ | reference-sample, `rect` | 479x1166 | 558,514 | 93.4 % | 53.9 % | 1.755 |
1327
+ | reference-sample, `polygon` | 477x1151 | 549,027 (−1.7 %) | 95.0 % | 54.8 % | 1.725 |
1319
1328
 
1320
1329
  Covered is Σ region rectangles over page area, as rigc prints it; under `polygon` the
1321
1330
  rectangles may overlap where a hull leaves room, so it is not a union and can exceed
@@ -1328,8 +1337,8 @@ idle --fps 12 --max 640`, compared frame by frame, max over R, G, B and A):
1328
1337
 
1329
1338
  | example | idle frames that differ | pixels that differ (all 49 frames) | max \|d\| |
1330
1339
  | --- | --- | --- | --- |
1331
- | demo | 49 of 49 | 2,594 | 1 |
1332
- | sample | 49 of 49 | 740 | 1 |
1340
+ | reference-demo | 49 of 49 | 2,594 | 1 |
1341
+ | reference-sample | 49 of 49 | 740 | 1 |
1333
1342
 
1334
1343
  That is the class `free` already costs (the table above, measured by the same
1335
1344
  comparison), a little larger. No figure in `check.json` moved but `pack_mode`: every
@@ -1339,11 +1348,11 @@ they are byte-identical to rigc 2.0.3's `--page-edges free` build of the same ri
1339
1348
  skeleton JSON differs only in its relative `images` path), and selftest `CK53` holds
1340
1349
  `rect` to rigc's own rectangle page.
1341
1350
 
1342
- The hull ceiling (rig-parts #58: hull area over rectangle area, 0.812 on demo and
1343
- 0.814 on sample) is not what the packer realises here: the hollows inside the meshes'
1351
+ The hull ceiling (rig-parts #58: hull area over rectangle area, 0.812 on reference-demo and
1352
+ 0.814 on reference-sample) is not what the packer realises here: the hollows inside the meshes'
1344
1353
  rectangles are worth only what fits into them. On the polygon pages, read off the
1345
- atlas, demo's packed rectangles overlap in 21 pairs (17 a region attachment inside a
1346
- mesh's rectangle, 4 a mesh inside another's) and sample's in 12 (10 and 2); no two
1354
+ atlas, reference-demo's packed rectangles overlap in 21 pairs (17 a region attachment inside a
1355
+ mesh's rectangle, 4 a mesh inside another's) and reference-sample's in 12 (10 and 2); no two
1347
1356
  region attachments overlap. Meshes in place of regions would be rigc's stage 2 of
1348
1357
  polygon packing (firejune/rigc#1093), which rigc measured and folded: on the three
1349
1358
  production rigs most favourable to it, it adds 0.15 % of the rectangle area over
@@ -1356,7 +1365,7 @@ so a part a few pixels wide (a lash, a brow, an iris) takes none. `--project vis
1356
1365
  keeps the erosion only along a rim where a later layer of the run is in front, and
1357
1366
  takes every other top-most `alpha >= 250` pixel; neither rule takes a fringe pixel
1358
1367
  (alpha below 250). On the examples it lowered the pixels that are visible but not
1359
- projected from 36,227 to 22,476 (`sample`) and 76,801 to 49,672 (`demo`), recomposite
1368
+ projected from 36,227 to 22,476 (`reference-sample`) and 76,801 to 49,672 (`reference-demo`), recomposite
1360
1369
  error pixels from 4,512 to 4,116 and 11,050 to 9,820, and the check seam from 0.207 to
1361
1370
  0.206 and 0.326 to 0.325, with no other check figure changed. The default stays the
1362
1371
  reference's so the examples stay comparable with it. `build` takes both flags.
@@ -1375,10 +1384,10 @@ drive M mesh attachment(s) totalling V vertices …`, which the stage prints; wi
1375
1384
  mesh-driving bone keyed it declares nothing, because rigc refuses a declaration
1376
1385
  that switches nothing off. The two write the same slots, skins and keys (`RG18`).
1377
1386
  Measured on the examples with `bun tools/idle_cost.ts` (rig-parts #13): `direct`
1378
- has 41 bones for the demo's 72 and 32 for the sample's 56; every shown mesh moves on
1387
+ has 41 bones for reference-demo's 72 and 32 for reference-sample's 56; every shown mesh moves on
1379
1388
  every idle frame under both (8 of 8 and 6 of 6, so 0 a dirty-skip renderer could
1380
- skip); the pose costs 14.8 against 15.3 us per frame (demo) and 8.3 against 8.8 us
1381
- (sample), the difference all in `updateWorldTransform`; the rendered idle frames
1389
+ skip); the pose costs 14.8 against 15.3 us per frame (reference-demo) and 8.3 against 8.8 us
1390
+ (reference-sample), the difference all in `updateWorldTransform`; the rendered idle frames
1382
1391
  differ by at most one level in a channel. The default stays `ctl`: the examples'
1383
1392
  `expected/rig.json` and `motion.json` are the reference's output, and the
1384
1393
  declaration is in the rig spec only, so `rigc validate <build> --profile spine-html`
@@ -1544,15 +1553,15 @@ above 8, the table's `opaque_px`), on the layer as read:
1544
1553
  | `background` | the share of opaque pixels whose own colour (straight alpha) has a min channel above 235 — the seam rule's "near-white", applied to the layer |
1545
1554
  | `area` | opaque pixels over the opaque pixels of the union of every **other** layer of the run ("the rest of the figure"); `-` when no other layer has any |
1546
1555
 
1547
- Not over alpha above 0: See-through hazes whole canvases at alpha 1..8 (the demo's
1556
+ Not over alpha above 0: See-through hazes whole canvases at alpha 1..8 (reference-demo's
1548
1557
  full-run face is 99.1 % translucent that way and 4.2 % over its opaque pixels). Not
1549
1558
  over the whole union: a layer is part of it, so it could never be more than 1x.
1550
1559
 
1551
1560
  | rule | crossed when | [observed] on the two examples' 116 layers (four runs) |
1552
1561
  | --- | --- | --- |
1553
- | `PLAN_LAYER_TRANSLUCENT` | judged, and `translucent` above 50 % | the most translucent judged layer is 17.8 % (sample, full run, `front hair`) |
1554
- | `PLAN_LAYER_BACKGROUND` | judged, `background` above 50 %, and `translucent` above 25 % | the most background-coloured judged layer is 21.9 % (demo, head run, `topwear`, a white dress); of judged layers above 10 % background, the most translucent is 5.6 % (demo, full run, `handwear-r`) |
1555
- | `PLAN_LAYER_OVERSIZED` | `area` above 4x | the largest is 1.681x (demo, head run, `back hair`, which fills the crop) |
1562
+ | `PLAN_LAYER_TRANSLUCENT` | judged, and `translucent` above 50 % | the most translucent judged layer is 17.8 % (reference-sample, full run, `front hair`) |
1563
+ | `PLAN_LAYER_BACKGROUND` | judged, `background` above 50 %, and `translucent` above 25 % | the most background-coloured judged layer is 21.9 % (reference-demo, head run, `topwear`, a white dress); of judged layers above 10 % background, the most translucent is 5.6 % (reference-demo, full run, `handwear-r`) |
1564
+ | `PLAN_LAYER_OVERSIZED` | `area` above 4x | the largest is 1.681x (reference-demo, head run, `back hair`, which fills the crop) |
1556
1565
 
1557
1566
  **Judged** means `area` at least 0.05x (or `-`). The two colour rules skip smaller
1558
1567
  layers on purpose: **[observed]** all 27 example layers of 150 px or more that are above
@@ -1749,7 +1758,7 @@ assemble*, at the end of this section):
1749
1758
  - `gate_spine-html.txt`: every summary line `(N passed, 0 failed)` — the packed build
1750
1759
  under the `spine-html` profile, gated once over the compile and once over the packed
1751
1760
  pages on disk. There is no `spine` gate of its own: `spine-html` holds every rule
1752
- `spine` measures (on the demo, rigc 1.5.1 and 2.0.3: `validate --profile spine`'s 14
1761
+ `spine` measures (on reference-demo, rigc 1.5.1 and 2.0.3: `validate --profile spine`'s 14
1753
1762
  measured rules are all among the build's 23, the 15 others not in `spine`; rigc
1754
1763
  2.1.3 and 2.10.1: the same 14 among the build's 24, which adds
1755
1764
  `A49_PACKED_FOOTPRINTS_DO_NOT_OVERLAP` on the packed pass, 16 not in `spine`; `CH09`
@@ -1760,19 +1769,19 @@ assemble*, at the end of this section):
1760
1769
  prints and `check.json`'s `seam_frame_scale` holds (issue #216). The frame
1761
1770
  holds s² pixels per rig pixel, so a stack that parts from the render over a
1762
1771
  fixed area of the rig reads s² times as many frame pixels: on the public
1763
- `sample` a part moved 2 rig px read 400, 891 and 1,560 frame px over 40 at
1764
- s = 1.0, 1.5 and 2.0, and 400, 396 and 390 rig px; the sample as built read
1772
+ `reference-sample` a part moved 2 rig px read 400, 891 and 1,560 frame px over 40 at
1773
+ s = 1.0, 1.5 and 2.0, and 400, 396 and 390 rig px; reference-sample as built read
1765
1774
  3, 3 and 7 frame px [measured, issue #216]. Divided by s² the bar reads the
1766
1775
  same rig at every scale, and at s = 1 it is the reference's count. The mean
1767
1776
  is a share of the frame and needs no such division (0.242, 0.188 and 0.226 on
1768
- the sample as built; 0.353, 0.305 and 0.340 with the part moved).
1777
+ reference-sample as built; 0.353, 0.305 and 0.340 with the part moved).
1769
1778
  `seam_px_over_40` and `seam_px_over_80` stay frame pixels, and so does each
1770
1779
  pair's count below. The bar reads one
1771
1780
  frame, the setup-pose still, never the idle. When it fails (or when `check
1772
1781
  --seam-pairs` asks, pass or fail), the pixels over 40 are split by the pair of
1773
1782
  parts that answers for each (issue #202): the two parts drawn last among those
1774
1783
  whose art (alpha above 0) lies in the 2x2 rig pixels the composite's bilinear
1775
- sample reads for that frame pixel, lower first, `(no art)` standing in where
1784
+ reference-sample reads for that frame pixel, lower first, `(no art)` standing in where
1776
1785
  fewer than two do. Each pair is a console line `seam pair <i> of <n>: "<a>" /
1777
1786
  "<b>" at the setup pose: <count> px over 40 (<count> over 80), frame box x
1778
1787
  <x0>..<x1>, y <y0>..<y1>, rig box …, picture seam/<i>_<a>_<b>.png` (in the
@@ -1818,8 +1827,8 @@ assemble*, at the end of this section):
1818
1827
  `loop_max_diff`; they are reported, not judged. A rig with none is measured from the
1819
1828
  idle render itself, exactly as before, and writes no such line or key.
1820
1829
 
1821
- On the examples: `sample` 23/23, seam 0.207 with 0 pixels over 40, loop 0;
1822
- `demo` (default rule) 23/23, seam 0.326 with 2 pixels over 40, loop 0.
1830
+ On the examples: `reference-sample` 23/23, seam 0.207 with 0 pixels over 40, loop 0;
1831
+ `reference-demo` (default rule) 23/23, seam 0.326 with 2 pixels over 40, loop 0.
1823
1832
 
1824
1833
  A green gate cannot see a wrong animation, so `check` also writes six **judgement
1825
1834
  lines** (issue #11; `TEXTURE_STRETCH`, issue #31), each a key of `check.json` and a console line
@@ -1836,10 +1845,10 @@ model itself fixes (a part on an unkeyed bone does not move, a lag is above 0, a
1836
1845
  is 0 pixels) is that value, not a margin — and where the model's value is an error
1837
1846
  the model fixes at "nothing moves" and the instrument reads exactly (the still regions,
1838
1847
  from geometry since issue #123), the bar is the arithmetic's own rounding, derived, not
1839
- measured. A bar is set once, from the figures of the day it was set, and is not chased: the torso floor 3.809 is half of sample's 7.618, which reads 7.617 since the chain links are turned (issue #73), a factor of 1.9997. The figures are this port's, measured on
1848
+ measured. A bar is set once, from the figures of the day it was set, and is not chased: the torso floor 3.809 is half of reference-sample's 7.618, which reads 7.617 since the chain links are turned (issue #73), a factor of 1.9997. The figures are this port's, measured on
1840
1849
  the two examples [observed]:
1841
1850
 
1842
- | line | measures | bar | `demo` | `sample` | SKIP when |
1851
+ | line | measures | bar | `reference-demo` | `reference-sample` | SKIP when |
1843
1852
  | --- | --- | --- | --- | --- | --- |
1844
1853
  | `BREATH_VISIBLE` | `topwear` parts rendered alone (`rigc render --slot`): heat mean over their box; `footwear` parts alone: heat max over theirs | torso mean ≥ 3.809; feet max ≤ 0 | 15.251; 0 | 7.617; 0 | no `topwear` or no `footwear` part |
1845
1854
  | `BLINK_NO_HOLE` | the setup pose with every `scaley` track on the eyewhite slots' bones held at its closed value, against the setup pose, at full size: pixels in the eyewhite box that show the page where the open eye had art | 0 px | 0 | 0 | no `eyewhite` part, or no `scaley` track on its bones goes below its first key |
@@ -1856,27 +1865,27 @@ centroid of every pixel that was not the background; its fields were `root_px` a
1856
1865
  mercy of which edge pixels the grid flips: over `--max` 620–660 the pixel figure
1857
1866
  scattered around the exact one by up to 0.3 frame px whatever the travel [observed,
1858
1867
  13 half-bands on the three examples and a variant], and every **root** half on every
1859
- example travels 0.04–0.6 frame px, so the ratio's denominator was noise — sample's
1860
- `bottomwear` read 4.187–6.849 over the sweep, demo's `sleeves` 2.960–6.503, and sample
1868
+ example travels 0.04–0.6 frame px, so the ratio's denominator was noise — reference-sample's
1869
+ `bottomwear` read 4.187–6.849 over the sweep, reference-demo's `sleeves` 2.960–6.503, and reference-sample
1861
1870
  with its skirt amplitudes ×0.1 read 0.512–13.53, FAIL or PASS by the grid. The exact
1862
1871
  reading of the same definition is the same at every size (4.007 on that skirt, a PASS).
1863
1872
  The fields are now `root_rig_px` and `tip_rig_px`, rig px, beside `instrument:
1864
1873
  "geometry"`, so an old and a new `check.json` are not read as one instrument. The bar
1865
- is the one set from the pixel instrument (half of demo's `bottomwear` 2.945, by the
1866
- rule above, not chased); demo's exact 3.222 clears it 2.19 times. The figures the two
1874
+ is the one set from the pixel instrument (half of reference-demo's `bottomwear` 2.945, by the
1875
+ rule above, not chased); reference-demo's exact 3.222 clears it 2.19 times. The figures the two
1867
1876
  instruments give the examples, and `scarf` (whose `bottomwear` is tracked in contour
1868
1877
  mode because its lattice fails the line — its README):
1869
1878
 
1870
1879
  | part | pixel, `--max 640` (until #118) | geometry |
1871
1880
  | --- | --- | --- |
1872
- | `demo` `bottomwear`, `sleeves` | 2.990, 3.287 | 3.222, 4.721 |
1873
- | `sample` `bottomwear`, `sleeves` | 4.396, 12.475 | 4.956, 11.830 |
1881
+ | `reference-demo` `bottomwear`, `sleeves` | 2.990, 3.287 | 3.222, 4.721 |
1882
+ | `reference-sample` `bottomwear`, `sleeves` | 4.396, 12.475 | 4.956, 11.830 |
1874
1883
  | `scarf` `handwear_r`, `handwear_l` | 6.242, 5.558 | 6.683, 5.345 |
1875
1884
  | `scarf` `bottomwear`, lattice / contour | 4.537 / 2.661 | 1.207 / 1.738 |
1876
1885
 
1877
1886
  The part rendered alone at up to `--max 8000` — the motion spanning pixels — converges
1878
1887
  on the geometric figure (`scarf`'s lattice `bottomwear` 1.337, 1.316, 1.285, 1.270 at
1879
- 1200, 2400, 4800, 8000), with one gap not explained: `sample`'s `bottomwear` tip reads
1888
+ 1200, 2400, 4800, 8000), with one gap not explained: `reference-sample`'s `bottomwear` tip reads
1880
1889
  2.342 rig px there against 2.596 from geometry, its root agreeing to 0.4 %.
1881
1890
 
1882
1891
  **`STILL_REGIONS_DARK` is measured from geometry too, and its scope changed (issue #123).**
@@ -1889,8 +1898,8 @@ on the geometric figure (`scarf`'s lattice `bottomwear` 1.337, 1.316, 1.285, 1.2
1889
1898
 
1890
1899
  Both were means of about one level, and both moved with the grid. Over `--max` 620–660
1891
1900
  on the three examples:
1892
- - demo read 1.03–1.16 times its calibration;
1893
- - sample read 0.95–1.07;
1901
+ - reference-demo read 1.03–1.16 times its calibration;
1902
+ - reference-sample read 0.95–1.07;
1894
1903
  - scarf read 0.99–1.38, with its head-frame mean between 1.350 and 1.869.
1895
1904
 
1896
1905
  The feet half was a screen-space heat mean held to 3.244.
@@ -1902,7 +1911,7 @@ In all three examples `hair_front` is drawn over the face and weighted to `head`
1902
1911
  bang bones. Its art swings into the face outline, relative to the head, on every idle
1903
1912
  frame:
1904
1913
 
1905
- | | `demo` | `sample` | `scarf` |
1914
+ | | `reference-demo` | `reference-sample` | `scarf` |
1906
1915
  | --- | --- | --- | --- |
1907
1916
  | deepest reach into the face | 2.816 rig px | 2.194 rig px | 2.479 rig px |
1908
1917
  | most face area covered on one frame | 89.395 rig px² | 50.605 rig px² | 31.908 rig px² |
@@ -1960,7 +1969,7 @@ reported `crossing` depth is the only instrument for it.
1960
1969
  **Before and after, the same builds, only `IDLE_MAX_PX` changed** (scratch copies of the
1961
1970
  tree):
1962
1971
 
1963
- | `--max` | before: face mean / calibration (ratio), feet mean, demo · sample · scarf | after: face `max_rig_px`, feet `max_rig_px`, all three |
1972
+ | `--max` | before: face mean / calibration (ratio), feet mean, reference-demo · reference-sample · scarf | after: face `max_rig_px`, feet `max_rig_px`, all three |
1964
1973
  | --- | --- | --- |
1965
1974
  | 620 | 1.283 / 1.196 (1.07), 1.504 · 0.933 / 0.900 (1.04), 0 · 1.350 / 1.360 (0.99), 0 | 4.202e-13, 0 · 4.418e-13, 0 · 4.224e-13, 0 |
1966
1975
  | 640 | 1.328 / 1.145 (1.16), 1.619 · 0.898 / 0.897 (1.00), 0 · 1.869 / 1.352 (1.38), 0 | the same |
@@ -1978,7 +1987,7 @@ The selftest's planted cases (by hand):
1978
1987
 
1979
1988
  After them, one **reported line** with no bar:
1980
1989
 
1981
- | line | reports | bar | `demo` | `sample` | SKIP when |
1990
+ | line | reports | bar | `reference-demo` | `reference-sample` | SKIP when |
1982
1991
  | --- | --- | --- | --- | --- | --- |
1983
1992
  | `RECOMPOSITE_HOLES` | `parts.json`'s `recomposite` block (§5), read rather than measured: `error_px`, `uncovered_error_px`, `hole_count`, and the largest hole's `px`, `box` (`x,y wxh`) and `borders` (`<part> <px> px`) | none — status `REPORTED`, never FAIL, and `PASS` does not read it | 1,564 px in 453 holes; largest 70 px at 351,155 6x22, `hair_back` 53 px, `hair_front` 12 px | 1,185 px in 259 holes; largest 94 px at 479,412 7x34, `sleeves` 42 px, `topwear` 40 px, `bottomwear` 6 px | `parts.json` has no `recomposite` block (the reference's files) |
1984
1993
 
@@ -1996,16 +2005,16 @@ look at `recomposite_error_rig.png` when the largest hole is more than a sliver.
1996
2005
  Under `--source <painting.png>`, a second reported line, also never a FAIL
1997
2006
  (issue #77):
1998
2007
 
1999
- | line | reports | bar | `demo` | `sample` | SKIP when |
2008
+ | line | reports | bar | `reference-demo` | `reference-sample` | SKIP when |
2000
2009
  | --- | --- | --- | --- | --- | --- |
2001
2010
  | `SETUP_POSE_VS_SOURCE` | the setup pose against the painting, by `assemble`'s own `measureRecomposite` over the stage's pixels — `mean_abs` and `within_share` (mean channel, within 8), `error_px` (max channel over 40), `uncovered_error_px` (of those, where the pose has alpha 128 or less), `hole_count` and the largest hole's box — with `painting_px`, `stage_px`, `render_px` and `render_scale` beside them. The painting is resampled onto the stage as assemble resamples it (lanczos3, alpha dropped). rigc renders onto an opaque grey, so the pose over white and its alpha are read off a second still of the same pose with every slot tinted black; both are carried onto the stage with the seam's map turned round (bilinear) | none — status `REPORTED`; assemble applies no bar to the figures it measures, so none is derived here | 3.146 / 93.43 % / 12,399 / 1,732, 518 holes, the largest 61 px at 351,157 6x20 (assemble's recomposite: 2.391 / 95.81 % / 11,050 / 1,564, 453) | 1.095 / 97.30 % / 5,348 / 1,239, 313 holes, the largest 88 px at 479,416 6x29 (assemble's: 0.835 / 97.95 % / 4,512 / 1,185, 259) | not written without `--source` |
2002
2011
 
2003
2012
  The figures are assemble's by construction, not a second definition beside them;
2004
2013
  what differs is what they are taken of — the pose rigc draws, not the flat stack —
2005
2014
  and the gap between the two columns above is that drawing: the render's resampling at
2006
- its scale (0.942 on the demo, 1.012 on the sample) and the warp back onto the stage,
2015
+ its scale (0.942 on reference-demo, 1.012 on reference-sample) and the warp back onto the stage,
2007
2016
  which soften every part edge by a pixel or two. It moves with the render's grid
2008
- [observed, the demo's still rendered at four sizes: mean 2.663 at scale 1.0003, 3.091
2017
+ [observed, reference-demo's still rendered at four sizes: mean 2.663 at scale 1.0003, 3.091
2009
2018
  at 1.0073, 3.146 at 0.942, 3.186 at 1.884], so compare the line with itself across
2010
2019
  rigs or edits, and with `RECOMPOSITE_HOLES` for where a hole is, not digit for digit
2011
2020
  with the recomposite. On the examples the line reads the same with and without
@@ -2035,11 +2044,11 @@ What each figure is, and is not:
2035
2044
  chains of both examples are written the first way — so the reading folds a step into
2036
2045
  (−¼, ¼] of a cycle and reports amplitudes unsigned. A lag of a quarter cycle or more
2037
2046
  cannot be told from a lead. Tracks whose keys are not a sampled sine are listed as
2038
- `unread`, and a keyed bone under a keyed ancestor of another period (the demo's
2047
+ `unread`, and a keyed bone under a keyed ancestor of another period (reference-demo's
2039
2048
  tassel under the head) is listed in `other_period` and not compared.
2040
2049
  - **Tip over root is a centroid, not a displacement.** Art entering or leaving a half
2041
2050
  moves its centroid too. The halves' mean heat was the brief's first choice and was
2042
- rejected: heat is texture times motion, and on the demo's sleeves the lower half's
2051
+ rejected: heat is texture times motion, and on reference-demo's sleeves the lower half's
2043
2052
  mean heat is 1.1 times the upper half's while its centroid travels 3.7 times as far.
2044
2053
  The halves split the box across its rows, which assumes the part hangs — true of a
2045
2054
  front-facing standing figure, the only input this tool takes.
@@ -2047,9 +2056,9 @@ What each figure is, and is not:
2047
2056
  distorts a texture as much as stretch — an edge at half its rest length squeezes
2048
2057
  the texels on it by the factor an edge at twice its length spreads them — so the
2049
2058
  figure is max(ratio, 1/ratio), and on both examples the worst triangle is a
2050
- compression (demo 0.720, sample 0.815). The ceiling rule is applied to the quantity
2059
+ compression (reference-demo 0.720, reference-sample 0.815). The ceiling rule is applied to the quantity
2051
2060
  whose zero means "nothing happened", as it is for heat: for a ratio that is |ln r|,
2052
- so twice demo's |ln 1.388| is ln(1.388²) = ln 1.926544 and sample clears it by 3.2
2061
+ so twice reference-demo's |ln 1.388| is ln(1.388²) = ln 1.926544 and reference-sample clears it by 3.2
2053
2062
  times. Doubling the ratio itself (2.776) was rejected: its zero is not at 1, and it
2054
2063
  passes an edge drawn at 2.7 times its rest length. The rest is the art's own
2055
2064
  proportions — on both examples every rest edge equals its `uvs` edge times the
@@ -2080,7 +2089,7 @@ What each figure is, and is not:
2080
2089
  its depth is reported per slot in `crossing`, which no bar reads.
2081
2090
  - **The feet are measured in screen space.** They ride the root, which the idle does not
2082
2091
  key, so the screen is their own frame.
2083
- - Until #123 the feet half read the screen-space heat. On the demo the long skirt,
2092
+ - Until #123 the feet half read the screen-space heat. On reference-demo the long skirt,
2084
2093
  drawn under the shoes, swings beside them and lit their rim to 1.622.
2085
2094
  - From the geometry, nothing drawn over the shoes enters them on any example, and
2086
2095
  the shoes move exactly 0.
@@ -2116,7 +2125,7 @@ it reads is there, and says SKIP with the reason when it is not:
2116
2125
  `PASS` reads every bar that measured, and the last console line says how many did:
2117
2126
  `check: PASS; 1 of 9 bar(s) measured, 8 skipped (loop, seam, …)` is a rig whose gate is
2118
2127
  green and nothing else was looked at. Without an idle no idle is rendered
2119
- (`idle_frames/`, `contact.png` and `motion_heat.png` are not written). The demo's own
2128
+ (`idle_frames/`, `contact.png` and `motion_heat.png` are not written). Reference-demo's own
2120
2129
  rig directory, copied away from its `parts.json`, reads `4 of 9`: the gate, the loop,
2121
2130
  `CHAIN_LAG` and `TEXTURE_STRETCH`.
2122
2131
 
@@ -2152,7 +2161,7 @@ What is composed:
2152
2161
 
2153
2162
  - **Images are `<id>.<file>`, not `<id>:<file>`.** rig-c names an atlas region
2154
2163
  by its PNG's basename, and an atlas region line that holds `:` is read as a
2155
- `key: value` line: measured through rig-c 2.15.0 on the demo renamed
2164
+ `key: value` line: measured through rig-c 2.15.0 on reference-demo renamed
2156
2165
  `demo:<name>` with images `demo:<file>`, `A07_ATLAS_TEXT_SHAPE` fails once per
2157
2166
  region; with the images under a `demo/` folder the rig gates green but the region
2158
2167
  keeps the bare basename, so two characters' `face` would collide. So the
@@ -2367,21 +2376,21 @@ is built (`CK83`–`CK85`, `RQ30`–`RQ35`).
2367
2376
 
2368
2377
  ## 8. What one character costs
2369
2378
 
2370
- | step | sample | demo | source |
2379
+ | step | reference-sample | reference-demo | source |
2371
2380
  | --- | --- | --- | --- |
2372
- | painting (GPU) | 20.2 s | 18.3 s | `generation.json` `elapsed_s`, in [spine-parts-examples](https://github.com/firejune/spine-parts-examples) |
2381
+ | painting (GPU) | 20.2 s | 18.3 s | `generation.json` `elapsed_s`, in [parts-examples](https://github.com/rig-c/parts-examples) |
2373
2382
  | See-through full run (GPU) | 194.9 s | 198.5 s | `inputs/layers/full/meta.json` `elapsed_s` |
2374
2383
  | See-through head run (GPU) | 170.9 s | 171.4 s | `inputs/layers/head/meta.json` `elapsed_s` |
2375
2384
  | `build` (CPU, user + sys) | 14.6 s | 30.7 s | measured with `/usr/bin/time -p` on an Apple M4 machine under other load, rigc's child processes included; wall clock 12.7 s and 27.5 s |
2376
2385
 
2377
2386
  About 6.5 minutes of GPU and under a minute of CPU per character, before any hand
2378
2387
  correction. The GPU figures are one run each on one machine; the painting's figure
2379
- excludes choosing among seeds (the demo was chosen from eighteen candidates).
2388
+ excludes choosing among seeds (reference-demo was chosen from eighteen candidates).
2380
2389
  Since issue #33 `check` runs one more `rigc build` and one more idle render (the face
2381
2390
  calibration, §7); the idle's `geometry.json` is the one issue #31 already writes. The `build` row
2382
2391
  was not re-measured: A/B against the tree before that change, alternating on one
2383
2392
  machine under a load average of 5 to 11, the difference in user + sys was +5.6 and
2384
- +0.8 s on the demo and +6.5 and −1.6 s on the sample over two rounds — inside what
2385
- the load moves the same build by (the pre-change demo build alone took 43.6 to
2393
+ +0.8 s on reference-demo and +6.5 and −1.6 s on reference-sample over two rounds — inside what
2394
+ the load moves the same build by (the pre-change reference-demo build alone took 43.6 to
2386
2395
  45.8 s there). Since issue #123 that build and render are gone again — the still regions read the
2387
2396
  idle's geometry — and the `build` row was not re-measured for it either.
package/docs/MIGRATION.md CHANGED
@@ -9,14 +9,14 @@ from the pull request that measured it.
9
9
 
10
10
  ## In one paragraph
11
11
 
12
- Install `rig-parts`. A config that built on 0.16.0 loads and builds unchanged: every
13
- config change since is a new, opt-in field inside a new mesh mode. The bytes a
14
- config without that mode builds moved once, by a declared exception (every mesh
15
- triangle's vertex order, #133); apart from it, each change since 0.16.0 that touched
16
- the code was measured against the tree before it on the three public examples'
17
- builds, and moved no byte of them. Inside the automatic mode, one change after the
18
- candidate moves declared bytes, named in *Since 1.0.0-rc.1*: the skinning envelope's
19
- reference (#169).
12
+ Install `@rig-c/parts` (the package's name after 1.5.3; *After 1.5.3* below). A
13
+ config that built on 0.16.0 loads and builds unchanged: every config change since is
14
+ a new, opt-in field inside a new mesh mode. The bytes a config without that mode
15
+ builds moved once, by a declared exception (every mesh triangle's vertex order,
16
+ #133); apart from it, each change since 0.16.0 that touched the code was measured
17
+ against the tree before it on the three public examples' builds, and moved no byte
18
+ of them. Inside the automatic mode, one change after the candidate moves declared
19
+ bytes, named in *Since 1.0.0-rc.1*: the skinning envelope's reference (#169).
20
20
 
21
21
  ## From 0.16.0 to 1.0.0-rc.1
22
22
 
@@ -31,7 +31,7 @@ reference (#169).
31
31
  | spec ids of the files authors write and this package writes | `spine-parts-requirements/1`, `spine-parts-scene/1`, `spine-parts-keypoints/1`, `spine-parts-bonemap/1`, `spine-parts-basis/1`, `spine-parts-scene-report/1` | unchanged: they name a file format, not the tool, so a file written before the rename still reads |
32
32
  | public examples repository | `spine-parts-examples` | unchanged (it keeps the name it was published under) |
33
33
 
34
- What to do: install with `npm install -g rig-parts` and write `rig-parts` in scripts.
34
+ What to do: install with `npm install -g @rig-c/parts` and write `rig-parts` in scripts.
35
35
  A script or a dependant that names the alias `spine-parts` keeps working and keeps
36
36
  receiving every release; how long the alias stays is RELEASING.md's *The alias stays
37
37
  until its retirement questions have written answers*. No build output carries the
@@ -135,3 +135,16 @@ What to do: nothing for a config without `auto`. A config under `auto` that decl
135
135
  `motion.residual` may write a different mesh than 1.0.0-rc.1 did, as above; a
136
136
  consumer that compares builds byte for byte with 1.0.0-rc.1 expects that move and
137
137
  nothing else.
138
+
139
+ ## After 1.5.3: the scoped name
140
+
141
+ | | 1.0.0 to 1.5.3 | after 1.5.3 |
142
+ | --- | --- | --- |
143
+ | npm package | `rig-parts` | `@rig-c/parts`; `rig-parts` and the alias `spine-parts` are published beside it at every version as aliases, the same files with only the `name` in `package.json` changed |
144
+ | command | `rig-parts`, and the alias `spine-parts` on the same launcher | unchanged |
145
+ | repository | `firejune/rig-parts` (GitHub redirects it) | `rig-c/parts`, beside `rig-c/core` (npm `rig-c`) and `rig-c/play` |
146
+ | spec ids, the config, the bytes a build writes | | unchanged |
147
+
148
+ What to do: install with `npm i -D @rig-c/parts` (or `npm install -g @rig-c/parts`);
149
+ command lines do not change. A dependant that names `rig-parts` keeps receiving
150
+ every release under it (#222).
package/docs/STABILITY.md CHANGED
@@ -231,7 +231,7 @@ the input and the machine. Measured: the evidence tools run every cell under a
231
231
  rig-c 2.23.0 (the same document's quiet timing table, a remote WSL runner, pool,
232
232
  load under 2); at rig-c 2.31.0 the whole rig stage of one automatic part, motion
233
233
  gate and acceptance loop included, took 1.1 s to 61.6 s on the eight parts the
234
- surveys switch, demo `bottomwear` the slowest at 12 gated builds, with a run-to-run
234
+ surveys switch, reference-demo `bottomwear` the slowest at 12 gated builds, with a run-to-run
235
235
  spread of ±15 % on that part (pull request #152's paired exclusive timing, remote
236
236
  20-core runner; the surveys print wall time to standard error, not into the
237
237
  documents). On CI (`ubuntu-latest`), the last two green runs on `main` took 4 min
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rig-parts",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "description": "AI-authored 2D character parts from one anime painting and its See-through layer decomposition: measured parts, weighted-mesh rig specs, verified through rig-c before anything is written. A CLI for agents that cannot see the image.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,10 +14,10 @@
14
14
  "author": "firejune",
15
15
  "repository": {
16
16
  "type": "git",
17
- "url": "https://github.com/firejune/rig-parts.git"
17
+ "url": "https://github.com/rig-c/parts.git"
18
18
  },
19
- "homepage": "https://github.com/firejune/rig-parts#readme",
20
- "bugs": "https://github.com/firejune/rig-parts/issues",
19
+ "homepage": "https://github.com/rig-c/parts#readme",
20
+ "bugs": "https://github.com/rig-c/parts/issues",
21
21
  "keywords": [
22
22
  "spine",
23
23
  "spine2d",
@@ -2,7 +2,7 @@
2
2
  name: rig-parts
3
3
  description: Turn one anime character painting and its See-through layer decomposition into a verified 2D character rig (Spine 4.3 skeleton data) — measured parts, weighted meshes, bone chains and a looping idle — with rig-parts, which gates everything through rig-c before it is written. Use for a request to rig or animate a single character painting, to run or read rig-parts layers, sheet, assemble, propose, rig, check, loop or build, or to write or fix a rig-parts config.json. Not for cutting art into parts by hand, for authoring a rig from loose PNGs (that is the rigc skill), for lip-sync or swapping a part's image, or for running See-through itself.
4
4
  license: MIT
5
- compatibility: Requires Bun 1.2 or later. The tool is the npm package rig-parts (bunx rig-parts, or bun add -d rig-parts); rig-c is installed with it. See-through is run separately.
5
+ compatibility: Requires Bun 1.2 or later. The tool is the npm package @rig-c/parts (npm i -D @rig-c/parts, or bun add -d @rig-c/parts), whose command is rig-parts; rig-c is installed with it. See-through is run separately.
6
6
  ---
7
7
 
8
8
  # rig-parts — a painting to a Spine rig, for agents
@@ -125,7 +125,7 @@ it and the order as `scene.json` records it (AUTHORING §7, *Composing several
125
125
  characters*).
126
126
 
127
127
  `--seam silhouette` repairs more of the seam on white garments than the default
128
- `near-white` (the demo: 10,340 → 8,644 recomposite error pixels); the default is
128
+ `near-white` (reference-demo: 10,340 → 8,644 recomposite error pixels); the default is
129
129
  the reference implementation's rule. `--project visible` lets thin visible parts
130
130
  (lashes, brows, irises) take the painting's pixels, which the default `core` rule
131
131
  erodes away. Name both rules you used in your report, and quote the assemble
@@ -150,16 +150,16 @@ share is synthesis where the painting was there to be taken.
150
150
 
151
151
  ## Where to read next
152
152
 
153
- [docs/AUTHORING.md](https://github.com/firejune/rig-parts/blob/main/docs/AUTHORING.md)
153
+ [docs/AUTHORING.md](https://github.com/rig-c/parts/blob/main/docs/AUTHORING.md)
154
154
  first — every config field, the command order, what to read after each stage, every
155
- refusal. It is in the installed package at `node_modules/rig-parts/docs/AUTHORING.md`,
155
+ refusal. It is in the installed package at `node_modules/@rig-c/parts/docs/AUTHORING.md`,
156
156
  the copy that matches the version you run. Two recipes there cover what this package
157
157
  leaves to you:
158
158
 
159
159
  - An expression or any other named animation: AUTHORING §3, *Recipe: expressions and other
160
160
  named animations* (`motion.animations_from`; built and gated with the rig, not measured).
161
161
  - A jiggle (a bust, the hips): AUTHORING §3, *Recipe: a soft region driven by physics* (a
162
- config-only bone, a `contour` region on it, a `physics` constraint; `examples/sample`
162
+ config-only bone, a `contour` region on it, a `physics` constraint; `examples/reference-sample`
163
163
  carries one, and its slow idle barely moves it).
164
164
 
165
165
  A `RIG_RIGC_GREEN` or `CHECK_RIGC_GREEN`