rtistree 0.5.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 (181) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +99 -0
  4. package/THIRD_PARTY_NOTICES.md +25 -0
  5. package/dist/art-direction.d.ts +77 -0
  6. package/dist/art-direction.js +186 -0
  7. package/dist/art-direction.js.map +1 -0
  8. package/dist/artifacts.d.ts +24 -0
  9. package/dist/artifacts.js +49 -0
  10. package/dist/artifacts.js.map +1 -0
  11. package/dist/assets.d.ts +16 -0
  12. package/dist/assets.js +96 -0
  13. package/dist/assets.js.map +1 -0
  14. package/dist/benchmark.d.ts +76 -0
  15. package/dist/benchmark.js +118 -0
  16. package/dist/benchmark.js.map +1 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +300 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/commands.d.ts +5315 -0
  21. package/dist/commands.js +591 -0
  22. package/dist/commands.js.map +1 -0
  23. package/dist/components.d.ts +20 -0
  24. package/dist/components.js +98 -0
  25. package/dist/components.js.map +1 -0
  26. package/dist/construction.d.ts +53 -0
  27. package/dist/construction.js +80 -0
  28. package/dist/construction.js.map +1 -0
  29. package/dist/critique.d.ts +44 -0
  30. package/dist/critique.js +45 -0
  31. package/dist/critique.js.map +1 -0
  32. package/dist/detail.d.ts +5 -0
  33. package/dist/detail.js +52 -0
  34. package/dist/detail.js.map +1 -0
  35. package/dist/document.d.ts +64 -0
  36. package/dist/document.js +56 -0
  37. package/dist/document.js.map +1 -0
  38. package/dist/export.d.ts +405 -0
  39. package/dist/export.js +344 -0
  40. package/dist/export.js.map +1 -0
  41. package/dist/font-inspection.d.ts +8 -0
  42. package/dist/font-inspection.js +34 -0
  43. package/dist/font-inspection.js.map +1 -0
  44. package/dist/graphics.d.ts +9 -0
  45. package/dist/graphics.js +72 -0
  46. package/dist/graphics.js.map +1 -0
  47. package/dist/history-storage.d.ts +10 -0
  48. package/dist/history-storage.js +59 -0
  49. package/dist/history-storage.js.map +1 -0
  50. package/dist/index.d.ts +27 -0
  51. package/dist/index.js +28 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/layout.d.ts +18 -0
  54. package/dist/layout.js +155 -0
  55. package/dist/layout.js.map +1 -0
  56. package/dist/loader.d.ts +9 -0
  57. package/dist/loader.js +108 -0
  58. package/dist/loader.js.map +1 -0
  59. package/dist/mcp.d.ts +4 -0
  60. package/dist/mcp.js +223 -0
  61. package/dist/mcp.js.map +1 -0
  62. package/dist/merge.d.ts +6 -0
  63. package/dist/merge.js +49 -0
  64. package/dist/merge.js.map +1 -0
  65. package/dist/native.d.ts +3 -0
  66. package/dist/native.js +6 -0
  67. package/dist/native.js.map +1 -0
  68. package/dist/paint.d.ts +9 -0
  69. package/dist/paint.js +331 -0
  70. package/dist/paint.js.map +1 -0
  71. package/dist/path-edit.d.ts +20 -0
  72. package/dist/path-edit.js +30 -0
  73. package/dist/path-edit.js.map +1 -0
  74. package/dist/pdf-output.d.ts +21 -0
  75. package/dist/pdf-output.js +297 -0
  76. package/dist/pdf-output.js.map +1 -0
  77. package/dist/pipeline.d.ts +39 -0
  78. package/dist/pipeline.js +227 -0
  79. package/dist/pipeline.js.map +1 -0
  80. package/dist/print-scene.d.ts +490 -0
  81. package/dist/print-scene.js +55 -0
  82. package/dist/print-scene.js.map +1 -0
  83. package/dist/production-workflow.d.ts +251 -0
  84. package/dist/production-workflow.js +335 -0
  85. package/dist/production-workflow.js.map +1 -0
  86. package/dist/program-worker.d.ts +1 -0
  87. package/dist/program-worker.js +31 -0
  88. package/dist/program-worker.js.map +1 -0
  89. package/dist/program.d.ts +85 -0
  90. package/dist/program.js +246 -0
  91. package/dist/program.js.map +1 -0
  92. package/dist/project-config.d.ts +91 -0
  93. package/dist/project-config.js +187 -0
  94. package/dist/project-config.js.map +1 -0
  95. package/dist/project.d.ts +897 -0
  96. package/dist/project.js +347 -0
  97. package/dist/project.js.map +1 -0
  98. package/dist/raster-edit.d.ts +61 -0
  99. package/dist/raster-edit.js +91 -0
  100. package/dist/raster-edit.js.map +1 -0
  101. package/dist/raster-studio.d.ts +84 -0
  102. package/dist/raster-studio.js +236 -0
  103. package/dist/raster-studio.js.map +1 -0
  104. package/dist/render.d.ts +79 -0
  105. package/dist/render.js +437 -0
  106. package/dist/render.js.map +1 -0
  107. package/dist/rich-text.d.ts +10 -0
  108. package/dist/rich-text.js +56 -0
  109. package/dist/rich-text.js.map +1 -0
  110. package/dist/schema.d.ts +1912 -0
  111. package/dist/schema.js +571 -0
  112. package/dist/schema.js.map +1 -0
  113. package/dist/spatial.d.ts +10 -0
  114. package/dist/spatial.js +29 -0
  115. package/dist/spatial.js.map +1 -0
  116. package/dist/studio-reference.d.ts +153 -0
  117. package/dist/studio-reference.js +39 -0
  118. package/dist/studio-reference.js.map +1 -0
  119. package/dist/svg.d.ts +5 -0
  120. package/dist/svg.js +315 -0
  121. package/dist/svg.js.map +1 -0
  122. package/dist/techniques.d.ts +74 -0
  123. package/dist/techniques.js +164 -0
  124. package/dist/techniques.js.map +1 -0
  125. package/dist/verify.d.ts +36 -0
  126. package/dist/verify.js +277 -0
  127. package/dist/verify.js.map +1 -0
  128. package/dist/viewport.d.ts +3 -0
  129. package/dist/viewport.js +71 -0
  130. package/dist/viewport.js.map +1 -0
  131. package/dist/workflow.d.ts +53 -0
  132. package/dist/workflow.js +66 -0
  133. package/dist/workflow.js.map +1 -0
  134. package/docs/agent-art-workflow.md +201 -0
  135. package/docs/agent-setup.md +83 -0
  136. package/docs/atelier.md +117 -0
  137. package/docs/cli-reference.md +61 -0
  138. package/docs/decisions/001-runtime-and-renderer.md +35 -0
  139. package/docs/decisions/002-composable-scenes-and-history.md +28 -0
  140. package/docs/decisions/003-editing-refinement-and-agent-validation.md +45 -0
  141. package/docs/decisions/004-print-production-and-projects.md +19 -0
  142. package/docs/decisions/005-programmable-digital-art.md +15 -0
  143. package/docs/decisions/006-staged-2d-art-production.md +13 -0
  144. package/docs/decisions/007-foundation-first-art-direction.md +13 -0
  145. package/docs/decisions/008-agent-onboarding-and-trial-lessons.md +48 -0
  146. package/docs/engine-overview.md +174 -0
  147. package/docs/evolution.md +179 -0
  148. package/docs/getting-started.md +107 -0
  149. package/docs/next-milestone.md +61 -0
  150. package/docs/previews/a3-production.json +36 -0
  151. package/docs/previews/benchmark.json +42 -0
  152. package/docs/previews/landscape.png +0 -0
  153. package/docs/previews/performance.json +24 -0
  154. package/docs/previews/poster.png +0 -0
  155. package/docs/production.md +107 -0
  156. package/docs/releasing.md +60 -0
  157. package/docs/scene-format.md +126 -0
  158. package/docs/studio.md +108 -0
  159. package/examples/hello/README.md +14 -0
  160. package/examples/hello/refine.json +10 -0
  161. package/examples/hello/render.mjs +9 -0
  162. package/examples/hello/scene.json +19 -0
  163. package/licenses/DM-Serif-Display-OFL.txt +93 -0
  164. package/licenses/Inter-OFL.txt +93 -0
  165. package/package.json +84 -0
  166. package/schemas/authoring.schema.json +2177 -0
  167. package/schemas/brief.schema.json +57 -0
  168. package/schemas/command.schema.json +3154 -0
  169. package/schemas/construction.schema.json +159 -0
  170. package/schemas/critique.schema.json +101 -0
  171. package/schemas/document.schema.json +41 -0
  172. package/schemas/export.schema.json +89 -0
  173. package/schemas/fragment.schema.json +1861 -0
  174. package/schemas/patch.schema.json +3177 -0
  175. package/schemas/pipeline.schema.json +205 -0
  176. package/schemas/production.schema.json +452 -0
  177. package/schemas/program.schema.json +152 -0
  178. package/schemas/project.schema.json +115 -0
  179. package/schemas/raster-read.schema.json +42 -0
  180. package/schemas/raster-write.schema.json +75 -0
  181. package/schemas/scene.schema.json +2014 -0
