pixelkiln 0.2.0 → 0.4.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/docs/AGENTS.md CHANGED
@@ -28,14 +28,14 @@ With the skill loaded, an agent should:
28
28
  5. Pass an explicit `--budget` within the amount the user authorized.
29
29
  6. Leave artwork selection in the local `pick` page unless the user gives a
30
30
  specific selection rule.
31
- 7. Commit the manifest, lockfile, generated output, and artifact companions—but
31
+ 7. Commit the manifest, lockfile, generated output, and artifact companions, but
32
32
  never credentials or `.pixelkiln/` caches.
33
33
 
34
34
  The skill guides the workflow; PixelKiln remains the deterministic execution
35
35
  layer. This separation keeps agent reasoning out of polling, hashing, downloads,
36
36
  state transitions, and output placement.
37
37
 
38
- ## PixelLab MCP and PixelKiln
38
+ ## Providers, PixelLab MCP, and PixelKiln
39
39
 
40
40
  The [official PixelLab MCP server](https://github.com/pixellab-code/pixellab-mcp)
41
41
  gives an agent direct PixelLab creation tools. It is complementary to PixelKiln,
@@ -47,10 +47,17 @@ not a replacement:
47
47
  | PixelKiln skill | Agent guidance for safe project-level operations. |
48
48
  | PixelKiln library/CLI | Budgets, state, provenance, review, recovery, audit, and packaging. |
49
49
  | PixelLab adapter | The current production and live-tested generation backend. |
50
-
51
- PixelKiln's core is provider-neutral by design, but PixelLab is the only
52
- production adapter today. Do not claim compatibility with another backend until
53
- its adapter and live integration tests ship.
50
+ | Retro Diffusion adapter | Experimental backend; authenticated paid single-still lifecycle plus mocked advanced-workflow tests. |
51
+
52
+ PixelKiln's core is provider-neutral, but PixelLab remains the only production
53
+ and paid-generation-tested adapter. Retro Diffusion generation support is
54
+ experimental. Paid RD Fast and RD Plus single-candidate stills have passed from
55
+ quote through validated download and recovery. Multi-candidate, tileset, GIF,
56
+ and spritesheet workflows still need representative live smoke tests. See
57
+ [PixelLab vs. Retro Diffusion](../PROVIDERS.md) before choosing a provider for a
58
+ new project or a large environment asset. Once chosen, follow
59
+ [Set up PixelLab](./PIXELLAB.md) or
60
+ [Set up Retro Diffusion](./RETRO_DIFFUSION.md).
54
61
 
55
62
  ## Recommended first prompt
56
63
 
@@ -5,7 +5,7 @@ PixelKiln separates provider mechanics from the project state machine:
5
5
  ```text
6
6
  manifest + lock + planning + review + recovery + artifact pipelines
7
7
  ──────────────────── Provider interface ─────────────────────────
8
- PixelLabProvider FakeProvider future adapters
8
+ PixelLabProvider RetroDiffusionProvider FakeProvider future adapters
9
9
  ```
10
10
 
11
11
  Everything above the provider boundary is backend-neutral. URL shapes, auth
@@ -31,7 +31,8 @@ retain:
31
31
  - provider and remote object/job ids;
32
32
  - explicit lifecycle status and errors;
33
33
  - source URLs/candidates/selections;
34
- - `outputs[]` with portable path, SHA-256, and optional structural role;
34
+ - `outputs[]` with portable path, SHA-256, optional structural role, and
35
+ optional PNG/GIF media type;
35
36
  - provider-specific metadata under a provider-id namespace;
36
37
  - successful submission cost and cost unit.
37
38
 
@@ -41,8 +42,10 @@ are rebased in memory and rewritten portably on the next save. The current
41
42
  manifest remains destination authority; a stale lock path cannot redirect
42
43
  restore into an unrelated project file.
43
44
 
44
- Unlike cost units—`generations`, `usd`, and `free`—are never summed. Candidate
45
- count also belongs to the provider estimate rather than being assumed globally.
45
+ Cost units that differ are never summed. Built-in adapters currently use
46
+ `generations`, `usd`, and `free`; custom adapters may register another
47
+ non-empty unit. Candidate count also belongs to the provider estimate rather
48
+ than being assumed globally.
46
49
 
47
50
  ## State machine
48
51
 
@@ -71,15 +74,17 @@ and exporters all use the same role model. A consumer must request a role when
71
74
  there is no unambiguous primary output.
72
75
 
73
76
  PNG ingestion validates signature, chunks, CRCs, palettes, compressed data,
74
- scanlines, dimensions, and supported color modes before bytes become durable
75
- output or recovery cache data.
77
+ scanlines, dimensions, and supported color modes. GIF ingestion walks the
78
+ logical screen, color tables, extensions, image-data blocks, and trailer. Both
79
+ formats are validated before bytes become durable output or recovery cache data.
76
80
 
77
81
  ## Concurrency and lock saves
78
82
 
79
83
  Lock writes use a same-directory temporary file and rename. An advisory writer
80
84
  lock serializes separate processes. In-process saves queue per path, and
81
85
  field-level dirty patches merge separate snapshots so updates to different
82
- assets—or different fields of one asset—do not silently lose the earlier write.
86
+ assets, or to different fields of one asset, do not silently lose the earlier
87
+ write.
83
88
  Stale advisory locks are recoverable after their safety window.
84
89
 
85
90
  ## Derived artifact transactions
@@ -110,11 +115,18 @@ byte is structurally validated before use.
110
115
 
111
116
  ## Provider capability boundary
112
117
 
113
- Required provider members cover support/estimate, submit, poll, selection where
114
- applicable, and download. Account-wide listing, tagging, deletion, and balance
115
- are optional. Commands such as adopt or salvage report a capability gap rather
116
- than failing through an undefined method.
117
-
118
- `FakeProvider` implements the same contract in memory, which keeps the paid
119
- pipeline testable without credentials or network access. See
120
- [library API](./LIBRARY.md) and [provider notes](../PROVIDERS.md).
118
+ Providers are selected from a registry by the manifest's top-level `provider`
119
+ id. Required members cover support/estimate, submit, poll, and download;
120
+ candidate selection is required only when an adapter can return alternatives.
121
+ Account-wide listing, tagging, deletion, and balance are optional. Commands
122
+ such as adopt or salvage report a capability gap rather than failing through
123
+ an undefined method.
124
+
125
+ `PixelLabProvider` is production and live-tested. `RetroDiffusionProvider` is
126
+ an experimental still, tileset, and animation adapter. Authenticated RD Fast
127
+ and RD Plus single-candidate still lifecycles have passed end to end. Its
128
+ multi-candidate, tileset, GIF, and spritesheet paths retain mocked coverage
129
+ pending paid live smokes. `FakeProvider` implements the same contract in memory, which
130
+ keeps the paid pipeline testable without credentials or network access. See
131
+ [library API](./LIBRARY.md) and
132
+ [PixelLab vs. Retro Diffusion](../PROVIDERS.md).
package/docs/CLI.md CHANGED
@@ -9,6 +9,11 @@ Unknown commands, positional arguments, and flags are errors. Repeated
9
9
  separated values work too. This strict parsing prevents a misspelled filter
10
10
  from widening a paid run.
11
11
 
12
+ The manifest's top-level `provider` field selects the provider for `plan`,
13
+ `doctor`, and pipeline commands. It defaults to `pixellab`; the built-in
14
+ `retrodiffusion` adapter is experimental and supports still-image
15
+ `map`/`pixflux`, `tiles` sheets, and `animation` GIF/spritesheet work.
16
+
12
17
  ## Everyday pipeline
13
18
 
14
19
  ### `init`
@@ -73,9 +78,10 @@ for a screenshot of the actual interface.
73
78
 
74
79
  ### `fetch`
75
80
 
76
- Download completed or selected outputs, validate complete PNG structure, write
77
- the manifest-authoritative destinations, populate the content cache, and update
78
- output hashes. `--tag` also pushes manifest tags after successful downloads.
81
+ Download completed or selected outputs, validate complete PNG or GIF structure,
82
+ write the manifest-authoritative destinations, populate the content cache, and
83
+ update output hashes. `--tag` also pushes manifest tags after successful
84
+ downloads when the provider supports tagging.
79
85
 
80
86
  ### `restore`
81
87
 
@@ -134,13 +140,57 @@ or download artwork.
134
140
 
135
141
  ### `balance`
136
142
 
137
- Show the provider's remaining balance and cost unit.
143
+ Show the manifest-selected provider's remaining balance and cost unit. Reports
144
+ a capability error when an installed provider has no balance endpoint.
138
145
 
139
146
  ### `status`
140
147
 
141
148
  Summarize lock entries by state and successful submission spend by cost unit.
142
149
  Supports `--json`; unlike units are never added together.
143
150
 
151
+ ### `workspace`
152
+
153
+ Register sibling projects in a schema-versioned catalog file, outside any one
154
+ manifest, so a shared provider account's complete claim set no longer depends
155
+ on remembering every `--claims` path. Offline throughout.
156
+
157
+ ```bash
158
+ pixelkiln workspace add ../other-game/pixelkiln.manifest.json
159
+ pixelkiln workspace add ../another-game/pixelkiln.manifest.json --name another
160
+ pixelkiln workspace list
161
+ pixelkiln workspace status --json
162
+ pixelkiln workspace claims
163
+ pixelkiln workspace remove another
164
+ ```
165
+
166
+ Subcommands:
167
+
168
+ | Subcommand | Effect |
169
+ |---|---|
170
+ | `add <manifest>` | Registers a project. Id defaults to the manifest's `name`; `--name` overrides it. Lock defaults to `pixelkiln.lock.json` beside the manifest; `--lock` overrides it. `--provider` overrides the manifest's provider id; `--account` sets a free-form account label. Refuses a duplicate id or a lockfile already registered under another id. Warns, but does not refuse, when the lock does not exist yet. |
171
+ | `remove <id-or-manifest>` | Drops a registration by project id or by manifest path. Touches no art, no lock, no provider account. |
172
+ | `list` | Lists registered projects and catalog diagnostics. Refuses if the catalog file does not exist. |
173
+ | `status` | Aggregate provider, spend-by-unit, plan state, and claim count, offline. Provider cost units are never summed across each other. Refuses if the catalog file does not exist. |
174
+ | `claims` | Validates the catalog and emits the exact union of `objectId`/`reviewObjectId`/`jobId` across every registered lock. Refuses to omit a project when any registered lock is missing or unreadable, or when the catalog has a duplicate id or lock path. |
175
+
176
+ `--workspace <path>` selects the catalog file; it defaults to
177
+ `pixelkiln.workspace.json` in the current directory. Stored paths are relative
178
+ to the catalog file's own directory, so a catalog survives a clone or move.
179
+ `list`/`status` support `--json` and `--check` (nonzero exit on any error-level
180
+ diagnostic); both treat a nonexistent catalog file as a hard error rather than
181
+ an empty, vacuously-safe one. This is the same hazard class as an incomplete
182
+ claim set. In `--json` output, the `workspace` key always names the catalog *file*;
183
+ `status` also reports `dir`, the catalog's own directory that
184
+ registered paths resolve against.
185
+
186
+ Passing `--workspace <path>` to `salvage` derives its claim set and its
187
+ sibling-manifest style signal from every project the catalog registers.
188
+ `--claims` still works and joins both the lockfile claim set and sibling
189
+ manifest list. A missing or unreadable registered lock is a hard error there
190
+ too. PixelKiln never skips one because the catalog exists to guarantee a
191
+ complete account-wide claim set. See
192
+ [Recovery and account safety](./RECOVERY.md#shared-workspace-catalog).
193
+
144
194
  ## Local quality and derived output
145
195
 
146
196
  ### `audit`
@@ -217,6 +267,9 @@ Print the package version. `-v` is an alias.
217
267
  | `--no-open` | pick/salvage | Do not automatically open the browser. |
218
268
  | `--tag` | fetch/adopt | Also push tags after the command's primary work. |
219
269
  | `--claims <paths>` | salvage | Other project lockfiles; repeatable and comma-separated. |
270
+ | `--workspace <path>` | workspace/salvage | Workspace catalog path; defaults to `pixelkiln.workspace.json`. On salvage, derives the claim set instead of repeated `--claims`. |
271
+ | `--provider <id>` | workspace add | Provider id to register the project under; defaults to the target manifest's provider. |
272
+ | `--account <label>` | workspace add | Free-form account label, e.g. distinguishing sandboxes. |
220
273
  | `--all` | salvage dry run | List every unclaimed object rather than the first 30. |
221
274
  | `--from <dir>` | init | Existing source tree to scan. |
222
275
  | `--exclude <names>` | init | Directory/name fragments to exclude; repeatable. |
package/docs/ENDPOINTS.md CHANGED
@@ -1,4 +1,4 @@
1
- # PixelLab API — measured reference
1
+ # Measured PixelLab API reference
2
2
 
3
3
  Every cost here was **measured against a live Tier 2 account**, not read from
4
4
  documentation. Where a figure came from docs rather than a meter, it says so.
@@ -10,7 +10,7 @@ Auth is one long-term key for everything: `Authorization: Bearer $PIXELLAB_API_K
10
10
 
11
11
  ---
12
12
 
13
- ## The API surface
13
+ ## Endpoint families
14
14
 
15
15
  | Family | Paths | What it covers |
16
16
  |---|---|---|
@@ -27,7 +27,7 @@ listed so it is obvious what exists.
27
27
 
28
28
  ---
29
29
 
30
- ## Single-image generators — measured
30
+ ## Single-image generators, measured
31
31
 
32
32
  The endpoints that produce one standalone image. This is the decision that
33
33
  matters most for icon and prop work.
@@ -50,12 +50,12 @@ regardless of size.
50
50
 
51
51
  **`pixflux` is the workhorse.** 1 generation, returns the PNG inline, and its
52
52
  `color_image` parameter is a genuine constraint. A two-colour palette produced
53
- 130 badges containing **only** `#000000` and `#ffffff` — verified 65/65 in each
53
+ 130 badges containing **only** `#000000` and `#ffffff`, verified 65/65 in each
54
54
  of two sets. Prose asking for the same thing gave a yellow star and a brown
55
55
  chocolate bar.
56
56
 
57
57
  **`bitforge` disappoints.** It is the only single-image endpoint with palette
58
- *and* style reference *and* synchronous delivery, all for 1 generation — which
58
+ *and* style reference *and* synchronous delivery, all for 1 generation, which
59
59
  should make it ideal. In practice it returned unrecognisable blobs for a simple
60
60
  "blacksmith anvil" prompt at `style_strength` 0, 10, 25 and 50. The first
61
61
  failure looked like the style reference overwhelming the prompt; sweeping the
@@ -63,7 +63,7 @@ strength proved otherwise. Possibly tuned for a different kind of subject (docs
63
63
  call it "Create S-M image", max area 200×200). **Do not reach for it on this
64
64
  evidence alone.**
65
65
 
66
- **`pixen` gave the best unconstrained detail** of anything at 1 generation — a
66
+ **`pixen` gave the best unconstrained detail** of anything at 1 generation, a
67
67
  properly rendered anvil with sparks where others produced flat shapes. It has no
68
68
  palette parameter, so it suits styles carried entirely by the prompt.
69
69
 
@@ -96,15 +96,15 @@ A palette swatch must also be **chunky**: a 4×1 image was rejected outright wit
96
96
 
97
97
  ---
98
98
 
99
- ## Post-processing utilities — measured
99
+ ## Post-processing utilities, measured
100
100
 
101
101
  Five endpoints take an image in and give one back. All are **synchronous**, all
102
- return `{usage, image}` inline, and all cost **1 generation** — including the
102
+ return `{usage, image}` inline, and all cost **1 generation**, including the
103
103
  ones that sound like pure image manipulation.
104
104
 
105
105
  | Endpoint | Cost | Palette survives? | What it actually does |
106
106
  |---|---|---|---|
107
- | `remove-background` | 1 | **yes** | Genuine cleanup — the only safe one |
107
+ | `remove-background` | 1 | **yes** | Genuine cleanup, the only safe one |
108
108
  | `rotate` | 1 | no | Re-renders from a new angle |
109
109
  | `resize` | 1 | no | **Re-generates**, does not resample |
110
110
  | `image-to-pixelart` | 1 | no | Destroys alpha too |
@@ -115,7 +115,7 @@ Measured on one 64×64 riso badge with an exact 4-colour palette
115
115
 
116
116
  | | colours out | transparency | result |
117
117
  |---|---|---|---|
118
- | source | 4 | 0.57 | — |
118
+ | source | 4 | 0.57 | n/a |
119
119
  | `remove-background` | **3** | 0.60 | dropped a stray fringe, kept the rest |
120
120
  | `rotate` | 30 | 0.58 | anti-aliased new angle |
121
121
  | `resize` → 32px | 38 | 0.57 | cream+rust came back **gold** |
@@ -123,7 +123,7 @@ Measured on one 64×64 riso badge with an exact 4-colour palette
123
123
 
124
124
  **`remove-background` is a de-fringe pass, not just a matte.** It removed the
125
125
  scattered sage-green speckles around the badge outline and left the three real
126
- inks untouched — colour count went *down*, transparency went *up*. It is the one
126
+ inks untouched. Colour count went *down*, transparency went *up*. It is the one
127
127
  utility safe to run on palette-locked art.
128
128
 
129
129
  **`resize` is generative, not a resampler.** The name is misleading: it takes a
@@ -131,7 +131,7 @@ utility safe to run on palette-locked art.
131
131
  badge came back as 38 colours of gold.
132
132
 
133
133
  **`color_image` does not rescue it.** `resize` accepts the parameter in its
134
- schema; passing the exact same swatch that `pixflux` honours changed nothing —
134
+ schema; passing the exact same swatch that `pixflux` honours changed nothing.
135
135
  56 colours, still gold. The forced palette works on **`pixflux` and `bitforge`
136
136
  only**, and being in another endpoint's schema is not evidence it is wired up.
137
137
 
@@ -146,7 +146,7 @@ prevent that.
146
146
 
147
147
  ---
148
148
 
149
- ## Tilesets — schema only, not yet measured
149
+ ## Tilesets: schema only, not yet measured
150
150
 
151
151
  Called out separately because these are the most capable endpoints for level art
152
152
  and they are relevant to the disc-golf game. **Costs below are unmeasured.**
@@ -155,17 +155,17 @@ and they are relevant to the disc-golf game. **Costs below are unmeasured.**
155
155
  versions; `/create-tileset*` are the older aliases with identical schemas.
156
156
 
157
157
  They take `lower_description` + `upper_description` (+ optional
158
- `transition_description`) — you describe two terrains and the transition between
158
+ `transition_description`). You describe two terrains and the transition between
159
159
  them, and get a tileset that blends them. Distinctively, they accept **both**
160
160
  `color_image` *and* per-layer reference images (`lower_reference_image`,
161
- `upper_reference_image`, `transition_reference_image`) — the only family that
162
- combines palette forcing with style anchoring.
161
+ `upper_reference_image`, `transition_reference_image`). They are the only
162
+ family that combines palette forcing with style anchoring.
163
163
 
