BENCH-RITUAL-COLOR-001 — Color Preset cues in one Virtual Playback exclusion zone keep exactly one colour on the rig and fall back to its resting colour

tests/113-semantic-exclusive-color-playbacks.spec.ts:58 · migrated-semantic-world · last run: not merged

show: EmptyBrowser UICue timingDMX outputDesktop layoutEncoder controlsGroupsPlaybacksPresetsProgrammerProgrammer timingRecordingSelectionShow PatchShow filesTest clockTyped APIVirtual Playbacks
Preconditions (3)
ContextLine
Use the isolated Show.Empty show.
t.show.use(Show.Empty)
62
Open the ToskLight browser application.
t.app.open()
63
The ToskLight browser application is ready.
t.app.expect.ready()
64

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
65
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
66
Step
Patch → api → add with
{
   number:  1,
   name:  "Sunstrip",
   address:  "1.1",
   <unresolved: ...SUNSTRIP>
}
t.patch.via.api.add({ number: 1, name: "Sunstrip", address: "1.1", ...SUNSTRIP })
68
Step
Patch → api → add with
{
   number:  2,
   name:  "PAR L",
   address:  "1.41",
   <unresolved: ...PAR>
}
t.patch.via.api.add({ number: 2, name: "PAR L", address: "1.41", ...PAR })
69
Step
Patch → api → add with
{
   number:  3,
   name:  "PAR R",
   address:  "1.46",
   <unresolved: ...PAR>
}
t.patch.via.api.add({ number: 3, name: "PAR R", address: "1.46", ...PAR })
70
Step
Patch → api → add with
{
   number:  4,
   name:  "Wash",
   address:  "1.61",
   <unresolved: ...WASH_MOVER>
}
t.patch.via.api.add({ number: 4, name: "Wash", address: "1.61", ...WASH_MOVER })
71
Step
Selection → fixtures → api → items with 1, 2, 3, 4.
t.selection.fixtures.via.api.items(1, 2, 3, 4)
72
Step
Group → api → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(1, { mode: StoreMode.Overwrite })
73
Step
Clear the current selection.
t.selection.clear()
74
Step
Group → api → select with 1.
t.group.via.api.select(1)
78
Step
Encoder → color → red → api → set with <unresolved: color.red>.
t.encoder.color.red.via.api.set(color.red)
79
Step
Encoder → color → green → api → set with <unresolved: color.green>.
t.encoder.color.green.via.api.set(color.green)
80
Step
Encoder → color → blue → api → set with <unresolved: color.blue>.
t.encoder.color.blue.via.api.set(color.blue)
81
Step
Encoder → color → white → api → set with <unresolved: color.white>.
t.encoder.color.white.via.api.set(color.white)
82
Step
Preset → api → store with PresetFamily.Color, <unresolved: index + 1>,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Color, index + 1, {
				mode: "overwrite",
			})
83
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
86
Step
Clear the current selection.
t.selection.clear()
87
Step
Group → api → select with 1.
t.group.via.api.select(1)
92
Step
Encoder → intensity → dimmer → api → set with 100.
t.encoder.intensity.dimmer.via.api.set(100)
93
Step
Preset → api → recall with PresetFamily.Color, <unresolved: index + 1>.
t.preset.via.api.recall(PresetFamily.Color, index + 1)
94
Step
Record → playback with <unresolved: 1 + index>.
t.record.playback(1 + index)
95
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
96
Step
Clear the current selection.
t.selection.clear()
97
Step
Playback → configure with $playback (result of record.playback),
{
   name:  <unresolved: color.name>,
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: color.name,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Toggle,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
98
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
108
Step
Desktop → configure with .desktop: Colour ritual
t.desktop.configure("Colour ritual")
111
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{ slug: "colour-ritual", column: 1, row: 1, width: 12, height: 10 },
			{ rows: 1, columns: COLORS.length },
		)
112
Step
Apply the configured Desktop layout.
desktop.apply()
117
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), <unresolved: color.name>, <unresolved: index + 1>.
t.virtualPlayback.assignSource(pane, color.name, index + 1)
121
Step
Virtual playback → create solo region with attached shift with $pane (result of desktopBuilder.addPane), zone = "Solo Region 1", cells = <unresolved: COLORS.map((_, index) => index + 1)>.
t.virtualPlayback.createSoloRegionWithAttachedShift(pane, zone, cells)
126
Expected
Virtual playback → zones:
[
  {
     name:  zone = "Solo Region 1",
     members:  <unresolved: cells.map((cell) => ({ page: 1, position: 400 + cell }))>
  }
]
t.virtualPlayback.expect.zones([
			{ name: zone, members: cells.map((cell) => ({ page: 1, position: 400 + cell })) },
		])
127
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), <unresolved: index + 1>.
t.virtualPlayback.activate(pane, index + 1)
157
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
159
Expected
fixture(1, 2) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(1, 2), rgb(color.rgb))
144
Expected
fixture(1, 11) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(1, 11), rgb(color.rgb))
145
Expected
fixture(2) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(2), rgb(color.rgb))
146
Expected
fixture(3) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(3), rgb(color.rgb))
147
Expected
fixture(4) DMX equals
{
   <unresolved: ...rgb("moverRgb" in color ? color.moverRgb : color.rgb)>,
   "Color white":  <unresolved: byte(color.moverWhite)>,
   Intensity:  255
}
t.expectFixtureDMX(fixture(4), {
				...rgb("moverRgb" in color ? color.moverRgb : color.rgb),
				"Color white": byte(color.moverWhite),
				Intensity: 255,
			})
148
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
163
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
165
Expected
fixture(1, 2) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(1, 2), rgb(color.rgb))
144
Expected
fixture(1, 11) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(1, 11), rgb(color.rgb))
145
Expected
fixture(2) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(2), rgb(color.rgb))
146
Expected
fixture(3) DMX equals <unresolved: rgb(color.rgb)>.
t.expectFixtureDMX(fixture(3), rgb(color.rgb))
147
Expected
fixture(4) DMX equals
{
   <unresolved: ...rgb("moverRgb" in color ? color.moverRgb : color.rgb)>,
   "Color white":  <unresolved: byte(color.moverWhite)>,
   Intensity:  255
}
t.expectFixtureDMX(fixture(4), {
				...rgb("moverRgb" in color ? color.moverRgb : color.rgb),
				"Color white": byte(color.moverWhite),
				Intensity: 255,
			})
148
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
169
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
171
Expected
fixture(1, 2) DMX equals resting =
{
   "Color red":  255,
   "Color green":  255,
   "Color blue":  255
}
t.expectFixtureDMX(fixture(1, 2), resting)
173
Expected
fixture(1, 11) DMX equals resting =
{
   "Color red":  255,
   "Color green":  255,
   "Color blue":  255
}
t.expectFixtureDMX(fixture(1, 11), resting)
174
Expected
fixture(2) DMX equals resting =
{
   "Color red":  255,
   "Color green":  255,
   "Color blue":  255
}
t.expectFixtureDMX(fixture(2), resting)
175
Expected
fixture(3) DMX equals resting =
{
   "Color red":  255,
   "Color green":  255,
   "Color blue":  255
}
t.expectFixtureDMX(fixture(3), resting)
176
Expected
fixture(4) DMX equals
{
   <unresolved: ...resting>,
   "Color white":  255,
   Intensity:  0
}
t.expectFixtureDMX(fixture(4), {
			...resting,
			"Color white": 255,
			Intensity: 0,
		})