@@ -0,0 +1,53 @@
1
+ import { type VisualCritic, type VisualCritique } from './critique.js';
2
+ import type { Patch } from './commands.js';
3
+ import { Project } from './project.js';
4
+ import type { RenderResult } from './render.js';
5
+ import type { Scene } from './schema.js';
6
+ import { type VerificationReport } from './verify.js';
7
+ export interface Observation {
8
+ iteration: number;
9
+ scene: Scene;
10
+ render: RenderResult;
11
+ verification: VerificationReport;
12
+ critique?: VisualCritique;
13
+ }
14
+ export type EditingAgent = (observation: Observation) => Promise<Patch | null>;
15
+ export interface IterationOptions {
16
+ maxIterations?: number;
17
+ maxStalled?: number;
18
+ minimumImprovement?: number;
19
+ stopOnPass?: boolean;
20
+ signal?: AbortSignal;
21
+ critic?: VisualCritic;
22
+ requireCritique?: boolean;
23
+ }
24
+ /** The agent is injected. This module contains no model credentials or graphics algorithms. */
25
+ export declare function runIterations(project: Project, agent: EditingAgent, options?: IterationOptions): Promise<{
26
+ reason: string;
27
+ iterations: number;
28
+ observations: {
29
+ iteration: number;
30
+ score: number;
31
+ status: string;
32
+ scene_hash: string;
33
+ }[];
34
+ render: RenderResult;
35
+ verification: VerificationReport;
36
+ critique: {
37
+ scene_hash: string;
38
+ png_hash: string;
39
+ reviewer: string;
40
+ method: "human" | "vision-agent";
41
+ summary: string;
42
+ score: number;
43
+ issues: {
44
+ id: string;
45
+ category: "coherence" | "composition" | "lighting" | "semantic" | "texture" | "typography";
46
+ severity: "high" | "low" | "medium";
47
+ target?: string | undefined;
48
+ region?: [number, number, number, number] | undefined;
49
+ message: string;
50
+ suggestion?: string | undefined;
51
+ }[];
52
+ } | null;
53
+ }>;
@@ -0,0 +1,66 @@
1
+ import { validateCritique } from './critique.js';
2
+ import { verifyRendered } from './verify.js';
3
+ /** The agent is injected. This module contains no model credentials or graphics algorithms. */
4
+ export async function runIterations(project, agent, options = {}) {
5
+ const max = options.maxIterations ?? 6, stallLimit = options.maxStalled ?? 2, threshold = options.minimumImprovement ?? 0.01;
6
+ if (!Number.isInteger(max) || max < 0 || max > 100)
7
+ throw new Error('maxIterations must be an integer between 0 and 100');
8
+ if (!Number.isInteger(stallLimit) ||
9
+ stallLimit < 1 ||
10
+ !Number.isFinite(threshold) ||
11
+ threshold < 0)
12
+ throw new Error('Invalid stopping criteria');
13
+ const observations = [];
14
+ let stalled = 0, previous = -1;
15
+ for (let iteration = 0; iteration <= max; iteration++) {
16
+ options.signal?.throwIfAborted();
17
+ const scene = await project.scene(), render = await project.renderer.render(scene, project.root), verification = await verifyRendered(scene, project.root, project.renderer, render);
18
+ const critique = options.critic
19
+ ? validateCritique(await options.critic({ scene, render, verification, signal: options.signal }), scene, render)
20
+ : await project.critique();
21
+ if (critique)
22
+ await project.recordCritique(critique);
23
+ observations.push({
24
+ iteration,
25
+ score: verification.score,
26
+ status: verification.status,
27
+ scene_hash: render.evidence.scene.hash,
28
+ });
29
+ const qualityScore = critique ? (verification.score + critique.score) / 2 : verification.score;
30
+ const result = (reason) => ({
31
+ reason,
32
+ iterations: iteration,
33
+ observations,
34
+ render,
35
+ verification,
36
+ critique,
37
+ });
38
+ if ((options.stopOnPass ?? true) &&
39
+ verification.status === 'pass' &&
40
+ (!options.requireCritique || !!critique) &&
41
+ (!critique || !critique.issues.some((i) => i.severity === 'high' || i.severity === 'medium')))
42
+ return result('passed');
43
+ if (iteration === max)
44
+ return result('iteration-budget');
45
+ if (previous >= 0 && qualityScore - previous < threshold)
46
+ stalled++;
47
+ else
48
+ stalled = 0;
49
+ if (stalled >= stallLimit)
50
+ return result('stalled');
51
+ previous = qualityScore;
52
+ const patch = await agent({
53
+ iteration,
54
+ scene,
55
+ render,
56
+ verification,
57
+ critique: critique ?? undefined,
58
+ });
59
+ options.signal?.throwIfAborted();
60
+ if (!patch)
61
+ return result('agent-finished');
62
+ await project.apply({ ...patch, expected_hash: render.evidence.scene.hash });
63
+ }
64
+ throw new Error('Unreachable iteration state');
65
+ }
66
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,201 @@
1
+ # Art direction for agents
2
+
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`
5
+ and MCP `studioHelp`, and exported as `artDirectionGuide` by the SDK.
6
+
7
+ MCP connections receive the core rules in the server's initialization
8
+ `instructions`. The full guide is also a discoverable JSON resource at
9
+ `rtistree://guides/art-direction`. Authoring tool descriptions point agents to it.
10
+ All of these surfaces share `src/art-direction.ts`; consumers do not need access
11
+ to this repository or its example files. SDK hosts should put the exported
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
14
+ to present instructions to its model; shipping guidance cannot force every client
15
+ or agent to read it, follow it, or exercise good visual judgment.
16
+
17
+ This is a repeatable process for detecting and correcting failures. It cannot guarantee better art on every attempt. The agent must be capable of drawing, observing and revising; the software cannot certify taste, anatomical understanding or the truth of a review.
18
+
19
+ ## Establish the standard before producing detail
20
+
21
+ Write the brief, intended medium, audience and quality expectation in plain language. Separate **prompt compliance** from **artistic success**. A recognisable dragon may still have poor construction; a technically valid PDF may still have poor composition.
22
+
23
+ Study relevant references. Record each source, an actual observation and how it changes the drawing. Open images before making visual claims; search-result descriptions are not visual inspection. Use references for structure, gesture, lighting and quality calibration. Do not substitute tracing, imported pixels or image-generation output when the brief prohibits them. Distinguish real anatomy from invented anatomy.
24
+
25
+ For an unfamiliar subject, include both a structural reference and an example of the intended quality. A diagram can explain a joint without demonstrating good composition or expressive drawing. Sources may be URLs or project-local notes; source claims are recorded, not automatically verified by Rtistree.
26
+
27
+ ## Follow the dependency of artistic decisions
28
+
29
+ For an asset family, begin with a representative sample: one character and one
30
+ prop that exercise the difficult construction. Establish their quality before
31
+ multiplying variants. The guide's `starter_plan` is a valid production plan
32
+ template with exploration, sample review and family review stages. Replace its
33
+ brief and adapt criteria before submitting it to `production`. Reference studies
34
+ can be supplied with the plan or appended through `study`. The template uses
35
+ the existing gates; it does not create an automatic visual critic.
36
+
37
+ 1. **Gesture and composition.** Produce at least three substantially different proposals. Change action, balance, overlap and negative space. Scaling or translating the same drawing does not explore a new pose.
38
+ 2. **Silhouette.** Inspect the subject at thumbnail size. Identify the focal contour, negative spaces and accidental mergers. A head merging into a wing is a drawing failure even if shading might reveal it later.
39
+ 3. **Construction.** Name landmarks and connect them through guide curves. Establish coherent mass, joints, perspective and overlap. Attach contours to shared landmarks so corrections propagate. In a creature, distinguish the skeleton, muscle masses and surface; in lettering, establish stroke proportions and spacing; in a product illustration, establish axes, proportions and perspective.
40
+ 4. **Values.** Use a plain background and grayscale. Group large light and shadow masses under a stated light direction. Inspect at full size and thumbnail size, then mirror the view. Examine both structure and rendering artifacts. Smooth gradients can expose form, but a set of shaded tubes is not automatically convincing anatomy.
41
+ 5. **Targeted revision.** Name the defect, predict a correction and capture the parent. Make the structural edit, capture the revision, then compare the actual images. Record improved, unchanged or worse, with visible evidence. A local fix is not proof that the whole drawing is good.
42
+ 6. **Foundation checkpoint.** Keep all blocking defects active. Seek human or independent review when required by the plan. Do not proceed to colour, textures, scenery or effects while construction remains inadequate.
43
+ 7. **Materials and finish.** Only after the foundation passes, develop surface, edge hierarchy and detail. Recheck the earlier decisions after significant edits. Complexity, brush count and time spent are not quality metrics.
44
+
45
+ If two structural revisions do not improve the drawing, revisit the construction model or the pose. Further detail is unlikely to rescue it. If there are local improvements but the overall result is still weak, say so explicitly and retain the failed gate.
46
+
47
+ ## Subject-specific checks learned from the asset trial
48
+
49
+ **Figures:** name and trace each shoulder–elbow–wrist and hip–knee–ankle chain,
50
+ including hidden portions. State which hand holds each object. In the Verdigris
51
+ Watch trial, the sword elbow crossed the torso beneath the shield arm. Moving
52
+ the elbow outside and above the body fixed that relationship. A valid landmark
53
+ graph can encode a bad pose; inspect balance, joint angles and negative spaces.
54
+ Helmet dome, eye slit, visor and jaw must read as connected forms.
55
+
56
+ **Props:** use one shared perspective grid for the body, lid, planks and fittings.
57
+ The first chest used unrelated angles. A reconstruction also briefly showed the
58
+ hidden backs of its hoops over the near lid, where they looked like handles.
59
+ Both shared geometry and correct occlusion matter. Distinct shaded faces and a
60
+ common palette are insufficient evidence of sound construction.
61
+
62
+ **Animation:** declare facing, travel direction, ground plane, stride distance,
63
+ cycle duration and contact/recovery phases. Play a full loop against ground
64
+ markers and inspect contact, passing and recovery frames at the intended size.
65
+ For ordinary forward walking, planted feet move backward relative to the body;
66
+ their relative velocity plus body velocity should approximately cancel in world
67
+ space. Recovering feet move forward while lifted. Check reachability, segment
68
+ lengths, knee flexion, lift, pivots, frame order and the loop boundary. Bind those
69
+ checks to the actual rig source used to draw the frames.
70
+
71
+ The original trial produced eight different PNGs but walked backward. Correcting
72
+ direction still left excessive knee bend, an odd helmet and crossed guard arms.
73
+ The user eventually called revision 4 “much better.” Record that as relative
74
+ improvement, without extrapolating it into approval of every asset. The distilled
75
+ lessons are embedded in the shipped guide; the full trial history lives in
76
+ `examples/warden-asset-trial` in the source repository and is not required by the
77
+ installed package.
78
+
79
+ Report three separate axes: **technical** (valid files and reproducibility),
80
+ **functional** (subject-specific behaviour/geometry), and **visual** (observed
81
+ appearance against the brief). An unobserved image or loop is unreviewed. A user
82
+ rejection supersedes an earlier favourable agent review. Keep failed candidates
83
+ and parent-linked corrections. Technical checks cannot override visual failures.
84
+
85
+ ## Enforced gates and their limits
86
+
87
+ Production plans support these stage fields:
88
+
89
+ ```json
90
+ {
91
+ "minimum_alternatives": 3,
92
+ "require_references": true,
93
+ "required_reviewer": "human"
94
+ }
95
+ ```
96
+
97
+ Use minimum alternatives on the exploration stage. Use the human checkpoint when
98
+ the user or agreed plan requires human acceptance; do not invent an approval
99
+ requirement for every task. Set concrete `criteria` and appropriate numerical
100
+ thresholds as well. Do not lower thresholds after seeing a weak result merely to advance.
101
+
102
+ - `minimum_alternatives` counts initial candidates with distinct PNG hashes. Revisions do not count as independent alternatives. The software can verify pixel differences; the reviewer must verify meaningful compositional differences.
103
+ - `require_references` requires a reference log. The software does not know whether the agent actually studied it.
104
+ - `required_reviewer: "human"` prevents a review declared as `vision-agent` from approving the stage. Reviewer identities and methods are declarations in a trusted local project, not authenticated identities. An agent must never mark its own opinion as human feedback.
105
+ - Blocking review issues prevent selection and advancement regardless of high overall scores. A criterion cannot simultaneously pass and have a blocking issue.
106
+ - Revision reviews must compare against the declared parent. A revision judged unchanged or worse cannot be selected.
107
+ - Re-reviewing a candidate appends to `review_history`. Earlier criticism is retained.
108
+ - `status` reports candidate readiness and `compare` reports gate reasons. Existing technical, stale-hash, candidate-restoration and undo checks continue to apply.
109
+
110
+ The engine cannot stop an observer from writing an inaccurate review. These gates expose decisions and prevent common shortcuts; they do not replace artistic judgment. A completed workflow means its declared checks passed, not that excellent art has been objectively established.
111
+
112
+ ## Requests an agent should use
113
+
114
+ Reference study can be supplied in the initial plan's `references` array, or appended during work:
115
+
116
+ ```json
117
+ {
118
+ "action": "study",
119
+ "session": "creature",
120
+ "reference": {
121
+ "id": "wing-construction",
122
+ "source": "<reference URL or project-local study>",
123
+ "observation": "The elbow precedes the wrist; the long fingers radiate from the wrist.",
124
+ "application": "Move the wrist independently from the shoulder and attach membrane contours to the finger ends."
125
+ }
126
+ }
127
+ ```
128
+
129
+ Reference IDs are unique. Appending a study does not rewrite criteria or earlier reviews.
130
+
131
+ Capture a revision after making the edit:
132
+
133
+ ```json
134
+ {
135
+ "action": "capture",
136
+ "session": "creature",
137
+ "candidate": "separated-jaw",
138
+ "expected_hash": "<current scene hash>",
139
+ "revision": {
140
+ "parent": "first-values",
141
+ "hypothesis": "Lowering the far wing will open a clear gap beneath the jaw."
142
+ }
143
+ }
144
+ ```
145
+
146
+ A review includes the normal candidate hashes, reviewer, method, strengths, weaknesses, scores and complete criterion verdicts. Add explicit issues and a comparison for revisions:
147
+
148
+ ```json
149
+ {
150
+ "issues": [
151
+ {
152
+ "criterion": "construction",
153
+ "severity": "blocking",
154
+ "observation": "The wing and foreleg terminate at one unexplained joint.",
155
+ "correction": "Design separate attachments and the intervening torso mass before adding detail."
156
+ }
157
+ ],
158
+ "comparison": {
159
+ "parent": "first-values",
160
+ "verdict": "improved",
161
+ "evidence": "The jaw is now separated from the far wing, but the shared shoulder joint is still unresolved."
162
+ }
163
+ }
164
+ ```
165
+
166
+ The construction criterion must be `pass: false` in this example. A comparison can truthfully say improved while the candidate remains blocked.
167
+
168
+ ## Named 2D construction guides
169
+
170
+ ```js
171
+ const drawing = art.guides({
172
+ points: {
173
+ shoulder: [200, 300],
174
+ elbow: { anchor: 'shoulder', offset: [-70, -20] },
175
+ wrist: { anchor: 'elbow', offset: [-40, -90] },
176
+ tip: { anchor: 'wrist', offset: [-120, -40] },
177
+ },
178
+ paths: {
179
+ leadingEdge: [
180
+ { op: 'M', to: 'shoulder' },
181
+ { op: 'Q', control: 'elbow', to: 'wrist' },
182
+ { op: 'L', to: 'tip' },
183
+ ],
184
+ },
185
+ });
186
+ ctx.stroke(art.path(drawing.paths.leadingEdge));
187
+ ```
188
+
189
+ Points can be coordinates, aliases or anchored offsets. Paths support M/L/Q/C/Z segments with shared point references. Moving the shoulder above moves its dependent elbow, wrist and tip. Use absolute points where independent articulation is intended. Cycles, unknown points, invalid coordinates and malformed paths fail validation.
190
+
191
+ This is a general construction graph, not inverse kinematics or anatomical knowledge. It is useful for creatures, botanical forms, lettering, diagrams and other drawings whose contours share control points. Programs still have native Canvas and raw pixels for anything the abstraction cannot express.
192
+
193
+ ## The dragon trials are calibration evidence
194
+
195
+ The original oil-style dragon met the requested subject beats and reproduced deterministically, but the user rejected its artistic quality. Its earlier favourable scores were false positives. Do not use that result as a passing quality reference.
196
+
197
+ The follow-up in `examples/dragon-foundation` studies anatomy references, rejects two silhouettes for losing the head in a wing, then makes two structural/value revisions to the remaining pose. It preserves failed reviews and stops at the foundation checkpoint. The image remains a weak construction study; improved separation and reproducibility do not make it excellent art.
198
+
199
+ Read `examples/dragon-foundation/README.md` for the actual observations, limitations and replay evidence. Treat the process as a way to learn from visible failures rather than manufacture a successful score.
200
+
201
+ The narrower experiment in `examples/dragon-head-study` draws a head illuminated by green fire. Replacing regular scale rows with irregular cells and a glowing line with turbulent fire improved those specific defects. The result still falls short in anatomy, light interaction and purposeful painting. A brush treatment over a weak drawing remains a weak drawing. This was a single-composition lighting experiment, not a successful run of the full foundation protocol; its assessment keeps the artistic failures explicit.
@@ -0,0 +1,83 @@
1
+ # Connect an agent
2
+
3
+ Rtistree provides a CLI, an MCP server and a TypeScript SDK. The engine renders locally;
4
+ your host supplies the model and any vision capability.
5
+
6
+ ## MCP over stdio
7
+
8
+ Install Rtistree in a project and create a scene using the [quickstart](getting-started.md).
9
+ Use this configuration shape in an MCP client that accepts `mcpServers`:
10
+
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "rtistree": {
15
+ "command": "node",
16
+ "args": [
17
+ "/absolute/path/to/my-art/node_modules/rtistree/dist/cli.js",
18
+ "serve",
19
+ "/absolute/path/to/my-art/scene.json"
20
+ ]
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ Replace both paths with real absolute paths. Use an absolute path to your Node executable
27
+ if the host does not inherit your terminal's PATH. Configuration location and field wrappers
28
+ vary by client; the underlying command is always `node <cli.js> serve <scene>`.
29
+ The server writes protocol messages only to stdout.
30
+
31
+ On connection, the client receives concise art-direction instructions. The full versioned
32
+ guide is available as the `rtistree://guides/art-direction` resource and through `studioHelp`.
33
+ Some clients do not automatically expose server instructions or resources to the model;
34
+ in that case, explicitly tell the agent to call `studioHelp` first.
35
+
36
+ Example task:
37
+
38
+ > Read Rtistree's art-direction guide, inspect this project and render it. Create one
39
+ > representative asset before expanding the family. Compare its silhouette and grayscale
40
+ > values, inspect it at the intended display size, and record technical, functional and
41
+ > visual findings separately. Revise failed criteria before exporting.
42
+
43
+ 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
+
48
+ ## CLI agents
49
+
50
+ ```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
55
+ ```
56
+
57
+ Read the JSON guide, open the rendered image, then choose a focused edit. Do not substitute a
58
+ successful `verify` result for visual review. CLI command details are in the [reference](cli-reference.md).
59
+
60
+ ## SDK hosts
61
+
62
+ ```js
63
+ import { rtistreeAgentInstructions, artDirectionGuide, Project } from 'rtistree';
64
+
65
+ const project = await Project.open('./scene.json');
66
+ const image = await project.render();
67
+ // Include rtistreeAgentInstructions in your host's agent instructions.
68
+ // Expose artDirectionGuide and image.png to the agent through your host's tools.
69
+ ```
70
+
71
+ These exports contain guidance; importing them does not automatically insert anything into
72
+ an external agent's context. The host must perform that integration. The renderer has no
73
+ built-in model client, API key handling or automatic visual critic.
74
+
75
+ ## Trust and review
76
+
77
+ Run only painting programs and recipes you trust. The JavaScript VM is not a security sandbox.
78
+ Normal rendering does not execute recipes. Keep an agent's access scoped to the intended
79
+ project, and inspect its proposed changes and outputs as appropriate to your workflow.
80
+
81
+ The [art-direction workflow](agent-art-workflow.md) documents sample selection, connected
82
+ construction, ground contact and existing production review gates. It makes lessons available;
83
+ it does not guarantee model compliance or artistic quality.
@@ -0,0 +1,117 @@
1
+ # Producing art in stages
2
+
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
+
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.
6
+
7
+ ## Working sequence
8
+
9
+ 1. Describe the brief and create a production plan. Set stage-specific criteria before making candidates: composition at thumbnail size; value masses at block-in; anatomy and lighting at form; directional paint and depth at materials; focal hierarchy and consistency at finishing. Do not demand finished texture from thumbnails.
10
+ 2. Author separate painting programs and an editable pipeline JSON. Generate two or three inexpensive compositions by reducing node dimensions. Auto-created raster layers fill the scene canvas, so small assets can serve as previews.
11
+ 3. Build explicitly, capture each candidate and compare their images. Open the returned PNG and relevant detail crops. Record what you actually see against every criterion.
12
+ 4. Select an eligible candidate. Selection restores its layers, assets and frozen inline pipeline, and can be undone. A candidate cannot replace an incumbent with a lower fidelity or quality rating. Unreviewed candidates and technical failures cannot be selected.
13
+ 5. Advance only while the selected scene is still current. Repeat at the next stage and higher resolution. If a criterion fails, make another candidate; do not lower the criterion merely to finish.
14
+ 6. Export the selected scene and audit a cold render, portable render and recipe replay. Report remaining aesthetic limitations separately from technical checks.
15
+
16
+ CLI actions also have SDK equivalents (`buildPipeline`, `production`) and MCP tools (`buildPipeline`, `production`). Structured errors stop the operation. Normal rendering reads baked images and never runs program code.
17
+
18
+ ## Editable dependency graph
19
+
20
+ ```json
21
+ {
22
+ "version": 1,
23
+ "id": "painting",
24
+ "shared": { "warmth": 0.4 },
25
+ "nodes": [
26
+ {
27
+ "id": "ground",
28
+ "target": "ground",
29
+ "source": "programs/ground.js",
30
+ "width": 1200,
31
+ "height": 800,
32
+ "bindings": { "warmth": "warmth" },
33
+ "seed": 42
34
+ },
35
+ {
36
+ "id": "glaze",
37
+ "target": "glaze",
38
+ "code": "const c=art.input('base'); art.techniques.glaze(c,'#a88152',0.08); return c;",
39
+ "width": 1200,
40
+ "height": 800,
41
+ "inputs": { "base": { "node": "ground" } }
42
+ }
43
+ ]
44
+ }
45
+ ```
46
+
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.
48
+
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.
50
+
51
+ 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.
52
+
53
+ ## Production requests
54
+
55
+ Create a plan with `graphics production my-project plan.json`:
56
+
57
+ ```json
58
+ {
59
+ "action": "plan",
60
+ "plan": {
61
+ "id": "landscape",
62
+ "brief": "A quiet mountain valley at dawn",
63
+ "stages": [
64
+ {
65
+ "id": "thumbnails",
66
+ "goal": "Choose the value composition",
67
+ "minimum_fidelity": 0.7,
68
+ "minimum_quality": 0.7,
69
+ "criteria": [
70
+ { "id": "depth", "description": "Three distance planes read at thumbnail size" }
71
+ ]
72
+ }
73
+ ]
74
+ }
75
+ }
76
+ ```
77
+
78
+ Use `{ "action": "capture", "session": "landscape", "candidate": "warm-dawn", "expected_hash": "<current scene hash>", "crops": [[100,100,200,150]] }`. The result includes a directory containing the image, thumbnail, scene and requested `detail-N.png` files. Candidate IDs cannot be overwritten. Capture supports up to 8 integer canvas-space crops. Session capacity is 64 candidates.
79
+
80
+ Use `compare` with the session ID for a labelled contact sheet and ranked reviews. Ranking is eligibility first, then artistic quality, then brief fidelity; it never blends technical and visual scores.
81
+
82
+ A `review` request includes session and a review object with `candidate`, exact `scene_hash` and `png_hash` from capture, `reviewer`, `method` (`human` or `vision-agent`), `fidelity` and `quality` in 0–1, `strengths`, `weaknesses`, and `criteria: [{id, pass, evidence}]`. Every criterion must be covered exactly once. These fields must be authored after visual inspection; Rtistree does not provide an automatic critic.
83
+
84
+ Use `select` with session, candidate and current `expected_hash`, then `advance` with session and the resulting scene hash. The final advance marks the session complete. `status` returns the plan, stage, candidates and selections. Session metadata writes are locked; scene writes use the existing journal lock and stale-scene guard. A failure writing session metadata after selection may require repeating selection; the scene transaction remains undoable.
85
+
86
+ JSON schemas: `schemas/pipeline.schema.json` and `schemas/production.schema.json`.
87
+
88
+ ## Painting techniques and escape hatches
89
+
90
+ ```js
91
+ const canvas = art.canvas();
92
+ const ctx = canvas.getContext('2d');
93
+ ctx.fillStyle = '#263e45';
94
+ ctx.fillRect(0, 0, art.width, art.height);
95
+ ctx.save();
96
+ ctx.clip(art.path('M20 180 Q160 30 300 180 L300 230 L20 230Z'));
97
+ art.techniques.stroke(
98
+ canvas,
99
+ [
100
+ { x: 30, y: 170, pressure: 0.3 },
101
+ { x: 130, y: 120, pressure: 1 },
102
+ { x: 260, y: 170, pressure: 0.2 },
103
+ ],
104
+ { preset: 'oil', size: 24, colour: '#c7b685', dryness: 0.25, opacity: 0.6 },
105
+ );
106
+ art.techniques.glaze(canvas, '#b69357', 0.08);
107
+ ctx.restore();
108
+ return canvas;
109
+ ```
110
+
111
+ `oil`, `filbert`, `scumble` and `ink` presets expose size, bristle count, variation, opacity, dryness and taper. Pressure controls width; overlapping strands accumulate paint. Presets are starting settings, not complete art styles. All methods respect current clipping and transforms, preserve context state and use the seeded RNG. Keep the runtime and technique version pinned for replay.
112
+
113
+ `art.techniques.mix` interpolates sRGB palette colours. `atmosphere` is the same operation applied toward a haze colour; it does not establish perspective for you. `weave` overlays sparse crossed lines; it should remain subordinate to form. See `examples/technique-study` for an executable swatch sheet.
114
+
115
+ For anything these helpers cannot express, use `canvas.getContext('2d')`, `art.path(svgPathData)`, pixel buffers, coordinate warps, custom masks and explicit raster edits. No new abstraction is required to paint a new subject.
116
+
117
+ The user rejected the artistic quality of the first dragon trial. The follow-up in `examples/dragon-foundation` retains failed reviews and stops before decoration. The original trial in `examples/dragon-oil-trial` records three composition candidates, successive stage reviews, editable source and a reproducibility audit. It is one stylized painting trial, not evidence of universal artistic excellence.
@@ -0,0 +1,61 @@
1
+ # CLI reference
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.
6
+
7
+ ## Inspect and edit
8
+
9
+ ```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
19
+ ```
20
+
21
+ Coordinates are `x y width height` in canvas pixels. A patch contains a reason and a typed
22
+ commands array. Supply the current `expected_hash` when coordinating concurrent edits.
23
+ See [scene format](scene-format.md) for command shapes and coordinate rules.
24
+
25
+ ## Verify, review and export
26
+
27
+ ```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
32
+ ```
33
+
34
+ Verification measures configured technical constraints. Critiques are authored after inspecting
35
+ images and bound to the current scene. Exports for physical documents and printer profiles are
36
+ described in [print production](production.md).
37
+
38
+ ## Studio and production
39
+
40
+ ```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
47
+ ```
48
+
49
+ Read [studio](studio.md) for program requests and [staged production](atelier.md) for plans,
50
+ candidate captures, reviews and selection. Program execution is for trusted code only.
51
+
52
+ ## Project creation and integration
53
+
54
+ ```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
59
+ ```
60
+
61
+ The MCP server uses stdio. See [agent setup](agent-setup.md).
@@ -0,0 +1,35 @@
1
+ # ADR 001: TypeScript control plane and native CPU Skia renderer
2
+
3
+ Status: accepted for the MVP. Later extensions and superseded limitations are documented in [ADR 003](003-editing-refinement-and-agent-validation.md).
4
+
5
+ ## Context
6
+
7
+ The architecture proposal suggests TypeScript and a Canvas-style renderer. This is not a requirement. The implementation needs reproducible text, paths, assets, masks, compositing, raster operations, and an ergonomic agent interface. It does not need a browser, interactive GUI, or GPU. The user explicitly authorized choosing any suitable language and ecosystem.
8
+
9
+ ## Decision
10
+
11
+ Use TypeScript on Node.js 22+, with native Skia supplied by `@napi-rs/canvas`. Use Zod for runtime validation and typed commands, YAML/JSON for authoring, and the official MCP TypeScript SDK for stdio agent tools. Keep renderer, verifier, and agent decisions separate. Use ordinary modules in one package, rather than prematurely publishing a monorepo of packages.
12
+
13
+ TypeScript serves the structured data and agent-facing control plane. CPU Skia supplies the expensive graphics primitives in native code. Pixel adjustments currently use typed arrays in TypeScript; that is the first candidate for profiling-driven native optimization.
14
+
15
+ This is **not a WebGL implementation**. There is no browser, DOM, canvas element, GPU driver requirement, or browser automation in the rendering path. The native package offers a familiar Canvas 2D API, which is an API shape rather than a browser dependency.
16
+
17
+ ## Alternatives considered
18
+
19
+ | Alternative | Strength | Reason not selected initially |
20
+ | --------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
21
+ | Python + Pillow/Cairo | Mature image analysis and raster tooling | More integration work to unify paths, font layout, compositing and the chosen typed command surface; remains reasonable for verification extensions. |
22
+ | Rust + Skia/tiny-skia | Tight memory control and efficient pixels | Larger build/distribution surface before proving the agent representation. A native raster kernel can be added behind the same API. |
23
+ | Browser Canvas/WebGL/WebGPU | Interactive previews and GPU throughput | Browser/driver variation and setup add complexity to a CPU-first, headless engine. |
24
+ | SVG + rasterization | Excellent vector composition | Local raster editing, operation history and tiles still need a separate raster subsystem. |
25
+
26
+ ## Consequences
27
+
28
+ - Rendering works locally with prebuilt native binaries, bundled fonts and no service credentials.
29
+ - Same input bytes, package lock, font bytes, renderer version and runtime/platform produce repeatable PNGs. Cross-platform or cross-version byte identity is not claimed.
30
+ - System font loading is disabled by the native adapter. Latin font packages and hashes are explicit dependencies. Applications embedding the SDK should not preload a separate native canvas font registry.
31
+ - Region rendering initially composites the full canvas, then crops exact pixels. Draft is a downsampled full render. These are correctness features, not performance optimizations.
32
+ - Full-canvas layer surfaces trade memory for simple correct composition. A surface budget rejects oversized scenes. Dirty-tile caches and region-aware kernels are later work.
33
+ - An external agent can supply natural-language planning and visual critique through MCP; the engine does not call a particular model provider.
34
+
35
+ References: [native Canvas/Skia binding](https://github.com/Brooooooklyn/canvas), [Zod validation](https://zod.dev/basics), [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk).