rtistree 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/CONTRIBUTING.md +47 -0
  3. package/README.md +38 -22
  4. package/SECURITY.md +20 -0
  5. package/THIRD_PARTY_NOTICES.md +1 -1
  6. package/dist/art-direction.js +1 -1
  7. package/dist/cli.js +55 -32
  8. package/dist/cli.js.map +1 -1
  9. package/dist/commands.d.ts +12 -0
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +1 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcp.js +18 -2
  14. package/dist/mcp.js.map +1 -1
  15. package/dist/print-scene.d.ts +6 -0
  16. package/dist/program.js +3 -1
  17. package/dist/program.js.map +1 -1
  18. package/dist/project-config.js +2 -1
  19. package/dist/project-config.js.map +1 -1
  20. package/dist/render.js +21 -1
  21. package/dist/render.js.map +1 -1
  22. package/dist/schema.d.ts +46 -0
  23. package/dist/schema.js +107 -0
  24. package/dist/schema.js.map +1 -1
  25. package/dist/sprites.d.ts +31 -0
  26. package/dist/sprites.js +142 -0
  27. package/dist/sprites.js.map +1 -0
  28. package/dist/starter.d.ts +7 -0
  29. package/dist/starter.js +38 -0
  30. package/dist/starter.js.map +1 -0
  31. package/dist/studio-reference.js +1 -1
  32. package/dist/studio-reference.js.map +1 -1
  33. package/docs/agent-art-workflow.md +12 -2
  34. package/docs/agent-setup.md +12 -7
  35. package/docs/atelier.md +15 -4
  36. package/docs/cli-reference.md +89 -26
  37. package/docs/core-concepts.md +95 -0
  38. package/docs/decisions/004-print-production-and-projects.md +1 -1
  39. package/docs/decisions/005-programmable-digital-art.md +1 -1
  40. package/docs/engine-overview.md +121 -165
  41. package/docs/evolution.md +12 -9
  42. package/docs/getting-started.md +84 -53
  43. package/docs/next-milestone.md +9 -9
  44. package/docs/production.md +22 -16
  45. package/docs/releasing.md +99 -43
  46. package/docs/scene-format.md +45 -8
  47. package/docs/sprites.md +166 -0
  48. package/docs/studio.md +27 -12
  49. package/examples/hello/README.md +24 -8
  50. package/examples/hello/render.mjs +2 -1
  51. package/package.json +10 -5
  52. package/schemas/authoring.schema.json +359 -229
  53. package/schemas/command.schema.json +462 -332
  54. package/schemas/patch.schema.json +462 -332
  55. package/schemas/scene.schema.json +347 -217
  56. package/schemas/sprites.schema.json +41 -0
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod';
2
+ import type { Project } from './project.js';
3
+ /** Controls the two portable artifacts written by exportSpriteSheet. */
4
+ export declare const spriteSheetOptionsSchema: z.ZodObject<{
5
+ manifest: z.ZodOptional<z.ZodString>;
6
+ atlas: z.ZodOptional<z.ZodObject<{
7
+ padding: z.ZodDefault<z.ZodNumber>;
8
+ extrusion: z.ZodDefault<z.ZodNumber>;
9
+ power_of_two: z.ZodDefault<z.ZodBoolean>;
10
+ max_width: z.ZodDefault<z.ZodNumber>;
11
+ }, z.core.$strict>>;
12
+ }, z.core.$strict>;
13
+ export type SpriteSheetOptions = z.infer<typeof spriteSheetOptionsSchema>;
14
+ /**
15
+ * Render declared canvas-frame sprites once and pack their exact RGBA pixels
16
+ * into a deterministic, engine-neutral PNG atlas and JSON manifest. Frames are
17
+ * intentionally not trimmed: their declared bounds and pivots remain stable.
18
+ */
19
+ export declare function exportSpriteSheet(project: Project, output: string, raw?: unknown): Promise<{
20
+ image: string;
21
+ manifest: string;
22
+ width: number;
23
+ height: number;
24
+ frames: number;
25
+ animations: number;
26
+ evidence: {
27
+ scene_hash: string;
28
+ source_png_hash: string;
29
+ atlas_png_hash: string;
30
+ };
31
+ }>;
@@ -0,0 +1,142 @@
1
+ import { extname, basename, resolve } from 'node:path';
2
+ import { z } from 'zod';
3
+ import { createCanvas } from './native.js';
4
+ import { writeArtifact } from './artifacts.js';
5
+ import { sceneHash, sha256 } from './assets.js';
6
+ import { spriteAtlasSchema } from './schema.js';
7
+ /** Controls the two portable artifacts written by exportSpriteSheet. */
8
+ export const spriteSheetOptionsSchema = z.strictObject({
9
+ manifest: z.string().min(1).max(2048).optional(),
10
+ atlas: spriteAtlasSchema.optional(),
11
+ });
12
+ function nextPowerOfTwo(value) {
13
+ let result = 1;
14
+ while (result < value)
15
+ result *= 2;
16
+ return result;
17
+ }
18
+ function packFrames(sprites, atlas) {
19
+ const margin = atlas.padding + atlas.extrusion;
20
+ const frames = Object.entries(sprites.frames)
21
+ .map(([id, frame]) => ({
22
+ id,
23
+ width: frame.bounds[2] + margin * 2,
24
+ height: frame.bounds[3] + margin * 2,
25
+ }))
26
+ // The explicit sort means authored object ordering cannot change the atlas.
27
+ .sort((a, b) => b.height - a.height || b.width - a.width || a.id.localeCompare(b.id));
28
+ const widest = Math.max(...frames.map((frame) => frame.width));
29
+ // POT sheets start at the narrowest possible valid power of two. This can
30
+ // fit tall sparse sets that a square-root estimate would wrongly reject.
31
+ const minimum = atlas.power_of_two
32
+ ? widest
33
+ : Math.max(widest, Math.ceil(Math.sqrt(frames.reduce((sum, frame) => sum + frame.width * frame.height, 0))));
34
+ if (minimum > atlas.max_width)
35
+ throw new Error('Sprite atlas frames exceed max_width');
36
+ let width = atlas.power_of_two ? nextPowerOfTwo(minimum) : minimum;
37
+ if (width > atlas.max_width)
38
+ throw new Error('Sprite atlas power-of-two width exceeds max_width');
39
+ while (true) {
40
+ let x = 0, y = 0, rowHeight = 0, usedWidth = 0;
41
+ const placements = [];
42
+ for (const frame of frames) {
43
+ if (x && x + frame.width > width) {
44
+ y += rowHeight;
45
+ x = 0;
46
+ rowHeight = 0;
47
+ }
48
+ if (y + frame.height > 8192)
49
+ break;
50
+ placements.push({ ...frame, x, y });
51
+ x += frame.width;
52
+ rowHeight = Math.max(rowHeight, frame.height);
53
+ usedWidth = Math.max(usedWidth, x);
54
+ }
55
+ if (placements.length === frames.length) {
56
+ const usedHeight = y + rowHeight;
57
+ const outputWidth = atlas.power_of_two ? width : usedWidth;
58
+ const outputHeight = atlas.power_of_two ? nextPowerOfTwo(usedHeight) : usedHeight;
59
+ if (outputWidth > 8192 || outputHeight > 8192)
60
+ throw new Error('Sprite atlas exceeds 8192 pixels');
61
+ return { placements, width: outputWidth, height: outputHeight };
62
+ }
63
+ const next = atlas.power_of_two
64
+ ? width * 2
65
+ : Math.min(atlas.max_width, Math.max(width + 1, Math.ceil(width * 1.5)));
66
+ if (next > atlas.max_width || next === width)
67
+ throw new Error('Sprite atlas cannot fit within max_width and 8192-pixel height');
68
+ width = next;
69
+ }
70
+ }
71
+ function copyPixel(target, targetWidth, targetX, targetY, source, sourceWidth, sourceX, sourceY) {
72
+ const to = (targetY * targetWidth + targetX) * 4, from = (sourceY * sourceWidth + sourceX) * 4;
73
+ target.set(source.subarray(from, from + 4), to);
74
+ }
75
+ /**
76
+ * Render declared canvas-frame sprites once and pack their exact RGBA pixels
77
+ * into a deterministic, engine-neutral PNG atlas and JSON manifest. Frames are
78
+ * intentionally not trimmed: their declared bounds and pivots remain stable.
79
+ */
80
+ export async function exportSpriteSheet(project, output, raw = {}) {
81
+ const options = spriteSheetOptionsSchema.parse(raw);
82
+ if (extname(output).toLowerCase() !== '.png')
83
+ throw new Error('Sprite atlas output must end in .png');
84
+ const image = resolve(output), manifest = resolve(options.manifest ?? output.replace(/\.png$/i, '.json'));
85
+ if (image === manifest)
86
+ throw new Error('Sprite atlas image and manifest must have different paths');
87
+ if (extname(manifest).toLowerCase() !== '.json')
88
+ throw new Error('Sprite atlas manifest must end in .json');
89
+ const scene = await project.scene(), sprites = scene.sprites;
90
+ if (!sprites)
91
+ throw new Error('Scene has no sprites manifest');
92
+ const atlas = spriteAtlasSchema.parse({ ...sprites.atlas, ...options.atlas }), packing = packFrames(sprites, atlas), render = await project.render({ quality: 'final', cache: false }), canvas = createCanvas(packing.width, packing.height), context = canvas.getContext('2d'), pixels = context.createImageData(packing.width, packing.height), records = {};
93
+ const placements = new Map(packing.placements.map((placement) => [placement.id, placement]));
94
+ for (const [id, frame] of Object.entries(sprites.frames)) {
95
+ const placement = placements.get(id);
96
+ const [sourceX, sourceY, width, height] = frame.bounds;
97
+ const x = placement.x + atlas.padding + atlas.extrusion, y = placement.y + atlas.padding + atlas.extrusion;
98
+ for (let py = 0; py < height; py++)
99
+ for (let px = 0; px < width; px++)
100
+ copyPixel(pixels.data, packing.width, x + px, y + py, render.pixels, render.width, sourceX + px, sourceY + py);
101
+ // Copy edge pixels into the extrusion ring. Padding outside this ring stays transparent.
102
+ for (let py = -atlas.extrusion; py < height + atlas.extrusion; py++)
103
+ for (let px = -atlas.extrusion; px < width + atlas.extrusion; px++) {
104
+ if (px >= 0 && py >= 0 && px < width && py < height)
105
+ continue;
106
+ copyPixel(pixels.data, packing.width, x + px, y + py, render.pixels, render.width, sourceX + Math.max(0, Math.min(width - 1, px)), sourceY + Math.max(0, Math.min(height - 1, py)));
107
+ }
108
+ records[id] = {
109
+ frame: [x, y, width, height],
110
+ source: frame.bounds,
111
+ pivot: frame.pivot,
112
+ duration: frame.duration,
113
+ tags: frame.tags,
114
+ };
115
+ }
116
+ context.putImageData(pixels, 0, 0);
117
+ const png = await canvas.encode('png'), pngHash = sha256(png), document = {
118
+ format: 'rtistree-sprites@1',
119
+ image: basename(image),
120
+ size: [packing.width, packing.height],
121
+ frames: records,
122
+ animations: sprites.animations,
123
+ atlas: { ...atlas, packing: 'shelf-v1', trimmed: false, sampling: 'nearest' },
124
+ evidence: {
125
+ scene_hash: sceneHash(scene),
126
+ source_png_hash: render.evidence.render.png_hash,
127
+ atlas_png_hash: pngHash,
128
+ },
129
+ };
130
+ await writeArtifact(image, png);
131
+ await writeArtifact(manifest, JSON.stringify(document, null, 2) + '\n');
132
+ return {
133
+ image,
134
+ manifest,
135
+ width: packing.width,
136
+ height: packing.height,
137
+ frames: Object.keys(records).length,
138
+ animations: Object.keys(sprites.animations).length,
139
+ evidence: document.evidence,
140
+ };
141
+ }
142
+ //# sourceMappingURL=sprites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sprites.js","sourceRoot":"","sources":["../src/sprites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /** Create a starter in a new directory. Existing paths are never overwritten. */
2
+ export declare function createStarter(directory: string): Promise<{
3
+ directory: string;
4
+ files: string[];
5
+ next: string[];
6
+ output: string;
7
+ }>;
@@ -0,0 +1,38 @@
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { resolve, join } from 'node:path';
3
+ /** Create a starter in a new directory. Existing paths are never overwritten. */
4
+ export async function createStarter(directory) {
5
+ const destination = resolve(directory);
6
+ const names = ['scene.json', 'refine.json', 'render.mjs', 'README.md'];
7
+ const templates = await Promise.all(names.map(async (name) => [name, await readFile(new URL(`../examples/hello/${name}`, import.meta.url))]));
8
+ const { version } = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
9
+ const manifest = {
10
+ name: 'rtistree-artwork',
11
+ private: true,
12
+ type: 'module',
13
+ scripts: { render: 'rtistree render scene.json -o hello.png', 'render:sdk': 'node render.mjs' },
14
+ dependencies: { rtistree: version },
15
+ };
16
+ // mkdir is exclusive: reject files, directories and symlinks, even empty directories.
17
+ try {
18
+ await mkdir(destination);
19
+ }
20
+ catch (error) {
21
+ if (error.code === 'EEXIST')
22
+ throw new Error(`Destination already exists: ${destination}. Choose a new directory.`);
23
+ throw error;
24
+ }
25
+ for (const [name, contents] of templates)
26
+ await writeFile(join(destination, name), contents, { flag: 'wx' });
27
+ await writeFile(join(destination, 'package.json'), JSON.stringify(manifest, null, 2) + '\n', {
28
+ flag: 'wx',
29
+ });
30
+ await writeFile(join(destination, '.gitignore'), 'node_modules/\nhistory/\n*.png\n*.evidence.json\n', { flag: 'wx' });
31
+ return {
32
+ directory: destination,
33
+ files: [...names, 'package.json', '.gitignore'],
34
+ next: ['Change into the created directory', 'npm install', 'npm run render'],
35
+ output: 'hello.png',
36
+ };
37
+ }
38
+ //# sourceMappingURL=starter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"starter.js","sourceRoot":"","sources":["../src/starter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,KAAK,CAAC,GAAG,CACP,KAAK,EAAE,IAAI,EAAE,EAAE,CACb,CAAC,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,qBAAqB,IAAI,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAU,CACzF,CACF,CAAC;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAC5B,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC7C,CAAC;IACzB,MAAM,QAAQ,GAAG;QACf,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE,MAAM,EAAE,yCAAyC,EAAE,YAAY,EAAE,iBAAiB,EAAE;QAC/F,YAAY,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE;KACpC,CAAC;IACF,sFAAsF;IACtF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YACpD,MAAM,IAAI,KAAK,CAAC,+BAA+B,WAAW,2BAA2B,CAAC,CAAC;QACzF,MAAM,KAAK,CAAC;IACd,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,SAAS;QACtC,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;QAC3F,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IACH,MAAM,SAAS,CACb,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,EAC/B,mDAAmD,EACnD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;IACF,OAAO;QACL,SAAS,EAAE,WAAW;QACtB,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,cAAc,EAAE,YAAY,CAAC;QAC/C,IAAI,EAAE,CAAC,mCAAmC,EAAE,aAAa,EAAE,gBAAgB,CAAC;QAC5E,MAAM,EAAE,WAAW;KACpB,CAAC;AACJ,CAAC"}
@@ -34,6 +34,6 @@ export const studioReference = {
34
34
  lighting: 'art.normal(heightFn,x,y,strength=1,step=1) → surface normal from central differences. art.light(normal,[r,g,b,a],{light:[x,y,z]?,ambient?,diffuse?,specular?,shininess?}) → RGBA using Lambert diffuse and Blinn–Phong specular, viewer along +Z. Artistic 2.5D shading, not ray tracing.',
35
35
  },