177

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionStep<unresolved: ...SUNSTRIP> Object member ...SUNSTRIP is not statically resolved.68
unresolved-expressionStep<unresolved: ...PAR> Object member ...PAR is not statically resolved.69
unresolved-expressionStep<unresolved: ...PAR> Object member ...PAR is not statically resolved.70
unresolved-expressionStep<unresolved: ...WASH_MOVER> Object member ...WASH_MOVER is not statically resolved.71
static-control-flowSourceControl flow for (const [index, color] of COLORS.entries()) { await t.group.via.api.select(1); await t.encoder.color.red.via.api.set(color.red); await t.encoder.color.green.via.api.set(color… is narrated once; iteration values are not guessed.77
unresolved-expressionStep<unresolved: color.red> Property access color.red depends on a runtime value.79
unresolved-expressionStep<unresolved: color.green> Property access color.green depends on a runtime value.80
unresolved-expressionStep<unresolved: color.blue> Property access color.blue depends on a runtime value.81
unresolved-expressionStep<unresolved: color.white> Property access color.white depends on a runtime value.82
unresolved-expressionStep<unresolved: index + 1> Expression index + 1 is not statically resolved.83
static-control-flowSourceControl flow for (const [index, color] of COLORS.entries()) { await t.group.via.api.select(1); await t.encoder.intensity.dimmer.via.api.set(100); await t.preset.via.api.recall(PresetFamily.C… is narrated once; iteration values are not guessed.91
unresolved-expressionStep<unresolved: index + 1> Expression index + 1 is not statically resolved.94
unresolved-expressionStep<unresolved: 1 + index> Expression 1 + index is not statically resolved.95
unresolved-expressionStep<unresolved: color.name> Property access color.name depends on a runtime value.99
static-control-flowSourceControl flow for (const [index, color] of COLORS.entries()) playbacks.push( await t.virtualPlayback.assignSource(pane, color.name, index + 1), ); is narrated once; iteration values are not guessed.119
unresolved-expressionStep<unresolved: color.name> Property access color.name depends on a runtime value.121
unresolved-expressionStep<unresolved: index + 1> Expression index + 1 is not statically resolved.121
unresolved-expressionStep<unresolved: COLORS.map((_, index) => index + 1)> Call expression COLORS.map((_, index) => index + 1) is dynamic and was not executed.123
unresolved-expressionExpected outcome<unresolved: cells.map((cell) => ({ page: 1, position: 400 + cell }))> Call expression cells.map((cell) => ({ page: 1, position: 400 + cell })) is dynamic and was not executed.128
static-control-flowSourceControl flow for (const [index, color] of COLORS.entries()) { await t.virtualPlayback.activate(pane, index + 1); await expectOnly(index); await t.clock.advanceStep(); await expectRig(color); } is narrated once; iteration values are not guessed.156
unresolved-expressionStep<unresolved: index + 1> Expression index + 1 is not statically resolved.157
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.144
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.145
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.146
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.147
unresolved-expressionExpected outcome<unresolved: ...rgb("moverRgb" in color ? color.moverRgb : color.rgb)> Object member ...rgb("moverRgb" in color ? color.moverRgb : color.rgb) is not statically resolved.149
unresolved-expressionExpected outcome<unresolved: byte(color.moverWhite)> Call expression byte(color.moverWhite) is dynamic and was not executed.150
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.144
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.145
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.146
unresolved-expressionExpected outcome<unresolved: rgb(color.rgb)> Call expression rgb(color.rgb) is dynamic and was not executed.147
unresolved-expressionExpected outcome<unresolved: ...rgb("moverRgb" in color ? color.moverRgb : color.rgb)> Object member ...rgb("moverRgb" in color ? color.moverRgb : color.rgb) is not statically resolved.149
unresolved-expressionExpected outcome<unresolved: byte(color.moverWhite)> Call expression byte(color.moverWhite) is dynamic and was not executed.150
unresolved-expressionExpected outcome<unresolved: ...resting> Object member ...resting is not statically resolved.178

BENCH-DYNAMIC-REUSE-001 — one targetless Dynamic applied to two mover Groups runs on each Group's own Virtual Playback and nowhere else

tests/114-semantic-dynamic-reuse-across-groups.spec.ts:39 · migrated-semantic-world · last run: not merged

show: EmptyBrowser UICue timingDMX outputDesktop layoutDynamicsEncoder controlsGroupsPlaybacksPresetsProgrammerProgrammer timingRecordingSelectionShow PatchShow filesTest clockTyped APIVirtual Playbacks
Preconditions (3)
ContextLine
Use the isolated Show.Empty show.
t.show.use(Show.Empty)
43
Open the ToskLight browser application.
t.app.open()
44
The ToskLight browser application is ready.
t.app.expect.ready()
45

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
46
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
47
Step
Patch → api → add with
{
   number:  number = ...<unresolved: GROUP_ONE>,
   name:  "Mover number = ...<unresolved: GROUP_ONE>", address: "1.<unresolved: 1 + (number - 1) * 15>", location: { x: <unresolved: ((number - 1) % 4) * 1000>, y: <unresolved: number <= 4 ? 0 : 1000>, z: 0 }, <unresolved: ...MOVER> }
t.patch.via.api.add({
				number,
				name: `Mover ${number}`,
				address: `1.${1 + (number - 1) * 15}`,
				location: {
					x: ((number - 1) % 4) * 1000,
					y: number <= 4 ? 0 : 1000,
					z: 0,
				},
				...MOVER,
			})
50
Step
Patch → api → add with
{
   number:  number = ...<unresolved: GROUP_TWO>,
   name:  "Mover number = ...<unresolved: GROUP_TWO>", address: "1.<unresolved: 1 + (number - 1) * 15>", location: { x: <unresolved: ((number - 1) % 4) * 1000>, y: <unresolved: number <= 4 ? 0 : 1000>, z: 0 }, <unresolved: ...MOVER> }
t.patch.via.api.add({
				number,
				name: `Mover ${number}`,
				address: `1.${1 + (number - 1) * 15}`,
				location: {
					x: ((number - 1) % 4) * 1000,
					y: number <= 4 ? 0 : 1000,
					z: 0,
				},
				...MOVER,
			})
50
Step
Selection → fixtures → api → items with ...<unresolved: GROUP_ONE>.
t.selection.fixtures.via.api.items(...GROUP_ONE)
61
Step
Group → api → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(1, { mode: StoreMode.Overwrite })
62
Step
Selection → fixtures → api → items with ...<unresolved: GROUP_TWO>.
t.selection.fixtures.via.api.items(...GROUP_TWO)
63
Step
Group → api → store with 2,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(2, { mode: StoreMode.Overwrite })
64
Expected
Group → fixtures: 1, ...<unresolved: GROUP_ONE>.
t.group.expect(1).fixtures(...GROUP_ONE)
65
Expected
Group → fixtures: 2, ...<unresolved: GROUP_TWO>.
t.group.expect(2).fixtures(...GROUP_TWO)
66
Step
Selection → fixtures → api → items with ...<unresolved: GROUP_ONE>, ...<unresolved: GROUP_TWO>.
t.selection.fixtures.via.api.items(...GROUP_ONE, ...GROUP_TWO)
73
Step
Encoder → position → pan → api → set with <unresolved: position.pan>.
t.encoder.position.pan.via.api.set(position.pan)
74
Step
Encoder → position → tilt → api → set with <unresolved: position.tilt>.
t.encoder.position.tilt.via.api.set(position.tilt)
75
Step
Preset → api → store with PresetFamily.Position, number = 1,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Position, number, {
				mode: "overwrite",
			})
76
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
79
Step
Selection → fixtures → api → items with ...<unresolved: GROUP_ONE>, ...<unresolved: GROUP_TWO>.
t.selection.fixtures.via.api.items(...GROUP_ONE, ...GROUP_TWO)
73
Step
Encoder → position → pan → api → set with <unresolved: position.pan>.
t.encoder.position.pan.via.api.set(position.pan)
74
Step
Encoder → position → tilt → api → set with <unresolved: position.tilt>.
t.encoder.position.tilt.via.api.set(position.tilt)
75
Step
Preset → api → store with PresetFamily.Position, number = 2,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Position, number, {
				mode: "overwrite",
			})
76
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
79
Step
Clear the current selection.
t.selection.clear()
81
Step
Dynamic → create with
{ pool: 1, name: "Rise", cycleMillis: <unresolved: CYCLE_MILLIS>, gridAngleDegrees: 0, lanes: [{ attribute: "intensity", keyframes: [[0, 0], [1, 1]] }, ...<unresolved: (["position:pan", "position:tilt"] as const).map((attribute) => ({ attribute, keyframes: [ [0, { preset: { family: PresetFamily.Position, number: 1 } }], [1, { preset: { family:…>] }.
t.dynamic.create({
			pool: 1,
			name: "Rise",
			cycleMillis: CYCLE_MILLIS,
			gridAngleDegrees: 0,
			lanes: [
				{ attribute: "intensity", keyframes: [[0, 0], [1, 1]] },
				...(["position:pan", "position:tilt"] as const).map((attribute) => ({
					attribute,
					keyframes: [
						[0, { preset: { family: PresetFamily.Position, number: 1 } }],
						[1, { preset: { family: PresetFamily.Position, number: 2 } }],
					] as Array<
						[number, { preset: { family: PresetFamily; number: number } }]
					>,
				})),
			],
		})
84
Expected
Dynamic → targetless: $dynamic (result of dynamic.create).
t.dynamic.expect(dynamic).targetless()
102
Step
Group → api → select with group = 1.
t.group.via.api.select(group)
106
Step
Dynamic → apply with $dynamic (result of dynamic.create).
t.dynamic.apply(dynamic)
107
Step
Record → playback with <unresolved: 1 + index>.
t.record.playback(1 + index)
108
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
109
Step
Clear the current selection.
t.selection.clear()
110
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Rise group = 1",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Rise ${group}`,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Toggle,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
111
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
121
Step
Group → api → select with group = 2.
t.group.via.api.select(group)
106
Step
Dynamic → apply with $dynamic (result of dynamic.create).
t.dynamic.apply(dynamic)
107
Step
Record → playback with <unresolved: 1 + index>.
t.record.playback(1 + index)
108
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
109
Step
Clear the current selection.
t.selection.clear()
110
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Rise group = 2",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Rise ${group}`,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Toggle,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
111
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
121
Expected
Dynamic → targetless: $dynamic (result of dynamic.create).
t.dynamic.expect(dynamic).targetless()
124
Step
Desktop → configure with .desktop: Dynamic reuse
t.desktop.configure("Dynamic reuse")
126
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{ slug: "dynamic-reuse", column: 1, row: 1, width: 12, height: 10 },
			{ rows: 1, columns: 2 },
		)
127
Step
Apply the configured Desktop layout.
desktop.apply()
132
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Rise 1", 1.
t.virtualPlayback.assignSource(pane, "Rise 1", 1)
133
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Rise 2", 2.
t.virtualPlayback.assignSource(pane, "Rise 2", 2)
134
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
163
Expected
Virtual playback → runtime: $first (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(first, { runtime: { enabled: true } })
164
Expected
Virtual playback → runtime: $second (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  false
  }
}
t.virtualPlayback.expect.runtime(second, { runtime: { enabled: false } })
165
Step
Advance the test clock by quarter = "<unresolved: CYCLE_MILLIS / 4>ms".
t.clock.advanceBy(quarter)
166
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: near(phase)>,
   "Tilt coarse":  <unresolved: between("tilt")>,
   "Pan coarse":  <unresolved: between("pan")>
}
t.expectFixtureDMX(fixture(number), {
					Intensity: near(phase),
					"Tilt coarse": between("tilt"),
					"Pan coarse": between("pan"),
				})
149
Expected
fixture(number) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(number), { Intensity: 0 })
158
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
171
Expected
Virtual playback → runtime: $first (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(first, { runtime: { enabled: true } })
172
Expected
Virtual playback → runtime: $second (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(second, { runtime: { enabled: true } })
173
Step
Advance the test clock by quarter = "<unresolved: CYCLE_MILLIS / 4>ms".
t.clock.advanceBy(quarter)
174
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: near(phase)>,
   "Tilt coarse":  <unresolved: between("tilt")>,
   "Pan coarse":  <unresolved: between("pan")>
}
t.expectFixtureDMX(fixture(number), {
					Intensity: near(phase),
					"Tilt coarse": between("tilt"),
					"Pan coarse": between("pan"),
				})
149
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: near(phase)>,
   "Tilt coarse":  <unresolved: between("tilt")>,
   "Pan coarse":  <unresolved: between("pan")>
}
t.expectFixtureDMX(fixture(number), {
					Intensity: near(phase),
					"Tilt coarse": between("tilt"),
					"Pan coarse": between("pan"),
				})
149
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
179
Expected
Virtual playback → runtime: $first (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  false
  }
}
t.virtualPlayback.expect.runtime(first, { runtime: { enabled: false } })
180
Expected
Virtual playback → runtime: $second (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(second, { runtime: { enabled: true } })
181
Step
Advance the test clock by quarter = "<unresolved: CYCLE_MILLIS / 4>ms".
t.clock.advanceBy(quarter)
182
Expected
fixture(number) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(number), { Intensity: 0 })
158
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: near(phase)>,
   "Tilt coarse":  <unresolved: between("tilt")>,
   "Pan coarse":  <unresolved: between("pan")>
}
t.expectFixtureDMX(fixture(number), {
					Intensity: near(phase),
					"Tilt coarse": between("tilt"),
					"Pan coarse": between("pan"),
				})
149
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
186
Expected
Virtual playback → runtime: $second (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  false
  }
}
t.virtualPlayback.expect.runtime(second, { runtime: { enabled: false } })
187
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
188
Expected
fixture(number) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(number), { Intensity: 0 })
158
Expected
fixture(number) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(number), { Intensity: 0 })
158
Expected
Dynamic → targetless: $dynamic (result of dynamic.create).
t.dynamic.expect(dynamic).targetless()
191

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionStep<unresolved: GROUP_ONE> Expression GROUP_ONE is not statically resolved.49
unresolved-expressionStep<unresolved: GROUP_ONE> Expression GROUP_ONE is not statically resolved.49
unresolved-expressionStep<unresolved: 1 + (number - 1) * 15> Expression 1 + (number - 1) * 15 is not statically resolved.53
unresolved-expressionStep<unresolved: ((number - 1) % 4) * 1000> Expression ((number - 1) % 4) * 1000 is not statically resolved.55
unresolved-expressionStep<unresolved: number <= 4 ? 0 : 1000> Expression number <= 4 ? 0 : 1000 is not statically resolved.56
unresolved-expressionStep<unresolved: ...MOVER> Object member ...MOVER is not statically resolved.59
unresolved-expressionStep<unresolved: GROUP_TWO> Expression GROUP_TWO is not statically resolved.49
unresolved-expressionStep<unresolved: GROUP_TWO> Expression GROUP_TWO is not statically resolved.49
unresolved-expressionStep<unresolved: 1 + (number - 1) * 15> Expression 1 + (number - 1) * 15 is not statically resolved.53
unresolved-expressionStep<unresolved: ((number - 1) % 4) * 1000> Expression ((number - 1) % 4) * 1000 is not statically resolved.55
unresolved-expressionStep<unresolved: number <= 4 ? 0 : 1000> Expression number <= 4 ? 0 : 1000 is not statically resolved.56
unresolved-expressionStep<unresolved: ...MOVER> Object member ...MOVER is not statically resolved.59
unresolved-expressionStep<unresolved: GROUP_ONE> Expression GROUP_ONE is not statically resolved.61
unresolved-expressionStep<unresolved: GROUP_TWO> Expression GROUP_TWO is not statically resolved.63
unresolved-expressionExpected outcome<unresolved: GROUP_ONE> Expression GROUP_ONE is not statically resolved.65
unresolved-expressionExpected outcome<unresolved: GROUP_TWO> Expression GROUP_TWO is not statically resolved.66
unresolved-expressionStep<unresolved: GROUP_ONE> Expression GROUP_ONE is not statically resolved.73
unresolved-expressionStep<unresolved: GROUP_TWO> Expression GROUP_TWO is not statically resolved.73
unresolved-expressionStep<unresolved: position.pan> Property access position.pan depends on a runtime value.74
unresolved-expressionStep<unresolved: position.tilt> Property access position.tilt depends on a runtime value.75
unresolved-expressionStep<unresolved: GROUP_ONE> Expression GROUP_ONE is not statically resolved.73
unresolved-expressionStep<unresolved: GROUP_TWO> Expression GROUP_TWO is not statically resolved.73
unresolved-expressionStep<unresolved: position.pan> Property access position.pan depends on a runtime value.74
unresolved-expressionStep<unresolved: position.tilt> Property access position.tilt depends on a runtime value.75
unresolved-expressionStep<unresolved: CYCLE_MILLIS> Expression CYCLE_MILLIS is not statically resolved.87
unresolved-expressionStep<unresolved: (["position:pan", "position:tilt"] as const).map((attribute) => ({ attribute, keyframes: [ [0, { preset: { family: PresetFamily.Position, number: 1 } }], [1, { preset: { family:…> Call expression (["position:pan", "position:tilt"] as const).map((attribute) => ({ attribute, keyframes: [ [0, { preset: { family: PresetFamily.Position, number: 1 } }], [1, { preset: { family:… is dynamic and was not executed.91
unresolved-expressionStep<unresolved: 1 + index> Expression 1 + index is not statically resolved.108
unresolved-expressionStep<unresolved: 1 + index> Expression 1 + index is not statically resolved.108
unresolved-expressionStep<unresolved: CYCLE_MILLIS / 4> Expression CYCLE_MILLIS / 4 is not statically resolved.160
static-control-flowSourceControl flow for (const [index, number] of members.entries()) { const phase = (progress + index * 0.25) % 1; const between = (axis: "pan" | "tilt") => { const from = percentOfTravel(axis, DO… is narrated once; iteration values are not guessed.142
unresolved-expressionExpected outcome<unresolved: near(phase)> Call expression near(phase) is dynamic and was not executed.150
unresolved-expressionExpected outcome<unresolved: between("tilt")> Call expression between("tilt") is dynamic and was not executed.151
unresolved-expressionExpected outcome<unresolved: between("pan")> Call expression between("pan") is dynamic and was not executed.152
static-control-flowSourceControl flow for (const number of members) await t.expectFixtureDMX(fixture(number), { Intensity: 0 }); is narrated once; iteration values are not guessed.157
unresolved-expressionStep<unresolved: CYCLE_MILLIS / 4> Expression CYCLE_MILLIS / 4 is not statically resolved.160
static-control-flowSourceControl flow for (const [index, number] of members.entries()) { const phase = (progress + index * 0.25) % 1; const between = (axis: "pan" | "tilt") => { const from = percentOfTravel(axis, DO… is narrated once; iteration values are not guessed.142
unresolved-expressionExpected outcome<unresolved: near(phase)> Call expression near(phase) is dynamic and was not executed.150
unresolved-expressionExpected outcome<unresolved: between("tilt")> Call expression between("tilt") is dynamic and was not executed.151
unresolved-expressionExpected outcome<unresolved: between("pan")> Call expression between("pan") is dynamic and was not executed.152
static-control-flowSourceControl flow for (const [index, number] of members.entries()) { const phase = (progress + index * 0.25) % 1; const between = (axis: "pan" | "tilt") => { const from = percentOfTravel(axis, DO… is narrated once; iteration values are not guessed.142
unresolved-expressionExpected outcome<unresolved: near(phase)> Call expression near(phase) is dynamic and was not executed.150
unresolved-expressionExpected outcome<unresolved: between("tilt")> Call expression between("tilt") is dynamic and was not executed.151
unresolved-expressionExpected outcome<unresolved: between("pan")> Call expression between("pan") is dynamic and was not executed.152
unresolved-expressionStep<unresolved: CYCLE_MILLIS / 4> Expression CYCLE_MILLIS / 4 is not statically resolved.160
static-control-flowSourceControl flow for (const number of members) await t.expectFixtureDMX(fixture(number), { Intensity: 0 }); is narrated once; iteration values are not guessed.157
static-control-flowSourceControl flow for (const [index, number] of members.entries()) { const phase = (progress + index * 0.25) % 1; const between = (axis: "pan" | "tilt") => { const from = percentOfTravel(axis, DO… is narrated once; iteration values are not guessed.142
unresolved-expressionExpected outcome<unresolved: near(phase)> Call expression near(phase) is dynamic and was not executed.150
unresolved-expressionExpected outcome<unresolved: between("tilt")> Call expression between("tilt") is dynamic and was not executed.151
unresolved-expressionExpected outcome<unresolved: between("pan")> Call expression between("pan") is dynamic and was not executed.152

BENCH-TEMP-RELEASE-001 — a Temp runs a Sunstrip Cuelist with its timing, follows into the release, and turns itself off once nothing is held

tests/115-semantic-temp-release-shutdown.spec.ts:22 · migrated-semantic-world · last run: not merged

show: EmptyBrowser UICommand keypadCommand lineCue runtimeCue timingCuesDMX outputDesktop layoutEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionShow PatchShow filesTest clockTyped APIVirtual Playbacks
Preconditions (3)
ContextLine
Use the isolated Show.Empty show.
t.show.use(Show.Empty)
26
Open the ToskLight browser application.
t.app.open()
27
The ToskLight browser application is ready.
t.app.expect.ready()
28

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
29
Step
Patch → api → add with
{
   number:  1,
   name:  "Sunstrip",
   address:  "1.1",
   <unresolved: ...SUNSTRIP_DIMMERS>
}
t.patch.via.api.add({ number: 1, name: "Sunstrip", address: "1.1", ...SUNSTRIP_DIMMERS })
31
Step
Patch → api → add with
{
   number:  2,
   name:  "Sunstrip RGB",
   address:  "1.11",
   <unresolved: ...SUNSTRIP>
}
t.patch.via.api.add({ number: 2, name: "Sunstrip RGB", address: "1.11", ...SUNSTRIP })
32
Step
Selection → fixtures → api → items with 1, 2.
t.selection.fixtures.via.api.items(1, 2)
35
Step
Encoder → intensity → dimmer → api → set with 100.
t.encoder.intensity.dimmer.via.api.set(100)
36
Step
Selection → fixtures → api → item with 2.
t.selection.fixtures.via.api.item(2)
37
Step
Encoder → color → red → api → set with 100.
t.encoder.color.red.via.api.set(100)
38
Step
Encoder → color → green → api → set with 100.
t.encoder.color.green.via.api.set(100)
39
Step
Encoder → color → blue → api → set with 100.
t.encoder.color.blue.via.api.set(100)
40
Step
Record → playback with 1.
t.record.playback(1)
41
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
42
Step
Command → type with "FIXTURE 1 THRU 2".
t.command.type("FIXTURE 1 THRU 2")
45
Step
Press keypad keys
[
  "SHIFT",
   "OFF",
   "0",
   "SHIFT",
   "ENT"
]
t.keypad.press(["SHIFT", "OFF", "0", "SHIFT", "ENT"])
46
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
47
Expected
Cue → present: $playback (result of record.playback), 2.
t.cue.expect(playback, 2).present()
48
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
49
Step
Clear the current selection.
t.selection.clear()
50
Step
Cue → open editor with $playback (result of record.playback).
t.cue.openEditor(playback)
53
Step
Cue editor → edit with 1,
{
   fade:  "0.2",
   outFade:  "1"
}
editor.edit(1, { fade: "0.2", outFade: "1" })
54
Step
Cue editor → edit with 2,
{
   fade:  "1",
   trigger:  "FOLLOW",
   triggerTime:  "0.3"
}
editor.edit(2, { fade: "1", trigger: "FOLLOW", triggerTime: "0.3" })
55
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Strip release",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Temp,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
			name: "Strip release",
			buttonCount: 1,
			hasFader: false,
			buttons: [PlaybackButton.Temp, PlaybackButton.Empty, PlaybackButton.Empty],
		})
57
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
63
Step
Desktop → configure with .desktop: Temp release
t.desktop.configure("Temp release")
64
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{ slug: "temp-release", column: 1, row: 1, width: 12, height: 10 },
			{ rows: 1, columns: 1 },
		)
65
Step
Apply the configured Desktop layout.
desktop.apply()
70
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Strip release", 1.
t.virtualPlayback.assignSource(pane, "Strip release", 1)
71
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
80
Expected
fixture(1, head) DMX equals
{
   Intensity:  level = 0
}
t.expectFixtureDMX(fixture(1, head), { Intensity: level })
77
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
82
Expected
Virtual playback → runtime: $temp (result of virtualPlayback.assignSource),
{
   runtime:  {
     temporary_active:  true
  }
}
t.virtualPlayback.expect.runtime(temp, {
			runtime: { temporary_active: true },
		})
83
Step
Advance the test clock by "100ms".
t.clock.advanceBy("100ms")
86
Expected
fixture(1, head) DMX equals
{
   Intensity:  level = {
     between:  [
      100,
       155
    ]
  }
}
t.expectFixtureDMX(fixture(1, head), { Intensity: level })
77
Step
Advance the test clock by "110ms".
t.clock.advanceBy("110ms")
88
Expected
fixture(1, head) DMX equals
{
   Intensity:  level = 255
}
t.expectFixtureDMX(fixture(1, head), { Intensity: level })
77
Step
Advance the test clock by "300ms".
t.clock.advanceBy("300ms")
92
Expected
Virtual playback → runtime: $temp (result of virtualPlayback.assignSource),
{
   runtime:  {
     temporary_active:  true
  }
}
t.virtualPlayback.expect.runtime(temp, {
			runtime: { temporary_active: true },
		})
93
Step
Advance the test clock by "500ms".
t.clock.advanceBy("500ms")
96
Expected
fixture(1, head) DMX equals
{
   Intensity:  level = {
     between:  [
      100,
       155
    ]
  }
}
t.expectFixtureDMX(fixture(1, head), { Intensity: level })
77
Step
Advance the test clock by "510ms".
t.clock.advanceBy("510ms")
101
Expected
fixture(1, head) DMX equals
{
   Intensity:  level = 0
}
t.expectFixtureDMX(fixture(1, head), { Intensity: level })
77
Expected
Virtual playback → runtime: $temp (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  false
  }
}
t.virtualPlayback.expect.runtime(temp, { runtime: { enabled: false } })
103
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
105
Expected
Virtual playback → runtime: $temp (result of virtualPlayback.assignSource),
{
   runtime:  {
     temporary_active:  true
  }
}
t.virtualPlayback.expect.runtime(temp, {
			runtime: { temporary_active: true },
		})
106
Step
Advance the test clock by "210ms".
t.clock.advanceBy("210ms")
109
Expected
fixture(1, head) DMX equals
{
   Intensity:  level = 255
}
t.expectFixtureDMX(fixture(1, head), { Intensity: level })
77

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionStep<unresolved: ...SUNSTRIP_DIMMERS> Object member ...SUNSTRIP_DIMMERS is not statically resolved.31
unresolved-expressionStep<unresolved: ...SUNSTRIP> Object member ...SUNSTRIP is not statically resolved.32

BENCH-DYNAMIC-EDITOR-001 — a two-axis Circle built by touch in the Dynamics editor stores typed Angle lanes in degrees and moves the movers

tests/127-dynamic-editor-position-circle.spec.ts:27 · migrated-semantic-world · last run: not merged

show: EmptyBrowser UICue timingDMX outputDynamicsGroupsProgrammer timingSelectionShow PatchShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.Empty show.
t.show.use(Show.Empty)
31
Open the ToskLight browser application.
t.app.open()
32
The ToskLight browser application is ready.
t.app.expect.ready()
33

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
34
Step
Patch → api → add with
{
   number:  <unresolved: number>,
   name:  "Mover <unresolved: number>", address: "1.<unresolved: 1 + (number - 1) * 15>", <unresolved: ...MOVER> }
t.patch.via.api.add({
				number,
				name: `Mover ${number}`,
				address: `1.${1 + (number - 1) * 15}`,
				...MOVER,
			})
37
Step
Selection → fixtures → api → items with ...<unresolved: MOVERS>.
t.selection.fixtures.via.api.items(...MOVERS)
43
Step
Group → api → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(1, { mode: StoreMode.Overwrite })
44
Step
Group → api → select with 1.
t.group.via.api.select(1)
45
Step
Built in → open with PaneType.Dynamics.
t.builtIn.open(PaneType.Dynamics)
47
Step
Tap empty Dynamics tile 1 and choose the lane
{
   group:  "position",
   attribute:  "Pan"
}
in the lane chooser.
t.dynamic.editor.create(1, {
			group: "position",
			attribute: "Pan",
		})
50
Expected
$circle (result of dynamic.editor.create) stores the lanes
[
  {
     family:  "position",
     component:  "pan"
  },
   {
     family:  "position",
     component:  "tilt"
  }
]
t.dynamic.editor.expect.lanes(circle, [
			{ family: "position", component: "pan" },
			{ family: "position", component: "tilt" },
		])
54
Expected
The "Middle" lane encoder reads "Current".
t.dynamic.editor.expect.encoder("Middle", "Current")
58
Expected
The "Amplitude" lane encoder reads "45°".
t.dynamic.editor.expect.encoder("Amplitude", "45°")
59
Step
Enter <unresolved: String(PAN_AMPLITUDE)> on the "Amplitude" lane encoder's value modal.
t.dynamic.editor.setEncoder("Amplitude", String(PAN_AMPLITUDE))
60
Expected
The "Amplitude" lane encoder reads "<unresolved: PAN_AMPLITUDE>°".
t.dynamic.editor.expect.encoder("Amplitude", `${PAN_AMPLITUDE}°`)
61
Step
Tap + Add Lane and choose the lane
{
   group:  "position",
   attribute:  "Tilt"
}
t.dynamic.editor.addLane(circle, { group: "position", attribute: "Tilt" })
64
Expected
$circle (result of dynamic.editor.create) stores the lanes
[
  {
     family:  "position",
     component:  "pan"
  },
   {
     family:  "position",
     component:  "tilt"
  }
]
t.dynamic.editor.expect.lanes(circle, [
			{ family: "position", component: "pan" },
			{ family: "position", component: "tilt" },
		])
65
Step
Select lane 2, "Tilt", in the Dynamics editor.
t.dynamic.editor.selectLane(2, "Tilt")
69
Step
Choose the "Cosinus" curve function for the selected lane.
t.dynamic.editor.chooseCurve("Cosinus")
70
Expected
The "Amplitude" lane encoder reads "<unresolved: TILT_AMPLITUDE>°".
t.dynamic.editor.expect.encoder("Amplitude", `${TILT_AMPLITUDE}°`)
71
Expected
Dynamic → editor → lane configuration: $circle (result of dynamic.editor.create), 1,
{
   mode:  "middle_amplitude",
   configuration:  {
     function:  "sinus",
     middle:  {
       kind:  "current"
    },
     amplitude:  {
       kind:  "scalar",
       value:  <unresolved: PAN_AMPLITUDE>
    }
  }
}
t.dynamic.editor.expect.laneConfiguration(circle, 1, {
			mode: "middle_amplitude",
			configuration: {
				function: "sinus",
				middle: { kind: "current" },
				amplitude: { kind: "scalar", value: PAN_AMPLITUDE },
			},
		})
72
Expected
Dynamic → editor → lane configuration: $circle (result of dynamic.editor.create), 2,
{
   mode:  "middle_amplitude",
   configuration:  {
     function:  "cosinus",
     middle:  {
       kind:  "current"
    },
     amplitude:  {
       kind:  "scalar",
       value:  <unresolved: TILT_AMPLITUDE>
    }
  }
}
t.dynamic.editor.expect.laneConfiguration(circle, 2, {
			mode: "middle_amplitude",
			configuration: {
				function: "cosinus",
				middle: { kind: "current" },
				amplitude: { kind: "scalar", value: TILT_AMPLITUDE },
			},
		})
80
Expected
The Dynamics editor shows no error.
t.dynamic.editor.expect.noError()
88
Step
In Dynamic Settings › Targets tap Take Selection, then go back to the pool.
t.dynamic.editor.takeSelectionAndClose()
90
Step
Tap the pool tile of $circle (result of dynamic.editor.create) to toggle it.
t.dynamic.editor.toggle(circle)
91
Step
Advance the test clock by "<unresolved: CYCLE_MILLIS / 4>ms".
t.clock.advanceBy(`${CYCLE_MILLIS / 4}ms`)
107
Expected
fixture(number) DMX equals
{
   "Pan coarse":  <unresolved: angle("pan", PAN_AMPLITUDE * Math.sin(turn))>,
   "Tilt coarse":  <unresolved: angle("tilt", TILT_AMPLITUDE * Math.cos(turn))>
}
t.expectFixtureDMX(fixture(number), {
					"Pan coarse": angle("pan", PAN_AMPLITUDE * Math.sin(turn)),
					"Tilt coarse": angle("tilt", TILT_AMPLITUDE * Math.cos(turn)),
				})
100
Step
Advance the test clock by "<unresolved: CYCLE_MILLIS / 4>ms".
t.clock.advanceBy(`${CYCLE_MILLIS / 4}ms`)
107
Expected
fixture(number) DMX equals
{
   "Pan coarse":  <unresolved: angle("pan", PAN_AMPLITUDE * Math.sin(turn))>,
   "Tilt coarse":  <unresolved: angle("tilt", TILT_AMPLITUDE * Math.cos(turn))>
}
t.expectFixtureDMX(fixture(number), {
					"Pan coarse": angle("pan", PAN_AMPLITUDE * Math.sin(turn)),
					"Tilt coarse": angle("tilt", TILT_AMPLITUDE * Math.cos(turn)),
				})
100
Step
Advance the test clock by "<unresolved: CYCLE_MILLIS / 4>ms".
t.clock.advanceBy(`${CYCLE_MILLIS / 4}ms`)
107
Expected
fixture(number) DMX equals
{
   "Pan coarse":  <unresolved: angle("pan", PAN_AMPLITUDE * Math.sin(turn))>,
   "Tilt coarse":  <unresolved: angle("tilt", TILT_AMPLITUDE * Math.cos(turn))>
}
t.expectFixtureDMX(fixture(number), {
					"Pan coarse": angle("pan", PAN_AMPLITUDE * Math.sin(turn)),
					"Tilt coarse": angle("tilt", TILT_AMPLITUDE * Math.cos(turn)),
				})
100

Diagnostics

DiagnosticWhereDetailLine
static-control-flowSourceControl flow for (const number of MOVERS) await t.patch.via.api.add({ number, name: `Mover ${number}`, address: `1.${1 + (number - 1) * 15}`, ...MOVER, }); is narrated once; iteration values are not guessed.36
unresolved-expressionStep<unresolved: number> Expression number is not statically resolved.38
unresolved-expressionStep<unresolved: number> Expression number is not statically resolved.39
unresolved-expressionStep<unresolved: 1 + (number - 1) * 15> Expression 1 + (number - 1) * 15 is not statically resolved.40
unresolved-expressionStep<unresolved: ...MOVER> Object member ...MOVER is not statically resolved.41
unresolved-expressionStep<unresolved: MOVERS> Expression MOVERS is not statically resolved.43
unresolved-expressionStep<unresolved: String(PAN_AMPLITUDE)> Call expression String(PAN_AMPLITUDE) is dynamic and was not executed.60
unresolved-expressionExpected outcome<unresolved: PAN_AMPLITUDE> Expression PAN_AMPLITUDE is not statically resolved.61
unresolved-expressionExpected outcome<unresolved: TILT_AMPLITUDE> Expression TILT_AMPLITUDE is not statically resolved.71
unresolved-expressionExpected outcome<unresolved: PAN_AMPLITUDE> Expression PAN_AMPLITUDE is not statically resolved.77
unresolved-expressionExpected outcome<unresolved: TILT_AMPLITUDE> Expression TILT_AMPLITUDE is not statically resolved.85
unresolved-expressionStep<unresolved: CYCLE_MILLIS / 4> Expression CYCLE_MILLIS / 4 is not statically resolved.107
static-control-flowSourceControl flow for (const [index, number] of MOVERS.entries()) { const turn = 2 * Math.PI * ((phase + index * 0.5) % 1); await t.expectFixtureDMX(fixture(number), { "Pan coarse": angle("pan", … is narrated once; iteration values are not guessed.98
unresolved-expressionExpected outcome<unresolved: angle("pan", PAN_AMPLITUDE * Math.sin(turn))> Call expression angle("pan", PAN_AMPLITUDE * Math.sin(turn)) is dynamic and was not executed.101
unresolved-expressionExpected outcome<unresolved: angle("tilt", TILT_AMPLITUDE * Math.cos(turn))> Call expression angle("tilt", TILT_AMPLITUDE * Math.cos(turn)) is dynamic and was not executed.102
unresolved-expressionStep<unresolved: CYCLE_MILLIS / 4> Expression CYCLE_MILLIS / 4 is not statically resolved.107
static-control-flowSourceControl flow for (const [index, number] of MOVERS.entries()) { const turn = 2 * Math.PI * ((phase + index * 0.5) % 1); await t.expectFixtureDMX(fixture(number), { "Pan coarse": angle("pan", … is narrated once; iteration values are not guessed.98
unresolved-expressionExpected outcome<unresolved: angle("pan", PAN_AMPLITUDE * Math.sin(turn))> Call expression angle("pan", PAN_AMPLITUDE * Math.sin(turn)) is dynamic and was not executed.101
unresolved-expressionExpected outcome<unresolved: angle("tilt", TILT_AMPLITUDE * Math.cos(turn))> Call expression angle("tilt", TILT_AMPLITUDE * Math.cos(turn)) is dynamic and was not executed.102
unresolved-expressionStep<unresolved: CYCLE_MILLIS / 4> Expression CYCLE_MILLIS / 4 is not statically resolved.107
static-control-flowSourceControl flow for (const [index, number] of MOVERS.entries()) { const turn = 2 * Math.PI * ((phase + index * 0.5) % 1); await t.expectFixtureDMX(fixture(number), { "Pan coarse": angle("pan", … is narrated once; iteration values are not guessed.98
unresolved-expressionExpected outcome<unresolved: angle("pan", PAN_AMPLITUDE * Math.sin(turn))> Call expression angle("pan", PAN_AMPLITUDE * Math.sin(turn)) is dynamic and was not executed.101
unresolved-expressionExpected outcome<unresolved: angle("tilt", TILT_AMPLITUDE * Math.cos(turn))> Call expression angle("tilt", TILT_AMPLITUDE * Math.cos(turn)) is dynamic and was not executed.102

BENCH-DYNAMIC-EDITOR-002 — Color and Zoom lanes chosen in the Dynamics editor are stored as semantic family lanes in their own units

tests/127-dynamic-editor-position-circle.spec.ts:113 · migrated-semantic-world · last run: not merged

show: EmptyBrowser UIDynamicsShow files
Preconditions (3)
ContextLine
Use the isolated Show.Empty show.
t.show.use(Show.Empty)
117
Open the ToskLight browser application.
t.app.open()
118
The ToskLight browser application is ready.
t.app.expect.ready()
119

Scenario contract

KindScenario contractLine
Step
Built in → open with PaneType.Dynamics.
t.builtIn.open(PaneType.Dynamics)
120
Step
Tap empty Dynamics tile 2 and choose the lane
{
   group:  "color",
   attribute:  "Red"
}
in the lane chooser.
t.dynamic.editor.create(2, { group: "color", attribute: "Red" })
122
Expected
The "Top" lane encoder reads "100%".
t.dynamic.editor.expect.encoder("Top", "100%")
123
Expected
The "Bottom" lane encoder reads "0%".
t.dynamic.editor.expect.encoder("Bottom", "0%")
124
Step
Tap + Add Lane and choose the lane
{
   group:  "color",
   attribute:  "White Blend"
}
t.dynamic.editor.addLane(look, { group: "color", attribute: "White Blend" })
125
Step
Tap + Add Lane and choose the lane
{
   group:  "focus",
   attribute:  "Zoom"
}
t.dynamic.editor.addLane(look, { group: "focus", attribute: "Zoom" })
126
Step
Select lane 3, "Zoom", in the Dynamics editor.
t.dynamic.editor.selectLane(3, "Zoom")
127
Expected
The "Top" lane encoder reads "40°".
t.dynamic.editor.expect.encoder("Top", "40°")
128
Expected
The "Bottom" lane encoder reads "10°".
t.dynamic.editor.expect.encoder("Bottom", "10°")
129
Expected
$look (result of dynamic.editor.create) stores the lanes
[
  {
     family:  "color",
     component:  "red"
  },
   {
     family:  "color",
     component:  "white_blend"
  },
   {
     family:  "zoom"
  }
]
t.dynamic.editor.expect.lanes(look, [
			{ family: "color", component: "red" },
			{ family: "color", component: "white_blend" },
			{ family: "zoom" },
		])
130
Expected
The Dynamics editor shows no error.
t.dynamic.editor.expect.noError()
135

Diagnostics

None.

HIGHLIGHT-006 — the production hardware simulator preserves geometry and sends independent full-height faders

tests/21-completion-coverage.spec.ts:5 · migrated-semantic-world · last run: not merged

Hardware simulatorOSC

Scenario contract

KindScenario contractLine
Expected
Hardware simulator → expect geometry and independent faders.
t.hardwareSimulator.expectGeometryAndIndependentFaders()
9

Diagnostics

None.

ENCODER-DISPLAY-001 — simulator touch controls emit encoder and NAV turn, held-turn, and click tokens

tests/21-completion-coverage.spec.ts:13 · migrated-semantic-world · last run: not merged

Hardware simulatorOSC

Scenario contract

KindScenario contractLine
Expected
Hardware simulator → expect encoder and navigation tokens.
t.hardwareSimulator.expectEncoderAndNavigationTokens()
17

Diagnostics

None.

UPDATE-002 — actual simulator pointer gestures emit complete, mutually exclusive Shift and Record sequences

tests/21-completion-coverage.spec.ts:21 · migrated-semantic-world · last run: not merged

Hardware simulatorOSC

Scenario contract

KindScenario contractLine
Expected
Hardware simulator → expect shift record pointer sequences.
t.hardwareSimulator.expectShiftRecordPointerSequences()
25

Diagnostics

None.

BENCH-UI-003 — captures semantic surfaces and emits typed secondary-screen intent

tests/37-semantic-desktop-show-clock.spec.ts:9 · migrated-semantic-world · last run: not merged

Browser UIDesktop layoutGenerated artifactsSecondary screen
Preconditions (1)
ContextLine
Open the ToskLight browser application.
t.app.open()
13

Scenario contract

KindScenario contractLine
Step
Built in → open with PaneType.Stage.2 tools
t.builtIn.open(PaneType.Stage)
14
Tool
Capture application screenshot "bench-application".
t.screenshot.application("bench-application")
15
Tool
Capture PaneType.Stage pane screenshot "bench-stage-built-in".
t.screenshot.builtIn(PaneType.Stage, "bench-stage-built-in")
16
Step
Desktop → create with "Screenshot Desktop".
t.desktop.create("Screenshot Desktop")
18
Step
Desktop → open settings for with "Screenshot Desktop".2 tools
t.desktop.openSettingsFor("Screenshot Desktop")
19
Tool
Capture "Desktop settings" dialog screenshot "bench-desktop-dialog".
t.screenshot.dialog("Desktop settings", "bench-desktop-dialog")
20
Tool
Capture application screenshot "bench-application-with-portal".
t.screenshot.application("bench-application-with-portal")
21
Step
Desktop → close settings.
t.desktop.closeSettings()
22
Step
Screen → create with screen: Bench output
{
   fixedPane:  "fixture_sheet",
   showDock:  false,
   showPlaybacks:  true,
   showPageControls:  true,
   fullscreen:  false,
   desiredOpen:  true,
   playbacks:  {
     perRow:  8,
     rows:  [
      {
         first:  41,
         fader:  true,
         buttons:  3
      }
    ],
     pageMode:  "dedicated"
  }
}
t.screen.create({
			name: "Bench output",
			fixedPane: "fixture_sheet",
			showDock: false,
			showPlaybacks: true,
			showPageControls: true,
			display: { id: "display-2", name: "Operator display" },
			bounds: { x: 100, y: 80, width: 1024, height: 768 },
			fullscreen: false,
			desiredOpen: true,
			playbacks: {
				perRow: 8,
				rows: [{ first: 41, fader: true, buttons: 3 }],
				pageMode: "dedicated",
			},
		})
24
Expected
Secondary-screen bridge action is "open_console_screen".
screen.expectBridgeAction("open_console_screen")
40
Expected
Secondary screen → fixed pane is "fixture_sheet".
screen.expectFixedPane("fixture_sheet")
41
Step
Close the configured secondary screen.
screen.close()
42
Expected
Secondary-screen bridge action is "close_console_screen".
screen.expectBridgeAction("close_console_screen")
43
Step
Remove the configured secondary screen.
screen.remove()
44

Diagnostics

None.

BENCH-SHOW-004 — runs named create, autosave, Save As, revision, and reopen through visible operator controls

tests/37-semantic-desktop-show-clock.spec.ts:48 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIShow files
Preconditions (10)
ContextLine
Open the ToskLight browser application.
t.app.open()
52
Create the show "Operator Empty <generated: UUID>".
t.show.create(`Operator Empty ${crypto.randomUUID()}`)
53
Save the active show.
t.show.save()
56
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
58
Save the active show as "Portable Source <generated: UUID>".
t.show.saveAs(
			`Portable Source ${crypto.randomUUID()}`,
		)
59
Save a named show revision "Approved operator state".
t.show.saveRevision("Approved operator state")
63
Save the active show as "Portable Later Copy <generated: UUID>".
t.show.saveAs(
			`Portable Later Copy ${crypto.randomUUID()}`,
		)
68
Load the show $source (result of show.saveAs).
t.show.load(source)
72
Load revision $revision (result of show.saveRevision) of $source (result of show.saveAs).
t.show.loadRevision(source, revision)
74
Save the active show.
t.show.save()
76

Scenario contract

KindScenario contractLine
Expected
Show → active is the created show.
t.show.expect.active(empty)
54
Expected
Show → dirty is false.
t.show.expect.dirty(false)
55
Expected
Show → active is the saved show copy.
t.show.expect.active(source)
62
Expected
Show → revision matches
{
   number:  $revision (result of show.saveRevision),
   name:  "Approved operator state"
}
t.show.expect.revision({
			number: revision,
			name: "Approved operator state",
		})
64
Expected
Show → active is the saved show copy.
t.show.expect.active(laterCopy)
71
Expected
Show → active is the saved show copy.
t.show.expect.active(source)
73
Expected
Show → active is the loaded revision copy.
t.show.expect.active(revisionCopy)
75

Diagnostics

None.

BENCH-CLOCK-DMX-001 — uses exact clock boundaries and fixture-aware logical DMX without hidden ticks

tests/37-semantic-desktop-show-clock.spec.ts:80 · migrated-semantic-world · last run: not merged

DMX outputSemantic oracleTest clock

Scenario contract

KindScenario contractLine
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
84
Expected
$first.now (from clock.advanceStep) is "2020-01-01T00:00:00Z".
expect(first.now).toBe("2020-01-01T00:00:00Z")
85
Expected
$first.packets_sent (from clock.advanceStep) is 2.
expect(first.packets_sent).toBe(2)
86
Step
Clock → at with
[
  {
     name:  "before",
     at:  "999ms"
  },
   {
     name:  "exact",
     at:  "1s"
  },
   {
     name:  "after",
     at:  "1.001s"
  }
]
, <generated: callback>.
t.clock.at(
			[
				{ name: "before", at: "999ms" },
				{ name: "exact", at: "1s" },
				{ name: "after", at: "1.001s" },
			],
			({ name, frame }) => boundaries.push(`${name}:${frame.now}`),
		)
89
Expected
boundaries =
[
]
equals
[
  "before:2020-01-01T00:00:00.999Z",
   "exact:2020-01-01T00:00:01Z",
   "after:2020-01-01T00:00:01.001Z"
]
expect(boundaries).toEqual([
			"before:2020-01-01T00:00:00.999Z",
			"exact:2020-01-01T00:00:01Z",
			"after:2020-01-01T00:00:01.001Z",
		])
97
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
103
Expected
fixtureRange(1, 3) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 3), { Intensity: 0 })
104
Expected
Calling t.expectFixtureDMX(fixture(1),
{
   "Missing component":  0
}
) rejects with /Valid channels: Intensity/u.
expect(
			t.expectFixtureDMX(fixture(1), { "Missing component": 0 }),
		).rejects.toThrow(/Valid channels: Intensity/u)
105
Expected
Calling t.expectFixtureDMX(fixture(1),
{
   Intensity:  256
}
) rejects with /integer from 0 through 255/u.
expect(
			t.expectFixtureDMX(fixture(1), { Intensity: 256 }),
		).rejects.toThrow(/integer from 0 through 255/u)
108

Diagnostics

None.

BENCH-COMMAND-SELECTION-002 — preserves ordered typed sources while Highlight power stays independent

tests/38-semantic-command-programmer-group-preset.spec.ts:18 · migrated-semantic-world · last run: not merged

Attached hardwareBrowser UIHighlightOSCSelectionSemantic oracleTyped API
Preconditions (2)
ContextLine
Open the ToskLight browser application.
t.app.open()
22
The ToskLight browser application is ready.
t.app.expect.ready()
23

Scenario contract

KindScenario contractLine
Step
Selection → targets with fixture(3), fixture(1).
t.selection.targets(fixture(3), fixture(1))
25
Expected
Selection: fixture(3), fixture(1).
t.expect.selection(fixture(3), fixture(1))
26
Step
Selection → groups → range with 1, 4.
t.selection.groups.range(1, 4)
28
Expected
Selection: groupRange(1, 4).
t.expect.selection(groupRange(1, 4))
29
Step
Selection → observe.
t.selection.observe()
30
Step
Highlight → api → on.
t.highlight.via.api.on()
32
Step
Highlight → api → off.
t.highlight.via.api.off()
33
Step
Selection → observe.
t.selection.observe()
34
Expected
$after.selected (from selection.observe) equals $before.selected (from selection.observe).
expect(after.selected).toEqual(before.selected)
35
Expected
$after.expression (from selection.observe) equals $before.expression (from selection.observe).
expect(after.expression).toEqual(before.expression)
36
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
38
Step
Highlight → osc → toggle.
t.highlight.via.osc.toggle()
40
Step
Highlight → osc → toggle.
t.highlight.via.osc.toggle()
41
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
43

Diagnostics

None.

BENCH-ENCODER-001 — normalized Dimmer absolute and relative API intents retain distinct semantics

tests/38-semantic-command-programmer-group-preset.spec.ts:48 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIDMX outputEncoder controlsProgrammerSelectionSemantic oracleShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
52
Open the ToskLight browser application.
t.app.open()
53
The ToskLight browser application is ready.
t.app.expect.ready()
54

Scenario contract

KindScenario contractLine
Expected
Show → active is Default Stage.
t.show.expect.active(Show.DefaultStage)
55
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
56
Expected
Selection: fixture(1).
t.expect.selection(fixture(1))
57
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
59
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
60
Step
Encoder → intensity → dimmer → api → add with 3.
t.encoder.intensity.dimmer.via.api.add(3)
61
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
62
Step
Encoder → intensity → dimmer → api → subtract with 2.
t.encoder.intensity.dimmer.via.api.subtract(2)
63
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
64
Expected
dmxFixture(1) DMX equals
{
   Intensity:  130
}
t.expectFixtureDMX(dmxFixture(1), { Intensity: 130 })
65

Diagnostics

None.

BENCH-GROUP-002 — live Group references refresh while dereferenced captures retain concrete fixtures

tests/38-semantic-command-programmer-group-preset.spec.ts:69 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIGroupsSelectionSemantic oracleShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
73
Open the ToskLight browser application.
t.app.open()
74
The ToskLight browser application is ready.
t.app.expect.ready()
75

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with 1, 2.
t.selection.fixtures.via.api.items(1, 2)
77
Step
Group → api → store with 80,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(80, { mode: StoreMode.Overwrite })
78
Step
Selection → targets with dereferencedGroup(80).
t.selection.targets(dereferencedGroup(80))
80
Step
Group → api → store with 80,
{
   mode:  StoreMode.Subtract
}
t.group.via.api.store(80, { mode: StoreMode.Subtract })
81
Expected
Group → empty: 80.
t.group.expect(80).empty()
82
Expected
Selection: fixture(1), fixture(2).
t.expect.selection(fixture(1), fixture(2))
83
Step
Group → api → store with 80,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(80, { mode: StoreMode.Overwrite })
85
Step
Group → api → select with 80.
t.group.via.api.select(80)
86
Expected
Selection: group(80).
t.expect.selection(group(80))
87
Step
Group → api → store with 80,
{
   mode:  StoreMode.Subtract
}
t.group.via.api.store(80, { mode: StoreMode.Subtract })
88
Expected
Group → empty: 80.
t.group.expect(80).empty()
89
Expected
Selection: group(80).
t.expect.selection(group(80))
90

Diagnostics

None.

BENCH-PRESET-001 — Preset families record and recall through pool, keypad, API, and OSC

tests/38-semantic-command-programmer-group-preset.spec.ts:94 · migrated-semantic-world · last run: not merged

show: Default StageAttached hardwareBrowser UICommand keypadCue timingDMX outputDesktop layoutEncoder controlsHighlightOSCPool UIPresetsProgrammerProgrammer timingSelectionSemantic oracleShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
98
Open the ToskLight browser application.
t.app.open()
99
The ToskLight browser application is ready.
t.app.expect.ready()
100

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
102
Step
Desktop → configure with .desktop: Groups and Presets
t.desktop.configure("Groups and Presets")
203
Step
Add the PaneType.Presets pane
desktop.addPane(PaneType.Presets, {
		slug: "presets",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
204
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 13,
		row: 1,
		width: 6,
		height: 18,
	})
211
Step
Add the PaneType.Stage pane
desktop.addPane(PaneType.Stage, {
		slug: "stage",
		column: 19,
		row: 1,
		width: 6,
		height: 18,
	})
218
Step
Apply the configured Desktop layout.
desktop.apply()
225
Step
Selection → fixtures → api → items with 101, 102.
t.selection.fixtures.via.api.items(101, 102)
104
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
106
Step
Encoder → color → red → api → set with
[
  40,
   ProgrammerToken.Thru,
   60
]
t.encoder.color.red.via.api.set([40, ProgrammerToken.Thru, 60])
110
Step
Encoder → position → pan → api → set with <unresolved: -135>.
t.encoder.position.pan.via.api.set(-135)
112
Step
Encoder → beam → gobo1 → api → set with 30.
t.encoder.beam.gobo1.via.api.set(30)
113
Step
Preset → api → store with PresetFamily.Mixed, 1,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Mixed, 1, {
			mode: "overwrite",
		})
115
Step
Preset → pool → store with PresetFamily.Intensity, 1,
{
   mode:  "overwrite"
}
t.preset.via.pool.store(PresetFamily.Intensity, 1, {
			mode: "overwrite",
		})
118
Step
Preset → keypad → store with PresetFamily.Color, 1,
{
   mode:  "overwrite"
}
t.preset.via.keypad.store(PresetFamily.Color, 1, {
			mode: "overwrite",
		})
121
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
125
Step
Preset → api → store with PresetFamily.Mixed, 2,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Mixed, 2, {
				mode: "overwrite",
			})
127
Expected
Preset → present: PresetFamily.Mixed, 2.
t.preset.expect(PresetFamily.Mixed, 2).present()
130
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
132
Step
Preset → api → store with PresetFamily.Position, 1,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Position, 1, {
			mode: "overwrite",
		})
135
Step
Preset → api → store with PresetFamily.Beam, 1,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Beam, 1, {
			mode: "overwrite",
		})
138
Expected
Preset → present: PresetFamily.Mixed, 1.
t.preset.expect(family, 1).present()
142
Expected
Preset → metadata: PresetFamily.Mixed, 1,
{
   family:  PresetFamily.Mixed,
   number:  1
}
t.preset.expect(family, 1).metadata({ family, number: 1 })
143
Expected
Preset → present: PresetFamily.Intensity, 1.
t.preset.expect(family, 1).present()
142
Expected
Preset → metadata: PresetFamily.Intensity, 1,
{
   family:  PresetFamily.Intensity,
   number:  1
}
t.preset.expect(family, 1).metadata({ family, number: 1 })
143
Expected
Preset → present: PresetFamily.Color, 1.
t.preset.expect(family, 1).present()
142
Expected
Preset → metadata: PresetFamily.Color, 1,
{
   family:  PresetFamily.Color,
   number:  1
}
t.preset.expect(family, 1).metadata({ family, number: 1 })
143
Expected
Preset → present: PresetFamily.Position, 1.
t.preset.expect(family, 1).present()
142
Expected
Preset → metadata: PresetFamily.Position, 1,
{
   family:  PresetFamily.Position,
   number:  1
}
t.preset.expect(family, 1).metadata({ family, number: 1 })
143
Expected
Preset → present: PresetFamily.Beam, 1.
t.preset.expect(family, 1).present()
142
Expected
Preset → metadata: PresetFamily.Beam, 1,
{
   family:  PresetFamily.Beam,
   number:  1
}
t.preset.expect(family, 1).metadata({ family, number: 1 })
143
Step
Preset → pool → edit with PresetFamily.Mixed, 1,
{
   title:  "Stage look"
}
t.preset.via.pool.edit(PresetFamily.Mixed, 1, {
			title: "Stage look",
		})
146
Expected
Preset → button: PresetFamily.Mixed, 1,
{
   title:  "Stage look"
}
t.preset.expect(PresetFamily.Mixed, 1).button({
			title: "Stage look",
		})
149
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
153
Step
Clear the current selection.
t.selection.clear()
154
Expected
Preset → expect visible selection count: 0.
t.preset.expectVisibleSelectionCount(0)
155
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
156
Expected
dmxFixture(101) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(dmxFixture(101), { Intensity: 0 })
157
Expected
dmxFixture(102) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(dmxFixture(102), { Intensity: 0 })
158
Step
Preset → tap empty pool slot with PresetFamily.Mixed, 9.
t.preset.tapEmptyPoolSlot(PresetFamily.Mixed, 9)
159
Expected
Selection.
t.expect.selection()
160
Step
Preset → pool → recall with PresetFamily.Mixed, 1.
t.preset.via.pool.recall(PresetFamily.Mixed, 1)
162
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
163
Expected
Poll → to be: <generated: callback>, count = 2.
expect
		.poll(async () => (await t.selection.observe()).selected.length)
		.toBe(count)
232
Step
Selection → observe.
t.selection.observe()
240
Expected
<unresolved: selection.targets.map((target) => target.number)> equals [102, 101].
expect(selection.targets.map((target) => target.number)).toEqual([102, 101])
241
Expected
$selection.expression (from selection.observe) equals
{
   type:  "static"
}
expect(selection.expression).toEqual({ type: "static" })
242
Expected
Preset → expect visible selection: 101, 102.
t.preset.expectVisibleSelection(101, 102)
166
Expected
dmxFixture(101) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(dmxFixture(101), { Intensity: 0 })
167
Expected
dmxFixture(102) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(dmxFixture(102), { Intensity: 0 })
168
Step
Preset → pool → recall with PresetFamily.Mixed, 1.
t.preset.via.pool.recall(PresetFamily.Mixed, 1)
170
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
171
Expected
dmxFixture(101) DMX equals
{
   Intensity:  179
}
t.expectFixtureDMX(dmxFixture(101), { Intensity: 179 })
172
Expected
dmxFixture(102) DMX equals
{
   Intensity:  179
}
t.expectFixtureDMX(dmxFixture(102), { Intensity: 179 })
173
Step
Preset → keypad → recall with PresetFamily.Position, 1.
t.preset.via.keypad.recall(PresetFamily.Position, 1)
175
Step
Selection → observe.
t.selection.observe()
240
Expected
<unresolved: selection.targets.map((target) => target.number)> equals [102, 101].
expect(selection.targets.map((target) => target.number)).toEqual([102, 101])
241
Expected
$selection.expression (from selection.observe) equals
{
   type:  "static"
}
expect(selection.expression).toEqual({ type: "static" })
242
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
178
Step
Clear the current selection.
t.selection.clear()
179
Expected
Preset → expect visible selection count: 0.
t.preset.expectVisibleSelectionCount(0)
180
Step
Preset → api → recall with PresetFamily.Color, 1.
t.preset.via.api.recall(PresetFamily.Color, 1)
181
Expected
Poll → to be: <generated: callback>, count = 2.
expect
		.poll(async () => (await t.selection.observe()).selected.length)
		.toBe(count)
232
Step
Selection → observe.
t.selection.observe()
240
Expected
<unresolved: selection.targets.map((target) => target.number)> equals [102, 101].
expect(selection.targets.map((target) => target.number)).toEqual([102, 101])
241
Expected
$selection.expression (from selection.observe) equals
{
   type:  "static"
}
expect(selection.expression).toEqual({ type: "static" })
242
Step
Preset → api → recall with PresetFamily.Color, 1.
t.preset.via.api.recall(PresetFamily.Color, 1)
184
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
186
Step
Preset → osc → recall with PresetFamily.Mixed, 2.
t.preset.via.osc.recall(PresetFamily.Mixed, 2)
188
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
189
Step
Selection → observe.
t.selection.observe()
240
Expected
<unresolved: selection.targets.map((target) => target.number)> equals [102, 101].
expect(selection.targets.map((target) => target.number)).toEqual([102, 101])
241
Expected
$selection.expression (from selection.observe) equals
{
   type:  "static"
}
expect(selection.expression).toEqual({ type: "static" })
242
Expected
dmxFixture(101) DMX equals
{
   Intensity:  179
}
t.expectFixtureDMX(dmxFixture(101), { Intensity: 179 })
191
Expected
dmxFixture(102) DMX equals
{
   Intensity:  179
}
t.expectFixtureDMX(dmxFixture(102), { Intensity: 179 })
192
Step
Highlight → osc → toggle.
t.highlight.via.osc.toggle()
193
Step
Selection → observe.
t.selection.observe()
240
Expected
<unresolved: selection.targets.map((target) => target.number)> equals [102, 101].
expect(selection.targets.map((target) => target.number)).toEqual([102, 101])
241
Expected
$selection.expression (from selection.observe) equals
{
   type:  "static"
}
expect(selection.expression).toEqual({ type: "static" })
242
Step
Highlight → osc → toggle.
t.highlight.via.osc.toggle()
195
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
197

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionStep<unresolved: -135> Expression -135 is not statically resolved.112
unresolved-expressionExpected outcome<unresolved: selection.targets.map((target) => target.number)> Call expression selection.targets.map((target) => target.number) is dynamic and was not executed.241
unresolved-expressionExpected outcome<unresolved: selection.targets.map((target) => target.number)> Call expression selection.targets.map((target) => target.number) is dynamic and was not executed.241
unresolved-expressionExpected outcome<unresolved: selection.targets.map((target) => target.number)> Call expression selection.targets.map((target) => target.number) is dynamic and was not executed.241
unresolved-expressionExpected outcome<unresolved: selection.targets.map((target) => target.number)> Call expression selection.targets.map((target) => target.number) is dynamic and was not executed.241
unresolved-expressionExpected outcome<unresolved: selection.targets.map((target) => target.number)> Call expression selection.targets.map((target) => target.number) is dynamic and was not executed.241

BENCH-CUE-PLAYBACK-001 — visible recording and typed runtime actions preserve Cue timing and concrete Playback identity

tests/39-semantic-playback-and-osc.spec.ts:19 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICue runtimeCue timingDMX outputEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
23
Open the ToskLight browser application.
t.app.open()
24
The ToskLight browser application is ready.
t.app.expect.ready()
25

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
26
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
27
Step
Selection → fixtures → api → item with 101.
t.selection.fixtures.via.api.item(101)
28
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
30
Step
Record → ui → playback with 1.
t.record.via.ui.playback(1)
31
Expected
Playback → present: $playback (result of record.via.ui.playback).
t.playback.expect(playback).present()
32
Expected
Cue → present: $playback (result of record.via.ui.playback), 1.
t.cue.expect(playback, 1).present()
33
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
35
Step
Encoder → intensity → dimmer → api → set with 80.
t.encoder.intensity.dimmer.via.api.set(80)
36
Step
Record → api → cue with
{
   playback:  $playback (result of record.via.ui.playback),
   cue:  2,
   mode:  CueRecordMode.Overwrite,
   timing:  {
     fade:  "1"
  }
}
t.record.via.api.cue({
			playback,
			cue: 2,
			mode: CueRecordMode.Overwrite,
			timing: { fade: "1" },
		})
37
Expected
Cue → metadata: $playback (result of record.via.ui.playback), 2,
{
   fade_millis:  1000
}
t.cue.expect(playback, 2).metadata({ fade_millis: 1_000 })
43
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
44
Step
Playback → api → off with $playback (result of record.via.ui.playback).
t.playback.via.api.off(playback)
46
Step
Playback → ui → go with $playback (result of record.via.ui.playback).
t.playback.via.ui.go(playback)
47
Expected
Playback → runtime: $playback (result of record.via.ui.playback),
{
   current_cue_number:  "1",
   enabled:  true
}
t.playback.expect(playback).runtime({
			current_cue_number: "1",
			enabled: true,
		})
48
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
52
Expected
dmxFixture(101) DMX equals
{
   Intensity:  51
}
t.expectFixtureDMX(dmxFixture(101), { Intensity: 51 })
53
Step
Playback → api → go with $playback (result of record.via.ui.playback).
t.playback.via.api.go(playback)
55
Step
Advance the test clock by "500ms".
t.clock.advanceBy("500ms")
56
Expected
dmxFixture(101) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(dmxFixture(101), { Intensity: 128 })
57
Step
Advance the test clock by "500ms".
t.clock.advanceBy("500ms")
58
Expected
dmxFixture(101) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(dmxFixture(101), { Intensity: 204 })
59
Step
Playback → api → select with $playback (result of record.via.ui.playback).
t.playback.via.api.select(playback)
61
Expected
Playback → selected: $playback (result of record.via.ui.playback).
t.playback.expect(playback).selected()
62

Diagnostics

None.

BENCH-PAGE-PLAYBACK-001 — current and explicit Page targets retain distinct Playback authority

tests/39-semantic-playback-and-osc.spec.ts:66 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICue timingEncoder controlsPlayback pagesPlaybacksProgrammerProgrammer timingRecordingSecondary screenSelectionSemantic oracleShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
70
Open the ToskLight browser application.
t.app.open()
71
The ToskLight browser application is ready.
t.app.expect.ready()
72

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
73
Step
Selection → fixtures → api → item with 101.
t.selection.fixtures.via.api.item(101)
75
Step
Encoder → intensity → dimmer → api → set with 25.
t.encoder.intensity.dimmer.via.api.set(25)
76
Step
Record → playback with 1.
t.record.playback(1)
77
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
78
Step
Selection → fixtures → api → item with 102.
t.selection.fixtures.via.api.item(102)
79
Step
Encoder → intensity → dimmer → api → set with 75.
t.encoder.intensity.dimmer.via.api.set(75)
80
Step
Record → playback with 2.
t.record.playback(2)
81
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
82
Step
Page → create with 2.
t.page.create(2)
84
Step
Page → rename with 2, "Second".
t.page.rename(2, "Second")
85
Step
Page → map with
{
   sourceAddress:  $second (result of record.playback),
   targetAddress:  {
     page:  2,
     position:  1
  }
}
t.page.map({
			sourceAddress: second,
			targetAddress: { page: 2, position: 1 },
		})
86
Expected
Page → named: 2, "Second".
t.page.expect(2).named("Second")
90
Step
Playback → api → off with $first (result of record.playback).
t.playback.via.api.off(first)
92
Step
Playback → api → off with $second (result of record.playback).
t.playback.via.api.off(second)
93
Step
Page → api → select with 1.
t.page.via.api.select(1)
94
Step
Playback → api → go with currentPagePlayback(1).
t.playback.via.api.go(currentPagePlayback(1))
95
Expected
Playback → runtime: $first (result of record.playback),
{
   enabled:  true
}
t.playback.expect(first).runtime({ enabled: true })
96
Expected
Playback → runtime: $second (result of record.playback),
{
   enabled:  false
}
t.playback.expect(second).runtime({ enabled: false })
97
Step
Page → ui → select with 2.
t.page.via.ui.select(2)
99
Step
Playback → api → go with currentPagePlayback(1).
t.playback.via.api.go(currentPagePlayback(1))
100
Expected
Playback → runtime:
{
   page:  2,
   position:  1
}
{
   enabled:  true
}
t.playback.expect({ page: 2, position: 1 }).runtime({ enabled: true })
101
Expected
Playback → runtime: $second (result of record.playback),
{
   enabled:  true
}
t.playback.expect(second).runtime({ enabled: true })
103
Step
Playback → api → off with $first (result of record.playback).
t.playback.via.api.off(first)
105
Step
Playback → api → go with explicitPagePlayback(1, 1).
t.playback.via.api.go(explicitPagePlayback(1, 1))
106
Expected
Playback → runtime: $first (result of record.playback),
{
   enabled:  true
}
t.playback.expect(first).runtime({ enabled: true })
107
Expected
Page → selected: 2.
t.page.expect(2).selected()
108
Step
Screen → create with screen: Independent Playbacks
{
   showPlaybacks:  true,
   showPageControls:  true,
   playbacks:  {
     perRow:  1,
     rows:  [
      {
         first:  1,
         fader:  true,
         buttons:  3
      }
    ],
     pageMode:  "dedicated"
  }
}
t.screen.create({
			name: "Independent Playbacks",
			showPlaybacks: true,
			showPageControls: true,
			playbacks: {
				perRow: 1,
				rows: [{ first: 1, fader: true, buttons: 3 }],
				pageMode: "dedicated",
			},
		})
110
Step
Screen handle → page → select with 1.
screen.page.select(1)
120
Expected
Secondary screen → selected page is 1.
screen.page.expectSelected(1)
121
Expected
<unresolved: await t.page.resolvedPage("main")> is 2.
expect(await t.page.resolvedPage("main")).toBe(2)
123
Expected
Page → selected: 1.
t.page.expect(1).selected()
124

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: await t.page.resolvedPage("main")> Expression await t.page.resolvedPage("main") is not statically resolved.123

BENCH-SELECTION-ROUTES-001 — visible panes, keypad, API, and OSC converge on the ordered selection oracle

tests/39-semantic-playback-and-osc.spec.ts:128 · migrated-semantic-world · last run: not merged

Attached hardwareBrowser UICommand keypadDesktop layoutFixture SheetOSCSelectionSemantic oracleTyped API
Preconditions (2)
ContextLine
Open the ToskLight browser application.
t.app.open()
132
The ToskLight browser application is ready.
t.app.expect.ready()
133

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Selection route proof
t.desktop.configure("Selection route proof")
134
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
			slug: "fixtures",
			column: 1,
			row: 1,
			width: 8,
			height: 18,
		})
135
Step
Add the PaneType.Stage pane
desktop.addPane(PaneType.Stage, {
			slug: "stage",
			column: 9,
			row: 1,
			width: 8,
			height: 18,
		})
142
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
			slug: "groups",
			column: 17,
			row: 1,
			width: 8,
			height: 18,
		})
149
Step
Apply the configured Desktop layout.
desktop.apply()
156
Step
Clear the current selection.
t.selection.clear()
158
Step
Selection → fixtures → fixture sheet → items with 1, 3, 2.
t.selection.fixtures.via.fixtureSheet.items(1, 3, 2)
159
Expected
Selection: fixture(1), fixture(3), fixture(2).
t.expect.selection(fixture(1), fixture(3), fixture(2))
160
Step
Clear the current selection.
t.selection.clear()
162
Step
Selection → fixtures → fixture sheet → range with 1, 4.
t.selection.fixtures.via.fixtureSheet.range(1, 4)
163
Expected
Selection: fixtureRange(1, 4).
t.expect.selection(fixtureRange(1, 4))
164
Step
Clear the current selection.
t.selection.clear()
166
Step
Selection → groups → api → range with 1, 4.
t.selection.groups.via.api.range(1, 4)
167
Expected
Selection: groupRange(1, 4).
t.expect.selection(groupRange(1, 4))
168
Step
Selection → fixtures → keypad → range with 2, 5.
t.selection.fixtures.via.keypad.range(2, 5)
170
Expected
Selection: fixtureRange(2, 5).
t.expect.selection(fixtureRange(2, 5))
171
Step
Selection → fixtures → api → items with 5, 2, 4.
t.selection.fixtures.via.api.items(5, 2, 4)
173
Expected
Selection: fixture(5), fixture(2), fixture(4).
t.expect.selection(fixture(5), fixture(2), fixture(4))
174
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
176
Step
Selection → fixtures → osc → item with 6.
t.selection.fixtures.via.osc.item(6)
178
Expected
Selection: fixture(6).
t.expect.selection(fixture(6))
179
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
181

Diagnostics

None.

SHOW-000 — Save As produces independent reusable show files

tests/40-semantic-generate-show-files.spec.ts:11 · migrated-semantic-world · last run: not merged

show: Compact Rigshow: Default StageBrowser UICommand keypadDesktop layoutFixture SheetGroupsPool UISelectionSemantic oracleShow files
Preconditions (13)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
15
Open the ToskLight browser application.
t.app.open()
16
The ToskLight browser application is ready.
t.app.expect.ready()
17
Show → ui → save as with "show-000-compact-copy-<generated: UUID>".
t.show.via.ui.saveAs(
			`show-000-compact-copy-${crypto.randomUUID()}`,
		)
35
Show → ui → save revision with "SHOW-000 compact UI mutation".
t.show.via.ui.saveRevision(
			"SHOW-000 compact UI mutation",
		)
38
Show → ui → load revision with $compactCopy (result of show.via.ui.saveAs), $compactRevision (result of show.via.ui.saveRevision).
t.show.via.ui.loadRevision(
			compactCopy,
			compactRevision,
		)
41
Reset the isolated working copy.
t.show.resetWorkingCopy()
53
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
62
Open the ToskLight browser application.
t.app.open()
63
The ToskLight browser application is ready.
t.app.expect.ready()
64
Show → ui → save as with "show-000-default-copy-<generated: UUID>".
t.show.via.ui.saveAs(
			`show-000-default-copy-${crypto.randomUUID()}`,
		)
69
Show → ui → save revision with "SHOW-000 default UI mutation".
t.show.via.ui.saveRevision("SHOW-000 default UI mutation")
72
Reset the isolated working copy.
t.show.resetWorkingCopy()
74

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Generated show workflow
t.desktop.configure("Generated show workflow")
83
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
84
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
91
Step
Apply the configured Desktop layout.
desktop.apply()
98
Step
Selection → fixtures → fixture sheet → item with 1.
t.selection.fixtures.via.fixtureSheet.item(1)
20
Expected
Selection: fixture(1).
t.expect.selection(fixture(1))
21
Step
Group → pool → store with 4,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(4, { mode: StoreMode.Overwrite })
22
Step
Group → pool → edit with 4,
{
   name:  "Copy Center Spot",
   color:  "#1bd6ec",
   icon:  "★"
}
t.group.via.pool.edit(4, {
			name: "Copy Center Spot",
			color: "#1bd6ec",
			icon: "★",
		})
23
Expected
Group → fixtures: 4, 1.
t.group.expect(4).fixtures(1)
28
Expected
Group → metadata: 4,
{
   name:  "Copy Center Spot",
   color:  "#1bd6ec",
   icon:  "★"
}
t.group.expect(4).metadata({
			name: "Copy Center Spot",
			color: "#1bd6ec",
			icon: "★",
		})
29
Expected
Show → active is the loaded revision copy.
t.show.expect.active(compactRevisionCopy)
45
Expected
Group → fixtures: 4, 1.
t.group.expect(4).fixtures(1)
46
Expected
Group → metadata: 4,
{
   name:  "Copy Center Spot",
   color:  "#1bd6ec",
   icon:  "★"
}
t.group.expect(4).metadata({
			name: "Copy Center Spot",
			color: "#1bd6ec",
			icon: "★",
		})
47
Expected
Show → active is Compact Rig.
t.show.expect.active(Show.CompactRig)
54
Expected
Group → empty: 4.
t.group.expect(4).empty()
55
Expected
Group → metadata: 4,
{
   name:  "Center Spot",
   color:  null,
   icon:  null
}
t.group.expect(4).metadata({
			name: "Center Spot",
			color: null,
			icon: null,
		})
56
Step
Selection → fixtures → fixture sheet → item with 1.
t.selection.fixtures.via.fixtureSheet.item(1)
65
Expected
Selection: fixture(1).
t.expect.selection(fixture(1))
66
Step
Group → keypad → store with 900,
{
   mode:  StoreMode.Overwrite
}
t.group.via.keypad.store(900, { mode: StoreMode.Overwrite })
67
Expected
Group → fixtures: 900, 1.
t.group.expect(900).fixtures(1)
68
Expected
Show → active is Default Stage.
t.show.expect.active(Show.DefaultStage)
75
Expected
Group → absent: 900.
t.group.expect(900).absent()
76

Diagnostics

None.

DIM-001 — ordered Group edits retain their live value and append re-added fixtures

tests/41-semantic-foundational-dimmer-command.spec.ts:11 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputGroupsShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
15
Open the ToskLight browser application.
t.app.open()
16
The ToskLight browser application is ready.
t.app.expect.ready()
17

Scenario contract

KindScenario contractLine
Step
Execute the desk command command = "GROUP 3 AT 50".
t.command.execute(command)
24
Step
Execute the desk command command = "GROUP 3 + 5 + 6".
t.command.execute(command)
24
Step
Execute the desk command command = "RECORD GROUP 3".
t.command.execute(command)
24
Expected
Group → fixtures: 3, 1, 2, 3, 4, 5, 6.
t.group.expect(3).fixtures(1, 2, 3, 4, 5, 6)
28
Step
Execute the desk command "FIXTURE 2".
t.command.execute("FIXTURE 2")
29
Step
Execute the desk command "RECORD - GROUP 3".
t.command.execute("RECORD - GROUP 3")
30
Expected
Group → fixtures: 3, 1, 3, 4, 5, 6.
t.group.expect(3).fixtures(1, 3, 4, 5, 6)
31
Step
Execute the desk command "GROUP 3 + 2".
t.command.execute("GROUP 3 + 2")
32
Step
Execute the desk command "RECORD GROUP 3".
t.command.execute("RECORD GROUP 3")
33
Expected
Group → fixtures: 3, 1, 3, 4, 5, 6, 2.
t.group.expect(3).fixtures(1, 3, 4, 5, 6, 2)
34
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
35
Expected
fixtureRange(1, 6) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 6), { Intensity: 128 })
36

Diagnostics

None.

DIM-002 — Lightning Desk command reaches the exact rendered output boundary

tests/41-semantic-foundational-dimmer-command.spec.ts:40 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue timingDMX outputProgrammer timingShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
44
Open the ToskLight browser application.
t.app.open()
45
The ToskLight browser application is ready.
t.app.expect.ready()
46

Scenario contract

KindScenario contractLine
Step
Programmer Fade → command-line AT fade is true.
t.timing.programmerFade.setCommandLineAtEnabled(true)
48
Step
Execute the desk command "GROUP 1 AT 50".
t.command.execute("GROUP 1 AT 50")
49
Step
Advance the test clock by "1.5s".
t.clock.advanceBy("1.5s")
50
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 64 })
51
Step
Advance the test clock by "1.5s".
t.clock.advanceBy("1.5s")
52
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 128 })
53
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
54
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 128 })
55

Diagnostics

None.

CMD-001 — Fixture and Group default modes toggle while explicit prefixes stay scoped

tests/41-semantic-foundational-dimmer-command.spec.ts:59 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand keypadCommand lineSemantic oracleShow files
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
63
Open the ToskLight browser application.
t.app.open()
64
The ToskLight browser application is ready.
t.app.expect.ready()
65

Scenario contract

KindScenario contractLine
Step
Press keypad keys
[
  "GRP"
]
t.keypad.press(["GRP"])
67
Expected
Command line shows "GROUP".
t.command.expect("GROUP")
68
Step
Press keypad keys
[
  "ENT"
]
t.keypad.press(["ENT"])
69
Expected
Command line shows "GROUP".
t.command.expect("GROUP")
70
Step
Press keypad keys
[
  "SHIFT",
   "GRP",
   "SHIFT"
]
t.keypad.press(["SHIFT", "GRP", "SHIFT"])
71
Expected
Command line shows "FIXTURE".
t.command.expect("FIXTURE")
72
Step
Press keypad keys
[
  "ENT"
]
t.keypad.press(["ENT"])
73
Expected
Command line shows "FIXTURE".
t.command.expect("FIXTURE")
74
Step
Execute the desk command "GROUP 1 + 2".
t.command.execute("GROUP 1 + 2")
76
Expected
Selection: group(1), fixture(2).
t.expect.selection(group(1), fixture(2))
77

Diagnostics

None.

GROUP-003 — derived Group follows source ordering

tests/42-semantic-foundational-groups.spec.ts:16 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDesktop layoutGroupsPool UISelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
20
Open the ToskLight browser application.
t.app.open()
21
The ToskLight browser application is ready.
t.app.expect.ready()
22

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Foundational Groups
t.desktop.configure("Foundational Groups")
117
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
118
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
125
Step
Apply the configured Desktop layout.
desktop.apply()
132
Step
Execute the desk command "GROUP 1 DIV 2".
t.command.execute("GROUP 1 DIV 2")
25
Step
Group → pool → store with 5,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(5, { mode: StoreMode.Overwrite })
26
Step
Selection → fixtures → api → items with ...sourceOrder =
[
  12,
   1,
   2,
   8,
   4,
   5,
   6,
   7,
   9,
   10,
   11
]
t.selection.fixtures.via.api.items(...sourceOrder)
29
Step
Group → pool → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(1, { mode: StoreMode.Overwrite })
30
Expected
Group → fixtures: 1, ...sourceOrder =
[
  12,
   1,
   2,
   8,
   4,
   5,
   6,
   7,
   9,
   10,
   11
]
t.group.expect(1).fixtures(...sourceOrder)
32
Expected
Group → fixtures: 5, 12, 2, 4, 6, 9, 11.
t.group.expect(5).fixtures(12, 2, 4, 6, 9, 11)
33
Expected
Group → empty: 4.
t.group.expect(4).empty()
34

Diagnostics

None.

GROUP-004 — frozen Group survives source edits and keeps unpatched fixtures programmable

tests/42-semantic-foundational-groups.spec.ts:38 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputDesktop layoutEncoder controlsGroupsPool UIProgrammerSelectionShow PatchShow filesTest clockTyped API
Preconditions (5)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
42
Open the ToskLight browser application.
t.app.open()
43
The ToskLight browser application is ready.
t.app.expect.ready()
44
Open the ToskLight browser application.
t.app.open()
56
The ToskLight browser application is ready.
t.app.expect.ready()
57

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Foundational Groups
t.desktop.configure("Foundational Groups")
117
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
118
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
125
Step
Apply the configured Desktop layout.
desktop.apply()
132
Step
Execute the desk command "DEGRP 1".
t.command.execute("DEGRP 1")
47
Step
Group → pool → store with 5,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(5, { mode: StoreMode.Overwrite })
48
Step
Selection → fixtures → api → items with ...sourceOrder =
[
  12,
   1,
   2,
   4,
   5,
   6,
   7,
   8,
   9,
   10,
   11
]
t.selection.fixtures.via.api.items(...sourceOrder)
51
Step
Group → pool → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(1, { mode: StoreMode.Overwrite })
52
Step
Patch → ui → unpatch with 3.
t.patch.via.ui.unpatch(3)
53
Expected
Patch → unpatched: 3.
t.patch.expect(3).unpatched()
54
Step
Execute the desk command "GROUP 5".
t.command.execute("GROUP 5")
58
Step
Encoder → intensity → dimmer → ui → set with 50.
t.encoder.intensity.dimmer.via.ui.set(50)
59
Expected
Group → fixtures: 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12.
t.group.expect(5).fixtures(
			1,
			2,
			3,
			4,
			5,
			6,
			7,
			8,
			9,
			10,
			11,
			12,
		)
60
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
74
Expected
fixtureRange(1, 2) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 2), { Intensity: 128 })
75
Expected
fixture(3) has no DMX output.
t.expectFixtureDMXAbsent(fixture(3))
76
Expected
fixtureRange(4, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(4, 12), { Intensity: 128 })
77

Diagnostics

None.

GROUP-005 — stored empty Groups remain distinct from missing references

tests/42-semantic-foundational-groups.spec.ts:81 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputDesktop layoutEncoder controlsFixture SheetGroupsPool UIProgrammerSelectionSemantic oracleShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
85
Open the ToskLight browser application.
t.app.open()
86
The ToskLight browser application is ready.
t.app.expect.ready()
87

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Foundational Groups
t.desktop.configure("Foundational Groups")
117
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
118
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
125
Step
Apply the configured Desktop layout.
desktop.apply()
132
Step
Group → api → delete with 4.
t.group.via.api.delete(4)
90
Expected
Group → absent: 4.
t.group.expect(4).absent()
91
Step
Execute the desk command "GROUP 1 THRU 5".
t.command.execute("GROUP 1 THRU 5")
92
Expected
Selection: groupRange(1, 5).
t.expect.selection(groupRange(1, 5))
93
Step
Clear the current selection.
t.selection.clear()
95
Step
Group → pool → store with 4,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(4, { mode: StoreMode.Overwrite })
96
Expected
Group → present: 4.
t.group.expect(4).present()
97
Expected
Group → empty: 4.
t.group.expect(4).empty()
98
Step
Group → pool → select with 4.
t.group.via.pool.select(4)
99
Expected
Selection: group(4).
t.expect.selection(group(4))
100
Step
Encoder → intensity → dimmer → ui → set with 50.
t.encoder.intensity.dimmer.via.ui.set(50)
101
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
102
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 0 })
103
Step
Selection → fixtures → fixture sheet → item with 1.
t.selection.fixtures.via.fixtureSheet.item(1)
105
Expected
Selection: fixture(1).
t.expect.selection(fixture(1))
106
Step
Group → pool → store with 4,
{
   mode:  StoreMode.Merge
}
t.group.via.pool.store(4, { mode: StoreMode.Merge })
107
Expected
Group → fixtures: 4, 1.
t.group.expect(4).fixtures(1)
108
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
109
Expected
fixture(1) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(1), { Intensity: 128 })
110

Diagnostics

None.

PROG-001 — values retain selection until replacement while leading Plus continues it

tests/43-semantic-foundational-programmer.spec.ts:12 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputSemantic oracleShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
16
Open the ToskLight browser application.
t.app.open()
17
The ToskLight browser application is ready.
t.app.expect.ready()
18

Scenario contract

KindScenario contractLine
Step
Execute the desk command command = "1 + 2 AT 50".
t.command.execute(command)
21
Step
Execute the desk command command = "AT 25".
t.command.execute(command)
21
Step
Execute the desk command command = "3 AT 75".
t.command.execute(command)
21
Step
Execute the desk command command = "+ 4 AT 100".
t.command.execute(command)
21
Expected
Selection: fixture(3), fixture(4).
t.expect.selection(fixture(3), fixture(4))
23
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
24
Expected
fixtureRange(1, 2) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixtureRange(1, 2), { Intensity: 64 })
25
Expected
fixtureRange(3, 4) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(3, 4), { Intensity: 255 })
26
Expected
fixtureRange(5, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 12), { Intensity: 0 })
27

Diagnostics

None.

PROG-002 — relative values spread across the live ordered Group

tests/43-semantic-foundational-programmer.spec.ts:31 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputDesktop layoutFixture SheetGroupsPool UISelectionShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
35
Open the ToskLight browser application.
t.app.open()
36
The ToskLight browser application is ready.
t.app.expect.ready()
37

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Foundational Programmer
t.desktop.configure("Foundational Programmer")
137
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
138
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
145
Step
Apply the configured Desktop layout.
desktop.apply()
152
Step
Selection → fixtures → fixture sheet → range with 1, 10.
t.selection.fixtures.via.fixtureSheet.range(1, 10)
40
Step
Group → pool → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(1, { mode: StoreMode.Overwrite })
41
Step
Execute the desk command "GROUP 1 AT 0 THRU 100".
t.command.execute("GROUP 1 AT 0 THRU 100")
42
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
43
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 0
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 28
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 57
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 85
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 113
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 142
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 170
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 198
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 227
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 255
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 0
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 0
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Step
Selection → fixtures → fixture sheet → items with ...sourceOrder =
[
  12,
   1,
   2,
   3,
   4,
   5,
   6,
   7,
   8,
   9,
   10
]
t.selection.fixtures.via.fixtureSheet.items(...sourceOrder)
50
Step
Group → pool → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.pool.store(1, { mode: StoreMode.Overwrite })
51
Expected
Group → fixtures: 1, ...sourceOrder =
[
  12,
   1,
   2,
   3,
   4,
   5,
   6,
   7,
   8,
   9,
   10
]
t.group.expect(1).fixtures(...sourceOrder)
52
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
53
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 26
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 51
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 77
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 102
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 128
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 153
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 179
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 204
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 230
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 255
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 0
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 0
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131

Diagnostics

None.

PROG-002 — fixture ranges and retained selections spread through the desk command line

tests/43-semantic-foundational-programmer.spec.ts:61 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
65
Open the ToskLight browser application.
t.app.open()
66
The ToskLight browser application is ready.
t.app.expect.ready()
67

Scenario contract

KindScenario contractLine
Step
Execute the desk command "1 THRU 5 AT 20 THRU 50".
t.command.execute("1 THRU 5 AT 20 THRU 50")
69
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
70
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 51
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 70
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 89
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 108
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 128
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Step
Execute the desk command "1 THRU 5".
t.command.execute("1 THRU 5")
73
Step
Execute the desk command "AT 0 THRU 50".
t.command.execute("AT 0 THRU 50")
74
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
75
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 0
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 32
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 64
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 96
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 128
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Step
Execute the desk command "1 THRU 5".
t.command.execute("1 THRU 5")
78
Step
Execute the desk command "AT 100 THRU 0 THRU 100".
t.command.execute("AT 100 THRU 0 THRU 100")
79
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
80
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 255
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 128
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 0
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 128
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131
Expected
fixture(index + 1) DMX equals
{
   Intensity:  intensity = 255
}
t.expectFixtureDMX(fixture(index + 1), { Intensity: intensity })
131

Diagnostics

None.

PROG-003 — newer fixture intensity wins LTP and releases back to its Group value

tests/43-semantic-foundational-programmer.spec.ts:85 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputEncoder controlsProgrammerShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
89
Open the ToskLight browser application.
t.app.open()
90
The ToskLight browser application is ready.
t.app.expect.ready()
91

Scenario contract

KindScenario contractLine
Step
Execute the desk command "GROUP 1 AT 50".
t.command.execute("GROUP 1 AT 50")
93
Step
Execute the desk command "1 AT 25".
t.command.execute("1 AT 25")
94
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
95
Expected
fixture(1) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixture(1), { Intensity: 64 })
96
Expected
fixtureRange(2, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(2, 12), { Intensity: 128 })
97
Step
Encoder → intensity → dimmer → release.
t.encoder.intensity.dimmer.release()
99
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
100
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 128 })
101

Diagnostics

None.

PROG-004 — Clear removes selection first and programmer values second

tests/43-semantic-foundational-programmer.spec.ts:105 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand keypadCommand lineDMX outputSemantic oracleShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
109
Open the ToskLight browser application.
t.app.open()
110
The ToskLight browser application is ready.
t.app.expect.ready()
111

Scenario contract

KindScenario contractLine
Step
Execute the desk command "1 + 2 AT 50".
t.command.execute("1 + 2 AT 50")
113
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
114
Step
Press keypad keys
[
  "CLR"
]
t.keypad.press(["CLR"])
115
Expected
Selection.
t.expect.selection()
116
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
117
Expected
fixtureRange(1, 2) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 2), { Intensity: 128 })
118
Step
Press keypad keys
[
  "CLR"
]
t.keypad.press(["CLR"])
120
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
121
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 0 })
122

Diagnostics

None.

CUE-008 — blind Preload records the same Cue without activating playback or output

tests/44-semantic-cue-recording-and-reconstruction.spec.ts:9 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICommand lineDMX outputGroupsPlaybacksPreloadRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
13
Open the ToskLight browser application.
t.app.open()
14
The ToskLight browser application is ready.
t.app.expect.ready()
15

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with ...fixtures =
[
  1,
   2,
   3,
   4
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 1,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Selection → fixtures → api → items with ...fixtures =
[
  5,
   6,
   7,
   8
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 2,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Selection → fixtures → api → items with ...fixtures =
[
  9,
   10,
   11,
   12
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 3,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Clear the current selection.
t.selection.clear()
150
Step
Start blind Preload programming.
t.preload.start()
18
Step
Execute the desk command "GROUP 1 AT 100".
t.command.execute("GROUP 1 AT 100")
19
Step
Record → playback with 1.
t.record.playback(1)
20
Expected
Playback → present: $playback (result of record.playback).
t.playback.expect(playback).present()
21
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
22
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 0 })
23
Step
Release blind Preload programming.
t.preload.release()
25
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
26
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
27
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 255 })
28
Expected
fixtureRange(5, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 12), { Intensity: 0 })
29