164
164
  Useful knobs: `tile_size`, `tileset_adherence` / `tileset_adherence_freedom`
165
165
  (how strictly tiles must fit together), `raggedness` and `slope_size` for edge
166
166
  character, plus the usual `outline` / `shading` / `detail`.
167
167
 
168
- `create-tiles-pro` is a different shape — a single `description` plus
168
+ `create-tiles-pro` is a different shape, a single `description` plus
169
169
  `style_images`, `tile_view`, `building_*` fields for structures.
170
170
 
171
171
  Its `style_images` is a **fourth** convention, and not the one two lines up:
@@ -178,14 +178,14 @@ Its `style_images` is a **fourth** convention, and not the one two lines up:
178
178
 
179
179
  Sending `generate-with-style-v2`'s nested `{image: {...}}` here is rejected as
180
180
  an extra field. Passing style images at all makes the endpoint ignore
181
- `tile_type` and `tile_view` and copy the reference's tile geometry instead —
182
- which is the only way to land new art on an existing sheet's ground plane.
181
+ `tile_type` and `tile_view` and copy the reference's tile geometry instead.
182
+ That is the only way to land new art on an existing sheet's ground plane.
183
183
 
184
184
  `GET /tiles-pro/{id}` carries no `status` field. It answers **423 while the set
