pixelkiln 0.20.2 → 0.22.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/CLI.md CHANGED
@@ -100,7 +100,10 @@ finish it before polling.
100
100
  Open the local candidate-review UI for jobs with alternatives. The page keeps
101
101
  native aspect ratios, uses exact integer zoom for small art, fits large work,
102
102
  and centers the decision surface on wide displays. A revision row shows its
103
- parent source beside the new candidates. A ComfyUI frame set appears as an
103
+ parent source beside the new candidates, and a regeneration (`gen --force`)
104
+ shows the art it would replace beside them while that file is still on disk,
105
+ so the question is "is this better?" rather than "is this good?". A ComfyUI
106
+ frame set appears as an
104
107
  animated ordered strip and is accepted or left unresolved as a unit. Its preview
105
108
  can be paused, starts paused when reduced motion is enabled, and stops while it
106
109
  is offscreen. Arrow keys navigate, Enter selects, 1–9 choose directly, and 0
@@ -207,6 +210,126 @@ when an installed provider, such as local ComfyUI, has no balance endpoint.
207
210
  Summarize lock entries by state and successful submission spend by cost unit.
208
211
  Supports `--json`; unlike units are never added together.
209
212
 
213
+ ### `gallery`
214
+
215
+ Open a local, read-only gallery of everything the project has generated. Each
216
+ lock entry is shown at integer zoom on a transparency checkerboard, grouped by
217
+ style, with its provenance one click away: the prompt actually sent, provider
218
+ and generator, dimensions, recorded cost, lock status and plan state, submit
219
+ and download times, job and object ids, every output with its path, SHA-256,
220
+ size, and on-disk status, revision lineage, the quality record (palette,
221
+ native-grid detection, audit, named approval), the manifest asset as declared,
222
+ and raw provider metadata.
223
+
224
+ ```bash
225
+ pixelkiln gallery
226
+ pixelkiln gallery --style environment --port 4180 --no-open
227
+ pixelkiln gallery --json > generations.json
228
+ ```
229
+
230
+ The gallery is lock-first. A lock entry the manifest no longer declares still
231
+ appears, marked `undeclared`, so paid work is never hidden; a declared asset
232
+ with no entry appears as a placeholder so the page also shows what has not
233
+ been made. Search matches asset ids, prompts, job and object ids, hashes, and
234
+ paths; chips filter by plan state, provider, and generator. Filters and sort
235
+ live in the URL query (`?state=failed,orphaned&group=none`) and the open record
236
+ in the hash (`#style/asset`), so a link lands on the same view. A render shows
237
+ up to 600 cards before offering the rest, which keeps very large projects
238
+ responsive. **Refresh** re-reads the manifest, lockfile, and disk, so the page
239
+ can stay open while `gen` runs in another terminal. The server binds to
240
+ localhost, serves only the files the current snapshot names, never contacts a
241
+ provider, and never writes anything. Stop it with Ctrl+C. See the
242
+ [Getting started guide](GETTING_STARTED.md#start-a-new-project) for a
243
+ screenshot.
244
+
245
+ `--json` prints the same snapshot to stdout without starting a server. It is
246
+ the offline, machine-readable answer to "what has this project generated?" for
247
+ scripts and agents; `--style` and `--only` narrow it the same way.
248
+
249
+ `--edit` lets the page change *intent*: an asset's prompt (for every style or
250
+ only the one being viewed), width, height, size, category, and tags; a style's
251
+ prompt prefix, prompt suffix, and forced palette; and a form under each style
252
+ to add a new asset. A style edit shows its blast radius before you save —
253
+ how many assets it changes the request for, including assets in styles that
254
+ `extends` this one and do not override the field themselves, and what
255
+ regenerating all of them would cost. Editing a child style sets a value on the
256
+ child only; clearing a field there makes it inherit again. Saving rewrites the manifest and
257
+ nothing else — the same edit you would make in an editor — so `plan` and the
258
+ page immediately report the asset `stale` or `missing` with its estimate, and
259
+ generation still goes through `pixelkiln gen` with its budget and confirmation.
260
+ The write is refused when the manifest changed on disk since the page loaded,
261
+ and a result the manifest loader would reject never lands. Edits are accepted
262
+ only from the page itself: the request must come from the gallery's own origin
263
+ and carry a session token minted when the server started. Without `--edit`
264
+ the gallery has no write route at all.
265
+
266
+ ```bash
267
+ pixelkiln gallery --edit
268
+ pixelkiln gallery --edit --workspace pixelkiln.workspace.json
269
+ ```
270
+
271
+ `--budget <n|provider=n>` enables generation from the page under that session
272
+ ceiling. It is the same `--budget` `gen` takes: one unkeyed amount when a run
273
+ involves a single provider, or one keyed amount per provider for a mixed run,
274
+ and nothing is queued without it. Each asset record and each style header
275
+ gains **Generate** (for `missing`, `stale`, and `failed` work), **Regenerate**
276
+ (for up-to-date work, as `gen --force`), and **Resume** (poll, review, and
277
+ fetch existing provider work at no cost). Before anything is submitted a
278
+ dialog lists every asset with its candidate count and estimate, the total per
279
+ provider, and what the session budget still allows — the page's version of
280
+ `gen`'s "Spend … on N asset(s)?" question. A run is then the same `submit`,
281
+ `poll`, and `fetch` library calls `gen` makes, writing the same lockfile, so a
282
+ terminal `plan` in another window agrees at every step. Progress appears in a
283
+ job strip under the filters; each job keeps the log lines the CLI would have
284
+ printed. Candidate sets stop in `review`: **Review** slides the `pick` sheet
285
+ out over the gallery, **Apply selections** writes the lockfile and downloads
286
+ the chosen art, and unchosen rows stay in review exactly as with `pick`. A
287
+ regeneration's sheet shows the current art beside the candidates.
288
+
289
+ **Compare** puts two to four records side by side at one shared zoom with
290
+ their fields in rows — provider, generator, candidates, size, cost, prompt,
291
+ dates, quality, hashes — and tints every row whose values differ. Shift-click
292
+ cards (or use **Compare +** in a record) to build the set; the tray at the
293
+ bottom opens it. The set lives in the URL (`?compare=a,b`), so a comparison
294
+ can be linked like any other view. It works in the read-only gallery too.
295
+
296
+ Two ceilings guard spend. The session budget is charged with each job's
297
+ estimate up front, so two quick clicks cannot both fit under the same
298
+ remainder, and each submission also carries the remaining ceiling as its own
299
+ `budget`, so a provider estimate that grows between plan and submit is refused
300
+ rather than paid. The balance preflight is the same as `gen`'s. Provider
301
+ credentials are loaded from the project's own `.env` files and never reach the
302
+ page; in a workspace whose projects name the same credential with different
303
+ values, the gallery refuses to generate for the second project rather than run
304
+ it on the first project's account — start a separate gallery for it.
305
+
306
+ "How many candidates" is a style setting, because it is part of the request
307
+ identity: Retro Diffusion, ComfyUI, and Scenario expose it as a provider option
308
+ (`numImages`/`numOutputs`), which each style header shows and, with `--edit`,
309
+ lets you change — every asset in the style becomes `stale`, and the header
310
+ says how many. PixelLab's count follows the generator and size (`map` and
311
+ `pixflux` return one image; a `1dir` style returns 4–64), so the header
312
+ explains that instead of offering a number.
313
+
314
+ ```bash
315
+ pixelkiln gallery --edit --budget 80
316
+ pixelkiln gallery --budget pixellab=40 --budget retrodiffusion=1.25 --workspace pixelkiln.workspace.json
317
+ ```
318
+
319
+ `--workspace <catalog>` shows every project the catalog registers in one
320
+ gallery, the way `workspace status` reads them: no manifest is needed in the
321
+ current directory, each project gets its own section and filter chip, and a
322
+ project whose manifest or lock cannot be read is listed with its error instead
323
+ of hiding the rest. Lock keys repeat across projects, so records are identified
324
+ as `project:style/asset` in links and search. `--style` and `--only` apply per
325
+ project; a project without the named ids simply shows nothing. `--json` prints
326
+ the combined snapshot with a `workspace.projects` summary.
327
+
328
+ ```bash
329
+ pixelkiln gallery --workspace pixelkiln.workspace.json
330
+ pixelkiln gallery --workspace pixelkiln.workspace.json --style base --json
331
+ ```
332
+
210
333
  ### `workspace`