Diagnostics

None.

CUE-001 — Record targets playbacks while decimal insertion and Record operations preserve tracking

tests/44-semantic-cue-recording-and-reconstruction.spec.ts:33 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICommand lineCue runtimeDMX outputEncoder controlsGroupsPlaybacksProgrammerRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
37
Open the ToskLight browser application.
t.app.open()
38
The ToskLight browser application is ready.
t.app.expect.ready()
39

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with ...fixtures =
[
  1,
   2,
   3,
   4
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 1,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Selection → fixtures → api → items with ...fixtures =
[
  5,
   6,
   7,
   8
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 2,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Selection → fixtures → api → items with ...fixtures =
[
  9,
   10,
   11,
   12
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 3,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Clear the current selection.
t.selection.clear()
150
Step
Execute the desk command "GROUP 1 AT 100".
t.command.execute("GROUP 1 AT 100")
42
Step
Record → playback with 1.
t.record.playback(1)
43
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
44
Step
Execute the desk command "GROUP 3 AT 100".
t.command.execute("GROUP 3 AT 100")
45
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  1.5
}
t.record.cue({ playback, cue: 1.5 })
46
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
47
Step
Execute the desk command "GROUP 2 AT 80".
t.command.execute("GROUP 2 AT 80")
48
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
49
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
50
Step
Execute the desk command "GROUP 2 AT 50".
t.command.execute("GROUP 2 AT 50")
51
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2,
   mode:  CueRecordMode.Merge
}
t.record.cue({
			playback,
			cue: 2,
			mode: CueRecordMode.Merge,
		})
52
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2,
   mode:  CueRecordMode.Subtract
}
t.record.cue({
			playback,
			cue: 2,
			mode: CueRecordMode.Subtract,
		})
57
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
62
Expected
Cue → present: $playback (result of record.playback), 1.
t.cue.expect(playback, 1).present()
64
Expected
Cue → present: $playback (result of record.playback), 1.5.
t.cue.expect(playback, 1.5).present()
65
Expected
Cue → present: $playback (result of record.playback), 2.
t.cue.expect(playback, 2).present()
66
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
67
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
69
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
70
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 255 })
71
Expected
fixtureRange(5, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 12), { Intensity: 0 })
72
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
74
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
75
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 255 })
76
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 8), { Intensity: 0 })
77
Expected
fixtureRange(9, 12) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(9, 12), { Intensity: 255 })
78
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
80
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
81
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 255 })
82
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 8), { Intensity: 0 })
83
Expected
fixtureRange(9, 12) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(9, 12), { Intensity: 255 })
84

Diagnostics

None.

CUE-002 — Cue-only restoration reconstructs identically for sequential GO and direct jumps

tests/44-semantic-cue-recording-and-reconstruction.spec.ts:88 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICommand lineCue runtimeDMX outputEncoder controlsGroupsPlaybacksProgrammerRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
92
Open the ToskLight browser application.
t.app.open()
93
The ToskLight browser application is ready.
t.app.expect.ready()
94

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with ...fixtures =
[
  1,
   2,
   3,
   4
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 1,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Selection → fixtures → api → items with ...fixtures =
[
  5,
   6,
   7,
   8
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 2,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Selection → fixtures → api → items with ...fixtures =
[
  9,
   10,
   11,
   12
]
t.selection.fixtures.via.api.items(...fixtures)
147
Step
Group → api → store with group = 3,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(group, { mode: GroupStoreMode.Overwrite })
148
Step
Clear the current selection.
t.selection.clear()
150
Step
Execute the desk command "GROUP 1 AT 30".
t.command.execute("GROUP 1 AT 30")
97
Step
Record → playback with 1.
t.record.playback(1)
98
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
99
Step
Execute the desk command "GROUP 1 AT 80".
t.command.execute("GROUP 1 AT 80")
100
Step
Record → cue only with true.
t.record.cueOnly(true)
101
Step
Record → append with $playback (result of record.playback).
t.record.append(playback)
102
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
103
Step
Execute the desk command "GROUP 2 AT 60".
t.command.execute("GROUP 2 AT 60")
104
Step
Record → cue only with false.
t.record.cueOnly(false)
105
Step
Record → append with $playback (result of record.playback).
t.record.append(playback)
106
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
107
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
108
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
110
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
111
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  77
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 77 })
112
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 8), { Intensity: 0 })
113
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
115
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
116
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 204 })
117
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 8), { Intensity: 0 })
118
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
120
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
121
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  77
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 77 })
122
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  153
}
t.expectFixtureDMX(fixtureRange(5, 8), { Intensity: 153 })
123
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
126
Step
Cue → goto with $playback (result of record.playback), cue = 1.
t.cue.goto(playback, cue)
127
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
128
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  77
}
t.expectFixtureDMX(fixtureRange(1, 4), {
				Intensity: cue === 2 ? 204 : 77,
			})
129
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 8), {
				Intensity: cue === 3 ? 153 : 0,
			})
132
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
126
Step
Cue → goto with $playback (result of record.playback), cue = 2.
t.cue.goto(playback, cue)
127
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
128
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixtureRange(1, 4), {
				Intensity: cue === 2 ? 204 : 77,
			})
129
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 8), {
				Intensity: cue === 3 ? 153 : 0,
			})
132
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
126
Step
Cue → goto with $playback (result of record.playback), cue = 3.
t.cue.goto(playback, cue)
127
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
128
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  77
}
t.expectFixtureDMX(fixtureRange(1, 4), {
				Intensity: cue === 2 ? 204 : 77,
			})
129
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  153
}
t.expectFixtureDMX(fixtureRange(5, 8), {
				Intensity: cue === 3 ? 153 : 0,
			})
132

Diagnostics

None.

CUE-003 — GO, pause, resume, back, and release use exact application-time boundaries

tests/45-semantic-cue-runtime-timing.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICue timingDMX outputEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
15
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
16
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
18
Step
Encoder → intensity → dimmer → api → set with 0.
t.encoder.intensity.dimmer.via.api.set(0)
19
Step
Record → playback with 1.
t.record.playback(1)
20
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
21
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
22
Step
Encoder → intensity → dimmer → api → set with 100.
t.encoder.intensity.dimmer.via.api.set(100)
23
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2,
   timing:  {
     fade:  "4"
  }
}
t.record.cue({ playback, cue: 2, timing: { fade: "4" } })
24
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
25
Step
Playback → configure with $playback (result of record.playback),
{
   buttons:  [
    PlaybackButton.GoBack,
     PlaybackButton.Go,
     PlaybackButton.Pause
  ]
}
t.playback.configure(playback, {
			buttons: [PlaybackButton.GoBack, PlaybackButton.Go, PlaybackButton.Pause],
		})
26
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
29
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
31
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
32
Step
Advance the test clock by "1s".
t.clock.advanceBy("1s")
33
Expected
fixture(1) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixture(1), { Intensity: 64 })
34
Step
Playback → pause with $playback (result of record.playback).
t.playback.pause(playback)
35
Step
Advance the test clock by "10s".
t.clock.advanceBy("10s")
36
Expected
fixture(1) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixture(1), { Intensity: 64 })
37
Step
Playback → pause with $playback (result of record.playback).
t.playback.pause(playback)
38
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
39
Expected
fixture(1) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixture(1), { Intensity: 255 })
40
Step
Playback → go back with $playback (result of record.playback).
t.playback.goBack(playback)
42
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
43
Expected
fixture(1) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixture(1), { Intensity: 255 })
44
Step
Advance the test clock by "4s".
t.clock.advanceBy("4s")
45
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
46
Step
Playback → release with $playback (result of record.playback).
t.playback.release(playback)
47
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
48
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
49

Diagnostics

None.

CUE-004 — per-value timing overrides Cue fallback and Force Cue Timing is reversible

tests/46-semantic-cue-value-timing.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue runtimeCue timingDMX outputEncoder controlsPlaybacksProgrammerProgrammer timingRecordingShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
14
Step
Execute the desk command "GROUP 1 AT 0".
t.command.execute("GROUP 1 AT 0")
16
Step
Record → playback with 1.
t.record.playback(1)
17
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
18
Step
Timing → programmer fade → api → set with "9s".
t.timing.programmerFade.via.api.set("9s")
20
Step
Execute the desk command "GROUP 1 AT 50 TIME 2".
t.command.execute("GROUP 1 AT 50 TIME 2")
21
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2,
   timing:  {
     fade:  "3"
  }
}
t.record.cue({ playback, cue: 2, timing: { fade: "3" } })
22
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
23
Expected
Cue → metadata: $playback (result of record.playback), 2,
{
   fade_millis:  3000,
   delay_millis:  0
}
t.cue.expect(playback, 2).metadata({
			fade_millis: 3_000,
			delay_millis: 0,
		})
24
Expected
Cue → group value timing: $playback (result of record.playback), 2, 1, "intensity",
{
   fade:  "2s"
}
t.cue
			.expect(playback, 2)
			.groupValueTiming(1, "intensity", { fade: "2s" })
28
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
32
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
33
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
34
Step
Advance the test clock by "1999ms".
t.clock.advanceBy("1999ms")
35
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  127
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 127 })
36
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
37
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 128 })
38

Diagnostics

None.

CUE-005 — GO, FOLLOW, and TIME retain their distinct Cue trigger meanings

tests/47-semantic-cue-trigger-and-selection.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand keypadCommand lineCue runtimeCue timingProgrammer timingRecordingShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
15
Step
Execute the desk command "GROUP 1 AT 50".
t.command.execute("GROUP 1 AT 50")
17
Step
Record → playback with 1.
t.record.playback(1)
18
Step
Command → type with "RECORD PBK 1 CUE 2 TIME TIME 0".
t.command.type("RECORD PBK 1 CUE 2 TIME TIME 0")
19
Expected
Command line shows "RECORD PBK 1 CUE 2 DELAY 0".
t.command.expect("RECORD PBK 1 CUE 2 DELAY 0")
20
Step
Press keypad keys
[
  "ENT"
]
t.keypad.press(["ENT"])
21
Step
Command → type with "RECORD PBK 1 CUE 3 TIME TIME 4".
t.command.type("RECORD PBK 1 CUE 3 TIME TIME 4")
22
Expected
Command line shows "RECORD PBK 1 CUE 3 DELAY 4".
t.command.expect("RECORD PBK 1 CUE 3 DELAY 4")
23
Step
Press keypad keys
[
  "ENT"
]
t.keypad.press(["ENT"])
24
Expected
Cue → trigger: $playback (result of record.playback), 1,
{
   type:  "manual"
}
t.cue.expect(playback, 1).trigger({ type: "manual" })
26
Expected
Cue → trigger: $playback (result of record.playback), 2,
{
   type:  "follow",
   delay_millis:  0
}
t.cue
			.expect(playback, 2)
			.trigger({ type: "follow", delay_millis: 0 })
27
Expected
Cue → trigger: $playback (result of record.playback), 3,
{
   type:  "wait",
   delay_millis:  4000
}
t.cue
			.expect(playback, 3)
			.trigger({ type: "wait", delay_millis: 4_000 })
30

Diagnostics

None.

CUE-006 — explicit playback selection supplies the implicit Cuelist without following execution order

tests/47-semantic-cue-trigger-and-selection.spec.ts:36 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue runtimeCue timingEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
40
Open the ToskLight browser application.
t.app.open()
41
The ToskLight browser application is ready.
t.app.expect.ready()
42

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
43
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
45
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
46
Step
Record → playback with 1.
t.record.playback(1)
47
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
48
Step
Selection → fixtures → api → item with 2.
t.selection.fixtures.via.api.item(2)
49
Step
Encoder → intensity → dimmer → api → set with 30.
t.encoder.intensity.dimmer.via.api.set(30)
50
Step
Record → playback with 2.
t.record.playback(2)
51
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
52
Step
Playback → select with $second (result of record.playback).
t.playback.select(second)
54
Expected
Playback → selected: $second (result of record.playback).
t.playback.expect(second).selected()
55
Step
Playback → go with $first (result of record.playback).
t.playback.go(first)
56
Expected
Playback → selected: $second (result of record.playback).
t.playback.expect(second).selected()
57
Step
Selection → fixtures → api → item with 3.
t.selection.fixtures.via.api.item(3)
59
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
60
Step
Execute the desk command "RECORD CUE 7".
t.command.execute("RECORD CUE 7")
61
Expected
Cue → present: $second (result of record.playback), 7.
t.cue.expect(second, 7).present()
62
Expected
Cue → absent: $first (result of record.playback), 7.
t.cue.expect(first, 7).absent()
63
Expected
Playback → selected: $second (result of record.playback).
t.playback.expect(second).selected()
64

Diagnostics

None.

CUE-007 — explicit zeroes block a later inserted on Cue from tracking past Cue 4