185
185
  is still drawing** and 200 with `storage_urls` when it is done, so the HTTP code
186
186
  is the status. Cost is reported at submit time and lands on the same 20/25/40
187
187
  canvas tiers as `1dir`, but the canvas is tile size x variation count, not one
188
- sprite — a small tile in a large set still reaches the top tier.
188
+ sprite. A small tile in a large set still reaches the top tier.
189
189
 
190
190
  All response shapes used by the client are validated at runtime. The TypeScript
191
191
  interfaces alone are not trusted at the HTTP boundary: missing ids, invalid
@@ -195,18 +195,19 @@ produce an `Invalid PixelLab response` error before pipeline state is updated.
195
195
  `outline_mode` defaults to `outline`, which draws a dark border around every
196
196
  tile. For ground tiles that is wrong: laid on a grid the borders read as
197
197
  quilting, with a seam at every cell edge. `segmentation` omits them and the
198
- same set tiles seamlessly — measured on a fairway-to-rough terrain set, where
198
+ same set tiles seamlessly, measured on a fairway-to-rough terrain set, where
199
199
  it was the difference between usable and unusable.
200
200
 
201
- `tile_feature` and `style_images` are **mutually exclusive** — "Connectable
202
- features (roads/tileset/building) cannot be combined with style tiles". So the
201
+ `tile_feature` and `style_images` are **mutually exclusive**. The API says
202
+ "Connectable features (roads/tileset/building) cannot be combined with style
203
+ tiles". So the
203
204
  geometry-anchoring trick above is unavailable for a connectable set, and its
