@skyphusion-labs/vivijure-core 0.9.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 (267) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +87 -0
  3. package/dist/audio-routing.d.ts +2 -0
  4. package/dist/audio-routing.d.ts.map +1 -0
  5. package/dist/audio-routing.js +4 -0
  6. package/dist/audio-routing.js.map +1 -0
  7. package/dist/audio-stage.d.ts +4 -0
  8. package/dist/audio-stage.d.ts.map +1 -0
  9. package/dist/audio-stage.js +25 -0
  10. package/dist/audio-stage.js.map +1 -0
  11. package/dist/beat-analyze.d.ts +22 -0
  12. package/dist/beat-analyze.d.ts.map +1 -0
  13. package/dist/beat-analyze.js +111 -0
  14. package/dist/beat-analyze.js.map +1 -0
  15. package/dist/beat-sync-types.d.ts +33 -0
  16. package/dist/beat-sync-types.d.ts.map +1 -0
  17. package/dist/beat-sync-types.js +4 -0
  18. package/dist/beat-sync-types.js.map +1 -0
  19. package/dist/bundle-assembler.d.ts +54 -0
  20. package/dist/bundle-assembler.d.ts.map +1 -0
  21. package/dist/bundle-assembler.js +376 -0
  22. package/dist/bundle-assembler.js.map +1 -0
  23. package/dist/bundle-durations.d.ts +5 -0
  24. package/dist/bundle-durations.d.ts.map +1 -0
  25. package/dist/bundle-durations.js +68 -0
  26. package/dist/bundle-durations.js.map +1 -0
  27. package/dist/bundle-storyboard.d.ts +11 -0
  28. package/dist/bundle-storyboard.d.ts.map +1 -0
  29. package/dist/bundle-storyboard.js +82 -0
  30. package/dist/bundle-storyboard.js.map +1 -0
  31. package/dist/captions.d.ts +25 -0
  32. package/dist/captions.d.ts.map +1 -0
  33. package/dist/captions.js +56 -0
  34. package/dist/captions.js.map +1 -0
  35. package/dist/cast-db.d.ts +61 -0
  36. package/dist/cast-db.d.ts.map +1 -0
  37. package/dist/cast-db.js +324 -0
  38. package/dist/cast-db.js.map +1 -0
  39. package/dist/cast-lora-train.d.ts +18 -0
  40. package/dist/cast-lora-train.d.ts.map +1 -0
  41. package/dist/cast-lora-train.js +215 -0
  42. package/dist/cast-lora-train.js.map +1 -0
  43. package/dist/cast-loras.d.ts +21 -0
  44. package/dist/cast-loras.d.ts.map +1 -0
  45. package/dist/cast-loras.js +69 -0
  46. package/dist/cast-loras.js.map +1 -0
  47. package/dist/clip-content-validate.d.ts +43 -0
  48. package/dist/clip-content-validate.d.ts.map +1 -0
  49. package/dist/clip-content-validate.js +115 -0
  50. package/dist/clip-content-validate.js.map +1 -0
  51. package/dist/clip-job-model.d.ts +42 -0
  52. package/dist/clip-job-model.d.ts.map +1 -0
  53. package/dist/clip-job-model.js +8 -0
  54. package/dist/clip-job-model.js.map +1 -0
  55. package/dist/clip-validate.d.ts +33 -0
  56. package/dist/clip-validate.d.ts.map +1 -0
  57. package/dist/clip-validate.js +247 -0
  58. package/dist/clip-validate.js.map +1 -0
  59. package/dist/d1-retry.d.ts +20 -0
  60. package/dist/d1-retry.d.ts.map +1 -0
  61. package/dist/d1-retry.js +67 -0
  62. package/dist/d1-retry.js.map +1 -0
  63. package/dist/db-env.d.ts +6 -0
  64. package/dist/db-env.d.ts.map +1 -0
  65. package/dist/db-env.js +2 -0
  66. package/dist/db-env.js.map +1 -0
  67. package/dist/dialogue-lines.d.ts +23 -0
  68. package/dist/dialogue-lines.d.ts.map +1 -0
  69. package/dist/dialogue-lines.js +84 -0
  70. package/dist/dialogue-lines.js.map +1 -0
  71. package/dist/film-advance-lease.d.ts +9 -0
  72. package/dist/film-advance-lease.d.ts.map +1 -0
  73. package/dist/film-advance-lease.js +19 -0
  74. package/dist/film-advance-lease.js.map +1 -0
  75. package/dist/film-model.d.ts +415 -0
  76. package/dist/film-model.d.ts.map +1 -0
  77. package/dist/film-model.js +541 -0
  78. package/dist/film-model.js.map +1 -0
  79. package/dist/film-orchestrator.d.ts +216 -0
  80. package/dist/film-orchestrator.d.ts.map +1 -0
  81. package/dist/film-orchestrator.js +2204 -0
  82. package/dist/film-orchestrator.js.map +1 -0
  83. package/dist/film-render-bridge.d.ts +26 -0
  84. package/dist/film-render-bridge.d.ts.map +1 -0
  85. package/dist/film-render-bridge.js +176 -0
  86. package/dist/film-render-bridge.js.map +1 -0
  87. package/dist/finish-hash.d.ts +10 -0
  88. package/dist/finish-hash.d.ts.map +1 -0
  89. package/dist/finish-hash.js +60 -0
  90. package/dist/finish-hash.js.map +1 -0
  91. package/dist/index.d.ts +48 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +45 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/key-safety.d.ts +5 -0
  96. package/dist/key-safety.d.ts.map +1 -0
  97. package/dist/key-safety.js +23 -0
  98. package/dist/key-safety.js.map +1 -0
  99. package/dist/lora-bundle.d.ts +19 -0
  100. package/dist/lora-bundle.d.ts.map +1 -0
  101. package/dist/lora-bundle.js +75 -0
  102. package/dist/lora-bundle.js.map +1 -0
  103. package/dist/lora-keys.d.ts +2 -0
  104. package/dist/lora-keys.d.ts.map +1 -0
  105. package/dist/lora-keys.js +4 -0
  106. package/dist/lora-keys.js.map +1 -0
  107. package/dist/modules/conformance.d.ts +58 -0
  108. package/dist/modules/conformance.d.ts.map +1 -0
  109. package/dist/modules/conformance.js +369 -0
  110. package/dist/modules/conformance.js.map +1 -0
  111. package/dist/modules/manifest-validate.d.ts +5 -0
  112. package/dist/modules/manifest-validate.d.ts.map +1 -0
  113. package/dist/modules/manifest-validate.js +60 -0
  114. package/dist/modules/manifest-validate.js.map +1 -0
  115. package/dist/modules/registry.d.ts +184 -0
  116. package/dist/modules/registry.d.ts.map +1 -0
  117. package/dist/modules/registry.js +653 -0
  118. package/dist/modules/registry.js.map +1 -0
  119. package/dist/modules/render-pipeline.d.ts +38 -0
  120. package/dist/modules/render-pipeline.d.ts.map +1 -0
  121. package/dist/modules/render-pipeline.js +40 -0
  122. package/dist/modules/render-pipeline.js.map +1 -0
  123. package/dist/modules/types.d.ts +544 -0
  124. package/dist/modules/types.d.ts.map +1 -0
  125. package/dist/modules/types.js +57 -0
  126. package/dist/modules/types.js.map +1 -0
  127. package/dist/operator-config.d.ts +20 -0
  128. package/dist/operator-config.d.ts.map +1 -0
  129. package/dist/operator-config.js +85 -0
  130. package/dist/operator-config.js.map +1 -0
  131. package/dist/output-extract.d.ts +8 -0
  132. package/dist/output-extract.d.ts.map +1 -0
  133. package/dist/output-extract.js +129 -0
  134. package/dist/output-extract.js.map +1 -0
  135. package/dist/planner-prompt.d.ts +12 -0
  136. package/dist/planner-prompt.d.ts.map +1 -0
  137. package/dist/planner-prompt.js +337 -0
  138. package/dist/planner-prompt.js.map +1 -0
  139. package/dist/planner-yaml.d.ts +15 -0
  140. package/dist/planner-yaml.d.ts.map +1 -0
  141. package/dist/planner-yaml.js +157 -0
  142. package/dist/planner-yaml.js.map +1 -0
  143. package/dist/platform/fetcher.d.ts +3 -0
  144. package/dist/platform/fetcher.d.ts.map +1 -0
  145. package/dist/platform/fetcher.js +7 -0
  146. package/dist/platform/fetcher.js.map +1 -0
  147. package/dist/platform/index.d.ts +6 -0
  148. package/dist/platform/index.d.ts.map +1 -0
  149. package/dist/platform/index.js +5 -0
  150. package/dist/platform/index.js.map +1 -0
  151. package/dist/platform/object-store-r2.d.ts +26 -0
  152. package/dist/platform/object-store-r2.d.ts.map +1 -0
  153. package/dist/platform/object-store-r2.js +74 -0
  154. package/dist/platform/object-store-r2.js.map +1 -0
  155. package/dist/platform/orchestrator-context.d.ts +20 -0
  156. package/dist/platform/orchestrator-context.d.ts.map +1 -0
  157. package/dist/platform/orchestrator-context.js +28 -0
  158. package/dist/platform/orchestrator-context.js.map +1 -0
  159. package/dist/platform/r2-types.d.ts +41 -0
  160. package/dist/platform/r2-types.d.ts.map +1 -0
  161. package/dist/platform/r2-types.js +3 -0
  162. package/dist/platform/r2-types.js.map +1 -0
  163. package/dist/platform/types.d.ts +90 -0
  164. package/dist/platform/types.d.ts.map +1 -0
  165. package/dist/platform/types.js +23 -0
  166. package/dist/platform/types.js.map +1 -0
  167. package/dist/preflight.d.ts +57 -0
  168. package/dist/preflight.d.ts.map +1 -0
  169. package/dist/preflight.js +243 -0
  170. package/dist/preflight.js.map +1 -0
  171. package/dist/presign.d.ts +5 -0
  172. package/dist/presign.d.ts.map +1 -0
  173. package/dist/presign.js +24 -0
  174. package/dist/presign.js.map +1 -0
  175. package/dist/public-id.d.ts +8 -0
  176. package/dist/public-id.d.ts.map +1 -0
  177. package/dist/public-id.js +25 -0
  178. package/dist/public-id.js.map +1 -0
  179. package/dist/render-adopt.d.ts +3 -0
  180. package/dist/render-adopt.d.ts.map +1 -0
  181. package/dist/render-adopt.js +92 -0
  182. package/dist/render-adopt.js.map +1 -0
  183. package/dist/render-log.d.ts +25 -0
  184. package/dist/render-log.d.ts.map +1 -0
  185. package/dist/render-log.js +139 -0
  186. package/dist/render-log.js.map +1 -0
  187. package/dist/render-module-config.d.ts +28 -0
  188. package/dist/render-module-config.d.ts.map +1 -0
  189. package/dist/render-module-config.js +124 -0
  190. package/dist/render-module-config.js.map +1 -0
  191. package/dist/render-mux.d.ts +18 -0
  192. package/dist/render-mux.d.ts.map +1 -0
  193. package/dist/render-mux.js +69 -0
  194. package/dist/render-mux.js.map +1 -0
  195. package/dist/render-orchestrator.d.ts +71 -0
  196. package/dist/render-orchestrator.d.ts.map +1 -0
  197. package/dist/render-orchestrator.js +376 -0
  198. package/dist/render-orchestrator.js.map +1 -0
  199. package/dist/render-sweep.d.ts +5 -0
  200. package/dist/render-sweep.d.ts.map +1 -0
  201. package/dist/render-sweep.js +62 -0
  202. package/dist/render-sweep.js.map +1 -0
  203. package/dist/renders-db.d.ts +129 -0
  204. package/dist/renders-db.d.ts.map +1 -0
  205. package/dist/renders-db.js +752 -0
  206. package/dist/renders-db.js.map +1 -0
  207. package/dist/runpod-submit.d.ts +151 -0
  208. package/dist/runpod-submit.d.ts.map +1 -0
  209. package/dist/runpod-submit.js +469 -0
  210. package/dist/runpod-submit.js.map +1 -0
  211. package/dist/runpod-types.d.ts +2 -0
  212. package/dist/runpod-types.d.ts.map +1 -0
  213. package/dist/runpod-types.js +4 -0
  214. package/dist/runpod-types.js.map +1 -0
  215. package/dist/scatter-notify.d.ts +4 -0
  216. package/dist/scatter-notify.d.ts.map +1 -0
  217. package/dist/scatter-notify.js +43 -0
  218. package/dist/scatter-notify.js.map +1 -0
  219. package/dist/scatter-orchestrator-types.d.ts +56 -0
  220. package/dist/scatter-orchestrator-types.d.ts.map +1 -0
  221. package/dist/scatter-orchestrator-types.js +3 -0
  222. package/dist/scatter-orchestrator-types.js.map +1 -0
  223. package/dist/scatter-orchestrator.d.ts +70 -0
  224. package/dist/scatter-orchestrator.d.ts.map +1 -0
  225. package/dist/scatter-orchestrator.js +614 -0
  226. package/dist/scatter-orchestrator.js.map +1 -0
  227. package/dist/scatter.d.ts +35 -0
  228. package/dist/scatter.d.ts.map +1 -0
  229. package/dist/scatter.js +171 -0
  230. package/dist/scatter.js.map +1 -0
  231. package/dist/secret-store.d.ts +5 -0
  232. package/dist/secret-store.d.ts.map +1 -0
  233. package/dist/secret-store.js +19 -0
  234. package/dist/secret-store.js.map +1 -0
  235. package/dist/shot-durations-parse.d.ts +3 -0
  236. package/dist/shot-durations-parse.d.ts.map +1 -0
  237. package/dist/shot-durations-parse.js +43 -0
  238. package/dist/shot-durations-parse.js.map +1 -0
  239. package/dist/srt.d.ts +11 -0
  240. package/dist/srt.d.ts.map +1 -0
  241. package/dist/srt.js +54 -0
  242. package/dist/srt.js.map +1 -0
  243. package/dist/storyboard-ids.d.ts +2 -0
  244. package/dist/storyboard-ids.d.ts.map +1 -0
  245. package/dist/storyboard-ids.js +12 -0
  246. package/dist/storyboard-ids.js.map +1 -0
  247. package/dist/storyboard-projects-db.d.ts +31 -0
  248. package/dist/storyboard-projects-db.d.ts.map +1 -0
  249. package/dist/storyboard-projects-db.js +153 -0
  250. package/dist/storyboard-projects-db.js.map +1 -0
  251. package/dist/storyboard-validate.d.ts +72 -0
  252. package/dist/storyboard-validate.d.ts.map +1 -0
  253. package/dist/storyboard-validate.js +595 -0
  254. package/dist/storyboard-validate.js.map +1 -0
  255. package/dist/structured-events.d.ts +6 -0
  256. package/dist/structured-events.d.ts.map +1 -0
  257. package/dist/structured-events.js +15 -0
  258. package/dist/structured-events.js.map +1 -0
  259. package/dist/tar.d.ts +9 -0
  260. package/dist/tar.d.ts.map +1 -0
  261. package/dist/tar.js +151 -0
  262. package/dist/tar.js.map +1 -0
  263. package/dist/voices.d.ts +12 -0
  264. package/dist/voices.d.ts.map +1 -0
  265. package/dist/voices.js +37 -0
  266. package/dist/voices.js.map +1 -0
  267. package/package.json +71 -0