tests/47-semantic-cue-trigger-and-selection.spec.ts:68 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue runtimeCue timingDMX outputEncoder controlsGroupsPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
72
Open the ToskLight browser application.
t.app.open()
73
The ToskLight browser application is ready.
t.app.expect.ready()
74

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
75
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
76
Step
Selection → fixtures → api → items with 1, 2, 3, 4.
t.selection.fixtures.via.api.items(1, 2, 3, 4)
78
Step
Group → api → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(1, { mode: StoreMode.Overwrite })
79
Step
Selection → fixtures → api → items with 5, 6, 7, 8.
t.selection.fixtures.via.api.items(5, 6, 7, 8)
80
Step
Group → api → store with 2,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(2, { mode: StoreMode.Overwrite })
81
Step
Selection → fixtures → api → items with 9, 10, 11, 12.
t.selection.fixtures.via.api.items(9, 10, 11, 12)
82
Step
Group → api → store with 3,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(3, { mode: StoreMode.Overwrite })
83
Step
Clear the current selection.
t.selection.clear()
84
Step
Execute the desk command "GROUP 1 AT 100".
t.command.execute("GROUP 1 AT 100")
85
Step
Record → playback with 1.
t.record.playback(1)
86
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
87
Step
Execute the desk command "GROUP 1 AT 0".
t.command.execute("GROUP 1 AT 0")
88
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
89
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
90
Step
Execute the desk command "GROUP 2 AT 100".
t.command.execute("GROUP 2 AT 100")
91
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  3
}
t.record.cue({ playback, cue: 3 })
92
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
93
Step
Execute the desk command "GROUP 1 AT 0".
t.command.execute("GROUP 1 AT 0")
94
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  4
}
t.record.cue({ playback, cue: 4 })
95
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
96
Step
Execute the desk command "GROUP 3 AT 100".
t.command.execute("GROUP 3 AT 100")
97
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  5
}
t.record.cue({ playback, cue: 5 })
98
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
99
Step
Execute the desk command "GROUP 1 AT 100".
t.command.execute("GROUP 1 AT 100")
100
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  3.5
}
t.record.cue({ playback, cue: 3.5 })
101
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
102
Expected
Cue → group value: $playback (result of record.playback), 1, 1, "intensity", 1.
t.cue.expect(playback, 1).groupValue(1, "intensity", 1)
104
Expected
Cue → group value: $playback (result of record.playback), 4, 1, "intensity", 0.
t.cue.expect(playback, 4).groupValue(1, "intensity", 0)
105
Step
Playback → release with $playback (result of record.playback).
t.playback.release(playback)
106
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
107
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
108
Expected
Playback → runtime: $playback (result of record.playback),
{
   current_cue_number:  "1"
}
t.playback.expect(playback).runtime({ current_cue_number: "1" })
109
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 255 })
110
Expected
fixtureRange(5, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(5, 12), { Intensity: 0 })
111
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
112
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
113
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 0 })
114
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
115
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
116
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 0 })
117
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(5, 8), { Intensity: 255 })
118
Expected
fixtureRange(9, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(9, 12), { Intensity: 0 })
119
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
120
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
121
Expected
fixtureRange(1, 8) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(1, 8), { Intensity: 255 })
122
Expected
fixtureRange(9, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(9, 12), { Intensity: 0 })
123
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
124
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
125
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 0 })
126
Expected
fixtureRange(5, 8) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(5, 8), { Intensity: 255 })
127
Expected
fixtureRange(9, 12) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(9, 12), { Intensity: 0 })
128
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
129
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
130
Expected
fixtureRange(1, 4) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixtureRange(1, 4), { Intensity: 0 })
131
Expected
fixtureRange(5, 12) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixtureRange(5, 12), { Intensity: 255 })
132

Diagnostics

None.

CUE-010 — tracking and LTP ownership stay per attribute and reveal the underlying programmer

tests/48-semantic-cue-tracking-and-merge.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue runtimeCue timingEncoder controlsPlaybacksProgrammerProgrammer timingRecordingResolved outputSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
15
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
16
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
18
Step
Encoder → intensity → dimmer → api → set with 100.
t.encoder.intensity.dimmer.via.api.set(100)
19
Step
Record → playback with 1.
t.record.playback(1)
20
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
21
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
22
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
23
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
24
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
25
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
26
Step
Encoder → color → red → api → set with 0.
t.encoder.color.red.via.api.set(0)
27
Step
Encoder → color → green → api → set with 0.
t.encoder.color.green.via.api.set(0)
28
Step
Encoder → color → blue → api → set with 100.
t.encoder.color.blue.via.api.set(100)
29
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  3
}
t.record.cue({ playback, cue: 3 })
30
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
31
Step
Clear the current selection.
t.selection.clear()
32
Step
Selection → fixtures → api → item with 2.
t.selection.fixtures.via.api.item(2)
33
Step
Encoder → intensity → dimmer → api → set with 40.
t.encoder.intensity.dimmer.via.api.set(40)
34
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  4
}
t.record.cue({ playback, cue: 4 })
35
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
36
Step
Playback → configure with $playback (result of record.playback),
{
   buttons:  [
    PlaybackButton.GoBack,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(playback, {
			buttons: [PlaybackButton.GoBack, PlaybackButton.Go, PlaybackButton.Off],
		})
37
Step
Cue → configure with $playback (result of record.playback),
{
   priority:  100
}
t.cue.configure(playback, { priority: 100 })
40
Step
Programmer → priority → api → set with 100.
t.programmer.priority.via.api.set(100)
41
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
42
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
44
Step
Encoder → color → red → api → set with 0.
t.encoder.color.red.via.api.set(0)
45
Step
Encoder → color → green → api → set with 100.
t.encoder.color.green.via.api.set(100)
46
Step
Encoder → color → blue → api → set with 0.
t.encoder.color.blue.via.api.set(0)
47
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
48
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
50
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
51
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
52
Expected
fixture(21) resolved values equal
{
   intensity:  0.5,
   "color:red":  0,
   "color:green":  1,
   "color:blue":  0
}
t.expectFixtureValue(fixture(21), {
			intensity: 0.5,
			"color:red": 0,
			"color:green": 1,
			"color:blue": 0,
		})
53
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
59
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
60
Expected
fixture(21) resolved values equal
{
   intensity:  0.5,
   "color:red":  0,
   "color:green":  0,
   "color:blue":  1
}
t.expectFixtureValue(fixture(21), {
			intensity: 0.5,
			"color:red": 0,
			"color:green": 0,
			"color:blue": 1,
		})
61
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
67
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
68
Expected
fixture(21) resolved values equal
{
   intensity:  0.5,
   "color:red":  0,
   "color:green":  0,
   "color:blue":  1
}
t.expectFixtureValue(fixture(21), {
			intensity: 0.5,
			"color:red": 0,
			"color:green": 0,
			"color:blue": 1,
		})
69
Step
Playback → off with $playback (result of record.playback).
t.playback.off(playback)
75
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
76
Expected
fixture(21) resolved values equal
{
   intensity:  0,
   "color:red":  0,
   "color:green":  1,
   "color:blue":  0
}
t.expectFixtureValue(fixture(21), {
			intensity: 0,
			"color:red": 0,
			"color:green": 1,
			"color:blue": 0,
		})
77

Diagnostics

None.

MERGE-002 — independent Sequences coexist and retrigger only their stored addresses

tests/48-semantic-cue-tracking-and-merge.spec.ts:86 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue runtimeCue timingEncoder controlsPlaybacksProgrammerProgrammer timingRecordingResolved outputSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
90
Open the ToskLight browser application.
t.app.open()
91
The ToskLight browser application is ready.
t.app.expect.ready()
92

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
93
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
94
Step
Programmer → priority → api → set with 100.
t.programmer.priority.via.api.set(100)
95
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
97
Step
Encoder → intensity → dimmer → api → set with 60.
t.encoder.intensity.dimmer.via.api.set(60)
98
Step
Encoder → color → red → api → set with 0.
t.encoder.color.red.via.api.set(0)
99
Step
Encoder → color → green → api → set with 0.
t.encoder.color.green.via.api.set(0)
100
Step
Encoder → color → blue → api → set with 100.
t.encoder.color.blue.via.api.set(100)
101
Step
Record → playback with 1.
t.record.playback(1)
102
Step
Playback → configure with $sequenceA (result of record.playback),
{
   name:  "Sequence A",
   buttons:  [
    PlaybackButton.On,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(sequenceA, {
			name: "Sequence A",
			buttons: [PlaybackButton.On, PlaybackButton.Go, PlaybackButton.Off],
		})
103
Step
Cue → configure with $sequenceA (result of record.playback),
{
   priority:  100
}
t.cue.configure(sequenceA, { priority: 100 })
107
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
108
Step
Clear the current selection.
t.selection.clear()
109
Step
Selection → fixtures → api → item with 22.
t.selection.fixtures.via.api.item(22)
111
Step
Encoder → intensity → dimmer → api → set with 40.
t.encoder.intensity.dimmer.via.api.set(40)
112
Step
Encoder → color → red → api → set with 100.
t.encoder.color.red.via.api.set(100)
113
Step
Encoder → color → green → api → set with 70.
t.encoder.color.green.via.api.set(70)
114
Step
Encoder → color → blue → api → set with 40.
t.encoder.color.blue.via.api.set(40)
115
Step
Record → playback with 2.
t.record.playback(2)
116
Step
Playback → configure with $sequenceB (result of record.playback),
{
   name:  "Sequence B",
   buttons:  [
    PlaybackButton.On,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(sequenceB, {
			name: "Sequence B",
			buttons: [PlaybackButton.On, PlaybackButton.Go, PlaybackButton.Off],
		})
117
Step
Cue → configure with $sequenceB (result of record.playback),
{
   priority:  100
}
t.cue.configure(sequenceB, { priority: 100 })
121
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
122
Step
Clear the current selection.
t.selection.clear()
123
Step
Playback → api → off with $sequenceA (result of record.playback).
t.playback.via.api.off(sequenceA)
124
Step
Playback → api → off with $sequenceB (result of record.playback).
t.playback.via.api.off(sequenceB)
125
Step
Playback → api → on with $sequenceA (result of record.playback).
t.playback.via.api.on(sequenceA)
126
Step
Playback → api → on with $sequenceB (result of record.playback).
t.playback.via.api.on(sequenceB)
127
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
128
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
130
Step
Encoder → color → red → api → set with 100.
t.encoder.color.red.via.api.set(100)
131
Step
Clear the current selection.
t.selection.clear()
132
Step
Selection → fixtures → api → item with 22.
t.selection.fixtures.via.api.item(22)
133
Step
Encoder → color → blue → api → set with 80.
t.encoder.color.blue.via.api.set(80)
134
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
135
Expected
fixture(22) resolved values equal
{
   "color:blue":  0.8
}
t.expectFixtureValue(fixture(22), { "color:blue": 0.8 })
136
Step
Command → clear.
t.command.clear()
138
Step
Playback → select with $sequenceA (result of record.playback).
t.playback.select(sequenceA)
139
Step
Cue → goto with $sequenceA (result of record.playback), 1.
t.cue.goto(sequenceA, 1)
141
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
142
Expected
fixture(21) resolved values equal
{
   intensity:  0.6,
   "color:red":  0,
   "color:green":  0,
   "color:blue":  1
}
t.expectFixtureValue(fixture(21), {
			intensity: 0.6,
			"color:red": 0,
			"color:green": 0,
			"color:blue": 1,
		})
143
Expected
fixture(22) resolved values equal
{
   intensity:  0.4,
   "color:red":  1,
   "color:green":  0.7,
   "color:blue":  0.8
}
t.expectFixtureValue(fixture(22), {
			intensity: 0.4,
			"color:red": 1,
			"color:green": 0.7,
			"color:blue": 0.8,
		})
149

Diagnostics

None.

MERGE-003 — full normal overwrite auto-Offs while partial, disabled, Flash, and Temp restore

tests/48-semantic-cue-tracking-and-merge.spec.ts:158 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue timingEncoder controlsPlaybacksProgrammerProgrammer timingRecordingResolved outputSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
162
Open the ToskLight browser application.
t.app.open()
163
The ToskLight browser application is ready.
t.app.expect.ready()
164

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
165
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
166
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
176
Step
Encoder → color → red → api → set with 0.
t.encoder.color.red.via.api.set(color[0])
179
Step
Encoder → color → green → api → set with 0.
t.encoder.color.green.via.api.set(color[1])
180
Step
Encoder → color → blue → api → set with 100.
t.encoder.color.blue.via.api.set(color[2])
181
Step
Record → playback with number = 1.
t.record.playback(number)
182
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Underlying blue",
   autoOff:  autoOff = true,
   buttons:  buttons = [
    PlaybackButton.On,
     PlaybackButton.Off,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, { name, autoOff, buttons })
183
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
184
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
185
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
176
Step
Encoder → color → red → api → set with 100.
t.encoder.color.red.via.api.set(color[0])
179
Step
Encoder → color → green → api → set with 0.
t.encoder.color.green.via.api.set(color[1])
180
Step
Encoder → color → blue → api → set with 0.
t.encoder.color.blue.via.api.set(color[2])
181
Step
Record → playback with number = 2.
t.record.playback(number)
182
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Replacing red",
   autoOff:  autoOff = false,
   buttons:  buttons = [
    PlaybackButton.On,
     PlaybackButton.Flash,
     PlaybackButton.Temp
  ]
}
t.playback.configure(playback, { name, autoOff, buttons })
183
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
184
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
185
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
176
Step
Encoder → intensity → dimmer → api → set with intensity = 100.
t.encoder.intensity.dimmer.via.api.set(intensity)
178
Step
Encoder → color → red → api → set with 0.
t.encoder.color.red.via.api.set(color[0])
179
Step
Encoder → color → green → api → set with 0.
t.encoder.color.green.via.api.set(color[1])
180
Step
Encoder → color → blue → api → set with 100.
t.encoder.color.blue.via.api.set(color[2])
181
Step
Record → playback with number = 3.
t.record.playback(number)
182
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Partial underlying blue",
   autoOff:  autoOff = true,
   buttons:  buttons = [
    PlaybackButton.On,
     PlaybackButton.Off,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, { name, autoOff, buttons })
183
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
184
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
185
Step
Selection → fixtures → api → item with 21.
t.selection.fixtures.via.api.item(21)
176
Step
Encoder → color → red → api → set with 100.
t.encoder.color.red.via.api.set(color[0])
179
Step
Encoder → color → green → api → set with 0.
t.encoder.color.green.via.api.set(color[1])
180
Step
Encoder → color → blue → api → set with 0.
t.encoder.color.blue.via.api.set(color[2])
181
Step
Record → playback with number = 4.
t.record.playback(number)
182
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Partial replacing red",
   autoOff:  autoOff = false,
   buttons:  buttons = [
    PlaybackButton.On,
     PlaybackButton.Flash,
     PlaybackButton.Temp
  ]
}
t.playback.configure(playback, { name, autoOff, buttons })
183
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
184
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
185
Expected
Playback → configuration: $underlying (result of recordLook),
{
   auto_off:  true
}
t.playback.expect(underlying).configuration({ auto_off: true })
221
Expected
Playback → configuration: $replacing (result of recordLook),
{
   auto_off:  false
}
t.playback.expect(replacing).configuration({ auto_off: false })
222
Step
Playback → on with $underlying (result of recordLook).
t.playback.on(underlying)
224
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
225
Step
Playback → on with $replacing (result of recordLook).
t.playback.on(replacing)
226
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
227
Expected
Playback → runtime: $underlying (result of recordLook),
{
   enabled:  false
}
t.playback.expect(underlying).runtime({ enabled: false })
228
Expected
fixture(21) resolved values equal
{
   "color:red":  1,
   "color:green":  0,
   "color:blue":  0
}
t.expectFixtureValue(fixture(21), {
			"color:red": 1,
			"color:green": 0,
			"color:blue": 0,
		})
229
Step
Playback → configure with $underlying (result of recordLook),
{
   autoOff:  false
}
t.playback.configure(underlying, { autoOff: false })
235
Step
Playback → api → off with $replacing (result of recordLook).
t.playback.via.api.off(replacing)
236
Step
Playback → on with $underlying (result of recordLook).
t.playback.on(underlying)
237
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
238
Step
Playback → on with $replacing (result of recordLook).
t.playback.on(replacing)
239
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
240
Expected
Playback → runtime: $underlying (result of recordLook),
{
   enabled:  true
}
t.playback.expect(underlying).runtime({ enabled: true })
241
Step
Playback → api → off with $replacing (result of recordLook).
t.playback.via.api.off(replacing)
242
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
243
Expected
fixture(21) resolved values equal
{
   "color:red":  0,
   "color:green":  0,
   "color:blue":  1
}
t.expectFixtureValue(fixture(21), {
			"color:red": 0,
			"color:green": 0,
			"color:blue": 1,
		})
244
Step
Playback → configure with $underlying (result of recordLook),
{
   autoOff:  true
}
t.playback.configure(underlying, { autoOff: true })
250
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
251
Step
Playback → ui → flash → hold with $replacing (result of recordLook), <generated: callback>.
t.playback.via.ui.flash(replacing).hold(async () => {
			await t.playback.expect(replacing).runtime({ enabled: false, flash: true });
			await t.clock.advanceStep();
			await t.playback.expect(underlying).runtime({ enabled: true });
			await t.expectFixtureValue(fixture(21), {
				"color:red": 1,
				"color:green": 0,
				"color:blue": 0,
			});
		})
252
Expected
Playback → runtime: $replacing (result of recordLook),
{
   enabled:  false,
   flash:  true
}
t.playback.expect(replacing).runtime({ enabled: false, flash: true })
253
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
254
Expected
Playback → runtime: $underlying (result of recordLook),
{
   enabled:  true
}
t.playback.expect(underlying).runtime({ enabled: true })
255
Expected
fixture(21) resolved values equal
{
   "color:red":  1,
   "color:green":  0,
   "color:blue":  0
}
t.expectFixtureValue(fixture(21), {
				"color:red": 1,
				"color:green": 0,
				"color:blue": 0,
			})
256
Expected
Playback → runtime: $replacing (result of recordLook),
{
   enabled:  false,
   flash:  false
}
t.playback.expect(replacing).runtime({ enabled: false, flash: false })
263
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
264
Expected
fixture(21) resolved values equal
{
   "color:red":  0,
   "color:green":  0,
   "color:blue":  1
}
t.expectFixtureValue(fixture(21), {
			"color:red": 0,
			"color:green": 0,
			"color:blue": 1,
		})
265
Step
Playback → ui → temp with $replacing (result of recordLook).
t.playback.via.ui.temp(replacing)
271
Expected
Playback → runtime: $replacing (result of recordLook),
{
   temporary_active:  true
}
t.playback.expect(replacing).runtime({ temporary_active: true })
272
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
273
Expected
Playback → runtime: $underlying (result of recordLook),
{
   enabled:  true
}
t.playback.expect(underlying).runtime({ enabled: true })
274
Expected
fixture(21) resolved values equal
{
   "color:red":  1,
   "color:green":  0,
   "color:blue":  0
}
t.expectFixtureValue(fixture(21), {
			"color:red": 1,
			"color:green": 0,
			"color:blue": 0,
		})
275
Step
Playback → ui → temp with $replacing (result of recordLook).
t.playback.via.ui.temp(replacing)
280
Expected
Playback → runtime: $replacing (result of recordLook),
{
   enabled:  false,
   temporary_active:  false
}
t.playback.expect(replacing).runtime({ enabled: false, temporary_active: false })
281
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
282
Expected
fixture(21) resolved values equal
{
   "color:red":  0,
   "color:green":  0,
   "color:blue":  1
}
t.expectFixtureValue(fixture(21), {
			"color:red": 0,
			"color:green": 0,
			"color:blue": 1,
		})
283
Step
Playback → api → off with $underlying (result of recordLook).
t.playback.via.api.off(underlying)
289
Step
Playback → api → off with $replacing (result of recordLook).
t.playback.via.api.off(replacing)
290
Step
Playback → on with $partialUnderlying (result of recordLook).
t.playback.on(partialUnderlying)
291
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
292
Step
Playback → on with $partialReplacing (result of recordLook).
t.playback.on(partialReplacing)
293
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
294
Expected
Playback → runtime: $partialUnderlying (result of recordLook),
{
   enabled:  true
}
t.playback.expect(partialUnderlying).runtime({ enabled: true })
295
Expected
fixture(21) resolved values equal
{
   intensity:  1,
   "color:red":  1,
   "color:green":  0,
   "color:blue":  0
}
t.expectFixtureValue(fixture(21), {
			intensity: 1,
			"color:red": 1,
			"color:green": 0,
			"color:blue": 0,
		})
296

Diagnostics

None.

CUE-009 — explicit Plain/Status Move/Copy choices preserve both independent axes

tests/49-semantic-cue-transfer-speed-and-navigation.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue runtimeEncoder controlsProgrammerRecordingSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
16
Step
Encoder → intensity → dimmer → api → set with 25.
t.encoder.intensity.dimmer.via.api.set(25)
17
Step
Record → playback with 1.
t.record.playback(1)
18
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
19
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
20
Step
Record → cue with
{
   playback:  $source (result of record.playback),
   cue:  2
}
t.record.cue({ playback: source, cue: 2 })
21
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
22
Step
Encoder → intensity → dimmer → api → set with 75.
t.encoder.intensity.dimmer.via.api.set(75)
23
Step
Record → playback with 2.
t.record.playback(2)
24
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
25
Expected
Cue → present: $source (result of record.playback), 2.
t.cue.expect(source, 2).present()
27
Expected
Cue → absent: $destination (result of record.playback), 2.
t.cue.expect(destination, 2).absent()
28
Step
Execute the desk command "COPY CUELIST 1 CUE 2 AT CUELIST 2 CUE 2".
t.command.execute("COPY CUELIST 1 CUE 2 AT CUELIST 2 CUE 2")
29
Step
Cue → transfer choice → cancel with "COPY".
t.cue.transferChoice("COPY").cancel()
30
Expected
Cue → present: $source (result of record.playback), 2.
t.cue.expect(source, 2).present()
31
Expected
Cue → absent: $destination (result of record.playback), 2.
t.cue.expect(destination, 2).absent()
32

Diagnostics

None.

CMD-002 — Speed Group commands address, synchronize, display, and manually unlink all five groups

tests/49-semantic-cue-transfer-speed-and-navigation.spec.ts:36 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICommand lineShow filesSpeed Groups
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
40
Open the ToskLight browser application.
t.app.open()
41
The ToskLight browser application is ready.
t.app.expect.ready()
42

Scenario contract

KindScenario contractLine
Step
Execute the desk command "SPD GRP 1 AT 120".
t.command.execute("SPD GRP 1 AT 120")
44
Expected
Speed group → A → bpm: 120.
t.speedGroup.A.expect.bpm(120)
45
Step
Execute the desk command "SPD GRP 2 AT 127.5".
t.command.execute("SPD GRP 2 AT 127.5")
46
Expected
Speed group → B → bpm: 127.5.
t.speedGroup.B.expect.bpm(127.5)
47
Step
Execute the desk command "SPD GRP 3 AT 131".
t.command.execute("SPD GRP 3 AT 131")
48
Expected
Speed group → C → bpm: 131.
t.speedGroup.C.expect.bpm(131)
49
Step
Execute the desk command "SPD GRP 4 AT 142".
t.command.execute("SPD GRP 4 AT 142")
50
Expected
Speed group → D → bpm: 142.
t.speedGroup.D.expect.bpm(142)
51
Step
Execute the desk command "SPD GRP 5 AT 153".
t.command.execute("SPD GRP 5 AT 153")
52
Expected
Speed group → E → bpm: 153.
t.speedGroup.E.expect.bpm(153)
53
Step
Execute the desk command "SPD GRP 1 AT + 5".
t.command.execute("SPD GRP 1 AT + 5")
55
Expected
Speed group → A → bpm: 125.
t.speedGroup.A.expect.bpm(125)
56
Step
Execute the desk command "SPD GRP 1 AT - 5".
t.command.execute("SPD GRP 1 AT - 5")
57
Expected
Speed group → A → bpm: 120.
t.speedGroup.A.expect.bpm(120)
58
Step
Execute the desk command "SPD GRP 3 AT 90".
t.command.execute("SPD GRP 3 AT 90")
59
Step
Execute the desk command "SPD GRP 1 AT SPD GRP 3".
t.command.execute("SPD GRP 1 AT SPD GRP 3")
60
Expected
Speed group → C → synchronized from: "A".
t.speedGroup.C.expect.synchronizedFrom(t.speedGroup.A.group)
61
Expected
Speed group → C → bpm: 120.
t.speedGroup.C.expect.bpm(120)
62
Step
Speed group → A → click → tap tempo with 80, 5.
t.speedGroup.A.via.click.tapTempo(80, 5)
64
Expected
Speed group → A → bpm within: 80, 2.
t.speedGroup.A.expect.bpmWithin(80, 2)
65
Expected
Speed group → A → synchronized from: null.
t.speedGroup.A.expect.synchronizedFrom(null)
66
Expected
Speed group → C → bpm: 120.
t.speedGroup.C.expect.bpm(120)
67
Expected
Speed group → C → synchronized from: null.
t.speedGroup.C.expect.synchronizedFrom(null)
68
Step
Execute the desk command "SPD GRP 1 AT 85".
t.command.execute("SPD GRP 1 AT 85")
70
Expected
Speed group → A → bpm: 85.
t.speedGroup.A.expect.bpm(85)
71
Expected
Speed group → C → bpm: 120.
t.speedGroup.C.expect.bpm(120)
72

Diagnostics

None.

CUE-014 — Cue Go To and Load preserve desk-local selection and authoritative output controls

tests/49-semantic-cue-transfer-speed-and-navigation.spec.ts:76 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue timingDMX outputEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
80
Open the ToskLight browser application.
t.app.open()
81
The ToskLight browser application is ready.
t.app.expect.ready()
82

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
83
Step
Timing → cue fade → set with "3s".
t.timing.cueFade.set("3s")
84
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
87
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
88
Step
Record → playback with slot = 1.
t.record.playback(slot)
89
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
90
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
91
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
92
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
93
Step
Encoder → intensity → dimmer → api → set with 80.
t.encoder.intensity.dimmer.via.api.set(80)
94
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  3
}
t.record.cue({ playback, cue: 3 })
95
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
96
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Twin A",
   buttons:  [
    PlaybackButton.GoBack,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(playback, {
				name,
				buttons: [PlaybackButton.GoBack, PlaybackButton.Go, PlaybackButton.Off],
			})
97
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
101
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
87
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
88
Step
Record → playback with slot = 2.
t.record.playback(slot)
89
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
90
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
91
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
92
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
93
Step
Encoder → intensity → dimmer → api → set with 80.
t.encoder.intensity.dimmer.via.api.set(80)
94
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  3
}
t.record.cue({ playback, cue: 3 })
95
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
96
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Twin B",
   buttons:  [
    PlaybackButton.GoBack,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(playback, {
				name,
				buttons: [PlaybackButton.GoBack, PlaybackButton.Go, PlaybackButton.Off],
			})
97
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
101
Step
Command → clear.
t.command.clear()
107
Step
Playback → select with $second (result of recordSequence).
t.playback.select(second)
108
Step
Playback → go with $first (result of recordSequence).
t.playback.go(first)
109
Expected
Playback → runtime: $first (result of recordSequence),
{
   current_cue_number:  "1"
}
t.playback.expect(first).runtime({ current_cue_number: "1" })
110
Expected
Playback → selected: $second (result of recordSequence).
t.playback.expect(second).selected()
111
Step
Execute the desk command "GO TO PBK 2 CUE 3".
t.command.execute("GO TO PBK 2 CUE 3")
113
Expected
Playback → runtime: $second (result of recordSequence),
{
   current_cue_number:  "3",
   master:  1,
   enabled:  true
}
t.playback.expect(second).runtime({
			current_cue_number: "3",
			master: 1,
			enabled: true,
		})
114
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
119
Expected
fixture(1) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixture(1), { Intensity: 204 })
120
Step
Execute the desk command "LOAD PBK 2 CUE 2".
t.command.execute("LOAD PBK 2 CUE 2")
122
Expected
Playback → runtime: $second (result of recordSequence),
{
   current_cue_number:  "3",
   effective_next_cue_number:  "2",
   effective_next_is_loaded:  true
}
t.playback.expect(second).runtime({
			current_cue_number: "3",
			effective_next_cue_number: "2",
			effective_next_is_loaded: true,
		})
123
Step
Playback → go with $second (result of recordSequence).
t.playback.go(second)
128
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
129
Expected
Playback → runtime: $second (result of recordSequence),
{
   current_cue_number:  "2",
   effective_next_cue_number:  "3",
   effective_next_is_loaded:  false
}
t.playback.expect(second).runtime({
			current_cue_number: "2",
			effective_next_cue_number: "3",
			effective_next_is_loaded: false,
		})
130
Expected
fixture(1) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(1), { Intensity: 128 })
135
Step
Execute the desk command "LOAD PBK 2 CUE 3".
t.command.execute("LOAD PBK 2 CUE 3")
137
Step
Playback → go back with $second (result of recordSequence).
t.playback.goBack(second)
138
Expected
Playback → runtime: $second (result of recordSequence),
{
   current_cue_number:  "1",
   loaded_cue_number:  "3",
   effective_next_is_loaded:  true
}
t.playback.expect(second).runtime({
			current_cue_number: "1",
			loaded_cue_number: "3",
			effective_next_is_loaded: true,
		})
139
Step
Playback → api → off with $second (result of recordSequence).
t.playback.via.api.off(second)
144
Expected
Playback → runtime: $second (result of recordSequence),
{
   enabled:  false,
   effective_next_is_loaded:  false
}
t.playback.expect(second).runtime({
			enabled: false,
			effective_next_is_loaded: false,
		})
145

Diagnostics

None.

DMX-001 — exact byte conversion agrees in logical, Art-Net, and sACN output

tests/49-semantic-network-output-protocols.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineCue timingDMX outputProgrammer timingSemantic oracleShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
15
Step
Execute the desk command "FIXTURE 1 AT 0 TIME 0".
t.command.execute("FIXTURE 1 AT 0 TIME 0")
17
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
18
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
19
Step
Execute the desk command "FIXTURE 1 AT 25 TIME 0".
t.command.execute("FIXTURE 1 AT 25 TIME 0")
20
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
21
Expected
fixture(1) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixture(1), { Intensity: 64 })
22
Step
Execute the desk command "FIXTURE 1 AT 50 TIME 0".
t.command.execute("FIXTURE 1 AT 50 TIME 0")
23
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
24
Expected
fixture(1) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(1), { Intensity: 128 })
25
Step
Execute the desk command "FIXTURE 1 AT 75 TIME 0".
t.command.execute("FIXTURE 1 AT 75 TIME 0")
26
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
27
Expected
fixture(1) DMX equals
{
   Intensity:  191
}
t.expectFixtureDMX(fixture(1), { Intensity: 191 })
28
Step
Execute the desk command "FIXTURE 1 AT 100 TIME 0".
t.command.execute("FIXTURE 1 AT 100 TIME 0")
29
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
30
Expected
fixture(1) DMX equals
{
   Intensity:  255
}
t.expectFixtureDMX(fixture(1), { Intensity: 255 })
31
Expected
Output packet: "artnet", 1, <generated: callback>.
t.expect.outputPacket("artnet", 1, (packet) =>
			expect(packet.slots[0]).toBe(255),
		)
32
Expected
<unresolved: packet.slots[0]> is 255.
expect(packet.slots[0]).toBe(255)
33
Expected
Output packet: "sacn", 101, <generated: callback>.
t.expect.outputPacket("sacn", 101, (packet) =>
			expect(packet.slots[0]).toBe(255),
		)
35
Expected
<unresolved: packet.slots[0]> is 255.
expect(packet.slots[0]).toBe(255)
36

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: packet.slots[0]> Expression packet.slots[0] is not statically resolved.33
unresolved-expressionExpected outcome<unresolved: packet.slots[0]> Expression packet.slots[0] is not statically resolved.36

DMX-002 — visible programming reaches a wire-correct ArtDMX packet

tests/49-semantic-network-output-protocols.spec.ts:41 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineSemantic oracleShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
45
Open the ToskLight browser application.
t.app.open()
46
The ToskLight browser application is ready.
t.app.expect.ready()
47

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 1 AT 25 TIME 0".
t.command.execute("FIXTURE 1 AT 25 TIME 0")
48
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
49
Expected
Output packet: "artnet", 1, <generated: callback>.
t.expect.outputPacket("artnet", 1, (packet) => {
			expect(packet.sequence).not.toBe(0);
			expect(packet.slots).toHaveLength(512);
			expect(packet.slots[0]).toBe(64);
			expect(packet.artnet).toMatchObject({
				id: "Art-Net\0",
				opcode: 0x5000,
				protocolVersion: 14,
				payloadLength: 512,
			});
		})
50
Expected
Not → to be: <unresolved: packet.sequence>, 0.
expect(packet.sequence).not.toBe(0)
51
Expected
To have length: <unresolved: packet.slots>, 512.
expect(packet.slots).toHaveLength(512)
52
Expected
<unresolved: packet.slots[0]> is 64.
expect(packet.slots[0]).toBe(64)
53
Expected
<unresolved: packet.artnet> matches { id: "Art-Net\u0000", opcode: 20480, protocolVersion: 14, payloadLength: 512 }.
expect(packet.artnet).toMatchObject({
				id: "Art-Net\0",
				opcode: 0x5000,
				protocolVersion: 14,
				payloadLength: 512,
			})
54

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: packet.sequence> Property access packet.sequence depends on a runtime value.51
unresolved-expressionExpected outcome<unresolved: packet.slots> Property access packet.slots depends on a runtime value.52
unresolved-expressionExpected outcome<unresolved: packet.slots[0]> Expression packet.slots[0] is not statically resolved.53
unresolved-expressionExpected outcome<unresolved: packet.artnet> Property access packet.artnet depends on a runtime value.54

DMX-003 — visible programming reaches a wire-correct E1.31 packet

tests/49-semantic-network-output-protocols.spec.ts:64 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineSemantic oracleShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
68
Open the ToskLight browser application.
t.app.open()
69
The ToskLight browser application is ready.
t.app.expect.ready()
70

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 1 AT 50 TIME 0".
t.command.execute("FIXTURE 1 AT 50 TIME 0")
71
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
72
Expected
Output packet: "sacn", 101, <generated: callback>.
t.expect.outputPacket("sacn", 101, (packet) => {
			expect(packet.sequence).not.toBe(0);
			expect(packet.priority).toBe(100);
			expect(packet.slots).toHaveLength(512);
			expect(packet.slots[0]).toBe(128);
			expect(packet.sacn).toMatchObject({
				preambleSize: 0x10,
				rootVector: 0x00000004,
				framingVector: 0x00000002,
				propertyValueCount: 513,
				startCode: 0,
			});
		})
73
Expected
Not → to be: <unresolved: packet.sequence>, 0.
expect(packet.sequence).not.toBe(0)
74
Expected
<unresolved: packet.priority> is 100.
expect(packet.priority).toBe(100)
75
Expected
To have length: <unresolved: packet.slots>, 512.
expect(packet.slots).toHaveLength(512)
76
Expected
<unresolved: packet.slots[0]> is 128.
expect(packet.slots[0]).toBe(128)
77
Expected
<unresolved: packet.sacn> matches { preambleSize: 16, rootVector: 4, framingVector: 2, propertyValueCount: 513, startCode: 0 }.
expect(packet.sacn).toMatchObject({
				preambleSize: 0x10,
				rootVector: 0x00000004,
				framingVector: 0x00000002,
				propertyValueCount: 513,
				startCode: 0,
			})
78

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: packet.sequence> Property access packet.sequence depends on a runtime value.74
unresolved-expressionExpected outcome<unresolved: packet.priority> Property access packet.priority depends on a runtime value.75
unresolved-expressionExpected outcome<unresolved: packet.slots> Property access packet.slots depends on a runtime value.76
unresolved-expressionExpected outcome<unresolved: packet.slots[0]> Expression packet.slots[0] is not statically resolved.77
unresolved-expressionExpected outcome<unresolved: packet.sacn> Property access packet.sacn depends on a runtime value.78

DMX-004 — remapped fan-out reaches every enabled destination and no disabled route

tests/49-semantic-network-output-protocols.spec.ts:89 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputOutput runtimeShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
93
Open the ToskLight browser application.
t.app.open()
94
The ToskLight browser application is ready.
t.app.expect.ready()
95

Scenario contract

KindScenario contractLine
Step
Output → network → add with "extra Art-Net",
{
   protocol:  "art_net",
   logicalUniverse:  1,
   destinationUniverse:  11,
   deliveryMode:  "unicast",
   capture:  true
}
t.output.network.add("extra Art-Net", {
			protocol: "art_net",
			logicalUniverse: 1,
			destinationUniverse: 11,
			deliveryMode: "unicast",
			capture: true,
		})
96
Step
Output → network → add with "disabled sACN",
{
   protocol:  "sacn",
   logicalUniverse:  1,
   destinationUniverse:  102,
   deliveryMode:  "unicast",
   enabled:  false,
   capture:  true
}
t.output.network.add("disabled sACN", {
			protocol: "sacn",
			logicalUniverse: 1,
			destinationUniverse: 102,
			deliveryMode: "unicast",
			enabled: false,
			capture: true,
		})
103
Step
Output → network → mark with "extra Art-Net".
t.output.network.mark("extra Art-Net")
111
Step
Output → network → mark with "disabled sACN".
t.output.network.mark("disabled sACN")
112
Step
Execute the desk command "FIXTURE 1 AT 25 TIME 0".
t.command.execute("FIXTURE 1 AT 25 TIME 0")
113
Step
Execute the desk command "FIXTURE 2 AT 50 TIME 0".
t.command.execute("FIXTURE 2 AT 50 TIME 0")
114
Step
Execute the desk command "FIXTURE 3 AT 75 TIME 0".
t.command.execute("FIXTURE 3 AT 75 TIME 0")
115
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
116
Expected
Output → network → expect packet: "extra Art-Net",
{
   slots:  {
     1:  64,
     2:  128,
     3:  191
  }
}
t.output.network.expectPacket("extra Art-Net", {
			slots: { 1: 64, 2: 128, 3: 191 },
		})
117
Expected
Output → network → expect no packet: "disabled sACN".
t.output.network.expectNoPacket("disabled sACN")
120
Expected
fixture(1) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixture(1), { Intensity: 64 })
121
Expected
fixture(2) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(2), { Intensity: 128 })
122
Expected
fixture(3) DMX equals
{
   Intensity:  191
}
t.expectFixtureDMX(fixture(3), { Intensity: 191 })
123

Diagnostics

None.

DMX-005 — a conflicting visible patch edit preserves both previous addresses atomically

tests/49-semantic-network-output-protocols.spec.ts:127 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UIShow PatchShow files
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
131
Open the ToskLight browser application.
t.app.open()
132
The ToskLight browser application is ready.
t.app.expect.ready()
133

Scenario contract