36
36
  example: 'return art.raster((x,y) => { const n=art.fbm(x/35,y/35); return [35+n*40,40+n*35,45+n*30,255]; });',
37
- edits: 'readRasterRegion reads exact canvas-space PNG pixels and a scene hash. writeRasterRegion consumes an exact-size project-local PNG and that expected_hash, with replace/over semantics and canvas/layer coordinates. Layer-space patches capture reference dimensions and follow transforms. Layer effects/masks can change patch appearance; locality guards reject outward leakage.',
37
+ edits: 'readRasterRegion reads exact canvas-space PNG pixels and a scene hash. writeRasterRegion consumes an exact-size project-local PNG and that expected_hash, with replace/over semantics and canvas/layer coordinates. Layer-space patches capture reference dimensions and follow transforms. Patches follow target effects/operations and precede its mask/opacity; ancestor effects can change appearance; locality guards reject outward leakage.',
38
38
  };
39
39
  //# sourceMappingURL=studio-reference.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"studio-reference.js","sourceRoot":"","sources":["../src/studio-reference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,mFAAmF;AACnF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,mBAAmB;IAC5B,UAAU,EAAE,gBAAgB;IAC5B,aAAa,EAAE,iBAAiB;IAChC,UAAU,EACR,8YAA8Y;IAChZ,QAAQ,EACN,sWAAsW;IACxW,SAAS,EACP,wPAAwP;IAC1P,MAAM,EAAE;QACN,iBAAiB,EAAE,EAAE;QACrB,MAAM,EAAE,EAAE;QACV,4BAA4B,EAAE,EAAE;QAChC,IAAI,EAAE,IAAI;QACV,UAAU,EAAE,GAAG;QACf,cAAc,EAAE,EAAE;QAClB,UAAU,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC;QACvB,WAAW,EAAE,GAAG;KACjB;IACD,GAAG,EAAE;QACH,MAAM,EACJ,gbAAgb;QAClb,MAAM,EACJ,uRAAuR;QACzR,MAAM,EACJ,iJAAiJ;QACnJ,MAAM,EACJ,sLAAsL;QACxL,KAAK,EACH,oGAAoG;QACtG,KAAK,EACH,0OAA0O;QAC5O,KAAK,EACH,qKAAqK;QACvK,WAAW,EACT,+IAA+I;QACjJ,MAAM,EACJ,qIAAqI;QACvI,IAAI,EAAE,kKAAkK;QACxK,QAAQ,EACN,0HAA0H;QAC5H,IAAI,EAAE,2EAA2E;QACjF,QAAQ,EACN,2RAA2R;KAC9R;IACD,OAAO,EACL,oGAAoG;IACtG,KAAK,EACH,sXAAsX;CACzX,CAAC"}
