pixelkiln 0.1.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/TILES.md ADDED
@@ -0,0 +1,118 @@
1
+ # Tiles and engine exports
2
+
3
+ PixelLab connectable output is not merely a directory of images. The response
4
+ contains ordered `storage_urls` plus `tile_rules` describing which adjacency
5
+ mask belongs to which image. PixelKiln preserves both pieces so downstream
6
+ tools never have to reconstruct semantics from filenames.
7
+
8
+ ## Stored state
9
+
10
+ A completed lock entry has role-qualified outputs in provider order and raw
11
+ metadata under the provider id:
12
+
13
+ ```jsonc
14
+ {
15
+ "outputs": [
16
+ { "path": "terrain-tile-00.png", "sha256": "…", "role": "tile-00" },
17
+ { "path": "terrain-tile-01.png", "sha256": "…", "role": "tile-01" }
18
+ ],
19
+ "providerMetadata": {
20
+ "pixellab": {
21
+ "tileKind": "tileset",
22
+ "tileRules": {
23
+ "rule_type": "corner",
24
+ "arity": 4,
25
+ "connectivity": "other",
26
+ "terrains": ["feature", "background"],
27
+ "tiles": { "tile_0": 0, "tile_1": 1 }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ Provider keys can contain gaps when a set includes stamp-only images. Output
35
+ roles therefore retain the original numeric key (`tile-07`) rather than being
36
+ renumbered by array position.
37
+
38
+ ## Command
39
+
40
+ ```bash
41
+ pixelkiln export --style ground --only terrain --format generic
42
+ pixelkiln export --style ground --only terrain --format tiled
43
+ pixelkiln export --style ground --only terrain --format godot
44
+ ```
45
+
46
+ `--format` defaults to `generic`. `--out dist/terrain` overrides the output
47
+ base when exactly one entry is selected. `--columns` controls atlas columns.
48
+ Without `--out`, files land in the style's `outDir` as
49
+ `<asset>-tileset.<extension>`, `<asset>-tileset.png`, and
50
+ `<asset>-tileset.pixelkiln.json`.
51
+
52
+ The companion record is engine-neutral: it stores portable source paths and
53
+ SHA-256s, export options (including raw provider rules), output hashes, and a
54
+ canonical fingerprint. `verifyArtifactBundle()` can detect changed inputs,
55
+ edited/missing outputs, or altered provenance offline without rebuilding the
56
+ atlas. The project manifest and lockfile are conservative inputs, ensuring that
57
+ newly declared or recorded tiles also make an older export stale. The TSJ/TRES
58
+ contracts therefore remain free of PixelKiln-only fields.
59
+
60
+ An existing export without a companion is adopted only when its bytes already
61
+ match. Once tracked, a changing output must still match its recorded hash;
62
+ manual edits stop the whole export rather than being silently replaced. Use
63
+ `--force` only after reviewing the difference to take ownership and re-baseline
64
+ the complete bundle.
65
+
66
+ An immutable transaction journal exists only while the three files are being
67
+ replaced. Following abrupt termination, the next export restores the old set if
68
+ commit was incomplete, or retains the fully committed new set and removes its
69
+ backups. Recovery will not follow journal paths outside the current bundle or
70
+ interrupt a live writer.
71
+
72
+ ## Generic JSON
73
+
74
+ The generic format is the lossless interchange contract:
75
+
76
+ - `format: "pixelkiln-tileset"` and `version: 1`
77
+ - atlas image, cell size, sheet size, and columns
78
+ - one ordered tile record with atlas id, original provider `sourceIndex`, role,
79
+ rectangle, optional bitmask, and `stampOnly`
80
+ - normalized rule type, arity, connectivity, terrain names, and masks
81
+ - the complete raw provider rule object in `providerRules`, including rule
82
+ families a current exporter does not yet normalize
83
+
84
+ Use it for custom engines, unsupported rule families, or as the input to a
85
+ project-specific importer.
86
+
87
+ ## Tiled
88
+
89
+ The `.tsj` export creates an image tileset and a Wang set. Tiled Wang ids are
90
+ written in its documented order: top edge, northeast corner, right edge,
91
+ southeast corner, bottom edge, southwest corner, left edge, northwest corner.
92
+
93
+ For PixelLab corner masks, bits NW/NE/SW/SE = 3/2/1/0 are placed into the four
94
+ corner positions. For edge masks, bits N/E/S/W = 0/1/2/3 are placed into the
95
+ four edge positions. Terrain names come from the provider metadata; editor
96
+ colors are deterministic display colors and do not alter the artwork.
97
+
98
+ ## Godot 4
99
+
100
+ The `.tres` export creates a `TileSet` containing one `TileSetAtlasSource`.
101
+ Four-corner masks use `TERRAIN_MODE_MATCH_CORNERS`; four-edge masks use
102
+ `TERRAIN_MODE_MATCH_SIDES`. Each mask becomes the corresponding terrain peering
103
+ bits on its atlas tile. Isometric and hex tile shapes are carried from the
104
+ resolved manifest spec.
105
+
106
+ The texture path is relative to the `.tres`, so the generated PNG and resource
107
+ can move together inside a Godot project.
108
+
109
+ ## Deliberate limits
110
+
111
+ - Tiled and Godot exports require every image to match the atlas cell size.
112
+ - Six-edge hex masks remain generic-only. Their engine layouts depend on hex
113
+ orientation and offset conventions that the current manifest does not yet
114
+ declare.
115
+ - `outline` and building-kit images absent from the rule map are stamp-only.
116
+ Generic export retains them; engine exporters reject a rule family whose
117
+ placement semantics would have to be invented.
118
+ - Export never changes source PNGs or the lockfile.
@@ -0,0 +1,26 @@
1
+ # Minimal example
2
+
3
+ ```bash
4
+ export PIXELLAB_API_KEY=...
5
+
6
+ # Free — shows exactly what a run would cost.
7
+ pixelkiln plan --manifest pixelkiln.manifest.json
8
+
9
+ # 3 assets x 40 generations = 120, returning 16 candidates each.
10
+ pixelkiln gen --manifest pixelkiln.manifest.json --budget 120
11
+ ```
12
+
13
+ `gen` opens a contact sheet in your browser to pick among the candidates, then
14
+ writes `out/base/tools/anvil.png` and friends, recording provenance in
15
+ `pixelkiln.lock.json`.
16
+
17
+ ## Adding a variant style
18
+
19
+ Add a second entry under `styles` with a different `outDir`, then:
20
+
21
+ ```bash
22
+ pixelkiln gen --style neon
23
+ ```
24
+
25
+ Every asset re-derives under the new style. The original files are untouched —
26
+ styles are separate namespaces in both the output tree and the lockfile.
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "../../schema/manifest.schema.json",
3
+ "name": "minimal-example",
4
+ "styles": {
5
+ "base": {
6
+ "generator": "1dir",
7
+ "size": 64,
8
+ "view": "top-down",
9
+ "promptPrefix": "Game achievement icon: one centered",
10
+ "promptSuffix": "bold dark outline, crisp chunky pixel clusters, readable silhouette at 32px, isolated single subject, no ground plane, transparent background, no letters, no numbers",
11
+ "styleImages": [],
12
+ "outDir": "out/base",
13
+ "tags": ["minimal-example"]
14
+ }
15
+ },
16
+ "assets": {
17
+ "anvil": { "prompt": "a blacksmith anvil with a single bright spark", "category": "tools" },
18
+ "potion": { "prompt": "a round glass potion bottle with a glowing liquid", "category": "items" },
19
+ "compass": { "prompt": "a brass compass with a red needle", "category": "items" }
20
+ }
21
+ }
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "pixelkiln",
3
+ "version": "0.1.0",
4
+ "description": "Manifest-driven pixel-art generation, review, recovery, and packaging with deterministic provenance.",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "pixelkiln": "./bin/pixelkiln.js"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "import": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "require": {
19
+ "types": "./dist/index.d.cts",
20
+ "default": "./dist/index.cjs"
21
+ }
22
+ }
23
+ },
24
+ "scripts": {
25
+ "pixelkiln": "tsx src/cli.ts",
26
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean --sourcemap && tsup src/cli.ts --format esm --dts --sourcemap",
27
+ "prepack": "npm run build",
28
+ "release": "semantic-release",
29
+ "typecheck": "tsc --noEmit",
30
+ "test": "vitest run",
31
+ "test:docs": "node scripts/check-docs.mjs",
32
+ "test:package": "node scripts/smoke-package.mjs",
33
+ "test:watch": "vitest",
34
+ "schema": "tsx scripts/gen-schema.ts",
35
+ "website:dev": "npm run dev --prefix website",
36
+ "website:check": "npm run check:content --prefix website",
37
+ "website:lint": "npm run lint --prefix website",
38
+ "website:build": "npm run build --prefix website"
39
+ },
40
+ "engines": {
41
+ "node": ">=20"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/gfargo/pixelkiln.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/gfargo/pixelkiln/issues"
49
+ },
50
+ "homepage": "https://pixelkiln.griffen.codes",
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "dependencies": {
55
+ "zod": "^3.23.8"
56
+ },
57
+ "devDependencies": {
58
+ "@semantic-release/changelog": "^7.0.0",
59
+ "@semantic-release/commit-analyzer": "^13.0.1",
60
+ "@semantic-release/git": "^11.0.1",
61
+ "@semantic-release/github": "^12.0.9",
62
+ "@semantic-release/npm": "^13.1.5",
63
+ "@semantic-release/release-notes-generator": "^14.1.1",
64
+ "@types/node": "^22.10.0",
65
+ "semantic-release": "^25.0.9",
66
+ "tsup": "^8.5.1",
67
+ "tsx": "^4.19.2",
68
+ "typescript": "^5.7.2",
69
+ "vitest": "^4.1.10",
70
+ "zod-to-json-schema": "^3.25.2"
71
+ },
72
+ "overrides": {
73
+ "esbuild": "^0.28.2"
74
+ },
75
+ "license": "MIT",
76
+ "keywords": [
77
+ "pixel-art",
78
+ "sprites",
79
+ "game-assets",
80
+ "pixellab",
81
+ "asset-pipeline",
82
+ "generative",
83
+ "lockfile",
84
+ "cli"
85
+ ],
86
+ "files": [
87
+ "dist",
88
+ "bin",
89
+ "schema",
90
+ "skills",
91
+ "docs",
92
+ "examples",
93
+ "README.md",
94
+ "CONTRIBUTING.md",
95
+ "SECURITY.md",
96
+ "PROVIDERS.md",
97
+ "NAMING.md",
98
+ "LICENSE"
99
+ ]
100
+ }
@@ -0,0 +1,255 @@
1
+ {
2
+ "$ref": "#/definitions/PixelkilnManifest",
3
+ "definitions": {
4
+ "PixelkilnManifest": {
5
+ "type": "object",
6
+ "properties": {
7
+ "$schema": {
8
+ "type": "string"
9
+ },
10
+ "name": {
11
+ "type": "string"
12
+ },
13
+ "styles": {
14
+ "type": "object",
15
+ "additionalProperties": {
16
+ "type": "object",
17
+ "properties": {
18
+ "generator": {
19
+ "type": "string",
20
+ "enum": [
21
+ "1dir",
22
+ "map",
23
+ "pixflux",
24
+ "tiles"
25
+ ],
26
+ "default": "map"
27
+ },
28
+ "size": {
29
+ "type": "integer",
30
+ "minimum": 32,
31
+ "maximum": 256
32
+ },
33
+ "view": {
34
+ "type": "string"
35
+ },
36
+ "promptSuffix": {
37
+ "type": "string",
38
+ "default": ""
39
+ },
40
+ "promptPrefix": {
41
+ "type": "string",
42
+ "default": ""
43
+ },
44
+ "styleImages": {
45
+ "type": "array",
46
+ "items": {
47
+ "type": "object",
48
+ "properties": {
49
+ "path": {
50
+ "type": "string"
51
+ }
52
+ },
53
+ "required": [
54
+ "path"
55
+ ],
56
+ "additionalProperties": false
57
+ },
58
+ "default": []
59
+ },
60
+ "outDir": {
61
+ "type": "string"
62
+ },
63
+ "outline": {
64
+ "type": "string"
65
+ },
66
+ "shading": {
67
+ "type": "string"
68
+ },
69
+ "detail": {
70
+ "type": "string"
71
+ },
72
+ "tileSize": {
73
+ "type": "integer",
74
+ "minimum": 16,
75
+ "maximum": 256
76
+ },
77
+ "tileType": {
78
+ "type": "string",
79
+ "enum": [
80
+ "hex",
81
+ "hex_pointy",
82
+ "isometric",
83
+ "oblique",
84
+ "octagon",
85
+ "square_topdown"
86
+ ]
87
+ },
88
+ "tileView": {
89
+ "type": "string",
90
+ "enum": [
91
+ "top-down",
92
+ "high top-down",
93
+ "low top-down",
94
+ "side"
95
+ ]
96
+ },
97
+ "tileFeature": {
98
+ "type": "string",
99
+ "enum": [
100
+ "roads",
101
+ "tileset",
102
+ "building"
103
+ ]
104
+ },
105
+ "outlineMode": {
106
+ "type": "string",
107
+ "enum": [
108
+ "outline",
109
+ "segmentation"
110
+ ]
111
+ },
112
+ "noBackground": {
113
+ "type": "boolean",
114
+ "default": true
115
+ },
116
+ "seed": {
117
+ "type": "integer"
118
+ },
119
+ "palette": {
120
+ "type": "array",
121
+ "items": {
122
+ "type": "string",
123
+ "pattern": "^#?[0-9a-f]{6}$"
124
+ },
125
+ "default": []
126
+ },
127
+ "mount": {
128
+ "type": "object",
129
+ "properties": {
130
+ "base": {
131
+ "type": "string"
132
+ },
133
+ "cellWidth": {
134
+ "type": "integer",
135
+ "exclusiveMinimum": 0
136
+ },
137
+ "cellHeight": {
138
+ "type": "integer",
139
+ "exclusiveMinimum": 0
140
+ },
141
+ "out": {
142
+ "type": "string"
143
+ }
144
+ },
145
+ "required": [
146
+ "cellWidth",
147
+ "cellHeight",
148
+ "out"
149
+ ],
150
+ "additionalProperties": false
151
+ },
152
+ "tags": {
153
+ "type": "array",
154
+ "items": {
155
+ "type": "string"
156
+ },
157
+ "default": []
158
+ }
159
+ },
160
+ "required": [
161
+ "outDir"
162
+ ],
163
+ "additionalProperties": false
164
+ }
165
+ },
166
+ "assets": {
167
+ "type": "object",
168
+ "additionalProperties": {
169
+ "type": "object",
170
+ "properties": {
171
+ "prompt": {
172
+ "type": "string"
173
+ },
174
+ "category": {
175
+ "type": "string"
176
+ },
177
+ "width": {
178
+ "type": "integer",
179
+ "minimum": 16,
180
+ "maximum": 400
181
+ },
182
+ "height": {
183
+ "type": "integer",
184
+ "minimum": 16,
185
+ "maximum": 400
186
+ },
187
+ "size": {
188
+ "type": "integer",
189
+ "minimum": 32,
190
+ "maximum": 256
191
+ },
192
+ "file": {
193
+ "type": "string"
194
+ },
195
+ "cell": {
196
+ "type": "array",
197
+ "minItems": 2,
198
+ "maxItems": 2,
199
+ "items": [
200
+ {
201
+ "type": "integer",
202
+ "minimum": 0
203
+ },
204
+ {
205
+ "type": "integer",
206
+ "minimum": 0
207
+ }
208
+ ]
209
+ },
210
+ "source": {
211
+ "type": "string"
212
+ },
213
+ "outputRole": {
214
+ "type": "string",
215
+ "minLength": 1
216
+ },
217
+ "tags": {
218
+ "type": "array",
219
+ "items": {
220
+ "type": "string"
221
+ },
222
+ "default": []
223
+ },
224
+ "styles": {
225
+ "type": "array",
226
+ "items": {
227
+ "type": "string"
228
+ },
229
+ "default": []
230
+ },
231
+ "promptByStyle": {
232
+ "type": "object",
233
+ "additionalProperties": {
234
+ "type": "string"
235
+ },
236
+ "default": {}
237
+ }
238
+ },
239
+ "required": [
240
+ "prompt"
241
+ ],
242
+ "additionalProperties": false
243
+ }
244
+ }
245
+ },
246
+ "required": [
247
+ "name",
248
+ "styles",
249
+ "assets"
250
+ ],
251
+ "additionalProperties": false
252
+ }
253
+ },
254
+ "$schema": "http://json-schema.org/draft-07/schema#"
255
+ }
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: pixelkiln
3
+ description: Use PixelKiln to plan, generate, review, recover, audit, pack, and export manifest-driven pixel-art projects. Apply when a task uses the PixelKiln CLI, manifest, lockfile, or generated asset workflow; do not use for unrelated one-off image generation.
4
+ ---
5
+
6
+ # PixelKiln
7
+
8
+ Treat generated pixel art as build state: declared in a manifest, costed before
9
+ submission, reviewed by a human, and recorded with exact provenance.
10
+
11
+ ## Working rules
12
+
13
+ - Locate `pixelkiln.manifest.json` first. Paths are manifest-relative.
14
+ - Never inspect, print, or commit provider credentials. PixelKiln can load
15
+ `PIXELLAB_API_KEY` from `.env.local` beside the manifest or from the current
16
+ working directory.
17
+ - Run `pixelkiln doctor --dry-run` and `pixelkiln plan` before paid work. Report
18
+ actionable, recoverable, and estimated cost figures with their provider unit.
19
+ - Do not regenerate recoverable work. Use `pixelkiln restore` first.
20
+ - Submit paid work only when the user has authorized generation. Always pass an
21
+ explicit `--budget` no higher than the authorized estimate.
22
+ - Leave visual selection to the local `pixelkiln pick` review page unless the
23
+ user explicitly provides a selection rule. Closing it applies nothing.
24
+ - Preserve manual edits and ownership errors. Inspect the difference before any
25
+ `--force` operation.
26
+ - Commit the manifest, lockfile, generated outputs, and derived artifact
27
+ companions. Never commit `.env.local` or `.pixelkiln/` cache data.
28
+
29
+ ## Choose the smallest workflow
30
+
31
+ For ordinary work, prefer:
32
+
33
+ ```bash
34
+ pixelkiln doctor --dry-run
35
+ pixelkiln plan
36
+ pixelkiln gen --budget <approved-provider-units>
37
+ pixelkiln audit --check
38
+ ```
39
+
40
+ Use the staged `submit` → `poll` → `pick` → `fetch` commands when resuming or
41
+ debugging one phase. Use `restore` for missing bytes, `adopt` for exact matches
42
+ already in the provider account, and `salvage` for reviewed unclaimed objects.
43
+ Use `pack`, `mount`, or `export` only for the artifact format the project needs.
44
+
45
+ PixelKiln's orchestration is provider-neutral. PixelLab is currently its only
46
+ production and live-tested adapter; `FakeProvider` is the deterministic test
47
+ adapter. Do not imply that other production providers already work.
48
+
49
+ When working in the PixelKiln repository, consult `docs/GETTING_STARTED.md` for
50
+ the full workflow, `docs/CLI.md` for flags, `docs/MANIFEST.md` for the schema,
51
+ and `docs/RECOVERY.md` before account adoption, salvage, discard, or purge.
@@ -0,0 +1,5 @@
1
+ interface:
2
+ display_name: "PixelKiln"
3
+ short_description: "Plan and ship provenance-safe pixel art"
4
+ brand_color: "#FF6B35"
5
+ default_prompt: "Use $pixelkiln to plan and safely produce this project's pixel-art assets."