204
205
  tiles land on whatever ground plane the view angle implies (measured: 32x24
205
206
  with the diamond midline at y=7, against a 32x32 sheet wanting y=15).
206
207
 
207
208
  `tile_feature` turns it from independent variations into a connectable set:
208
209
  `roads` (18-configuration path set), `tileset` (16-tile Wang corner set for a
209
- terrain transition — describe it as the transition, not one terrain), and
210
+ terrain transition; describe it as the transition, not one terrain), and
210
211
  `building` (floor/wall/doorway kit). These are sliced by index, so the returned
211
212
  order is load-bearing. They are structural multi-output results, not candidates
212
213
  to choose between: PixelKiln persists every URL in numeric order and labels the
@@ -230,12 +231,12 @@ committing to a set**.
230
231
  ## Recipes
231
232
 
232
233
  **Lock a palette.** Use `pixflux` with a `color_image` swatch. Build the swatch
233
- with `paletteSwatch()` — 64×64 blocks, one band per colour. It is a real
234
+ with `paletteSwatch()`: 64×64 blocks, one band per colour. It is a real
234
235
  constraint, not a hint: 130 badges across two sets came back containing *only*
235
236
  the requested colours.
236
237
 
237
238
  **Re-roll one bad asset.** 1 generation. `gen --only <id> --force`. Cheaper than
