@nodaro/shared 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodaro/shared",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "Shared types, model catalog, wire contracts, and structural vocabularies for the Nodaro platform and SDK.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -104,6 +104,23 @@ describe("appearance variations (cast-variations spec §4)", () => {
104
104
  })
105
105
  })
106
106
 
107
+ describe("variationFolds (cast-variations §4/§6 — review F5)", () => {
108
+ const meta = { durationSec: 10, width: 1920, height: 1080, aspectRatio: "16:9" }
109
+ const doc = {
110
+ meta,
111
+ slots: [slot],
112
+ scenes: [{ ...baseScene, sceneNumber: 1, visualResolved: "a man juggles", slotRefs: ["hero"] }],
113
+ }
114
+ it("videoAnalysisResultSchema round-trips variationFolds — strip-mode consumers keep the §6 fold note", () => {
115
+ const withFolds = { ...doc, variationFolds: [{ slotId: "hero", variationId: "era", label: "Era" }] }
116
+ expect(videoAnalysisResultSchema.parse(withFolds)).toEqual(withFolds)
117
+ })
118
+ it("absent variationFolds stays absent (no [] materialization)", () => {
119
+ const parsed = videoAnalysisResultSchema.parse(doc)
120
+ expect("variationFolds" in parsed && parsed.variationFolds !== undefined).toBe(false)
121
+ })
122
+ })
123
+
107
124
  describe("binding rewrite helpers (merge consumes — spec §4)", () => {
108
125
  it("rewriteSceneBindings renames slot keys and per-slot variation values", () => {
109
126
  expect(rewriteSceneBindings({ "man-2": "dream", other: "era" }, { "man-2": "hero" }, { hero: { dream: "flashback" } }))
@@ -128,6 +128,16 @@ export const videoAnalysisResultSchema = z.object({
128
128
  }),
129
129
  slots: z.array(entitySlotSchema),
130
130
  scenes: z.array(analyzedSceneSchema).min(1),
131
+ /** CAST VARIATIONS (§4 cap handling): looks the analyzer's merge FOLDED into
132
+ * the default at VIDEO_ANALYSIS_MAX_VARIATIONS — recorded, never silent. In
133
+ * the wire schema so strip-mode consumers (the recast client's validated
134
+ * blueprint view) keep it: the §6 "folded into default look" note is the
135
+ * user's only pre-pay defense against a wrong split. */
136
+ variationFolds: z.array(z.object({
137
+ slotId: z.string(),
138
+ variationId: z.string(),
139
+ label: z.string(),
140
+ })).optional(),
131
141
  })
132
142
  export type VideoAnalysisResult = z.infer<typeof videoAnalysisResultSchema>
133
143