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.
- package/CHANGELOG.md +20 -0
- package/CONTRIBUTING.md +47 -0
- package/README.md +38 -22
- package/SECURITY.md +20 -0
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/art-direction.js +1 -1
- package/dist/cli.js +55 -32
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +18 -2
- package/dist/mcp.js.map +1 -1
- package/dist/print-scene.d.ts +6 -0
- package/dist/program.js +3 -1
- package/dist/program.js.map +1 -1
- package/dist/project-config.js +2 -1
- package/dist/project-config.js.map +1 -1
- package/dist/render.js +21 -1
- package/dist/render.js.map +1 -1
- package/dist/schema.d.ts +46 -0
- package/dist/schema.js +107 -0
- package/dist/schema.js.map +1 -1
- package/dist/sprites.d.ts +31 -0
- package/dist/sprites.js +142 -0
- package/dist/sprites.js.map +1 -0
- package/dist/starter.d.ts +7 -0
- package/dist/starter.js +38 -0
- package/dist/starter.js.map +1 -0
- package/dist/studio-reference.js +1 -1
- package/dist/studio-reference.js.map +1 -1
- package/docs/agent-art-workflow.md +12 -2
- package/docs/agent-setup.md +12 -7
- package/docs/atelier.md +15 -4
- package/docs/cli-reference.md +89 -26
- package/docs/core-concepts.md +95 -0
- package/docs/decisions/004-print-production-and-projects.md +1 -1
- package/docs/decisions/005-programmable-digital-art.md +1 -1
- package/docs/engine-overview.md +121 -165
- package/docs/evolution.md +12 -9
- package/docs/getting-started.md +84 -53
- package/docs/next-milestone.md +9 -9
- package/docs/production.md +22 -16
- package/docs/releasing.md +99 -43
- package/docs/scene-format.md +45 -8
- package/docs/sprites.md +166 -0
- package/docs/studio.md +27 -12
- package/examples/hello/README.md +24 -8
- package/examples/hello/render.mjs +2 -1
- package/package.json +10 -5
- package/schemas/authoring.schema.json +359 -229
- package/schemas/command.schema.json +462 -332
- package/schemas/patch.schema.json +462 -332
- package/schemas/scene.schema.json +347 -217
- package/schemas/sprites.schema.json +41 -0
package/docs/production.md
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
# Projects, print production and editing
|
|
1
|
+
# Projects, print production and editing
|
|
2
2
|
|
|
3
3
|
## Start a project
|
|
4
4
|
|
|
5
|
+
Run these commands from a directory where `npm install rtistree` has completed.
|
|
6
|
+
`project new` creates the artwork files and presets, not a Node package or dependency installation.
|
|
7
|
+
|
|
5
8
|
```sh
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
npx rtistree project new alpine --size A3 --orientation landscape --ppi 300 --bleed 3mm --output-dir output
|
|
10
|
+
npx rtistree render alpine --preset screen
|
|
11
|
+
npx rtistree preflight alpine --preset screen
|
|
9
12
|
```
|
|
10
13
|
|
|
11
14
|
`project new` accepts A3, A4, A5, Letter, or a custom pair such as `160x100` (mm) or `8.5inx11in`. It creates `rtistree.yaml`, a scene with layer fragments, assets/fonts/profiles/history directories, local JSON Schemas, a README and a designated output directory. The destination must be new. Existing scene-file commands remain available; opening a configured entry-point scene also discovers its project settings.
|
|
12
15
|
|
|
13
|
-
Generated projects start with an sRGB screen preset and a CMYK print preset. Before using the print preset, copy your printer/paper ICC file into `profiles/` and set `presets.print.profile`. Set `profile_hash` to its
|
|
16
|
+
Generated projects start with an sRGB screen preset and a CMYK print preset. Before using the print preset, copy your printer/paper ICC file into `profiles/` and set `presets.print.profile`. Set `profile_hash` to `sha256:` followed by its 64-character hexadecimal digest to pin it. CMYK export rejects missing, invalid, changed or non-CMYK profiles. The demo profile is for exercising the pipeline, not a recommendation for a printing process.
|
|
17
|
+
An unconfigured print preset fails preflight with exit code 2; the first example deliberately
|
|
18
|
+
uses the screen preset. After configuring a real profile, run `npx rtistree preflight alpine --preset print`
|
|
19
|
+
before the CMYK export and proof commands below.
|
|
14
20
|
|
|
15
21
|
Project paths are local to the project root. CLI/MCP renders and artwork exports use `output_dir`; CLI verification and preflight reports use it too. History and critique records remain persistent project state. Explicit CLI `--output` paths override artifact destinations.
|
|
16
22
|
|
|
@@ -37,12 +43,12 @@ The renderer accepts edges up to 8,192 pixels. Print preflight also enforces a 3
|
|
|
37
43
|
## Formats and colour
|
|
38
44
|
|
|
39
45
|
```sh
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
npx rtistree export alpine --preset print --format pdf
|
|
47
|
+
npx rtistree export alpine --preset print --format tiff
|
|
48
|
+
npx rtistree export alpine --preset screen --format jpeg
|
|
49
|
+
npx rtistree export alpine --format svg -o alpine/output/artwork.svg
|
|
50
|
+
npx rtistree proof alpine --preset print
|
|
51
|
+
npx rtistree export alpine --format project -o /tmp/alpine-copy/scene.json
|
|
46
52
|
```
|
|
47
53
|
|
|
48
54
|
Known artwork extensions are inferred for `export` and full `render`. Region renders remain PNG. A filename extension must agree with the actual format. Portable scene export keeps its original meaning with `--format project` or a JSON/YAML destination, and copies configured print profiles/presets when exporting a project.
|
|
@@ -71,7 +77,7 @@ Preflight checks physical geometry, render capacity, output profiles, font glyph
|
|
|
71
77
|
|
|
72
78
|
Each artwork export has a `.evidence.json` containing the scene hash, output hash, resolved settings, ICC hash, backend versions and inspection of the actual encoded bytes. Raster inspection reads format, dimensions, channels, profile and density. PDF inspection reads page boxes, image colour-space declarations, embedded font descriptors and profile streams. This complements visual proof inspection; it does not replace press validation.
|
|
73
79
|
|
|
74
|
-
##
|
|
80
|
+
## Editing operations
|
|
75
81
|
|
|
76
82
|
Commands are available through `apply` in the CLI, SDK and MCP. See generated command/patch schemas for complete inputs.
|
|
77
83
|
|
|
@@ -93,15 +99,15 @@ Shapes support stroke caps, joins, dash arrays and dash offsets. Text styles sup
|
|
|
93
99
|
|
|
94
100
|
Masks now support editable SVG-style paths, image alpha/luminance/colour-range selections, and union/intersection/subtraction/XOR. Combined masks use one coordinate space; children inherit the outer space and reference size. The processing order is selection/algebra, inversion, grow/shrink, then feathering. Image masks reference an asset directly, making external segmentation masks usable without a visible mask layer.
|
|
95
101
|
|
|
96
|
-
|
|
102
|
+
Additional scoped operations are levels, piecewise-linear RGB/channel curves, white balance, clone and heal. Cloning samples a frozen copy of the target using `source_offset`. Healing adds a local mean-colour correction to that cloned texture; this is a deterministic colour-matched clone, not a Poisson or learned healing algorithm. All operate non-destructively through the existing history and scoped-pixel checks.
|
|
97
103
|
|
|
98
104
|
## SVG interchange and trial
|
|
99
105
|
|
|
100
106
|
```sh
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
npx rtistree import-svg drawing.svg -o drawing.scene.json
|
|
108
|
+
npx rtistree export drawing.scene.json --format svg -o drawing.svg
|
|
103
109
|
```
|
|
104
110
|
|
|
105
111
|
The importer supports static paths, rectangles, circles, ellipses, lines, polygons, polylines, groups, transforms and basic stroke/fill styling. Unsupported elements/attributes, remote resources, scripts and entities are rejected rather than silently dropped. Text, filters and arbitrary CSS are not imported. Exported text is outlined; complex export fallbacks are embedded images. Full round-trip equivalence for arbitrary SVG is not promised.
|
|
106
112
|
|
|
107
|
-
The [print trial](
|
|
113
|
+
The [print trial](https://github.com/Coly010/rtistree/blob/main/examples/print-trial/README.md) used an external image-generation tool to create a ceramic vase/leaf photograph. Rtistree then extracted its silhouette with masks, added a contact shadow and colour adjustment, adapted it to two aspect ratios, and exported CMYK PDF/TIFF/JPEG. The source, exact prompt, edits, critiques, final scenes and output evidence are retained.
|
package/docs/releasing.md
CHANGED
|
@@ -1,60 +1,116 @@
|
|
|
1
1
|
# Release process
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
Rtistree uses Release Please to prepare version and changelog updates, and npm trusted
|
|
4
|
+
publishing to publish from GitHub Actions. The repository is `Coly010/rtistree`, the npm
|
|
5
|
+
package is `rtistree`, and the website is `https://rtistree.dev`.
|
|
6
|
+
|
|
7
|
+
## Everyday releases
|
|
8
|
+
|
|
9
|
+
1. Merge changes into `main` using Conventional Commit messages. For squash merges, use
|
|
10
|
+
a conventional PR title; that title becomes the commit message.
|
|
11
|
+
2. The **Release** workflow opens or updates a release PR with the next version,
|
|
12
|
+
`CHANGELOG.md`, both package lockfiles, and the README and website version labels.
|
|
13
|
+
3. Review the generated notes and the **Graphics engine** and **Documentation website**
|
|
14
|
+
checks on that PR. Release PRs stay open until a maintainer decides to ship.
|
|
15
|
+
4. Merge the release PR. The same workflow creates the `vX.Y.Z` tag and GitHub release,
|
|
16
|
+
validates the tagged source and packaged installation, then publishes the tested
|
|
17
|
+
tarball to npm with provenance. It also attaches that tarball to the GitHub release.
|
|
18
|
+
|
|
19
|
+
There is no npm token or personal access token in this flow. GitHub supplies a short-lived
|
|
20
|
+
OIDC identity that npm checks against the configured repository and workflow.
|
|
21
|
+
|
|
22
|
+
### Commit messages and versions
|
|
23
|
+
|
|
24
|
+
| Commit | Example | Version change |
|
|
25
|
+
| --------------------------------- | -------------------------------------------------- | --------------------------------------- |
|
|
26
|
+
| `fix:` | `fix: preserve layer opacity when undoing an edit` | Patch: 0.5.1 → 0.5.2 |
|
|
27
|
+
| `feat:` | `feat: add palette extraction` | Minor: 0.5.1 → 0.6.0 |
|
|
28
|
+
| Breaking change (`!`) | `feat!: replace the scene coordinate format` | Minor before 1.0; major from 1.0 onward |
|
|
29
|
+
| `docs:`, `ci:`, `chore:`, `test:` | `docs: explain sprite export` | No release on their own |
|
|
30
|
+
|
|
31
|
+
Use a `BREAKING CHANGE:` footer to explain migration steps for breaking changes.
|
|
32
|
+
The largest applicable change determines the release version. Do not edit versions by hand
|
|
33
|
+
for a routine release. Releases continue to use normal `0.x.y` versions on npm's `latest`
|
|
34
|
+
tag while the project is a public alpha; this does not claim a stable 1.0 API.
|
|
35
|
+
|
|
36
|
+
The manifest starts at the already-published 0.5.1. `bootstrap-sha` bounds the initial
|
|
37
|
+
history scan at that tag. Older non-conventional commit messages are not automatically
|
|
38
|
+
converted into changelog entries. Once the first automated release is merged, normal
|
|
39
|
+
release history takes over.
|
|
40
|
+
|
|
41
|
+
## Trusted publisher setup
|
|
42
|
+
|
|
43
|
+
The npm package owner configures this once in the package's settings:
|
|
44
|
+
|
|
45
|
+
- Provider: GitHub Actions
|
|
46
|
+
- Repository owner: `Coly010`
|
|
47
|
+
- Repository: `rtistree`
|
|
48
|
+
- Workflow filename: `release.yml`
|
|
49
|
+
- Environment: leave blank (the workflow does not use a GitHub environment)
|
|
50
|
+
- Permission: publish
|
|
17
51
|
|
|
18
|
-
|
|
19
|
-
Confirm `npm whoami` is the intended owner. Build and inspect the package before publishing:
|
|
52
|
+
Alternatively, with an authenticated npm owner account and 2FA:
|
|
20
53
|
|
|
21
54
|
```sh
|
|
22
|
-
npm
|
|
23
|
-
npm
|
|
55
|
+
npx --yes npm@11.19.1 trust list rtistree
|
|
56
|
+
npx --yes npm@11.19.1 trust github rtistree --repository Coly010/rtistree --file release.yml --allow-publish --yes
|
|
24
57
|
```
|
|
25
58
|
|
|
26
|
-
|
|
27
|
-
|
|
59
|
+
The workflow uses Node.js 24, npm 11.19.1, a GitHub-hosted runner and `id-token: write`.
|
|
60
|
+
No `NPM_TOKEN`, `NODE_AUTH_TOKEN`, or enablement variable is required. A trust mismatch
|
|
61
|
+
fails publication visibly rather than silently skipping it.
|
|
28
62
|
|
|
29
|
-
|
|
63
|
+
In GitHub **Settings → Actions → General → Workflow permissions**, enable **Allow GitHub
|
|
64
|
+
Actions to create and approve pull requests**. GitHub bundles creation and approval in
|
|
65
|
+
one setting; this workflow creates release PRs but does not approve or merge them.
|
|
66
|
+
The repository's default workflow permission can remain read-only.
|
|
30
67
|
|
|
31
|
-
|
|
68
|
+
Bot-created PRs and releases do not trigger ordinary workflows when using `GITHUB_TOKEN`.
|
|
69
|
+
The Release workflow explicitly dispatches both validation workflows on the release PR
|
|
70
|
+
branch and publishes in a dependent job when a release is created. This avoids needing a
|
|
71
|
+
long-lived GitHub token just to trigger CI.
|
|
32
72
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- Workflow filename: `release.yml`
|
|
73
|
+
See the [npm trusted publishing documentation](https://docs.npmjs.com/trusted-publishers/)
|
|
74
|
+
and [Release Please documentation](https://github.com/googleapis/release-please-action).
|
|
36
75
|
|
|
37
|
-
|
|
38
|
-
`NPM_TRUSTED_PUBLISHING_ENABLED` to `true`. Without it, release validation runs but npm
|
|
39
|
-
publication is skipped. This permits the initial GitHub tarball release before npm sign-in.
|
|
76
|
+
## Recovering a failed release
|
|
40
77
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
78
|
+
A GitHub release can exist while npm publication is still running or has failed. Check the
|
|
79
|
+
**Release** workflow before announcing availability. Correct the account/trust problem, then
|
|
80
|
+
use **Actions → Release → Run workflow**, select `main`, and enter the existing tag in the
|
|
81
|
+
`tag` input. Leave the tag blank to refresh the release PR instead.
|
|
45
82
|
|
|
46
|
-
|
|
83
|
+
The retry checks that the tag matches the package, has a published GitHub release and belongs
|
|
84
|
+
to `main`. It rebuilds and tests the tarball. If npm already has that version, the workflow
|
|
85
|
+
only skips publication when its integrity matches the checked tarball; a mismatch or registry
|
|
86
|
+
error fails. Never delete/reuse a published version to fix package contents: ship a new version.
|
|
87
|
+
A failed publish can also be retried by rerunning failed jobs from its original workflow run.
|
|
47
88
|
|
|
48
|
-
##
|
|
89
|
+
## Local validation
|
|
49
90
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
91
|
+
```sh
|
|
92
|
+
npm ci
|
|
93
|
+
npm run check
|
|
94
|
+
npm run format:check
|
|
95
|
+
npm run docs:check
|
|
96
|
+
npm run package:check
|
|
97
|
+
npm ci --prefix website
|
|
98
|
+
npm run build --prefix website
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The package check installs the actual tarball in a temporary project and exercises the CLI,
|
|
102
|
+
starter, rendering, SDK and MCP guide. It retains the checked archive for the publish job.
|
|
103
|
+
Large trial assets stay in the repository; only the small hello example ships in the package.
|
|
53
104
|
|
|
54
|
-
|
|
55
|
-
The Sites project ID is in `website/.openai/hosting.json`; never replace it on redeployment.
|
|
56
|
-
Use the Sites publishing flow to save and deploy the validated source and static archive.
|
|
57
|
-
The `website.yml` workflow validates and uploads a deployable static artifact for each change.
|
|
105
|
+
## Website deployment
|
|
58
106
|
|
|
59
|
-
|
|
60
|
-
|
|
107
|
+
The website is an Astro/Starlight static build in `website/`. `docs/` is the source of truth;
|
|
108
|
+
the content sync script publishes an explicit list of current user guides plus the changelog,
|
|
109
|
+
remaps repository links and copies curated assets. Maintainer procedures and historical proposals/
|
|
110
|
+
decisions remain in the repository. Removed generated routes and raw source copies are deleted
|
|
111
|
+
during synchronization. Generated files are ignored by Git but included in a standalone Sites source snapshot.
|
|
112
|
+
|
|
113
|
+
`npm run build --prefix website` produces `website/dist`. The `website.yml` workflow validates
|
|
114
|
+
and uploads that static artifact. **npm releases do not deploy the live website.** Publish the
|
|
115
|
+
validated website through the Sites flow when documentation or the displayed version changes.
|
|
116
|
+
Keep the existing project ID in `website/.openai/hosting.json` when redeploying.
|
package/docs/scene-format.md
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
# Scene format v1
|
|
2
2
|
|
|
3
|
-
The examples in this document are the implemented format. The original proposal is exploratory; unsupported fields are rejected, not silently interpreted.
|
|
3
|
+
The examples in this document are the implemented format. The original proposal is exploratory; unsupported fields are rejected, not silently interpreted. The package ships schemas in `node_modules/rtistree/schemas/`. Use `authoring.schema.json`
|
|
4
|
+
for source scenes with includes/components and `fragment.schema.json` for included files.
|
|
5
|
+
`npx rtistree schema --kind scene` prints the resolved scene schema; `--kind command` prints
|
|
6
|
+
a single-command schema. A transaction uses `patch.schema.json`. Repository contributors
|
|
7
|
+
can regenerate all schemas with `npm run schema`.
|
|
4
8
|
|
|
5
|
-
The [production guide](production.md) describes
|
|
9
|
+
The [production guide](production.md) describes physical documents, exports, affine and perspective transforms, extended masks, adjustments, path commands and typography.
|
|
6
10
|
|
|
7
|
-
The [studio guide](studio.md) describes
|
|
11
|
+
The [studio guide](studio.md) describes programmable assets and dense editing. Assets may carry a `recipe: {source, hash}` reference to a frozen program manifest. Promoted regions accept `composite: replace|over` (default replacement). Programs are executed explicitly and baked; scenes never execute referenced recipes while rendering.
|
|
8
12
|
|
|
9
13
|
## Files and assets
|
|
10
14
|
|
|
11
|
-
Root documents contain `version: 1`, `canvas`, `layers` and/or `include`, optional `assets`, `metadata`, and `verification: {rules: [...]}`. Fragments contain `include`, `assets`, `fonts`, `components` and `layers`. JSON and YAML can be mixed.
|
|
15
|
+
Root documents contain `version: 1`, `canvas`, optional `layers` and/or `include`, optional `assets`, `metadata`, and `verification: {rules: [...]}`. Fragments contain `include`, `assets`, `fonts`, `components` and `layers`. JSON and YAML can be mixed. Root scenes can also declare `fonts`, `components`, `document` and `paragraph_styles`.
|
|
16
|
+
The loader permits at most 128 document reads including the root, and 256 total layers after expansion.
|
|
12
17
|
|
|
13
18
|
```yaml
|
|
14
19
|
assets:
|
|
15
20
|
portrait:
|
|
16
21
|
type: image # or generated-image; provenance category only
|
|
17
22
|
source: ./assets/portrait.png
|
|
18
|
-
hash
|
|
23
|
+
# hash is optional; when supplied, use sha256: followed by the file’s 64 hex digest characters
|
|
19
24
|
```
|
|
20
25
|
|
|
21
26
|
PNG, JPEG, WebP and TIFF assets are supported. ICC-tagged input is normalised to sRGB. The separate `import-svg` command converts a closed static geometry subset into scene layers. No URL loading or external resource resolution is permitted. Asset paths must resolve inside the root scene directory, including after symlink resolution. File size is limited to 64 MiB and decoded dimensions to 32 megapixels. Large rasters belong in binary image files, not YAML arrays.
|
|
@@ -66,7 +71,7 @@ Shapes are `rectangle` (optional radius), `ellipse`, or `path` with SVG path dat
|
|
|
66
71
|
|
|
67
72
|
Text is retained as semantic content. It wraps at whitespace and respects explicit newlines. `style` supports `font: inter|display`, `size`, `weight: regular|bold`, `colour`, `line_height` as a multiplier, and `align: left|center|right`. `display` uses DM Serif Display regular; its bold variant is not supplied. Text is clipped to its box, and the verifier reports overflow. Bundled Latin fonts provide reproducible typography; a custom font can be registered in the scene fonts map and selected by its ID.
|
|
68
73
|
|
|
69
|
-
Generators: `solid` (`colour`); `gradient` (`from`, `to`, `angle`, with 0° horizontal and 90° vertical); `noise` (`seed`, `amount`, optional base `colour`). Every
|
|
74
|
+
Generators: `solid` (`colour`); `gradient` (`from`, `to`, `angle`, with 0° horizontal and 90° vertical); `noise` (`seed`, `amount`, optional base `colour`). Every noise generator requires an explicit integer seed. Noise is sampled in a stable row-major order.
|
|
70
75
|
|
|
71
76
|
Blend modes: normal, multiply, screen, overlay, darken, lighten, difference, soft-light, hard-light. Compositing and colour adjustments use Skia's sRGB path; this is not a linear-light color grading engine.
|
|
72
77
|
|
|
@@ -115,12 +120,44 @@ Tiles have canvas bounds, a single-character palette, and rows of keys. Rows mus
|
|
|
115
120
|
|
|
116
121
|
`replaceTile` replaces a tile with exactly matching bounds or appends a new one. Transparent tile pixels composite over underlying layer content. Palette tiles remain compact grids. Separately, `promoteRegion`, `updateRegion` and `demoteRegion` manage patches with 1–4× resolution and optional external raster sources; see [evolution](evolution.md).
|
|
117
122
|
|
|
123
|
+
For a complete pixel-art and sprite workflow, see [Pixel art, sprites and
|
|
124
|
+
spritesheets](sprites.md). An optional pixel-art scene contract makes integer
|
|
125
|
+
coordinates, palette use and nearest-neighbour delivery explicit:
|
|
126
|
+
|
|
127
|
+
```yaml
|
|
128
|
+
pixel_art:
|
|
129
|
+
scale: 1 # authored tile pixel → scene-pixel multiplier
|
|
130
|
+
palette: ['#00000000', '#f2be81', '#b75c40']
|
|
131
|
+
strict: true # reject transforms/blur and invalid tile geometry
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The optional `sprites` manifest selects integer canvas rectangles and records
|
|
135
|
+
their game-facing pivot, duration and tags. Animations list frame IDs and a
|
|
136
|
+
loop flag. Atlas settings support padding, edge extrusion, power-of-two output
|
|
137
|
+
and a maximum width:
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
sprites:
|
|
141
|
+
frames:
|
|
142
|
+
walk_0: { bounds: [0, 0, 16, 16], pivot: [8, 14], duration: 120, tags: [walk, right] }
|
|
143
|
+
animations:
|
|
144
|
+
walk_right: { frames: [walk_0], loop: true }
|
|
145
|
+
atlas: { padding: 1, extrusion: 1, power_of_two: true, max_width: 2048 }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`rtistree sprites scene.json -o atlas.png --manifest atlas.json` renders the
|
|
149
|
+
declared frame rectangles and writes an engine-neutral, deterministic atlas
|
|
150
|
+
manifest. Frames are not trimmed; exported records retain both atlas and source
|
|
151
|
+
rectangles. Use `rtistree schema --kind scene` for the complete scene contract
|
|
152
|
+
and `rtistree schema --kind sprites` for export options in the installed version.
|
|
153
|
+
|
|
118
154
|
## Commands and verification
|
|
119
155
|
|
|
120
|
-
`apply` accepts `{reason, expected_hash?, commands: [...]}`. Commands include add/remove/move/resize layer, set opacity/blend/text/style, group siblings, align/distribute siblings, apply effect, apply raster operation, and replace tile. See `
|
|
156
|
+
`apply` accepts `{reason, expected_hash?, commands: [...]}`. Commands include add/remove/move/resize layer, set opacity/blend/text/style, group siblings, align/distribute siblings, apply effect, apply raster operation, and replace tile. See `rtistree schema --kind command` for exact fields. Removing referenced mask or verification targets is rejected unless the resulting scene is valid. Grouping can change compositing with interleaved siblings; it is an explicit structural edit without a locality promise.
|
|
121
157
|
|
|
122
158
|
Verification always checks rendered text overflow. Optional rules cover safe-area, text-overflow, text-equals, required-role, contrast, no-overlap and region-luma. Luma is a mean weighted sRGB channel value in [0,1], not perceptual luminance. `contrast` uses declared foreground and explicit background colours. `pixel-contrast` and `visible-area` use counterfactual rendered samples through `verifyRendered` / `Project.verify`. Geometry checks use transformed bounding boxes, not exact silhouettes. A heatmap marks issue bounds. All reports state these limitations.
|
|
123
159
|
|
|
124
|
-
`render-region` requires an integer rectangle fully inside the canvas and equals an exact crop of the full render. `draft` halves both output dimensions after rendering; preview and final currently use the same full-quality pipeline. PNG output includes renderer evidence in a sidecar.
|
|
160
|
+
`render-region` requires an integer rectangle fully inside the canvas and equals an exact crop of the full render. `draft` halves both output dimensions after rendering; preview and final currently use the same full-quality pipeline. PNG output includes renderer evidence in a sidecar. Scene hashes cover the resolved scene, including authored metadata. Journal timestamps are outside
|
|
161
|
+
that scene hash and do not influence pixel output; a timestamp you put in scene metadata does change the hash.
|
|
125
162
|
|
|
126
163
|
The [evolution guide](evolution.md) documents the expanded command surface, coordinates, components, fonts, adaptive regions, critiques, rebase, compaction, and agent trials.
|
package/docs/sprites.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Pixel art, sprites and spritesheets
|
|
2
|
+
|
|
3
|
+
Rtistree can author small raster assets and package them as a sprite set. The
|
|
4
|
+
sprite workflow is deliberately split into two jobs:
|
|
5
|
+
|
|
6
|
+
1. draw and inspect each frame as an ordinary Rtistree scene or studio asset;
|
|
7
|
+
2. describe the frames, pivots and animation timing in a `sprites` manifest and
|
|
8
|
+
export a deterministic atlas for the game or other runtime to consume.
|
|
9
|
+
|
|
10
|
+
This keeps the artwork editable and reviewable while making the delivery format
|
|
11
|
+
boring and portable. Rtistree is an asset authoring and verification tool here;
|
|
12
|
+
it is not a game engine, a runtime animation system or an automatic animation
|
|
13
|
+
critic.
|
|
14
|
+
|
|
15
|
+
## Choose the pixel-art contract
|
|
16
|
+
|
|
17
|
+
Use the optional `pixel_art` scene contract when the image is meant to be read
|
|
18
|
+
as pixels rather than as a smoothly sampled illustration. A pixel-art scene
|
|
19
|
+
should declare its palette policy and grid scale, then keep the following
|
|
20
|
+
invariants visible to the agent and reviewer:
|
|
21
|
+
|
|
22
|
+
- coordinates and frame dimensions are integer pixels;
|
|
23
|
+
- colour choices come from the declared palette, including transparency;
|
|
24
|
+
- `scale` is an integer multiplier from a tile's authored grid to its
|
|
25
|
+
scene-pixel bounds;
|
|
26
|
+
- atlas sampling uses nearest-neighbour filtering;
|
|
27
|
+
- frame canvases and pivots are stable across an animation;
|
|
28
|
+
- strict mode rejects transforms, rotation and blur on the scene's pixel-art
|
|
29
|
+
layers and checks tile geometry and declared palette membership.
|
|
30
|
+
|
|
31
|
+
The contract does not make a weak drawing good. It makes common production
|
|
32
|
+
mistakes detectable and makes an intentional one-pixel edit auditable. Keep
|
|
33
|
+
the intended game display size in the brief and inspect the result at that size
|
|
34
|
+
as well as zoomed in.
|
|
35
|
+
|
|
36
|
+
For small, deliberately indexed marks, palette tiles are the compact scene
|
|
37
|
+
primitive:
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
- id: lantern
|
|
41
|
+
type: raster
|
|
42
|
+
tiles:
|
|
43
|
+
- bounds: [8, 8, 10, 6]
|
|
44
|
+
palette:
|
|
45
|
+
.: '#00000000'
|
|
46
|
+
a: '#f2be81'
|
|
47
|
+
b: '#b75c40'
|
|
48
|
+
pixels:
|
|
49
|
+
- '....aa....'
|
|
50
|
+
- '...abba...'
|
|
51
|
+
- '..abbbba..'
|
|
52
|
+
- '..abbbba..'
|
|
53
|
+
- '...abba...'
|
|
54
|
+
- '....aa....'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Rows must be equal in width and every key must exist in the palette. Palette
|
|
58
|
+
tiles are limited to 256 × 256 and are scaled with nearest-neighbour sampling.
|
|
59
|
+
Use `replaceTile` for an auditable tile-sized revision. For dense or generated
|
|
60
|
+
frames, use the studio's `art.raster`, `art.pixels` and `art.put` APIs instead;
|
|
61
|
+
those bake ordinary PNG assets with a replayable recipe.
|
|
62
|
+
|
|
63
|
+
The complete scene and command shapes are in [scene format](scene-format.md).
|
|
64
|
+
Run `rtistree schema --kind scene` or `rtistree schema --kind command` against
|
|
65
|
+
the installed version rather than copying a stale schema from a blog post.
|
|
66
|
+
|
|
67
|
+
## Build a sprite set
|
|
68
|
+
|
|
69
|
+
Start with one representative character frame and one representative prop.
|
|
70
|
+
Record the intended facing, ground line, display scale, palette, silhouette and
|
|
71
|
+
pivot before multiplying the set. A useful frame brief says what must remain
|
|
72
|
+
stable (for example, the foot contact point) and what changes (for example,
|
|
73
|
+
the lifted leg).
|
|
74
|
+
|
|
75
|
+
The scene's `sprites` manifest is the delivery description for a set. Each
|
|
76
|
+
`frames[id].bounds` is a canvas rectangle selecting source pixels. The exporter
|
|
77
|
+
writes a JSON manifest in which each output `frames[id]` records:
|
|
78
|
+
|
|
79
|
+
- the frame rectangle in the atlas;
|
|
80
|
+
- the original canvas `source` rectangle;
|
|
81
|
+
- the pixel pivot or origin used by the game;
|
|
82
|
+
- optional duration and tags such as `idle`, `contact` or `recovery`;
|
|
83
|
+
- animation order and loop behaviour; use tags to carry labels such as facing.
|
|
84
|
+
|
|
85
|
+
Atlas placement is deterministic. The same frame inputs and atlas settings
|
|
86
|
+
produce the same packed image and metadata on the same pinned runtime. Keep
|
|
87
|
+
the atlas image and its metadata together; the metadata is part of the asset,
|
|
88
|
+
not an optional comment for the viewer.
|
|
89
|
+
|
|
90
|
+
Export the set with the installed command:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
npx rtistree sprites scene.json -o output/sprites.png --manifest output/sprites.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The command accepts a scene or configured project containing the sprite
|
|
97
|
+
manifest. Use `npx rtistree sprites --help` and the installed schema/help
|
|
98
|
+
output for the exact options in the release you are using. The PNG path must
|
|
99
|
+
end in `.png` and the manifest path in `.json`. The export produces an atlas
|
|
100
|
+
image plus machine-readable frame and animation metadata. Frames are not
|
|
101
|
+
trimmed or rotated. `padding`, `extrusion`, `power_of_two` and `max_width`
|
|
102
|
+
control packing; edge extrusion copies the frame's edge pixels and the
|
|
103
|
+
remaining padding stays transparent.
|
|
104
|
+
|
|
105
|
+
The same export is available through the SDK as `exportSpriteSheet(project,
|
|
106
|
+
output, options)` and through the MCP `exportSprites` tool. SDK callers should
|
|
107
|
+
retain the returned atlas and metadata as release artifacts; MCP callers should
|
|
108
|
+
expose the result to the agent so it can inspect the actual image and not only
|
|
109
|
+
the JSON. The MCP tool writes `<name>.png` and `<name>.json` into the configured
|
|
110
|
+
project output directory.
|
|
111
|
+
|
|
112
|
+
## Review an animation before shipping it
|
|
113
|
+
|
|
114
|
+
Technical validity and animation quality are separate gates. For each set,
|
|
115
|
+
check the following in order:
|
|
116
|
+
|
|
117
|
+
1. Render every frame and inspect a contact sheet at the intended display size.
|
|
118
|
+
2. Confirm frame dimensions, alpha margins, palette use, atlas rectangles and
|
|
119
|
+
pivots against the manifest.
|
|
120
|
+
3. Play a complete loop against a ground marker. Inspect contact, passing and
|
|
121
|
+
recovery frames, then inspect the loop boundary.
|
|
122
|
+
4. Check that the subject's silhouette, weight, facing and prop ownership read
|
|
123
|
+
consistently. For walking, planted feet should remain coherent against the
|
|
124
|
+
ground while lifted feet recover in the travel direction.
|
|
125
|
+
5. Record technical, functional and visual results separately. A set can have
|
|
126
|
+
reproducible PNGs and valid metadata while still being rejected for weak
|
|
127
|
+
posing, muddy silhouettes or a broken loop.
|
|
128
|
+
|
|
129
|
+
`rtistree verify` can check declared technical constraints and scoped changes;
|
|
130
|
+
it cannot watch a loop, judge a silhouette or prove that a reviewer looked at
|
|
131
|
+
the image. Keep the rendered frames, contact sheet, atlas, manifest and any
|
|
132
|
+
rejected revision together so a later agent can compare against the actual
|
|
133
|
+
parent rather than trusting a summary.
|
|
134
|
+
|
|
135
|
+
## Existing example
|
|
136
|
+
|
|
137
|
+
The [Verdigris Watch asset trial](https://github.com/Coly010/rtistree/tree/main/examples/warden-asset-trial)
|
|
138
|
+
is the reference end-to-end example. It draws 17 transparent sprites, bakes an
|
|
139
|
+
eight-frame walk cycle, records fixed pivots and 8 fps playback metadata, packs
|
|
140
|
+
an atlas, and provides a small viewer for stepping through the loop. Its
|
|
141
|
+
`render.mjs` and `verify.mjs` intentionally keep atlas assembly and motion
|
|
142
|
+
checks visible, so the example also documents what the first-class export is
|
|
143
|
+
meant to make less bespoke.
|
|
144
|
+
|
|
145
|
+
The trial is evidence of a reproducible workflow, not a claim that every image
|
|
146
|
+
is production-quality. Read its review and inspect the actual frames before
|
|
147
|
+
using it as a visual reference.
|
|
148
|
+
|
|
149
|
+
For the smallest strict-pixel example, see
|
|
150
|
+
[`examples/pixel-sprite-lab`](https://github.com/Coly010/rtistree/tree/main/examples/pixel-sprite-lab).
|
|
151
|
+
It uses four 16 × 16 palette-tile frames, a fixed `[8, 14]` pivot, 120 ms
|
|
152
|
+
durations, a `walk_right` animation, one-pixel padding and one-pixel edge
|
|
153
|
+
extrusion. Its verifier checks source-to-atlas pixels, palette use, fixed
|
|
154
|
+
pivots and deterministic cold export.
|
|
155
|
+
|
|
156
|
+
## Scope and limits
|
|
157
|
+
|
|
158
|
+
The sprite workflow is a neutral asset format. It does not add a dependency on
|
|
159
|
+
Godot, Unity, Phaser or another game engine, and it does not promise a native
|
|
160
|
+
timeline, inverse kinematics, automatic retargeting, palette optimisation or
|
|
161
|
+
automatic visual approval. A renderer or game project can consume the atlas and
|
|
162
|
+
metadata through its own adapter.
|
|
163
|
+
|
|
164
|
+
For a broader view of the agent protocol, read [art direction for agents](agent-art-workflow.md),
|
|
165
|
+
then [programmable digital art](studio.md) for seeded frame generation and
|
|
166
|
+
[production](production.md) for general image export.
|
package/docs/studio.md
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
# Programmable digital art
|
|
1
|
+
# Programmable digital art
|
|
2
2
|
|
|
3
3
|
The studio is the escape hatch below scene abstractions. An agent can build an image using paths and gradients, paint pressure-sensitive strokes, calculate pixel colours, sample textures, or write a custom image-processing algorithm. No image-generation model is used by these tools.
|
|
4
4
|
|
|
5
5
|
Scene layers still describe composition. Programs produce ordinary pinned PNG assets and can replace the source of a raster/image layer. Their exact source, seed, parameters, input snapshots and output hash are saved as a recipe. Rendering, inspecting and opening a scene never runs a program. Re-execution is explicit, and existing edits remain undoable.
|
|
6
6
|
|
|
7
|
+
This is also the frame-generation path for sprites: keep the frame construction
|
|
8
|
+
function pure and parameterise its pose or animation phase, then bake one asset
|
|
9
|
+
per frame. A `sprites` manifest can reference those frames and the sprite
|
|
10
|
+
exporter can pack them into an atlas with pivots, durations and animation tags.
|
|
11
|
+
See [pixel art, sprites and spritesheets](sprites.md) for the review and delivery
|
|
12
|
+
workflow.
|
|
13
|
+
|
|
7
14
|
## First painting
|
|
8
15
|
|
|
16
|
+
Run these commands from a directory where `npm install rtistree` has already completed.
|
|
17
|
+
`project new` creates a scene project; unlike `init`, it does not create a package.json
|
|
18
|
+
or install Rtistree. The custom size `100x100` is in millimetres and gives this example
|
|
19
|
+
a 400 × 400 design canvas.
|
|
20
|
+
|
|
9
21
|
```sh
|
|
10
|
-
|
|
11
|
-
|
|
22
|
+
npx rtistree project new study --size 100x100
|
|
23
|
+
npx rtistree studio-help
|
|
12
24
|
```
|
|
13
25
|
|
|
14
26
|
Save this as `study/programs/rubber.js`:
|
|
@@ -41,16 +53,16 @@ Save a request as `study/paint.json`:
|
|
|
41
53
|
```
|
|
42
54
|
|
|
43
55
|
```sh
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
npx rtistree program study study/paint.json
|
|
57
|
+
npx rtistree render study -o study/output/rubber.png
|
|
58
|
+
npx rtistree program-replay study rubberPaint
|
|
47
59
|
```
|
|
48
60
|
|
|
49
61
|
Supply exactly one of `source` (a project-local JavaScript file) or `code` (an inline function body). A program receives `art` and `parameters`, runs synchronously and returns one Canvas with the declared dimensions. It cannot import modules through the public API. A new `target` creates a raster layer; an existing target must accept an image source. Omit `target` to register an asset for subsequent mask, region or layer operations. The runner captures the starting scene hash and rejects a concurrent edit before committing.
|
|
50
62
|
|
|
51
63
|
## Authoring vocabulary
|
|
52
64
|
|
|
53
|
-
`
|
|
65
|
+
`rtistree studio-help` and the MCP `studioHelp` tool expose the complete signatures and a runnable example. TypeScript consumers can use `RasterStudio` from the SDK.
|
|
54
66
|
|
|
55
67
|
| API | Purpose |
|
|
56
68
|
| ----------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
@@ -72,9 +84,10 @@ Height-field lighting is an artistic 2.5D calculation, with the viewer along pos
|
|
|
72
84
|
|
|
73
85
|
## Dense regional edits
|
|
74
86
|
|
|
75
|
-
`readRasterRegion` / `
|
|
87
|
+
`readRasterRegion` / `rtistree raster-read PROJECT request.json` read a PNG crop of the composite or an isolated layer. The request contains integer canvas-space `bounds` and an optional `target`. The result includes the scene hash and an asset descriptor (`source` and `hash`). Wrap
|
|
88
|
+
that descriptor in a `registerAsset` command with an `id` before using it as a program input.
|
|
76
89
|
|
|
77
|
-
`writeRasterRegion` / `
|
|
90
|
+
`writeRasterRegion` / `rtistree raster-write PROJECT request.json` consumes:
|
|
78
91
|
|
|
79
92
|
```json
|
|
80
93
|
{
|
|
@@ -89,7 +102,8 @@ Height-field lighting is an artistic 2.5D calculation, with the viewer along pos
|
|
|
89
102
|
}
|
|
90
103
|
```
|
|
91
104
|
|
|
92
|
-
The source must be a project-local PNG matching the region's exact dimensions. `replace` clears/replaces the region, including alpha; `over` composites it onto the previous pixels. The command creates or updates a named promoted region at scale 1 and stores an immutable copy of the PNG. `space: layer` captures reference dimensions, so the patch follows later transforms and resizing. `space: canvas` stays at canvas coordinates.
|
|
105
|
+
The source must be a project-local PNG matching the region's exact dimensions. `replace` clears/replaces the region, including alpha; `over` composites it onto the previous pixels. The command creates or updates a named promoted region at scale 1 and stores an immutable copy of the PNG. `space: layer` captures reference dimensions, so the patch follows later transforms and resizing. `space: canvas` stays at canvas coordinates. The patch is composited after the target layer’s effects and ordinary operations, but
|
|
106
|
+
before its mask and opacity. Ancestor effects can still change its appearance; locality validation rejects changes leaking outside the declared region. Undo/redo restores the prior image.
|
|
93
107
|
|
|
94
108
|
For a custom filter, register the descriptor returned by the read, pass that asset to `runProgram.inputs`, calculate the new pixels, and write the returned PNG into a region. Use the latest scene hash returned by each mutation. Canvas-space reads cannot automatically become local-space reads of a rotated object; use canvas-space patch coordinates for a direct read/edit/write round trip.
|
|
95
109
|
|
|
@@ -101,8 +115,9 @@ Programs execute only when explicitly requested and must be trusted code. A work
|
|
|
101
115
|
|
|
102
116
|
The runner checks a 16-megapixel output limit, 16 input images, an 8,192-pixel edge, 256 KiB source, 64 KiB parameters, and up to 30 seconds of execution. The parent watchdog allows two additional seconds for worker setup. Studio helper allocations are capped at 32 cumulative megapixels including inputs; V8's heap limit is 256 MiB. Native Canvas buffers and arbitrary allocations made through exposed native objects are outside the V8 accounting, so these limits are not an OS memory quota. Scene rendering retains its separate surface budget.
|
|
103
117
|
|
|
104
|
-
|
|
118
|
+
Programs do not rebake automatically. The [pipeline API](atelier.md) provides an explicit
|
|
119
|
+
dependency graph with caching; run it when you want to rebuild changed nodes. Changing program code, parameters or an input does not automatically rebake dependent assets. Explicit execution replaces a target source through the existing transaction/history mechanism. If execution or commit fails, the scene is unchanged; a late failed commit can leave unreferenced content-addressed artifacts.
|
|
105
120
|
|
|
106
121
|
## Trial
|
|
107
122
|
|
|
108
|
-
The [manual wheel trial](
|
|
123
|
+
The [manual wheel trial](https://github.com/Coly010/rtistree/blob/main/examples/manual-wheel-trial/README.md) used no model-generated or downloaded imagery. Its eight layers were painted with code, geometry, material fields, text and brushes. Source, recipes, initial/refined images, critiques and replay checks are retained. The result demonstrates a reproducible digital illustration; its visual evaluation explicitly leaves photographic realism unachieved.
|