238
- asking for more candidates — a `1dir` call that yields 16 candidates costs 20–40.
239
+ asking for more candidates. A `1dir` call that yields 16 candidates costs 20–40.
239
240
 
240
241
  **Clean up fringing.** `remove-background` at 1 generation, and it will not
241
242
  disturb the palette.
@@ -245,7 +246,7 @@ size. Do not use `resize`.
245
246
 
246
247
  **Anchor to an existing look rather than a palette.** `generate-with-style-v2`
247
248
  (20) or `generate-image-v2` (40). `bitforge` claims to do this for 1, but see
248
- above. `map` has no style anchoring at all — a 1-bit set generated through it
249
+ above. `map` has no style anchoring at all. A 1-bit set generated through it
249
250
  came back with a yellow star and a brown chocolate bar.
250
251
 
251
252
  **Write prompts for a monochrome style.** Strip colour words from the prompt
@@ -263,7 +264,7 @@ whole set. Put the medium in the *suffix*, after the subject.
263
264
  ## Candidates
264
265
 
265
266
  Only `create-1-direction-object` returns multiple candidates, and the count is
266
- derived from size — it cannot be requested:
267
+ derived from size, and cannot be requested:
267
268
 
268
269
  | size | candidates |
269
270
  |---|---|
@@ -285,8 +286,8 @@ once a 1-generation re-roll exists: forty re-rolls cost one `1dir` call.
285
286
  **image survives**: a March 2026 sprite still resolved from `/v2/objects` four