211
334
 
212
335
  Register sibling projects in a schema-versioned catalog file, outside any one
@@ -452,16 +575,17 @@ Print the package version. `-v` is an alias.
452
575
  | `--lock <path>` | manifest commands | Lock path; defaults beside the manifest. |
453
576
  | `--style a,b` | most workflows | Restrict styles; repeatable. |
454
577
  | `--only id1,id2` | most workflows | Restrict asset ids; repeatable. |
455
- | `--budget <n\|provider=n>` | submit/gen | Refuse work above this cost. Repeat `provider=n` for every provider in a mixed run; do not mix keyed and unkeyed forms. |
578
+ | `--budget <n\|provider=n>` | submit/gen/gallery | Refuse work above this cost. Repeat `provider=n` for every provider in a mixed run; do not mix keyed and unkeyed forms. For `gallery`, the session ceiling that enables generation from the page. |
456
579
  | `--force` | gen/fetch/derived commands/recipe install/quality snapshot | Regenerate current work, replace a changed or untracked fetch destination, rebuild current quality-profile output, take ownership of modified/unowned derived output, replace changed recipe files, or replace a changed quality baseline. A refinement rebuild resets approval. |
457
580
  | `--dry-run` | supported mutating commands | Inspect without spending or mutating provider state. |
458
- | `--json` | plan/doctor/audit/cache/status/salvage/refine/recipe/quality | Machine-readable stdout where supported. |
581
+ | `--json` | plan/doctor/audit/cache/status/gallery/salvage/refine/recipe/quality | Machine-readable stdout where supported. For `gallery`, prints the snapshot instead of serving it. |
459
582
  | `--check` | plan/audit/cache | Exit nonzero when selected state is unsafe. |