KindScenario contractLine
Step
Patch → prepare address conflict.
t.patch.prepareAddressConflict()
134
Step
Patch → ui → address with $conflict.candidate (from patch.prepareAddressConflict), "2.1".
t.patch.via.ui.address(conflict.candidate, "2.1")
135
Step
Patch → keep old address after conflict.
t.patch.keepOldAddressAfterConflict()
136
Expected
Patch → address: $conflict.anchor (from patch.prepareAddressConflict), "2.1".
t.patch.expect(conflict.anchor).address("2.1")
137
Expected
Patch → address: $conflict.candidate (from patch.prepareAddressConflict), "2.2".
t.patch.expect(conflict.candidate).address("2.2")
138

Diagnostics

None.

DMX-006 — visible programming encodes deterministic 16-bit coarse and fine bytes

tests/49-semantic-network-output-protocols.spec.ts:142 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICommand lineCue timingDMX outputOutput runtimeProgrammer timingShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
146
Open the ToskLight browser application.
t.app.open()
147
The ToskLight browser application is ready.
t.app.expect.ready()
148

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
149
Step
Output → network → install sixteen bit fixture.
t.output.network.installSixteenBitFixture()
150
Step
Execute the desk command "FIXTURE $fixtureNumber (result of output.network.installSixteenBitFixture) AT 50 TIME 0".
t.command.execute(`FIXTURE ${fixtureNumber} AT 50 TIME 0`)
151
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
152
Expected
fixture(fixtureNumber) DMX equals
{
   "Intensity coarse":  128,
   "Intensity fine":  0
}
t.expectFixtureDMX(fixture(fixtureNumber), {
			"Intensity coarse": 128,
			"Intensity fine": 0,
		})
153

Diagnostics

None.

DMX-007 — one route failure is isolated and recovery sends current state

tests/49-semantic-network-output-protocols.spec.ts:160 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineOutput runtimeSemantic oracleShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
164
Open the ToskLight browser application.
t.app.open()
165
The ToskLight browser application is ready.
t.app.expect.ready()
166

Scenario contract

KindScenario contractLine
Step
Output → network → add with "recovering Art-Net",
{
   protocol:  "art_net",
   logicalUniverse:  1,
   destinationUniverse:  11,
   deliveryMode:  "unicast",
   capture:  true
}
t.output.network.add("recovering Art-Net", {
			protocol: "art_net",
			logicalUniverse: 1,
			destinationUniverse: 11,
			deliveryMode: "unicast",
			capture: true,
		})
167
Step
Output → network → failure with "recovering Art-Net", true.
t.output.network.failure("recovering Art-Net", true)
174
Step
Output → network → mark with "recovering Art-Net".
t.output.network.mark("recovering Art-Net")
175
Step
Execute the desk command "FIXTURE 1 AT 25 TIME 0".
t.command.execute("FIXTURE 1 AT 25 TIME 0")
176
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
177
Expected
Output → network → expect no packet: "recovering Art-Net".
t.output.network.expectNoPacket("recovering Art-Net")
178
Expected
Output packet: "artnet", 1, <generated: callback>.
t.expect.outputPacket("artnet", 1, (packet) =>
			expect(packet.slots[0]).toBe(64),
		)
179
Expected
<unresolved: packet.slots[0]> is 64.
expect(packet.slots[0]).toBe(64)
180
Step
Output → network → failure with "recovering Art-Net", false.
t.output.network.failure("recovering Art-Net", false)
182
Step
Output → network → mark with "recovering Art-Net".
t.output.network.mark("recovering Art-Net")
183
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
184
Expected
Output → network → expect packet: "recovering Art-Net",
{
   slots:  {
     1:  64
  },
   sequenceNonZero:  true
}
t.output.network.expectPacket("recovering Art-Net", {
			slots: { 1: 64 },
			sequenceNonZero: true,
		})
185

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: packet.slots[0]> Expression packet.slots[0] is not statically resolved.180

DMX-009 — protocol-correct delivery modes persist and resolve to actual destinations

tests/49-semantic-network-output-protocols.spec.ts:192 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineOutput runtimeShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
196
Open the ToskLight browser application.
t.app.open()
197
The ToskLight browser application is ready.
t.app.expect.ready()
198

Scenario contract

KindScenario contractLine
Step
Output → network → add with "Art-Net broadcast",
{
   protocol:  "art_net",
   logicalUniverse:  1,
   destinationUniverse:  201,
   deliveryMode:  "broadcast"
}
t.output.network.add("Art-Net broadcast", {
			protocol: "art_net",
			logicalUniverse: 1,
			destinationUniverse: 201,
			deliveryMode: "broadcast",
		})
199
Step
Output → network → add with "Art-Net unicast",
{
   protocol:  "art_net",
   logicalUniverse:  1,
   destinationUniverse:  202,
   deliveryMode:  "unicast",
   capture:  true
}
t.output.network.add("Art-Net unicast", {
			protocol: "art_net",
			logicalUniverse: 1,
			destinationUniverse: 202,
			deliveryMode: "unicast",
			capture: true,
		})
205
Step
Output → network → add with "sACN multicast",
{
   protocol:  "sacn",
   logicalUniverse:  1,
   destinationUniverse:  301,
   deliveryMode:  "multicast"
}
t.output.network.add("sACN multicast", {
			protocol: "sacn",
			logicalUniverse: 1,
			destinationUniverse: 301,
			deliveryMode: "multicast",
		})
212
Step
Output → network → add with "sACN unicast",
{
   protocol:  "sacn",
   logicalUniverse:  1,
   destinationUniverse:  302,
   deliveryMode:  "unicast",
   capture:  true
}
t.output.network.add("sACN unicast", {
			protocol: "sacn",
			logicalUniverse: 1,
			destinationUniverse: 302,
			deliveryMode: "unicast",
			capture: true,
		})
218
Step
Output → network → mark with "Art-Net unicast".
t.output.network.mark("Art-Net unicast")
225
Step
Output → network → mark with "sACN unicast".
t.output.network.mark("sACN unicast")
226
Step
Execute the desk command "FIXTURE 1 AT 50 TIME 0".
t.command.execute("FIXTURE 1 AT 50 TIME 0")
227
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
228
Expected
Output → network → expect stored: "Art-Net broadcast",
{
   delivery_mode:  "broadcast",
   destination:  null
}
t.output.network.expectStored("Art-Net broadcast", {
			delivery_mode: "broadcast",
			destination: null,
		})
229
Expected
Output → network → expect stored: "sACN multicast",
{
   delivery_mode:  "multicast",
   destination:  null
}
t.output.network.expectStored("sACN multicast", {
			delivery_mode: "multicast",
			destination: null,
		})
233
Expected
Output → network → expect diagnostic: "Art-Net broadcast",
{
   delivery_mode:  "broadcast",
   destination:  "255.255.255.255:6454",
   enabled:  true
}
t.output.network.expectDiagnostic("Art-Net broadcast", {
			delivery_mode: "broadcast",
			destination: "255.255.255.255:6454",
			enabled: true,
		})
237
Expected
Output → network → expect diagnostic: "sACN multicast",
{
   delivery_mode:  "multicast",
   destination:  "239.255.1.45:5568",
   enabled:  true
}
t.output.network.expectDiagnostic("sACN multicast", {
			delivery_mode: "multicast",
			destination: "239.255.1.45:5568",
			enabled: true,
		})
242
Expected
Output → network → expect same payload: "Art-Net unicast", "sACN unicast".
t.output.network.expectSamePayload("Art-Net unicast", "sACN unicast")
247

Diagnostics

None.

CUE-011 — Cuelist View edits preserve Cue identity, runtime selection, and persisted values

tests/50-semantic-cue-editing.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue runtimeCue timingCuesEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
14
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
15
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
17
Step
Encoder → intensity → dimmer → api → set with 25.
t.encoder.intensity.dimmer.via.api.set(25)
18
Step
Record → playback with 1.
t.record.playback(1)
19
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
20
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
21
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
22
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
23
Step
Encoder → intensity → dimmer → api → set with 75.
t.encoder.intensity.dimmer.via.api.set(75)
24
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  3
}
t.record.cue({ playback, cue: 3 })
25
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
26
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "CUE-011 Sequence",
   buttons:  [
    PlaybackButton.GoBack,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(playback, {
			name: "CUE-011 Sequence",
			buttons: [PlaybackButton.GoBack, PlaybackButton.Go, PlaybackButton.Off],
		})
27
Step
Playback → api → go with $playback (result of record.playback).
t.playback.via.api.go(playback)
31
Expected
Playback → runtime: $playback (result of record.playback),
{
   current_cue_number:  "1"
}
t.playback.expect(playback).runtime({ current_cue_number: "1" })
32
Step
Cue → open editor with $playback (result of record.playback).
t.cue.openEditor(playback)
34
Expected
Cue editor → structure.
editor.expect.structure()
35
Step
Cue editor → select with 2.
editor.select(2)
36
Step
Cue editor → edit with 2,
{
   fade:  "2.5",
   delay:  "1.25",
   trigger:  "TIME",
   triggerTime:  "4"
}
editor.edit(2, {
			fade: "2.5",
			delay: "1.25",
			trigger: "TIME",
			triggerTime: "4",
		})
37
Expected
Cue → metadata: $playback (result of record.playback), 2,
{
   fade_millis:  2500,
   delay_millis:  1250
}
t.cue.expect(playback, 2).metadata({
			fade_millis: 2_500,
			delay_millis: 1_250,
		})
43
Expected
Cue → trigger: $playback (result of record.playback), 2,
{
   type:  "wait",
   delay_millis:  4000
}
t.cue
			.expect(playback, 2)
			.trigger({ type: "wait", delay_millis: 4_000 })
47
Step
Cue editor → select with 3.
editor.select(3)
51
Step
Cue editor → select with 2.
editor.select(2)
52
Expected
Cue editor → selected: 2,
{
   fade:  "2.5",
   delay:  "1.25",
   triggerTime:  "4"
}
editor.expect.selected(2, {
			fade: "2.5",
			delay: "1.25",
			triggerTime: "4",
		})
53
Step
Cue editor → inspect settings.
editor.inspectSettings()
58
Expected
Cue editor → selected: 2.
editor.expect.selected(2)
59
Expected
Playback → runtime: $playback (result of record.playback),
{
   current_cue_number:  "1"
}
t.playback.expect(playback).runtime({ current_cue_number: "1" })
60
Step
Cue editor → reject with 2,
{
   fade:  "-1"
}
editor.reject(2, { fade: "-1" })
62
Expected
Cue → metadata: $playback (result of record.playback), 2,
{
   fade_millis:  2500,
   delay_millis:  1250
}
t.cue.expect(playback, 2).metadata({
			fade_millis: 2_500,
			delay_millis: 1_250,
		})
63
Expected
Playback → runtime: $playback (result of record.playback),
{
   current_cue_number:  "1"
}
t.playback.expect(playback).runtime({ current_cue_number: "1" })
67
Step
Cue → reopen editor with $playback (result of record.playback).
t.cue.reopenEditor(playback)
69
Step
Cue editor → select with 2.
editor.select(2)
70
Expected
Cue editor → selected: 2,
{
   fade:  "2.5",
   delay:  "1.25",
   triggerTime:  "4"
}
editor.expect.selected(2, {
			fade: "2.5",
			delay: "1.25",
			triggerTime: "4",
		})
71

Diagnostics

None.

FILE-002 — File Manager provides the three-column browsing workflow and text editor

tests/50-semantic-files-and-text-editor.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIDesktop layoutFile ManagerShow filesText Editor
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: File Manager editing
t.desktop.configure("File Manager editing")
14
Step
Add the PaneType.FileManager pane
desktop.addPane(PaneType.FileManager, {
			slug: "files",
			column: 1,
			row: 1,
			width: 24,
			height: 18,
		})
15
Step
Apply the configured Desktop layout.
desktop.apply()
22
Expected
Files → expect manager edits text.
t.files.expectManagerEditsText()
23

Diagnostics

None.

TEXT-001 — dedicated Text Editor persists its file association and reports dirty state

tests/50-semantic-files-and-text-editor.spec.ts:32 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIDesktop layoutFile ManagerShow filesText Editor
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
36
Open the ToskLight browser application.
t.app.open()
37
The ToskLight browser application is ready.
t.app.expect.ready()
38

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Text Editor saving
t.desktop.configure("Text Editor saving")
39
Step
Add the PaneType.TextEditor pane
desktop.addPane(PaneType.TextEditor, {
			slug: "editor",
			column: 1,
			row: 1,
			width: 24,
			height: 18,
		})
40
Step
Apply the configured Desktop layout.
desktop.apply()
47
Expected
Files → expect editor dirty save.
t.files.expectEditorDirtySave()
48

Diagnostics

None.

TEXT-015 — Text Editors synchronize, surface conflicts, recover files, and retain configured views

tests/50-semantic-files-and-text-editor.spec.ts:52 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIDesktop layoutFile ManagerShow filesText Editor
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
56
Open the ToskLight browser application.
t.app.open()
57
The ToskLight browser application is ready.
t.app.expect.ready()
58

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Text Editor collaboration
t.desktop.configure("Text Editor collaboration")
59
Step
Add the PaneType.TextEditor pane
desktop.addPane(PaneType.TextEditor, {
			slug: "first-editor",
			column: 1,
			row: 1,
			width: 12,
			height: 18,
		})
60
Step
Add the PaneType.TextEditor pane
desktop.addPane(PaneType.TextEditor, {
			slug: "second-editor",
			column: 13,
			row: 1,
			width: 12,
			height: 18,
		})
67
Step
Apply the configured Desktop layout.
desktop.apply()
74
Expected
Files → expect two editor lifecycle.
t.files.expectTwoEditorLifecycle()
75
Expected
Files → expect editor modes.
t.files.expectEditorModes()
76

Diagnostics

None.

FILE-016 — File Manager operations, launchers, hosted picking, and system fallback stay confined

tests/50-semantic-files-and-text-editor.spec.ts:80 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIDesktop layoutFile ManagerShow filesText Editor
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
84
Open the ToskLight browser application.
t.app.open()
85
The ToskLight browser application is ready.
t.app.expect.ready()
86

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: File Manager workflows
t.desktop.configure("File Manager workflows")
87
Step
Add the PaneType.FileManager pane
desktop.addPane(PaneType.FileManager, {
			slug: "files",
			column: 1,
			row: 1,
			width: 24,
			height: 18,
		})
88
Step
Apply the configured Desktop layout.
desktop.apply()
95
Expected
Files → expect manager operations.
t.files.expectManagerOperations()
96
Expected
Files → expect setup launchers.
t.files.expectSetupLaunchers()
97
Expected
Files → expect hosted picker.
t.files.expectHostedPicker()
98
Expected
Files → expect system picker fallback.
t.files.expectSystemPickerFallback()
99

Diagnostics

None.

CUE-012 — Cuelist Settings persist Sequence and Chaser runtime policy

tests/51-semantic-cuelist-settings.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue runtimeCuelist SettingsCuesEncoder controlsPlaybacksProgrammerRecordingSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
15
Step
Encoder → intensity → dimmer → api → set with 25.
t.encoder.intensity.dimmer.via.api.set(25)
16
Step
Record → playback with 1.
t.record.playback(1)
17
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
18
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
19
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
20
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
21
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "CUE-012 Settings",
   buttons:  [
    PlaybackButton.GoBack,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(playback, {
			name: "CUE-012 Settings",
			buttons: [PlaybackButton.GoBack, PlaybackButton.Go, PlaybackButton.Off],
		})
22
Step
Cue → open editor with $playback (result of record.playback).
t.cue.openEditor(playback)
27
Step
Cue editor → open settings.
editor.openSettings()
28
Expected
Cue list settings → expect defaults.
settings.expectDefaults()
29
Step
Cue list settings → configure with
{
   mode:  "Chaser",
   priority:  42,
   intensityPriority:  "LTP",
   wrap:  "Reset",
   restart:  "Continue Current Cue",
   forceCueTiming:  true,
   disableCueTiming:  true,
   speedMultiplier:  2,
   chaserXfade:  50
}
settings.configure({
			mode: "Chaser",
			priority: 42,
			intensityPriority: "LTP",
			wrap: "Reset",
			restart: "Continue Current Cue",
			forceCueTiming: true,
			disableCueTiming: true,
			speedMultiplier: 2,
			chaserXfade: 50,
		})
30
Step
Cue list settings → save.
settings.save()
41
Expected
Cue → expect list → configuration: $playback (result of record.playback),
{
   mode:  "chaser",
   priority:  42,
   intensity_priority_mode:  "ltp",
   wrap_mode:  "reset",
   restart_mode:  "continue_current_cue",
   force_cue_timing:  true,
   disable_cue_timing:  true,
   speed_group:  "A",
   speed_multiplier:  2,
   chaser_xfade_percent:  50
}
t.cue.expectList(playback).configuration({
			mode: "chaser",
			priority: 42,
			intensity_priority_mode: "ltp",
			wrap_mode: "reset",
			restart_mode: "continue_current_cue",
			force_cue_timing: true,
			disable_cue_timing: true,
			speed_group: "A",
			speed_multiplier: 2,
			chaser_xfade_percent: 50,
		})
43

Diagnostics

None.

CUE-013 — deleting the active Cue holds output and anchors GO around the surviving Cues

tests/52-semantic-cue-deletion.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue runtimeCue timingDMX outputEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
15
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
16
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
18
Step
Encoder → intensity → dimmer → api → set with 25.
t.encoder.intensity.dimmer.via.api.set(25)
19
Step
Record → playback with 1.
t.record.playback(1)
20
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
21
Step
Encoder → intensity → dimmer → api → set with 50.
t.encoder.intensity.dimmer.via.api.set(50)
22
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
23
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
24
Step
Encoder → intensity → dimmer → api → set with 75.
t.encoder.intensity.dimmer.via.api.set(75)
25
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  3
}
t.record.cue({ playback, cue: 3 })
26
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
27
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Delete Active Sequence",
   buttons:  [
    PlaybackButton.GoBack,
     PlaybackButton.Go,
     PlaybackButton.Off
  ]
}
t.playback.configure(playback, {
			name: "Delete Active Sequence",
			buttons: [PlaybackButton.GoBack, PlaybackButton.Go, PlaybackButton.Off],
		})
28
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
33
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
34
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
35
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
36
Expected
fixture(1) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(1), { Intensity: 128 })
37
Step
Cue → delete with $playback (result of record.playback), 2.
t.cue.delete(playback, 2)
39
Expected
Cue → absent: $playback (result of record.playback), 2.
t.cue.expect(playback, 2).absent()
40
Expected
Playback → runtime: $playback (result of record.playback),
{
   current_cue_number:  "2",
   deleted_cue_hold:  {
     deleted_number:  "2",
     previous_number:  "1",
     next_number:  "3"
  }
}
t.playback.expect(playback).runtime({
			current_cue_number: "2",
			deleted_cue_hold: {
				deleted_number: "2",
				previous_number: "1",
				next_number: "3",
			},
		})
41
Expected
fixture(1) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(1), { Intensity: 128 })
49
Step
Playback → go with $playback (result of record.playback).
t.playback.go(playback)
51
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
52
Expected
Playback → runtime: $playback (result of record.playback),
{
   current_cue_number:  "3"
}
t.playback.expect(playback).runtime({ current_cue_number: "3" })
53
Expected
fixture(1) DMX equals
{
   Intensity:  191
}
t.expectFixtureDMX(fixture(1), { Intensity: 191 })
54
Step
Playback → go back with $playback (result of record.playback).
t.playback.goBack(playback)
56
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
57
Expected
Playback → runtime: $playback (result of record.playback),
{
   current_cue_number:  "1"
}
t.playback.expect(playback).runtime({ current_cue_number: "1" })
58
Expected
fixture(1) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixture(1), { Intensity: 64 })
59

Diagnostics

None.

PRELOAD-001 — programmer-only Preload stays blind, commits, and releases

tests/53-semantic-programmer-preload.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue timingDMX outputPreloadProgrammer timingShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
14
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
16
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
17
Step
Start blind Preload programming.
t.preload.start()
19
Expected
Preload → active.
t.preload.expect.active()
20
Step
Preload → set fixture value with
{
   fixture:  1,
   attribute:  "intensity",
   value:  {
     kind:  "normalized",
     value:  0.5
  }
}
t.preload.setFixtureValue({
			fixture: 1,
			attribute: "intensity",
			value: { kind: "normalized", value: 0.5 },
		})
21
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
26
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
27
Step
Preload → api → commit.
t.preload.via.api.commit()
29
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
30
Expected
fixture(1) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(1), { Intensity: 128 })
31
Step
Release blind Preload programming.
t.preload.release()
33
Expected
Preload → inactive.
t.preload.expect.inactive()
34
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
35
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
36

Diagnostics

None.

PRELOAD-002 — physical Playback Preload preserves all seven ordered action verbs

