@rig-c/core 2.86.0 → 3.0.1
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/README.md +3 -1
- package/docs/AUTHORING.md +1 -1
- package/package.json +10 -7
- package/skills/rigc/SKILL.md +41 -28
- package/skills/rigc-face/SKILL.md +34 -16
- package/skills/rigc-rigging/SKILL.md +13 -6
- package/src/assertions/emitted/index.ts +1 -1
- package/src/assertions/harness.ts +2 -3
- package/src/assertions/kinds.ts +1 -20
- package/src/assertions/model/index.ts +1 -1
- package/src/assertions/report.ts +0 -11
- package/src/cli/shared.ts +1 -9
- package/src/core/entry.ts +2 -1
- package/src/motion.ts +3 -0
- package/src/render_read.ts +1 -0
- package/src/validate.ts +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/rig-c/core/main/assets/banner.svg" alt="
|
|
2
|
+
<img src="https://raw.githubusercontent.com/rig-c/core/main/assets/banner.svg" alt="@rig-c/core — AI-authored 2D rigging and animation, verified before it is written" width="100%" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-38BDF8.svg?style=flat-square" alt="license" /></a>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
+
# @rig-c/core
|
|
12
|
+
|
|
11
13
|
**AI-authored 2D rigging and animation, verified before it is written.** rigc is
|
|
12
14
|
a rig compiler: a rig spec and a motion spec in, skeleton data out — in the Spine 4.3
|
|
13
15
|
format, with rigc's own compiled model beside it —
|
package/docs/AUTHORING.md
CHANGED
|
@@ -367,7 +367,7 @@ What the flags mean:
|
|
|
367
367
|
| `--manifest` | a cut manifest. Only for a rig with **measured art** behind it; a foreign skeleton has none |
|
|
368
368
|
| `--cut` | `build`, `explain` and `validate`: look up a named cut in `--cuts <cuts.json>`, **instead of** `--rig`/`--motion`/`--out` — the two spellings are one build stated two ways and are refused together. A `cuts.json` is `{ "<name>": { "rig": …, "motion": …, "out": …, "manifest"?: … } }`, every path in it relative to the table's own file, so the table lives with the project that owns the art |
|
|
369
369
|
| `--cuts` | the `cuts.json` `--cut` names. Required beside it — `--cut` alone is refused, with no guess at where the table lives |
|
|
370
|
-
| `--profile` | `spine` = the 36 validity rules (**the default**) · `rig-play` = all 50, opt-in.
|
|
370
|
+
| `--profile` | `spine` = the 36 validity rules (**the default**) · `rig-play` = all 50, opt-in. Since 3.0, `spine-html` is refused with `--profile "spine-html"; known profiles: spine, rig-play` (usage error, exit 2); replace it with `--profile rig-play`, which runs the same rules |
|
|
371
371
|
| `--report` | `build` and `repack`: also write the gate's report as a JSON document (`build-report/1`) to this file — every gate's `PASS`, `SKIP` and `FAIL` rows, its summary figures and stats line, which supplier judged it, and every `pack:` line's figures. Written when the command writes `--out` and when a gate is red, before the exit; a file already at the path is removed first, so a compile error or a refused repack leaves none. Never inside `--out`, refused by name. The printed lines are byte-identical with it and without it — **§5.3** |
|
|
372
372
|
| `--candidate` | `check`, `bench`, `render`, `inspect`, `preview`, `chainfit` and `vote` only: a **compiled** artifact — the directory `build --out` wrote, or a `skeleton.json` path. A directory holding no `skeleton.json`, or a path with nothing at it, is refused `nothing at <path>`, exit 2, nothing written, by every command that takes a build — `validate <dir>` and a directory given to `diff` included (`RC27`). `--atlas <path>` names the atlas when it does not sit beside the skeleton. On `render` and `check` a rigc build whose `skeleton.model.json` is `rigc-compiled/3` or `/2` needs no atlas at all: with no `--atlas` and no atlas beside it, it is drawn from the document's `pages`, the same frames, geometry and figures as with it, and the `atlas` line says `— not there`. An atlas that is there is still read, and held to `pages`: one that differs (edited after the build) is drawn through spine-core, and the `poser` line names the first difference. A build drawn through an atlas that is not there — a `rigc-compiled/1` document, or a build the core refuses — is refused `nothing at <the atlas>: … is drawn through its atlas (<why>)`, exit 2, nothing written; a Spine export without its atlas is refused `nothing at <the atlas>` as it always was. A directory whose files are not one build — a `skeleton.json` or a `skeleton.atlas` from another build beside this one's `skeleton.model.json` — is drawn through spine-core where the runtime can load the pair, the `poser` line naming the two digests or the atlas's first difference; where it cannot, it is refused `<skeleton> does not load against <the atlas>: spine-core draws this pair (<the poser line's why>) and could not resolve it — "<the runtime's own words>". <dir> is not one build: …`, exit 2, nothing written (`RC18`) — another build's skeleton beside this build's atlas typically ends `"Region not found in atlas: <region> (attachment: <name>)"`. Rebuild, or put the build's own three files back beside each other. A Spine export beside an atlas it was not exported with is refused in the same words, ending `The skeleton and the atlas are not one pair`. An atlas copied from another build's directory usually stops earlier, at its pages — their paths are relative to the directory it was written in — and is refused naming the first one: `nothing at <the page>: <the atlas> names it as a page, and spine-core draws this pair through that atlas (<why>). … <dir> is not one build: …`, exit 2, nothing written (`RC18`); an export whose atlas names a page that is not there is refused the same way, ending `and the page has to be there`. A build moved or copied whole away from the directory it was built in stops at the same place, on either poser, and is refused naming the page and the file that names it: `nothing at <the page>: <the skeleton.model.json> names it as a page, and the core draws this build from it. A page path is relative to the build's directory, so a build moved or copied away from the directory it was built in names pages that are not here — build it again where it is, or build it with --copy-images, which writes its pages beside it` (under `--poser spine`, `<the atlas> names it as a page, and spine-core draws this pair through that atlas (--poser spine)` with the same ending), exit 2, nothing written (`RC21`); only where the core refused the files does a page refusal say the directory is not one build. `bench --bones` and `rigc bonedist` — on its `--candidate` and on its `--reference` — refuse a pair the runtime cannot load in the words above with `spine-core poses this pair (bonedist's candidate: …)` or `(bonedist's reference: …)`, exit 2, nothing written (`RC20`); they read no page image, so a build whose pages are elsewhere is measured as it is in place. A `skeleton.json` that is not JSON is refused `rigc: cannot read <the file>: <the parser's words> (line N, column N)`, exit 2, by `render`, `check`, `bench` and `bonedist` as by every other command that reads one (`RC22`). With the atlas gone, `check` on a `rigc-compiled/3` build reads its pages' `scale:` lines off the document, so its texture note and `check.json`'s `textureFrom.candidateScales` are what they are with the atlas; on a `/2` build its texture note says whether the atlas declares a `scale:` line is not read (that document does not state one), and `candidateScales` is `null` (`RC13`). **`vote` and `preview` take it more than once**: `vote` 2–4 times, one per pane, labelled A, B, C, D in the order given; `preview` any number of times, one pane per candidate in the order given, each headed by its path and its gate line, and the same skeleton twice (a directory and its `skeleton.json` are one) is refused by name. `--atlas` goes with one candidate only. Everywhere else a repeat is a typo and is refused |
|
|
373
373
|
| `--animation` | `render`, `preview` and `vote` only: which animation to show. The default is **every** one for `render`, the **first** for `preview` (each candidate's own first, with several), and for `vote` the first of candidate A. A name the skeleton does not have is refused, with the ones it does have listed — and for `vote` and a several-candidate `preview`, so is a name that only *some* candidates have, naming the one that lacks it |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rig-c/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "AI-authored 2D rigging and animation, verified before it is written. rigc compiles a rig spec into skeleton data in the Spine 4.3 format, gates it with named assertions held to a spine-core round trip's verdicts, and emits nothing that fails. Ships as an agent skill.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,15 +22,18 @@
|
|
|
22
22
|
"./runtime": "./src/runtime/index.ts",
|
|
23
23
|
"./cli": "./cli.ts",
|
|
24
24
|
"./package.json": "./package.json",
|
|
25
|
-
"./*.ts": "./*.ts",
|
|
26
|
-
"./*.mjs": "./*.mjs",
|
|
27
|
-
"./*.cjs": "./*.cjs",
|
|
28
|
-
"./*.json": "./*.json",
|
|
29
|
-
"./*.md": "./*.md",
|
|
30
25
|
"./LICENSE": "./LICENSE",
|
|
31
26
|
"./bin/rigc": "./bin/rigc.cjs",
|
|
32
27
|
"./tools/png_probe": "./tools/png_probe.mjs",
|
|
33
|
-
"
|
|
28
|
+
"./deformgen": "./src/deformgen.ts",
|
|
29
|
+
"./environment": "./src/environment.ts",
|
|
30
|
+
"./motion": "./src/motion.ts",
|
|
31
|
+
"./passthrough": "./src/passthrough.ts",
|
|
32
|
+
"./stop": "./src/stop.ts",
|
|
33
|
+
"./meshrasters": "./src/meshrasters.ts",
|
|
34
|
+
"./seam": "./src/seam.ts",
|
|
35
|
+
"./folds": "./src/folds.ts",
|
|
36
|
+
"./model": "./src/model.ts"
|
|
34
37
|
},
|
|
35
38
|
"engines": {
|
|
36
39
|
"bun": ">=1.4.0"
|
package/skills/rigc/SKILL.md
CHANGED
|
@@ -28,7 +28,7 @@ index within that same limit; only legacy uncoded library errors point at `§5.1
|
|
|
28
28
|
## Non-negotiables
|
|
29
29
|
|
|
30
30
|
- **Validation is never bypassed.** `build` writes nothing on a red gate; there is
|
|
31
|
-
no
|
|
31
|
+
no flag to skip it, and none may be added — AUTHORING §0 says so in as many
|
|
32
32
|
words. Correctness is the whole of the reason: the assertions are what make the
|
|
33
33
|
output trustworthy, and they are held to the official parser's verdicts in the
|
|
34
34
|
repository's CI — all but the parse itself, which runs only where the runtime is
|
|
@@ -55,20 +55,23 @@ Codex, Gemini CLI and Antigravity read skills from `.agents/skills/` in the
|
|
|
55
55
|
workspace and none of them reads `node_modules`; `rigc skills install` puts every
|
|
56
56
|
skill the package ships there, and `rigc skills --help` says what it refuses.
|
|
57
57
|
|
|
58
|
-
The package links no Spine runtime. `
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`build`
|
|
63
|
-
|
|
64
|
-
rigc's
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
The package links no Spine runtime. `build` writes `skeleton.json`,
|
|
59
|
+
`skeleton.atlas` and `skeleton.model.json`. `preview`, `vote`, `bench` and `bonedist`
|
|
60
|
+
run through `@esotericsoftware/spine-core`: install it beside
|
|
61
|
+
the package (`bun add -d @esotericsoftware/spine-core`) and the same `rigc` runs
|
|
62
|
+
them, and `build` runs the round trip as well. Without it those commands are refused
|
|
63
|
+
by name, while `build`, `validate`, `explain`, `diff`, `render`, `check` and `inspect`
|
|
64
|
+
(`--poser core|spine`) run on rigc's own core over `skeleton.model.json` —
|
|
65
|
+
`rigc --version` names the entry that ran (AUTHORING §0). In the parse's place that
|
|
66
|
+
`build` runs two rules of its own over rigc's model document, `A00_MODEL_READ` and
|
|
67
|
+
`A00_MODEL_REGIONS_ON_PAGES`; they are not registry assertions, so its summary
|
|
68
|
+
counts two more, and AUTHORING §5.2 has a row for each.
|
|
67
69
|
|
|
68
70
|
## The loop
|
|
69
71
|
|
|
70
72
|
1. `rigc build --rig <spec> --motion <spec> --images <dir> --out <dir>` compiles,
|
|
71
|
-
gates,
|
|
73
|
+
gates (under `--profile spine`, the default, or `--profile rig-play`), and writes
|
|
74
|
+
`skeleton.json`, `skeleton.atlas` and `skeleton.model.json` only on green.
|
|
72
75
|
2. Read the report. Every red line names the file to change; fix the spec and
|
|
73
76
|
build again.
|
|
74
77
|
3. `rigc explain --rig <spec> --motion <spec> --out <dir>` when the red line is
|
|
@@ -85,11 +88,17 @@ row for each.
|
|
|
85
88
|
cover a feature the art shows — and answer each with `render --hide <slot>` (or
|
|
86
89
|
`--slot <slot,…>`), which draws the frame again without that part on the same
|
|
87
90
|
grid, so the two frames say which part a pixel is. AUTHORING §0 holds the three.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
For motion and dial readings, `render --pass-through <cloth>:<leg>` names the
|
|
92
|
+
frames where a cloth drawn over a leg passes through it (AUTHORING §8.5),
|
|
93
|
+
`render --angle-range <bone>:<relative-to>` prints how far a bone turns against
|
|
94
|
+
another (AUTHORING §8.7), `render --seam <slot>:<slot>` reads joint gaps,
|
|
95
|
+
visible ghosts and background exposure (AUTHORING §8.8), and
|
|
96
|
+
`render --parallax <dial>` reads a slider dial across its value grid
|
|
97
|
+
(AUTHORING §8.12). When the question is geometry — is this bone where the art is,
|
|
98
|
+
which way does it squash, where in rig units is this point —
|
|
99
|
+
`rigc inspect --candidate <out> --show art,bones,names --dim` draws the bones
|
|
100
|
+
over the art and writes a legend beside the picture that puts every mark back in
|
|
101
|
+
world units; AUTHORING §13 maps each question to its view.
|
|
93
102
|
5. `rigc check --candidate <out> --frames <dir>` when you have reference pictures
|
|
94
103
|
(`--out <dir>` writes the picture each of its numbers came from — open the worst).
|
|
95
104
|
Read its output from the top: the framing block says whether the figures under
|
|
@@ -100,17 +109,21 @@ row for each.
|
|
|
100
109
|
`rigc vote --candidate <a> --candidate <b>` when several candidates are green and
|
|
101
110
|
only a person can choose between them.
|
|
102
111
|
6. `rigc validate <out>` re-gates artifacts already on disk, and
|
|
103
|
-
`rigc <command> --help` is each command's own flag table.
|
|
104
|
-
--out <dir>` packs a build again under `build --pack`'s
|
|
105
|
-
parts were not kept, and writes only after every region and
|
|
106
|
-
shown unchanged (`--
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
`rigc <command> --help` is each command's own flag table.
|
|
113
|
+
`rigc repack <out> --out <dir>` packs a build again under `build --pack`'s
|
|
114
|
+
packing flags when its parts were not kept, and writes only after every region and
|
|
115
|
+
the skeleton are shown unchanged (`--keep-pages` refreshes `skeleton.model.json`
|
|
116
|
+
over the existing atlas pages; `--accept-skeleton-differences` writes a rebuild
|
|
117
|
+
whose skeleton differs, every difference printed; `--stage-box <slot>` reads a
|
|
118
|
+
build's stage box) — AUTHORING §0.4. A mesh refused because its triangles are
|
|
119
|
+
several pieces that share no vertex: `rigc split --rig … --motion … --slot <slot> --out <dir>`
|
|
120
|
+
writes both specs back with one mesh per piece and every deform key renumbered —
|
|
121
|
+
build that — AUTHORING §3.4.11.
|
|
122
|
+
7. Every finished unit ends with `rigc preview --candidate <out>` (or
|
|
123
|
+
`rigc review <out>` when `@rig-c/review` is installed beside the project and a
|
|
124
|
+
person reviews the build via its loopback URL, AUTHORING §0), and the report
|
|
125
|
+
names the `.html` or URL it produced. The hand-off to a person is part of the
|
|
126
|
+
work.
|
|
114
127
|
|
|
115
128
|
The loop in full, with `pose` before it and `chainfit` after the first build:
|
|
116
129
|
AUTHORING §0.
|
|
@@ -141,7 +154,7 @@ spec files field by field, the emission rules, the loop, and the failure map. Th
|
|
|
141
154
|
| --- | --- | --- |
|
|
142
155
|
| a **skeleton** — how many bones, where each pivot sits, what hangs off what | [RIGGING.md](https://github.com/rig-c/core/blob/main/docs/RIGGING.md) | `rigc-rigging` |
|
|
143
156
|
| a **movement** — an idle, a loop, from this pose to that one | [MOTION.md](https://github.com/rig-c/core/blob/main/docs/MOTION.md) | `rigc-motion` |
|
|
144
|
-
| a **face** — a blink, a gaze, a head turn a
|
|
157
|
+
| a **face** — a blink, a gaze, a head turn or a value-driven face dial | [FACE.md](https://github.com/rig-c/core/blob/main/docs/FACE.md) | `rigc-face` |
|
|
145
158
|
| a **skeleton.json somebody else authored** — read it, repair it, extend it | [INGEST.md](https://github.com/rig-c/core/blob/main/docs/INGEST.md) | `rigc-ingest` |
|
|
146
159
|
| you are the **person operating** the agent rather than the agent | [PROMPTING.md](https://github.com/rig-c/core/blob/main/docs/PROMPTING.md) | — |
|
|
147
160
|
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rigc-face
|
|
3
|
-
description: Author a face on plain Spine data with rigc — a blink, a gaze shift, a breathing portrait
|
|
3
|
+
description: Author a face on plain Spine data with rigc — a blink, a gaze shift, a breathing portrait, a head turn (from a flat sheet a few degrees off axis or a per-vertex depth map across its turn ceiling) and slider-driven face dials, built from closed-form deform transforms, derived group tracks, per-part parallax and socket alpha clipping. Use when the request is a talking or living portrait, a standing character, an expression, a head turn or a look dial, such as "rig this face", "make the portrait blink and look around" or "turn the head". Not for Live2D file conversion, cutting a face illustration into parts, or VTuber-style real-time face tracking.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Requires Bun 1.4 or later and the npm package @rig-c/core (rig-c is the convenience name).
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Face — a turn, a gaze and a
|
|
8
|
+
# Face — a turn, a gaze, a blink and a dial
|
|
9
9
|
|
|
10
10
|
Load this when the request is a **head rather than a body**: a drawn face that
|
|
11
|
-
breathes, blinks, moves its eyes
|
|
12
|
-
|
|
13
|
-
it
|
|
11
|
+
breathes, blinks, moves its eyes, turns off axis (on a flat sheet or a per-vertex
|
|
12
|
+
`depth` map) or exposes its turn as a slider-driven dial. Every rule below is owned
|
|
13
|
+
by [FACE.md](https://github.com/rig-c/core/blob/main/docs/FACE.md); this file says when to open it and what it will
|
|
14
|
+
not do for you.
|
|
14
15
|
|
|
15
16
|
📖 **A failure line ends with the command that prints its row of the guide** —
|
|
16
17
|
` (see rigc guide <RULE>)`. Run that command first, before reading anything else:
|
|
@@ -27,9 +28,22 @@ index within that same limit; only legacy uncoded library errors point at `§5.1
|
|
|
27
28
|
|
|
28
29
|
- **Validation is never bypassed.** `build` writes nothing on a red gate, and there
|
|
29
30
|
is no flag that changes that — AUTHORING §0.
|
|
30
|
-
- **The compiler never invents a value.** A `deform` key states
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
- **The compiler never invents a value.** A `deform` key states either explicit
|
|
32
|
+
vertex deltas or `transform` (`yaw`/`pitch` with `radius` and `degrees`, or over
|
|
33
|
+
the mesh's per-vertex `depth` sheet, AUTHORING §3.4.5 and FACE §2.1, §2.2), and a
|
|
34
|
+
bone group track states `derive` (`depth` per member, `carried` shared shift); the
|
|
35
|
+
compiler evaluates the closed form from the parameters you declare and never
|
|
36
|
+
guesses a radius, angle or depth — AUTHORING §4, §4.5.1, §4.11.1 and FACE §1,
|
|
37
|
+
§1.1, §3.1.
|
|
38
|
+
- **A face angle exposed as a dial is a slider constraint, not a playback time.**
|
|
39
|
+
Map a control bone across `[−1, +1]` onto the turn animation with a slider
|
|
40
|
+
(AUTHORING §3.5.2, FACE §8), bound its degrees by the turn ceiling `build` and
|
|
41
|
+
`explain` print for the depth sheet (FACE §2.2), set `additive: true` when yaw and
|
|
42
|
+
pitch dials share a target (`A40_SLIDERS_COMPOSE_ON_A_SHARED_TARGET`), keep driven
|
|
43
|
+
constraints after their driver (`A42_DRIVEN_CONSTRAINTS_UPDATE_AFTER_THEIR_DRIVER`),
|
|
44
|
+
read the dial across its value grid with `rigc render --candidate <out> --parallax <dial>`
|
|
45
|
+
(AUTHORING §8.12), and clip an iris or highlight to its painted socket with
|
|
46
|
+
`alphaClip` (AUTHORING §3.4, FACE §11).
|
|
33
47
|
- **The validator's messages are the instructions.** Read each named failure as the
|
|
34
48
|
pointer to the file that has to change — AUTHORING §5.
|
|
35
49
|
|
|
@@ -46,19 +60,23 @@ nothing about the fold, so author under `--profile rig-play`.
|
|
|
46
60
|
|
|
47
61
|
What `A39` still cannot say is whether the projection was the right one —
|
|
48
62
|
nothing measures whether 12° was the angle the shot wanted. FACE §9.2 is that
|
|
49
|
-
demonstration, three builds with one of them refused, and §9.3 is the
|
|
50
|
-
|
|
63
|
+
demonstration, three builds with one of them refused, and §9.3 is the differential
|
|
64
|
+
audit and the three limits it does not lift.
|
|
51
65
|
|
|
52
66
|
## Read, in this order
|
|
53
67
|
|
|
54
|
-
1. [AUTHORING.md](https://github.com/rig-c/core/blob/main/docs/AUTHORING.md) —
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
1. [AUTHORING.md](https://github.com/rig-c/core/blob/main/docs/AUTHORING.md) — `alphaClip` and per-vertex `depth` maps
|
|
69
|
+
(§3.4, §3.4.5), slider constraints (§3.5.2), the `deform` timeline, `derive` and
|
|
70
|
+
`transform` field by field (§4, §4.5.1, §4.11, §4.11.1), the failure map
|
|
71
|
+
(§5–§6), `render --parallax <dial>` (§8.12), and the editor's conventions (§10).
|
|
57
72
|
2. [MOTION.md](https://github.com/rig-c/core/blob/main/docs/MOTION.md) — timing, easing and the offset table (§3),
|
|
58
73
|
candidates and the ballot (§4–§5). A blink and a gaze are ordinary motion work.
|
|
59
|
-
3. [FACE.md](https://github.com/rig-c/core/blob/main/docs/FACE.md) — the face's own geometry: the closed form
|
|
60
|
-
|
|
61
|
-
|
|
74
|
+
3. [FACE.md](https://github.com/rig-c/core/blob/main/docs/FACE.md) — the face's own geometry: the closed form and
|
|
75
|
+
`transform` (§1, §1.1), per-vertex depth sheets and turn ceilings (§2, §2.1,
|
|
76
|
+
§2.2), the shared-shift hierarchy and `derive` (§3, §3.1), the 3×5 mesh and its
|
|
77
|
+
silhouette cliff (§4), what foreshortens (§5), the blink and channel allocation
|
|
78
|
+
(§6–§7), the three cliffs and the turn as a slider-driven value (§8), the deform
|
|
79
|
+
audit gap (§9), and non-goals and `alphaClip` socket clipping (§11).
|
|
62
80
|
4. Then [RIGGING.md](https://github.com/rig-c/core/blob/main/docs/RIGGING.md) for the hierarchy as a general rule
|
|
63
81
|
rather than this closed form, and [INGEST.md](https://github.com/rig-c/core/blob/main/docs/INGEST.md) if the head
|
|
64
82
|
arrived as a compiled skeleton.
|
|
@@ -36,17 +36,24 @@ index within that same limit; only legacy uncoded library errors point at `§5.1
|
|
|
36
36
|
## What this guide will not do
|
|
37
37
|
|
|
38
38
|
Nothing grades a hierarchy. A rig with its head off its torso passes the gate, the
|
|
39
|
-
pixels are nearly blind to structure, and the
|
|
40
|
-
|
|
39
|
+
pixels are nearly blind to structure, and the instruments that see it at all are
|
|
40
|
+
named in RIGGING §11 and §11.2 — none as a pass bar. `rigc pose` and `rigc chainfit`
|
|
41
|
+
read part placements and chain hinges from a key-pose picture inside the loop
|
|
42
|
+
(AUTHORING §11, RIGGING §9–§10); `rigc bonedist` measures per-frame bone
|
|
43
|
+
world-transform distance against the same rig's own `home` setup-pose animation
|
|
44
|
+
(RIGGING §7.3) or, at the finish line only, against another skeleton (RIGGING
|
|
45
|
+
§11.2, subject to the honesty rule in AUTHORING §9.1).
|
|
41
46
|
|
|
42
47
|
## Read, in this order
|
|
43
48
|
|
|
44
49
|
1. [AUTHORING.md](https://github.com/rig-c/core/blob/main/docs/AUTHORING.md) — the rig spec field by field (§3),
|
|
45
|
-
the failure map (§5–§6), reading a pose out of a picture
|
|
46
|
-
|
|
50
|
+
the failure map (§5–§6), reading a pose out of a picture and diagnostic render
|
|
51
|
+
flags (§8.1, §8.5, §8.7, §8.8, §11, §12), the honesty rule (§9.1), and the
|
|
52
|
+
editor's own conventions (§10).
|
|
47
53
|
2. [RIGGING.md](https://github.com/rig-c/core/blob/main/docs/RIGGING.md) — the structure itself: what identifies a
|
|
48
|
-
pivot and what moving one costs (§2–§3), gauges (§4), what a chain can reach
|
|
49
|
-
(§6), and the instruments that see structure
|
|
54
|
+
pivot and what moving one costs (§2–§3), gauges (§4), what a chain can reach and
|
|
55
|
+
`bonedist` against `home` (§6–§7, §7.3), and the instruments that see structure
|
|
56
|
+
(§11, §11.2).
|
|
50
57
|
3. Then [MOTION.md](https://github.com/rig-c/core/blob/main/docs/MOTION.md) once the skeleton exists;
|
|
51
58
|
[FACE.md](https://github.com/rig-c/core/blob/main/docs/FACE.md) if the figure is a head;
|
|
52
59
|
[INGEST.md](https://github.com/rig-c/core/blob/main/docs/INGEST.md) if the skeleton was handed to you already
|
|
@@ -129,7 +129,7 @@ export function roundTripOnlyCodes(): string[] {
|
|
|
129
129
|
|
|
130
130
|
/** The restated rules over one build's emitted texts, in `validate()`'s report shape. */
|
|
131
131
|
export function validateEmittedText(given: EmittedTextInput): VerdictLists & { profile: AssertionProfile } {
|
|
132
|
-
//
|
|
132
|
+
// Refuse unknown and removed profiles before choosing policy or writing a report (issue #1668).
|
|
133
133
|
const input: EmittedTextInput = { ...given, profile: resolveProfile(given.profile, 'the emitted text') };
|
|
134
134
|
const known = new Set(EMITTED_TEXT_RULES.map((r) => r.code));
|
|
135
135
|
const unrun = roundTripOnlyCodes().filter((code) => !known.has(code));
|
|
@@ -75,9 +75,8 @@ export interface VerdictHarness extends VerdictLists {
|
|
|
75
75
|
* the table lacks — `validate` for the gate, so its message is the one it was.
|
|
76
76
|
*/
|
|
77
77
|
export function verdictHarness(profile: AssertionProfile, kinds: Readonly<Record<string, AssertionKind>>, who: string): VerdictHarness {
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
// they get here, so this is the floor for a caller of the harness itself.
|
|
78
|
+
// Anything outside the two profiles is refused by name. Entries check before
|
|
79
|
+
// they get here too; this is the floor for a caller of the harness itself.
|
|
81
80
|
profile = resolveProfile(profile, who);
|
|
82
81
|
const failures: Failure[] = [];
|
|
83
82
|
const passed: string[] = [];
|
package/src/assertions/kinds.ts
CHANGED
|
@@ -14,28 +14,9 @@
|
|
|
14
14
|
/** The two rulebooks — `ValidateProfile` in `src/validate.ts`, where the choice between them is argued. */
|
|
15
15
|
export type AssertionProfile = 'spine' | 'rig-play';
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* A profile's former name, which the CLI's `--profile` still reads for one
|
|
19
|
-
* minor and resolves at parse time, printing the deprecation line that names
|
|
20
|
-
* the profile it reads as (issue #1277). Nothing past the flag parser sees an
|
|
21
|
-
* alias: the rule set is keyed on the profile it resolves to, so the alias and
|
|
22
|
-
* its target cannot come to run different rules.
|
|
23
|
-
*/
|
|
24
|
-
export const PROFILE_ALIASES: Readonly<Record<string, AssertionProfile>> = { 'spine-html': 'rig-play' };
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The profile a gate entry runs under: a profile as given, a former name as the
|
|
28
|
-
* profile it became — silently, because the CLI prints the deprecation line and
|
|
29
|
-
* a library caller of `validate()` through a courtesy key passed the former
|
|
30
|
-
* name on the release before this one and must get the same rules — and
|
|
31
|
-
* anything else refused by name. `kindRunsUnder` reads every name but
|
|
32
|
-
* `rig-play` as validity-only, so an unresolved name would run a weaker gate in
|
|
33
|
-
* silence, under a name nobody chose (issue #1277).
|
|
34
|
-
*/
|
|
17
|
+
/** Refuse an unknown profile before the kind rule can silently select validity alone. */
|
|
35
18
|
export function resolveProfile(profile: string, who: string): AssertionProfile {
|
|
36
19
|
if (profile === 'spine' || profile === 'rig-play') return profile;
|
|
37
|
-
const target = Object.hasOwn(PROFILE_ALIASES, profile) ? PROFILE_ALIASES[profile] : undefined;
|
|
38
|
-
if (target !== undefined) return target;
|
|
39
20
|
throw new Error(`${who}: profile ${JSON.stringify(profile)} is not a profile; the profiles are "spine" and "rig-play"`);
|
|
40
21
|
}
|
|
41
22
|
|
|
@@ -386,7 +386,7 @@ function rigFigures(stats: Record<string, number | string>, read: ReadDocument |
|
|
|
386
386
|
* pass one.
|
|
387
387
|
*/
|
|
388
388
|
export function validateModel(given: ModelValidateInput, plant: Partial<ModelSupply> = {}): ModelReport {
|
|
389
|
-
//
|
|
389
|
+
// Refuse unknown and removed profiles before choosing policy or writing a report (issue #1668).
|
|
390
390
|
const input: ModelValidateInput = { ...given, profile: resolveProfile(given.profile, 'the model side') };
|
|
391
391
|
const supply: ModelSupply = { ...MODEL_SUPPLY, ...plant };
|
|
392
392
|
const h = verdictHarness(input.profile, { ...ASSERTION_KIND, ...MODEL_PARSE_KIND }, 'the model side');
|
package/src/assertions/report.ts
CHANGED
|
@@ -12,17 +12,6 @@ import { failLine } from '../guide.ts';
|
|
|
12
12
|
|
|
13
13
|
export const VALIDATE_PROFILES: readonly AssertionProfile[] = ['spine', 'rig-play'];
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* The line `--profile <alias>` prints on stderr before the command runs: the
|
|
17
|
-
* old name, the profile it reads as, and the flag to pass instead (issue
|
|
18
|
-
* #1277). Stderr so a report on stdout reads the same whichever name the
|
|
19
|
-
* caller typed; the report itself names the profile that judged it, which is
|
|
20
|
-
* the target and never the alias.
|
|
21
|
-
*/
|
|
22
|
-
export function profileAliasLine(alias: string, target: AssertionProfile): string {
|
|
23
|
-
return `rigc: --profile ${alias} is deprecated and reads as --profile ${target}, the same rules; it is accepted until the next major release — pass --profile ${target}`;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
15
|
/**
|
|
27
16
|
* What the CLI uses when `--profile` is absent — and ONLY the CLI. This is not
|
|
28
17
|
* `validate()`'s default; that function has none (`ValidateProfile` in
|
package/src/cli/shared.ts
CHANGED
|
@@ -26,11 +26,10 @@ import {
|
|
|
26
26
|
CLI_DEFAULT_PROFILE,
|
|
27
27
|
type GateHere,
|
|
28
28
|
type PackPageFigures,
|
|
29
|
-
profileAliasLine,
|
|
30
29
|
VALIDATE_PROFILES,
|
|
31
30
|
} from '../assertions/report.ts';
|
|
32
31
|
import type { VerdictLists } from '../assertions/harness.ts';
|
|
33
|
-
import {
|
|
32
|
+
import type { AssertionProfile } from '../assertions/kinds.ts';
|
|
34
33
|
import { MAX_CANDIDATES, MIN_CANDIDATES } from '../ballot.ts';
|
|
35
34
|
import { BONEDIST_SPEC, IDENTITY_CORRESPONDENCE } from '../correspondence.ts';
|
|
36
35
|
import { ANCHOR_MAX_RESIDUAL, ANCHOR_MAX_UNEXPLAINED, DEFAULT_HINGE_MAX, DEFAULT_HINGE_MIN, DEFAULT_MIN_LEVER_PX, DEFAULT_MIN_VISIBLE, DEFAULT_PASSES } from '../chainfit.ts';
|
|
@@ -2245,13 +2244,6 @@ export function usageText(docs: readonly CommandDoc[], checkout: string, rules:
|
|
|
2245
2244
|
export function readProfile(flags: Record<string, string>): AssertionProfile {
|
|
2246
2245
|
const raw = flags.profile;
|
|
2247
2246
|
if (raw === undefined) return CLI_DEFAULT_PROFILE;
|
|
2248
|
-
// A former name resolves here and nowhere else (issue #1277): past this line
|
|
2249
|
-
// the alias does not exist, so it cannot select a rule set of its own.
|
|
2250
|
-
const aliased = Object.hasOwn(PROFILE_ALIASES, raw) ? PROFILE_ALIASES[raw] : undefined;
|
|
2251
|
-
if (aliased !== undefined) {
|
|
2252
|
-
console.error(profileAliasLine(raw, aliased));
|
|
2253
|
-
return aliased;
|
|
2254
|
-
}
|
|
2255
2247
|
const found = VALIDATE_PROFILES.find((p) => p === raw);
|
|
2256
2248
|
if (!found) throw new UsageError(`--profile ${JSON.stringify(raw)}; known profiles: ${VALIDATE_PROFILES.join(', ')}`);
|
|
2257
2249
|
return found;
|
package/src/core/entry.ts
CHANGED
|
@@ -47,5 +47,6 @@ export type { DrawnRegion, UvPage, UvRegion, UvSource } from './uvs.ts';
|
|
|
47
47
|
export { clipThrough, clipShapeOf, convexWhy, REGION_UVS, REGION_TRIANGLES } from './clipping.ts';
|
|
48
48
|
export type { ClipShape, ClipResult } from './clipping.ts';
|
|
49
49
|
export { eventsFired } from './events.ts';
|
|
50
|
-
export { bezierPolyline, BEZIER_PIECES } from './animation.ts';
|
|
50
|
+
export { bezierPolyline, BEZIER_PIECES, IRR_OFFSET } from './animation.ts';
|
|
51
51
|
export type { ModelPage, ModelPageRegion } from '../model.ts';
|
|
52
|
+
export { RUNTIME_PI } from './world.ts';
|
package/src/motion.ts
CHANGED
package/src/render_read.ts
CHANGED
package/src/validate.ts
CHANGED
|
@@ -2009,7 +2009,7 @@ function once<T>(supply: () => T): () => T {
|
|
|
2009
2009
|
}
|
|
2010
2010
|
|
|
2011
2011
|
export function validate(input: ValidateInput): ValidateReport {
|
|
2012
|
-
//
|
|
2012
|
+
// Refuse unknown and removed profiles before choosing policy or writing a report (issue #1668).
|
|
2013
2013
|
const profile = resolveProfile(input.profile, 'validate');
|
|
2014
2014
|
/** True when this profile's rulebook includes the policy layer. */
|
|
2015
2015
|
const policy = profile === 'rig-play';
|