460
583
  | `--yes`, `-y` | confirmed operations | Skip an interactive confirmation. For `refine approve`, it records an already-completed human review; it does not replace one. |
461
- | `--no-open` | pick/salvage | Do not automatically open the browser. |
584
+ | `--no-open` | pick/salvage/gallery | Do not automatically open the browser. |
585
+ | `--edit` | gallery | Let the page change asset prompts, sizes, category, and tags, and add assets. Rewrites the manifest only; never contacts a provider or spends. |
462
586
  | `--tag` | fetch/adopt | Also push tags after the command's primary work. |
463
587
  | `--claims <paths>` | salvage | Other project lockfiles; repeatable and comma-separated. |
464
- | `--workspace <path>` | workspace/salvage | Workspace catalog path; defaults to `pixelkiln.workspace.json`. On salvage, derives the claim set instead of repeated `--claims`. |
588
+ | `--workspace <path>` | workspace/salvage/gallery | Workspace catalog path; defaults to `pixelkiln.workspace.json` for `workspace`. On salvage, derives the claim set instead of repeated `--claims`; on gallery, shows every registered project. |
465
589
  | `--provider <id>` | balance/adopt/salvage/purge/workspace add | Select the account provider for a mixed manifest, or set the workspace catalog's default provider hint. |
466
590
  | `--account <label>` | workspace add | Free-form account label, e.g. distinguishing sandboxes. |
467
591
  | `--all` | salvage dry run | List every unclaimed object rather than the first 30. |
@@ -470,7 +594,7 @@ Print the package version. `-v` is an alias.
470
594
  | `--generator <name>` | init | Generator assigned to the scaffolded style. |
471
595
  | `--name <name>` | init | Project name for the scaffolded manifest. |
472
596
  | `--write-prompts` | adopt | Recover provider prompts into the manifest. |
473
- | `--port <n>` | pick/salvage | Local review server port; otherwise chooses a free port. |
597
+ | `--port <n>` | pick/salvage/gallery | Local review or gallery server port; otherwise chooses a free port. |
474
598
  | `--out <path>` | pack/export/refine/recipe install/quality snapshot | Output base override, final native PNG for path-mode refine, exact recipe destination, or quality baseline path. Export requires one selected tileset. |
475
599
  | `--inputs <path>` | pack/quality snapshot | JSON input array; requires `--out`. Quality cases use `{ id, path, record?, tolerances? }`. |
476
600
  | `--columns <n>` | pack/export | Grid columns, 1–1024; default is near-square. |
@@ -156,6 +156,15 @@ If a run stops between stages, rerun `plan`. It points `processing` work to
156
156
  `poll`, `review` work to `pick`, and `selected` or `download-failed` work to
157
157
  `fetch`; these resume existing paid work without another submission.
158
158
 