1
+ {"version":3,"file":"studio-reference.js","sourceRoot":"","sources":["../src/studio-reference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,mFAAmF;AACnF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,mBAAmB;IAC5B,UAAU,EAAE,gBAAgB;IAC5B,aAAa,EAAE,iBAAiB;IAChC,UAAU,EACR,8YAA8Y;IAChZ,QAAQ,EACN,sWAAsW;IACxW,SAAS,EACP,wPAAwP;IAC1P,MAAM,EAAE;QACN,iBAAiB,EAAE,EAAE;QACrB,MAAM,EAAE,EAAE;QACV,4BAA4B,EAAE,EAAE;QAChC,IAAI,EAAE,IAAI;QACV,UAAU,EAAE,GAAG;QACf,cAAc,EAAE,EAAE;QAClB,UAAU,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC;QACvB,WAAW,EAAE,GAAG;KACjB;IACD,GAAG,EAAE;QACH,MAAM,EACJ,gbAAgb;QAClb,MAAM,EACJ,uRAAuR;QACzR,MAAM,EACJ,iJAAiJ;QACnJ,MAAM,EACJ,sLAAsL;QACxL,KAAK,EACH,oGAAoG;QACtG,KAAK,EACH,0OAA0O;QAC5O,KAAK,EACH,qKAAqK;QACvK,WAAW,EACT,+IAA+I;QACjJ,MAAM,EACJ,qIAAqI;QACvI,IAAI,EAAE,kKAAkK;QACxK,QAAQ,EACN,0HAA0H;QAC5H,IAAI,EAAE,2EAA2E;QACjF,QAAQ,EACN,2RAA2R;KAC9R;IACD,OAAO,EACL,oGAAoG;IACtG,KAAK,EACH,obAAob;CACvb,CAAC"}
@@ -1,7 +1,7 @@
1
1
  # Art direction for agents
2
2
 
3
3
  Read this before creating illustration, painting or procedural assets. The versioned
4
- protocol is returned by `graphics art-guide`, included in `graphics studio-help`
4
+ protocol is returned by `rtistree art-guide`, included in `rtistree studio-help`
5
5
  and MCP `studioHelp`, and exported as `artDirectionGuide` by the SDK.
6
6
 
7
7
  MCP connections receive the core rules in the server's initialization
@@ -10,7 +10,7 @@ MCP connections receive the core rules in the server's initialization
10
10
  All of these surfaces share `src/art-direction.ts`; consumers do not need access
11
11
  to this repository or its example files. SDK hosts should put the exported
12
12
  `rtistreeAgentInstructions` in their agent context and expose the full guide.
13
- CLI hosts should read `graphics art-guide` before authoring. A client decides how
13
+ CLI hosts should read `rtistree art-guide` before authoring. A client decides how
14
14
  to present instructions to its model; shipping guidance cannot force every client
15
15
  or agent to read it, follow it, or exercise good visual judgment.
16
16
 
@@ -59,6 +59,16 @@ hidden backs of its hoops over the near lid, where they looked like handles.
59
59
  Both shared geometry and correct occlusion matter. Distinct shaded faces and a
60
60
  common palette are insufficient evidence of sound construction.
61
61
 
62
+ **Pixel art:** declare the intended display size, palette and transparency policy.
63
+ Keep coordinates, frame dimensions and pivots on integer pixels, use
64
+ nearest-neighbour scaling, and inspect at the actual game size. A declared
65
+ pixel-art contract can catch palette overruns, invalid tile geometry and
66
+ disallowed transforms or blur; the sprite exporter preserves exact RGBA frame
67
+ pixels. It cannot decide whether a one-pixel choice is artistically good.
68
+ Use palette tiles for compact indexed marks and seeded studio programs for dense
69
+ or generated frames. Pack a set only after the individual frames and their
70
+ contact sheet have been inspected.
71
+
62
72
  **Animation:** declare facing, travel direction, ground plane, stride distance,
63
73
  cycle duration and contact/recovery phases. Play a full loop against ground
64
74
  markers and inspect contact, passing and recovery frames at the intended size.
@@ -1,5 +1,8 @@
1
1
  # Connect an agent
2
2
 
3
+ New to Rtistree? Read [Core concepts: an agent is the interface](core-concepts.md)
4
+ for how you, your agent and the engine work together.
5
+
3
6
  Rtistree provides a CLI, an MCP server and a TypeScript SDK. The engine renders locally;
4
7
  your host supplies the model and any vision capability.
5
8
 
@@ -41,17 +44,19 @@ Example task:
41
44
  > visual findings separately. Revise failed criteria before exporting.
42
45
 
43
46
  The server exposes inspection, rendering, crop inspection, typed edits, undo/redo, verification,
44
- critiques, program execution, pipelines and staged production. Rendering tools return PNG image
45
- content; use a vision-capable agent to judge appearance. Structured inspection alone cannot
46
- establish that an image looks good.
47
+ critiques, program execution, pipelines, sprite-atlas export and staged production. The
48
+ `exportSprites` tool writes an engine-neutral PNG atlas plus JSON frame/animation metadata for
49
+ a scene with a `sprites` manifest. Rendering tools return PNG image content; use a
50
+ vision-capable agent to judge appearance. Structured inspection alone cannot establish that an
51
+ image looks good.
47
52
 
48
53
  ## CLI agents
49
54
 
50
55
  ```sh
51
- npx graphics art-guide
52
- npx graphics inspect scene.json
53
- npx graphics render scene.json -o review.png
54
- npx graphics studio-help
56
+ npx rtistree art-guide
57
+ npx rtistree inspect scene.json
58
+ npx rtistree render scene.json -o review.png
59
+ npx rtistree studio-help
55
60
  ```
56
61
 
57
62
  Read the JSON guide, open the rendered image, then choose a focused edit. Do not substitute a
package/docs/atelier.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Start with [Art direction for agents](agent-art-workflow.md): reference study, distinct silhouettes, construction, grayscale values and targeted revision. Its protocol is included in CLI/MCP `studioHelp`.
4
4
 
5
- Rtistree provides the tools and records; a human or agent still makes visual decisions. No image-generation service or 3D renderer is required. Start with `graphics studio-help` for the synchronous painting API and technique catalogue.
5
+ Rtistree provides the tools and records; a human or agent still makes visual decisions. No image-generation service or 3D renderer is required. Start with `rtistree studio-help` for the synchronous painting API and technique catalogue.
6
6
 
7
7
  ## Working sequence
8
8
 
@@ -17,6 +17,13 @@ CLI actions also have SDK equivalents (`buildPipeline`, `production`) and MCP to
17
17
 
18
18
  ## Editable dependency graph
19
19
 
20
+ These examples assume an installed package and an existing scene project; see
21
+ [the first painting](studio.md#first-painting). Save the graph as `pipeline.json`,
22
+ create `programs/ground.js` inside the artwork project, and make that program return
23
+ a Canvas of the requested dimensions. For a minimal ground program, use
24
+ `return art.raster(() => [38, 62, 69, 255]);`. Source paths inside the graph resolve
25
+ from the artwork project root; the CLI request filename resolves from your shell directory.
26
+
20
27
  ```json
21
28
  {
22
29
  "version": 1,
@@ -44,15 +51,19 @@ CLI actions also have SDK equivalents (`buildPipeline`, `production`) and MCP to
44
51
  }
45
52
  ```
46
53
 
47
- `graphics pipeline my-project pipeline.json` reports `built` or `cached` for each node. An input can instead use `{ "asset": "registered-asset-id" }`. Source and inline code are mutually exclusive. Only subscribed shared parameters enter a node's key. Per-node parameters override nothing implicitly: an explicit binding takes precedence over a parameter of the same name. A changed node whose PNG is identical need not rebuild its dependants. Node array order defines auto-created layer order; dependency order defines execution order. Existing layer geometry is preserved. Changing output resolution changes cache keys. Removing a node does not remove previously authored layers or assets; use normal scene commands for removal.
54
+ `rtistree pipeline my-project pipeline.json` reports `built` or `cached` for each node. An input can instead use `{ "asset": "registered-asset-id" }`. Source and inline code are mutually exclusive. Only subscribed shared parameters enter a node's key. Per-node parameters override nothing implicitly: an explicit binding takes precedence over a parameter of the same name. A changed node whose PNG is identical need not rebuild its dependants. Node array order defines auto-created layer order; dependency order defines execution order. Existing layer geometry is preserved. Changing output resolution changes cache keys. Removing a node does not remove previously authored layers or assets; use normal scene commands for removal.
48
55
 
49
- All node artifacts are baked before one scene transaction. A failed build can leave unused immutable files in the cache, but never a partially updated scene. Identical builds add no history. Use `expected_hash` with the SDK/MCP to reject a scene changed since inspection.
56
+ All node artifacts are baked before one scene transaction. The CLI takes the graph
57
+ as the request file directly. To pass a previously inspected `expected_hash`, use
58
+ the SDK third argument or MCP’s separate `expected_hash` field. A failed build can leave unused immutable files in the cache, but never a partially updated scene. Identical builds add no history. Use `expected_hash` with the SDK/MCP to reject a scene changed since inspection.
50
59
 
51
60
  The exact executed graph, including inline source, is stored under `scene.metadata.pipeline_<id>`. After restoring a candidate, use that graph to resume its settings; a working `pipeline.json` file is deliberately not overwritten by selection. Portable export includes the selected graph and registered input assets, so it can rebuild without the original source files.
61
+ It does not copy production sessions, rejected candidates, reviews or edit history; retain
62
+ the original project if you need those records.
52
63
 
53
64
  ## Production requests
54
65
 
55
- Create a plan with `graphics production my-project plan.json`:
66
+ Create a plan with `rtistree production my-project plan.json`:
56
67
 
57
68
  ```json
58
69
  {
@@ -1,34 +1,54 @@
1
1
  # CLI reference
2
2
 
3
- Installing Rtistree exposes `graphics`. In a local npm project, use `npx graphics`.
4
- Run `graphics --help` for the complete installed-version reference. Structured results go to
5
- stdout as JSON; errors go to stderr. Verification failure exits 2; other errors exit 1.
3
+ Installing Rtistree exposes `rtistree` and the compatibility alias `graphics`. In a local npm project, use `npx rtistree`.
4
+ Run `rtistree --help` for the complete installed-version reference. Structured results go to
5
+ stdout as JSON; errors go to stderr. Failed verification/preflight and non-identical recipe replay exit 2; input/runtime errors exit 1.
6
+
7
+ ## Create a starter
8
+
9
+ ```sh
10
+ npx rtistree@latest init my-art
11
+ cd my-art
12
+ npm install
13
+ npm run render
14
+ ```
15
+
16
+ The destination must be a new directory. The starter includes a scene, sample patch, SDK example
17
+ and npm render scripts. `init` writes starter files without installing dependencies or executing painting programs.
6
18
 
7
19
  ## Inspect and edit
8
20
 
9
21
  ```sh
10
- graphics inspect scene.json
11
- graphics inspect scene.json --layer title
12
- graphics inspect-region scene.json 0 0 100 100
13
- graphics render scene.json -o image.png
14
- graphics render-region scene.json 0 0 100 100 -o crop.png
15
- graphics apply scene.json patch.json
16
- graphics undo scene.json
17
- graphics redo scene.json
18
- graphics history scene.json
22
+ npx rtistree inspect scene.json
23
+ npx rtistree inspect scene.json --layer title
24
+ npx rtistree inspect-region scene.json 0 0 100 100
25
+ npx rtistree render scene.json -o image.png
26
+ npx rtistree render-region scene.json 0 0 100 100 -o crop.png
27
+ npx rtistree sprites scene.json -o output/sprites.png --manifest output/sprites.json
28
+ npx rtistree apply scene.json patch.json
29
+ npx rtistree undo scene.json
30
+ npx rtistree redo scene.json
31
+ npx rtistree history scene.json
19
32
  ```
20
33
 
21
34
  Coordinates are `x y width height` in canvas pixels. A patch contains a reason and a typed
22
35
  commands array. Supply the current `expected_hash` when coordinating concurrent edits.
23
36
  See [scene format](scene-format.md) for command shapes and coordinate rules.
24
37
 
38
+ `sprites` reads a scene or configured project with a sprite manifest and writes a
39
+ deterministically packed atlas plus frame/animation metadata. The atlas output
40
+ must end in `.png`; the optional `--manifest` path must end in `.json`. Pixel-art
41
+ projects can opt into integer, palette and nearest-neighbour guardrails. Use
42
+ `npx rtistree sprites --help` for the exact options supported by the installed
43
+ version.
44
+
25
45
  ## Verify, review and export
26
46
 
27
47
  ```sh
28
- graphics verify scene.json -o report.json --heatmap heatmap.png
29
- graphics critique scene.json critique.json
30
- graphics export scene.json -o portable/scene.json
31
- graphics export scene.json --format png -o image.png
48
+ npx rtistree verify scene.json -o report.json --heatmap heatmap.png
49
+ npx rtistree critique scene.json critique.json
50
+ npx rtistree export scene.json -o portable/scene.json
51
+ npx rtistree export scene.json --format png -o image.png
32
52
  ```
33
53
 
34
54
  Verification measures configured technical constraints. Critiques are authored after inspecting
@@ -38,12 +58,12 @@ described in [print production](production.md).
38
58
  ## Studio and production
39
59
 
40
60
  ```sh
41
- graphics art-guide
42
- graphics studio-help
43
- graphics program scene.json program.json
44
- graphics program-replay scene.json asset-id
45
- graphics pipeline scene.json pipeline.json
46
- graphics production scene.json request.json
61
+ npx rtistree art-guide
62
+ npx rtistree studio-help
63
+ npx rtistree program scene.json program.json
64
+ npx rtistree program-replay scene.json asset-id
65
+ npx rtistree pipeline scene.json pipeline.json
66
+ npx rtistree production scene.json request.json
47
67
  ```
48
68
 
49
69
  Read [studio](studio.md) for program requests and [staged production](atelier.md) for plans,
@@ -52,10 +72,53 @@ candidate captures, reviews and selection. Program execution is for trusted code
52
72
  ## Project creation and integration
53
73
 
54
74
  ```sh
55
- graphics project new artwork --size A3 --orientation landscape --ppi 300 --bleed 3mm
56
- graphics schema --kind scene
57
- graphics schema --kind command
58
- graphics serve /absolute/path/to/scene.json
75
+ npx rtistree project new artwork --size A3 --orientation landscape --ppi 300 --bleed 3mm
76
+ npx rtistree schema --kind scene
77
+ npx rtistree schema --kind command
78
+ npx rtistree serve /absolute/path/to/scene.json
59
79
  ```
60
80
 
61
81
  The MCP server uses stdio. See [agent setup](agent-setup.md).
82
+
83
+ ## Additional commands
84
+
85
+ | Command | Purpose |
86
+ | ----------------------------------------------------------- | ----------------------------------------------------------------------------------- |
87
+ | `npx rtistree rebase scene.json` | Merge manual source changes into journaled state; conflicts fail without committing |
88
+ | `npx rtistree compact scene.json` | Compress history while retaining undo and redo |
89
+ | `npx rtistree raster-read scene.json read.json` | Write an exact crop plus evidence and return an asset descriptor |
90
+ | `npx rtistree raster-write scene.json write.json` | Commit an exact-size PNG patch with a required current hash |
91
+ | `npx rtistree sprites scene.json -o output/sprites.png` | Pack declared sprite frames into an atlas and write animation metadata |
92
+ | `npx rtistree import-svg drawing.svg -o drawing.scene.json` | Import the supported static SVG subset |
93
+ | `npx rtistree preflight artwork --preset screen` | Check physical document/export settings and save a report |
94
+ | `npx rtistree proof artwork --preset print -o proof.png` | Make a CMYK round-trip proof; requires a configured ICC profile |
95
+ | `npx rtistree benchmark scene.json brief.json before` | Capture a benchmark checkpoint after recording a current critique |
96
+ | `npx rtistree benchmark scene.json brief.json finish` | Finish after at least two inspected checkpoints |
97
+
98
+ Dense request shapes are in [studio](studio.md). Source rebasing, critiques and benchmark
99
+ requirements are in [editing workflows](evolution.md). Names such as `patch.json`, `read.json`
100
+ and `critique.json` are request files you author, not files created by `init`.
101
+
102
+ ## Options, paths and output
103
+
104
+ - `--output` / `-o` chooses an artifact path. Explicit paths and request filenames resolve
105
+ from the shell's working directory. Asset/program paths inside requests resolve from the
106
+ artwork project root. Without `-o`, configured projects use `output_dir`; bare scene files
107
+ use a `renders/` directory alongside the scene.
108
+ - `render --quality draft|preview|final` controls PNG rendering. Draft halves dimensions
109
+ after rendering; preview and final share the full-quality path. `--layer ID` renders an
110
+ isolated layer on a full-size transparent canvas. `render-region` requires an integer crop
111
+ entirely inside the canvas; default/final quality is an exact full-render crop.
112
+ - `inspect-region` also writes `inspection.png` and its evidence unless you supply `-o`.
113
+ - Artwork `export` and full `render` accept `--format`, `--preset` and `--ppi`. Known output
114
+ extensions are inferred. Print exports additionally accept `--profile` (project-relative
115
+ ICC file; implies CMYK), `--colour-space srgb|cmyk` and `--crop-marks`. Use `export` for
116
+ print options; a plain PNG `render` with only `--profile` does not select the export path.
117
+ - `schema --kind scene` describes a resolved scene. Source scenes with includes/components
118
+ use the packaged `authoring.schema.json`; a patch uses `patch.schema.json`.
119
+
120
+ JSON is the structured result format; help is plain text and `serve` writes MCP protocol
121
+ messages. The npm/npx launcher can print its own installation notices. `verify` and
122
+ `preflight` failures, and non-identical `program-replay` results, exit 2. Input/runtime/export
123
+ errors exit 1. Warnings alone do not make preflight fail. Program or pipeline build success
124
+ only means execution succeeded; it does not establish visual quality.
@@ -0,0 +1,95 @@
1
+ # Core concepts: an agent is the interface
2
+
3
+ Rtistree is designed to be operated through an agent. You describe what you want,
4
+ set constraints and give feedback. The agent uses Rtistree to construct artwork,
5
+ inspect renders and make focused revisions.
6
+
7
+ The CLI, MCP server and TypeScript SDK are the agent's controls. They are also
8
+ available for direct human use, but learning every command is not the intended
9
+ starting point for someone who wants to make art.
10
+
11
+ ## Three roles
12
+
13
+ | Role | Responsibility |
14
+ | --------- | -------------------------------------------------------------------------------------------------- |
15
+ | You | Set the brief, references, constraints and intended use; judge whether the result meets your needs |
16
+ | The agent | Plan the work, call tools, inspect images, identify defects and revise the artwork |
17
+ | Rtistree | Store the editable scene, render it, apply typed edits, track history and export files |
18
+
19
+ Rtistree does not contain a model. Your agent host supplies the model, its context,
20
+ image-viewing capability and tool access. An agent that cannot inspect images can
21
+ still operate the tools, but cannot credibly judge their visual quality.
22
+
23
+ You can connect an MCP-capable host, give an agent access to the CLI, or integrate
24
+ the SDK into your own application. [Agent setup](agent-setup.md) explains each path.
25
+ The host decides which tools require confirmation and what files the agent can access.
26
+
27
+ ## A conversation becomes an editable scene
28
+
29
+ A useful starting brief might be:
30
+
31
+ > Create a square event poster with a bold title, a quiet landscape and room for
32
+ > a date. Keep the title and illustration independently editable. Show me a
33
+ > composition before adding detail.
34
+
35
+ The agent creates a scene with named layers rather than treating the final PNG as
36
+ its only state. Text, geometry, image assets, masks and adjustments can retain
37
+ separate identities. For painted detail, trusted JavaScript programs can produce
38
+ baked raster assets with saved source, parameters and seeds.
39
+
40
+ After inspecting the render, you might say:
41
+
42
+ > The title works. Reduce the contrast behind it and move the sun farther right.
43
+
44
+ The agent can inspect the relevant layers, change those parts and render again.
45
+ It should preserve the parts you approved and check that the requested revision
46
+ actually helps. Scoped raster edits have an enforced pixel-locality check;
47
+ arbitrary structural edits do not automatically promise that every other pixel
48
+ will remain unchanged.
49
+
50
+ A painted image is only as editable as its construction. If an agent bakes every
51
+ part into one asset, Rtistree cannot recover meaningful objects from those pixels.
52
+ Ask for independent layers or program parameters for the parts you expect to revise.
53
+
54
+ ## The working loop
55
+
56
+ 1. **Direct:** establish the brief, references, intended size and acceptance criteria.
57
+ 2. **Construct:** make a representative composition or asset with useful editable structure.
58
+ 3. **Inspect:** open the actual render, including silhouettes, crops or animation frames as relevant.
59
+ 4. **Refine:** identify a specific defect, make a focused change and compare the result.
60
+ 5. **Deliver:** export the accepted state and keep the source needed for future edits.
61
+
62
+ This loop is deliberate. A successful command, valid file or reproducible image
63
+ is not proof that the artwork is good. The agent brings drawing and observation
64
+ skills; Rtistree provides tools and records. A stronger agent may use the same
65
+ toolkit better, but the toolkit does not guarantee artistic success.
66
+
67
+ ## Guidance travels with the tool
68
+
69
+ The package includes art-direction guidance based on recorded trials: connected
70
+ construction, coherent prop perspective, ground contact, representative samples,
71
+ and separate technical, functional and visual assessment.
72
+
73
+ - MCP supplies compact instructions during connection and exposes the full guide
74
+ through `studioHelp` and the `rtistree://guides/art-direction` resource.
75
+ - CLI agents can read it with `rtistree art-guide`.
76
+ - SDK hosts can provide `rtistreeAgentInstructions` and `artDirectionGuide` to their agent.
77
+
78
+ Availability is not automatic compliance: some hosts do not pass server instructions
79
+ to their model. Ask the agent to read the guide before authoring. The
80
+ [art-direction workflow](agent-art-workflow.md) explains the process and optional
81
+ production gates in detail.
82
+
83
+ ## Local work and explicit execution
84
+
85
+ Ordinary scene loading and rendering use local assets and do not execute painting
86
+ recipes. Program execution, pipeline builds and recipe replay are explicit actions
87
+ for trusted code; the JavaScript VM is not a security sandbox. The agent host's
88
+ model calls may use a remote service even though Rtistree renders locally.
89
+
90
+ Edits are journaled and can be undone. Portable export saves the current artwork,
91
+ assets and recipes as a new baseline; it does not copy the complete edit history
92
+ or production reviews. Keep the original project when those records matter.
93
+
94
+ Start by [connecting your agent](agent-setup.md). To understand the mechanics
95
+ first, [make your first image](getting-started.md) with the small CLI walkthrough.
@@ -16,4 +16,4 @@ Hybrid PDF preserves supported text, vectors, gradients and isolation-free group
16
16
 
17
17
  The print trial revealed two defects that were fixed during implementation: metadata configuration could overwrite the requested CMYK conversion, and mask inversion after erosion expanded the selected foreground instead of shrinking it. Actual-file tests and visual proof inspection cover these cases. The original engine regression suite remains in place, alongside production and editing tests.
18
18
 
19
- See [the production guide](../production.md) for capabilities and operational limits, [the A3 evidence](../previews/a3-production.json), and [the generated-asset print trial](../../examples/print-trial/README.md).
19
+ See [the production guide](../production.md) for capabilities and operational limits, [the A3 evidence](../previews/a3-production.json), and [the generated-asset print trial](https://github.com/Coly010/rtistree/blob/main/examples/print-trial/README.md).