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
@@ -0,0 +1,663 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { z } from "zod";
3
+ import { AcceptanceSchema, AgenticRetryBaseSchema, AuxiliaryMapsSchema, CoarseToFineBaseSchema, ControlModeSchema, EditSchema, FacingDirectionSchema, GenerationModeSchema, HiresFixSchema, nonEmptyString, PalettePolicyBaseSchema, PromptSpecBaseShape, ProviderNameSchema, RuntimeSpecBaseSchema, ScoreWeightsSchema, VlmGateSchema, } from "../shared/schemas.js";
4
+ import { formatIssuePath as formatPathBase } from "../shared/zod.js";
5
+ const promptSpecSchema = z.object(PromptSpecBaseShape);
6
+ const generationPolicySchema = z.object({
7
+ size: nonEmptyString,
8
+ quality: nonEmptyString,
9
+ draftQuality: nonEmptyString.optional(),
10
+ finalQuality: nonEmptyString.optional(),
11
+ background: nonEmptyString,
12
+ outputFormat: z.enum(["png", "jpeg", "webp"]),
13
+ highQuality: z.boolean().optional(),
14
+ hiresFix: HiresFixSchema.optional(),
15
+ candidates: z.number().int().min(1),
16
+ maxRetries: z.number().int().min(0),
17
+ fallbackProviders: z.array(ProviderNameSchema),
18
+ providerConcurrency: z.number().int().positive().optional(),
19
+ rateLimitPerMinute: z.number().int().positive().optional(),
20
+ vlmGate: VlmGateSchema.optional(),
21
+ coarseToFine: CoarseToFineBaseSchema.extend({
22
+ enabled: z.boolean(),
23
+ promoteTopK: z.number().int().min(1),
24
+ requireDraftAcceptance: z.boolean(),
25
+ }).optional(),
26
+ agenticRetry: AgenticRetryBaseSchema.extend({
27
+ enabled: z.boolean(),
28
+ maxRetries: z.number().int().min(0),
29
+ }).optional(),
30
+ });
31
+ const resizeVariantSchema = z.object({
32
+ name: nonEmptyString,
33
+ width: z.number().int().positive(),
34
+ height: z.number().int().positive(),
35
+ algorithm: z.enum(["nearest", "lanczos3"]).optional(),
36
+ });
37
+ const postProcessSchema = z.object({
38
+ resizeTo: z
39
+ .object({
40
+ width: z.number().int().positive(),
41
+ height: z.number().int().positive(),
42
+ })
43
+ .optional(),
44
+ algorithm: z.enum(["nearest", "lanczos3"]).optional(),
45
+ stripMetadata: z.boolean().optional(),
46
+ pngPaletteColors: z.number().int().min(2).max(256).optional(),
47
+ operations: z
48
+ .object({
49
+ trim: z
50
+ .object({
51
+ enabled: z.boolean().optional(),
52
+ threshold: z.number().min(0).max(255).optional(),
53
+ })
54
+ .optional(),
55
+ pad: z
56
+ .object({
57
+ pixels: z.number().int().min(0),
58
+ extrude: z.boolean().optional(),
59
+ background: nonEmptyString.optional(),
60
+ })
61
+ .optional(),
62
+ quantize: z
63
+ .object({
64
+ colors: z.number().int().min(2).max(256),
65
+ dither: z.number().min(0).max(1).optional(),
66
+ })
67
+ .optional(),
68
+ outline: z
69
+ .object({
70
+ size: z.number().int().min(1).max(64),
71
+ color: nonEmptyString.optional(),
72
+ })
73
+ .optional(),
74
+ resizeVariants: z
75
+ .object({
76
+ variants: z.array(resizeVariantSchema),
77
+ })
78
+ .optional(),
79
+ pixelPerfect: z
80
+ .object({
81
+ enabled: z.boolean().optional(),
82
+ scale: z.number().int().min(1).max(16).optional(),
83
+ })
84
+ .optional(),
85
+ smartCrop: z
86
+ .object({
87
+ enabled: z.boolean().optional(),
88
+ mode: z.enum(["alpha-bounds", "center"]).optional(),
89
+ padding: z.number().int().min(0).max(256).optional(),
90
+ })
91
+ .optional(),
92
+ emitVariants: z
93
+ .object({
94
+ raw: z.boolean().optional(),
95
+ pixel: z.boolean().optional(),
96
+ styleRef: z.boolean().optional(),
97
+ layerColor: z.boolean().optional(),
98
+ layerMatte: z.boolean().optional(),
99
+ })
100
+ .optional(),
101
+ })
102
+ .optional(),
103
+ });
104
+ const regenerationSourceSchema = z.object({
105
+ mode: z.enum(["selection-lock", "selection-lock-edit"]),
106
+ selectionLockPath: nonEmptyString,
107
+ selectionLockGeneratedAt: nonEmptyString.optional(),
108
+ lockInputHash: nonEmptyString,
109
+ lockSelectedOutputPath: nonEmptyString,
110
+ });
111
+ const plannedTargetSchema = z.object({
112
+ id: nonEmptyString,
113
+ kind: nonEmptyString.optional(),
114
+ out: nonEmptyString,
115
+ templateId: nonEmptyString.optional(),
116
+ dependsOn: z.array(nonEmptyString).optional(),
117
+ styleReferenceFrom: z.array(nonEmptyString).optional(),
118
+ atlasGroup: z.union([nonEmptyString, z.null()]).optional(),
119
+ styleKitId: nonEmptyString.optional(),
120
+ styleReferenceImages: z.array(nonEmptyString).optional(),
121
+ loraPath: nonEmptyString.optional(),
122
+ loraStrength: z.number().min(0).max(2).optional(),
123
+ visualStylePolicy: z
124
+ .object({
125
+ lineContrastMin: z.number().min(0).max(1).optional(),
126
+ shadingBandCountMax: z.number().int().min(1).max(256).optional(),
127
+ uiRectilinearityMin: z.number().min(0).max(1).optional(),
128
+ })
129
+ .optional(),
130
+ consistencyGroup: nonEmptyString.optional(),
131
+ consistencyGroupScoring: z
132
+ .object({
133
+ warningThreshold: z.number().positive().optional(),
134
+ penaltyThreshold: z.number().positive().optional(),
135
+ penaltyWeight: z.number().min(0).optional(),
136
+ })
137
+ .optional(),
138
+ generationMode: GenerationModeSchema.optional(),
139
+ evaluationProfileId: nonEmptyString.optional(),
140
+ scoringProfile: nonEmptyString.optional(),
141
+ controlImage: nonEmptyString.optional(),
142
+ controlMode: ControlModeSchema.optional(),
143
+ facing: FacingDirectionSchema.optional(),
144
+ scoreWeights: ScoreWeightsSchema.optional(),
145
+ tileable: z.boolean().optional(),
146
+ seamThreshold: z.number().optional(),
147
+ seamStripPx: z.number().int().positive().optional(),
148
+ alphaHaloRiskMax: z.number().min(0).max(1).optional(),
149
+ alphaStrayNoiseMax: z.number().min(0).max(1).optional(),
150
+ alphaEdgeSharpnessMin: z.number().min(0).max(1).optional(),
151
+ mattingHiddenRgbLeakMax: z.number().min(0).max(1).optional(),
152
+ mattingMaskConsistencyMin: z.number().min(0).max(1).optional(),
153
+ mattingSemiTransparencyRatioMax: z.number().min(0).max(1).optional(),
154
+ packTextureBudgetMB: z.number().positive().optional(),
155
+ spritesheetSilhouetteDriftMax: z.number().min(0).max(1).optional(),
156
+ spritesheetAnchorDriftMax: z.number().min(0).max(1).optional(),
157
+ spritesheetIdentityDriftMax: z.number().min(0).max(1).optional(),
158
+ spritesheetPoseDriftMax: z.number().min(0).max(1).optional(),
159
+ spritesheetWalkLowerBodyMotionMin: z.number().min(0).max(1).optional(),
160
+ spritesheetWalkFootMotionMin: z.number().min(0).max(1).optional(),
161
+ spritesheetWalkFootToUpperMotionRatioMin: z.number().positive().optional(),
162
+ seamHeal: z
163
+ .object({
164
+ enabled: z.boolean().optional(),
165
+ stripPx: z.number().int().positive().optional(),
166
+ strength: z.number().min(0).max(1).optional(),
167
+ })
168
+ .optional(),
169
+ wrapGrid: z
170
+ .object({
171
+ columns: z.number().int().positive(),
172
+ rows: z.number().int().positive(),
173
+ seamThreshold: z.number().optional(),
174
+ seamStripPx: z.number().int().positive().optional(),
175
+ topology: z
176
+ .object({
177
+ mode: z.enum(["self", "one-to-one", "many-to-many"]),
178
+ maxMismatchRatio: z.number().min(0).max(1).optional(),
179
+ colorTolerance: z.number().int().min(0).max(255).optional(),
180
+ })
181
+ .optional(),
182
+ })
183
+ .optional(),
184
+ palette: PalettePolicyBaseSchema.optional(),
185
+ generationDisabled: z.boolean().optional(),
186
+ catalogDisabled: z.boolean().optional(),
187
+ spritesheet: z
188
+ .object({
189
+ sheetTargetId: nonEmptyString,
190
+ isSheet: z.boolean().optional(),
191
+ animations: z
192
+ .array(z.object({
193
+ name: nonEmptyString,
194
+ count: z.number().int().positive(),
195
+ fps: z.number().optional(),
196
+ loop: z.boolean().optional(),
197
+ facing: FacingDirectionSchema.optional(),
198
+ pivot: z
199
+ .object({
200
+ x: z.number(),
201
+ y: z.number(),
202
+ })
203
+ .optional(),
204
+ }))
205
+ .optional(),
206
+ animationName: nonEmptyString.optional(),
207
+ facing: FacingDirectionSchema.optional(),
208
+ frameIndex: z.number().int().min(0).optional(),
209
+ frameCount: z.number().int().positive().optional(),
210
+ fps: z.number().optional(),
211
+ loop: z.boolean().optional(),
212
+ pivot: z
213
+ .object({
214
+ x: z.number(),
215
+ y: z.number(),
216
+ })
217
+ .optional(),
218
+ })
219
+ .optional(),
220
+ acceptance: AcceptanceSchema.optional(),
221
+ runtimeSpec: RuntimeSpecBaseSchema.optional(),
222
+ promptSpec: promptSpecSchema,
223
+ generationPolicy: generationPolicySchema.optional(),
224
+ postProcess: postProcessSchema.optional(),
225
+ provider: ProviderNameSchema.optional(),
226
+ model: nonEmptyString.optional(),
227
+ edit: EditSchema.optional(),
228
+ regenerationSource: regenerationSourceSchema.optional(),
229
+ auxiliaryMaps: AuxiliaryMapsSchema.optional(),
230
+ });
231
+ const candidateScoreSchema = z.object({
232
+ outputPath: nonEmptyString,
233
+ score: z.number(),
234
+ passedAcceptance: z.boolean(),
235
+ reasons: z.array(nonEmptyString),
236
+ stage: z.enum(["draft", "refine", "autocorrect"]).optional(),
237
+ promoted: z.boolean().optional(),
238
+ sourceOutputPath: nonEmptyString.optional(),
239
+ autoCorrectAttempt: z.number().int().min(1).optional(),
240
+ components: z.record(z.number()).optional(),
241
+ metrics: z.record(z.number()).optional(),
242
+ vlm: z
243
+ .object({
244
+ score: z.number().min(0).max(5),
245
+ threshold: z.number().min(0).max(5),
246
+ maxScore: z.number().min(1),
247
+ passed: z.boolean(),
248
+ reason: nonEmptyString,
249
+ rubric: nonEmptyString.optional(),
250
+ evaluator: z.enum(["command", "http"]),
251
+ })
252
+ .optional(),
253
+ warnings: z.array(nonEmptyString).optional(),
254
+ selected: z.boolean().optional(),
255
+ });
256
+ const packInvariantIssueSchema = z.object({
257
+ level: z.enum(["error", "warning"]),
258
+ code: nonEmptyString,
259
+ message: nonEmptyString,
260
+ targetIds: z.array(nonEmptyString).min(1),
261
+ evaluationProfileId: nonEmptyString.optional(),
262
+ metrics: z.record(z.number()).optional(),
263
+ });
264
+ const packInvariantSummarySchema = z.object({
265
+ errors: z.number().int().min(0),
266
+ warnings: z.number().int().min(0),
267
+ issues: z.array(packInvariantIssueSchema),
268
+ metrics: z
269
+ .object({
270
+ textureBudgetMBByProfile: z
271
+ .record(z.object({
272
+ estimatedMB: z.number(),
273
+ budgetMB: z.number().optional(),
274
+ targetCount: z.number().int().min(0),
275
+ }))
276
+ .optional(),
277
+ spritesheetContinuityByAnimation: z
278
+ .record(z.object({
279
+ comparisons: z.number().int().min(0),
280
+ maxSilhouetteDrift: z.number(),
281
+ maxAnchorDrift: z.number(),
282
+ maxIdentityDrift: z.number().optional(),
283
+ maxPoseDrift: z.number().optional(),
284
+ maxUpperBodyMotionDrift: z.number().optional(),
285
+ maxLowerBodyMotionDrift: z.number().optional(),
286
+ maxFootMotionDrift: z.number().optional(),
287
+ }))
288
+ .optional(),
289
+ })
290
+ .optional(),
291
+ });
292
+ const stageArtifactSchemas = {
293
+ "targets-index": z.object({
294
+ generatedAt: nonEmptyString.optional(),
295
+ manifestPath: nonEmptyString.optional(),
296
+ targets: z.array(plannedTargetSchema).min(1),
297
+ }),
298
+ "provenance-run": z.object({
299
+ runId: nonEmptyString,
300
+ inputHash: nonEmptyString,
301
+ startedAt: nonEmptyString,
302
+ finishedAt: nonEmptyString,
303
+ generatedAt: nonEmptyString,
304
+ jobs: z.array(z.object({
305
+ jobId: nonEmptyString,
306
+ provider: ProviderNameSchema,
307
+ model: nonEmptyString,
308
+ targetId: nonEmptyString,
309
+ inputHash: nonEmptyString,
310
+ startedAt: nonEmptyString,
311
+ finishedAt: nonEmptyString,
312
+ outputPath: nonEmptyString,
313
+ bytesWritten: z.number().int().min(0).optional(),
314
+ skipped: z.boolean().optional(),
315
+ candidateOutputs: z
316
+ .array(z.object({
317
+ outputPath: nonEmptyString,
318
+ bytesWritten: z.number().int().min(0),
319
+ }))
320
+ .optional(),
321
+ candidateScores: z.array(candidateScoreSchema).optional(),
322
+ coarseToFine: z
323
+ .object({
324
+ enabled: z.boolean(),
325
+ draftQuality: nonEmptyString,
326
+ finalQuality: nonEmptyString,
327
+ promoteTopK: z.number().int().min(1),
328
+ minDraftScore: z.number().optional(),
329
+ requireDraftAcceptance: z.boolean(),
330
+ draftCandidateCount: z.number().int().min(0),
331
+ promoted: z.array(z.object({
332
+ outputPath: nonEmptyString,
333
+ score: z.number(),
334
+ passedAcceptance: z.boolean(),
335
+ refinedOutputPath: nonEmptyString.optional(),
336
+ })),
337
+ discarded: z.array(z.object({
338
+ outputPath: nonEmptyString,
339
+ score: z.number(),
340
+ passedAcceptance: z.boolean(),
341
+ reason: nonEmptyString,
342
+ })),
343
+ skippedReason: nonEmptyString.optional(),
344
+ warnings: z.array(nonEmptyString).optional(),
345
+ })
346
+ .optional(),
347
+ agenticRetry: z
348
+ .object({
349
+ enabled: z.boolean(),
350
+ maxRetries: z.number().int().min(0),
351
+ attempted: z.number().int().min(0),
352
+ succeeded: z.boolean(),
353
+ skippedReason: nonEmptyString.optional(),
354
+ attempts: z.array(z.object({
355
+ attempt: z.number().int().min(1),
356
+ sourceOutputPath: nonEmptyString,
357
+ outputPath: nonEmptyString,
358
+ critique: nonEmptyString,
359
+ triggeredBy: z.array(nonEmptyString),
360
+ scoreBefore: z.number(),
361
+ scoreAfter: z.number(),
362
+ passedBefore: z.boolean(),
363
+ passedAfter: z.boolean(),
364
+ reasonsBefore: z.array(nonEmptyString),
365
+ reasonsAfter: z.array(nonEmptyString),
366
+ })),
367
+ })
368
+ .optional(),
369
+ styleReferenceLineage: z
370
+ .array(z.object({
371
+ source: z.enum(["style-kit", "target-output"]),
372
+ reference: nonEmptyString,
373
+ sourceTargetId: nonEmptyString.optional(),
374
+ resolvedPath: nonEmptyString.optional(),
375
+ }))
376
+ .optional(),
377
+ generationMode: GenerationModeSchema.optional(),
378
+ edit: EditSchema.optional(),
379
+ regenerationSource: regenerationSourceSchema.optional(),
380
+ warnings: z.array(nonEmptyString).optional(),
381
+ })),
382
+ failures: z
383
+ .array(z.object({
384
+ targetId: nonEmptyString,
385
+ provider: ProviderNameSchema,
386
+ attemptedProviders: z.array(ProviderNameSchema),
387
+ message: nonEmptyString,
388
+ }))
389
+ .optional(),
390
+ }),
391
+ "acceptance-report": z.object({
392
+ generatedAt: nonEmptyString,
393
+ imagesDir: nonEmptyString,
394
+ strict: z.boolean(),
395
+ total: z.number().int().min(0),
396
+ passed: z.number().int().min(0),
397
+ failed: z.number().int().min(0),
398
+ errors: z.number().int().min(0),
399
+ warnings: z.number().int().min(0),
400
+ packInvariants: packInvariantSummarySchema.optional(),
401
+ items: z.array(z.object({
402
+ targetId: nonEmptyString,
403
+ out: nonEmptyString,
404
+ imagePath: nonEmptyString,
405
+ exists: z.boolean(),
406
+ width: z.number().int().positive().optional(),
407
+ height: z.number().int().positive().optional(),
408
+ format: nonEmptyString.optional(),
409
+ sizeBytes: z.number().int().min(0).optional(),
410
+ hasAlphaChannel: z.boolean().optional(),
411
+ hasTransparentPixels: z.boolean().optional(),
412
+ metrics: z
413
+ .object({
414
+ seamScore: z.number().optional(),
415
+ seamStripPx: z.number().optional(),
416
+ wrapGridColumns: z.number().optional(),
417
+ wrapGridRows: z.number().optional(),
418
+ wrapGridSeamScore: z.number().optional(),
419
+ wrapGridSeamStripPx: z.number().optional(),
420
+ wrapGridTopologyComparisons: z.number().optional(),
421
+ wrapGridTopologyMismatchRatio: z.number().optional(),
422
+ wrapGridTopologyThreshold: z.number().optional(),
423
+ wrapGridTopologyColorTolerance: z.number().optional(),
424
+ styleLineContrast: z.number().optional(),
425
+ styleShadingBandCount: z.number().optional(),
426
+ styleUiRectilinearity: z.number().optional(),
427
+ mattingMaskCoverage: z.number().optional(),
428
+ mattingSemiTransparencyRatio: z.number().optional(),
429
+ mattingMaskConsistency: z.number().optional(),
430
+ mattingHiddenRgbLeak: z.number().optional(),
431
+ paletteCompliance: z.number().optional(),
432
+ distinctColors: z.number().optional(),
433
+ alphaBoundaryPixels: z.number().optional(),
434
+ alphaHaloRisk: z.number().optional(),
435
+ alphaStrayNoise: z.number().optional(),
436
+ alphaEdgeSharpness: z.number().optional(),
437
+ })
438
+ .optional(),
439
+ issues: z.array(z.object({
440
+ level: z.enum(["error", "warning"]),
441
+ code: nonEmptyString,
442
+ targetId: nonEmptyString,
443
+ imagePath: nonEmptyString,
444
+ message: nonEmptyString,
445
+ })),
446
+ })),
447
+ }),
448
+ "eval-report": z.object({
449
+ generatedAt: nonEmptyString,
450
+ strict: z.boolean(),
451
+ imagesDir: nonEmptyString,
452
+ targetCount: z.number().int().min(0),
453
+ passed: z.number().int().min(0),
454
+ failed: z.number().int().min(0),
455
+ hardErrors: z.number().int().min(0),
456
+ adaptersUsed: z.array(z.enum(["clip", "lpips", "ssim"])),
457
+ adapterHealth: z.object({
458
+ configured: z.array(z.enum(["clip", "lpips", "ssim"])),
459
+ active: z.array(z.enum(["clip", "lpips", "ssim"])),
460
+ failed: z.array(z.enum(["clip", "lpips", "ssim"])),
461
+ adapters: z.array(z.object({
462
+ name: z.enum(["clip", "lpips", "ssim"]),
463
+ mode: z.enum(["command", "http", "unconfigured"]),
464
+ configured: z.boolean(),
465
+ active: z.boolean(),
466
+ failed: z.boolean(),
467
+ attemptedTargets: z.number().int().min(0),
468
+ successfulTargets: z.number().int().min(0),
469
+ failedTargets: z.number().int().min(0),
470
+ warningCount: z.number().int().min(0),
471
+ warnings: z.array(nonEmptyString),
472
+ })),
473
+ }),
474
+ adapterWarnings: z.array(nonEmptyString),
475
+ consistencyGroupSummary: z
476
+ .array(z.object({
477
+ consistencyGroup: nonEmptyString,
478
+ targetCount: z.number().int().min(0),
479
+ evaluatedTargetCount: z.number().int().min(0),
480
+ warningTargetIds: z.array(nonEmptyString),
481
+ outlierTargetIds: z.array(nonEmptyString),
482
+ warningCount: z.number().int().min(0),
483
+ outlierCount: z.number().int().min(0),
484
+ maxScore: z.number(),
485
+ totalPenalty: z.number().int().min(0),
486
+ metricMedians: z.record(z.number()),
487
+ }))
488
+ .optional(),
489
+ packInvariants: packInvariantSummarySchema.optional(),
490
+ targets: z.array(z.object({
491
+ targetId: nonEmptyString,
492
+ out: nonEmptyString,
493
+ consistencyGroup: nonEmptyString.optional(),
494
+ passedHardGates: z.boolean(),
495
+ hardGateErrors: z.array(nonEmptyString),
496
+ hardGateWarnings: z.array(nonEmptyString),
497
+ acceptanceMetrics: z.record(z.number()).optional(),
498
+ candidateScore: z.number().optional(),
499
+ candidateReasons: z.array(nonEmptyString).optional(),
500
+ candidateMetrics: z.record(z.number()).optional(),
501
+ candidateVlm: z
502
+ .object({
503
+ score: z.number().min(0).max(5),
504
+ threshold: z.number().min(0).max(5),
505
+ maxScore: z.number().min(1),
506
+ passed: z.boolean(),
507
+ reason: nonEmptyString,
508
+ rubric: nonEmptyString.optional(),
509
+ evaluator: z.enum(["command", "http"]),
510
+ })
511
+ .optional(),
512
+ candidateVlmGrades: z
513
+ .array(z.object({
514
+ outputPath: nonEmptyString,
515
+ selected: z.boolean(),
516
+ score: z.number().min(0).max(5),
517
+ threshold: z.number().min(0).max(5),
518
+ maxScore: z.number().min(1),
519
+ passed: z.boolean(),
520
+ reason: nonEmptyString,
521
+ rubric: nonEmptyString.optional(),
522
+ evaluator: z.enum(["command", "http"]),
523
+ }))
524
+ .optional(),
525
+ adapterMetrics: z.record(z.number()).optional(),
526
+ adapterScore: z.number().optional(),
527
+ adapterScoreComponents: z.record(z.number()).optional(),
528
+ adapterWarnings: z.array(nonEmptyString).optional(),
529
+ consistencyGroupOutlier: z
530
+ .object({
531
+ score: z.number(),
532
+ warningThreshold: z.number(),
533
+ threshold: z.number(),
534
+ penaltyThreshold: z.number(),
535
+ penaltyWeight: z.number(),
536
+ warned: z.boolean(),
537
+ penalty: z.number().int().min(0),
538
+ reasons: z.array(nonEmptyString),
539
+ metricDeltas: z.record(z.number()),
540
+ })
541
+ .optional(),
542
+ finalScore: z.number(),
543
+ })),
544
+ }),
545
+ "selection-lock": z.object({
546
+ generatedAt: nonEmptyString,
547
+ evalReportPath: nonEmptyString,
548
+ provenancePath: nonEmptyString,
549
+ targets: z.array(z.object({
550
+ targetId: nonEmptyString,
551
+ approved: z.boolean(),
552
+ inputHash: nonEmptyString,
553
+ selectedOutputPath: nonEmptyString,
554
+ provider: ProviderNameSchema.optional(),
555
+ model: nonEmptyString.optional(),
556
+ score: z.number().optional(),
557
+ evalFinalScore: z.number().optional(),
558
+ groupSignalTrace: z
559
+ .object({
560
+ consistencyGroup: nonEmptyString,
561
+ score: z.number(),
562
+ warningThreshold: z.number(),
563
+ penaltyThreshold: z.number(),
564
+ penaltyWeight: z.number(),
565
+ warned: z.boolean(),
566
+ penalty: z.number().int().min(0),
567
+ reasons: z.array(nonEmptyString),
568
+ metricDeltas: z.record(z.number()),
569
+ })
570
+ .optional(),
571
+ })),
572
+ }),
573
+ };
574
+ export const STAGE_ARTIFACT_CONTRACT_VERSION = "0.3.0-stage-contract-v1";
575
+ export class StageArtifactContractError extends Error {
576
+ code;
577
+ kind;
578
+ artifactPath;
579
+ diagnostics;
580
+ constructor(init) {
581
+ const first = init.diagnostics[0];
582
+ super(first
583
+ ? `[${init.code}] ${init.kind} failed at ${first.path}: ${first.message}`
584
+ : `[${init.code}] ${init.kind} validation failed.`);
585
+ this.name = "StageArtifactContractError";
586
+ this.code = init.code;
587
+ this.kind = init.kind;
588
+ this.artifactPath = init.artifactPath;
589
+ this.diagnostics = init.diagnostics;
590
+ this.cause = init.cause;
591
+ }
592
+ }
593
+ export function validateStageArtifact(kind, value, artifactPath) {
594
+ const schema = stageArtifactSchemas[kind];
595
+ const parsed = schema.safeParse(value);
596
+ if (!parsed.success) {
597
+ throw new StageArtifactContractError({
598
+ code: "stage_artifact_contract_invalid",
599
+ kind,
600
+ artifactPath,
601
+ diagnostics: parsed.error.issues.map((issue) => ({
602
+ path: formatIssuePath(issue.path),
603
+ code: issue.code,
604
+ message: issue.message,
605
+ })),
606
+ });
607
+ }
608
+ return parsed.data;
609
+ }
610
+ export async function readAndValidateStageArtifact(kind, artifactPath) {
611
+ let raw;
612
+ try {
613
+ raw = await readFile(artifactPath, "utf8");
614
+ }
615
+ catch (error) {
616
+ throw new StageArtifactContractError({
617
+ code: "stage_artifact_json_invalid",
618
+ kind,
619
+ artifactPath,
620
+ diagnostics: [
621
+ {
622
+ path: "$",
623
+ code: "read_error",
624
+ message: error instanceof Error
625
+ ? error.message
626
+ : `Unable to read artifact file: ${String(error)}`,
627
+ },
628
+ ],
629
+ cause: error,
630
+ });
631
+ }
632
+ let parsed;
633
+ try {
634
+ parsed = JSON.parse(raw);
635
+ }
636
+ catch (error) {
637
+ throw new StageArtifactContractError({
638
+ code: "stage_artifact_json_invalid",
639
+ kind,
640
+ artifactPath,
641
+ diagnostics: [
642
+ {
643
+ path: "$",
644
+ code: "invalid_json",
645
+ message: error instanceof Error ? error.message : `Unable to parse JSON: ${String(error)}`,
646
+ },
647
+ ],
648
+ cause: error,
649
+ });
650
+ }
651
+ return validateStageArtifact(kind, parsed, artifactPath);
652
+ }
653
+ function formatIssuePath(pathItems) {
654
+ if (pathItems.length === 0) {
655
+ return "$";
656
+ }
657
+ const base = formatPathBase(pathItems);
658
+ if (typeof pathItems[0] === "string") {
659
+ return base.startsWith("[") ? `$${base}` : `$.${base}`;
660
+ }
661
+ return base;
662
+ }
663
+ //# sourceMappingURL=stageArtifacts.js.map