159
+ To browse what the project has made so far, run
160
+ [`pixelkiln gallery`](CLI.md#gallery). It serves a read-only page of every
161
+ generation with its full record — prompt, provider, cost, hashes, lineage, and
162
+ quality state — and can stay open while `gen` runs. With several registered
163
+ projects, `pixelkiln gallery --workspace pixelkiln.workspace.json` shows them
164
+ all in one page.
165
+
166
+ ![PixelKiln local generation gallery](../website/public/gallery-ui-showcase.jpg)
167
+
159
168
  ## Start from existing art
160
169
 
161
170
  Scaffold the manifest from PNGs, then reconcile exact file hashes with the
package/docs/LIBRARY.md CHANGED
@@ -77,6 +77,64 @@ await requireRevisionReady(spec, lock)
77
77
  accepted modes with optional `supportsRevision(mode)`. Omission means no
78
78
  revision support and makes resolution fail offline.
79
79
 
80
+ ## Inspect every generation
81
+
82
+ `buildGallerySnapshot` is the offline, serializable view behind
83
+ `pixelkiln gallery`: every lock entry with its plan state, outputs, quality
84
+ record, lineage, and manifest intent, plus lock entries the manifest no longer
85
+ declares. It is built from the same sources as `buildPlan` and contacts no
86
+ provider.
87
+
88
+ ```ts
89
+ import {
90
+ buildGallerySnapshot,
91
+ loadLock,
92
+ loadManifest,
93
+ renderGallery,
94
+ resolveSpecs,
95
+ serveGallery,
96
+ } from "pixelkiln"
97
+
98
+ const loaded = await loadManifest("pixelkiln.manifest.json")
99
+ const specs = await resolveSpecs(loaded)
100
+ const lock = await loadLock("pixelkiln.lock.json")
101
+ const { snapshot, media } = await buildGallerySnapshot({
102
+ loaded, specs, lock, lockPath: "pixelkiln.lock.json",
103
+ })
104
+
105
+ for (const item of snapshot.items) {
106
+ console.log(item.key, item.state, item.cost, item.costUnit, item.outputs.map((o) => o.sha256))
107
+ }
108
+ ```
109
+
110
+ `buildWorkspaceGallerySnapshot({ workspace, workspacePath })` does the same
111
+ for every project a workspace catalog registers, namespacing item ids as
112
+ `project:style/asset` and listing an unreadable project's error under
113
+ `snapshot.workspace.projects` instead of throwing.
114
+
115
+ `renderGallery(snapshot)` returns the self-contained HTML page, and
116
+ `serveGallery({ load })` runs the localhost server; `load` is called again for
117
+ every page load and `/api/gallery.json` request, and `media` is the exact
118
+ allowlist of files the server will read. Output URLs inside the snapshot are
119
+ only meaningful while that server runs.
120
+
121
+ Passing `edit: createGalleryEditHandler({ manifestFor, reload })` adds the one
122
+ write route behind `pixelkiln gallery --edit`. `applyManifestEdit(path, edit)`
123
+ is the underlying primitive: it patches the raw manifest JSON, preserves the
124
+ file's indentation, refuses to write when the file's hash no longer matches
125
+ `expectedSha256` (`ManifestDriftError`), and validates the result through
126
+ `loadManifest` and `resolveSpecs` before the rename (`ManifestEditError`).
127
+ It never touches the lockfile or a provider.
128
+
129
+ `createGenerateHandlers({ loadProject, providerFor, budget, reload })` is the
130
+ generation side of `pixelkiln gallery --budget`: `start` validates a request
131
+ against `buildPlan` and the session budget and runs `submit`, `poll`, and
132
+ `fetchAssets` as a background job; `status` reports jobs and spend; `review`
133
+ and `applyReview` host the `pick` sheet for a job's waiting keys. The sheet
134
+ itself comes from `prepareReview`, which `runPicker` also uses: it gathers the
135
+ candidate groups, the local files the sheet may load, and the apply step,
136
+ without an HTTP server of its own.
137
+
80
138
  ## Audit and gate generated art
81
139
 
82
140
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixelkiln",
3
- "version": "0.20.2",
3
+ "version": "0.22.0",
4
4
  "description": "Manifest-driven pixel-art generation, review, recovery, and packaging with deterministic provenance.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -27,6 +27,11 @@ hashes.
27
27
  pass one `--budget provider=amount` ceiling for every paid provider in the plan.
28
28
  - Leave visual selection to the local `pixelkiln pick` review page unless the
29
29
  user explicitly provides a selection rule. Closing it applies nothing.
30
+ - To answer "what has this project generated?", use `pixelkiln gallery --json`
31
+ for the offline provenance snapshot, or open `pixelkiln gallery` for the
32
+ person to browse it. Both are read-only and contact no provider. Leave
33
+ `gallery --edit` and `gallery --budget` to the person: an agent changes the
34
+ manifest directly and spends only through `gen` with an explicit `--budget`.
30
35
  - When a selected style declares `quality`, run manifest-mode `pixelkiln refine`
31
36
  after its source is accepted and downloaded. Read the quality reference below.
32
37
  Do not copy manifest-owned palette, path, interpreter, or threshold settings