spine-rigc 2.57.0 → 2.58.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 +1 -1
- package/docs/AUTHORING.md +621 -270
- package/package.json +1 -1
- package/skills/rigc/SKILL.md +8 -3
- package/skills/rigc-face/SKILL.md +8 -3
- package/skills/rigc-ingest/SKILL.md +8 -3
- package/skills/rigc-motion/SKILL.md +8 -3
- package/skills/rigc-rigging/SKILL.md +8 -3
- package/src/atlas.ts +10 -10
- package/src/cli/core_commands.ts +6 -5
- package/src/cli/shared.ts +11 -6
- package/src/compile.ts +333 -333
- package/src/deformgen.ts +28 -28
- package/src/emit_spine.ts +5 -5
- package/src/errors.ts +8 -0
- package/src/guide.ts +10 -12
- package/src/keys.ts +4 -4
- package/src/model.ts +10 -10
- package/src/motion.ts +6 -6
- package/src/rig.ts +76 -76
- package/src/stop.ts +30 -30
- package/src/trackgen.ts +11 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spine-rigc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.58.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": {
|
package/skills/rigc/SKILL.md
CHANGED
|
@@ -16,9 +16,14 @@ whole interface, and this skill only says which of them to open.
|
|
|
16
16
|
|
|
17
17
|
📖 **A failure line ends with the command that prints its row of the guide** —
|
|
18
18
|
` (see rigc guide <RULE>)`. Run that command first, before reading anything else:
|
|
19
|
-
it prints that rule's row of the shipped guide and nothing else
|
|
20
|
-
(and `§<n>.<m>`, `§<n>.<m>.<k>`)
|
|
21
|
-
|
|
19
|
+
it prints that rule's row of the shipped guide and nothing else. `rigc guide §<n>`
|
|
20
|
+
(and `§<n>.<m>`, `§<n>.<m>.<k>`) prints the section's heading, own prose and
|
|
21
|
+
subsection index from `docs/AUTHORING.md`; add `--all` to include subsection
|
|
22
|
+
bodies. A leaf prints its full text either way. Sizes describe full ledger spans;
|
|
23
|
+
`--all` with a rule name is refused, exit 2. A compile error points at its stable
|
|
24
|
+
`CE_` code row. `rigc guide §5.1.<k>` prints a numbered compile-error group of
|
|
25
|
+
at most 30,000 UTF-8 bytes, and `rigc guide §5.1` prints the introduction and
|
|
26
|
+
index within that same limit; only legacy uncoded library errors point at `§5.1`.
|
|
22
27
|
|
|
23
28
|
## Non-negotiables
|
|
24
29
|
|
|
@@ -14,9 +14,14 @@ it will not do for you.
|
|
|
14
14
|
|
|
15
15
|
📖 **A failure line ends with the command that prints its row of the guide** —
|
|
16
16
|
` (see rigc guide <RULE>)`. Run that command first, before reading anything else:
|
|
17
|
-
it prints that rule's row of the shipped guide and nothing else
|
|
18
|
-
(and `§<n>.<m>`, `§<n>.<m>.<k>`)
|
|
19
|
-
|
|
17
|
+
it prints that rule's row of the shipped guide and nothing else. `rigc guide §<n>`
|
|
18
|
+
(and `§<n>.<m>`, `§<n>.<m>.<k>`) prints the section's heading, own prose and
|
|
19
|
+
subsection index from `docs/AUTHORING.md`; add `--all` to include subsection
|
|
20
|
+
bodies. A leaf prints its full text either way. Sizes describe full ledger spans;
|
|
21
|
+
`--all` with a rule name is refused, exit 2. A compile error points at its stable
|
|
22
|
+
`CE_` code row. `rigc guide §5.1.<k>` prints a numbered compile-error group of
|
|
23
|
+
at most 30,000 UTF-8 bytes, and `rigc guide §5.1` prints the introduction and
|
|
24
|
+
index within that same limit; only legacy uncoded library errors point at `§5.1`.
|
|
20
25
|
|
|
21
26
|
## Non-negotiables
|
|
22
27
|
|
|
@@ -15,9 +15,14 @@ not do for you.
|
|
|
15
15
|
|
|
16
16
|
📖 **A failure line ends with the command that prints its row of the guide** —
|
|
17
17
|
` (see rigc guide <RULE>)`. Run that command first, before reading anything else:
|
|
18
|
-
it prints that rule's row of the shipped guide and nothing else
|
|
19
|
-
(and `§<n>.<m>`, `§<n>.<m>.<k>`)
|
|
20
|
-
|
|
18
|
+
it prints that rule's row of the shipped guide and nothing else. `rigc guide §<n>`
|
|
19
|
+
(and `§<n>.<m>`, `§<n>.<m>.<k>`) prints the section's heading, own prose and
|
|
20
|
+
subsection index from `docs/AUTHORING.md`; add `--all` to include subsection
|
|
21
|
+
bodies. A leaf prints its full text either way. Sizes describe full ledger spans;
|
|
22
|
+
`--all` with a rule name is refused, exit 2. A compile error points at its stable
|
|
23
|
+
`CE_` code row. `rigc guide §5.1.<k>` prints a numbered compile-error group of
|
|
24
|
+
at most 30,000 UTF-8 bytes, and `rigc guide §5.1` prints the introduction and
|
|
25
|
+
index within that same limit; only legacy uncoded library errors point at `§5.1`.
|
|
21
26
|
|
|
22
27
|
## Non-negotiables
|
|
23
28
|
|
|
@@ -15,9 +15,14 @@ not do for you.
|
|
|
15
15
|
|
|
16
16
|
📖 **A failure line ends with the command that prints its row of the guide** —
|
|
17
17
|
` (see rigc guide <RULE>)`. Run that command first, before reading anything else:
|
|
18
|
-
it prints that rule's row of the shipped guide and nothing else
|
|
19
|
-
(and `§<n>.<m>`, `§<n>.<m>.<k>`)
|
|
20
|
-
|
|
18
|
+
it prints that rule's row of the shipped guide and nothing else. `rigc guide §<n>`
|
|
19
|
+
(and `§<n>.<m>`, `§<n>.<m>.<k>`) prints the section's heading, own prose and
|
|
20
|
+
subsection index from `docs/AUTHORING.md`; add `--all` to include subsection
|
|
21
|
+
bodies. A leaf prints its full text either way. Sizes describe full ledger spans;
|
|
22
|
+
`--all` with a rule name is refused, exit 2. A compile error points at its stable
|
|
23
|
+
`CE_` code row. `rigc guide §5.1.<k>` prints a numbered compile-error group of
|
|
24
|
+
at most 30,000 UTF-8 bytes, and `rigc guide §5.1` prints the introduction and
|
|
25
|
+
index within that same limit; only legacy uncoded library errors point at `§5.1`.
|
|
21
26
|
|
|
22
27
|
## Non-negotiables
|
|
23
28
|
|
|
@@ -14,9 +14,14 @@ will not do for you.
|
|
|
14
14
|
|
|
15
15
|
📖 **A failure line ends with the command that prints its row of the guide** —
|
|
16
16
|
` (see rigc guide <RULE>)`. Run that command first, before reading anything else:
|
|
17
|
-
it prints that rule's row of the shipped guide and nothing else
|
|
18
|
-
(and `§<n>.<m>`, `§<n>.<m>.<k>`)
|
|
19
|
-
|
|
17
|
+
it prints that rule's row of the shipped guide and nothing else. `rigc guide §<n>`
|
|
18
|
+
(and `§<n>.<m>`, `§<n>.<m>.<k>`) prints the section's heading, own prose and
|
|
19
|
+
subsection index from `docs/AUTHORING.md`; add `--all` to include subsection
|
|
20
|
+
bodies. A leaf prints its full text either way. Sizes describe full ledger spans;
|
|
21
|
+
`--all` with a rule name is refused, exit 2. A compile error points at its stable
|
|
22
|
+
`CE_` code row. `rigc guide §5.1.<k>` prints a numbered compile-error group of
|
|
23
|
+
at most 30,000 UTF-8 bytes, and `rigc guide §5.1` prints the introduction and
|
|
24
|
+
index within that same limit; only legacy uncoded library errors point at `§5.1`.
|
|
20
25
|
|
|
21
26
|
## Non-negotiables
|
|
22
27
|
|
package/src/atlas.ts
CHANGED
|
@@ -1998,7 +1998,7 @@ function packOnePageByFootprint(
|
|
|
1998
1998
|
if (shapesMeet(shape, put.x, put.y, other.shape, other.x, other.y)) {
|
|
1999
1999
|
throw new CompileError(
|
|
2000
2000
|
`internal: the footprint pass placed a ${shape.width}x${shape.height} cell at ${put.x},${put.y} over ` +
|
|
2001
|
-
`the footprint of the ${other.shape.width}x${other.shape.height} cell at ${other.x},${other.y}`,
|
|
2001
|
+
`the footprint of the ${other.shape.width}x${other.shape.height} cell at ${other.x},${other.y}`, 'CE_ATLAS_INTERNAL_FOOTPRINT_OVERLAP',
|
|
2002
2002
|
);
|
|
2003
2003
|
}
|
|
2004
2004
|
}
|
|
@@ -2313,7 +2313,7 @@ function layoutPack(
|
|
|
2313
2313
|
// Unreachable: every cell was proven to fit an empty page above. Kept as
|
|
2314
2314
|
// a named stop rather than an infinite loop if that ever stops holding.
|
|
2315
2315
|
throw new CompileError(
|
|
2316
|
-
`packing stalled with ${remaining.length} region(s) left and an empty ${maxEdge}x${maxEdge} page`,
|
|
2316
|
+
`packing stalled with ${remaining.length} region(s) left and an empty ${maxEdge}x${maxEdge} page`, 'CE_ATLAS_PACKING_STALLED',
|
|
2317
2317
|
);
|
|
2318
2318
|
}
|
|
2319
2319
|
// ⭐ Then the page is written at the smallest power-of-two pair that holds
|
|
@@ -2337,7 +2337,7 @@ function layoutPack(
|
|
|
2337
2337
|
if (shrunk === null) {
|
|
2338
2338
|
// Unreachable for the same reason as the stall above: these cells were
|
|
2339
2339
|
// just placed on a maxEdge page.
|
|
2340
|
-
throw new CompileError(`page ${pageIndex + 1} of the spill holds ${onPage.length} region(s) that no page fits
|
|
2340
|
+
throw new CompileError(`page ${pageIndex + 1} of the spill holds ${onPage.length} region(s) that no page fits`, 'CE_ATLAS_SPILL_UNPACKABLE');
|
|
2341
2341
|
}
|
|
2342
2342
|
const onThisPage: Placement[] = [];
|
|
2343
2343
|
shrunk.rects.forEach((rect, i) => {
|
|
@@ -2460,19 +2460,19 @@ export function packAtlas(inputs: PackInput[], opts: PackOptions = {}): PackResu
|
|
|
2460
2460
|
const stem = opts.pageStem ?? 'skeleton';
|
|
2461
2461
|
const pageEdges = opts.pageEdges ?? DEFAULT_PAGE_EDGES;
|
|
2462
2462
|
if (!PAGE_EDGES.includes(pageEdges)) {
|
|
2463
|
-
throw new CompileError(`--page-edges ${JSON.stringify(String(opts.pageEdges))}; known values: ${PAGE_EDGES.join(', ')}
|
|
2463
|
+
throw new CompileError(`--page-edges ${JSON.stringify(String(opts.pageEdges))}; known values: ${PAGE_EDGES.join(', ')}`, 'CE_ATLAS_PAGE_EDGES_VALUE');
|
|
2464
2464
|
}
|
|
2465
2465
|
const shape = opts.shape ?? DEFAULT_PACK_SHAPE;
|
|
2466
2466
|
if (!PACK_SHAPES.includes(shape)) {
|
|
2467
|
-
throw new CompileError(`--pack-shape ${JSON.stringify(String(opts.shape))}; known values: ${PACK_SHAPES.join(', ')}
|
|
2467
|
+
throw new CompileError(`--pack-shape ${JSON.stringify(String(opts.shape))}; known values: ${PACK_SHAPES.join(', ')}`, 'CE_ATLAS_PACK_SHAPE_VALUE');
|
|
2468
2468
|
}
|
|
2469
2469
|
if (!Number.isInteger(pageSize) || pageSize < 1) {
|
|
2470
|
-
throw new CompileError(`--page-size must be a positive integer, got ${String(opts.pageSize)}
|
|
2470
|
+
throw new CompileError(`--page-size must be a positive integer, got ${String(opts.pageSize)}`, 'CE_ATLAS_PAGE_SIZE_POSITIVE_INTEGER');
|
|
2471
2471
|
}
|
|
2472
2472
|
if (!Number.isInteger(padding) || padding < 0) {
|
|
2473
|
-
throw new CompileError(`--padding must be a non-negative integer, got ${String(opts.padding)}
|
|
2473
|
+
throw new CompileError(`--padding must be a non-negative integer, got ${String(opts.padding)}`, 'CE_ATLAS_PADDING_NONNEGATIVE_INTEGER');
|
|
2474
2474
|
}
|
|
2475
|
-
if (inputs.length === 0) throw new CompileError('nothing to pack: this compile emitted no images');
|
|
2475
|
+
if (inputs.length === 0) throw new CompileError('nothing to pack: this compile emitted no images', 'CE_ATLAS_IMAGES_REQUIRED');
|
|
2476
2476
|
|
|
2477
2477
|
const maxEdge = floorPowerOfTwo(pageSize);
|
|
2478
2478
|
|
|
@@ -2485,7 +2485,7 @@ export function packAtlas(inputs: PackInput[], opts: PackOptions = {}): PackResu
|
|
|
2485
2485
|
`"${sorted[i].region}" is ${sorted[i].width}x${sorted[i].height} and with --padding ${padding} needs a ` +
|
|
2486
2486
|
`${cells[i].w}x${cells[i].h} cell, which does not fit a ${maxEdge}x${maxEdge} page ` +
|
|
2487
2487
|
`(${sorted[i].absPath}). Raise --page-size, lower --padding, or leave this build unpacked — a packer ` +
|
|
2488
|
-
'cannot split one drawing across two pages.',
|
|
2488
|
+
'cannot split one drawing across two pages.', 'CE_ATLAS_REGION_EXCEEDS_PAGE',
|
|
2489
2489
|
);
|
|
2490
2490
|
}
|
|
2491
2491
|
|
|
@@ -2542,7 +2542,7 @@ export function packAtlas(inputs: PackInput[], opts: PackOptions = {}): PackResu
|
|
|
2542
2542
|
// two reads, or one of the two readers is wrong about it.
|
|
2543
2543
|
throw new CompileError(
|
|
2544
2544
|
`"${place.region}" measured ${input.width}x${input.height} from its PNG header and decodes to ` +
|
|
2545
|
-
`${source.width}x${source.height} (${input.absPath})`,
|
|
2545
|
+
`${source.width}x${source.height} (${input.absPath})`, 'CE_ATLAS_IMAGE_DIMENSIONS_CHANGED',
|
|
2546
2546
|
);
|
|
2547
2547
|
}
|
|
2548
2548
|
extrudeCell(plate, source, place.x - padding, place.y - padding, padding);
|
package/src/cli/core_commands.ts
CHANGED
|
@@ -2017,27 +2017,28 @@ export function cmdSkills(flags: Record<string, string>, positional: string[]):
|
|
|
2017
2017
|
// ---------------------------------------------------------------------------
|
|
2018
2018
|
|
|
2019
2019
|
/**
|
|
2020
|
-
* `rigc guide <RULE>` / `rigc guide §<n>[.<m>]`: a slice of the `docs/AUTHORING.md`
|
|
2020
|
+
* `rigc guide <RULE>` / `rigc guide §<n>[.<m>[.<k>]] [--all]`: a slice of the `docs/AUTHORING.md`
|
|
2021
2021
|
* this package ships, read now — never a copy (`src/guide.ts` says why). A
|
|
2022
2022
|
* finding code's table is read from the shipped document it lives in, and the
|
|
2023
2023
|
* answer names that file.
|
|
2024
2024
|
*/
|
|
2025
2025
|
export function cmdGuide(flags: Record<string, string>, positional: string[]): void {
|
|
2026
|
-
const flagged = Object.keys(flags);
|
|
2027
|
-
if (flagged.length > 0) throw new UsageError(`guide takes
|
|
2026
|
+
const flagged = Object.keys(flags).filter((flag) => flag !== 'all');
|
|
2027
|
+
if (flagged.length > 0) throw new UsageError(`guide takes only --all, and ${flagged.map((f) => `--${f}`).join(', ')} was given — name one rule or one §section`);
|
|
2028
2028
|
if (positional.length !== 1) {
|
|
2029
2029
|
throw new UsageError(
|
|
2030
2030
|
positional.length === 0
|
|
2031
|
-
? 'guide takes one rule name — the one a failure line names before its colon — or one §<n> / §<n>.<m>'
|
|
2031
|
+
? 'guide takes one rule name — the one a failure line names before its colon — or one §<n> / §<n>.<m> / §<n>.<m>.<k>'
|
|
2032
2032
|
: `guide takes one rule name or one §section, and ${positional.length} were given: ${positional.map((p) => JSON.stringify(p)).join(', ')}`,
|
|
2033
2033
|
);
|
|
2034
2034
|
}
|
|
2035
|
+
if (flags.all !== undefined && !positional[0].startsWith('§')) throw new UsageError(`guide --all takes a §section, and ${JSON.stringify(positional[0])} is a rule name — omit --all to read its row`);
|
|
2035
2036
|
const elsewhere: Record<string, string> = {};
|
|
2036
2037
|
for (const table of GUIDE_RULE_TABLES_ELSEWHERE) {
|
|
2037
2038
|
const path = join(PACKAGE_ROOT, table.file);
|
|
2038
2039
|
if (existsSync(path)) elsewhere[table.file] = readFileSync(path, 'utf8');
|
|
2039
2040
|
}
|
|
2040
|
-
const answer = guideAnswer(positional[0], { guide: readFileSync(join(PACKAGE_ROOT, GUIDE_FILE), 'utf8'), elsewhere });
|
|
2041
|
+
const answer = guideAnswer(positional[0], { guide: readFileSync(join(PACKAGE_ROOT, GUIDE_FILE), 'utf8'), elsewhere }, { all: flags.all !== undefined });
|
|
2041
2042
|
if (!answer.ok) throw new GuideError(refusalLine(answer.rule, answer.detail));
|
|
2042
2043
|
for (const line of answer.lines) console.log(line);
|
|
2043
2044
|
}
|
package/src/cli/shared.ts
CHANGED
|
@@ -132,7 +132,7 @@ export { PACKAGE_ROOT, readPackageMeta, readVersion };
|
|
|
132
132
|
* needs a value` (issue #328). `CLI10`/`CLI11` in `selftest.ts` now hold the two
|
|
133
133
|
* halves together by reading `--help` rather than by naming a flag.
|
|
134
134
|
*/
|
|
135
|
-
const BOOLEAN_FLAGS = new Set(['all-frames', 'all-bones', 'help', 'copy-images', 'again', 'pack', 'copy', 'geometry', 'folds', 'accept-skeleton-differences', 'keep-pages', 'dim']);
|
|
135
|
+
const BOOLEAN_FLAGS = new Set(['all', 'all-frames', 'all-bones', 'help', 'copy-images', 'again', 'pack', 'copy', 'geometry', 'folds', 'accept-skeleton-differences', 'keep-pages', 'dim']);
|
|
136
136
|
|
|
137
137
|
/**
|
|
138
138
|
* The flags a command is allowed to spell more than once.
|
|
@@ -1164,6 +1164,7 @@ const FLAG_MEANINGS: Record<string, string> = {
|
|
|
1164
1164
|
ballot: `the ballot the --record'd vote answers (default \`${DEFAULT_BALLOT}\`); its embedded manifest is what the vote is checked against`,
|
|
1165
1165
|
ledger: `the append-only JSONL the vote lands in (default \`${DEFAULT_LEDGER}\`)`,
|
|
1166
1166
|
again: 'record a second vote on a ballot the ledger already has; without it, a repeat is refused rather than doubled',
|
|
1167
|
+
all: 'guide §section only: include its subsection bodies; without it, a section with subsections prints its heading, own prose and subsection index; a leaf prints its full text either way',
|
|
1167
1168
|
dir:
|
|
1168
1169
|
`the directory to install into, resolved against your working directory (default \`${DEFAULT_SKILLS_DIR}\`, the ` +
|
|
1169
1170
|
'workspace directory Codex, Gemini CLI and Antigravity read skills from)',
|
|
@@ -1858,13 +1859,17 @@ export const COMMANDS: CommandDoc[] = [
|
|
|
1858
1859
|
spineFormat: false,
|
|
1859
1860
|
usage: [
|
|
1860
1861
|
'rigc guide <RULE> (the guide\'s row for the rule a failure line names — the line ends with this command)',
|
|
1861
|
-
'rigc guide §<n> | §<n>.<m> | §<n>.<m>.<k> (
|
|
1862
|
+
'rigc guide §<n> | §<n>.<m> | §<n>.<m>.<k> [--all] (a section\'s own prose and subsection index; --all includes their bodies)',
|
|
1862
1863
|
],
|
|
1863
|
-
flags: [],
|
|
1864
|
+
flags: ['all'],
|
|
1864
1865
|
notes: [
|
|
1865
1866
|
'guide reads the docs/AUTHORING.md this command ships with, at the moment it runs, and',
|
|
1866
1867
|
'prints a slice of it — the row(s) whose first cell names the rule, each under the',
|
|
1867
|
-
'file, section and heading it sits in, or
|
|
1868
|
+
'file, section and heading it sits in, or a section\'s heading, own prose and child index.',
|
|
1869
|
+
'§<n> is ## <n>., §<n>.<m> the m-th ### under it, §<n>.<m>.<k> the k-th #### under that.',
|
|
1870
|
+
'--all includes the subsection bodies; a leaf prints its full text either way. The',
|
|
1871
|
+
'header and index sizes describe full ledger spans. --all with a rule is refused.',
|
|
1872
|
+
'An ingest finding',
|
|
1868
1873
|
'code\'s row lives in docs/INGEST.md\'s finding-code table, and its answer names that',
|
|
1869
1874
|
'file. A name the guide does not have is refused with the nearest real names, exit 1.',
|
|
1870
1875
|
],
|
|
@@ -2956,8 +2961,8 @@ function refuse(err: unknown, command: string | undefined, USAGE: string, entry:
|
|
|
2956
2961
|
process.exit(2);
|
|
2957
2962
|
}
|
|
2958
2963
|
if (err instanceof CompileError) {
|
|
2959
|
-
//
|
|
2960
|
-
console.error(compileErrorLine(err.message));
|
|
2964
|
+
// The site's code points at its one AUTHORING row; uncoded library errors keep the legacy section.
|
|
2965
|
+
console.error(compileErrorLine(err.message, err.code));
|
|
2961
2966
|
// The drops the compile recorded before it stopped, in the same line the
|
|
2962
2967
|
// green build prints (issue #671). They were reported from the compile
|
|
2963
2968
|
// RESULT alone, so the run that failed BECAUSE a file was missing was the
|