286
287
  months on while `/v2/map-objects/{id}` returned 404. pixelkiln's `poll` checks
287
288
  the objects collection on a 404 rather than writing the work off.
288
- - `pixflux`/`pixen`/`bitforge` results are **not account objects** at all —
289
- bytes come back inline and are never listed. `adopt` and `salvage` cannot see
289
+ - `pixflux`/`pixen`/`bitforge` results are **not account objects** at all.
290
+ Bytes come back inline and are never listed. `adopt` and `salvage` cannot see
290
291
  them, and they cannot be tagged.
291
292
 
292
293
  ---
@@ -309,15 +310,15 @@ once a 1-generation re-roll exists: forty re-rolls cost one `1dir` call.
309
310
 
310
311
  Listed so the gaps are known rather than assumed away:
311
312
 
312
- - `inpaint`, `inpaint-v3`, `edit-image`, `edit-images-v2` — targeted edits.
313
+ - `inpaint`, `inpaint-v3`, `edit-image`, `edit-images-v2`, for targeted edits.
313
314
  Both `inpaint` and `edit-image` accept `color_image`, but given that `resize`
314
315
  accepts and ignores it, assume nothing until measured.
315
- - `image-to-pixelart-pro` — takes only `image` + `description`, no size fields.
316
+ - `image-to-pixelart-pro` takes only `image` + `description`, no size fields.
316
317
  The non-Pro version is characterised above.
