@rig-c/parts 0.0.0-stage → 1.5.3

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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +134 -0
  3. package/README.md +431 -2
  4. package/bin/rig-parts.cjs +43 -0
  5. package/cli.ts +1240 -0
  6. package/docs/AUTHORING.md +2387 -0
  7. package/docs/MIGRATION.md +137 -0
  8. package/docs/STABILITY.md +262 -0
  9. package/package.json +70 -4
  10. package/skills/rig-parts/SKILL.md +167 -0
  11. package/src/apng.ts +381 -0
  12. package/src/assemble.ts +2259 -0
  13. package/src/autoamplitude.ts +194 -0
  14. package/src/autoenvelope.ts +404 -0
  15. package/src/automesh.ts +585 -0
  16. package/src/automotion.ts +447 -0
  17. package/src/autoreplay.ts +516 -0
  18. package/src/build.ts +1240 -0
  19. package/src/check.ts +2942 -0
  20. package/src/comfy/client.ts +245 -0
  21. package/src/comfy/index.ts +19 -0
  22. package/src/comfy/painting.ts +136 -0
  23. package/src/comfy/seethrough.ts +171 -0
  24. package/src/config.ts +2283 -0
  25. package/src/contour.ts +1901 -0
  26. package/src/coords.ts +26 -0
  27. package/src/diagnostics.ts +198 -0
  28. package/src/errors.ts +39 -0
  29. package/src/gif.ts +213 -0
  30. package/src/graphs.ts +302 -0
  31. package/src/headbox.ts +173 -0
  32. package/src/heat.ts +313 -0
  33. package/src/inputs.ts +100 -0
  34. package/src/instruments.ts +1145 -0
  35. package/src/keypoints.ts +296 -0
  36. package/src/layers.ts +598 -0
  37. package/src/localweights.ts +217 -0
  38. package/src/mesh.ts +362 -0
  39. package/src/motion.ts +311 -0
  40. package/src/palette.ts +208 -0
  41. package/src/parts.ts +410 -0
  42. package/src/propose.ts +2540 -0
  43. package/src/pyfmt.ts +135 -0
  44. package/src/raster/blur.ts +80 -0
  45. package/src/raster/components.ts +165 -0
  46. package/src/raster/composite.ts +81 -0
  47. package/src/raster/index.ts +9 -0
  48. package/src/raster/morph.ts +116 -0
  49. package/src/raster/png.ts +82 -0
  50. package/src/raster/poly.ts +166 -0
  51. package/src/raster/resize.ts +301 -0
  52. package/src/raster/types.ts +89 -0
  53. package/src/raster/warp.ts +121 -0
  54. package/src/requirements.ts +1240 -0
  55. package/src/rig.ts +1440 -0
  56. package/src/round.ts +62 -0
  57. package/src/scene.ts +1414 -0
  58. package/src/sheet.ts +128 -0
  59. package/src/skeleton.ts +400 -0
  60. package/src/structure.ts +858 -0
  61. package/src/tags.ts +121 -0
  62. package/src/weights.ts +124 -0
  63. package/workflows/seethrough.json +68 -0
