lootforge 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +764 -0
  3. package/bin/lootforge.js +28 -0
  4. package/dist/benchmarks/coarseToFineCost.d.ts +21 -0
  5. package/dist/benchmarks/coarseToFineCost.js +49 -0
  6. package/dist/benchmarks/coarseToFineCost.js.map +1 -0
  7. package/dist/checks/boundaryMetrics.d.ts +12 -0
  8. package/dist/checks/boundaryMetrics.js +102 -0
  9. package/dist/checks/boundaryMetrics.js.map +1 -0
  10. package/dist/checks/candidateScore.d.ts +11 -0
  11. package/dist/checks/candidateScore.js +462 -0
  12. package/dist/checks/candidateScore.js.map +1 -0
  13. package/dist/checks/commandParser.d.ts +5 -0
  14. package/dist/checks/commandParser.js +99 -0
  15. package/dist/checks/commandParser.js.map +1 -0
  16. package/dist/checks/consistencyOutliers.d.ts +42 -0
  17. package/dist/checks/consistencyOutliers.js +156 -0
  18. package/dist/checks/consistencyOutliers.js.map +1 -0
  19. package/dist/checks/imageAcceptance.d.ts +67 -0
  20. package/dist/checks/imageAcceptance.js +967 -0
  21. package/dist/checks/imageAcceptance.js.map +1 -0
  22. package/dist/checks/packInvariants.d.ts +56 -0
  23. package/dist/checks/packInvariants.js +1064 -0
  24. package/dist/checks/packInvariants.js.map +1 -0
  25. package/dist/checks/softAdapters.d.ts +25 -0
  26. package/dist/checks/softAdapters.js +275 -0
  27. package/dist/checks/softAdapters.js.map +1 -0
  28. package/dist/checks/vlmGate.d.ts +8 -0
  29. package/dist/checks/vlmGate.js +200 -0
  30. package/dist/checks/vlmGate.js.map +1 -0
  31. package/dist/cli/commands/atlas.d.ts +5 -0
  32. package/dist/cli/commands/atlas.js +18 -0
  33. package/dist/cli/commands/atlas.js.map +1 -0
  34. package/dist/cli/commands/eval.d.ts +6 -0
  35. package/dist/cli/commands/eval.js +23 -0
  36. package/dist/cli/commands/eval.js.map +1 -0
  37. package/dist/cli/commands/generate.d.ts +18 -0
  38. package/dist/cli/commands/generate.js +66 -0
  39. package/dist/cli/commands/generate.js.map +1 -0
  40. package/dist/cli/commands/init.d.ts +15 -0
  41. package/dist/cli/commands/init.js +146 -0
  42. package/dist/cli/commands/init.js.map +1 -0
  43. package/dist/cli/commands/package.d.ts +6 -0
  44. package/dist/cli/commands/package.js +27 -0
  45. package/dist/cli/commands/package.js.map +1 -0
  46. package/dist/cli/commands/plan.d.ts +16 -0
  47. package/dist/cli/commands/plan.js +49 -0
  48. package/dist/cli/commands/plan.js.map +1 -0
  49. package/dist/cli/commands/process.d.ts +14 -0
  50. package/dist/cli/commands/process.js +29 -0
  51. package/dist/cli/commands/process.js.map +1 -0
  52. package/dist/cli/commands/regenerate.d.ts +29 -0
  53. package/dist/cli/commands/regenerate.js +244 -0
  54. package/dist/cli/commands/regenerate.js.map +1 -0
  55. package/dist/cli/commands/review.d.ts +5 -0
  56. package/dist/cli/commands/review.js +18 -0
  57. package/dist/cli/commands/review.js.map +1 -0
  58. package/dist/cli/commands/select.d.ts +6 -0
  59. package/dist/cli/commands/select.js +21 -0
  60. package/dist/cli/commands/select.js.map +1 -0
  61. package/dist/cli/commands/serve.d.ts +16 -0
  62. package/dist/cli/commands/serve.js +100 -0
  63. package/dist/cli/commands/serve.js.map +1 -0
  64. package/dist/cli/commands/validate.d.ts +17 -0
  65. package/dist/cli/commands/validate.js +108 -0
  66. package/dist/cli/commands/validate.js.map +1 -0
  67. package/dist/cli/index.d.ts +1 -0
  68. package/dist/cli/index.js +157 -0
  69. package/dist/cli/index.js.map +1 -0
  70. package/dist/cli/parseArgs.d.ts +3 -0
  71. package/dist/cli/parseArgs.js +37 -0
  72. package/dist/cli/parseArgs.js.map +1 -0
  73. package/dist/contracts/stageArtifacts.d.ts +4031 -0
  74. package/dist/contracts/stageArtifacts.js +663 -0
  75. package/dist/contracts/stageArtifacts.js.map +1 -0
  76. package/dist/manifest/load.d.ts +3 -0
  77. package/dist/manifest/load.js +50 -0
  78. package/dist/manifest/load.js.map +1 -0
  79. package/dist/manifest/normalize-palette.d.ts +17 -0
  80. package/dist/manifest/normalize-palette.js +235 -0
  81. package/dist/manifest/normalize-palette.js.map +1 -0
  82. package/dist/manifest/normalize-policy.d.ts +48 -0
  83. package/dist/manifest/normalize-policy.js +239 -0
  84. package/dist/manifest/normalize-policy.js.map +1 -0
  85. package/dist/manifest/normalize-prompt.d.ts +14 -0
  86. package/dist/manifest/normalize-prompt.js +73 -0
  87. package/dist/manifest/normalize-prompt.js.map +1 -0
  88. package/dist/manifest/normalize-target.d.ts +49 -0
  89. package/dist/manifest/normalize-target.js +542 -0
  90. package/dist/manifest/normalize-target.js.map +1 -0
  91. package/dist/manifest/schema.d.ts +7570 -0
  92. package/dist/manifest/schema.js +373 -0
  93. package/dist/manifest/schema.js.map +1 -0
  94. package/dist/manifest/semantic-validation.d.ts +4 -0
  95. package/dist/manifest/semantic-validation.js +526 -0
  96. package/dist/manifest/semantic-validation.js.map +1 -0
  97. package/dist/manifest/types.d.ts +263 -0
  98. package/dist/manifest/types.js +2 -0
  99. package/dist/manifest/types.js.map +1 -0
  100. package/dist/manifest/validate.d.ts +12 -0
  101. package/dist/manifest/validate.js +221 -0
  102. package/dist/manifest/validate.js.map +1 -0
  103. package/dist/output/assetPackManifest.d.ts +19 -0
  104. package/dist/output/assetPackManifest.js +20 -0
  105. package/dist/output/assetPackManifest.js.map +1 -0
  106. package/dist/output/catalog.d.ts +60 -0
  107. package/dist/output/catalog.js +107 -0
  108. package/dist/output/catalog.js.map +1 -0
  109. package/dist/output/contactSheet.d.ts +13 -0
  110. package/dist/output/contactSheet.js +124 -0
  111. package/dist/output/contactSheet.js.map +1 -0
  112. package/dist/output/phaserManifest.d.ts +8 -0
  113. package/dist/output/phaserManifest.js +25 -0
  114. package/dist/output/phaserManifest.js.map +1 -0
  115. package/dist/output/pixiManifest.d.ts +8 -0
  116. package/dist/output/pixiManifest.js +37 -0
  117. package/dist/output/pixiManifest.js.map +1 -0
  118. package/dist/output/provenance.d.ts +121 -0
  119. package/dist/output/provenance.js +10 -0
  120. package/dist/output/provenance.js.map +1 -0
  121. package/dist/output/runtimeManifests.d.ts +21 -0
  122. package/dist/output/runtimeManifests.js +82 -0
  123. package/dist/output/runtimeManifests.js.map +1 -0
  124. package/dist/output/unityImportManifest.d.ts +10 -0
  125. package/dist/output/unityImportManifest.js +58 -0
  126. package/dist/output/unityImportManifest.js.map +1 -0
  127. package/dist/output/zip.d.ts +5 -0
  128. package/dist/output/zip.js +68 -0
  129. package/dist/output/zip.js.map +1 -0
  130. package/dist/pipeline/atlas.d.ts +33 -0
  131. package/dist/pipeline/atlas.js +286 -0
  132. package/dist/pipeline/atlas.js.map +1 -0
  133. package/dist/pipeline/eval.d.ts +104 -0
  134. package/dist/pipeline/eval.js +246 -0
  135. package/dist/pipeline/eval.js.map +1 -0
  136. package/dist/pipeline/generate.d.ts +44 -0
  137. package/dist/pipeline/generate.js +1088 -0
  138. package/dist/pipeline/generate.js.map +1 -0
  139. package/dist/pipeline/package.d.ts +18 -0
  140. package/dist/pipeline/package.js +218 -0
  141. package/dist/pipeline/package.js.map +1 -0
  142. package/dist/pipeline/process.d.ts +15 -0
  143. package/dist/pipeline/process.js +776 -0
  144. package/dist/pipeline/process.js.map +1 -0
  145. package/dist/pipeline/review.d.ts +10 -0
  146. package/dist/pipeline/review.js +341 -0
  147. package/dist/pipeline/review.js.map +1 -0
  148. package/dist/pipeline/seamHeal.d.ts +2 -0
  149. package/dist/pipeline/seamHeal.js +70 -0
  150. package/dist/pipeline/seamHeal.js.map +1 -0
  151. package/dist/pipeline/select.d.ts +39 -0
  152. package/dist/pipeline/select.js +79 -0
  153. package/dist/pipeline/select.js.map +1 -0
  154. package/dist/providers/job.d.ts +29 -0
  155. package/dist/providers/job.js +113 -0
  156. package/dist/providers/job.js.map +1 -0
  157. package/dist/providers/localDiffusion.d.ts +28 -0
  158. package/dist/providers/localDiffusion.js +235 -0
  159. package/dist/providers/localDiffusion.js.map +1 -0
  160. package/dist/providers/nano.d.ts +36 -0
  161. package/dist/providers/nano.js +402 -0
  162. package/dist/providers/nano.js.map +1 -0
  163. package/dist/providers/openai.d.ts +37 -0
  164. package/dist/providers/openai.js +378 -0
  165. package/dist/providers/openai.js.map +1 -0
  166. package/dist/providers/policy.d.ts +9 -0
  167. package/dist/providers/policy.js +192 -0
  168. package/dist/providers/policy.js.map +1 -0
  169. package/dist/providers/prompt.d.ts +3 -0
  170. package/dist/providers/prompt.js +63 -0
  171. package/dist/providers/prompt.js.map +1 -0
  172. package/dist/providers/registry.d.ts +24 -0
  173. package/dist/providers/registry.js +92 -0
  174. package/dist/providers/registry.js.map +1 -0
  175. package/dist/providers/runtime.d.ts +15 -0
  176. package/dist/providers/runtime.js +101 -0
  177. package/dist/providers/runtime.js.map +1 -0
  178. package/dist/providers/runtimeConfig.d.ts +20 -0
  179. package/dist/providers/runtimeConfig.js +146 -0
  180. package/dist/providers/runtimeConfig.js.map +1 -0
  181. package/dist/providers/types-core.d.ts +514 -0
  182. package/dist/providers/types-core.js +60 -0
  183. package/dist/providers/types-core.js.map +1 -0
  184. package/dist/providers/types.d.ts +4 -0
  185. package/dist/providers/types.js +5 -0
  186. package/dist/providers/types.js.map +1 -0
  187. package/dist/service/generationRequest.d.ts +58 -0
  188. package/dist/service/generationRequest.js +203 -0
  189. package/dist/service/generationRequest.js.map +1 -0
  190. package/dist/service/providerCapabilities.d.ts +40 -0
  191. package/dist/service/providerCapabilities.js +114 -0
  192. package/dist/service/providerCapabilities.js.map +1 -0
  193. package/dist/service/server.d.ts +31 -0
  194. package/dist/service/server.js +774 -0
  195. package/dist/service/server.js.map +1 -0
  196. package/dist/shared/errors.d.ts +13 -0
  197. package/dist/shared/errors.js +24 -0
  198. package/dist/shared/errors.js.map +1 -0
  199. package/dist/shared/fs.d.ts +6 -0
  200. package/dist/shared/fs.js +30 -0
  201. package/dist/shared/fs.js.map +1 -0
  202. package/dist/shared/image.d.ts +25 -0
  203. package/dist/shared/image.js +136 -0
  204. package/dist/shared/image.js.map +1 -0
  205. package/dist/shared/paths.d.ts +30 -0
  206. package/dist/shared/paths.js +103 -0
  207. package/dist/shared/paths.js.map +1 -0
  208. package/dist/shared/schemas.d.ts +209 -0
  209. package/dist/shared/schemas.js +93 -0
  210. package/dist/shared/schemas.js.map +1 -0
  211. package/dist/shared/typeGuards.d.ts +1 -0
  212. package/dist/shared/typeGuards.js +4 -0
  213. package/dist/shared/typeGuards.js.map +1 -0
  214. package/dist/shared/zod.d.ts +1 -0
  215. package/dist/shared/zod.js +14 -0
  216. package/dist/shared/zod.js.map +1 -0
  217. package/dist/showcase/format.d.ts +9 -0
  218. package/dist/showcase/format.js +61 -0
  219. package/dist/showcase/format.js.map +1 -0
  220. package/dist/showcase/panelRenderer.d.ts +59 -0
  221. package/dist/showcase/panelRenderer.js +294 -0
  222. package/dist/showcase/panelRenderer.js.map +1 -0
  223. package/dist/showcase/releaseConfig.d.ts +233 -0
  224. package/dist/showcase/releaseConfig.js +75 -0
  225. package/dist/showcase/releaseConfig.js.map +1 -0
  226. package/dist/showcase/releaseEvidence.d.ts +25 -0
  227. package/dist/showcase/releaseEvidence.js +540 -0
  228. package/dist/showcase/releaseEvidence.js.map +1 -0
  229. package/dist/showcase/releaseEvidenceSchema.d.ts +1611 -0
  230. package/dist/showcase/releaseEvidenceSchema.js +165 -0
  231. package/dist/showcase/releaseEvidenceSchema.js.map +1 -0
  232. package/dist/showcase/scenarioRenderer.d.ts +19 -0
  233. package/dist/showcase/scenarioRenderer.js +488 -0
  234. package/dist/showcase/scenarioRenderer.js.map +1 -0
  235. package/docs/ADAPTER_CONTRACT.md +141 -0
  236. package/docs/ENGINE_TARGETING.md +86 -0
  237. package/docs/MANIFEST_POLICY_COVERAGE.md +130 -0
  238. package/docs/RELEASE_WORKFLOW.md +117 -0
  239. package/docs/ROADMAP.md +411 -0
  240. package/docs/ROADMAP_ISSUES.md +244 -0
  241. package/docs/SERVICE_MODE.md +137 -0
  242. package/docs/manifest-schema.md +254 -0
  243. package/package.json +70 -0