317
- - the tileset family — schema documented above, costs unmeasured
318
- - `create-isometric-tile`, `create-ui-asset`, `generate-font-pro` — job-based,
319
- response shapes not in the simple `{usage, image}` form
320
- - the character family (23 paths) — out of pixelkiln's scope by design
318
+ - the tileset family, with schema documented above and costs unmeasured
319
+ - `create-isometric-tile`, `create-ui-asset`, `generate-font-pro`, all job-based,
320
+ with response shapes not in the simple `{usage, image}` form
321
+ - the character family (23 paths), out of pixelkiln's scope by design
321
322
 
322
323
  ---
323
324
 
@@ -328,7 +329,7 @@ curl -s -H "Authorization: Bearer $PIXELLAB_API_KEY" \
328
329
  https://api.pixellab.ai/v2/balance
329
330
  ```
330
331
 
331
- The count lives at **`subscription.generations`**, not at the top level — a
332
+ The count lives at **`subscription.generations`**, not at the top level. A
332
333
  probe reading `.generations` gets `undefined` and silently reports every cost as
333
334
  `NaN` rather than failing:
334
335
 
@@ -340,5 +341,5 @@ probe reading `.generations` gets `undefined` and silently reports every cost as
340
341
  ```
341
342
 
342
343
  Take a balance reading, make one call, wait a few seconds, read again. Prefer
343
- the response's `usage` field where present — it is inline, exact, and immune to
344
+ the response's `usage` field where present. It is inline, exact, and immune to
344
345
  the billing lag.
@@ -32,6 +32,11 @@ It does not accept style images or a forced palette. On a measured 1-bit restyle
32
32
  switching from reference-anchored generation to `map` changed median palette
33
33
  distance from 6.6 to 41.9; cheap output is not cheap when unusable.
34
34
 
35
+ The API describes map objects as transparent, but both 256px isolated-object
36
+ attempts in the [environment provider benchmark](./PROVIDER_BENCHMARK.md) were
37
+ opaque. `map` has no `noBackground` control in PixelKiln. Check alpha before
38
+ assuming the file can be placed directly over a map.
39
+
35
40
  ## `1dir`
36
41
 
37
42
  `1dir` is the single-facing sibling of PixelLab's rotatable/animated object
@@ -114,7 +119,7 @@ instead creates a structural set in provider order:
114
119
  | `tileset` | 16-tile Wang-corner terrain transition. |
115
120
  | `building` | Floor/wall/doorway/pillar/stair construction kit. |
116
121
 
117
- Describe a `tileset` asset as the transition—“fairway grass to rough meadow”—
122
+ Describe a `tileset` asset as the transition, "fairway grass to rough meadow",
118
123
  rather than one terrain. Every returned member is required, so PixelKiln
119
124
  records numerical roles such as `tile-00` rather than treating them as choices.
120
125
 
@@ -1,6 +1,6 @@
1
1
  # Getting started
2
2
 
3
- Pixelkiln turns a committed asset manifest into generated files with a
3
+ PixelKiln turns a committed asset manifest into generated files with a
4
4
  committed provenance lockfile. Planning, auditing, packing, mounting, and
5
5
  exporting are local operations. Only generation, provider polling, candidate
6
6
  selection, downloads, tagging, account adoption, salvage, purge, and balance