@@ -0,0 +1,137 @@
1
+ # Migrating from 0.16.0
2
+
3
+ 0.16.0 was the last version published under the package's former name. This page is
4
+ what changed between it and 1.0.0 for a user of the command, an author of a config
5
+ and a reader of the files a build writes; what 1.0.0 holds stable is
6
+ [STABILITY.md](STABILITY.md). It comes in two parts: 0.16.0 to the release candidate
7
+ 1.0.0-rc.1, then what landed between the candidate and 1.0.0. Every figure is quoted
8
+ from the pull request that measured it.
9
+
10
+ ## In one paragraph
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).
20
+
21
+ ## From 0.16.0 to 1.0.0-rc.1
22
+
23
+ ### The package name
24
+
25
+ | | 0.16.0 | 1.0.0-rc.1 and 1.0.0 |
26
+ | --- | --- | --- |
27
+ | npm package | the former name | `rig-parts`; the alias `spine-parts` is published beside it at every version, the same files with only the `name` in `package.json` changed |
28
+ | command | the former name | `rig-parts`; the install also keeps the alias `spine-parts` as a second command on the same launcher, for the transition |
29
+ | repository | the former repository name (GitHub redirects it) | `firejune/rig-parts` |
30
+ | selftest variables | the `SPINE_PARTS_` names | `RIG_PARTS_CORPUS`, `RIG_PARTS_SELFTEST_JOBS`, each read first, with the former `SPINE_PARTS_` name read when it is not set |
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
+ | public examples repository | `spine-parts-examples` | unchanged (it keeps the name it was published under) |
33
+
34
+ What to do: install with `npm install -g rig-parts` and write `rig-parts` in scripts.
35
+ A script or a dependant that names the alias `spine-parts` keeps working and keeps
36
+ receiving every release; how long the alias stays is RELEASING.md's *The alias stays
37
+ until its retirement questions have written answers*. No build output carries the
38
+ package name: a grep of all 330 files the three example builds write found neither
39
+ spelling (#142). The console does: the lines that name the tool (5 per build: the
40
+ `build`, `assemble`, `rig` twice and `check` lines) now say `rig-parts`. Where a
41
+ config uses a constraint or `--idle-keys direct`, the `why` prose this package writes
42
+ into `rig.json`'s invariants names `rig-parts` too; that prefix is the one known
43
+ output change of the rename (#142).
44
+
45
+ ### rig-c, as this package sees it
46
+
47
+ The dependency is `rig-c` `^2.33.0` at 1.0.0 (`^2.31.0` at 1.0.0-rc.1; the moves
48
+ between the two are in *Since 1.0.0-rc.1*), where 0.16.0 took the same upstream
49
+ package under its former npm name at `^2.15.0`; that name is spelled only in `CHANGELOG.md`.
50
+ The upstream package was renamed on npm at 2.20.4 with the same `exports` map
51
+ (#138), and every import, probe and sentence here names `rig-c`. A project that
52
+ installed the former upstream name beside this package installs nothing more:
53
+ `rig-c` comes as a dependency. No Spine runtime is a dependency, as in 0.16.0.
54
+
55
+ ### The config
56
+
57
+ **A config that built on 0.16.0 loads unchanged.** The loader's only change between
58
+ the two is one more optional key, `auto`, on `meshes.<part>`, and the objects under it;
59
+ no key was removed, renamed or made required outside it, and no CLI flag was added or
60
+ removed (`git diff v0.16.0` of `src/config.ts` and `cli.ts`). `grid` and `contour`
61
+ meshes read exactly as before, and `propose` still writes `grid`.
62
+
63
+ What an author who adopts the new mode meets (AUTHORING §3, *An automatic mesh*):
64
+
65
+ - **`meshes.<part>.auto`**, the third mesh mode (#131): the contour mesh at alpha 1
66
+ and above, reduced and locally refined by rig-c's `reduceMesh` under declared
67
+ bounds. Exactly one of `grid`, `contour` and `auto` per mesh.
68
+ - **`motion` is required in it** (#134): at least `maxLocalDeformation`, the bound
69
+ the reduced mesh's motion against its unreduced source on the idle must meet
70
+ before the part is written. A part the idle cannot deform is refused, never
71
+ passed.
72
+ - **`maxOvershoot` and `maxUndercut` take `null`** (#139), in `sourceBounds` and in
73
+ `targets.artFit`: measured and reported, not bounded. Leaving the field out is
74
+ still refused by name.
75
+ - **The acceptance loop** (#141) replays a less-reduced step when the motion gate
76
+ refuses the full reduction; it needs no field. **`motion.selection`** (#151,
77
+ opt-in) replaces its bisection with a budgeted multi-interval search.
78
+ - **The Stage B opt-ins** (#147): `boundaryRuns`, `retriangulate`, `removalOrder`.
79
+ - **`motion.gradation`** (#150, opt-in): the author's G for rig-c's allocation
80
+ contrast row.
81
+ - **`motion.residual`** (#152, opt-in): the skinning residual as a per-step veto.
82
+
83
+ Without any of these the mode's output is what it was before each was added: every
84
+ pull request that added one compared the opt-out run against the tree before it,
85
+ byte for byte.
86
+
87
+ ### The bytes a build writes
88
+
89
+ | change | what moved | measured |
90
+ | --- | --- | --- |
91
+ | #131, the automatic mode | nothing for a config without `auto` | 330 of 330 files of the three example builds identical, main at rig-c 2.15.0 against the change at 2.19.0 |
92
+ | #133, the winding | **the declared exception**: every mesh `triangles` triple `[a, b, c]` is written `[a, c, b]` (counter-clockwise in Spine world), in `rig.json`, the compiled `skeleton.json`, `skeleton.model.json` and the render's `geometry.json`; the `TEXTURE_STRETCH` entries in `check.json` that print a triangle's vertices and edge print them in that order; `spine.sha256` follows the skeleton bytes | every rendered PNG byte-identical before and after; the triangle index, the unordered edge, the frame, the ratio and the severity unchanged |
93
+ | #134, #137 to #142, #146, #147, #150, #152 | nothing | 330 of 330 at each, against the tree before it; the console differs in the one `rigc <version>` line per build where rig-c moved |
94
+ | #172 unit 1b, one mask under `stray` | nothing for a part without `auto.source.stray`; a part that declares it now builds where its extra islands at or under the figure refused it (`REDUCE_SOURCE_FAILS_ITS_ART_BOUNDS`): the islands are cleared from the art every reader of the mesh takes, and its row gains `stray_cleared` (islands, pixels, art pixels) and its mesh line a `stray cleared` clause; the written image is the part as assembled | the selftest's `SY01`–`SY06` on a synthetic crumb part; a part without `stray` reads the very mask object it read before (`SY03`) |
95
+ | #151, the multi-interval selection | nothing without `motion.selection` | measured on the selftest's fixture configs, not the example builds: rig.json, motion.json, mesh_report.json and the printed log identical in all six configurations; #152 then measured the example builds against the tree #151 left, 330 of 330 |
96
+
97
+ What to do: a consumer that compares a build with one 0.16.0 wrote, byte for byte,
98
+ expects the #133 exception and nothing else; one that reads the meshes (a renderer,
99
+ a culling pass, rig-c's own orientation rows) now reads every triangle
100
+ counter-clockwise in Spine world, as rig-c writes its own. Spine does not cull, so
101
+ nothing draws differently.
102
+
103
+ ## Since 1.0.0-rc.1
104
+
105
+ Every change below is additive to the interface: a field that was refused is now
106
+ accepted, or a build that was refused now builds; nothing a 1.0.0-rc.1 config could
107
+ say is removed or reads differently, outside the declared byte move below. No CLI
108
+ flag was added or removed.
109
+
110
+ - **Density-only regions** (#156, opt-in): an `auto.regions` entry may leave out both
111
+ `bone` and `band` to ask rig-c for density without touching any weight. One without
112
+ the other is refused by name (`CONFIG_REGION_BAND_NEEDS_BONE`,
113
+ `CONFIG_REGION_BONE_NEEDS_BAND`; at 1.0.0-rc.1 the same input was refused
114
+ `CONFIG_FIELD_PRESENT`, naming the missing field), and a region with both reads as
115
+ before. A config without such a region builds as before.
116
+ - **The skinning envelope's reference** (#169), **the declared byte move**: under
117
+ `motion.residual`, the envelope rig-c's reducer is sent is derived against the
118
+ lowest common ancestor of the slot's bone and every bone the part's weights bind,
119
+ where 1.0.0-rc.1 derived it against the slot's bone and, when a bound bone did not
120
+ hang below it, sent no target, so the residual veto did not apply. Such a part's
121
+ reduction, written mesh and `mesh_report.json` row move; a part whose bound bones
122
+ all hang below the slot's bone makes the same call as before. The
123
+ `skinning_residual` row keeps its shape: its `reference` names the bone the envelope
124
+ was derived against, and a part whose reference is not the slot's bone carries a
125
+ second `rule` sentence naming the rule. `ENVELOPE_BONE_NOT_BELOW_REFERENCE` keeps
126
+ its name and its check.
127
+ - **rig-c `^2.33.0`** (#163, #166, #173, from `^2.31.0`): 2.32.1 refuses, by name, a
128
+ refinement insertion whose triangle would read as degenerate (`MQ_DEGENERATE`)
129
+ instead of writing it (rigc#1311); 2.32.2 no longer misrefuses a motion sample on an
130
+ edge two triangles share (`COMPARE_UV_CARRIER_NOT_UNIQUE`, rigc#1323); 2.33.0 adds
131
+ named interior lines, which this package does not send. The three example builds
132
+ are byte-identical across the move (#173).
133
+
134
+ What to do: nothing for a config without `auto`. A config under `auto` that declares
135
+ `motion.residual` may write a different mesh than 1.0.0-rc.1 did, as above; a
136
+ consumer that compares builds byte for byte with 1.0.0-rc.1 expects that move and
137
+ nothing else.
@@ -0,0 +1,262 @@
1
+ # Interface stability
2
+
3
+ This page states what **1.0.0 holds stable**, and what it does not. Every item is
4
+ read off the tree: the command and flag lists below are held to
5
+ `cli.ts`, and the config field list to the loader in `src/config.ts`, by the
6
+ selftest's `TY13` and `TY14` (the `tree` suite), so neither list can drift from the
7
+ code without a red run. What changed for an author coming from 0.16.0 is
8
+ [MIGRATION.md](MIGRATION.md).
9
+
10
+ ## What "stable" means here
11
+
12
+ From 1.0.0 the package follows semantic versioning over the items on this page. A
13
+ stable item is not removed, renamed, or given another meaning inside a major
14
+ version; a new command, flag, optional config field, report key or refusal may
15
+ arrive in a minor version, because a reader written against the old surface still
16
+ reads it. A refusal may be retired in a minor version when what it refused becomes
17
+ accepted (0.13.0 retired two ik refusals that way, when rig-c's parser took them
18
+ over).
19
+
20
+ The list was frozen for review at the release candidate 1.0.0-rc.1, and 1.0.0 was
21
+ promoted from it after the owner's acceptance of the production evidence (issue #126,
22
+ item 7; `docs/evidence/production-trial.md` in the repository). Every interface
23
+ change between the two is additive, and [MIGRATION.md](MIGRATION.md)'s *Since
24
+ 1.0.0-rc.1* names each one, with the build bytes that moved.
25
+
26
+ Bytes are a separate promise, and a narrower one: **one version of this package
27
+ with one installed rig-c writes the same bytes for the same inputs** (*Determinism*
28
+ below). A build's bytes are not promised across versions. A later version may move
29
+ them, and when it does, the change that moves them declares which bytes and why (the
30
+ winding change of #133 is the example: [MIGRATION.md](MIGRATION.md)).
31
+
32
+ ## Commands and flags
33
+
34
+ Exit codes are part of the interface: **0** the command did what it says, **1** it
35
+ refused its input (every reason a `FAIL` line), **2** a usage error or a command
36
+ this version does not implement. No command is unimplemented at 1.0.0 (`LATER`
37
+ in `cli.ts` is empty). A refusal line has the shape
38
+ ` FAIL <RULE>: <object> — <value found>; <value required>`: the rule name is a
39
+ stable identifier, and the detail after it is prose that may be reworded. A command
40
+ also answers to the alias `spine-parts` as long as the install keeps it
41
+ ([MIGRATION.md](MIGRATION.md)). `-h`, `help` and `-v` are the short forms of
42
+ `--help` and `--version`. The flags' meanings are `rig-parts --help`'s; their
43
+ defaults are the help's too, and none is guessed from the art.
44
+
45
+ <!-- stable:commands -->
46
+ | command | flags |
47
+ | --- | --- |
48
+ | `layers` | one positional path: a wrapper directory, a `layers.json` or a `.psd` |
49
+ | `sheet` | `--source`, `--layers` (repeatable), `--out`; optional `--cell`, `--cols` |
50
+ | `inputs` | `--source`, `--config`, `--out` |
51
+ | `comfy` | `paint`: `--config`, `--out`; optional `--seeds`, `--seed0`, `--host`, `--wait`, `--timeout`, `--poll` |
52
+ | `comfy` | `seethrough`: `--image`, `--out`; optional `--resolution`, `--steps`, `--seed`, `--prefix`, `--offload`, `--lama`, `--nf4`, `--host`, `--wait`, `--timeout`, `--poll` |
53
+ | `assemble` | `--propose-plan` with `--source`, `--full`, `--head`, `--config`; or `--source`, `--full`, `--head`, `--config`, `--out`, optional `--seam` (near-white, silhouette), `--project` (core, visible) |
54
+ | `propose` | `--head-box` with `--full`, `--canvas` |
55
+ | `propose` | `--parts`, `--source`, `--out`; optional `--compare` or `--from-config` (one of them), `--keypoints`, `--person` and `--wrist-snap` (each with `--keypoints`) |
56
+ | `compare` | `--left`, `--right`; optional `--map` |
57
+ | `rig` | `--config`, `--parts`, `--out`; optional `--idle-keys` (ctl, direct), `--page-edges` (pot, free), `--pack-shape` (rect, polygon) |
58
+ | `check` | `--rig`, `--out`; optional `--parts`, `--source`, `--page-edges`, `--pack-shape`, `--requirements`, `--seam-pairs`, `--keep-stills` |
59
+ | `loop` | `--frames`, `--out`; optional `--palette` |
60
+ | `build` | `--config`, `--source`, `--full`, `--head`, `--out`; optional `--seam`, `--project`, `--page-edges`, `--pack-shape`, `--loop`, `--requirements`, `--idle-keys` |
61
+ | `compose` | `--scene`, `--out`; optional `--requirements`, `--accept` |
62
+ | (none) | `--version`, `--help` |
63
+ <!-- /stable:commands -->
64
+
65
+ `TY13` holds the first column to the commands `cli.ts` dispatches and the set of
66
+ flags named anywhere in the table to the set of flags `cli.ts` spells. It holds the
67
+ names, not which command takes which flag: that pairing is the CLI's, and the `cli`
68
+ suite's controls read it from the help.
69
+
70
+ ## The config contract
71
+
72
+ `src/config.ts` is the schema and the loader, and
73
+ [AUTHORING §3](AUTHORING.md#3-configjson-field-by-field) explains every field. The
74
+ rules that make the contract:
75
+
76
+ - **Every key is known or refused** (`CONFIG_KEY_KNOWN`), a required key that is
77
+ missing is refused by name (`CONFIG_FIELD_PRESENT`), and nothing is defaulted
78
+ from the art. A field absent where absence means "none" (a contour's `stray`, an
79
+ automatic mesh's `minAngle`) is written as that in the report, never filled in.
80
+ - **Two open doors, and nothing reads behind them**: `note` and any key ending in
81
+ `_note` hold a string anywhere an object is; any key beginning `x-` with a name
82
+ after it holds any JSON value in the same places. They are not open in `meshes`,
83
+ `regions` or `motion.blink.still`, whose keys are part names.
84
+ - **Coordinates** in `bones`, `meshes` and `motion` are rig pixels, y down, origin
85
+ top-left.
86
+ - **A mesh is one of three modes**: `grid` (the lattice, what `propose` writes),
87
+ `contour` (the traced outline with declared interior points) or `auto` (the
88
+ automatic mode: the contour mesh at alpha 1 and above reduced by rig-c's
89
+ `reduceMesh` under declared bounds, written only when its motion against the
90
+ unreduced source passes the author's bounds). Two, or none, is
91
+ `CONFIG_MESH_MODE`. The top-level default does not change: `propose` writes
92
+ `grid`, and a config that names no `auto` builds as it did before the mode
93
+ existed.
94
+ - **`constraints`** are rig-c's own rig-spec constraints (`RigConstraint` in
95
+ rig-c's `src/rig.ts`), handed to rigc as written; this loader checks their
96
+ `type`, their `name` and that every bone they name resolves.
97
+
98
+ The fields, object by object (a bold path is where the object sits; `<part>` is a
99
+ part name, `[i]` an entry of a list):
100
+
101
+ <!-- stable:config -->
102
+ - **config** — required by the full loader, in front of rig and build: `key`, `assemble`, `bones`, `meshes`, `regions`, `motion`; optional: `generation`, `seethrough`, `constraints`
103
+ - **generation** — required: `checkpoint`, `loras`, `trigger`, `identity`, `sampler`, `costume`, `negative_extra`, `style`, `negative_pose`, `latent`, `seed`; optional: `pose`, `control`
104
+ - **generation.loras[i]** — required: `name`, `strength`; optional: `strength_clip`
105
+ - **generation.sampler** — required: `steps`, `cfg`, `sampler`, `scheduler`
106
+ - **generation.control** — required: `skeleton`, `strength`, `end_percent`; optional: `model`
107
+ - **generation.control.skeleton**, the pose file it names when it is no built-in — required: `width`, `height`, `points`
108
+ - **seethrough** — required: `resolution`, `steps`, `seed`, `offload`; optional: `head_box`
109
+ - **assemble** — required: `rig_scale`, `plan` (from plain `assemble` on); optional: `extend_below_crop`, `patches`, `cuts`
110
+ - **assemble.extend_below_crop[i]** — required: `part`, `run`, `tag`
111
+ - **assemble.patches[i]** — required: `name`, `box`, `alpha`, `draw`
112
+ - **assemble.patches[i].draw**, when an object — required: `before`
113
+ - **assemble.cuts[i]** — required: `from`, `into`, `polygon`, `draw`, `overlap`; optional: `under`
114
+ - **assemble.cuts[i].draw**, when an object — required: `before`
115
+ - **bones[i]**, a single bone — required: `name`, `parent`, `at`; optional: `tip`
116
+ - **bones[i]**, a chain — required: `chain`, `parent`, `points`, `tip`
117
+ - **meshes.&lt;part&gt;** — exactly one of `grid`, `contour`, `auto`; required in every mode: `r`, `segments`; optional in every mode: `exponent`, `rule`; optional with `contour` or `auto`: `ribs`
118
+ - **meshes.&lt;part&gt;.ribs.&lt;chain&gt;** — required: `stations`
119
+ - **meshes.&lt;part&gt;.contour** — required: `tolerance`, `margin`, `spacing`; optional: `budget`, `stray`, `regions`
120
+ - **meshes.&lt;part&gt;.contour.regions[i]** — required: `name`, `shape`, `bone`, `spacing`, `band`, and `cx`, `cy`, `r` for a circle or `points` for a polygon
121
+ - **meshes.&lt;part&gt;.auto** — required: `source`, `sourceBounds`, `targets`, `influences`, `budget`, `minArtSamples`, `motion`; optional: `protect`, `regions`, the three Stage B opt-ins `boundaryRuns`, `retriangulate`, `removalOrder`, and `stimulus`
122
+ - **meshes.&lt;part&gt;.auto.source** — required: `tolerance`, `margin`, `spacing`; optional: `stray`
123
+ - **meshes.&lt;part&gt;.auto.sourceBounds** and **meshes.&lt;part&gt;.auto.targets.artFit** — required: `minCoverage`, `maxOvershoot`, `maxUndercut` (each of the last two a number or null, the bound declared absent)
124
+ - **meshes.&lt;part&gt;.auto.targets** — required: `artFit`, `maxBoundaryDeviation`; optional: `minAngle`
125
+ - **meshes.&lt;part&gt;.auto.influences** — required: `maxInfluences`, `minWeight`
126
+ - **meshes.&lt;part&gt;.auto.budget** — required: `maxCandidates`
127
+ - **meshes.&lt;part&gt;.auto.motion** — required: `maxLocalDeformation`; optional: `maxStretch`, `minStretch`, `deformMayFold`, `gradation`, `selection`, `residual`
128
+ - **meshes.&lt;part&gt;.auto.motion.selection** — required: `policy`, `maxProbes`
129
+ - **meshes.&lt;part&gt;.auto.motion.residual** — required: `maxResidual`
130
+ - **meshes.&lt;part&gt;.auto.protect** — optional: `hull`, `vertices`, `edges`, `regionBoundaries`, `weightJump`, `influences`
131
+ - **meshes.&lt;part&gt;.auto.regions[i]** — required: `name`, `shape`, `maxEdgeLength`, `transition`, `grade`, `minArtSamples`, and `cx`, `cy`, `r` for a circle or `points` for a polygon; optional: `bone`, `band` (both or neither; with neither the region is density only)
132
+ - **meshes.&lt;part&gt;.auto.boundaryRuns** — required: `maxVertices`
133
+ - **meshes.&lt;part&gt;.auto.stimulus**, or each entry of it when a list — required: `chain`, `degrees`
134
+ - **regions.&lt;part&gt;** — a bone name
135
+ - **motion** — required: `duration`, `tracks`; optional: `blink`, `animations_from`
136
+ - **motion.tracks[i]**, a single track — required: `bone`, `prop`, `amp`, `period`, `phase`; optional: `base`
137
+ - **motion.tracks[i]**, a chain track — required: `chain`, `amps`, `period`, `phase`, `lag`
138
+ - **motion.blink** — required: `t`, `eyes`, `squash`; optional: `brows`, `brow_drop`, `still`
139
+ - **motion.blink.still.&lt;part&gt;** — required: `row`, `bone`
140
+ - **motion.animations_from**, the file it names — required: `spec`, `animations`
141
+ - **proposal.json**, the file propose writes — `bones`, `meshes`, `regions`, `motion` under the rules above, and `notes`
142
+ <!-- /stable:config -->
143
+
144
+ `TY14` holds the set of field names in backticks above to the set of names the
145
+ loader's object checks spell (every `c.object(…)` in `src/config.ts`, with the lists
146
+ they name), in both directions, and refuses an object check whose key list it cannot
147
+ read. It holds the names, not their nesting or which are required: the `config`
148
+ suite's controls hold those, refusal by refusal.
149
+
150
+ The values a field takes (`retriangulate` is "delaunay", `removalOrder`
151
+ "deformation-load", `selection.policy` "multi-interval"; the units and ranges of
152
+ every number) are AUTHORING §3's tables, and the loader refuses any other by name.
153
+
154
+ ## Files this package writes
155
+
156
+ | file | written by | what is stable |
157
+ | --- | --- | --- |
158
+ | `parts.json`, `parts/<name>.png` | `assemble`, `build` | one record per part: `from`, the box `x`, `y`, `w`, `h` (rig px), the pixel counts `src/parts.ts` documents (`opaque_px`, `visible_px`, `occluded_px`, `projected_core_px`, `source_px_taken`, `visible_not_projected_px`, `refused_drift_px`, `merged_px`, `seam_override_px`, and `fringe_pushed_back` when not empty); `rig_size`, `scale_rig_per_source`, `ghost_px`, `recomposite` |
159
+ | `rig/rig.json`, `rig/motion.json`, `rig/images/` | `rig`, `build`, `compose` | rig-c's rig spec and motion spec, `spec` `rigc-rig/1` and `rigc-motion/1`: the format is rig-c's, and this package writes only what rig-c's parser accepts |
160
+ | `rig/mesh_report.json` | `rig`, `build` | one row per mesh: `part`, `vertices`, `triangles`, `hull`, `bones`, `max_influences`, `mean_influences`, `art_coverage`, then `grid` (a lattice); `mode` "contour" with `params`, `contour`, `regions`; or `mode` "auto" with `settings`, `source`, `result`, `residuals`, `worst_residual`, `worst_region`, `motion_amplitude`, `termination`, `weights`, `regions`, `deformation`, `quality_report` (rig-c's `mesh-quality-report/1` document whole), `motion_report`, and, only when they apply, `stray_cleared` (after `source`, when `source.stray` is declared), `skinning_residual` and `replay` (`AutoMeshReport` in `src/rig.ts`); in every mode, `exponent` when the mesh declares one (after `grid`, or after `mode`); `ribs` when a contour or auto mesh declares them (after `exponent`, or after `mode`), and then `contour.ribs` (`source.contour.ribs` in the automatic mode) |
161
+ | `check/check.json` and the rest of `check/` | `check`, `build`, `compose` | the reference's fields in its order (`gate_spine_html_green`, `rigc_entry`, `pack_mode`, `loop_max_diff`, the seam figures — `seam_mean`, `seam_px_over_40`, `seam_px_over_80` and, from issue #216, `seam_frame_scale`, the frame scale the bar divides the count by), `loop_physics` after `loop_max_diff` when the rig declares a physics constraint, `seam_pairs` after the seam figures when the seam bar fails or `--seam-pairs` asks (each row's picture under `check/seam/`; `--keep-stills` leaves the setup-pose still and its `frames.json` under `check/setup_still/`), then the judgement lines (`BREATH_VISIBLE`, `BLINK_NO_HOLE`, `CHAIN_LAG`, `TIP_OVER_ROOT`, `STILL_REGIONS_DARK`, `TEXTURE_STRETCH`), `RECOMPOSITE_HOLES`, `SETUP_POSE_VS_SOURCE`, `skipped`, a `requirements` block under `--requirements`, and `PASS`; `check/build/skeleton.json`, `.atlas` and `.png` are the packed artifact rig-c writes |
162
+ | `proposal.json`, `render/landmarks*.png` | `propose` | the config's four rig sections and `notes` |
163
+ | `basis.json` | `propose` | spec `spine-parts-basis/1` |
164
+ | the scene report | `compose` | spec `spine-parts-scene-report/1` |
165
+ | `idle.png`, `idle-indexed.png`, `idle.gif` | `loop`, `build --loop` | APNG and GIF encodings of the rendered idle |
166
+
167
+ Files authors write for this package, each with a spec id the reader holds:
168
+ `spine-parts-requirements/1` (`check --requirements`), `spine-parts-scene/1`
169
+ (`compose --scene`), `spine-parts-keypoints/1` (`propose --keypoints`),
170
+ `spine-parts-bonemap/1` (`compare --map`). The spec ids keep the package's former
171
+ name on purpose: they name a file format, not the tool, and a file written before
172
+ the rename still reads. They do not change at 1.0.
173
+
174
+ ## Environment
175
+
176
+ The installed package reads two environment variables and no other: `PATH`, where
177
+ the launcher finds Bun and the CLI finds the `rigc` its own `node_modules` holds,
178
+ and `COMFY_HOST`, which `comfy paint` and `comfy seethrough` read when `--host` is
179
+ not given (it has no default). `RIG_PARTS_CORPUS` and `RIG_PARTS_SELFTEST_JOBS`,
180
+ with their former `SPINE_PARTS_` names read when they are not set, are the
181
+ selftest's, a development interface of this repository: the selftest does not ship
182
+ in the package.
183
+
184
+ ## rig-c
185
+
186
+ `dependencies` takes `rig-c` `^2.33.0`: 2.33.0 or any later 2.x. Bun 1.2 or later
187
+ runs the package (`engines`). What this package relies on in rig-c, every import
188
+ read off `src/` and `cli.ts`:
189
+
190
+ - the named entries `rig-c/mesh` (the outline functions, `measureAuthoredMeshFit`,
191
+ `reduceMesh`, `skinningEnvelopeBone`, `writeMeshQualityReport` and their types)
192
+ and `rig-c/meshcompare` (`compareMeshesInMotion`);
193
+ - the deep paths its `exports` map carries: `rig-c/src/rig.ts` (`parseRigSpec`,
194
+ `RIG_SPEC_VERSION`, the constraint keys), `rig-c/src/errors.ts`,
195
+ `rig-c/src/png.ts`, `rig-c/src/transform.ts` (the y flip, through
196
+ `src/coords.ts` only), `rig-c/tools/plate.ts` (the PNG codec) and
197
+ `rig-c/tools/font5x7.ts`;
198
+ - the `rigc` command: `build` and `render`, and `--version`, whose `entry:` line
199
+ says which validator gated a build (`check.json`'s `rigc_entry`).
200
+
201
+ A rig-c release that moves any of these breaks this package by name, and the
202
+ install smoke is where that shows first. No Spine runtime is a dependency: an
203
+ install is gated by rigc's own validator, and `@esotericsoftware/spine-core` is a
204
+ development dependency of this repository only.
205
+
206
+ ## What is not stable
207
+
208
+ - **The evidence documents** under `docs/evidence/`: their layout, columns and
209
+ figures are a measurement record of one tree on one rig-c, regenerated when the
210
+ tools or rig-c move.
211
+ - **The tools** under `tools/` (the matrix, the surveys, the comparisons) and their
212
+ command lines, and the scripts under `scripts/`.
213
+ - **The selftest**: its control names, counts and line wording.
214
+ - **Console prose** beyond the shapes above: the detail after a rule name, the
215
+ wording of a note, the order of informational lines.
216
+ - **The examples' `expected/` outputs**: they are this repository's regression
217
+ record and move with any change that declares a byte move.
218
+ - **Bytes across versions**, as stated at the top.
219
+
220
+ ## Bounded time, and what the checks cost
221
+
222
+ The automatic mode's search is bounded by counts the author declares or the call
223
+ derives, never by a clock (`src/` reads none): rig-c's `reduceMesh` tries at most
224
+ `budget.maxCandidates` steps, the acceptance loop replays at most ⌈log₂(N − I)⌉
225
+ removal steps (N the call's accepted operations, I the refinement's), and the
226
+ multi-interval selection at most `motion.selection.maxProbes`, each replay one
227
+ unpacked gated build and one motion comparison. Wall time is therefore a property of
228
+ the input and the machine. Measured: the evidence tools run every cell under a
229
+ 600 s cap and a whole matrix under 2,700 s (`docs/evidence/auto-mesh-matrix.md`,
230
+ *re-running*); one `reduceMesh` call on the public parts took 0.7 s to 10.7 s at
231
+ rig-c 2.23.0 (the same document's quiet timing table, a remote WSL runner, pool,
232
+ load under 2); at rig-c 2.31.0 the whole rig stage of one automatic part, motion
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
235
+ spread of ±15 % on that part (pull request #152's paired exclusive timing, remote
236
+ 20-core runner; the surveys print wall time to standard error, not into the
237
+ documents). On CI (`ubuntu-latest`), the last two green runs on `main` took 4 min
238
+ 54 s and 8 min 28 s for the full selftest (842 controls over 45 suites at
239
+ `22b2c5a`, with the public examples fetched; the job's limit is 20 minutes) and
240
+ 42 s and 41 s for the install smoke (6 cases; limit 10 minutes), at `8be4cd1` and
241
+ `22b2c5a` respectively. None of these figures is a promise: they are what the named
242
+ runs measured.
243
+
244
+ ## Determinism
245
+
246
+ The same inputs, with the same version of this package and the same installed
247
+ rig-c, write the same bytes: fixed key order in every JSON written, stable sorts, no
248
+ clock, no randomness and no locale-sensitive formatting. `src/` is pure outside
249
+ `src/comfy/` (`TY06` refuses a clock, randomness or network call anywhere else under
250
+ `src/`). The selftest holds it by running the same thing twice and comparing the bytes:
251
+ `PN01` (the PNG codec), `PT01` (`parts.json` round trip), `AS07` (`assemble`
252
+ from the CLI), `SK04` (the skeleton), `RG03` (two lattice builds), `CW20` and
253
+ `CT20` (a contour rig and a contour mesh), `AM24` (an automatic mesh), `MO11`,
254
+ `MO27`, `MO44`, `MO50`, `MO63` and `MO74` (the motion gate, the acceptance
255
+ loop's replay, every Stage B opt-in, a gradation, the multi-interval selection's
256
+ policy path and the residual veto), `CK02`, `CK33` and `CK79` (`check`, its
257
+ stretch geometry, and `check --requirements`), `DG13` (`basis.json`), `LP08`
258
+ (the indexed APNG) and `ST26` (the `compare` printout). With the public examples
259
+ fetched, the `chain` suite builds each of them and holds `parts.json`
260
+ (`CH02`), `rig.json`, `motion.json` and `mesh_report.json` (`CH03`),
261
+ `check.json` (`CH04`) and the gate file (`CH05`) to its tracked `expected/`,
262
+ field by field, with the tolerances `CH07` plants against.
package/package.json CHANGED
@@ -1,6 +1,72 @@
1
1
  {
2
2
  "name": "@rig-c/parts",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.5.3",
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
+ "type": "module",
6
+ "bin": {
7
+ "rig-parts": "./bin/rig-parts.cjs",
8
+ "spine-parts": "./bin/rig-parts.cjs"
9
+ },
10
+ "engines": {
11
+ "bun": ">=1.2.0"
12
+ },
13
+ "license": "MIT",
14
+ "author": "firejune",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/firejune/rig-parts.git"
18
+ },
19
+ "homepage": "https://github.com/firejune/rig-parts#readme",
20
+ "bugs": "https://github.com/firejune/rig-parts/issues",
21
+ "keywords": [
22
+ "spine",
23
+ "spine2d",
24
+ "spine-2d",
25
+ "ai",
26
+ "ai-agents",
27
+ "rigging",
28
+ "character-rigging",
29
+ "character-parts",
30
+ "layer-decomposition",
31
+ "see-through",
32
+ "anime",
33
+ "live2d-alternative",
34
+ "weighted-mesh",
35
+ "skeletal-animation",
36
+ "psd",
37
+ "cli"
38
+ ],
39
+ "files": [
40
+ "bin/rig-parts.cjs",
41
+ "cli.ts",
42
+ "src",
43
+ "workflows",
44
+ "docs/AUTHORING.md",
45
+ "docs/MIGRATION.md",
46
+ "docs/STABILITY.md",
47
+ "skills",
48
+ "NOTICE.md"
49
+ ],
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "scripts": {
54
+ "fetch-examples": "bash scripts/fetch-examples.sh",
55
+ "selftest": "bun selftest.ts",
56
+ "smoke": "bun scripts/install_smoke.ts",
57
+ "typecheck": "bunx tsc --noEmit",
58
+ "lint": "bunx eslint .",
59
+ "prepublishOnly": "bun run typecheck && bun run lint && bun run selftest"
60
+ },
61
+ "dependencies": {
62
+ "ag-psd": "^31.0.2",
63
+ "rig-c": "^2.33.0"
64
+ },
65
+ "devDependencies": {
66
+ "@esotericsoftware/spine-core": "4.3.13",
67
+ "@types/bun": "^1.4.2",
68
+ "eslint": "^10.11.0",
69
+ "typescript": "^5.9.3",
70
+ "typescript-eslint": "^8.70.1"
71
+ }
72
+ }
@@ -0,0 +1,167 @@
1
+ ---
2
+ name: rig-parts
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
+ 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.
6
+ ---
7
+
8
+ # rig-parts — a painting to a Spine rig, for agents
9
+
10
+ rig-parts merges See-through's two layer runs over one painting into rig-space
11
+ parts, authors a rig spec and a motion spec over them, and hands those to
12
+ rig-c, which compiles, gates, packs and renders. You cannot see the painting,
13
+ the layers or the rig. The printed lines, `docs/AUTHORING.md` and the files each
14
+ stage writes are the whole interface.
15
+
16
+ ## Non-negotiables
17
+
18
+ - **rig-c's gate is never bypassed.** rig-parts writes no Spine data
19
+ itself; `rig` writes only after rigc's `build` gate is green, and `build`'s
20
+ artifact is what rigc wrote. There is no flag that skips it, and none may be added.
21
+ `check.json`'s `rigc_entry` names which gate ran: rigc's own validator in an
22
+ install, the spine-core round trip where the runtime is installed beside rigc.
23
+ - **No value is invented.** A missing config field is a refusal naming it. Take a
24
+ value from the command that proposes it (`propose --head-box`,
25
+ `assemble --propose-plan`, `propose`) or decide it yourself — never guess one
26
+ because the tool refused.
27
+ - **The refusal is the instruction.** `FAIL RULE: object — detail` names the object,
28
+ the value found and the value required; AUTHORING §6 maps every rule to the field
29
+ or input that has to change.
30
+ - **Green is not "looks right".** `check` measures the gates, the seam, the loop and
31
+ six judgement lines (`BREATH_VISIBLE`, `BLINK_NO_HOLE`, `CHAIN_LAG`,
32
+ `TIP_OVER_ROOT`, `STILL_REGIONS_DARK` — its face half in the head's own frame —
33
+ and `TEXTURE_STRETCH`) (AUTHORING §7). A judgement line that says
34
+ SKIP was not verified: report it as such, with its reason, never as passed.
35
+ No line judges a bang over the face or the eyes: `STILL_REGIONS_DARK`'s
36
+ `crossing` reports how deep each one swings, and only an eye can say whether
37
+ that reads right.
38
+ - **What a scene asks is declared, not assumed.** When the request says what the
39
+ motion must do — a hand on a cup, a sleeve taking half an arm's turn, a joint
40
+ inside a range, a fringe that must not part from the face — write it into a `spine-parts-requirements/1` file and pass
41
+ `check --requirements <file>` (or `build --requirements`); every bar in it is the
42
+ requester's, never yours to invent (AUTHORING §7, *Declared requirements*). Each
43
+ line is PASS, FAIL or NOT MEASURABLE; a NOT MEASURABLE is not green, and a kind the
44
+ file does not declare was not measured — say so, never "passed".
45
+ - **A hole in the layers is invisible to every bar.** Painting that no part holds is
46
+ missing from the setup pose and from the flat stack alike, so the seam passes over
47
+ it. `assemble` lists it (`uncovered hole N: <px> px at x,y wxh (between …)`) and
48
+ paints it red in `recomposite_error_rig.png`; `check` copies it into `check.json` as
49
+ `RECOMPOSITE_HOLES`, a REPORTED line with no bar. Read it; never report it as a
50
+ pass.
51
+
52
+ ## The loop
53
+
54
+ 1. `rig-parts inputs --source <painting> --config config.json --out <dir>` writes
55
+ `st_input_full.png`, the painting on a white square. The config needs only `key`,
56
+ `seethrough` and `assemble.rig_scale` at this point. Run See-through on it — any
57
+ route; the optional `comfy seethrough` adapter only talks to a ComfyUI box.
58
+ 2. `rig-parts layers <full run>` — read the table. A `WARN PLAN_LAYER_…` line names
59
+ a layer See-through invented (a translucent haze, or one out of proportion);
60
+ the plan step leaves it out and says so in its `notes`.
61
+ 3. `rig-parts propose --head-box --full <full run> --canvas <W>x<H>` → put
62
+ `head_box` in the config, run `inputs` again (it now also writes
63
+ `st_input_head.png`, the crop at that box), and run See-through on the crop.
64
+ 4. `rig-parts assemble --propose-plan …` → `config.assemble.plan` and
65
+ `extend_below_crop`.
66
+ 5. `rig-parts assemble … --out work` — read the `uncovered hole` lines and look at
67
+ `work/render/recomposite_error_rig.png`; a large red hole between two parts is a
68
+ gap See-through left (a skirt split into two legs), fixed in the plan or the layers,
69
+ not in the rig. Then `rig-parts propose --parts work/rig
70
+ --source <painting> --out work` → copy `bones`, `meshes`, `regions`, `motion`
71
+ from `proposal.json` into the config. `assemble` needs the plan and none of
72
+ those four; do not stub them to get past it (AUTHORING §4 says what each step
73
+ requires). If an `uncovered hole` stays large with the plan right — a piece
74
+ of the figure neither run holds, red in `recomposite_error_rig.png` — add an
75
+ `assemble.patches` entry (a rig-pixel box, `alpha: "silhouette"`, drawn
76
+ `"back"` and reaching under its neighbours, its bone in `regions`) and assemble
77
+ again; never add a part to `rig/` or `parts/` by hand (AUTHORING §5).
78
+ One layer holding two things that must move apart (a scarf end inside
79
+ `topwear`, both arms in one `handwear`): add an `assemble.cuts` entry — a
80
+ polygon in rig pixels read off `work/rig/parts/<part>.png` plus its
81
+ `parts.json` `x`, `y`, a new name, a `draw`, an `overlap` (the band the part
82
+ keeps under the piece's edge; 1 px closed the seam on scarf) — and give the piece its own
83
+ `meshes` entry; the `cut:` line gives the split. At overlap 0 a cut through
84
+ opaque art leaves a seam `check` reads (AUTHORING §5).
85
+ A seated or reclining figure: add `--keypoints <file>` (body-18 joints in
86
+ painting px, each observed, occluded or missing; AUTHORING §3, *A posed
87
+ figure*) so the neck, hip, chest and sleeves follow the pose and LINT reads
88
+ the joints, not screen y. Never write a joint you did not get from an
89
+ estimator or the painting: say `missing` and let the rule stand in.
90
+ 6. Correct against `render/landmarks.png` and `note:` lines; a
91
+ `coverage … not checked` line is a bone no check read (the line says why),
92
+ and `basis.json` beside the proposal says what each bone rests on — check
93
+ the `ratio` bones and any with a `fallback` first. `propose …
94
+ --from-config config.json` (with the same `--keypoints`) until it prints no
95
+ `LINT` line. `rig-parts compare
96
+ --left work/proposal.json --right config.json` lists what the correction changed,
97
+ bone by bone — origin, parent, tip, length, direction (AUTHORING §4).
98
+ A constraint the motion needs (an ik reaching a scene target, physics on a
99
+ link) goes in `config.constraints`, in rig-c's own rig-spec shape: the
100
+ loader resolves the bones it names and nothing else, and rigc's gate refuses
101
+ the rest in its words. A scene target is a single bone under `root`. A two-bone
102
+ ik over links the idle keys needs `--idle-keys direct` on `rig` or `build`
103
+ (rigc refuses the pair the link's control splits, and the line names the flag
104
+ on the command that ran; AUTHORING §3).
105
+ 7. `rig-parts build --config … --source … --full … --head … --out out --loop`
106
+ (add `--idle-keys direct` when step 6 said so).
107
+ It stops at the first stage that refuses, printing that stage's lines under
108
+ `[assemble]`, `[rig]` or `[check]`. Fix what the FAIL line names and build again.
109
+ 8. Read `out/check/check.json` — the six judgement lines the same way as the seam
110
+ and the loop: a FAIL names the field to change (AUTHORING §6);
111
+ `TEXTURE_STRETCH` names the worst mesh triangle (slot, triangle, vertices, edge,
112
+ frame), so quote it even on a PASS. Quote
113
+ `RECOMPOSITE_HOLES` (uncovered px, hole count, the largest hole's box) in the
114
+ report whatever `PASS` says. The artifact is the three paths the build prints
115
+ last: `check/build/skeleton.json`, `skeleton.atlas` and the packed page. Report
116
+ them with the pack line and the check figures verbatim.
117
+
118
+ Several characters in one rig: build each one green on its own, then
119
+ `rig-parts compose --scene scene.json --out scene` (spec `spine-parts-scene/1`:
120
+ the canvas, each character's `build` and `offset`, an optional plate with its
121
+ `provenance`, and the `order` of the characters' slots, back to front). You write
122
+ the order and the offsets; nothing infers them, nothing scales a character, and
123
+ nothing detects or separates people. Report the plate's provenance as you declared
124
+ it and the order as `scene.json` records it (AUTHORING §7, *Composing several
125
+ characters*).
126
+
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
129
+ the reference implementation's rule. `--project visible` lets thin visible parts
130
+ (lashes, brows, irises) take the painting's pixels, which the default `core` rule
131
+ erodes away. Name both rules you used in your report, and quote the assemble
132
+ `pixels:` line: its occluded share is hidden art, its "visible but not projected"
133
+ share is synthesis where the painting was there to be taken.
134
+
135
+ ## What this will not do
136
+
137
+ - Run See-through or generate the painting itself. The optional `comfy seethrough`
138
+ and `comfy paint` commands drive a ComfyUI box you name; nothing else here reaches
139
+ a GPU or the network.
140
+ - Give a layer two depths: a layer in front of another in one place and behind it in
141
+ another is right in the still and wrong in motion.
142
+ - Propose, key or judge any animation but the looping `idle`, or lip-sync: every slot
143
+ holds one attachment, so nothing swaps a part's image. Expressions and a jiggle are
144
+ yours to build on top (below).
145
+ - Write animated WebP: `loop` writes GIF and APNG.
146
+ - Know what the art does not tag: a swinging element painted inside another layer,
147
+ hair of an unfamiliar shape, whether an accessory swings. Those are yours to add.
148
+ - Promise a success rate. Three public characters and eight private ones check green;
149
+ that is all that has been measured.
150
+
151
+ ## Where to read next
152
+
153
+ [docs/AUTHORING.md](https://github.com/firejune/rig-parts/blob/main/docs/AUTHORING.md)
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`,
156
+ the copy that matches the version you run. Two recipes there cover what this package
157
+ leaves to you:
158
+
159
+ - An expression or any other named animation: AUTHORING §3, *Recipe: expressions and other
160
+ named animations* (`motion.animations_from`; built and gated with the rig, not measured).
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`
163
+ carries one, and its slow idle barely moves it).
164
+
165
+ A `RIG_RIGC_GREEN` or `CHECK_RIGC_GREEN`
166
+ line quotes rig-c's own assertion; rig-c's guide for those is
167
+ `node_modules/rig-c/docs/AUTHORING.md`, and its `rigc` skill covers the compiler.