tests/54-semantic-physical-playback-preload.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICue timingEncoder controlsPlaybacksPreloadProgrammerProgrammer timingRecordingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
14
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
15
Step
Clear the current selection.
t.selection.clear()
22
Step
Selection → fixtures → api → item with fixture = 1.
t.selection.fixtures.via.api.item(fixture)
23
Step
Encoder → intensity → dimmer → api → set with 30.
t.encoder.intensity.dimmer.via.api.set(30)
24
Step
Record → playback with slot = 1.
t.record.playback(slot)
25
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
26
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
27
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
28
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
29
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Physical button = PlaybackButton.Toggle",
   buttons:  [
    button = PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Physical ${button}`,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
30
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
34
Step
Clear the current selection.
t.selection.clear()
22
Step
Selection → fixtures → api → item with fixture = 2.
t.selection.fixtures.via.api.item(fixture)
23
Step
Encoder → intensity → dimmer → api → set with 30.
t.encoder.intensity.dimmer.via.api.set(30)
24
Step
Record → playback with slot = 2.
t.record.playback(slot)
25
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
26
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
27
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
28
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
29
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Physical button = PlaybackButton.Go",
   buttons:  [
    button = PlaybackButton.Go,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Physical ${button}`,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
30
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
34
Step
Clear the current selection.
t.selection.clear()
22
Step
Selection → fixtures → api → item with fixture = 3.
t.selection.fixtures.via.api.item(fixture)
23
Step
Encoder → intensity → dimmer → api → set with 30.
t.encoder.intensity.dimmer.via.api.set(30)
24
Step
Record → playback with slot = 3.
t.record.playback(slot)
25
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
26
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
27
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
28
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
29
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Physical button = PlaybackButton.GoBack",
   buttons:  [
    button = PlaybackButton.GoBack,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Physical ${button}`,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
30
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
34
Step
Clear the current selection.
t.selection.clear()
22
Step
Selection → fixtures → api → item with fixture = 4.
t.selection.fixtures.via.api.item(fixture)
23
Step
Encoder → intensity → dimmer → api → set with 30.
t.encoder.intensity.dimmer.via.api.set(30)
24
Step
Record → playback with slot = 4.
t.record.playback(slot)
25
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
26
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
27
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
28
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
29
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Physical button = PlaybackButton.Off",
   buttons:  [
    button = PlaybackButton.Off,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Physical ${button}`,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
30
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
34
Step
Clear the current selection.
t.selection.clear()
22
Step
Selection → fixtures → api → item with fixture = 5.
t.selection.fixtures.via.api.item(fixture)
23
Step
Encoder → intensity → dimmer → api → set with 30.
t.encoder.intensity.dimmer.via.api.set(30)
24
Step
Record → playback with slot = 5.
t.record.playback(slot)
25
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
26
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
27
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
28
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
29
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Physical button = PlaybackButton.On",
   buttons:  [
    button = PlaybackButton.On,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Physical ${button}`,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
30
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
34
Step
Clear the current selection.
t.selection.clear()
22
Step
Selection → fixtures → api → item with fixture = 6.
t.selection.fixtures.via.api.item(fixture)
23
Step
Encoder → intensity → dimmer → api → set with 30.
t.encoder.intensity.dimmer.via.api.set(30)
24
Step
Record → playback with slot = 6.
t.record.playback(slot)
25
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
26
Step
Encoder → intensity → dimmer → api → set with 70.
t.encoder.intensity.dimmer.via.api.set(70)
27
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
28
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
29
Step
Playback → configure with $playback (result of record.playback),
{
   name:  "Physical button = PlaybackButton.Temp",
   buttons:  [
    button = PlaybackButton.Temp,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name: `Physical ${button}`,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
30
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
34
Step
Playback → api → go with $backPlayback (result of recordPlayback).
t.playback.via.api.go(backPlayback)
45
Step
Playback → api → go with $backPlayback (result of recordPlayback).
t.playback.via.api.go(backPlayback)
46
Step
Playback → api → go with $offPlayback (result of recordPlayback).
t.playback.via.api.go(offPlayback)
47
Step
Preload → configure with
{
   programmer:  false,
   playbackScope:  {
     position_ranges:  [
      {
         start:  1,
         end:  6
      }
    ],
     pages:  null
  },
   programmerFade:  2000,
   cueFade:  0
}
t.preload.configure({
			programmer: false,
			playbackScope: {
				position_ranges: [{ start: 1, end: 6 }],
				pages: null,
			},
			programmerFade: 2_000,
			cueFade: 0,
		})
48
Step
Playback → open.
t.playback.open()
57
Step
Start blind Preload programming.
t.preload.start()
58
Step
Playback → toggle with $togglePlayback (result of recordPlayback).
t.playback.toggle(togglePlayback)
60
Step
Playback → go with $goPlayback (result of recordPlayback).
t.playback.go(goPlayback)
61
Step
Playback → go back with $backPlayback (result of recordPlayback).
t.playback.goBack(backPlayback)
62
Step
Playback → off with $offPlayback (result of recordPlayback).
t.playback.off(offPlayback)
63
Step
Playback → on with $onPlayback (result of recordPlayback).
t.playback.on(onPlayback)
64
Step
Playback → ui → temp with $tempPlayback (result of recordPlayback).
t.playback.via.ui.temp(tempPlayback)
65
Step
Playback → ui → temp with $tempPlayback (result of recordPlayback).
t.playback.via.ui.temp(tempPlayback)
66
Expected
Preload → pending playback actions:
[
  "toggle",
   "go",
   "go-minus",
   "off",
   "on",
   "temp-on",
   "temp-off"
]
t.preload.expect.pendingPlaybackActions([
			"toggle",
			"go",
			"go-minus",
			"off",
			"on",
			"temp-on",
			"temp-off",
		])
67
Step
Preload → commit.
t.preload.commit()
77
Step
Advance the test clock by "2s".
t.clock.advanceBy("2s")
78
Expected
Playback → runtime: $togglePlayback (result of recordPlayback),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(togglePlayback).runtime({
			enabled: true,
			current_cue_number: "1",
		})
79
Expected
Playback → runtime: $goPlayback (result of recordPlayback),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(goPlayback).runtime({
			enabled: true,
			current_cue_number: "1",
		})
83
Expected
Playback → runtime: $backPlayback (result of recordPlayback),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(backPlayback).runtime({
			enabled: true,
			current_cue_number: "1",
		})
87
Expected
Playback → runtime: $onPlayback (result of recordPlayback),
{
   enabled:  true
}
t.playback.expect(onPlayback).runtime({ enabled: true })
91
Step
Release blind Preload programming.
t.preload.release()
93
Expected
Playback → runtime: $togglePlayback (result of recordPlayback),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(togglePlayback).runtime({
			enabled: true,
			current_cue_number: "1",
		})
94
Expected
Playback → runtime: $onPlayback (result of recordPlayback),
{
   enabled:  true
}
t.playback.expect(onPlayback).runtime({ enabled: true })
98

Diagnostics

None.

OSC-001 — page changes produce one complete feedback cycle without periodic mutation

tests/55-semantic-osc-api-and-cross-surface.spec.ts:12 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateOSCPlayback pagesShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
16
Open the ToskLight browser application.
t.app.open()
17
The ToskLight browser application is ready.
t.app.expect.ready()
18

Scenario contract

KindScenario contractLine
Step
Page → create with 2.
t.page.create(2)
19
Step
Page → rename with 2, "Page 2".
t.page.rename(2, "Page 2")
20
Expected
Cross surface → expect complete feedback for page: "Page 2".
t.crossSurface.expectCompleteFeedbackForPage("Page 2")
22
Expected
Page → selected: 2.
t.page.expect(2).selected()
23

Diagnostics

None.

OSC-002 — hardware-equivalent command reaches shared programmer and output

tests/55-semantic-osc-api-and-cross-surface.spec.ts:27 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateDMX outputOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
31
Open the ToskLight browser application.
t.app.open()
32
The ToskLight browser application is ready.
t.app.expect.ready()
33

Scenario contract

KindScenario contractLine
Step
Cross surface → execute osc group command and verify output.
t.crossSurface.executeOscGroupCommandAndVerifyOutput()
35
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  64
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 64 })
36

Diagnostics

None.

OSC-003 — two OSC surfaces share the desk's command line and unsubscribe is reference-counted

tests/55-semantic-osc-api-and-cross-surface.spec.ts:40 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
44
Open the ToskLight browser application.
t.app.open()
45
The ToskLight browser application is ready.
t.app.expect.ready()
46

Scenario contract

KindScenario contractLine
Expected
Cross surface → expect subscribers share the desk command line.
t.crossSurface.expectSubscribersShareTheDeskCommandLine()
48

Diagnostics

None.

OSC-004 — invalid input is rejected without programmer or output mutation

tests/55-semantic-osc-api-and-cross-surface.spec.ts:52 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
56
Open the ToskLight browser application.
t.app.open()
57
The ToskLight browser application is ready.
t.app.expect.ready()
58

Scenario contract

KindScenario contractLine
Step
Cross surface → reject invalid group command.
t.crossSurface.rejectInvalidGroupCommand()
60
Expected
Invalid visible input leaves Programmer and rendered output state unchanged.
t.crossSurface.rejectInvalidGroupCommand()
60

Diagnostics

None.

OSC-005 — one command line is built from several surfaces and completed once

tests/55-semantic-osc-api-and-cross-surface.spec.ts:64 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
68
Open the ToskLight browser application.
t.app.open()
69
The ToskLight browser application is ready.
t.app.expect.ready()
70

Scenario contract

KindScenario contractLine
Step
Cross surface → complete one shared value from several surfaces.
t.crossSurface.completeOneSharedValueFromSeveralSurfaces()
72
Expected
One command line is built from several surfaces of the desk and completed once, writing one value into the desk's one Programmer.
t.crossSurface.completeOneSharedValueFromSeveralSurfaces()
72

Diagnostics

None.

OSC-006 — exact OSC addresses retain targets with shared page feedback and independent pickup

tests/55-semantic-osc-api-and-cross-surface.spec.ts:76 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateCue timingEncoder controlsOSCPlayback pagesPlaybacksProgrammerProgrammer timingRecordingSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
80
Open the ToskLight browser application.
t.app.open()
81
The ToskLight browser application is ready.
t.app.expect.ready()
82

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
83
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
85
Step
Encoder → intensity → dimmer → api → set with 25.
t.encoder.intensity.dimmer.via.api.set(25)
86
Step
Record → playback with 1.
t.record.playback(1)
87
Step
Playback → api → off with $first (result of record.playback).
t.playback.via.api.off(first)
88
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
89
Step
Selection → fixtures → api → item with 2.
t.selection.fixtures.via.api.item(2)
90
Step
Encoder → intensity → dimmer → api → set with 75.
t.encoder.intensity.dimmer.via.api.set(75)
91
Step
Record → playback with 2.
t.record.playback(2)
92
Step
Playback → api → off with $second (result of record.playback).
t.playback.via.api.off(second)
93
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
94
Step
Playback → configure with $first (result of record.playback),
{
   buttons:  [
    PlaybackButton.Go,
     PlaybackButton.GoBack,
     PlaybackButton.Flash
  ]
}
t.playback.configure(first, {
			buttons: [PlaybackButton.Go, PlaybackButton.GoBack, PlaybackButton.Flash],
		})
95
Step
Playback → configure with $second (result of record.playback),
{
   buttons:  [
    PlaybackButton.Go,
     PlaybackButton.GoBack,
     PlaybackButton.Flash
  ]
}
t.playback.configure(second, {
			buttons: [PlaybackButton.Go, PlaybackButton.GoBack, PlaybackButton.Flash],
		})
98
Step
Page → create with 2.
t.page.create(2)
101
Step
Page → rename with 2, "Page 2".
t.page.rename(2, "Page 2")
102
Step
Page → map with
{
   sourceAddress:  $second (result of record.playback),
   targetAddress:  {
     page:  2,
     position:  1
  }
}
t.page.map({
			sourceAddress: second,
			targetAddress: { page: 2, position: 1 },
		})
103
Step
Cross surface → verify explicit page osc addressing and pickup.
t.crossSurface.verifyExplicitPageOscAddressingAndPickup()
108
Expected
Playback → runtime:
{
   page:  2,
   position:  1
}
{
   enabled:  true
}
t.playback.expect({ page: 2, position: 1 }).runtime({ enabled: true })
109
Expected
Playback → runtime: $second (result of record.playback),
{
   enabled:  true
}
t.playback.expect(second).runtime({ enabled: true })
111

Diagnostics

None.

CROSS-003 — relative software, API, and OSC encoder changes bypass Programmer Fade

tests/55-semantic-osc-api-and-cross-surface.spec.ts:115 · migrated-semantic-world · last run: not merged

show: Twelve DimmersAttached hardwareBrowser UICue timingDMX outputEncoder controlsOSCProgrammerProgrammer timingSelectionSemantic oracleShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
119
Open the ToskLight browser application.
t.app.open()
120
The ToskLight browser application is ready.
t.app.expect.ready()
121

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "5s".
t.timing.programmerFade.via.api.set("5s")
122
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
124
Step
Encoder → intensity → dimmer → ui → set with 0.
t.encoder.intensity.dimmer.via.ui.set(0)
125
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
126
Expected
<unresolved: beforeDrag.universes.find((item) => item.universe === 1)?.slots[0]> is 0.
expect(
			beforeDrag.universes.find((item) => item.universe === 1)?.slots[0],
		).toBe(0)
127
Step
Encoder → intensity → dimmer → ui → drag with "add", "slow".
t.encoder.intensity.dimmer.via.ui.drag("add", "slow")
130
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
132
Expected
$firstFrame.now (from clock.advanceStep) is $beforeDrag.now (from clock.advanceStep).
expect(firstFrame.now).toBe(beforeDrag.now)
136
Expected
<unresolved: firstFrame.universes.find((item) => item.universe === 1)?.slots[0]> is <unresolved: Math.round(target * 255)>.
expect(
			firstFrame.universes.find((item) => item.universe === 1)?.slots[0],
		).toBe(Math.round(target * 255))
137
Step
Encoder → intensity → dimmer → ui → set with 0.
t.encoder.intensity.dimmer.via.ui.set(0)
140
Step
Encoder → intensity → dimmer → ui → add with 10.
t.encoder.intensity.dimmer.via.ui.add(10)
141
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
142
Expected
fixture(1) DMX equals
{
   Intensity:  26
}
t.expectFixtureDMX(fixture(1), { Intensity: 26 })
143
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
145
Step
Encoder → intensity → dimmer → osc → add with 1.
t.encoder.intensity.dimmer.via.osc.add(1)
147
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
148
Expected
fixture(1) DMX equals
{
   Intensity:  28
}
t.expectFixtureDMX(fixture(1), { Intensity: 28 })
149
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
151
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
154
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
155
Step
Selection → fixtures → api → item with 2.
t.selection.fixtures.via.api.item(2)
156
Step
Encoder → intensity → dimmer → api → set with 80.
t.encoder.intensity.dimmer.via.api.set(80)
157
Step
Selection → fixtures → api → items with 1, 2.
t.selection.fixtures.via.api.items(1, 2)
158
Step
Encoder → intensity → dimmer → api → add with 10.
t.encoder.intensity.dimmer.via.api.add(10)
159
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
160
Expected
fixture(1) DMX equals
{
   Intensity:  77
}
t.expectFixtureDMX(fixture(1), { Intensity: 77 })
161
Expected
fixture(2) DMX equals
{
   Intensity:  230
}
t.expectFixtureDMX(fixture(2), { Intensity: 230 })
162

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: beforeDrag.universes.find((item) => item.universe === 1)?.slots[0]> Expression beforeDrag.universes.find((item) => item.universe === 1)?.slots[0] is not statically resolved.128
unresolved-expressionExpected outcome<unresolved: firstFrame.universes.find((item) => item.universe === 1)?.slots[0]> Expression firstFrame.universes.find((item) => item.universe === 1)?.slots[0] is not statically resolved.138
unresolved-expressionExpected outcome<unresolved: Math.round(target * 255)> Call expression Math.round(target * 255) is dynamic and was not executed.139

API-001 — authenticated revisioned membership updates preserve one atomic visible Group result

tests/55-semantic-osc-api-and-cross-surface.spec.ts:166 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UIGroupsSelectionSemantic oracleShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
170
Open the ToskLight browser application.
t.app.open()
171
The ToskLight browser application is ready.
t.app.expect.ready()
172

Scenario contract

KindScenario contractLine
Step
Group → snapshot with 3.
t.group.snapshot(3)
174
Expected
Not → to be null: $before (result of group.snapshot).
expect(before).not.toBeNull()
175
Expected
Group → expect api authentication rejected: 3, $before.revision (from group.snapshot).
t.group.expectApiAuthenticationRejected(3, before.revision)
177
Step
Selection → fixtures → api → item with 5.
t.selection.fixtures.via.api.item(5)
178
Step
Group → record via api with 3, StoreMode.Merge, $before.revision (from group.snapshot), "api-001-merge".
t.group.recordViaApi(
			3,
			StoreMode.Merge,
			before.revision,
			"api-001-merge",
		)
179
Expected
$changed (result of group.recordViaApi) matches
{
   status:  "changed",
   replayed:  false,
   group:  {
     state:  "stored",
     id:  "3",
     revision:  <unresolved: before.revision + 1>
  }
}
expect(changed).toMatchObject({
			status: "changed",
			replayed: false,
			group: { state: "stored", id: "3", revision: before.revision + 1 },
		})
185
Step
Group → snapshot with 3.
t.group.snapshot(3)
190
Expected
Group → expect stale api record rejected: 3, StoreMode.Merge, $before.revision (from group.snapshot), <unresolved: before.revision + 1>.
t.group.expectStaleApiRecordRejected(
			3,
			StoreMode.Merge,
			before.revision,
			before.revision + 1,
		)
191
Expected
<unresolved: await t.group.snapshot(3)> equals $afterChanged (result of group.snapshot).
expect(await t.group.snapshot(3)).toEqual(afterChanged)
197
Expected
Group → fixtures: 3, 1, 2, 3, 4, 5.
t.group.expect(3).fixtures(1, 2, 3, 4, 5)
198
Step
Group → snapshot with 3.
t.group.snapshot(3)
199
Expected
$after?.revision (from group.snapshot) is <unresolved: before.revision + 1>.
expect(after?.revision).toBe(before.revision + 1)
200

Diagnostics

DiagnosticWhereDetailLine
static-control-flowSourceThe if/else !before has conditional execution; branches are documented separately and no branch is assumed.176
unresolved-expressionExpected outcome<unresolved: before.revision + 1> Expression before.revision + 1 is not statically resolved.188
unresolved-expressionExpected outcome<unresolved: before.revision + 1> Expression before.revision + 1 is not statically resolved.195
unresolved-expressionExpected outcome<unresolved: await t.group.snapshot(3)> Expression await t.group.snapshot(3) is not statically resolved.197
unresolved-expressionExpected outcome<unresolved: before.revision + 1> Expression before.revision + 1 is not statically resolved.200

API-002 — Group and Cuelist/Cue typed mutations remain ordered visible operations

tests/55-semantic-osc-api-and-cross-surface.spec.ts:204 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue runtimeEncoder controlsGroupsProgrammerRecordingSelectionSemantic oracleShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
208
Open the ToskLight browser application.
t.app.open()
209
The ToskLight browser application is ready.
t.app.expect.ready()
210

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with 1, 2.
t.selection.fixtures.via.api.items(1, 2)
212
Step
Group → record via api with 90, StoreMode.Overwrite, 0, "api-002-create".
t.group.recordViaApi(
			90,
			StoreMode.Overwrite,
			0,
			"api-002-create",
		)
213
Step
Selection → fixtures → api → item with 3.
t.selection.fixtures.via.api.item(3)
219
Step
Group → record via api with 90, StoreMode.Merge, $created.group.revision (from group.recordViaApi), "api-002-merge".
t.group.recordViaApi(
			90,
			StoreMode.Merge,
			created.group.revision,
			"api-002-merge",
		)
220
Expected
Group → fixtures: 90, 1, 2, 3.
t.group.expect(90).fixtures(1, 2, 3)
226
Step
Group → record via api with 90, "delete", $merged.group.revision (from group.recordViaApi), "api-002-delete".
t.group.recordViaApi(
			90,
			"delete",
			merged.group.revision,
			"api-002-delete",
		)
227
Expected
[
  $created.group.revision (from group.recordViaApi),
   $merged.group.revision (from group.recordViaApi),
   $deleted.group.revision (from group.recordViaApi)
]
equals
[
  1,
   2,
   3
]
expect([
			created.group.revision,
			merged.group.revision,
			deleted.group.revision,
		]).toEqual([1, 2, 3])
233
Expected
eventSequences =
[
  <unresolved: created.status === "changed" ? created.eventSequence : null>,
   <unresolved: merged.status === "changed" ? merged.eventSequence : null>,
   <unresolved: deleted.status === "changed" ? deleted.eventSequence : null>
]
equals
[
  <unresolved: expect.any(Number)>,
   <unresolved: expect.any(Number)>,
   <unresolved: expect.any(Number)>
]
expect(eventSequences).toEqual([
			expect.any(Number),
			expect.any(Number),
			expect.any(Number),
		])
243
Expected
To be less than: <unresolved: created.status === "changed" ? created.eventSequence : null>, <unresolved: eventSequences[1] as number>.
expect(eventSequences[0]).toBeLessThan(eventSequences[1] as number)
248
Expected
To be less than: <unresolved: merged.status === "changed" ? merged.eventSequence : null>, <unresolved: eventSequences[2] as number>.
expect(eventSequences[1]).toBeLessThan(eventSequences[2] as number)
249
Expected
$deleted.group (from group.recordViaApi) matches
{
   state:  "deleted",
   id:  "90"
}
expect(deleted.group).toMatchObject({ state: "deleted", id: "90" })
250
Expected
Group → absent: 90.
t.group.expect(90).absent()
251
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
253
Step
Encoder → intensity → dimmer → api → set with 25.
t.encoder.intensity.dimmer.via.api.set(25)
254
Step
Record → record via api with
{
   playback:  {
     page:  1,
     position:  1
  },
   cue:  90
}
t.record.recordViaApi({ playback: { page: 1, position: 1 }, cue: 90 })
255
Expected
$cueCreated (result of record.recordViaApi) matches
{
   status:  "changed",
   recordedCue:  {
     number:  "90",
     deleted:  false
  }
}
expect(cueCreated).toMatchObject({
			status: "changed",
			recordedCue: { number: "90", deleted: false },
		})
256
Step
Selection → fixtures → api → item with 2.
t.selection.fixtures.via.api.item(2)
260
Step
Encoder → intensity → dimmer → api → set with 75.
t.encoder.intensity.dimmer.via.api.set(75)
261
Step
Record → record via api with
{
   playback:  {
     page:  1,
     position:  1
  },
   cue:  90
}
t.record.recordViaApi({
			playback: { page: 1, position: 1 },
			cue: 90,
		})
262
Expected
$cueOverwritten (result of record.recordViaApi) matches
{
   status:  "changed",
   recordedCue:  {
     number:  "90",
     deleted:  false
  }
}
expect(cueOverwritten).toMatchObject({
			status: "changed",
			recordedCue: { number: "90", deleted: false },
		})
266
Expected
To be less than: $cueCreated.showEventSequence (from record.recordViaApi), $cueOverwritten.showEventSequence (from record.recordViaApi).
expect(cueCreated.showEventSequence).toBeLessThan(
			cueOverwritten.showEventSequence,
		)
272
Expected
Cue → present:
{
   page:  1,
   position:  1
}
, 90.
t.cue.expect({ page: 1, position: 1 }, 90).present()
275
Step
Record → record via api with
{
   playback:  {
     page:  1,
     position:  1
  },
   cue:  91
}
t.record.recordViaApi({ playback: { page: 1, position: 1 }, cue: 91 })
276
Expected
To be less than: $cueOverwritten.showEventSequence (from record.recordViaApi), $siblingCue.showEventSequence (from record.recordViaApi).
expect(cueOverwritten.showEventSequence).toBeLessThan(
			siblingCue.showEventSequence,
		)
279
Expected
Cue → present:
{
   page:  1,
   position:  1
}
, 91.
t.cue.expect({ page: 1, position: 1 }, 91).present()
282
Step
Cue → delete via api with
{
   page:  1,
   position:  1
}
, 90.
t.cue.deleteViaApi({ page: 1, position: 1 }, 90)
283
Expected
$cueDeleted (result of cue.deleteViaApi) matches
{
   status:  "changed",
   deletedCue:  {
     number:  "90"
  }
}
expect(cueDeleted).toMatchObject({
			status: "changed",
			deletedCue: { number: "90" },
		})
284
Expected
To be less than: $siblingCue.showEventSequence (from record.recordViaApi), $cueDeleted.showEventSequence (from cue.deleteViaApi).
expect(siblingCue.showEventSequence).toBeLessThan(
			cueDeleted.showEventSequence,
		)
290
Expected
Cue → absent:
{
   page:  1,
   position:  1
}
, 90.
t.cue.expect({ page: 1, position: 1 }, 90).absent()
293
Expected
Cue → present:
{
   page:  1,
   position:  1
}
, 91.
t.cue.expect({ page: 1, position: 1 }, 91).present()
294

Diagnostics

DiagnosticWhereDetailLine
static-control-flowSourceThe conditional expression created.status === "changed" has conditional execution; branches are documented separately and no branch is assumed.239
static-control-flowSourceThe conditional expression merged.status === "changed" has conditional execution; branches are documented separately and no branch is assumed.240
static-control-flowSourceThe conditional expression deleted.status === "changed" has conditional execution; branches are documented separately and no branch is assumed.241
unresolved-expressionExpected outcome<unresolved: created.status === "changed" ? created.eventSequence : null> Expression created.status === "changed" ? created.eventSequence : null is not statically resolved.239
unresolved-expressionExpected outcome<unresolved: merged.status === "changed" ? merged.eventSequence : null> Expression merged.status === "changed" ? merged.eventSequence : null is not statically resolved.240
unresolved-expressionExpected outcome<unresolved: deleted.status === "changed" ? deleted.eventSequence : null> Expression deleted.status === "changed" ? deleted.eventSequence : null is not statically resolved.241
unresolved-expressionExpected outcome<unresolved: expect.any(Number)> Call expression expect.any(Number) is dynamic and was not executed.244
unresolved-expressionExpected outcome<unresolved: expect.any(Number)> Call expression expect.any(Number) is dynamic and was not executed.245
unresolved-expressionExpected outcome<unresolved: expect.any(Number)> Call expression expect.any(Number) is dynamic and was not executed.246
unresolved-expressionExpected outcome<unresolved: created.status === "changed" ? created.eventSequence : null> Expression created.status === "changed" ? created.eventSequence : null is not statically resolved.239
unresolved-expressionExpected outcome<unresolved: eventSequences[1] as number> Expression eventSequences[1] as number is not statically resolved.248
unresolved-expressionExpected outcome<unresolved: merged.status === "changed" ? merged.eventSequence : null> Expression merged.status === "changed" ? merged.eventSequence : null is not statically resolved.240
unresolved-expressionExpected outcome<unresolved: eventSequences[2] as number> Expression eventSequences[2] as number is not statically resolved.249
static-control-flowSourceThe if/else cueCreated.status !== "changed" || cueOverwritten.status !== "changed" has conditional execution; branches are documented separately and no branch is assumed.270
static-control-flowSourceThe if/else siblingCue.status !== "changed" has conditional execution; branches are documented separately and no branch is assumed.277
static-control-flowSourceThe if/else cueDeleted.status !== "changed" has conditional execution; branches are documented separately and no branch is assumed.288

CROSS-001 — equivalent group value agrees across command surfaces

tests/55-semantic-osc-api-and-cross-surface.spec.ts:298 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICommand lineDMX outputShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
302
Open the ToskLight browser application.
t.app.open()
303
The ToskLight browser application is ready.
t.app.expect.ready()
304

Scenario contract

KindScenario contractLine
Step
Execute the desk command "GROUP 1 AT 50".
t.command.execute("GROUP 1 AT 50")
306
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
307
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 128 })
308

Diagnostics

None.

CROSS-001 — typed API Group value produces the shared Programmer and wire output

tests/55-semantic-osc-api-and-cross-surface.spec.ts:312 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateDMX outputOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
316
Open the ToskLight browser application.
t.app.open()
317
The ToskLight browser application is ready.
t.app.expect.ready()
318

Scenario contract

KindScenario contractLine
Step
Cross surface → apply group one at fifty via api.
t.crossSurface.applyGroupOneAtFiftyViaApi()
320
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 128 })
321

Diagnostics

None.

CROSS-001 — real OSC Group command produces the shared Programmer and wire output

tests/55-semantic-osc-api-and-cross-surface.spec.ts:325 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICross-surface stateDMX outputOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
329
Open the ToskLight browser application.
t.app.open()
330
The ToskLight browser application is ready.
t.app.expect.ready()
331

Scenario contract

KindScenario contractLine
Step
Cross surface → apply group one at fifty via osc.
t.crossSurface.applyGroupOneAtFiftyViaOsc()
333
Expected
fixtureRange(1, 12) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixtureRange(1, 12), { Intensity: 128 })
334

Diagnostics

None.

CROSS-002 — browser live-reconciles external REST and typed live-action mutations

tests/55-semantic-osc-api-and-cross-surface.spec.ts:338 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICross-surface stateGroupsOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
342
Open the ToskLight browser application.
t.app.open()
343
The ToskLight browser application is ready.
t.app.expect.ready()
344

Scenario contract

KindScenario contractLine
Step
Cross surface → reconcile external group mutation.
t.crossSurface.reconcileExternalGroupMutation()
346
Expected
The browser reconciles external Group membership and Programmer value mutations before and after reload.
t.crossSurface.reconcileExternalGroupMutation()
346
Expected
Group → fixtures: 3, 1, 2, 3, 4, 5.
t.group.expect(3).fixtures(1, 2, 3, 4, 5)
347

Diagnostics

None.

PRELOAD-003 — Playback panes persist sparse addresses with Follow Main and Pinned page sources

tests/55-semantic-virtual-playback-layout.spec.ts:11 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICue timingDesktop layoutEncoder controlsPlaybacksProgrammerProgrammer timingRecordingSelectionSemantic oracleShow filesTyped APIVirtual Playbacks
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
15
Open the ToskLight browser application.
t.app.open()
16
The ToskLight browser application is ready.
t.app.expect.ready()
17

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
18
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
19
Expected
<unresolved: panePlaybackAddress(1, 1)> equals { page: 1, position: 401 }.
expect(panePlaybackAddress(1, 1)).toEqual({ page: 1, position: 401 })
20
Expected
<unresolved: panePlaybackAddress(300, 1)> equals { page: 1, position: 700 }.
expect(panePlaybackAddress(300, 1)).toEqual({ page: 1, position: 700 })
21
Expected
<unresolved: panePlaybackAddress(1, 2)> equals { page: 2, position: 401 }.
expect(panePlaybackAddress(1, 2)).toEqual({ page: 2, position: 401 })
22
Expected
<unresolved: panePlaybackAddress(600, 99)> equals { page: 99, position: 1000 }.
expect(panePlaybackAddress(600, 99)).toEqual({ page: 99, position: 1000 })
23
Expected
To throw: <generated: callback>, "Playback position must be within 1-1000".
expect(() => panePlaybackAddress(601, 1)).toThrow("Playback position must be within 1-1000")
24
Step
Clear the current selection.
t.selection.clear()
31
Step
Selection → fixtures → api → item with fixture = 3.
t.selection.fixtures.via.api.item(fixture)
32
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
33
Step
Record → playback with slot = 5.
t.record.playback(slot)
34
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
35
Step
Encoder → intensity → dimmer → api → set with 80.
t.encoder.intensity.dimmer.via.api.set(80)
36
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
37
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
38
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Virtual Source A",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Go,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Go,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
39
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
49
Step
Clear the current selection.
t.selection.clear()
31
Step
Selection → fixtures → api → item with fixture = 4.
t.selection.fixtures.via.api.item(fixture)
32
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
33
Step
Record → playback with slot = 6.
t.record.playback(slot)
34
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
35
Step
Encoder → intensity → dimmer → api → set with 80.
t.encoder.intensity.dimmer.via.api.set(80)
36
Step
Record → cue with
{
   playback:  $playback (result of record.playback),
   cue:  2
}
t.record.cue({ playback, cue: 2 })
37
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
38
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Virtual Source B",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Go,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Go,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
39
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
49
Step
Desktop → configure with .desktop: Virtual Playback Desktop
t.desktop.configure("Virtual Playback Desktop")
56
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{
				slug: "virtual-playbacks-follow",
				column: 1,
				row: 1,
				width: 12,
				height: 5,
			},
			{ rows: 2, columns: 6, pageMode: "follow_main" },
		)
57
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{
				slug: "virtual-playbacks-pinned",
				column: 1,
				row: 6,
				width: 12,
				height: 5,
			},
			{ rows: 2, columns: 6, pageMode: "pinned", pinnedPage: 2 },
		)
68
Step
Apply the configured Desktop layout.
desktop.apply()
79
Expected
Virtual playback → effective page: $followPane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.expect.effectivePage(followPane, 1)
83
Expected
Virtual playback → effective page: $pinnedPane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.expect.effectivePage(pinnedPane, 2)
84
Step
Virtual playback → assign source with $followPane (result of desktopBuilder.addPane), "Virtual Source A", 1, 1.
t.virtualPlayback.assignSource(
			followPane,
			"Virtual Source A",
			1,
			1,
		)
86
Step
Virtual playback → assign source with $pinnedPane (result of desktopBuilder.addPane), "Virtual Source B", 1, 2.
t.virtualPlayback.assignSource(
			pinnedPane,
			"Virtual Source B",
			1,
			2,
		)
92
Step
Virtual playback → configure top button with $pinnedPane (result of desktopBuilder.addPane), 1, PlaybackButton.Toggle, 2.
t.virtualPlayback.configureTopButton(
			pinnedPane,
			1,
			PlaybackButton.Toggle,
			2,
		)
98
Step
Virtual playback → activate with $followPane (result of desktopBuilder.addPane), 1, 1.
t.virtualPlayback.activate(followPane, 1, 1)
105
Step
Virtual playback → activate with $pinnedPane (result of desktopBuilder.addPane), 1, 2.
t.virtualPlayback.activate(pinnedPane, 1, 2)
106
Expected
Virtual playback → runtime: $firstPlayback (result of virtualPlayback.assignSource),
{
   identity:  {
     kind:  "playback",
     page:  1,
     position:  401
  },
   target:  "cue_list",
   runtime:  {
     enabled:  true,
     current:  {
       number:  "1"
    }
  }
}
t.virtualPlayback.expect.runtime(firstPlayback, {
			identity: {
				kind: "playback",
				page: 1,
				position: 401,
			},
			target: "cue_list",
			runtime: { enabled: true, current: { number: "1" } },
		})
107
Expected
Virtual playback → runtime: $secondPlayback (result of virtualPlayback.assignSource),
{
   identity:  {
     kind:  "playback",
     page:  2,
     position:  401
  },
   target:  "cue_list",
   runtime:  {
     enabled:  true,
     current:  {
       number:  "1"
    }
  }
}
t.virtualPlayback.expect.runtime(secondPlayback, {
			identity: {
				kind: "playback",
				page: 2,
				position: 401,
			},
			target: "cue_list",
			runtime: { enabled: true, current: { number: "1" } },
		})
116
Expected
Playback → runtime: $firstSource (result of recordSource),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(firstSource).runtime({ enabled: true, current_cue_number: "1" })
125
Expected
Playback → runtime: $secondSource (result of recordSource),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(secondSource).runtime({ enabled: true, current_cue_number: "1" })
126
Expected
Playback → present: $firstSource (result of recordSource).
t.playback.expect(firstSource).present()
127
Expected
Playback → present: $secondSource (result of recordSource).
t.playback.expect(secondSource).present()
128
Step
Virtual playback → set main page with 2.
t.virtualPlayback.setMainPage(2)
130
Expected
Virtual playback → effective page: $followPane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.expect.effectivePage(followPane, 2)
131
Expected
Virtual playback → effective page: $pinnedPane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.expect.effectivePage(pinnedPane, 2)
132
Step
Virtual playback → set main page with 1.
t.virtualPlayback.setMainPage(1)
133
Expected
Virtual playback → effective page: $followPane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.expect.effectivePage(followPane, 1)
134
Expected
Virtual playback → effective page: $pinnedPane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.expect.effectivePage(pinnedPane, 2)
135
Step
Virtual playback → reload with $followPane (result of desktopBuilder.addPane).
t.virtualPlayback.reload(followPane)
137
Expected
Virtual playback → logical cells: $followPane (result of desktopBuilder.addPane), 12.
t.virtualPlayback.expect.logicalCells(followPane, 12)
138
Expected
Virtual playback → logical cells: $pinnedPane (result of desktopBuilder.addPane), 12.
t.virtualPlayback.expect.logicalCells(pinnedPane, 12)
139
Expected
Virtual playback → button: $followPane (result of desktopBuilder.addPane), 1, "GO", 1.
t.virtualPlayback.expect.button(followPane, 1, "GO", 1)
140
Expected
Virtual playback → button: $pinnedPane (result of desktopBuilder.addPane), 1, "TOGGLE", 2.
t.virtualPlayback.expect.button(pinnedPane, 1, "TOGGLE", 2)
141
Expected
Virtual playback → assignment: $firstPlayback (result of virtualPlayback.assignSource),
{
   button_count:  1,
   has_fader:  false,
   buttons:  [
    "go",
     "none",
     "none"
  ]
}
t.virtualPlayback.expect.assignment(firstPlayback, {
			button_count: 1,
			has_fader: false,
			buttons: ["go", "none", "none"],
		})
142
Expected
Virtual playback → assignment: $secondPlayback (result of virtualPlayback.assignSource),
{
   button_count:  1,
   has_fader:  false,
   buttons:  [
    "toggle",
     "none",
     "none"
  ]
}
t.virtualPlayback.expect.assignment(secondPlayback, {
			button_count: 1,
			has_fader: false,
			buttons: ["toggle", "none", "none"],
		})
147

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: panePlaybackAddress(1, 1)> Call expression panePlaybackAddress(1, 1) is dynamic and was not executed.20
unresolved-expressionExpected outcome<unresolved: panePlaybackAddress(300, 1)> Call expression panePlaybackAddress(300, 1) is dynamic and was not executed.21
unresolved-expressionExpected outcome<unresolved: panePlaybackAddress(1, 2)> Call expression panePlaybackAddress(1, 2) is dynamic and was not executed.22
unresolved-expressionExpected outcome<unresolved: panePlaybackAddress(600, 99)> Call expression panePlaybackAddress(600, 99) is dynamic and was not executed.23

LOCK-001 — Desk Lock protects every screen and keeps its configuration in Screens

tests/56-semantic-desk-lock.spec.ts:6 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIDesk LockScreensShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
10
Open the ToskLight browser application.
t.app.open()
11
The ToskLight browser application is ready.
t.app.expect.ready()
12

Scenario contract

KindScenario contractLine
Expected
Desk lock → expect pin protection across screens.
t.deskLock.expectPinProtectionAcrossScreens()
14
Expected
Desk lock → expect button fallback.
t.deskLock.expectButtonFallback()
15
Expected
Desk lock → expect screen settings ownership.
t.deskLock.expectScreenSettingsOwnership()
16

Diagnostics

None.

VPB-007 — show-owned Solo Region selection is inert, saved winners are authoritative, and regions are explicitly removable

tests/56-semantic-virtual-playback-exclusion-zone.spec.ts:10 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICue timingDesktop layoutEncoder controlsPlaybacksProgrammerProgrammer timingRecordingResolved outputSelectionShow filesTest clockTyped APIVirtual Playbacks
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
14
Open the ToskLight browser application.
t.app.open()
15
The ToskLight browser application is ready.
t.app.expect.ready()
16

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
17
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
18
Step
Clear the current selection.
t.selection.clear()
26
Step
Selection → fixtures → api → item with fixtureNumber = 3.
t.selection.fixtures.via.api.item(fixtureNumber)
27
Step
Encoder → intensity → dimmer → api → set with intensity = 25.
t.encoder.intensity.dimmer.via.api.set(intensity)
28
Step
Record → playback with slot = 5.
t.record.playback(slot)
29
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
30
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Touring A",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Toggle,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
31
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
41
Step
Clear the current selection.
t.selection.clear()
26
Step
Selection → fixtures → api → item with fixtureNumber = 4.
t.selection.fixtures.via.api.item(fixtureNumber)
27
Step
Encoder → intensity → dimmer → api → set with intensity = 50.
t.encoder.intensity.dimmer.via.api.set(intensity)
28
Step
Record → playback with slot = 6.
t.record.playback(slot)
29
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
30
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Touring B",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Toggle,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
31
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
41
Step
Clear the current selection.
t.selection.clear()
26
Step
Selection → fixtures → api → item with fixtureNumber = 5.
t.selection.fixtures.via.api.item(fixtureNumber)
27
Step
Encoder → intensity → dimmer → api → set with intensity = 75.
t.encoder.intensity.dimmer.via.api.set(intensity)
28
Step
Record → playback with slot = 7.
t.record.playback(slot)
29
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
30
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Touring C",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [
					PlaybackButton.Toggle,
					PlaybackButton.Empty,
					PlaybackButton.Empty,
				],
			})
31
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
41
Step
Desktop → configure with .desktop: Touring Virtual Playbacks
t.desktop.configure("Touring Virtual Playbacks")
49
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{
				slug: "touring-virtual-playbacks",
				column: 1,
				row: 1,
				width: 12,
				height: 10,
			},
			{ rows: 3, columns: 6 },
		)
50
Step
Apply the configured Desktop layout.
desktop.apply()
61
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Touring A", 1.
t.virtualPlayback.assignSource(
			pane,
			"Touring A",
			1,
		)
64
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Touring B", 2.
t.virtualPlayback.assignSource(
			pane,
			"Touring B",
			2,
		)
69
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Touring C", 3.
t.virtualPlayback.assignSource(
			pane,
			"Touring C",
			3,
		)
74
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
79
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
80
Expected
Virtual playback → runtime: $firstPlayback (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(firstPlayback, { runtime: { enabled: true } })
81
Expected
Virtual playback → runtime: $secondPlayback (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(secondPlayback, { runtime: { enabled: true } })
82
Step
Virtual playback → create solo region with attached shift with $pane (result of desktopBuilder.addPane), "Touring pair",
[
  1,
   2
]
t.virtualPlayback.createSoloRegionWithAttachedShift(
			pane,
			"Touring pair",
			[1, 2],
		)
84
Expected
Virtual playback → zones:
[
  {
     name:  "Touring pair",
     members:  [
      {
         page:  1,
         position:  401
      },
       {
         page:  1,
         position:  402
      }
    ]
  }
]
t.virtualPlayback.expect.zones([
			{ name: "Touring pair", members: [{ page: 1, position: 401 }, { page: 1, position: 402 }] },
		])
89
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 1, "top bottom left".
t.virtualPlayback.expect.fence(pane, 1, "top bottom left")
92
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 2, "top right bottom".
t.virtualPlayback.expect.fence(pane, 2, "top right bottom")
93
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 1, "top bottom left".
t.virtualPlayback.expect.fence(pane, 1, "top bottom left")
99
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 2, "top right bottom".
t.virtualPlayback.expect.fence(pane, 2, "top right bottom")
100
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 1, "top bottom left".
t.virtualPlayback.expect.fence(pane, 1, "top bottom left")
99
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 2, "top right bottom".
t.virtualPlayback.expect.fence(pane, 2, "top right bottom")
100
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 1, "top bottom left".
t.virtualPlayback.expect.fence(pane, 1, "top bottom left")
105
Expected
Virtual playback → fence: $pane (result of desktopBuilder.addPane), 2, "top right bottom".
t.virtualPlayback.expect.fence(pane, 2, "top right bottom")
106
Expected
Virtual playback → runtime: $firstPlayback (result of virtualPlayback.assignSource),
{
   identity:  {
     kind:  "playback",
     page:  1,
     position:  401
  },
   target:  "cue_list",
   runtime:  {
     enabled:  false
  }
}
t.virtualPlayback.expect.runtime(firstPlayback, {
			identity: {
				kind: "playback",
				page: 1,
				position: 401,
			},
			target: "cue_list",
			runtime: { enabled: false },
		})
109
Expected
Virtual playback → runtime: $secondPlayback (result of virtualPlayback.assignSource),
{
   identity:  {
     kind:  "playback",
     page:  1,
     position:  402
  },
   target:  "cue_list",
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(secondPlayback, {
			identity: {
				kind: "playback",
				page: 1,
				position: 402,
			},
			target: "cue_list",
			runtime: { enabled: true },
		})
118
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
128
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
129
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
130
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
131
Expected
Virtual playback → runtime: $firstPlayback (result of virtualPlayback.assignSource),
{
   target:  "cue_list",
   runtime:  {
     enabled:  false
  }
}
t.virtualPlayback.expect.runtime(firstPlayback, {
			target: "cue_list",
			runtime: { enabled: false },
		})
132
Expected
Virtual playback → runtime: $secondPlayback (result of virtualPlayback.assignSource),
{
   target:  "cue_list",
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(secondPlayback, {
			target: "cue_list",
			runtime: { enabled: true },
		})
136
Expected
Virtual playback → runtime: $thirdPlayback (result of virtualPlayback.assignSource),
{
   target:  "cue_list",
   runtime:  {
     enabled:  false
  }
}
t.virtualPlayback.expect.runtime(thirdPlayback, {
			target: "cue_list",
			runtime: { enabled: false },
		})
140
Expected
Playback → runtime: $firstSource (result of recordSource),
{
   enabled:  false
}
t.playback.expect(firstSource).runtime({ enabled: false })
144
Expected
Playback → runtime: $secondSource (result of recordSource),
{
   enabled:  true
}
t.playback.expect(secondSource).runtime({ enabled: true })
145
Expected
Playback → runtime: $thirdSource (result of recordSource),
{
   enabled:  false
}
t.playback.expect(thirdSource).runtime({ enabled: false })
146
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
147
Expected
fixture(3) resolved values equal
{
   intensity:  0
}
t.expectFixtureValue(fixture(3), { intensity: 0 })
148
Expected
fixture(4) resolved values equal
{
   intensity:  0.5
}
t.expectFixtureValue(fixture(4), { intensity: 0.5 })
149
Expected
fixture(5) resolved values equal
{
   intensity:  0
}
t.expectFixtureValue(fixture(5), { intensity: 0 })
150
Step
Virtual playback → delete solo region with $pane (result of desktopBuilder.addPane), "Touring pair".
t.virtualPlayback.deleteSoloRegion(pane, "Touring pair")
152
Expected
Virtual playback → zones:
[
]
t.virtualPlayback.expect.zones([])
153
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
154
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
155
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
156
Expected
Virtual playback → runtime: $firstPlayback (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(firstPlayback, {
			runtime: { enabled: true },
		})
157
Expected
Virtual playback → runtime: $secondPlayback (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(secondPlayback, {
			runtime: { enabled: true },
		})
160

Diagnostics

None.

UPDATE-001 — Update Add New appends ordered Group membership

tests/57-semantic-system-integrations.spec.ts:6 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineGroupsSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
10
Open the ToskLight browser application.
t.app.open()
11
The ToskLight browser application is ready.
t.app.expect.ready()
12

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → item with 5.
t.selection.fixtures.via.api.item(5)
13
Step
Execute the desk command "UPDATE ALL GROUP 3" through the API.
t.command.via.api.execute("UPDATE ALL GROUP 3")
14
Expected
Group → fixtures: 3, 1, 2, 3, 4, 5.
t.group.expect(3).fixtures(1, 2, 3, 4, 5)
15

Diagnostics

None.

HIGHLIGHT-001 — HIGH follows the actual stepped selection

tests/57-semantic-system-integrations.spec.ts:19 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICommand keypadHighlightSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
23
Open the ToskLight browser application.
t.app.open()
24
The ToskLight browser application is ready.
t.app.expect.ready()
25

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with 101, 102, 103.
t.selection.fixtures.via.api.items(101, 102, 103)
26
Step
Highlight → on.
t.highlight.on()
27
Step
Press keypad keys
[
  "NEXT"
]
t.keypad.press(["NEXT"])
28
Expected
Highlight → expect selection: 101.
t.highlight.expectSelection(101)
29
Step
Highlight → wait for control debounce.
t.highlight.waitForControlDebounce()
30
Step
Press keypad keys
[
  "NEXT"
]
t.keypad.press(["NEXT"])
31
Expected
Highlight → expect selection: 102.
t.highlight.expectSelection(102)
32
Step
Highlight → off.
t.highlight.off()
33

Diagnostics

None.

HIGHLIGHT-002 — HIGH follows external selection and survives an empty selection

tests/57-semantic-system-integrations.spec.ts:37 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIHighlightSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
41
Open the ToskLight browser application.
t.app.open()
42
The ToskLight browser application is ready.
t.app.expect.ready()
43

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with 101, 102, 103, 104.
t.selection.fixtures.via.api.items(101, 102, 103, 104)
44
Step
Highlight → on.
t.highlight.on()
45
Step
Clear the current selection.
t.selection.clear()
46
Step
Selection → fixtures → api → items with 103, 104.
t.selection.fixtures.via.api.items(103, 104)
47
Expected
Highlight → expect selection: 103, 104.
t.highlight.expectSelection(103, 104)
48
Step
Highlight → off.
t.highlight.off()
49

Diagnostics

None.

HIGHLIGHT-003 — PREV NEXT ALL mutate the real selection

tests/57-semantic-system-integrations.spec.ts:53 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICommand keypadHighlightSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
57
Open the ToskLight browser application.
t.app.open()
58
The ToskLight browser application is ready.
t.app.expect.ready()
59

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with 101, 102, 103, 104.
t.selection.fixtures.via.api.items(101, 102, 103, 104)
60
Step
Highlight → on.
t.highlight.on()
61
Step
Press keypad keys
[
  "NEXT"
]
t.keypad.press(["NEXT"])
62
Expected
Highlight → expect selection: 101.
t.highlight.expectSelection(101)
63
Step
Highlight → wait for control debounce.
t.highlight.waitForControlDebounce()
64
Step
Press keypad keys
[
  "NEXT"
]
t.keypad.press(["NEXT"])
65
Expected
Highlight → expect selection: 102.
t.highlight.expectSelection(102)
66
Step
Highlight → wait for control debounce.
t.highlight.waitForControlDebounce()
67
Step
Press keypad keys
[
  "ALL"
]
t.keypad.press(["ALL"])
68
Expected
Highlight → expect selection: 101, 102, 103, 104.
t.highlight.expectSelection(101, 102, 103, 104)
69
Step
Highlight → wait for control debounce.
t.highlight.waitForControlDebounce()
70
Step
Press keypad keys
[
  "PREV"
]
t.keypad.press(["PREV"])
71
Expected
Highlight → expect selection: 104.
t.highlight.expectSelection(104)
72
Step
Highlight → off.
t.highlight.off()
73

Diagnostics

None.

HIGHLIGHT-005 — Highlight errors remain reachable and dismissible

tests/57-semantic-system-integrations.spec.ts:77 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIDesk integrationsShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
81
Open the ToskLight browser application.
t.app.open()
82
The ToskLight browser application is ready.
t.app.expect.ready()
83

Scenario contract

KindScenario contractLine
Expected
System integration → expect highlight error overlay.
t.systemIntegration.expectHighlightErrorOverlay()
84

Diagnostics

None.

FIXTURE-001 — a complete fixture profile is created through the desk library

tests/57-semantic-system-integrations.spec.ts:88 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIDesk integrationsShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
92
Open the ToskLight browser application.
t.app.open()
93
The ToskLight browser application is ready.
t.app.expect.ready()
94

Scenario contract

KindScenario contractLine
Expected
System integration → expect fixture profile creation: "Semantic Acceptance", "Revisioned profile <unresolved: crypto.randomUUID().slice(0, 8)>".
t.systemIntegration.expectFixtureProfileCreation(
			"Semantic Acceptance",
			`Revisioned profile ${crypto.randomUUID().slice(0, 8)}`,
		)
95

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: crypto.randomUUID().slice(0, 8)> Call expression crypto.randomUUID().slice(0, 8) is dynamic and was not executed.97

MATTER-001 — the desk-persistent Matter bridge toggles from Network and Inputs

tests/57-semantic-system-integrations.spec.ts:102 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIDesk integrationsShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
106
Open the ToskLight browser application.
t.app.open()
107
The ToskLight browser application is ready.
t.app.expect.ready()
108

Scenario contract

KindScenario contractLine
Expected
System integration → expect matter bridge toggle.
t.systemIntegration.expectMatterBridgeToggle()
109

Diagnostics

None.

SOUND-001 — a desk-local audio observation drives Speed Group A

tests/57-semantic-system-integrations.spec.ts:113 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UIDesk integrationsShow files
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
117
Open the ToskLight browser application.
t.app.open()
118
The ToskLight browser application is ready.
t.app.expect.ready()
119

Scenario contract

KindScenario contractLine
Expected
System integration → expect sound to light configuration.
t.systemIntegration.expectSoundToLightConfiguration()
120

Diagnostics

None.

PRELOAD-004 — virtual GO and TOGGLE alone remain pending and share Programmer Fade

tests/57-semantic-virtual-playback-preload.spec.ts:10 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICommand lineCue timingDesktop layoutEncoder controlsPlaybacksPreloadProgrammerProgrammer timingRecordingResolved outputSelectionShow filesTest clockTyped APIVirtual Playbacks
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
14
Open the ToskLight browser application.
t.app.open()
15
The ToskLight browser application is ready.
t.app.expect.ready()
16

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
17
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
18
Step
Clear the current selection.
t.selection.clear()
27
Step
Selection → fixtures → api → item with fixtureNumber = 3.
t.selection.fixtures.via.api.item(fixtureNumber)
28
Step
Encoder → intensity → dimmer → api → set with intensity = 100.
t.encoder.intensity.dimmer.via.api.set(intensity)
29
Step
Record → playback with slot = 5.
t.record.playback(slot)
30
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
31
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Virtual GO",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    button = PlaybackButton.Go,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
32
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
38
Step
Clear the current selection.
t.selection.clear()
27
Step
Selection → fixtures → api → item with fixtureNumber = 4.
t.selection.fixtures.via.api.item(fixtureNumber)
28
Step
Encoder → intensity → dimmer → api → set with intensity = 80.
t.encoder.intensity.dimmer.via.api.set(intensity)
29
Step
Record → playback with slot = 6.
t.record.playback(slot)
30
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
31
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Virtual TOGGLE",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    button = PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
32
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
38
Step
Clear the current selection.
t.selection.clear()
27
Step
Selection → fixtures → api → item with fixtureNumber = 5.
t.selection.fixtures.via.api.item(fixtureNumber)
28
Step
Encoder → intensity → dimmer → api → set with intensity = 60.
t.encoder.intensity.dimmer.via.api.set(intensity)
29
Step
Record → playback with slot = 3.
t.record.playback(slot)
30
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
31
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Physical live",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    button = PlaybackButton.Go,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
32
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
38
Step
Desktop → configure with .desktop: Preload Virtual Playbacks
t.desktop.configure("Preload Virtual Playbacks")
64
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{
				slug: "preload-virtual-playbacks",
				column: 1,
				row: 1,
				width: 12,
				height: 10,
			},
			{ rows: 1, columns: 3 },
		)
65
Step
Apply the configured Desktop layout.
desktop.apply()
76
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Virtual GO", 1.
t.virtualPlayback.assignSource(
			pane,
			"Virtual GO",
			1,
		)
77
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Virtual TOGGLE", 2.
t.virtualPlayback.assignSource(
			pane,
			"Virtual TOGGLE",
			2,
		)
82
Expected
Playback → present: $goSource (result of recordSource).
t.playback.expect(goSource).present()
87
Expected
Playback → present: $toggleSource (result of recordSource).
t.playback.expect(toggleSource).present()
88
Step
Preload → configure with
{
   programmer:  false,
   playbackScope:  {
     position_ranges:  [
      {
         start:  401,
         end:  402
      }
    ],
     pages:  null
  },
   programmerFade:  2500,
   cueFade:  8000
}
t.preload.configure({
			programmer: false,
			playbackScope: { position_ranges: [{ start: 401, end: 402 }], pages: null },
			programmerFade: 2_500,
			cueFade: 8_000,
		})
90
Step
Start blind Preload programming.
t.preload.start()
96
Step
Execute the desk command "1 AT 35".
t.command.execute("1 AT 35")
97
Step
Playback → open.
t.playback.open()
98
Step
Playback → go with $physicalPlayback (result of recordSource).
t.playback.go(physicalPlayback)
99
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 1.
t.virtualPlayback.activate(pane, 1)
100
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
101
Expected
Preload → pending matching:
{
   groupIds:  [
  ],
   playbackActions:  [
    [
      $virtualGo (result of virtualPlayback.assignSource),
       "go",
       {
         surface_id:  <unresolved: expect.any(String)>,
         control_id:  <unresolved: expect.any(Number)>
      }
    ],
     [
      $virtualToggle (result of virtualPlayback.assignSource),
       "toggle",
       {
         surface_id:  <unresolved: expect.any(String)>,
         control_id:  <unresolved: expect.any(Number)>
      }
    ]
  ]
}
t.preload.expect.pendingMatching({ groupIds: [], playbackActions: [
            [virtualGo, "go", { surface_id: expect.any(String), control_id: expect.any(Number) }],
            [virtualToggle, "toggle", { surface_id: expect.any(String), control_id: expect.any(Number) }],
        ] })
102
Expected
Playback → runtime: $goSource (result of recordSource),
{
   enabled:  false
}
t.playback.expect(goSource).runtime({ enabled: false })
106
Expected
Playback → runtime: $toggleSource (result of recordSource),
{
   enabled:  false
}
t.playback.expect(toggleSource).runtime({ enabled: false })
107
Expected
Playback → runtime: $physicalPlayback (result of recordSource),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(physicalPlayback).runtime({
			enabled: true,
			current_cue_number: "1",
		})
108
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
112
Expected
fixture(3) resolved values equal
{
   intensity:  0
}
t.expectFixtureValue(fixture(3), { intensity: 0 })
113
Expected
fixture(4) resolved values equal
{
   intensity:  0
}
t.expectFixtureValue(fixture(4), { intensity: 0 })
114
Step
Preload → commit.
t.preload.commit()
116
Expected
Virtual playback → runtime: $virtualGo (result of virtualPlayback.assignSource),
{
   identity:  {
     kind:  "playback",
     page:  1,
     position:  401
  },
   target:  "cue_list",
   runtime:  {
     enabled:  true,
     current:  {
       number:  "1"
    }
  }
}
t.virtualPlayback.expect.runtime(virtualGo, {
			identity: {
				kind: "playback",
				page: 1,
				position: 401,
			},
			target: "cue_list",
			runtime: { enabled: true, current: { number: "1" } },
		})
117
Expected
Virtual playback → runtime: $virtualToggle (result of virtualPlayback.assignSource),
{
   identity:  {
     kind:  "playback",
     page:  1,
     position:  402
  },
   target:  "cue_list",
   runtime:  {
     enabled:  true,
     current:  {
       number:  "1"
    }
  }
}
t.virtualPlayback.expect.runtime(virtualToggle, {
			identity: {
				kind: "playback",
				page: 1,
				position: 402,
			},
			target: "cue_list",
			runtime: { enabled: true, current: { number: "1" } },
		})
126
Step
Advance the test clock by "2500ms".
t.clock.advanceBy("2500ms")
135
Expected
fixture(3) resolved values equal
{
   intensity:  1
}
t.expectFixtureValue(fixture(3), { intensity: 1 })
136
Expected
fixture(4) resolved values equal
{
   intensity:  0.8
}
t.expectFixtureValue(fixture(4), { intensity: 0.8 })
137
Step
Release blind Preload programming.
t.preload.release()
139
Expected
Virtual playback → runtime: $virtualGo (result of virtualPlayback.assignSource),
{
   target:  "cue_list",
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(virtualGo, {
			target: "cue_list",
			runtime: { enabled: true },
		})
140
Expected
Virtual playback → runtime: $virtualToggle (result of virtualPlayback.assignSource),
{
   target:  "cue_list",
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(virtualToggle, {
			target: "cue_list",
			runtime: { enabled: true },
		})
144
Expected
fixture(1) resolved values equal
{
   intensity:  0.35
}
t.expectFixtureValue(fixture(1), { intensity: 0.35 })
148

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: expect.any(String)> Call expression expect.any(String) is dynamic and was not executed.103
unresolved-expressionExpected outcome<unresolved: expect.any(Number)> Call expression expect.any(Number) is dynamic and was not executed.103
unresolved-expressionExpected outcome<unresolved: expect.any(String)> Call expression expect.any(String) is dynamic and was not executed.104
unresolved-expressionExpected outcome<unresolved: expect.any(Number)> Call expression expect.any(Number) is dynamic and was not executed.104

PRELOAD-005 — programmer capture and four range/page eligibility scopes persist independently

tests/58-semantic-preload-capture-mask.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UIPreloadPreload SettingsShow files
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Preload → open settings.
t.preload.openSettings()
27
Step
Preload settings → configure with mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  1000
      }
    ],
     pages:  null
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  1000
      }
    ],
     pages:  null
  }
}
settings.expect.mask(mask)
32
Step
Preload settings → configure with mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  1000
      }
    ],
     pages:  null
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  1000
      }
    ],
     pages:  null
  }
}
settings.expect.mask(mask)
32
Step
Preload settings → configure with mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  15
      }
    ],
     pages:  null
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  15
      }
    ],
     pages:  null
  }
}
settings.expect.mask(mask)
32
Step
Preload settings → configure with mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  15
      }
    ],
     pages:  null
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  1,
         end:  15
      }
    ],
     pages:  null
  }
}
settings.expect.mask(mask)
32
Step
Preload settings → configure with mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  301,
         end:  305
      },
       {
         start:  401,
         end:  680
      }
    ],
     pages:  [
      1,
       2
    ]
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  301,
         end:  305
      },
       {
         start:  401,
         end:  680
      }
    ],
     pages:  [
      1,
       2
    ]
  }
}
settings.expect.mask(mask)
32
Step
Preload settings → configure with mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  301,
         end:  305
      },
       {
         start:  401,
         end:  680
      }
    ],
     pages:  [
      1,
       2
    ]
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  301,
         end:  305
      },
       {
         start:  401,
         end:  680
      }
    ],
     pages:  [
      1,
       2
    ]
  }
}
settings.expect.mask(mask)
32
Step
Preload settings → configure with mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  101,
         end:  115
      }
    ],
     pages:  [
      99
    ]
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = false,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  101,
         end:  115
      }
    ],
     pages:  [
      99
    ]
  }
}
settings.expect.mask(mask)
32
Step
Preload settings → configure with mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  101,
         end:  115
      }
    ],
     pages:  [
      99
    ]
  }
}
settings.configure(mask)
31
Expected
Preload settings → mask: mask =
{
   programmer:  programmer = true,
   playbackScope:  playbackScope = {
     position_ranges:  [
      {
         start:  101,
         end:  115
      }
    ],
     pages:  [
      99
    ]
  }
}
settings.expect.mask(mask)
32

Diagnostics

None.

PRELOAD-006 — combined Preload commits atomically and releases only programmer data

tests/59-semantic-combined-preload.spec.ts:10 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICommand lineCue timingDesktop layoutEncoder controlsPlaybacksPreloadProgrammerProgrammer timingRecordingResolved outputSelectionShow filesTest clockTyped APIVirtual Playbacks
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
14
Open the ToskLight browser application.
t.app.open()
15
The ToskLight browser application is ready.
t.app.expect.ready()
16

Scenario contract

KindScenario contractLine
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
17
Step
Timing → cue fade → set with "0s".
t.timing.cueFade.set("0s")
18
Step
Clear the current selection.
t.selection.clear()
27
Step
Selection → fixtures → api → item with fixtureNumber = 1.
t.selection.fixtures.via.api.item(fixtureNumber)
28
Step
Encoder → intensity → dimmer → api → set with intensity = 25.
t.encoder.intensity.dimmer.via.api.set(intensity)
29
Step
Record → playback with slot = 5.
t.record.playback(slot)
30
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
31
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Underlying source",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    button = PlaybackButton.Go,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
32
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
38
Step
Clear the current selection.
t.selection.clear()
27
Step
Selection → fixtures → api → item with fixtureNumber = 3.
t.selection.fixtures.via.api.item(fixtureNumber)
28
Step
Encoder → intensity → dimmer → api → set with intensity = 60.
t.encoder.intensity.dimmer.via.api.set(intensity)
29
Step
Record → playback with slot = 1.
t.record.playback(slot)
30
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
31
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Physical combined",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    button = PlaybackButton.Go,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
32
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
38
Step
Clear the current selection.
t.selection.clear()
27
Step
Selection → fixtures → api → item with fixtureNumber = 4.
t.selection.fixtures.via.api.item(fixtureNumber)
28
Step
Encoder → intensity → dimmer → api → set with intensity = 80.
t.encoder.intensity.dimmer.via.api.set(intensity)
29
Step
Record → playback with slot = 6.
t.record.playback(slot)
30
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
31
Step
Playback → configure with $playback (result of record.playback),
{
   name:  name = "Virtual combined",
   buttonCount:  1,
   hasFader:  false,
   buttons:  [
    button = PlaybackButton.Toggle,
     PlaybackButton.Empty,
     PlaybackButton.Empty
  ]
}
t.playback.configure(playback, {
				name,
				buttonCount: 1,
				hasFader: false,
				buttons: [button, PlaybackButton.Empty, PlaybackButton.Empty],
			})
32
Step
Playback → api → off with $playback (result of record.playback).
t.playback.via.api.off(playback)
38
Step
Preload → configure with
{
   programmer:  true,
   playbackScope:  {
     position_ranges:  [
      {
         start:  1,
         end:  1000
      }
    ],
     pages:  null
  },
   programmerFade:  1500,
   cueFade:  8000
}
t.preload.configure({
			programmer: true,
			playbackScope: { position_ranges: [{ start: 1, end: 1000 }], pages: null },
			programmerFade: 1_500,
			cueFade: 8_000,
		})
57
Step
Playback → api → go with $underlying (result of recordSource).
t.playback.via.api.go(underlying)
63
Step
Advance the test clock by "8s".
t.clock.advanceBy("8s")
64
Expected
fixture(1) resolved values equal
{
   intensity:  0.25
}
t.expectFixtureValue(fixture(1), { intensity: 0.25 })
65
Step
Desktop → configure with .desktop: Combined Preload
t.desktop.configure("Combined Preload")
67
Step
Add the PaneType.VirtualPlaybacks pane
desktop.addPane(
			PaneType.VirtualPlaybacks,
			{
				slug: "combined-preload",
				column: 1,
				row: 1,
				width: 12,
				height: 10,
			},
			{ rows: 1, columns: 2 },
		)
68
Step
Apply the configured Desktop layout.
desktop.apply()
79
Step
Virtual playback → assign source with $pane (result of desktopBuilder.addPane), "Virtual combined", 2.
t.virtualPlayback.assignSource(
			pane,
			"Virtual combined",
			2,
		)
80
Step
Start blind Preload programming.
t.preload.start()
86
Step
Execute the desk command "GROUP 1 AT 80".
t.command.execute("GROUP 1 AT 80")
87
Step
Playback → open.
t.playback.open()
88
Step
Playback → go with $physicalPlayback (result of recordSource).
t.playback.go(physicalPlayback)
89
Step
Virtual playback → activate with $pane (result of desktopBuilder.addPane), 2.
t.virtualPlayback.activate(pane, 2)
90
Expected
Preload → pending matching:
{
   groupIds:  [
    "1"
  ],
   playbackActions:  [
    [
      $physicalPlayback (result of recordSource),
       "go",
       {
         surface_id:  <unresolved: expect.any(String)>,
         control_id:  <unresolved: expect.any(Number)>
      }
    ],
     [
      $virtualPlayback (result of virtualPlayback.assignSource),
       "toggle",
       {
         surface_id:  <unresolved: expect.any(String)>,
         control_id:  <unresolved: expect.any(Number)>
      }
    ]
  ]
}
t.preload.expect.pendingMatching({ groupIds: ["1"], playbackActions: [
            [physicalPlayback, "go", { surface_id: expect.any(String), control_id: expect.any(Number) }],
            [virtualPlayback, "toggle", { surface_id: expect.any(String), control_id: expect.any(Number) }],
        ] })
91
Step
Preload → commit.
t.preload.commit()
96
Expected
Preload → atomic commit: "1",
[
  $physicalPlayback (result of recordSource),
   $virtualPlayback (result of virtualPlayback.assignSource)
]
t.preload.expect.atomicCommit("1", [
			physicalPlayback,
			virtualPlayback,
		])
97
Step
Advance the test clock by "1500ms".
t.clock.advanceBy("1500ms")
101
Expected
fixture(1) resolved values equal
{
   intensity:  0.8
}
t.expectFixtureValue(fixture(1), { intensity: 0.8 })
102
Expected
Playback → runtime: $physicalPlayback (result of recordSource),
{
   enabled:  true,
   current_cue_number:  "1"
}
t.playback.expect(physicalPlayback).runtime({
			enabled: true,
			current_cue_number: "1",
		})
103
Expected
Virtual playback → runtime: $virtualPlayback (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true,
     current:  {
       number:  "1"
    }
  }
}
t.virtualPlayback.expect.runtime(virtualPlayback, {
			runtime: {
				enabled: true,
				current: { number: "1" },
			},
		})
107
Step
Release blind Preload programming.
t.preload.release()
114
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
116
Expected
fixture(1) resolved values equal
{
   intensity:  0.25
}
t.expectFixtureValue(fixture(1), { intensity: 0.25 })
117
Expected
Playback → runtime: $physicalPlayback (result of recordSource),
{
   enabled:  true
}
t.playback.expect(physicalPlayback).runtime({ enabled: true })
118
Expected
Virtual playback → runtime: $virtualPlayback (result of virtualPlayback.assignSource),
{
   runtime:  {
     enabled:  true
  }
}
t.virtualPlayback.expect.runtime(virtualPlayback, {
			runtime: { enabled: true },
		})
119

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: expect.any(String)> Call expression expect.any(String) is dynamic and was not executed.92
unresolved-expressionExpected outcome<unresolved: expect.any(Number)> Call expression expect.any(Number) is dynamic and was not executed.92
unresolved-expressionExpected outcome<unresolved: expect.any(String)> Call expression expect.any(String) is dynamic and was not executed.93
unresolved-expressionExpected outcome<unresolved: expect.any(Number)> Call expression expect.any(Number) is dynamic and was not executed.93

MIB-001 — a dark fixture prepositions for its next lit Cue

tests/60-semantic-move-in-black.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICue runtimeMove in BlackPlaybacksResolved outputShow PatchShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
11
Open the ToskLight browser application.
t.app.open()
18
The ToskLight browser application is ready.
t.app.expect.ready()
19

Scenario contract

KindScenario contractLine
Step
Move in black → install with
{
   enabledFixture:  101,
   disabledFixture:  102,
   playback:  1,
   delay:  "1s"
}
t.moveInBlack.install({
			enabledFixture: 101,
			disabledFixture: 102,
			playback: 1,
			delay: "1s",
		})
12
Expected
Move in black → expect configuration: 101,
{
   enabled:  true,
   delay:  "1s"
}
t.moveInBlack.expectConfiguration(101, {
			enabled: true,
			delay: "1s",
		})
21
Expected
Move in black → expect configuration: 102,
{
   enabled:  false,
   delay:  "1s"
}
t.moveInBlack.expectConfiguration(102, {
			enabled: false,
			delay: "1s",
		})
25
Step
Move in black → ui → select fixture with 101.
t.moveInBlack.via.ui.selectFixture(101)
29
Step
Move in black → ui → set enabled with 101, false.
t.moveInBlack.via.ui.setEnabled(101, false)
30
Step
Move in black → ui → set enabled with 101, true.
t.moveInBlack.via.ui.setEnabled(101, true)
31
Step
Move in black → ui → set delay with 101, "1200ms".
t.moveInBlack.via.ui.setDelay(101, "1200ms")
32
Step
Move in black → ui → set delay with 101, "1s".
t.moveInBlack.via.ui.setDelay(101, "1s")
33
Step
Move in black → reopen patch.
t.moveInBlack.reopenPatch()
34
Expected
Move in black → expect configuration: 101,
{
   enabled:  true,
   delay:  "1s"
}
t.moveInBlack.expectConfiguration(101, {
			enabled: true,
			delay: "1s",
		})
35
Step
Move in black → reset.
t.moveInBlack.reset()
40
Step
Playback → open.
t.playback.open()
41
Step
Playback → go with
{
   page:  1,
   position:  1
}
t.playback.go({ page: 1, position: 1 })
42
Step
Playback → go with
{
   page:  1,
   position:  1
}
t.playback.go({ page: 1, position: 1 })
43
Step
Advance the test clock by "1999ms".
t.clock.advanceBy("1999ms")
47
Expected
fixture(101) resolved values equal
{
   "position:pan":  <unresolved: -161.918>
}
t.expectFixtureValue(fixture(101), { "position:pan": -161.918 })
48
Expected
Move in black → expect state: 101,
{
   state:  "delaying",
   currentCue:  "2",
   targetCue:  "3"
}
t.moveInBlack.expectState(101, {
			state: "delaying",
			currentCue: "2",
			targetCue: "3",
		})
49
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
55
Expected
fixture(101) resolved values equal
{
   intensity:  0,
   "position:pan":  <unresolved: -162>
}
t.expectFixtureValue(fixture(101), { intensity: 0, "position:pan": -162 })
56
Expected
Move in black → expect state: 101,
{
   state:  "delaying",
   currentCue:  "2",
   targetCue:  "3"
}
t.moveInBlack.expectState(101, {
			state: "delaying",
			currentCue: "2",
			targetCue: "3",
		})
57
Expected
Move in black → expect safety delay: 101, "1s".
t.moveInBlack.expectSafetyDelay(101, "1s")
62
Expected
Move in black → expect state: 102,
{
   state:  "disabled",
   currentCue:  "2",
   targetCue:  "3"
}
t.moveInBlack.expectState(102, {
			state: "disabled",
			currentCue: "2",
			targetCue: "3",
		})
63
Step
Advance the test clock by "999ms".
t.clock.advanceBy("999ms")
70
Expected
fixture(101) resolved values equal
{
   "position:pan":  <unresolved: -161.918>
}
t.expectFixtureValue(fixture(101), { "position:pan": -161.918 })
71
Step
Advance the test clock by "1ms".
t.clock.advanceBy("1ms")
72
Expected
Move in black → expect state: 101,
{
   state:  "moving",
   currentCue:  "2",
   targetCue:  "3"
}
t.moveInBlack.expectState(101, {
			state: "moving",
			currentCue: "2",
			targetCue: "3",
		})
73
Expected
fixture(101) resolved values equal
{
   "position:pan":  <unresolved: -161.811>
}
t.expectFixtureValue(fixture(101), { "position:pan": -161.811 })
78
Step
Advance the test clock by "1500ms".
t.clock.advanceBy("1500ms")
80
Expected
fixture(101) resolved values equal
{
   intensity:  0,
   "position:pan":  0.149
}
t.expectFixtureValue(fixture(101), { intensity: 0, "position:pan": 0.149 })
81
Expected
fixture(102) resolved values equal
{
   "position:pan":  <unresolved: -162>
}
t.expectFixtureValue(fixture(102), { "position:pan": -162 })
82
Step
Advance the test clock by "1500ms".
t.clock.advanceBy("1500ms")
83
Expected
fixture(101) resolved values equal
{
   intensity:  0,
   "position:pan":  162
}
t.expectFixtureValue(fixture(101), { intensity: 0, "position:pan": 162 })
84
Expected
fixture(102) resolved values equal
{
   "position:pan":  <unresolved: -162>
}
t.expectFixtureValue(fixture(102), { "position:pan": -162 })
85
Expected
Move in black → expect state: 101,
{
   state:  "completed",
   currentCue:  "2",
   targetCue:  "3"
}
t.moveInBlack.expectState(101, {
			state: "completed",
			currentCue: "2",
			targetCue: "3",
		})
86
Step
Playback → go with
{
   page:  1,
   position:  1
}
t.playback.go({ page: 1, position: 1 })
92
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
93
Expected
fixture(101) resolved values equal
{
   "position:pan":  162
}
t.expectFixtureValue(fixture(101), { "position:pan": 162 })
94
Expected
fixture(102) resolved values equal
{
   "position:pan":  <unresolved: -162>
}
t.expectFixtureValue(fixture(102), { "position:pan": -162 })
95
Step
Advance the test clock by "1500ms".
t.clock.advanceBy("1500ms")
96
Expected
fixture(101) resolved values equal
{
   "position:pan":  162
}
t.expectFixtureValue(fixture(101), { "position:pan": 162 })
97
Expected
fixture(102) resolved values equal
{
   "position:pan":  0
}
t.expectFixtureValue(fixture(102), { "position:pan": 0 })
98

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: -161.918> Expression -161.918 is not statically resolved.48
unresolved-expressionExpected outcome<unresolved: -162> Expression -162 is not statically resolved.56
unresolved-expressionExpected outcome<unresolved: -161.918> Expression -161.918 is not statically resolved.71
unresolved-expressionExpected outcome<unresolved: -161.811> Expression -161.811 is not statically resolved.78
unresolved-expressionExpected outcome<unresolved: -162> Expression -162 is not statically resolved.82
unresolved-expressionExpected outcome<unresolved: -162> Expression -162 is not statically resolved.85
unresolved-expressionExpected outcome<unresolved: -162> Expression -162 is not statically resolved.95

PBK-001 — Set inspection resolves one playback identity and Close is mutation-free

tests/61-semantic-playback-configuration.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UIPlayback ConfigurationPlaybacksShow files
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
12
Open the ToskLight browser application.
t.app.open()
14
The ToskLight browser application is ready.
t.app.expect.ready()
15

Scenario contract

KindScenario contractLine
Step
Playback configuration → prepare inspection.
t.playbackConfiguration.prepareInspection()
13
Expected
Playback configuration → expect inspection without mutation: 1,
{
   address:  {
     page:  1,
     position:  1
  },
   targetType:  "cue_list",
   buttons:  [
    "go_minus",
     "go",
     "flash"
  ],
   buttonCount:  3,
   fader:  "master",
   hasFader:  true,
   color:  "#20c997"
}
t.playbackConfiguration.expectInspectionWithoutMutation(1, {
			address: {page:1,position:1},
			targetType: "cue_list",
			buttons: ["go_minus", "go", "flash"],
			buttonCount: 3,
			fader: "master",
			hasFader: true,
			color: "#20c997",
		})
16

Diagnostics

None.

PBK-002 — Cue List assignment, color, and None plus Apply clear are atomic

tests/61-semantic-playback-configuration.spec.ts:28 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIPlayback ConfigurationPlaybacksShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
32
Open the ToskLight browser application.
t.app.open()
34
The ToskLight browser application is ready.
t.app.expect.ready()
35

Scenario contract

KindScenario contractLine
Step
Playback configuration → prepare assignment.
t.playbackConfiguration.prepareAssignment()
33
Step
Playback configuration → assign cue list with 1, "Configured Sequence", "#8b5cf6".
t.playbackConfiguration.assignCueList(
			1,
			"Configured Sequence",
			"#8b5cf6",
		)
36
Expected
Playback configuration → expect assignment: 1,
{
   targetType:  "cue_list",
   cueList:  "Configured Sequence",
   buttons:  [
    "go_minus",
     "go",
     "flash"
  ],
   buttonCount:  3,
   fader:  "master",
   hasFader:  true,
   color:  "#8b5cf6"
}
t.playbackConfiguration.expectAssignment(1, {
			targetType: "cue_list",
			cueList: "Configured Sequence",
			buttons: ["go_minus", "go", "flash"],
			buttonCount: 3,
			fader: "master",
			hasFader: true,
			color: "#8b5cf6",
		})
41
Step
Playback configuration → clear with 1.
t.playbackConfiguration.clear(1)
50
Expected
Playback configuration → expect unassigned: 1.
t.playbackConfiguration.expectUnassigned(1)
51
Expected
Playback configuration → expect cue list present: "Configured Sequence".
t.playbackConfiguration.expectCueListPresent("Configured Sequence")
52

Diagnostics

None.

PBK-003 — default navigation and remapped Select Contents dispatch one exact action

tests/61-semantic-playback-configuration.spec.ts:56 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UIPlayback ConfigurationPlaybacksShow files
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
60
Open the ToskLight browser application.
t.app.open()
62
The ToskLight browser application is ready.
t.app.expect.ready()
63

Scenario contract

KindScenario contractLine
Step
Playback configuration → prepare action matrix.
t.playbackConfiguration.prepareActionMatrix()
61
Step
Playback → go with
{
   page:  1,
   position:  1
}
t.playback.go({ page: 1, position: 1 })
64
Step
Playback → go with
{
   page:  1,
   position:  1
}
t.playback.go({ page: 1, position: 1 })
65
Step
Playback → go back with
{
   page:  1,
   position:  1
}
t.playback.goBack({ page: 1, position: 1 })
66
Expected
Playback → runtime:
{
   page:  1,
   position:  1
}
{
   current_cue_number:  "1"
}
t.playback.expect({ page: 1, position: 1 }).runtime({ current_cue_number: "1" })
67
Step
Playback configuration → set button with 1, "Top button", "Select contents".
t.playbackConfiguration.setButton(1, "Top button", "Select contents")
68
Expected
Playback configuration → expect assignment: 1,
{
   address:  {
     page:  1,
     position:  1
  },
   buttons:  [
    "select_contents",
     "go",
     "flash"
  ]
}
t.playbackConfiguration.expectAssignment(1, {
			address: {page:1,position:1},
			buttons: ["select_contents", "go", "flash"],
		})
69
Step
Playback configuration → select contents without playback mutation with 1, 1,
{
   fixtures:  [
    1,
     2
  ],
   group:  3
}
t.playbackConfiguration.selectContentsWithoutPlaybackMutation(1, 1, {
			fixtures: [1, 2],
			group: 3,
		})
73

Diagnostics

None.

PBK-004 — X-fade travel advances one Cue and preserves manual direction and timing

tests/61-semantic-playback-configuration.spec.ts:80 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICue runtimePlayback ConfigurationPlaybacksResolved outputShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
84
Open the ToskLight browser application.
t.app.open()
86
The ToskLight browser application is ready.
t.app.expect.ready()
87

Scenario contract

KindScenario contractLine
Step
Playback configuration → prepare crossfade.
t.playbackConfiguration.prepareCrossfade()
85
Step
Playback → fader with
{
   page:  1,
   position:  1
}
, 25.
t.playback.fader({ page: 1, position: 1 }, 25)
88
Expected
Playback → runtime:
{
   page:  1,
   position:  1
}
{
   current_cue_number:  "1",
   manual_xfade_position:  0.25,
   manual_xfade_progress:  0.25,
   manual_xfade_direction:  "towards_high"
}
t.playback.expect({ page: 1, position: 1 }).runtime({
			current_cue_number: "1",
			manual_xfade_position: 0.25,
			manual_xfade_progress: 0.25,
			manual_xfade_direction: "towards_high",
		})
89
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
96
Expected
fixture(1) resolved values equal
{
   intensity:  0.25
}
t.expectFixtureValue(fixture(1), { intensity: 0.25 })
97
Step
Playback → fader with
{
   page:  1,
   position:  1
}
, 100.
t.playback.fader({ page: 1, position: 1 }, 100)
98
Expected
Playback → runtime:
{
   page:  1,
   position:  1
}
{
   current_cue_number:  "2",
   manual_xfade_position:  1,
   manual_xfade_direction:  "towards_low"
}
t.playback.expect({ page: 1, position: 1 }).runtime({
			current_cue_number: "2",
			manual_xfade_position: 1,
			manual_xfade_direction: "towards_low",
		})
99
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
104
Expected
fixture(1) resolved values equal
{
   intensity:  1
}
t.expectFixtureValue(fixture(1), { intensity: 1 })
105
Expected
Cue → metadata:
{
   page:  1,
   position:  1
}
, 1,
{
   fade_millis:  30000,
   delay_millis:  10000
}
t.cue
			.expect({ page: 1, position: 1 }, 1)
			.metadata({ fade_millis: 30_000, delay_millis: 10_000 })
106
Expected
Cue → metadata:
{
   page:  1,
   position:  1
}
, 2,
{
   fade_millis:  30000,
   delay_millis:  10000
}
t.cue
			.expect({ page: 1, position: 1 }, 2)
			.metadata({ fade_millis: 30_000, delay_millis: 10_000 })
109

Diagnostics

None.

PBK-005 — Temp and held Swap have explicit lifetimes and restore the underlying playback

tests/61-semantic-playback-configuration.spec.ts:115 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIPlayback ConfigurationPlaybacksResolved outputShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
119
Open the ToskLight browser application.
t.app.open()
121
The ToskLight browser application is ready.
t.app.expect.ready()
122

Scenario contract

KindScenario contractLine
Step
Playback configuration → prepare temp and swap.
t.playbackConfiguration.prepareTempAndSwap()
120
Step
Playback → open.
t.playback.open()
123
Step
Playback → ui → temp with
{
   page:  1,
   position:  2
}
t.playback.via.ui.temp({ page: 1, position: 2 })
124
Expected
Playback configuration → expect temporary: 2, true.
t.playbackConfiguration.expectTemporary(2, true)
125
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
126
Expected
fixture(1) resolved values equal
{
   intensity:  0.8
}
t.expectFixtureValue(fixture(1), { intensity: 0.8 })
127
Expected
fixture(2) resolved values equal
{
   intensity:  0.6
}
t.expectFixtureValue(fixture(2), { intensity: 0.6 })
128
Expected
fixture(3) resolved values equal
{
   intensity:  0.4
}
t.expectFixtureValue(fixture(3), { intensity: 0.4 })
129
Step
Playback → ui → temp with
{
   page:  1,
   position:  2
}
t.playback.via.ui.temp({ page: 1, position: 2 })
130
Expected
Playback configuration → expect temporary: 2, false.
t.playbackConfiguration.expectTemporary(2, false)
131
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
132
Expected
fixture(1) resolved values equal
{
   intensity:  0.3
}
t.expectFixtureValue(fixture(1), { intensity: 0.3 })
133
Step
Playback → ui → swap → hold with
{
   page:  1,
   position:  2
}
, <generated: callback>.
t.playback.via.ui.swap({ page: 1, position: 2 }).hold(async () => {
			await t.playbackConfiguration.expectSwap(2, true);
			await t.clock.advanceBy("0ms");
			await t.expectFixtureValue(fixture(1), { intensity: 0.8 });
			await t.expectFixtureValue(fixture(2), { intensity: 0 });
			await t.expectFixtureValue(fixture(3), { intensity: 0.4 });
		})
135
Expected
Playback configuration → expect swap: 2, true.
t.playbackConfiguration.expectSwap(2, true)
136
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
137
Expected
fixture(1) resolved values equal
{
   intensity:  0.8
}
t.expectFixtureValue(fixture(1), { intensity: 0.8 })
138
Expected
fixture(2) resolved values equal
{
   intensity:  0
}
t.expectFixtureValue(fixture(2), { intensity: 0 })
139
Expected
fixture(3) resolved values equal
{
   intensity:  0.4
}
t.expectFixtureValue(fixture(3), { intensity: 0.4 })
140
Expected
Playback configuration → expect swap: 2, false.
t.playbackConfiguration.expectSwap(2, false)
142
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
143
Expected
fixture(1) resolved values equal
{
   intensity:  0.3
}
t.expectFixtureValue(fixture(1), { intensity: 0.3 })
144
Expected
fixture(2) resolved values equal
{
   intensity:  0.6
}
t.expectFixtureValue(fixture(2), { intensity: 0.6 })
145
Expected
fixture(3) resolved values equal
{
   intensity:  0.4
}
t.expectFixtureValue(fixture(3), { intensity: 0.4 })
146
Expected
Playback → runtime:
{
   page:  1,
   position:  1
}
{
   enabled:  true
}
t.playback.expect({ page: 1, position: 1 }).runtime({ enabled: true })
147
Expected
Playback → runtime:
{
   page:  1,
   position:  3
}
{
   enabled:  true
}
t.playback.expect({ page: 1, position: 3 }).runtime({ enabled: true })
148
Expected
Playback → runtime:
{
   page:  1,
   position:  4
}
{
   enabled:  true
}
t.playback.expect({ page: 1, position: 4 }).runtime({ enabled: true })
149

Diagnostics

None.

PBK-006 — specialized layouts control their authoritative Speed, Group, Grand, and Fade masters

tests/61-semantic-playback-configuration.spec.ts:153 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIPlayback ConfigurationPlaybacksShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
157
Open the ToskLight browser application.
t.app.open()
159
The ToskLight browser application is ready.
t.app.expect.ready()
160

Scenario contract

KindScenario contractLine
Step
Playback configuration → prepare masters.
t.playbackConfiguration.prepareMasters()
158
Step
Playback configuration → press with 1, "DOUBLE".
t.playbackConfiguration.press(1, "DOUBLE")
161
Step
Playback configuration → set slot fader with 1, 0.5.
t.playbackConfiguration.setSlotFader(1, 0.5)
162
Step
Playback configuration → set slot fader with 2, 0.4.
t.playbackConfiguration.setSlotFader(2, 0.4)
163
Step
Playback configuration → press with 2, "SELECT".
t.playbackConfiguration.press(2, "SELECT")
164
Step
Playback configuration → set slot fader with 3, 0.3.
t.playbackConfiguration.setSlotFader(3, 0.3)
165
Step
Playback configuration → press with 3, "BLACKOUT".
t.playbackConfiguration.press(3, "BLACKOUT")
166
Step
Playback configuration → set slot fader with 4, 0.25.
t.playbackConfiguration.setSlotFader(4, 0.25)
167
Step
Playback configuration → set slot fader with 5, 0.25.
t.playbackConfiguration.setSlotFader(5, 0.25)
168
Expected
Playback configuration → expect masters:
{
   speed:  {
     manualBpm:  240,
     effectiveBpm:  120,
     paused:  false
  },
   neighborBpms:  [
    96,
     72,
     60,
     48
  ],
   group:  {
     master:  0.4,
     flashLevel:  0
  },
   grand:  {
     level:  0.3,
     effectiveLevel:  0.3,
     blackout:  true,
     dynamicsPaused:  false
  },
   programmerFadeMillis:  5000,
   cueFadeMillis:  15000
}
t.playbackConfiguration.expectMasters({
			speed: { manualBpm: 240, effectiveBpm: 120, paused: false },
			neighborBpms: [96, 72, 60, 48],
			group: { master: 0.4, flashLevel: 0 },
			grand: {
				level: 0.3,
				effectiveLevel: 0.3,
				blackout: true,
				dynamicsPaused: false,
			},
			programmerFadeMillis: 5_000,
			cueFadeMillis: 15_000,
		})
169
Expected
Playback configuration → expect assignment: 1,
{
   address:  {
     page:  1,
     position:  1
  },
   targetType:  "speed_group",
   buttons:  [
    "double",
     "half",
     "learn"
  ],
   fader:  "learned_percentage",
   color:  "#8b5cf6"
}
t.playbackConfiguration.expectAssignment(1, {
			address: {page:1,position:1},
			targetType: "speed_group",
			buttons: ["double", "half", "learn"],
			fader: "learned_percentage",
			color: "#8b5cf6",
		})
182
Expected
Playback configuration → expect assignment: 2,
{
   address:  {
     page:  1,
     position:  2
  },
   targetType:  "group"
}
t.playbackConfiguration.expectAssignment(2, {
			address: {page:1,position:2},
			targetType: "group",
		})
189
Expected
Playback configuration → expect assignment: 3,
{
   address:  {
     page:  1,
     position:  3
  },
   targetType:  "grand_master"
}
t.playbackConfiguration.expectAssignment(3, {
			address: {page:1,position:3},
			targetType: "grand_master",
		})
193

Diagnostics

None.

PBK-006 — independent overlapping Group Masters use the highest assigned level

tests/61-semantic-playback-configuration.spec.ts:200 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputGroupsPlayback ConfigurationPlaybacksSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
204
Open the ToskLight browser application.
t.app.open()
206
The ToskLight browser application is ready.
t.app.expect.ready()
207

Scenario contract

KindScenario contractLine
Step
Playback configuration → clear page.
t.playbackConfiguration.clearPage()
205
Step
Selection → fixtures → api → items with 1, 2, 3, 4, 5, 6.
t.selection.fixtures.via.api.items(1, 2, 3, 4, 5, 6)
209
Step
Group → api → store with 5,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(5, { mode: GroupStoreMode.Overwrite })
210
Step
Selection → fixtures → api → items with 1, 3, 5.
t.selection.fixtures.via.api.items(1, 3, 5)
211
Step
Group → api → store with 6,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(6, { mode: GroupStoreMode.Overwrite })
212
Step
Selection → fixtures → api → items with 2, 4, 6.
t.selection.fixtures.via.api.items(2, 4, 6)
213
Step
Group → api → store with 7,
{
   mode:  GroupStoreMode.Overwrite
}
t.group.via.api.store(7, { mode: GroupStoreMode.Overwrite })
214
Step
Clear the current selection.
t.selection.clear()
215
Step
Playback configuration → assign group master with 1, 6.
t.playbackConfiguration.assignGroupMaster(1, 6)
217
Step
Playback configuration → assign group master with 2, 7.
t.playbackConfiguration.assignGroupMaster(2, 7)
218
Step
Execute the desk command "GROUP 7 AT 100".
t.command.execute("GROUP 7 AT 100")
219
Step
Playback configuration → set slot fader with 2, 0.8.
t.playbackConfiguration.setSlotFader(2, 0.8)
220
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
221
Expected
fixture(1) DMX equals
{
   Intensity:  0
}
t.expectFixtureDMX(fixture(1), { Intensity: 0 })
222
Expected
fixture(2) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixture(2), { Intensity: 204 })
223
Expected
fixture(4) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixture(4), { Intensity: 204 })
224
Expected
fixture(6) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixture(6), { Intensity: 204 })
225
Step
Playback configuration → assign group master with 3, 5.
t.playbackConfiguration.assignGroupMaster(3, 5)
227
Step
Playback configuration → set slot fader with 3, 0.6.
t.playbackConfiguration.setSlotFader(3, 0.6)
228
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
229
Expected
fixture(2) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixture(2), { Intensity: 204 })
230
Expected
fixture(4) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixture(4), { Intensity: 204 })
231
Expected
fixture(6) DMX equals
{
   Intensity:  204
}
t.expectFixtureDMX(fixture(6), { Intensity: 204 })
232
Step
Playback configuration → assign grand master with 4.
t.playbackConfiguration.assignGrandMaster(4)
234
Step
Playback configuration → set slot fader with 4, 0.5.
t.playbackConfiguration.setSlotFader(4, 0.5)
235
Step
Advance the test clock by "0ms".
t.clock.advanceBy("0ms")
236
Expected
fixture(2) DMX equals
{
   Intensity:  102
}
t.expectFixtureDMX(fixture(2), { Intensity: 102 })
237
Expected
fixture(4) DMX equals
{
   Intensity:  102
}
t.expectFixtureDMX(fixture(4), { Intensity: 102 })
238
Expected
fixture(6) DMX equals
{
   Intensity:  102
}
t.expectFixtureDMX(fixture(6), { Intensity: 102 })
239

Diagnostics

None.

TIME-001 — zero ticks emit current state without advancing behavior time

tests/62-semantic-time-persistence-and-recovery.spec.ts:13 · migrated-semantic-world · last run: not merged

show: Twelve DimmersAttached hardwareBrowser UICue timingDMX outputDesktop layoutEncoder controlsOSCProgrammerProgrammer timingSelectionSemantic oracleShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
17
Open the ToskLight browser application.
t.app.open()
18
The ToskLight browser application is ready.
t.app.expect.ready()
19

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Time and recovery programming
t.desktop.configure("Time and recovery programming")
121
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
122
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
129
Step
Apply the configured Desktop layout.
desktop.apply()
136
Step
Timing → programmer fade → api → set with "0ms".
t.timing.programmerFade.via.api.set("0ms")
21
Step
Selection → fixtures → ui → item with 1.
t.selection.fixtures.via.ui.item(1)
22
Step
Encoder → intensity → dimmer → ui → set with 50.
t.encoder.intensity.dimmer.via.ui.set(50)
23
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
24
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
26
Step
Advance the test clock by one deterministic step.
t.clock.advanceStep()
27
Expected
$second.now (from clock.advanceStep) is $first.now (from clock.advanceStep).
expect(second.now).toBe(first.now)
28
Expected
fixture(1) DMX equals
{
   Intensity:  128
}
t.expectFixtureDMX(fixture(1), { Intensity: 128 })
29
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
31

Diagnostics

None.

TIME-002 — absolute fixture Set Value follows Programmer Fade at every timing boundary

tests/62-semantic-time-persistence-and-recovery.spec.ts:36 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICue timingDMX outputDesktop layoutEncoder controlsProgrammerProgrammer timingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
40
Open the ToskLight browser application.
t.app.open()
41
The ToskLight browser application is ready.
t.app.expect.ready()
42

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Time and recovery programming
t.desktop.configure("Time and recovery programming")
121
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
122
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
129
Step
Apply the configured Desktop layout.
desktop.apply()
136
Step
Programmer Fade → command-line AT fade is true.
t.timing.programmerFade.setCommandLineAtEnabled(true)
44
Step
Timing → programmer fade → api → set with "3s".
t.timing.programmerFade.via.api.set("3s")
45
Step
Selection → fixtures → ui → item with 1.
t.selection.fixtures.via.ui.item(1)
46
Step
Encoder → intensity → dimmer → ui → set with 0.
t.encoder.intensity.dimmer.via.ui.set(0)
47
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
48
Step
Encoder → intensity → dimmer → ui → set with 100.
t.encoder.intensity.dimmer.via.ui.set(100)
49
Step
Clock → at with
[
  {
     name:  "start",
     at:  "0ms"
  },
   {
     name:  "midpoint",
     at:  "1.5s"
  },
   {
     name:  "complete",
     at:  "3s"
  }
]
, <generated: callback>.
t.clock.at(
			[
				{ name: "start", at: "0ms" },
				{ name: "midpoint", at: "1.5s" },
				{ name: "complete", at: "3s" },
			],
			async ({ name }) => {
				await t.expectFixtureDMX(fixture(1), {
					Intensity: name === "start" ? 0 : name === "midpoint" ? 128 : 255,
				});
			},
		)
50
Expected
fixture(1) DMX equals
{
   Intensity:  <unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255>
}
t.expectFixtureDMX(fixture(1), {
					Intensity: name === "start" ? 0 : name === "midpoint" ? 128 : 255,
				})
57

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255> Expression name === "start" ? 0 : name === "midpoint" ? 128 : 255 is not statically resolved.58

TIME-002 — absolute Group Set Value follows Programmer Fade for every ordered member

tests/62-semantic-time-persistence-and-recovery.spec.ts:65 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UICue timingDMX outputDesktop layoutEncoder controlsPool UIProgrammerProgrammer timingSelectionShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
69
Open the ToskLight browser application.
t.app.open()
70
The ToskLight browser application is ready.
t.app.expect.ready()
71

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Time and recovery programming
t.desktop.configure("Time and recovery programming")
121
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
122
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
129
Step
Apply the configured Desktop layout.
desktop.apply()
136
Step
Programmer Fade → command-line AT fade is true.
t.timing.programmerFade.setCommandLineAtEnabled(true)
73
Step
Timing → programmer fade → api → set with "3s".
t.timing.programmerFade.via.api.set("3s")
74
Step
Selection → groups → pool → item with 3.
t.selection.groups.via.pool.item(3)
75
Step
Encoder → intensity → dimmer → ui → set with 0.
t.encoder.intensity.dimmer.via.ui.set(0)
76
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
77
Step
Encoder → intensity → dimmer → ui → set with 100.
t.encoder.intensity.dimmer.via.ui.set(100)
78
Step
Clock → at with
[
  {
     name:  "start",
     at:  "0ms"
  },
   {
     name:  "midpoint",
     at:  "1.5s"
  },
   {
     name:  "complete",
     at:  "3s"
  }
]
, <generated: callback>.
t.clock.at(
			[
				{ name: "start", at: "0ms" },
				{ name: "midpoint", at: "1.5s" },
				{ name: "complete", at: "3s" },
			],
			async ({ name }) => {
				for (const number of [1, 2, 3, 4])
					await t.expectFixtureDMX(fixture(number), {
						Intensity: name === "start" ? 0 : name === "midpoint" ? 128 : 255,
					});
			},
		)
79
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255>
}
t.expectFixtureDMX(fixture(number), {
						Intensity: name === "start" ? 0 : name === "midpoint" ? 128 : 255,
					})
87
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255>
}
t.expectFixtureDMX(fixture(number), {
						Intensity: name === "start" ? 0 : name === "midpoint" ? 128 : 255,
					})
87
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255>
}
t.expectFixtureDMX(fixture(number), {
						Intensity: name === "start" ? 0 : name === "midpoint" ? 128 : 255,
					})
87
Expected
fixture(number) DMX equals
{
   Intensity:  <unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255>
}
t.expectFixtureDMX(fixture(number), {
						Intensity: name === "start" ? 0 : name === "midpoint" ? 128 : 255,
					})
87

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionExpected outcome<unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255> Expression name === "start" ? 0 : name === "midpoint" ? 128 : 255 is not statically resolved.88
unresolved-expressionExpected outcome<unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255> Expression name === "start" ? 0 : name === "midpoint" ? 128 : 255 is not statically resolved.88
unresolved-expressionExpected outcome<unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255> Expression name === "start" ? 0 : name === "midpoint" ? 128 : 255 is not statically resolved.88
unresolved-expressionExpected outcome<unresolved: name === "start" ? 0 : name === "midpoint" ? 128 : 255> Expression name === "start" ? 0 : name === "midpoint" ? 128 : 255 is not statically resolved.88

SHOW-001 — operator programming and a named revision survive an abrupt restart

tests/62-semantic-time-persistence-and-recovery.spec.ts:95 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIDesktop layoutEncoder controlsGroupsPool UIProgrammerSelectionShow files
Preconditions (5)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
99
Open the ToskLight browser application.
t.app.open()
100
The ToskLight browser application is ready.
t.app.expect.ready()
101
Save a named show revision "SHOW-001 before restart".
t.show.saveRevision("SHOW-001 before restart")
107
The ToskLight browser application is ready.
t.app.expect.ready()
109

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Time and recovery programming
t.desktop.configure("Time and recovery programming")
121
Step
Add the PaneType.Fixtures pane
desktop.addPane(PaneType.Fixtures, {
		slug: "fixtures",
		column: 1,
		row: 1,
		width: 12,
		height: 18,
	})
122
Step
Add the PaneType.Groups pane
desktop.addPane(PaneType.Groups, {
		slug: "groups",
		column: 13,
		row: 1,
		width: 12,
		height: 18,
	})
129
Step
Apply the configured Desktop layout.
desktop.apply()
136
Step
Selection → fixtures → ui → items with 5, 6.
t.selection.fixtures.via.ui.items(5, 6)
103
Step
Group → pool → store with 3,
{
   mode:  StoreMode.Merge
}
t.group.via.pool.store(3, { mode: StoreMode.Merge })
104
Step
Selection → targets with group(3).
t.selection.targets(group(3))
105
Step
Encoder → intensity → dimmer → ui → set with 40.
t.encoder.intensity.dimmer.via.ui.set(40)
106
Step
Show → restart with RestartMode.Abrupt.
t.show.restart(RestartMode.Abrupt)
108
Expected
Group → fixtures: 3, 1, 2, 3, 4, 5, 6.
t.group.expect(3).fixtures(1, 2, 3, 4, 5, 6)
110
Expected
Show → revision matches
{
   number:  $revision (result of show.saveRevision),
   name:  "SHOW-001 before restart"
}
t.show.expect.revision({
			number: revision,
			name: "SHOW-001 before restart",
		})
111

Diagnostics

None.

SHOW-003 — a malformed active show remains intact while the operator recovers safely

tests/62-semantic-time-persistence-and-recovery.spec.ts:139 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIShow files
Preconditions (2)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
143
Open the ToskLight browser application.
t.app.open()
144

Scenario contract

KindScenario contractLine
Step
Show → recovery → prepare malformed active.
t.show.recovery.prepareMalformedActive()
145
Expected
Show → recovery required.
t.show.expect.recoveryRequired()
146
Step
Show → load clean default.
t.show.loadCleanDefault()
147
Expected
Show → recovered.
t.show.expect.recovered()
148

Diagnostics

None.

SHOW-005 — named revisions load as durable, visibly independent copies

tests/62-semantic-time-persistence-and-recovery.spec.ts:152 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIGroupsSelectionShow filesTyped API
Preconditions (8)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
156
Open the ToskLight browser application.
t.app.open()
157
The ToskLight browser application is ready.
t.app.expect.ready()
158
Save the active show as "SHOW-005 source <generated: UUID>".
t.show.saveAs(`SHOW-005 source ${crypto.randomUUID()}`)
159
Save a named show revision "SHOW-005 named revision".
t.show.saveRevision("SHOW-005 named revision")
160
Save the active show as "SHOW-005 changed <generated: UUID>".
t.show.saveAs(`SHOW-005 changed ${crypto.randomUUID()}`)
163
Load revision $revision (result of show.saveRevision) of $source (result of show.saveAs).
t.show.loadRevision(source, revision)
165
Save the active show.
t.show.save()
168

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → items with 5, 6.
t.selection.fixtures.via.api.items(5, 6)
161
Step
Group → api → store with 3,
{
   mode:  StoreMode.Merge
}
t.group.via.api.store(3, { mode: StoreMode.Merge })
162
Expected
Show → active is the saved show copy.
t.show.expect.active(changed)
164
Expected
Show → active is the loaded revision copy.
t.show.expect.active(revisionCopy)
166
Expected
Group → fixtures: 3, 1, 2, 3, 4.
t.group.expect(3).fixtures(1, 2, 3, 4)
167
Expected
Show → active is the loaded revision copy.
t.show.expect.active(revisionCopy)
169

Diagnostics

None.

MANUAL-019 — saved workspaces are Desktops while physical control surfaces remain desks

tests/63-semantic-operator-shell.spec.ts:6 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIOperator shellShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
10
Open the ToskLight browser application.
t.app.open()
11
The ToskLight browser application is ready.
t.app.expect.ready()
12

Scenario contract

KindScenario contractLine
Expected
Operator shell → expect desktop and desk terminology.
t.operatorShell.expectDesktopAndDeskTerminology()
13

Diagnostics

None.

MANUAL-019 — fixture browsers share title-bar search and readable name/detail alignment

tests/63-semantic-operator-shell.spec.ts:17 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIOperator shellShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
21
Open the ToskLight browser application.
t.app.open()
22
The ToskLight browser application is ready.
t.app.expect.ready()
23

Scenario contract

KindScenario contractLine
Expected
Operator shell → expect fixture browser alignment.
t.operatorShell.expectFixtureBrowserAlignment()
24

Diagnostics

None.

MANUAL-019 — every operator file field uses its confined extension contract

tests/63-semantic-operator-shell.spec.ts:28 · migrated-semantic-world · last run: not merged

show: Twelve DimmersBrowser UIOperator shellShow files
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
32
Open the ToskLight browser application.
t.app.open()
33
The ToskLight browser application is ready.
t.app.expect.ready()
34

Scenario contract

KindScenario contractLine
Expected
Operator shell → expect operator file picker contracts.
t.operatorShell.expectOperatorFilePickerContracts()
35

Diagnostics

None.

COMMAND-HISTORY-001 — Command Line history shows accepted and rejected desk commands once

tests/64-semantic-operator-controls.spec.ts:8 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICommand lineShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Expected
Command → history → expect accepted and rejected.
t.command.history.expectAcceptedAndRejected()
15

Diagnostics

None.

PROG-002 — software encoder value dialog spreads a two-point range over the ordered selection

tests/64-semantic-operator-controls.spec.ts:19 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputEncoder controlsProgrammerShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
23
Open the ToskLight browser application.
t.app.open()
24
The ToskLight browser application is ready.
t.app.expect.ready()
25

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 1 THRU 5".
t.command.execute("FIXTURE 1 THRU 5")
26
Step
Encoder → intensity → dimmer → ui → set with
[
  0,
   ProgrammerToken.Thru,
   50
]
t.encoder.intensity.dimmer.via.ui.set([
			0,
			ProgrammerToken.Thru,
			50,
		])
27
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
32
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 0
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
34
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 32
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
34
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 64
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
34
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 96
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
34
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 128
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
34

Diagnostics

None.

PROG-002 — software encoder value dialog lands a multi-point intensity spread once over the ordered selection

tests/64-semantic-operator-controls.spec.ts:38 · migrated-semantic-world · last run: not merged

show: Compact RigBrowser UICommand lineDMX outputEncoder controlsProgrammerShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
42
Open the ToskLight browser application.
t.app.open()
43
The ToskLight browser application is ready.
t.app.expect.ready()
44

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 1 THRU 5".
t.command.execute("FIXTURE 1 THRU 5")
45
Step
Encoder → intensity → dimmer → ui → set with
[
  100,
   ProgrammerToken.Thru,
   0,
   ProgrammerToken.Thru,
   100
]
t.encoder.intensity.dimmer.via.ui.set([
			100,
			ProgrammerToken.Thru,
			0,
			ProgrammerToken.Thru,
			100,
		])
46
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
53
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 255
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
55
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 128
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
55
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 0
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
55
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 128
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
55
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 255
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
55

Diagnostics

None.

PROG-002 — software encoder value dialog spreads a multi-point Pan over the ordered moving-head selection

tests/64-semantic-operator-controls.spec.ts:59 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UICommand lineDMX outputEncoder controlsProgrammerShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
63
Open the ToskLight browser application.
t.app.open()
64
The ToskLight browser application is ready.
t.app.expect.ready()
65

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 101 THRU 105".
t.command.execute("FIXTURE 101 THRU 105")
66
Step
Encoder → position → pan → ui → set with
[
  270,
   ProgrammerToken.Thru,
   <unresolved: -270>,
   ProgrammerToken.Thru,
   270
]
t.encoder.position.pan.via.ui.set([
			270,
			ProgrammerToken.Thru,
			-270,
			ProgrammerToken.Thru,
			270,
		])
68
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
75
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 255
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
77
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 128
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
77
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 0
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
77
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 128
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
77
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 255
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
77

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionStep<unresolved: -270> Expression -270 is not statically resolved.71

ENCODER-DISPLAY-001 — OSC NAV wraps families while non-first encoder turn, held-turn, and click follow the displayed cell

tests/64-semantic-operator-controls.spec.ts:83 · migrated-semantic-world · last run: not merged

show: Default StageAttached hardwareBrowser UICommand lineOSCShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
87
Open the ToskLight browser application.
t.app.open()
88
The ToskLight browser application is ready.
t.app.expect.ready()
89

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 101".
t.command.execute("FIXTURE 101")
90
Expected
Attached encoder → expect navigation and secondary encoder.
t.attachedEncoder.expectNavigationAndSecondaryEncoder()
91

Diagnostics

None.

PROG-002 — hardware encoder modal spreads a typed value over the ordered selection

tests/64-semantic-operator-controls.spec.ts:95 · migrated-semantic-world · last run: not merged

show: Compact RigAttached hardwareBrowser UICommand lineDMX outputOSCShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
99
Open the ToskLight browser application.
t.app.open()
100
The ToskLight browser application is ready.
t.app.expect.ready()
101

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 1 THRU 5".
t.command.execute("FIXTURE 1 THRU 5")
102
Expected
Attached encoder → expect typed intensity spread.
t.attachedEncoder.expectTypedIntensitySpread()
103
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
104
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 0
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
106
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 32
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
106
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 64
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
106
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 96
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
106
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 128
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
106

Diagnostics

None.

PROG-002 — hardware encoder modal lands a multi-point intensity spread once over the ordered selection

tests/64-semantic-operator-controls.spec.ts:110 · migrated-semantic-world · last run: not merged

show: Compact RigAttached hardwareBrowser UICommand lineDMX outputOSCShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.CompactRig show.
t.show.use(Show.CompactRig)
114
Open the ToskLight browser application.
t.app.open()
115
The ToskLight browser application is ready.
t.app.expect.ready()
116

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 1 THRU 5".
t.command.execute("FIXTURE 1 THRU 5")
117
Expected
Attached encoder → expect multi point intensity spread.
t.attachedEncoder.expectMultiPointIntensitySpread()
118
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
119
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 255
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
121
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 128
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
121
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 0
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
121
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 128
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
121
Expected
fixture(number + 1) DMX equals
{
   Intensity:  value = 255
}
t.expectFixtureDMX(fixture(number + 1), { Intensity: value })
121

Diagnostics

None.

PROG-002 — hardware encoder modal spreads a multi-point Pan over the ordered moving-head selection

tests/64-semantic-operator-controls.spec.ts:125 · migrated-semantic-world · last run: not merged

show: Default StageAttached hardwareBrowser UICommand lineDMX outputOSCShow filesTest clock
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
129
Open the ToskLight browser application.
t.app.open()
130
The ToskLight browser application is ready.
t.app.expect.ready()
131

Scenario contract

KindScenario contractLine
Step
Execute the desk command "FIXTURE 101 THRU 105".
t.command.execute("FIXTURE 101 THRU 105")
132
Expected
Attached encoder → expect multi point pan spread.
t.attachedEncoder.expectMultiPointPanSpread()
133
Step
Advance the test clock by "3s".
t.clock.advanceBy("3s")
134
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 255
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
136
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 128
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
136
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 0
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
136
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 128
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
136
Expected
fixture(number + 101) DMX equals
{
   Pan:  value = 255
}
t.expectFixtureDMX(fixture(number + 101), {
				Pan: value,
			})
136

Diagnostics

None.

POSITION-HOME-001 — Return Home applies per-head Position defaults as one programmer gesture

tests/65-semantic-special-dialogs-and-hardware-selection.spec.ts:6 · migrated-semantic-world · last run: not merged

show: Default StageAttached hardwareBrowser UICommand keypadOSCProgrammerSemantic oracleShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
10
Open the ToskLight browser application.
t.app.open()
11
The ToskLight browser application is ready.
t.app.expect.ready()
12

Scenario contract

KindScenario contractLine
Step
Special → position → prepare return home contract.
t.special.position.prepareReturnHomeContract()
13
Step
Special → position → return home.
t.special.position.returnHome()
15
Expected
Special → position → expect at home.
t.special.position.expectAtHome()
16
Step
Press keypad keys
[
  "SHIFT",
   "ESC",
   "SHIFT"
]
t.keypad.press(["SHIFT", "ESC", "SHIFT"])
17
Expected
Special → position → expect before return home.
t.special.position.expectBeforeReturnHome()
18
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
20
Step
Special → position → return home.
t.special.position.returnHome()
22
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
24
Expected
Special → position → expect at home.
t.special.position.expectAtHome()
26
Step
Press keypad keys
[
  "CLR"
]
t.keypad.press(["CLR"])
28
Expected
Selection.
t.expect.selection()
29
Expected
Special → position → expect unavailable.
t.special.position.expectUnavailable()
30

Diagnostics

None.

COLOR-RANGE-001 — Shift-drag applies an ordered Color range from software and attached hardware

tests/65-semantic-special-dialogs-and-hardware-selection.spec.ts:34 · migrated-semantic-world · last run: not merged

show: Default StageAttached hardwareBrowser UICommand keypadOSCProgrammerShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
38
Open the ToskLight browser application.
t.app.open()
39
The ToskLight browser application is ready.
t.app.expect.ready()
40

Scenario contract

KindScenario contractLine
Step
Special → color → prepare range contract.
t.special.color.prepareRangeContract()
41
Step
Special → color → set uniform.
t.special.color.setUniform()
43
Step
Press keypad keys
[
  "SHIFT",
   "ESC",
   "SHIFT"
]
t.keypad.press(["SHIFT", "ESC", "SHIFT"])
44
Expected
Special → color → expect prior.
t.special.color.expectPrior()
45
Step
Special → color → apply range with shift.
t.special.color.applyRangeWithShift()
47
Step
Press keypad keys
[
  "SHIFT",
   "ESC",
   "SHIFT"
]
t.keypad.press(["SHIFT", "ESC", "SHIFT"])
48
Expected
Special → color → expect prior.
t.special.color.expectPrior()
49
Step
Special → color → cancel range with shift.
t.special.color.cancelRangeWithShift()
50
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
52
Step
Special → color → apply range with hardware shift.
t.special.color.applyRangeWithHardwareShift()
54
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
56
Expected
Special → color → expect range.
t.special.color.expectRange()
58
Expected
Special → color → expect selection preserved.
t.special.color.expectSelectionPreserved()
59

Diagnostics

None.

PLAYBACK-SELECT-001 — an attached-hardware playback card selects its concrete Cuelist playback

tests/65-semantic-special-dialogs-and-hardware-selection.spec.ts:63 · migrated-semantic-world · last run: not merged

show: Default StageAttached hardwareBrowser UIEncoder controlsOSCPlaybacksProgrammerRecordingSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
67
Open the ToskLight browser application.
t.app.open()
68
The ToskLight browser application is ready.
t.app.expect.ready()
69

Scenario contract

KindScenario contractLine
Step
Selection → fixtures → api → item with 101.
t.selection.fixtures.via.api.item(101)
70
Step
Encoder → intensity → dimmer → api → set with 73.
t.encoder.intensity.dimmer.via.api.set(73)
71
Step
Record → playback with 1.
t.record.playback(1)
72
Step
Playback → name target cuelist with $playback (result of record.playback), "Front Cuelist".
t.playback.nameTargetCuelist(playback, "Front Cuelist")
73
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
74
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
76
Step
Playback → select from hardware card with $playback (result of record.playback).
t.playback.selectFromHardwareCard(playback)
78
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
80
Expected
Playback → selected: $playback (result of record.playback).
t.playback.expect(playback).selected()
82

Diagnostics

None.

STAGE-001 — Live and Follow Preload Stage panes retain independent operator configuration

tests/66-semantic-stage-visualizer.spec.ts:7 · migrated-semantic-world · last run: not merged

show: Default StageBrowser UIDesktop layoutShow files
Preconditions (3)
ContextLine
Use the isolated Show.DefaultStage show.
t.show.use(Show.DefaultStage)
11
Open the ToskLight browser application.
t.app.open()
12
The ToskLight browser application is ready.
t.app.expect.ready()
13

Scenario contract

KindScenario contractLine
Step
Desktop → configure with .desktop: Stage lane proof
t.desktop.configure("Stage lane proof")
15
Step
Add the PaneType.Stage pane
desktop.addPane(
			PaneType.Stage,
			{
				slug: "live-stage",
				column: 1,
				row: 1,
				width: 12,
				height: 18,
			},
			{ view: StageView.TwoDimensional, followPreload: false },
		)
16
Step
Add the PaneType.Stage pane
desktop.addPane(
			PaneType.Stage,
			{
				slug: "preload-stage",
				column: 13,
				row: 1,
				width: 12,
				height: 18,
			},
			{ view: StageView.TwoDimensional, followPreload: true },
		)
27
Step
Apply the configured Desktop layout.
desktop.apply()
38
Expected
Desktop builder → expect stage pane: $live (result of desktopBuilder.addPane),
{
   lane:  "live",
   view:  StageView.TwoDimensional,
   followPreload:  false,
   nativeRendererAvailable:  false
}
desktop.expectStagePane(live, {
			lane: "live",
			view: StageView.TwoDimensional,
			followPreload: false,
			nativeRendererAvailable: false,
		})
40
Expected
Desktop builder → expect stage pane: $preload (result of desktopBuilder.addPane),
{
   lane:  "preload",
   view:  StageView.TwoDimensional,
   followPreload:  true,
   nativeRendererAvailable:  false
}
desktop.expectStagePane(preload, {
			lane: "preload",
			view: StageView.TwoDimensional,
			followPreload: true,
			nativeRendererAvailable: false,
		})
46

Diagnostics

None.

PERF-PROGRAMMER-001 — programmer actions acknowledge and reach their first output frame within the output-tick budget

tests/77-programmer-action-latency.spec.ts:8 · unresolved · last run: not merged

show: Twelve DimmersAttached hardwareBrowser UICommand keypadCommand lineDMX outputEncoder controlsOSCPresetsProgrammerSelectionShow filesTyped API
Preconditions (3)
ContextLine
Use the isolated Show.TwelveDimmers show.
t.show.use(Show.TwelveDimmers)
12
Open the ToskLight browser application.
t.app.open()
13
The ToskLight browser application is ready.
t.app.expect.ready()
14

Scenario contract

KindScenario contractLine
Step
Command → api → type with "FIXTURE 1".
t.command.via.api.type("FIXTURE 1")
24
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
33
Step
Encoder → intensity → dimmer → api → set with 20.
t.encoder.intensity.dimmer.via.api.set(20)
42
Step
Press keypad keys
[
  "PRE"
]
t.keypad.press(["PRE"])
63
Step
Press keypad keys
[
  "ESC"
]
t.keypad.press(["ESC"])
65
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
71
Step
Encoder → intensity → dimmer → api → set with 45.
t.encoder.intensity.dimmer.via.api.set(45)
72
Step
Preset → api → store with PresetFamily.Intensity, 99,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Intensity, 99, {
			mode: "overwrite",
		})
73
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
76
Step
Preset → api → recall with PresetFamily.Intensity, 99.
t.preset.via.api.recall(PresetFamily.Intensity, 99)
84
Step
Show → contract identity.
t.show.contractIdentity()
87
Step
Connect the simulated attached hardware surface.
t.hardware.connect()
90
Step
Disconnect the simulated attached hardware surface.
t.hardware.disconnect()
94
Expected
fixture(1) DMX equals
{
   Intensity:  140
}
t.expectFixtureDMX(fixture(1), { Intensity: 140 })
107

Diagnostics

DiagnosticWhereDetailLine
missing-migration-statusSourceNo exact source, ID, and title match exists in the generated migration inventory.8

BENCH-PRESET-COLOR-001 — a Cue on a Group Color Preset follows a replaced fixture from a color wheel to RGBWA mixing

tests/94-semantic-preset-color-across-fixture-types.spec.ts:24 · migrated-semantic-world · last run: not merged

show: EmptyBrowser UICommand lineCue runtimeCue timingDMX outputEncoder controlsGroupsPlaybacksPresetsProgrammerProgrammer timingRecordingSelectionSemantic oracleShow PatchShow filesTest clockTyped API
Preconditions (3)
ContextLine
Use the isolated Show.Empty show.
t.show.use(Show.Empty)
28
Open the ToskLight browser application.
t.app.open()
30
The ToskLight browser application is ready.
t.app.expect.ready()
31

Scenario contract

KindScenario contractLine
Step
Set the active show's color programming model to "intent".
t.show.colorModel("intent")
29
Step
Timing → programmer fade → api → set with "0s".
t.timing.programmerFade.via.api.set("0s")
32
Step
Patch → api → add with
{
   number:  1,
   name:  "Wheel Spot",
   address:  "1.1",
   <unresolved: ...WHEEL_SPOT>
}
t.patch.via.api.add({
			number: 1,
			name: "Wheel Spot",
			address: "1.1",
			...WHEEL_SPOT,
		})
35
Step
Selection → fixtures → api → item with 1.
t.selection.fixtures.via.api.item(1)
41
Step
Group → api → store with 1,
{
   mode:  StoreMode.Overwrite
}
t.group.via.api.store(1, { mode: StoreMode.Overwrite })
42
Expected
Group → fixtures: 1, 1.
t.group.expect(1).fixtures(1)
43
Step
Execute the desk command "GROUP 1 AT COLOR 100 DIV 0 DIV 0 DIV 0" through the API.
t.command.via.api.execute("GROUP 1 AT COLOR 100 DIV 0 DIV 0 DIV 0")
46
Step
Preset → api → store with PresetFamily.Color, 1,
{
   mode:  "overwrite"
}
t.preset.via.api.store(PresetFamily.Color, 1, { mode: "overwrite" })
47
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
48
Step
Clear the current selection.
t.selection.clear()
49
Step
Execute the desk command "GROUP 1 AT 100" through the visible command line.
t.command.via.ui.execute("GROUP 1 AT 100")
52
Step
Execute the desk command "GROUP 1 AT 2.1" through the visible command line.
t.command.via.ui.execute("GROUP 1 AT 2.1")
53
Step
Record → ui → playback with 1.
t.record.via.ui.playback(1)
54
Expected
Cue → present: $playback (result of record.via.ui.playback), 1.
t.cue.expect(playback, 1).present()
55
Expected
Cue → group value: $playback (result of record.via.ui.playback), 1, 1, "intensity", 1.
t.cue.expect(playback, 1).groupValue(1, "intensity", 1)
56
Step
Read stored Cue 1 from the Cuelist assigned to Playback $playback (result of record.via.ui.playback).
t.cue.cue(playback, 1)
57
Step
Read the stored PresetFamily.Color Preset 1, requiring that it exists.
t.preset.requiredObject(PresetFamily.Color, 1)
58
Expected
$recordedCue?.group_changes (from cue.cue) equals <unresolved: expect.arrayContaining([ expect.objectContaining({ group_id: "1", preset_reference: expect.objectContaining({ preset_instance_id: colorPreset.body.instance_id, source_attribute:…>.
expect(recordedCue?.group_changes).toEqual(
			expect.arrayContaining([
				expect.objectContaining({
					group_id: "1",
					preset_reference: expect.objectContaining({
						preset_instance_id: colorPreset.body.instance_id,
						source_attribute: "color",
					}),
				}),
			]),
		)
59
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
70
Step
Clear the current selection.
t.selection.clear()
71
Step
Playback → api → go with $playback (result of record.via.ui.playback).
t.playback.via.api.go(playback)
73
Expected
Playback → runtime: $playback (result of record.via.ui.playback),
{
   current_cue_number:  "1",
   enabled:  true
}
t.playback.expect(playback).runtime({
			current_cue_number: "1",
			enabled: true,
		})
74
Step
Advance the test clock by "5s".
t.clock.advanceBy("5s")
78
Expected
fixture(1) DMX equals
{
   "Intensity coarse":  255,
   "Intensity fine":  255,
   "Color wheel 1":  <unresolved: AURO_DEEP_RED_SLOT>
}
t.expectFixtureDMX(
			fixture(1),
			{
				"Intensity coarse": 255,
				"Intensity fine": 255,
				"Color wheel 1": AURO_DEEP_RED_SLOT,
			},
		)
79
Step
Playback → api → off with $playback (result of record.via.ui.playback).
t.playback.via.api.off(playback)
88
Expected
Playback → runtime: $playback (result of record.via.ui.playback),
{
   enabled:  false
}
t.playback.expect(playback).runtime({ enabled: false })
89
Step
Advance the test clock by "5s".
t.clock.advanceBy("5s")
90
Step
Patch → api → remove with 1.
t.patch.via.api.remove(1)
93
Expected
Group → empty: 1.
t.group.expect(1).empty()
94
Step
Patch → api → add with
{
   number:  2,
   name:  "RGBWA Wash",
   address:  "1.1",
   <unresolved: ...RGBWA_WASH>
}
t.patch.via.api.add({
			number: 2,
			name: "RGBWA Wash",
			address: "1.1",
			...RGBWA_WASH,
		})
95
Step
Selection → fixtures → api → item with 2.
t.selection.fixtures.via.api.item(2)
101
Step
Group → api → store with 1,
{
   mode:  StoreMode.Merge
}
t.group.via.api.store(1, { mode: StoreMode.Merge })
102
Expected
Group → fixtures: 1, 2.
t.group.expect(1).fixtures(2)
103
Step
Clear the current selection.
t.selection.clear()
104
Step
Execute the desk command "GROUP 1 AT COLOR 0 DIV 100 DIV 0 DIV 0" through the API.
t.command.via.api.execute("GROUP 1 AT COLOR 0 DIV 100 DIV 0 DIV 0")
107
Step
Preset → api → update with PresetFamily.Color, 1,
{
   mode:  "all"
}
t.preset.via.api.update(PresetFamily.Color, 1, { mode: "all" })
108
Step
Execute the desk command "GROUP 1 AT COLOR 100 DIV 0 DIV 0 DIV 0" through the API.
t.command.via.api.execute("GROUP 1 AT COLOR 100 DIV 0 DIV 0 DIV 0")
109
Step
Preset → api → update with PresetFamily.Color, 1,
{
   mode:  "all"
}
t.preset.via.api.update(PresetFamily.Color, 1, { mode: "all" })
111
Step
Clear Programmer values through the encoder intent.
t.encoder.clear()
112
Step
Clear the current selection.
t.selection.clear()
113
Step
Playback → api → go with $playback (result of record.via.ui.playback).
t.playback.via.api.go(playback)
116
Expected
Playback → runtime: $playback (result of record.via.ui.playback),
{
   current_cue_number:  "1",
   enabled:  true
}
t.playback.expect(playback).runtime({
			current_cue_number: "1",
			enabled: true,
		})
117
Step
Advance the test clock by "5s".
t.clock.advanceBy("5s")
121
Expected
fixture(2) DMX equals
{
   Intensity:  255,
   "Color red":  255,
   "Color green":  0,
   "Color blue":  0,
   "Color white":  0,
   "Color amber":  0
}
t.expectFixtureDMX(
			fixture(2),
			{
				Intensity: 255,
				"Color red": 255,
				"Color green": 0,
				"Color blue": 0,
				"Color white": 0,
				"Color amber": 0,
			},
		)
122
Step
Playback → api → off with $playback (result of record.via.ui.playback).
t.playback.via.api.off(playback)
135
Step
Advance the test clock by "5s".
t.clock.advanceBy("5s")
136
Expected
fixture(2) DMX equals
{
   Intensity:  0,
   "Color green":  255,
   "Color blue":  255,
   "Color white":  255
}
t.expectFixtureDMX(
			fixture(2),
			{ Intensity: 0, "Color green": 255, "Color blue": 255, "Color white": 255 },
		)
137

Diagnostics

DiagnosticWhereDetailLine
unresolved-expressionStep<unresolved: ...WHEEL_SPOT> Object member ...WHEEL_SPOT is not statically resolved.39
unresolved-expressionExpected outcome<unresolved: expect.arrayContaining([ expect.objectContaining({ group_id: "1", preset_reference: expect.objectContaining({ preset_instance_id: colorPreset.body.instance_id, source_attribute:…> Call expression expect.arrayContaining([ expect.objectContaining({ group_id: "1", preset_reference: expect.objectContaining({ preset_instance_id: colorPreset.body.instance_id, source_attribute:… is dynamic and was not executed.60
unresolved-expressionExpected outcome<unresolved: AURO_DEEP_RED_SLOT> Expression AURO_DEEP_RED_SLOT is not statically resolved.84
unresolved-expressionStep<unresolved: ...RGBWA_WASH> Object member ...RGBWA_WASH is not statically resolved.99

BENCH-PRODUCT-DEMO-001 — narrates the complete Full HD product demo surface in one regression run

tests/product-demo.spec.ts:5 · unresolved · last run: not merged

Browser UIGenerated artifacts

Scenario contract

KindScenario contractLine
Step
Run the complete narrated Full HD product-demo workflow and its internal semantic assertions.
t.demo.run()
9
Expected
Complete product-demo workflow and its internal semantic assertions pass.
t.demo.run()
9

Diagnostics

DiagnosticWhereDetailLine
missing-migration-statusSourceNo exact source, ID, and title match exists in the generated migration inventory.5