@@ -9,7 +9,8 @@ checks need provider access.
9
9
  ## Requirements
10
10
 
11
11
  - Node.js 20 or newer
12
- - A PixelLab API key for provider-backed commands
12
+ - A credential for the manifest's selected provider: `PIXELLAB_API_KEY` for
13
+ PixelLab or `RD_API_KEY` for experimental Retro Diffusion support
13
14
  - A repository checkout until the first npm release in
14
15
  [issue #1](https://github.com/gfargo/pixelkiln/issues/1) is complete
15
16
 
@@ -53,6 +54,24 @@ in `.env.local` beside the manifest:
53
54
  PIXELLAB_API_KEY=...
54
55
  ```
55
56
 
57
+ For experimental Retro Diffusion generation, set the manifest's
58
+ top-level `provider` to `retrodiffusion` and use:
59
+
60
+ ```dotenv
61
+ RD_API_KEY=...
62
+ ```
63
+
64
+ Its still, tileset-sheet, animated-GIF, and PNG-spritesheet workflows are
65
+ implemented. Authenticated single-candidate RD Fast and RD Plus stills have
66
+ passed from quote through validated download, provenance, and cache.
67
+ Multi-candidate, tileset, GIF, and spritesheet live runs remain, so PixelLab
68
+ remains the production adapter. See
69
+ [Manifest reference](MANIFEST.md#experimental-retro-diffusion) for
70
+ provider options and current limits, or
71
+ [PixelLab vs. Retro Diffusion](../PROVIDERS.md) for selection guidance.
72
+ The provider setup guides give the shortest complete path for
73
+ [PixelLab](PIXELLAB.md) and [Retro Diffusion](RETRO_DIFFUSION.md).
74
+
56
75
  Before spending anything, validate and price the selected work:
57
76
 
58
77
  ```bash
@@ -134,8 +153,8 @@ pipeline stages also exit nonzero after partial failures or timeouts.
134
153
  - `restore` repairs missing generated outputs without buying new generations.
135
154
  - `.pixelkiln/cache/` stores downloaded PNG bytes by SHA-256, so restoration can
136
155
  still work after a temporary provider URL expires.
137
- - `cache --check` verifies hashes and fully decodes cached PNG structure before
138
- trusting recovery bytes, then validates the account object-hash cache.
156
+ - `cache --check` verifies hashes and structurally validates cached PNG/GIF
157
+ media before trusting recovery bytes, then validates the account object-hash cache.
139
158
  `cache --prune` removes corrupt, partial, and unreferenced project content
140
159
  plus invalid hash entries. It does not mistake
141
160
  objects belonging to another project for disposable account data.
@@ -143,7 +162,7 @@ pipeline stages also exit nonzero after partial failures or timeouts.
143
162
  - `salvage --claims <every-other-lockfile>` reviews remote objects no project
144
163
  currently claims. `salvage` never deletes; `purge` is a separate confirmed
145
164
  operation.
146
- - Pixelkiln refuses to overwrite a file whose bytes differ from its recorded
165
+ - PixelKiln refuses to overwrite a file whose bytes differ from its recorded
147
166
  hash. Resolve intentional hand edits explicitly.
148
167
 
149
168
  ## What belongs in Git
package/docs/LIBRARY.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Library API
2
2
 
3
- Pixelkiln's public package entry point exposes the same provider-independent
3
+ PixelKiln's public package entry point exposes the same provider-independent
4
4
  primitives used by the CLI. Use these when a build tool, editor integration, or
5
5
  game pipeline needs structured results instead of terminal output.
6
6
 
@@ -130,9 +130,9 @@ await fetchAssets(provider, specs, lock, lockPath)
130
130
  ```
131
131
 
132
132
  Provider-backed operations mutate the supplied lock object; persist at the
133
- workflow boundary with `saveLock`. See [PROVIDERS.md](../PROVIDERS.md) before
134
- implementing another backend, especially its optional capabilities and cost
135
- units.
133
+ workflow boundary with `saveLock`. See
134
+ [PixelLab vs. Retro Diffusion](../PROVIDERS.md) before selecting or implementing
135
+ another backend, especially its optional capabilities and cost units.
136
136
 
137
137
  `submit` validates adapter estimates again at the spending boundary and returns
138
138
  `{ spent, unit }` for successful submissions. Lock entries retain fractional