@@ -0,0 +1,23 @@
1
+ // Safe relative key / path segment helpers (ported from vivijure shared.ts).
2
+ export const BUNDLE_KEY_PREFIX = "bundles/";
3
+ const REL_KEY_CHARS = /^[A-Za-z0-9._\-\/]+$/;
4
+ export function isSafeRelKey(key) {
5
+ if (typeof key !== "string" || key.length === 0 || key.length > 1024)
6
+ return false;
7
+ if (key.startsWith("/"))
8
+ return false;
9
+ if (!REL_KEY_CHARS.test(key))
10
+ return false;
11
+ return !key.split("/").includes("..");
12
+ }
13
+ export function isSafeBundleKey(key) {
14
+ return isSafeRelKey(key) && key.startsWith(BUNDLE_KEY_PREFIX);
15
+ }
16
+ export function sanitizeKeySegment(raw, fallback = "project") {
17
+ const s = raw
18
+ .replace(/[^A-Za-z0-9._\-]/g, "_")
19
+ .replace(/\.\.+/g, "_")
20
+ .replace(/^[._-]+/, "");
21
+ return s.length > 0 ? s : fallback;
22
+ }
23
+ //# sourceMappingURL=key-safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-safety.js","sourceRoot":"","sources":["../src/key-safety.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAE7C,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI;QAAE,OAAO,KAAK,CAAC;IACnF,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,QAAQ,GAAG,SAAS;IAClE,MAAM,CAAC,GAAG,GAAG;SACV,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC;SACjC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC1B,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACrC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { StoryboardValidated } from "./storyboard-validate.js";
2
+ import type { CastMember } from "./cast-db.js";
3
+ export interface LoraBundleTrainingImage {
4
+ key: string;
5
+ }
6
+ export interface LoraBundleCharacterRef {
7
+ name: string;
8
+ prompt: string;
9
+ trainingImages: LoraBundleTrainingImage[];
10
+ portrait?: LoraBundleTrainingImage;
11
+ }
12
+ export interface LoraBundleArgs {
13
+ storyboard: StoryboardValidated;
14
+ characterRefs: Record<string, LoraBundleCharacterRef>;
15
+ }
16
+ export declare function buildLoraTrainingBundleArgs(cast: CastMember, bundleSuffix: string): LoraBundleArgs;
17
+ export declare function deriveLoraDestKey(castId: number, timestamp: number): string;
18
+ export declare function extractTrainedLoraKey(output: unknown): string | null;
19
+ //# sourceMappingURL=lora-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lora-bundle.d.ts","sourceRoot":"","sources":["../src/lora-bundle.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,uBAAuB,EAAE,CAAC;IAC1C,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,mBAAmB,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;CACvD;AAMD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,UAAU,EAChB,YAAY,EAAE,MAAM,GACnB,cAAc,CAiChB;AAOD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3E;AAOD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAcpE"}
@@ -0,0 +1,75 @@
1
+ // Pure helpers for standalone LoRA training bundles.
2
+ //
3
+ // Route handlers wrap these with env-touching pieces (assembleBundle,
4
+ // submitTrainLoraJob). Keeping data-shaping here lets vitest cover the
5
+ // bundle-builder logic without importing cloudflare:workers.
6
+ // Build the (storyboard, characterRefs) tuple that assembleBundle takes
7
+ // for a single-slot LoRA training bundle. The synthesized storyboard
8
+ // satisfies the validator: one scene with a non-empty prompt that
9
+ // references slot A, which is also the only entry in use_characters.
10
+ export function buildLoraTrainingBundleArgs(cast, bundleSuffix) {
11
+ const safeSlug = cast.slug || `cast-${cast.id}`;
12
+ const projectName = `lora-${safeSlug}-${bundleSuffix}`;
13
+ return {
14
+ storyboard: {
15
+ title: projectName,
16
+ projectName,
17
+ full_prompt: "",
18
+ duration_seconds: undefined,
19
+ clip_seconds: undefined,
20
+ style_prefix: "",
21
+ style_category: "None",
22
+ style_preset: "None",
23
+ use_characters: ["A"],
24
+ cast_rules: "",
25
+ scenes: [
26
+ {
27
+ id: "lora_train_shot",
28
+ prompt: "lora training reference shot (not rendered)",
29
+ character_slots: ["A"],
30
+ target_seconds: 1,
31
+ },
32
+ ],
33
+ },
34
+ characterRefs: {
35
+ A: {
36
+ name: cast.name,
37
+ prompt: cast.bible || cast.name,
38
+ trainingImages: cast.ref_keys.map((r) => ({ key: r.key })),
39
+ portrait: cast.portrait_key ? { key: cast.portrait_key } : undefined,
40
+ },
41
+ },
42
+ };
43
+ }
44
+ // Build the destination R2 key for the trained .safetensors. Per-cast
45
+ // prefix lets a future GC pass enumerate by cast id; the timestamp
46
+ // version keeps retraining immutable so an in-flight render that
47
+ // references the prior key does not break. The GPU backend may use its
48
+ // own convention; this is returned to the client for traceability.
49
+ export function deriveLoraDestKey(castId, timestamp) {
50
+ return `loras/cast-${castId}/${timestamp}.safetensors`;
51
+ }
52
+ // The trained-LoRA R2 key from a completed train_lora job envelope. The clean-room
53
+ // backend returns it nested under result.lora[slot].lora_id (a cast-training bundle
54
+ // is single-slot, so it's the one entry); the legacy vivijure-serverless envelope
55
+ // used a top-level lora_key. Reads both shapes so the cast page harvests the key
56
+ // either way; returns null only if neither carries one.
57
+ export function extractTrainedLoraKey(output) {
58
+ if (!output || typeof output !== "object")
59
+ return null;
60
+ const o = output;
61
+ if (typeof o.lora_key === "string" && o.lora_key)
62
+ return o.lora_key;
63
+ const lora = o.lora;
64
+ if (lora && typeof lora === "object" && !Array.isArray(lora)) {
65
+ for (const entry of Object.values(lora)) {
66
+ if (entry && typeof entry === "object") {
67
+ const id = entry.lora_id;
68
+ if (typeof id === "string" && id)
69
+ return id;
70
+ }
71
+ }
72
+ }
73
+ return null;
74
+ }
75
+ //# sourceMappingURL=lora-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lora-bundle.js","sourceRoot":"","sources":["../src/lora-bundle.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,sEAAsE;AACtE,uEAAuE;AACvE,6DAA6D;AAqB7D,wEAAwE;AACxE,qEAAqE;AACrE,kEAAkE;AAClE,qEAAqE;AACrE,MAAM,UAAU,2BAA2B,CACzC,IAAgB,EAChB,YAAoB;IAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;IAChD,MAAM,WAAW,GAAG,QAAQ,QAAQ,IAAI,YAAY,EAAE,CAAC;IACvD,OAAO;QACL,UAAU,EAAE;YACV,KAAK,EAAE,WAAW;YAClB,WAAW;YACX,WAAW,EAAE,EAAE;YACf,gBAAgB,EAAE,SAAS;YAC3B,YAAY,EAAE,SAAS;YACvB,YAAY,EAAE,EAAE;YAChB,cAAc,EAAE,MAAM;YACtB,YAAY,EAAE,MAAM;YACpB,cAAc,EAAE,CAAC,GAAG,CAAC;YACrB,UAAU,EAAE,EAAE;YACd,MAAM,EAAE;gBACN;oBACE,EAAE,EAAE,iBAAiB;oBACrB,MAAM,EAAE,6CAA6C;oBACrD,eAAe,EAAE,CAAC,GAAG,CAAC;oBACtB,cAAc,EAAE,CAAC;iBAClB;aACF;SACF;QACD,aAAa,EAAE;YACb,CAAC,EAAE;gBACD,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI;gBAC/B,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC1D,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS;aACrE;SACF;KACF,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,mEAAmE;AACnE,iEAAiE;AACjE,uEAAuE;AACvE,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,SAAiB;IACjE,OAAO,cAAc,MAAM,IAAI,SAAS,cAAc,CAAC;AACzD,CAAC;AAED,mFAAmF;AACnF,oFAAoF;AACpF,kFAAkF;AAClF,iFAAiF;AACjF,wDAAwD;AACxD,MAAM,UAAU,qBAAqB,CAAC,MAAe;IACnD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,CAAC,GAAG,MAAiC,CAAC;IAC5C,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC,QAAQ,CAAC;IACpE,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;IACpB,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,IAA+B,CAAC,EAAE,CAAC;YACnE,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvC,MAAM,EAAE,GAAI,KAA+B,CAAC,OAAO,CAAC;gBACpD,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE;oBAAE,OAAO,EAAE,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function deriveLoraDestKey(castId: number, timestamp: number): string;
2
+ //# sourceMappingURL=lora-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lora-keys.d.ts","sourceRoot":"","sources":["../src/lora-keys.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3E"}
@@ -0,0 +1,4 @@
1
+ export function deriveLoraDestKey(castId, timestamp) {
2
+ return `loras/cast-${castId}/${timestamp}.safetensors`;
3
+ }
4
+ //# sourceMappingURL=lora-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lora-keys.js","sourceRoot":"","sources":["../src/lora-keys.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,SAAiB;IACjE,OAAO,cAAc,MAAM,IAAI,SAAS,cAAc,CAAC;AACzD,CAAC"}
@@ -0,0 +1,58 @@
1
+ export interface ConformanceCheck {
2
+ name: string;
3
+ pass: boolean;
4
+ detail: string;
5
+ }
6
+ /** Validate a module's manifest (the GET /module.json body) against the contract. */
7
+ export declare function checkManifest(raw: unknown): ConformanceCheck[];
8
+ /** Validate that a body is a well-formed InvokeResponse: { ok:true, output } or { ok:false, error:string }. */
9
+ export declare function checkInvokeResponse(raw: unknown): ConformanceCheck;
10
+ /** Validate that a body is a well-formed CancelResponse: { ok:true } or { ok:false, error:string }. A
11
+ * module whose manifest advertises `cancelable` must answer POST /cancel with this shape (a bad/unknown
12
+ * token is DATA -> ok:false with a reason, never a crash), so the core can trust ok:true as "the job is
13
+ * not running on our account" and degrade-log on ok:false (#327 / #328). */
14
+ export declare function checkCancelResponse(raw: unknown): ConformanceCheck;
15
+ /** Validate that a hook's success output honors its typed contract shape (the payload inside
16
+ * `{ ok:true, output }`). Use this AFTER checkInvokeResponse confirms the envelope: a module can be
17
+ * envelope-correct yet return a payload that breaks the hook contract, which the core would then
18
+ * hand downstream as garbage. An unknown hook name is itself a failure. */
19
+ export declare function checkHookOutput(hook: string, output: unknown): ConformanceCheck;
20
+ /** Terminal-seam guard for a module's RESOLVED hook output. The generic transport (invokeModule /
21
+ * pollModule) is payload-agnostic -- it also backs dispatchChain's output->input fold and dispatchPickOne
22
+ * and cannot enforce a specific hook's contract without rejecting those legitimate toy payloads. The
23
+ * ORCHESTRATOR that consumes a hook enforces it instead: after awaitInvoke / pollModule resolves, the
24
+ * payload IS the real contract type. Returns a concise, traceable degrade reason (module id + hook + what
25
+ * broke, so it reads cleanly on the event channel) when the output violates the hook contract, or null
26
+ * when it honors it, so the core never threads an envelope-correct but malformed payload downstream
27
+ * (#345 / F5b). A legitimate soft-degrade (ok:true + passthrough + `degraded`) still carries its required
28
+ * contract fields, so it passes this guard untouched -- only a genuinely malformed payload is caught. */
29
+ export declare function hookOutputViolation(moduleId: string, hook: string, output: unknown): string | null;
30
+ /** True iff every check passed. */
31
+ export declare function allPass(checks: ConformanceCheck[]): boolean;
32
+ /** The failed checks, for a concise report. */
33
+ export declare function failures(checks: ConformanceCheck[]): ConformanceCheck[];
34
+ /** A Fetcher-shaped module handle: the SAME thing `MODULE_DISPATCH.get(script)` and a service binding
35
+ * both return. The live runner is transport-agnostic -- it drives whatever Fetcher it is handed. */
36
+ export interface ConformanceFetcher {
37
+ fetch(input: Request | string, init?: RequestInit): Promise<Response>;
38
+ }
39
+ /** Run the conformance suite against a LIVE module Fetcher at install time (docs/module-dispatch.md 4.3).
40
+ * Drives the module over the SAME transport it will run on (a dispatched user Worker, or a service
41
+ * binding), asserting: a valid manifest at GET /module.json; a well-formed InvokeResponse ENVELOPE for
42
+ * its first hook; and that a bad-hook request DEGRADES (HTTP 200 + { ok:false }, never a crash). The
43
+ * install route INSERTs the registry row ONLY when every check passes; a resident-but-failing module is
44
+ * never installed and never dispatched. Total: a network failure becomes a failed check, never a throw.
45
+ *
46
+ * SCOPE (be honest about what this gate proves): it validates the CONTRACT WIRING -- manifest shape,
47
+ * the invoke/degrade envelope, and, for a SYNCHRONOUS hook (a module that answers `ok:true + output`
48
+ * right away, e.g. plan.enhance), the typed hook OUTPUT via checkHookOutput. It deliberately does NOT
49
+ * validate the typed output of an ASYNC hook (motion.backend / keyframe / finish / speech / master),
50
+ * which answers `ok:true + pending + poll`: proving that output shape would require POLLING THE JOB TO
51
+ * COMPLETION, i.e. triggering the module's real (often GPU) work just to install it -- an unacceptable
52
+ * cost + side effect for an install gate. Typed-output conformance for async hooks is therefore the
53
+ * MODULE'S OWN responsibility, proven by its conformance CI (checkHookOutput over a controlled
54
+ * completion in tests/conformance.live.test.ts / `npm run conformance`), not by this install-time gate.
55
+ * The gate blocks a mis-wired or non-degrading module; it does not (and cannot cheaply) re-run an async
56
+ * module's per-shot output contract. */
57
+ export declare function runLiveConformance(fetcher: ConformanceFetcher): Promise<ConformanceCheck[]>;
58
+ //# sourceMappingURL=conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/modules/conformance.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAkCD,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAoB9D;AAED,+GAA+G;AAC/G,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAUlE;AAED;;;6EAG6E;AAC7E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAMlE;AA0GD;;;4EAG4E;AAC5E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAO/E;AAED;;;;;;;;0GAQ0G;AAC1G,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGlG;AAED,mCAAmC;AACnC,wBAAgB,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAE3D;AAED,+CAA+C;AAC/C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAEvE;AAID;qGACqG;AACrG,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACvE;AAyBD;;;;;;;;;;;;;;;;;yCAiByC;AACzC,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA4DjG"}
@@ -0,0 +1,369 @@
1
+ // Module conformance harness (vivijure-module/2; /1 accepted transitionally).
2
+ //
3
+ // The "does this module honor the contract?" checker. Anyone writing a module (in this repo or
4
+ // another) runs these checks against their worker to know it will plug into the core cleanly:
5
+ // - its GET /module.json is a valid manifest (api version, name, version, known hooks, sane
6
+ // config_schema + provides),
7
+ // - its POST /invoke returns a well-formed InvokeResponse,
8
+ // - and it degrades (a bad request is DATA -- HTTP 200 with { ok:false }, never a crash).
9
+ //
10
+ // The pure checks here are dependency-free + unit-tested; the live runner (tests/conformance.live
11
+ // .test.ts) drives them against a deployed module URL. This is the conformance half of the module
12
+ // SDK: the contract is the law, and this is how a contributor proves they obey it.
13
+ import { SUPPORTED_MODULE_APIS } from "./types.js";
14
+ import { validateManifest } from "./manifest-validate.js";
15
+ const ok = (name, detail = "ok") => ({ name, pass: true, detail });
16
+ const bad = (name, detail) => ({ name, pass: false, detail });
17
+ const FIELD_TYPES = ["int", "float", "bool", "enum", "string"];
18
+ const FIELD_SCOPES = ["render", "install"];
19
+ /** One config_schema field has a valid type and a default consistent with that type. */
20
+ function checkConfigField(key, f) {
21
+ const label = "config." + key;
22
+ if (!f || typeof f !== "object")
23
+ return bad(label, "field is not an object");
24
+ const ff = f;
25
+ const t = ff.type;
26
+ if (typeof t !== "string" || !FIELD_TYPES.includes(t))
27
+ return bad(label, "bad field type " + String(t));
28
+ // scope is optional (omitted => "render", a per-render knob); when present it must be a known scope.
29
+ if (ff.scope !== undefined && (typeof ff.scope !== "string" || !FIELD_SCOPES.includes(ff.scope))) {
30
+ return bad(label, "bad field scope " + String(ff.scope));
31
+ }
32
+ if (t === "enum") {
33
+ if (!Array.isArray(ff.values) || ff.values.length === 0)
34
+ return bad(label, "enum needs a non-empty values[]");
35
+ if (typeof ff.default !== "string" || !ff.values.includes(ff.default)) {
36
+ return bad(label, "enum default must be one of values");
37
+ }
38
+ }
39
+ else if (t === "bool") {
40
+ if (typeof ff.default !== "boolean")
41
+ return bad(label, "bool default must be a boolean");
42
+ }
43
+ else if (t === "string") {
44
+ if (typeof ff.default !== "string")
45
+ return bad(label, "string default must be a string");
46
+ }
47
+ else {
48
+ if (typeof ff.default !== "number")
49
+ return bad(label, t + " default must be a number");
50
+ }
51
+ return ok(label, String(t));
52
+ }
53
+ /** Validate a module's manifest (the GET /module.json body) against the contract. */
54
+ export function checkManifest(raw) {
55
+ const checks = [];
56
+ const m = validateManifest(raw);
57
+ if (typeof m === "string") {
58
+ checks.push(bad("manifest", m));
59
+ return checks;
60
+ }
61
+ checks.push(ok("manifest", m.name + " v" + m.version));
62
+ checks.push(SUPPORTED_MODULE_APIS.has(String(m.api))
63
+ ? ok("api-version", String(m.api))
64
+ : bad("api-version", String(m.api) + " not in " + [...SUPPORTED_MODULE_APIS].join("/")));
65
+ checks.push(ok("hooks", m.hooks.join(", ")));
66
+ if (m.config_schema) {
67
+ for (const [k, f] of Object.entries(m.config_schema))
68
+ checks.push(checkConfigField(k, f));
69
+ }
70
+ if (m.provides) {
71
+ const good = m.provides.every((p) => p && typeof p.id === "string" && typeof p.label === "string");
72
+ checks.push(good ? ok("provides", String(m.provides.length)) : bad("provides", "each provides[] needs id + label"));
73
+ }
74
+ return checks;
75
+ }
76
+ /** Validate that a body is a well-formed InvokeResponse: { ok:true, output } or { ok:false, error:string }. */
77
+ export function checkInvokeResponse(raw) {
78
+ if (!raw || typeof raw !== "object")
79
+ return bad("invoke-response", "not an object");
80
+ const r = raw;
81
+ if (r.ok === true) {
82
+ if ("output" in r)
83
+ return ok("invoke-response", "ok:true + output");
84
+ if (r.pending === true && typeof r.poll === "string")
85
+ return ok("invoke-response", "ok:true + pending + poll");
86
+ return bad("invoke-response", "ok:true but neither output nor pending+poll");
87
+ }
88
+ if (r.ok === false)
89
+ return typeof r.error === "string" ? ok("invoke-response", "ok:false + error") : bad("invoke-response", "ok:false but error is not a string");
90
+ return bad("invoke-response", "missing boolean `ok`");
91
+ }
92
+ /** Validate that a body is a well-formed CancelResponse: { ok:true } or { ok:false, error:string }. A
93
+ * module whose manifest advertises `cancelable` must answer POST /cancel with this shape (a bad/unknown
94
+ * token is DATA -> ok:false with a reason, never a crash), so the core can trust ok:true as "the job is
95
+ * not running on our account" and degrade-log on ok:false (#327 / #328). */
96
+ export function checkCancelResponse(raw) {
97
+ if (!raw || typeof raw !== "object")
98
+ return bad("cancel-response", "not an object");
99
+ const r = raw;
100
+ if (r.ok === true)
101
+ return ok("cancel-response", "ok:true");
102
+ if (r.ok === false)
103
+ return typeof r.error === "string" ? ok("cancel-response", "ok:false + error") : bad("cancel-response", "ok:false but error is not a string");
104
+ return bad("cancel-response", "missing boolean `ok`");
105
+ }
106
+ // --------------------------------------------------------------------------- hook output payloads
107
+ const isRec = (v) => !!v && typeof v === "object" && !Array.isArray(v);
108
+ const isStr = (v) => typeof v === "string";
109
+ const isNum = (v) => typeof v === "number" && Number.isFinite(v);
110
+ const isStrArr = (v) => Array.isArray(v) && v.every(isStr);
111
+ /** Per-hook output validators: the typed payload each hook must return inside `{ ok:true, output }`.
112
+ * Validating the envelope (checkInvokeResponse) is not enough -- a `finish` module that returns
113
+ * `{ ok:true, output:{} }` is well-formed at the envelope but breaks the contract. Each returns a
114
+ * reason string on a shape violation, or null when the payload honors the hook's contract. Only the
115
+ * REQUIRED fields are enforced; optional contract fields are not demanded (mirrors the runtime,
116
+ * which treats hint fields as optional). */
117
+ const HOOK_OUTPUT_CHECKS = {
118
+ keyframe: (o) => {
119
+ if (!isStr(o.project))
120
+ return "keyframe output needs a string project";
121
+ if (!Array.isArray(o.keyframes))
122
+ return "keyframe output needs a keyframes[]";
123
+ const bad = o.keyframes.find((k) => !isRec(k) || !isStr(k.shot_id) || !isStr(k.keyframe_key));
124
+ if (bad)
125
+ return "each keyframe needs shot_id + keyframe_key";
126
+ // Optional: trained_loras maps slot -> R2 key (string -> string).
127
+ if (o.trained_loras !== undefined) {
128
+ if (!isRec(o.trained_loras))
129
+ return "keyframe output trained_loras must be an object";
130
+ if (Object.values(o.trained_loras).some((v) => !isStr(v))) {
131
+ return "keyframe output trained_loras values must be R2 key strings";
132
+ }
133
+ }
134
+ return null;
135
+ },
136
+ "motion.backend": (o) => {
137
+ if (!isStr(o.shot_id))
138
+ return "motion output needs a string shot_id";
139
+ if (!isStr(o.clip_key))
140
+ return "motion output needs a string clip_key";
141
+ if (!isNum(o.fps))
142
+ return "motion output needs a numeric fps";
143
+ if (!isNum(o.frames))
144
+ return "motion output needs a numeric frames";
145
+ return null;
146
+ },
147
+ finish: (o) => {
148
+ if (!isStr(o.shot_id))
149
+ return "finish output needs a string shot_id";
150
+ if (!isStr(o.clip_key))
151
+ return "finish output needs a string clip_key";
152
+ if (!isNum(o.out_fps))
153
+ return "finish output needs a numeric out_fps";
154
+ if (!isNum(o.frames))
155
+ return "finish output needs a numeric frames";
156
+ if (!isStrArr(o.applied))
157
+ return "finish output needs an applied string[]";
158
+ return null;
159
+ },
160
+ score: (o) => {
161
+ if (!isStr(o.film_key))
162
+ return "score output needs a string film_key";
163
+ if (!isStrArr(o.applied))
164
+ return "score output needs an applied string[]";
165
+ if (o.degraded !== undefined && !isStr(o.degraded))
166
+ return "score degraded, when present, must be a string (the chain degrade reason)";
167
+ return null;
168
+ },
169
+ dialogue: (o) => {
170
+ if (!isStr(o.project))
171
+ return "dialogue output needs a string project";
172
+ if (!Array.isArray(o.audio))
173
+ return "dialogue output needs an audio[]";
174
+ const badEntry = o.audio.find((a) => !isRec(a) || !isStr(a.shot_id) || !isStr(a.audio_key) || !isStr(a.voice_id));
175
+ if (badEntry)
176
+ return "each dialogue audio needs shot_id + audio_key + voice_id";
177
+ if (!isStrArr(o.applied))
178
+ return "dialogue output needs an applied string[]";
179
+ return null;
180
+ },
181
+ speech: (o) => {
182
+ if (!isStr(o.shot_id))
183
+ return "speech output needs a string shot_id";
184
+ if (!isStr(o.audio_key))
185
+ return "speech output needs a string audio_key";
186
+ if (!isStrArr(o.applied))
187
+ return "speech output needs an applied string[]";
188
+ return null;
189
+ },
190
+ "plan.enhance": (o) => {
191
+ if (!isRec(o.storyboard))
192
+ return "plan.enhance output needs a storyboard object";
193
+ if (!Array.isArray(o.storyboard.scenes)) {
194
+ return "plan.enhance storyboard needs a scenes[]";
195
+ }
196
+ return null;
197
+ },
198
+ "cast.image": (o) => {
199
+ if (!isNum(o.cast_id))
200
+ return "cast.image output needs a numeric cast_id";
201
+ if (!Array.isArray(o.images))
202
+ return "cast.image output needs an images[]";
203
+ const bad = o.images.find((i) => !isRec(i) || !isStr(i.key) || !isStr(i.mime));
204
+ if (bad)
205
+ return "each cast.image needs key + mime";
206
+ if (!isStrArr(o.applied))
207
+ return "cast.image output needs an applied string[]";
208
+ return null;
209
+ },
210
+ notify: (o) => {
211
+ if (!isStrArr(o.delivered))
212
+ return "notify output needs a delivered string[]";
213
+ return null;
214
+ },
215
+ master: (o) => {
216
+ if (!isStr(o.audio_key))
217
+ return "master output needs a string audio_key";
218
+ if (!isStrArr(o.applied))
219
+ return "master output needs an applied string[]";
220
+ return null;
221
+ },
222
+ "film.finish": (o) => {
223
+ if (!isStr(o.film_key))
224
+ return "film.finish output needs a string film_key";
225
+ // applied/degraded stay OPTIONAL (vendored-contract back-compat; the core defaults `applied ?? []`)
226
+ // but a present value must honor the type -- a malformed applied would otherwise flow into job
227
+ // state unchecked (film-orchestrator records it verbatim).
228
+ if (o.applied !== undefined && !isStrArr(o.applied))
229
+ return "film.finish applied, when present, must be a string[]";
230
+ if (o.degraded !== undefined && !isStr(o.degraded))
231
+ return "film.finish degraded, when present, must be a string (the uncarded reason)";
232
+ if (o.prepend_seconds !== undefined && (typeof o.prepend_seconds !== "number" || !Number.isFinite(o.prepend_seconds) || o.prepend_seconds < 0))
233
+ return "film.finish prepend_seconds, when present, must be a non-negative finite number";
234
+ return null;
235
+ },
236
+ };
237
+ /** Validate that a hook's success output honors its typed contract shape (the payload inside
238
+ * `{ ok:true, output }`). Use this AFTER checkInvokeResponse confirms the envelope: a module can be
239
+ * envelope-correct yet return a payload that breaks the hook contract, which the core would then
240
+ * hand downstream as garbage. An unknown hook name is itself a failure. */
241
+ export function checkHookOutput(hook, output) {
242
+ const label = "output." + hook;
243
+ const validator = HOOK_OUTPUT_CHECKS[hook];
244
+ if (!validator)
245
+ return bad(label, "unknown hook " + hook);
246
+ if (!isRec(output))
247
+ return bad(label, "output is not an object");
248
+ const reason = validator(output);
249
+ return reason ? bad(label, reason) : ok(label);
250
+ }
251
+ /** Terminal-seam guard for a module's RESOLVED hook output. The generic transport (invokeModule /
252
+ * pollModule) is payload-agnostic -- it also backs dispatchChain's output->input fold and dispatchPickOne
253
+ * and cannot enforce a specific hook's contract without rejecting those legitimate toy payloads. The
254
+ * ORCHESTRATOR that consumes a hook enforces it instead: after awaitInvoke / pollModule resolves, the
255
+ * payload IS the real contract type. Returns a concise, traceable degrade reason (module id + hook + what
256
+ * broke, so it reads cleanly on the event channel) when the output violates the hook contract, or null
257
+ * when it honors it, so the core never threads an envelope-correct but malformed payload downstream
258
+ * (#345 / F5b). A legitimate soft-degrade (ok:true + passthrough + `degraded`) still carries its required
259
+ * contract fields, so it passes this guard untouched -- only a genuinely malformed payload is caught. */
260
+ export function hookOutputViolation(moduleId, hook, output) {
261
+ const check = checkHookOutput(hook, output);
262
+ return check.pass ? null : `module ${moduleId} violated ${hook} contract: ${check.detail}`;
263
+ }
264
+ /** True iff every check passed. */
265
+ export function allPass(checks) {
266
+ return checks.every((c) => c.pass);
267
+ }
268
+ /** The failed checks, for a concise report. */
269
+ export function failures(checks) {
270
+ return checks.filter((c) => !c.pass);
271
+ }
272
+ // The bad-hook the degrade check submits; deliberately not a real HookName so a conformant module must
273
+ // answer HTTP 200 + { ok:false } (data, never a crash / 4xx / 5xx).
274
+ const DEGRADE_PROBE_HOOK = "not.a.real.hook";
275
+ async function fetchJson(fetcher, path, init) {
276
+ try {
277
+ const res = await fetcher.fetch("https://module" + path, init);
278
+ let body = null;
279
+ try {
280
+ body = await res.json();
281
+ }
282
+ catch (e) {
283
+ return { status: res.status, body: null, err: `body not JSON: ${e.message}` };
284
+ }
285
+ return { status: res.status, body };
286
+ }
287
+ catch (e) {
288
+ return { status: 0, body: null, err: `unreachable: ${e.message}` };
289
+ }
290
+ }
291
+ /** Run the conformance suite against a LIVE module Fetcher at install time (docs/module-dispatch.md 4.3).
292
+ * Drives the module over the SAME transport it will run on (a dispatched user Worker, or a service
293
+ * binding), asserting: a valid manifest at GET /module.json; a well-formed InvokeResponse ENVELOPE for
294
+ * its first hook; and that a bad-hook request DEGRADES (HTTP 200 + { ok:false }, never a crash). The
295
+ * install route INSERTs the registry row ONLY when every check passes; a resident-but-failing module is
296
+ * never installed and never dispatched. Total: a network failure becomes a failed check, never a throw.
297
+ *
298
+ * SCOPE (be honest about what this gate proves): it validates the CONTRACT WIRING -- manifest shape,
299
+ * the invoke/degrade envelope, and, for a SYNCHRONOUS hook (a module that answers `ok:true + output`
300
+ * right away, e.g. plan.enhance), the typed hook OUTPUT via checkHookOutput. It deliberately does NOT
301
+ * validate the typed output of an ASYNC hook (motion.backend / keyframe / finish / speech / master),
302
+ * which answers `ok:true + pending + poll`: proving that output shape would require POLLING THE JOB TO
303
+ * COMPLETION, i.e. triggering the module's real (often GPU) work just to install it -- an unacceptable
304
+ * cost + side effect for an install gate. Typed-output conformance for async hooks is therefore the
305
+ * MODULE'S OWN responsibility, proven by its conformance CI (checkHookOutput over a controlled
306
+ * completion in tests/conformance.live.test.ts / `npm run conformance`), not by this install-time gate.
307
+ * The gate blocks a mis-wired or non-degrading module; it does not (and cannot cheaply) re-run an async
308
+ * module's per-shot output contract. */
309
+ export async function runLiveConformance(fetcher) {
310
+ const checks = [];
311
+ // 1) manifest
312
+ const man = await fetchJson(fetcher, "/module.json");
313
+ if ("err" in man || man.status !== 200) {
314
+ const why = "err" in man ? man.err : `GET /module.json -> ${man.status}`;
315
+ checks.push(bad("manifest", why));
316
+ return checks; // no manifest -> nothing else can be meaningfully checked
317
+ }
318
+ const manifestChecks = checkManifest(man.body);
319
+ checks.push(...manifestChecks);
320
+ const manifest = validateManifest(man.body);
321
+ if (typeof manifest === "string")
322
+ return checks; // checkManifest already recorded the failure
323
+ // 2) first-hook invoke: well-formed envelope (+ typed payload when synchronous)
324
+ const hook = manifest.hooks[0];
325
+ const probe = await fetchJson(fetcher, "/invoke", {
326
+ method: "POST",
327
+ headers: { "content-type": "application/json" },
328
+ body: JSON.stringify({
329
+ hook,
330
+ // A plan.enhance-shaped input; for other hooks the module simply degrades (ok:false), which is
331
+ // still a conformant envelope. The gate validates the CONTRACT WIRING, not a real render.
332
+ input: { storyboard: { scenes: [{ prompt: "a quiet street at night" }] } },
333
+ config: {},
334
+ context: { project: "conformance", job_id: "install-gate" },
335
+ }),
336
+ });
337
+ if ("err" in probe || probe.status !== 200) {
338
+ const why = "err" in probe ? probe.err : `POST /invoke -> ${probe.status}`;
339
+ checks.push(bad("invoke", why));
340
+ }
341
+ else {
342
+ const env = checkInvokeResponse(probe.body);
343
+ checks.push(env);
344
+ const b = probe.body;
345
+ // Typed output is validated ONLY for a synchronous answer. An async module returns pending here, and
346
+ // proving its output shape would mean polling its real (GPU) job to completion at install time --
347
+ // see the SCOPE note above; async output conformance is the module's own CI, not this gate.
348
+ if (env.pass && b.ok === true && b.pending !== true) {
349
+ checks.push(checkHookOutput(hook, b.output));
350
+ }
351
+ }
352
+ // 3) degrade: a bad hook is DATA (HTTP 200 + ok:false), never a crash
353
+ const deg = await fetchJson(fetcher, "/invoke", {
354
+ method: "POST",
355
+ headers: { "content-type": "application/json" },
356
+ body: JSON.stringify({ hook: DEGRADE_PROBE_HOOK, input: {}, config: {}, context: { project: "conformance", job_id: "install-gate-degrade" } }),
357
+ });
358
+ if ("err" in deg || deg.status !== 200) {
359
+ const why = "err" in deg ? deg.err : `POST /invoke (bad hook) -> ${deg.status}`;
360
+ checks.push(bad("degrade", why));
361
+ }
362
+ else {
363
+ const shape = checkInvokeResponse(deg.body);
364
+ const okFalse = !!deg.body && typeof deg.body === "object" && deg.body.ok === false;
365
+ checks.push(shape.pass && okFalse ? ok("degrade", "bad hook -> 200 + ok:false") : bad("degrade", "bad hook must return 200 + ok:false"));
366
+ }
367
+ return checks;
368
+ }
369
+ //# sourceMappingURL=conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/modules/conformance.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,EAAE;AACF,+FAA+F;AAC/F,8FAA8F;AAC9F,8FAA8F;AAC9F,iCAAiC;AACjC,6DAA6D;AAC7D,4FAA4F;AAC5F,EAAE;AACF,kGAAkG;AAClG,kGAAkG;AAClG,mFAAmF;AAEnF,OAAO,EAAE,qBAAqB,EAAiB,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAQ1D,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,MAAM,GAAG,IAAI,EAAoB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAC7F,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,MAAc,EAAoB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AAEhG,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC/D,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAE3C,wFAAwF;AACxF,SAAS,gBAAgB,CAAC,GAAW,EAAE,CAAU;IAC/C,MAAM,KAAK,GAAG,SAAS,GAAG,GAAG,CAAC;IAC9B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;IAC7E,MAAM,EAAE,GAAG,CAA4B,CAAC;IACxC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;IAClB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACxG,qGAAqG;IACrG,IAAI,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACjG,OAAO,GAAG,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC,KAAK,EAAE,iCAAiC,CAAC,CAAC;QAC9G,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAE,EAAE,CAAC,MAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;YACrF,OAAO,GAAG,CAAC,KAAK,EAAE,oCAAoC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;SAAM,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;QACxB,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,GAAG,CAAC,KAAK,EAAE,gCAAgC,CAAC,CAAC;IAC3F,CAAC;SAAM,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,KAAK,EAAE,iCAAiC,CAAC,CAAC;IAC3F,CAAC;SAAM,CAAC;QACN,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,2BAA2B,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,MAAM,MAAM,GAAuB,EAAE,CAAC;IACtC,MAAM,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACvD,MAAM,CAAC,IAAI,CAAE,qBAA6C,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3E,CAAC,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,GAAG,qBAAqB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3F,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;QACnG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,kCAAkC,CAAC,CAAC,CAAC;IACtH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IACpF,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;QAClB,IAAI,QAAQ,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;QACpE,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC,iBAAiB,EAAE,0BAA0B,CAAC,CAAC;QAC/G,OAAO,GAAG,CAAC,iBAAiB,EAAE,6CAA6C,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,CAAC,CAAC,EAAE,KAAK,KAAK;QAAE,OAAO,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,iBAAiB,EAAE,oCAAoC,CAAC,CAAC;IAClK,OAAO,GAAG,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,CAAC;AACxD,CAAC;AAED;;;6EAG6E;AAC7E,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IACpF,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAC3D,IAAI,CAAC,CAAC,EAAE,KAAK,KAAK;QAAE,OAAO,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,iBAAiB,EAAE,oCAAoC,CAAC,CAAC;IAClK,OAAO,GAAG,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,CAAC;AACxD,CAAC;AAED,mGAAmG;AAEnG,MAAM,KAAK,GAAG,CAAC,CAAU,EAAgC,EAAE,CACzD,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACpD,MAAM,KAAK,GAAG,CAAC,CAAU,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;AACjE,MAAM,KAAK,GAAG,CAAC,CAAU,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvF,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAiB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAEnF;;;;;6CAK6C;AAC7C,MAAM,kBAAkB,GAAoE;IAC1F,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;QACd,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,wCAAwC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;YAAE,OAAO,qCAAqC,CAAC;QAC9E,MAAM,GAAG,GAAI,CAAC,CAAC,SAAuB,CAAC,IAAI,CACzC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAChE,CAAC;QACF,IAAI,GAAG;YAAE,OAAO,4CAA4C,CAAC;QAC7D,kEAAkE;QAClE,IAAI,CAAC,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;gBAAE,OAAO,iDAAiD,CAAC;YACtF,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1D,OAAO,6DAA6D,CAAC;YACvE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE;QACtB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,sCAAsC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;YAAE,OAAO,uCAAuC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,OAAO,mCAAmC,CAAC;QAC9D,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;YAAE,OAAO,sCAAsC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;QACZ,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,sCAAsC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;YAAE,OAAO,uCAAuC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,uCAAuC,CAAC;QACtE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;YAAE,OAAO,sCAAsC,CAAC;QACpE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,yCAAyC,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE;QACX,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;YAAE,OAAO,sCAAsC,CAAC;QACtE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,wCAAwC,CAAC;QAC1E,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;YAAE,OAAO,2EAA2E,CAAC;QACvI,OAAO,IAAI,CAAC;IACd,CAAC;IACD,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;QACd,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,wCAAwC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,kCAAkC,CAAC;QACvE,MAAM,QAAQ,GAAI,CAAC,CAAC,KAAmB,CAAC,IAAI,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CACnF,CAAC;QACF,IAAI,QAAQ;YAAE,OAAO,0DAA0D,CAAC;QAChF,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,2CAA2C,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;QACZ,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,sCAAsC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;YAAE,OAAO,wCAAwC,CAAC;QACzE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,yCAAyC,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE;QACpB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC;YAAE,OAAO,+CAA+C,CAAC;QACjF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,CAAC,CAAC,UAAsC,CAAC,MAAM,CAAC,EAAE,CAAC;YACrE,OAAO,0CAA0C,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;QAClB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,2CAA2C,CAAC;QAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;YAAE,OAAO,qCAAqC,CAAC;QAC3E,MAAM,GAAG,GAAI,CAAC,CAAC,MAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9F,IAAI,GAAG;YAAE,OAAO,kCAAkC,CAAC;QACnD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,6CAA6C,CAAC;QAC/E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;QACZ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YAAE,OAAO,0CAA0C,CAAC;QAC9E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;QACZ,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;YAAE,OAAO,wCAAwC,CAAC;QACzE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,yCAAyC,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;QACnB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;YAAE,OAAO,4CAA4C,CAAC;QAC5E,oGAAoG;QACpG,+FAA+F;QAC/F,2DAA2D;QAC3D,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,OAAO,uDAAuD,CAAC;QACpH,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;YAAE,OAAO,4EAA4E,CAAC;QACxI,IAAI,CAAC,CAAC,eAAe,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,CAAC,eAAe,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC;YAAE,OAAO,iFAAiF,CAAC;QACzO,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC;AAEF;;;4EAG4E;AAC5E,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAe;IAC3D,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAgB,CAAC,CAAC;IACvD,IAAI,CAAC,SAAS;QAAE,OAAO,GAAG,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,GAAG,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;0GAQ0G;AAC1G,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,IAAY,EAAE,MAAe;IACjF,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,QAAQ,aAAa,IAAI,cAAc,KAAK,CAAC,MAAM,EAAE,CAAC;AAC7F,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,OAAO,CAAC,MAA0B;IAChD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,QAAQ,CAAC,MAA0B;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAUD,uGAAuG;AACvG,oEAAoE;AACpE,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAE7C,KAAK,UAAU,SAAS,CACtB,OAA2B,EAC3B,IAAY,EACZ,IAAkB;IAElB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/D,IAAI,IAAI,GAAY,IAAI,CAAC;QACzB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,kBAAmB,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3F,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAiB,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IAChF,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;yCAiByC;AACzC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAA2B;IAClE,MAAM,MAAM,GAAuB,EAAE,CAAC;IAEtC,cAAc;IACd,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACrD,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,uBAAuB,GAAG,CAAC,MAAM,EAAE,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC,CAAC,0DAA0D;IAC3E,CAAC;IACD,MAAM,cAAc,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,CAAC,6CAA6C;IAE9F,gFAAgF;IAChF,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,IAAI;YACJ,+FAA+F;YAC/F,0FAA0F;YAC1F,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC,EAAE,EAAE;YAC1E,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE;SAC5D,CAAC;KACH,CAAC,CAAC;IACH,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,KAAK,CAAC,MAAM,EAAE,CAAC;QAC3E,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,CAAC,GAAG,KAAK,CAAC,IAA6D,CAAC;QAC9E,qGAAqG;QACrG,kGAAkG;QAClG,4FAA4F;QAC5F,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YACpD,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE;QAC9C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,CAAC;KAC/I,CAAC,CAAC;IACH,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,8BAA8B,GAAG,CAAC,MAAM,EAAE,CAAC;QAChF,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAK,GAAG,CAAC,IAAyB,CAAC,EAAE,KAAK,KAAK,CAAC;QAC1G,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,EAAE,4BAA4B,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,qCAAqC,CAAC,CAAC,CAAC;IAC3I,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type ModuleManifest } from "./types.js";
2
+ /** Validate a parsed manifest enough to trust it in the registry. Returns the typed manifest or a
3
+ * reason string. We check the contract version, a name, and that every declared hook is known. */
4
+ export declare function validateManifest(raw: unknown): ModuleManifest | string;
5
+ //# sourceMappingURL=manifest-validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-validate.d.ts","sourceRoot":"","sources":["../../src/modules/manifest-validate.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAEpB;mGACmG;AACnG,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,GAAG,MAAM,CA0CtE"}