package/README.md ADDED
@@ -0,0 +1,764 @@
1
+ <p align="center">
2
+ <img src="docs/showcase/0.2.0/04-release-hero.png" alt="LootForge release banner" width="960" />
3
+ </p>
4
+
5
+ <h1 align="center">LootForge</h1>
6
+
7
+ <p align="center">
8
+ <strong>Manifest-driven CLI for generating, validating, and packaging runtime-ready game image assets.</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://github.com/Someblueman/lootforge/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/Someblueman/lootforge/actions/workflows/ci.yml/badge.svg" /></a>
13
+ <a href="https://github.com/Someblueman/lootforge/actions/workflows/security.yml"><img alt="Security" src="https://github.com/Someblueman/lootforge/actions/workflows/security.yml/badge.svg" /></a>
14
+ <a href="https://github.com/Someblueman/lootforge/releases/tag/v0.3.0"><img alt="Release v0.3.0" src="https://img.shields.io/badge/release-v0.3.0-2f855a" /></a>
15
+ <a href="https://github.com/Someblueman/lootforge/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/Someblueman/lootforge?style=flat" /></a>
16
+ </p>
17
+
18
+ <p align="center"><code>Current version: 0.3.0 (Tempered Steel)</code></p>
19
+
20
+ ## Quick Start
21
+
22
+ Requirements: `node >=22`, `npm >=10`
23
+
24
+ Install:
25
+
26
+ ```bash
27
+ npm install --cache .npm-cache
28
+ npm run build
29
+ ```
30
+
31
+ Run a local validation pass (no provider API keys required):
32
+
33
+ ```bash
34
+ node bin/lootforge.js init --out .
35
+ node bin/lootforge.js plan --manifest assets/imagegen/manifest.json --out assets/imagegen
36
+ node bin/lootforge.js validate --manifest assets/imagegen/manifest.json --out assets/imagegen
37
+ ```
38
+
39
+ ## Why LootForge
40
+
41
+ Most image generators stop at `prompt -> image`.
42
+ LootForge is designed for `prompt -> image -> game runtime artifact`.
43
+
44
+ Key outcomes:
45
+
46
+ - Consistent output structure
47
+ - Deterministic job metadata and provenance
48
+ - Inspectable validation and quality reports
49
+ - Runtime-ready atlas/manifests and portable pack artifacts
50
+
51
+ ## Core Workflow
52
+
53
+ `init -> plan -> validate -> generate -> process -> atlas -> eval -> review -> select -> package`
54
+
55
+ ## Core Capabilities
56
+
57
+ - `next` manifest schema with style kits, evaluation profiles, and spritesheet planning
58
+ - Provider selection: `openai`, `nano`, `local`, or `auto`
59
+ - Provider-aware normalization (`jpg -> jpeg`) with explicit unsupported-provider errors (no silent transparent fallback)
60
+ - Enforced provider runtime contract (manifest/env endpoint, timeout, retry, delay, concurrency)
61
+ - Deterministic job IDs keyed to normalized generation policy
62
+ - Multi-candidate generation with deterministic best-of scoring
63
+ - Optional VLM candidate gating (`generationPolicy.vlmGate`) with per-candidate traceability
64
+ - Post-process operators (`trim`, `pad/extrude`, `quantize`, `outline`, `resizeVariants`)
65
+ - Pixel-level acceptance checks with JSON report output
66
+ - Pack-level invariants in acceptance/eval (runtime-output uniqueness, spritesheet continuity, optional texture budgets)
67
+ - Atlas stage with optional TexturePacker integration plus reproducibility artifacts
68
+ - Pack assembly with runtime manifests and review artifacts
69
+
70
+ ## Quick Links
71
+
72
+ - [Showcase](#showcase-what-lootforge-output-looks-like)
73
+ - [Quickstart (end-to-end)](#quickstart-end-to-end)
74
+ - [CLI Commands](#cli-commands)
75
+ - [Manifest Schema](#manifest-version-next)
76
+ - [Service Mode](#lootforge-serve)
77
+ - [Environment Variables](#environment-variables)
78
+ - [Status / Roadmap](#status--roadmap)
79
+
80
+ ## Showcase: What LootForge Output Looks Like
81
+
82
+ The `0.3.0` release showcase is evidence-driven and versioned under `docs/showcase/0.3.0/`.
83
+ It combines release-over-release quality deltas with feature-specific proof panels.
84
+
85
+ ### 1) Release quality delta (`0.2.0 -> 0.3.0`)
86
+
87
+ ![Release quality delta](docs/showcase/0.3.0/01-quality-delta.png)
88
+
89
+ ### 2) Nano vs OpenAI (best-case per provider)
90
+
91
+ ![Nano vs OpenAI best-case](docs/showcase/0.3.0/02-provider-openai-vs-nano.png)
92
+
93
+ ### 3) Spritesheet continuity and drift QA
94
+
95
+ ![Spritesheet drift QA](docs/showcase/0.3.0/03-spritesheet-drift-qa.png)
96
+
97
+ ### 4) Style-bible policy checks
98
+
99
+ ![Style bible policy checks](docs/showcase/0.3.0/04-style-bible-policy.png)
100
+
101
+ ### 5) Coarse-to-fine promotion evidence
102
+
103
+ ![Coarse to fine evidence](docs/showcase/0.3.0/05-coarse-to-fine.png)
104
+
105
+ ### 6) Agentic auto-correction retries
106
+
107
+ ![Agentic retry evidence](docs/showcase/0.3.0/06-agentic-retry.png)
108
+
109
+ ### 7) Pack-level invariants
110
+
111
+ ![Pack invariants evidence](docs/showcase/0.3.0/07-pack-invariants.png)
112
+
113
+ ### 8) Consistency-group outlier scoring
114
+
115
+ ![Consistency outlier evidence](docs/showcase/0.3.0/08-consistency-outliers.png)
116
+
117
+ Release evidence artifacts:
118
+
119
+ - JSON report: `docs/showcase/0.3.0/evidence/report.json`
120
+ - Summary markdown: `docs/showcase/0.3.0/evidence/summary.md`
121
+
122
+ Regenerate showcase evidence end-to-end:
123
+
124
+ ```bash
125
+ # one-time: refresh pinned baseline evidence
126
+ npm run release:showcase -- --release 0.2.0 --mode all --providers openai-baseline
127
+
128
+ # capture + compare + render 0.3.0 evidence panels
129
+ npm run release:showcase -- --release 0.3.0 --mode all
130
+
131
+ # verify release metadata + showcase docs consistency
132
+ npm run check:release:metadata
133
+ npm run check:release-showcase
134
+
135
+ # run the full release gate before tagging
136
+ npm run check:release
137
+ ```
138
+
139
+ ## Requirements
140
+
141
+ - Node.js 22+ (recommended)
142
+ - npm 10+
143
+ - Optional: `texturepacker` for atlas sprite sheets
144
+ - Provider keys only for generation:
145
+ - `OPENAI_API_KEY`
146
+ - `GEMINI_API_KEY`
147
+
148
+ ## Installation
149
+
150
+ ### Local development
151
+
152
+ ```bash
153
+ npm install --cache .npm-cache
154
+ npm run build
155
+ ```
156
+
157
+ Run the built CLI:
158
+
159
+ ```bash
160
+ node bin/lootforge.js --help
161
+ ```
162
+
163
+ If you want global command access during development:
164
+
165
+ ```bash
166
+ npm link
167
+ lootforge --help
168
+ ```
169
+
170
+ ## Quickstart (end-to-end)
171
+
172
+ ```bash
173
+ # 1) Scaffold manifest + folders
174
+ node dist/cli/index.js init --out .
175
+
176
+ # 2) Plan jobs
177
+ node dist/cli/index.js plan \
178
+ --manifest assets/imagegen/manifest.json \
179
+ --out assets/imagegen
180
+
181
+ # 3) Validate manifest (strict by default)
182
+ node dist/cli/index.js validate \
183
+ --manifest assets/imagegen/manifest.json \
184
+ --out assets/imagegen
185
+
186
+ # 4) Generate images (requires provider API key)
187
+ node dist/cli/index.js generate \
188
+ --out assets/imagegen \
189
+ --provider openai
190
+
191
+ # 5) Process raw assets into runtime-ready outputs
192
+ node dist/cli/index.js process --out assets/imagegen
193
+
194
+ # 6) Build atlases, evaluate/select, then package artifact bundle
195
+ node dist/cli/index.js atlas --out assets/imagegen
196
+ node dist/cli/index.js eval --out assets/imagegen --strict true
197
+ node dist/cli/index.js review --out assets/imagegen
198
+ node dist/cli/index.js select --out assets/imagegen
199
+ node dist/cli/index.js package \
200
+ --manifest assets/imagegen/manifest.json \
201
+ --out assets/imagegen
202
+ ```
203
+
204
+ ## CLI Commands
205
+
206
+ The sections below focus on behavior, key outputs, and commonly used flags.
207
+ For full option coverage, run `lootforge <command> --help`.
208
+
209
+ ### Command Summary
210
+
211
+ | Command | Primary purpose | Main artifacts |
212
+ | ------------ | -------------------------------------------------------- | ---------------------------------------------------- |
213
+ | `init` | Scaffold manifest + workspace folders | `manifest.json`, `raw/`, `processed/`, `jobs/` |
214
+ | `plan` | Validate manifest and emit provider job plans | `targets-index.json`, provider JSONL files |
215
+ | `validate` | Run manifest and optional image acceptance checks | `validation-report.json`, optional acceptance report |
216
+ | `generate` | Generate candidate images using selected provider(s) | Provider raw outputs + provenance |
217
+ | `regenerate` | Re-run approved targets via edit-first lock flow | Updated generated assets + lock-linked provenance |
218
+ | `process` | Apply post-processing and image acceptance | Processed catalog + acceptance report |
219
+ | `atlas` | Build atlas artifacts and reproducibility config | Atlas manifest and optional sheet assets |
220
+ | `eval` | Compute quality scoring and adapter telemetry | `eval-report.json` |
221
+ | `review` | Render review artifact from eval outputs | `review/review.html` |
222
+ | `select` | Materialize approved selections into lockfile | `locks/selection-lock.json` |
223
+ | `package` | Assemble runtime-ready distributable packs | `dist/packs/*` + final zip |
224
+ | `serve` | Start local HTTP service mode for tool/command execution | `v1` JSON endpoints |
225
+
226
+ ### `lootforge init`
227
+
228
+ Scaffolds a starter workspace:
229
+
230
+ - `assets/imagegen/manifest.json`
231
+ - `assets/imagegen/raw/`
232
+ - `assets/imagegen/processed/`
233
+ - `assets/imagegen/jobs/`
234
+
235
+ Example:
236
+
237
+ ```bash
238
+ lootforge init --out .
239
+ ```
240
+
241
+ ### `lootforge plan`
242
+
243
+ Validates the manifest and writes planned jobs:
244
+
245
+ - `<out>/jobs/targets-index.json`
246
+ - `<out>/jobs/openai.jsonl`
247
+ - `<out>/jobs/nano.jsonl`
248
+ - `<out>/jobs/local.jsonl`
249
+
250
+ Example:
251
+
252
+ ```bash
253
+ lootforge plan --manifest assets/imagegen/manifest.json --out assets/imagegen
254
+ ```
255
+
256
+ ### `lootforge validate`
257
+
258
+ Outputs:
259
+
260
+ - `<out>/checks/validation-report.json`
261
+ - Optional: `<out>/checks/image-acceptance-report.json`
262
+ - acceptance report may include top-level `packInvariants` summary when pack-level checks emit issues/metrics
263
+
264
+ Key flags:
265
+
266
+ - `--strict true|false` (default: `true`)
267
+ - `--check-images true|false` (default: `false`)
268
+ - `--images-dir <path>` optional override for acceptance checks
269
+
270
+ Example:
271
+
272
+ ```bash
273
+ lootforge validate --manifest assets/imagegen/manifest.json --out assets/imagegen --strict true --check-images true
274
+ ```
275
+
276
+ ### `lootforge generate`
277
+
278
+ Runs provider generation from planned targets index.
279
+
280
+ Key flags:
281
+
282
+ - `--out <dir>`
283
+ - `--index <path>` optional (default `<out>/jobs/targets-index.json`)
284
+ - `--provider openai|nano|local|auto`
285
+ - `--ids a,b,c` optional subset
286
+
287
+ Example:
288
+
289
+ ```bash
290
+ lootforge generate --out assets/imagegen --provider nano --ids enemy-1,ui-icon-attack
291
+ ```
292
+
293
+ ### `lootforge regenerate`
294
+
295
+ Re-runs selected targets from selection-lock state, with dedicated edit-first flow support.
296
+
297
+ Key flags:
298
+
299
+ - `--out <dir>`
300
+ - `--index <path>` optional (default `<out>/jobs/targets-index.json`)
301
+ - `--lock <path>` optional (default `<out>/locks/selection-lock.json`)
302
+ - `--ids a,b,c` optional subset (default: all lock-approved targets)
303
+ - `--edit true|false` (default: `true`)
304
+ - `--instruction "<text>"` optional instruction override for edit mode
305
+ - `--preserve-composition true|false` (default: `true`)
306
+ - `--provider openai|nano|local|auto`
307
+
308
+ Behavior:
309
+
310
+ - Uses selection lock approved outputs as edit-base input (`role=base`) for each regenerated target.
311
+ - Preserves lock provenance in `provenance/run.json` (`regenerationSource` metadata) for traceability.
312
+ - For safety, selection-lock output paths must resolve inside the active `--out` root.
313
+
314
+ Example:
315
+
316
+ ```bash
317
+ lootforge regenerate --out assets/imagegen --edit true --ids player-idle
318
+ ```
319
+
320
+ ### `lootforge process`
321
+
322
+ Reads raw outputs, applies post-processing and acceptance checks, and writes:
323
+
324
+ - `<out>/assets/imagegen/processed/images/*` (or `<out>/processed/images/*` when `out` is already `assets/imagegen`)
325
+ - Compatibility mirror: `<out>/assets/images/*`
326
+ - `<out>/assets/imagegen/processed/catalog.json`
327
+ - `<out>/checks/image-acceptance-report.json`
328
+ - includes optional `packInvariants` summary (`errors`, `warnings`, `issues`, `metrics`)
329
+
330
+ Example:
331
+
332
+ ```bash
333
+ lootforge process --out assets/imagegen --strict true
334
+ ```
335
+
336
+ ### `lootforge atlas`
337
+
338
+ Reads generated images and atlas groups, then writes:
339
+
340
+ - `<out>/assets/atlases/manifest.json`
341
+ - Optional atlas sheets/json when TexturePacker is available
342
+
343
+ Example:
344
+
345
+ ```bash
346
+ lootforge atlas --out assets/imagegen
347
+ ```
348
+
349
+ ### `lootforge package`
350
+
351
+ Assembles shareable outputs under:
352
+
353
+ - `<out>/dist/packs/<pack-id>/...`
354
+ - `<out>/dist/packs/game-asset-pack-<pack-id>.zip`
355
+
356
+ Key flags:
357
+
358
+ - `--runtimes <list>` optional comma-separated runtime exports (`phaser,pixi,unity`)
359
+
360
+ Notes:
361
+
362
+ - Phaser manifest output is always emitted as baseline compatibility.
363
+
364
+ Example:
365
+
366
+ ```bash
367
+ lootforge package --out assets/imagegen --runtimes pixi,unity
368
+ ```
369
+
370
+ ### `lootforge serve`
371
+
372
+ Starts a local HTTP service wrapper for command execution (no auth/credit layer in core).
373
+
374
+ Key flags:
375
+
376
+ - `--host <host>` optional (default `127.0.0.1`)
377
+ - `--port <port>` optional (default `8744`)
378
+ - `--out <dir>` optional default output root used when request payload omits `out`
379
+ - `--max-active-jobs <number>` optional concurrent active tool limit before returning `429 service_busy` (default `2`)
380
+
381
+ Core endpoints:
382
+
383
+ - `GET /v1/health`
384
+ - `GET /v1/tools`
385
+ - `GET /v1/contracts/generation-request`
386
+ - `POST /v1/tools/:name`
387
+ - `POST /v1/:name` (alias)
388
+ - `POST /v1/generation/requests` (canonical request -> `plan` + `generate` mapping)
389
+
390
+ Notes:
391
+
392
+ - Service mode applies active-job backpressure and returns `429` with `error.code = "service_busy"` when at capacity.
393
+
394
+ Example:
395
+
396
+ ```bash
397
+ lootforge serve --host 127.0.0.1 --port 8744 --out assets/imagegen
398
+ ```
399
+
400
+ Service request/response contract details: `docs/SERVICE_MODE.md`
401
+
402
+ ### `lootforge eval`
403
+
404
+ Runs hard/soft quality scoring and writes:
405
+
406
+ - `<out>/checks/eval-report.json`
407
+ - `eval-report.json` includes adapter health telemetry:
408
+ - `adapterHealth.configured`: enabled adapters with command/URL configured
409
+ - `adapterHealth.active`: adapters that returned at least one successful result
410
+ - `adapterHealth.failed`: adapters that failed or were enabled but unconfigured
411
+ - `adapterHealth.adapters[]`: per-adapter mode, target attempt/success/fail counters, warnings
412
+ - `eval-report.json` also includes VLM gate traceability when enabled:
413
+ - `candidateVlm`: selected candidate VLM score/threshold/decision
414
+ - `candidateVlmGrades[]`: per-candidate VLM score, threshold, pass/fail, evaluator mode, and reason
415
+ - `eval-report.json` acceptance metrics include edge-aware alpha boundary signals:
416
+ - `alphaHaloRisk`
417
+ - `alphaStrayNoise`
418
+ - `alphaEdgeSharpness`
419
+ - `eval-report.json` may include a top-level `packInvariants` summary:
420
+ - `errors`, `warnings`, and issue list
421
+ - continuity metrics per animation (`maxSilhouetteDrift`, `maxAnchorDrift`)
422
+ - texture budget metrics by evaluation profile
423
+ - `eval-report.json` may include consistency-group drift summaries:
424
+ - `consistencyGroupSummary[]`: per-group warning/outlier counts, warned/outlier target ids, max outlier score, total ranking penalty, and metric medians
425
+ - `targets[].consistencyGroupOutlier`: per-target warning/penalty trace (`score`, thresholds, weight, reasons, metric deltas)
426
+
427
+ Optional CLIP/LPIPS/SSIM adapter execution:
428
+
429
+ - Enable adapters with:
430
+ - `LOOTFORGE_ENABLE_CLIP_ADAPTER=1`
431
+ - `LOOTFORGE_ENABLE_LPIPS_ADAPTER=1`
432
+ - `LOOTFORGE_ENABLE_SSIM_ADAPTER=1`
433
+ - Configure each enabled adapter with either:
434
+ - `LOOTFORGE_<NAME>_ADAPTER_CMD` (reads JSON from stdin and writes JSON to stdout)
435
+ - `LOOTFORGE_<NAME>_ADAPTER_URL` (HTTP endpoint accepting JSON POST and returning JSON)
436
+ - Adapter response contract:
437
+ - `{"metrics":{"alignment":0.82},"score":5}` or flat numeric JSON fields
438
+ - `score` is applied as additive soft-score bonus/penalty in eval ranking
439
+ - Timeout controls:
440
+ - Per-adapter: `LOOTFORGE_<NAME>_ADAPTER_TIMEOUT_MS`
441
+ - Global fallback: `LOOTFORGE_ADAPTER_TIMEOUT_MS`
442
+ - Reference docs and runnable examples:
443
+ - `docs/ADAPTER_CONTRACT.md`
444
+ - `examples/adapters/stdin-adapter-example.js`
445
+ - `examples/adapters/http-adapter-example.js`
446
+ - Adapter `referenceImages` payload paths are normalized to absolute paths under the active `--out` root.
447
+ - Optional VLM candidate hard gate:
448
+ - configure per target with `generationPolicy.vlmGate`
449
+ - evaluator transport:
450
+ - `LOOTFORGE_VLM_GATE_CMD` (stdin/stdout JSON)
451
+ - `LOOTFORGE_VLM_GATE_URL` (HTTP JSON POST)
452
+ - timeout override: `LOOTFORGE_VLM_GATE_TIMEOUT_MS`
453
+ - candidates below threshold are rejected before final candidate selection
454
+
455
+ Example:
456
+
457
+ ```bash
458
+ lootforge eval --out assets/imagegen --strict true
459
+ ```
460
+
461
+ ### `lootforge review`
462
+
463
+ Builds a review artifact from eval data:
464
+
465
+ - `<out>/review/review.html`
466
+ - Includes per-target score breakdown details (candidate reasons/metrics, VLM gate traces, and adapter components/metrics/warnings).
467
+
468
+ Example:
469
+
470
+ ```bash
471
+ lootforge review --out assets/imagegen
472
+ ```
473
+
474
+ ### `lootforge select`
475
+
476
+ Builds lockfile selections from provenance + eval:
477
+
478
+ - `<out>/locks/selection-lock.json`
479
+ - includes optional group-signal traceability fields per target when present in eval:
480
+ - `evalFinalScore`
481
+ - `groupSignalTrace` (`consistencyGroup`, `score`, thresholds, weight, penalty, reasons)
482
+
483
+ Example:
484
+
485
+ ```bash
486
+ lootforge select --out assets/imagegen
487
+ ```
488
+
489
+ ## Manifest (`version: "next"`)
490
+
491
+ Top-level fields:
492
+
493
+ - `version`: must be `next`
494
+ - `pack`: `{ id, version, license, author }` (required)
495
+ - `providers`: `{ default, openai?, nano?, local? }` (required)
496
+ - each provider may define runtime defaults: `endpoint`, `timeoutMs`, `maxRetries`, `minDelayMs`, `defaultConcurrency`
497
+ - `providers.local` may also define `baseUrl` (local endpoint alias)
498
+ - `styleKits[]` (required)
499
+ - directed-synthesis scaffolding:
500
+ - `styleReferenceImages[]?` (provider-specific style-image guidance inputs)
501
+ - `loraPath?`, `loraStrength?` (`0..2`, requires `loraPath`)
502
+ - `consistencyGroups[]` (optional)
503
+ - `evaluationProfiles[]` (required)
504
+ - optional `consistencyGroupScoring?`: `warningThreshold`, `penaltyThreshold`, `penaltyWeight`
505
+ - `atlas` options for packing defaults and per-group overrides
506
+ - `targets[]` (required)
507
+
508
+ `styleKits[].palettePath` behavior:
509
+
510
+ - When `target.palette` is unset, LootForge auto-loads colors from the style-kit palette file and applies them as the default exact palette policy.
511
+ - An explicit `target.palette` always takes precedence over style-kit defaults.
512
+
513
+ Per target:
514
+
515
+ - `id`, `kind`, `out`, `atlasGroup?`, `styleKitId`, `consistencyGroup`, `evaluationProfileId`
516
+ - `templateId?`: optional lookup into top-level `targetTemplates[]` for reusable orchestration policy
517
+ - `dependsOn?`: optional target-id list used to enforce dependency-aware generate ordering
518
+ - `styleReferenceFrom?`: optional target-id list for style-reference chaining from previously generated targets
519
+ - when omitted, `dependsOn` is used as the default style-reference chain
520
+ - `generationMode`: `text|edit-first`
521
+ - `edit-first` mode requires a provider with `image-edits` support (`openai`, `local`, and `nano` when using an image-edit-capable Gemini model)
522
+ - `edit.inputs[].path`: when used, must resolve inside the active `--out` root at runtime (`generate`, `eval`, and `regenerate`)
523
+ - `generationPolicy.background: "transparent"` requires a provider that supports transparent outputs (unsupported providers now fail validation)
524
+ - `generationPolicy.vlmGate?`: optional candidate gate (`threshold` defaults to `4` on a `0..5` scale, optional `rubric`)
525
+ - `generationPolicy.coarseToFine?`: optional promotion controls (`enabled`, `promoteTopK`, `minDraftScore`, `requireDraftAcceptance`)
526
+ - `generationPolicy.agenticRetry?`: optional self-healing edit-first loop controls (`enabled`, `maxRetries`)
527
+ - `generationPolicy.draftQuality` / `generationPolicy.finalQuality`: optional quality split used by coarse-pass and refinement-pass generation
528
+ - when coarse-to-fine is enabled, draft/intermediate promotion ranking uses local image metrics only; full VLM/soft-adapter scoring runs on final promoted refine candidates
529
+ - benchmark helper: `npm run benchmark:coarse-to-fine -- --baseline <baseline-run.json> --coarse <coarse-run.json>`
530
+ - outputs stage-weighted cost-per-approved comparisons from provenance runs
531
+ - directed-synthesis scaffolding:
532
+ - `controlImage?` with `controlMode?` (`canny|depth|openpose`) must be provided together
533
+ - `generationPolicy.highQuality?`
534
+ - `generationPolicy.hiresFix?` (`enabled?`, `upscale?`, `denoiseStrength?`)
535
+ - `prompt` (string or structured object) for non-spritesheet targets
536
+ - `provider?` (`openai|nano|local`)
537
+ - `acceptance`: `{ size, alpha, maxFileSizeKB }`
538
+ - optional generation/runtime fields (`generationPolicy`, `postProcess`, `runtimeSpec`, `model`, `edit`, `auxiliaryMaps`, `palette`, `tileable`, `seamThreshold`, `seamStripPx`, `seamHeal`, `wrapGrid`)
539
+ - `palette.strict` (exact mode only): enforces 100% visible-pixel compliance with the declared exact palette in process/acceptance/scoring.
540
+ - `seamHeal`: optional pass for tileables (`enabled`, `stripPx`, `strength`) applied during process before final encode.
541
+ - `wrapGrid`: optional per-cell tile validation (`columns`, `rows`, optional seam thresholds) enforced in image acceptance.
542
+ - post-process semantic controls:
543
+ - `postProcess.operations.smartCrop` (`enabled`, `mode: alpha-bounds|center`, `padding`)
544
+ - `postProcess.operations.pixelPerfect` (`enabled`, optional integer `scale`)
545
+ - `postProcess.operations.emitVariants` (`raw`, `styleRef`, `pixel`) for explicit `__raw` / `__style_ref` / `__pixel` outputs
546
+ - edge-aware boundary gates are configured via `evaluationProfiles[].hardGates`:
547
+ - `alphaHaloRiskMax` (`0..1`)
548
+ - `alphaStrayNoiseMax` (`0..1`)
549
+ - `alphaEdgeSharpnessMin` (`0..1`)
550
+ - pack-level hard gates are configured via `evaluationProfiles[].hardGates`:
551
+ - `packTextureBudgetMB` (`>0`)
552
+ - `spritesheetSilhouetteDriftMax` (`0..1`)
553
+ - `spritesheetAnchorDriftMax` (`0..1`)
554
+ - consistency-group warning and ranking influence controls are configured via `evaluationProfiles[].consistencyGroupScoring`:
555
+ - `warningThreshold` (`>0`)
556
+ - `penaltyThreshold` (`>0`)
557
+ - `penaltyWeight` (`>=0`)
558
+ - `kind: "spritesheet"` targets define `animations` and are expanded/assembled by the pipeline
559
+
560
+ Minimal example:
561
+
562
+ ```json
563
+ {
564
+ "version": "next",
565
+ "pack": {
566
+ "id": "my-pack",
567
+ "version": "0.1.0",
568
+ "license": "UNLICENSED",
569
+ "author": "you"
570
+ },
571
+ "providers": {
572
+ "default": "openai",
573
+ "openai": { "model": "gpt-image-1" },
574
+ "nano": { "model": "gemini-2.5-flash-image" },
575
+ "local": { "model": "sdxl-controlnet", "baseUrl": "http://127.0.0.1:8188" }
576
+ },
577
+ "styleKits": [
578
+ {
579
+ "id": "fantasy-topdown",
580
+ "rulesPath": "style/fantasy/style.md",
581
+ "palettePath": "style/fantasy/palette.txt",
582
+ "referenceImages": [],
583
+ "lightingModel": "top-left key with warm fill"
584
+ }
585
+ ],
586
+ "consistencyGroups": [
587
+ {
588
+ "id": "player-family",
589
+ "description": "Shared protagonist style and silhouette rules.",
590
+ "styleKitId": "fantasy-topdown",
591
+ "referenceImages": []
592
+ }
593
+ ],
594
+ "evaluationProfiles": [
595
+ {
596
+ "id": "sprite-quality",
597
+ "hardGates": {
598
+ "requireAlpha": true,
599
+ "maxFileSizeKB": 512,
600
+ "alphaHaloRiskMax": 0.08,
601
+ "alphaStrayNoiseMax": 0.01,
602
+ "alphaEdgeSharpnessMin": 0.8,
603
+ "packTextureBudgetMB": 48,
604
+ "spritesheetSilhouetteDriftMax": 0.2,
605
+ "spritesheetAnchorDriftMax": 0.15
606
+ }
607
+ }
608
+ ],
609
+ "targets": [
610
+ {
611
+ "id": "player-idle",
612
+ "kind": "sprite",
613
+ "out": "player-idle.png",
614
+ "atlasGroup": "actors",
615
+ "styleKitId": "fantasy-topdown",
616
+ "consistencyGroup": "player-family",
617
+ "evaluationProfileId": "sprite-quality",
618
+ "generationMode": "text",
619
+ "prompt": "Top-down sci-fi pilot idle sprite with clear silhouette.",
620
+ "postProcess": {
621
+ "resizeTo": "512x512",
622
+ "algorithm": "lanczos3",
623
+ "stripMetadata": true
624
+ },
625
+ "acceptance": {
626
+ "size": "512x512",
627
+ "alpha": true,
628
+ "maxFileSizeKB": 512
629
+ }
630
+ }
631
+ ]
632
+ }
633
+ ```
634
+
635
+ See also: `docs/manifest-schema.md`
636
+
637
+ Provider runtime precedence (`generate` / `regenerate`):
638
+
639
+ - target-level `generationPolicy.maxRetries` overrides provider retry defaults
640
+ - provider runtime defaults load from manifest `providers.<name>` config
641
+ - environment overrides can replace provider runtime defaults without manifest edits
642
+ - provider capability parity is enforced at startup (`supports(...)` must match declared capabilities)
643
+
644
+ ## Output Contract
645
+
646
+ `lootforge package` emits:
647
+
648
+ - `dist/packs/<pack-id>/assets/images/*`
649
+ - `dist/packs/<pack-id>/assets/atlases/*`
650
+ - `dist/packs/<pack-id>/manifest/asset-pack.json`
651
+ - `dist/packs/<pack-id>/manifest/phaser.json`
652
+ - `dist/packs/<pack-id>/manifest/pixi.json` (when requested via `--runtimes`)
653
+ - `dist/packs/<pack-id>/manifest/unity-import.json` (when requested via `--runtimes`)
654
+ - `dist/packs/<pack-id>/review/catalog.json`
655
+ - `dist/packs/<pack-id>/review/contact-sheet.png`
656
+ - `dist/packs/<pack-id>/provenance/run.json`
657
+ - `dist/packs/<pack-id>/checks/validation-report.json`
658
+ - `dist/packs/<pack-id>/checks/image-acceptance-report.json`
659
+ - `dist/packs/<pack-id>/checks/eval-report.json` (when available)
660
+ - `dist/packs/<pack-id>/provenance/selection-lock.json` (when available)
661
+ - `dist/packs/<pack-id>/review/review.html` (when available)
662
+ - `dist/packs/game-asset-pack-<pack-id>.zip`
663
+
664
+ Stage outputs during generation flow:
665
+
666
+ - `raw/` stage: generated provider outputs
667
+ - `processed/` stage: deterministic post-processed outputs + catalog
668
+ - compatibility mirror under `assets/images/`
669
+ - atlas reproducibility artifact: `assets/atlases/atlas-config.json`
670
+
671
+ ## Environment Variables
672
+
673
+ Provider keys:
674
+
675
+ - `OPENAI_API_KEY`: required for OpenAI generation
676
+ - `GEMINI_API_KEY`: required for Nano generation
677
+
678
+ Provider runtime overrides (env wins over manifest provider config):
679
+
680
+ - OpenAI:
681
+ - `LOOTFORGE_OPENAI_ENDPOINT` (or `OPENAI_IMAGES_ENDPOINT`)
682
+ - `LOOTFORGE_OPENAI_EDITS_ENDPOINT` (or `OPENAI_EDITS_ENDPOINT`)
683
+ - `LOOTFORGE_OPENAI_TIMEOUT_MS` (or `OPENAI_TIMEOUT_MS`)
684
+ - `LOOTFORGE_OPENAI_MAX_RETRIES` (or `OPENAI_MAX_RETRIES`)
685
+ - `LOOTFORGE_OPENAI_MIN_DELAY_MS` (or `OPENAI_MIN_DELAY_MS`)
686
+ - `LOOTFORGE_OPENAI_DEFAULT_CONCURRENCY` (or `OPENAI_DEFAULT_CONCURRENCY`)
687
+ - Nano/Gemini:
688
+ - `LOOTFORGE_NANO_ENDPOINT` (or `GEMINI_API_BASE`)
689
+ - `LOOTFORGE_NANO_TIMEOUT_MS` (or `GEMINI_TIMEOUT_MS`)
690
+ - `LOOTFORGE_NANO_MAX_RETRIES` (or `GEMINI_MAX_RETRIES`)
691
+ - `LOOTFORGE_NANO_MIN_DELAY_MS` (or `GEMINI_MIN_DELAY_MS`)
692
+ - `LOOTFORGE_NANO_DEFAULT_CONCURRENCY` (or `GEMINI_DEFAULT_CONCURRENCY`)
693
+ - Local diffusion:
694
+ - `LOOTFORGE_LOCAL_ENDPOINT` (or `LOCAL_DIFFUSION_BASE_URL`)
695
+ - `LOOTFORGE_LOCAL_TIMEOUT_MS` (or `LOCAL_DIFFUSION_TIMEOUT_MS`)
696
+ - `LOOTFORGE_LOCAL_MAX_RETRIES` (or `LOCAL_DIFFUSION_MAX_RETRIES`)
697
+ - `LOOTFORGE_LOCAL_MIN_DELAY_MS` (or `LOCAL_DIFFUSION_MIN_DELAY_MS`)
698
+ - `LOOTFORGE_LOCAL_DEFAULT_CONCURRENCY` (or `LOCAL_DIFFUSION_DEFAULT_CONCURRENCY`)
699
+
700
+ Eval adapter toggles:
701
+
702
+ - `LOOTFORGE_ENABLE_CLIP_ADAPTER`: enable CLIP adapter execution in `lootforge eval`
703
+ - `LOOTFORGE_ENABLE_LPIPS_ADAPTER`: enable LPIPS adapter execution in `lootforge eval`
704
+ - `LOOTFORGE_ENABLE_SSIM_ADAPTER`: enable SSIM adapter execution in `lootforge eval`
705
+
706
+ Eval adapter transports:
707
+
708
+ - `LOOTFORGE_CLIP_ADAPTER_CMD` or `LOOTFORGE_CLIP_ADAPTER_URL`
709
+ - `LOOTFORGE_LPIPS_ADAPTER_CMD` or `LOOTFORGE_LPIPS_ADAPTER_URL`
710
+ - `LOOTFORGE_SSIM_ADAPTER_CMD` or `LOOTFORGE_SSIM_ADAPTER_URL`
711
+
712
+ Eval adapter timeout controls:
713
+
714
+ - `LOOTFORGE_ADAPTER_TIMEOUT_MS`: global timeout (ms)
715
+ - `LOOTFORGE_<NAME>_ADAPTER_TIMEOUT_MS`: per-adapter timeout override (ms)
716
+
717
+ VLM gate transport:
718
+
719
+ - `LOOTFORGE_VLM_GATE_CMD`: command transport for VLM candidate gate scoring
720
+ - `LOOTFORGE_VLM_GATE_URL`: HTTP transport for VLM candidate gate scoring
721
+ - `LOOTFORGE_VLM_GATE_TIMEOUT_MS`: timeout override for VLM gate requests (ms)
722
+
723
+ Service mode:
724
+
725
+ - `LOOTFORGE_SERVICE_HOST`: default host for `lootforge serve`
726
+ - `LOOTFORGE_SERVICE_PORT`: default port for `lootforge serve`
727
+ - `LOOTFORGE_SERVICE_OUT`: default output root injected when service payload omits `out`
728
+
729
+ No network keys are required for `init`, `plan`, `validate`, `atlas`, or `package`.
730
+
731
+ ## Development
732
+
733
+ Local verification commands:
734
+
735
+ - `npm run check`
736
+ - `npm run build`
737
+ - `npm test`
738
+ - `npm run test:unit`
739
+ - `npm run test:integration`
740
+ - `npm run test:coverage:full`
741
+ - `npm run check:release`
742
+
743
+ `0.3.0` release-train branch policy:
744
+
745
+ - Keep `main` release-only until `0.3.0` is ready to cut.
746
+ - Use `release/0.3` as the integration branch for ongoing work.
747
+ - Branch feature work from `release/0.3` and PR back into `release/0.3`.
748
+ - Release by PR `release/0.3 -> main`, then tag `v0.3.0`.
749
+
750
+ ## Status / Roadmap
751
+
752
+ `0.3.0` (`Tempered Steel`) is the active release train for the next public cut.
753
+
754
+ Release roadmap:
755
+
756
+ - `0.2.0` (`Emberforge`): public beta foundation (edit/regenerate workflow, score transparency, tile/palette reliability)
757
+ - `0.3.0` (`Tempered Steel`): control and consistency upgrades (group-level drift scoring, provider edit parity)
758
+ - `0.4.0` (`Anvilheart`): local production path (ControlNet contracts + LoRA/provenance maturity)
759
+ - `0.5.0` (`Runesmelter`): team scale and integration maturity (CI regressions + broader runtime export presets)
760
+ - `1.0.0` (`Mythic Foundry`): GA contract stabilization and public operational readiness
761
+
762
+ See `docs/ROADMAP.md` for detailed scope, per-version `Upcoming` vs `Future` queues, exit criteria, and cross-version trackers.
763
+ See `docs/ENGINE_TARGETING.md` for framework market/compatibility analysis and runtime export strategy.
764
+ See `CHANGELOG.md` for versioned release notes and `docs/RELEASE_WORKFLOW.md` for release/changelog/showcase maintenance.