feat(scenario): implement the phase 6 scenario director
Add Format Specification section 21 (Scenario Model 0.1) and the runtime that realizes it: the scenario director, seven trigger classes, timelines with repeats and branches, admission and concurrency control, nested ownership with bounded cleanup, and the production GC5 resource counters. Exhibit E provides a reproducible forty-minute long-scenario reference and scenario-challenge.xzbt covers the PRD 131 cases. A standalone acceptance/soak page is built by tools/build-scenario-acceptance.mjs. 252 automated checks pass. The two-hour real-duration development soak required by the GC6 schedule remains pending. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01M7dgfQ12mpM4JjSMv3inLA
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
{
|
||||
"xzbt": "0.1",
|
||||
"meta": {
|
||||
"id": "exhibit-e",
|
||||
"name": "Exhibit E — Long Passage",
|
||||
"version": "0.1.0",
|
||||
"description": "A forty-minute procedural passage: approach, repeated signals, branching disturbance, and recovery."
|
||||
},
|
||||
"runtime": {
|
||||
"seed": 42
|
||||
},
|
||||
"parameters": {
|
||||
"activity": {
|
||||
"type": "number",
|
||||
"default": 0.35,
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"label": "Activity"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"initial": "normal"
|
||||
},
|
||||
"beats": {
|
||||
"type": "integer",
|
||||
"initial": 0
|
||||
},
|
||||
"journeys": {
|
||||
"type": "integer",
|
||||
"initial": 0
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"buses": {
|
||||
"ambient": {
|
||||
"gain": 0.5
|
||||
},
|
||||
"effects": {
|
||||
"gain": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
"sounds": {
|
||||
"bed": {
|
||||
"name": "Distant hum",
|
||||
"bus": "ambient",
|
||||
"usage": [
|
||||
"automatic"
|
||||
],
|
||||
"cadence": {
|
||||
"class": "ambient"
|
||||
},
|
||||
"recipe": {
|
||||
"mode": "continuous",
|
||||
"release": "1s",
|
||||
"nodes": {
|
||||
"tone": {
|
||||
"type": "oscillator",
|
||||
"frequency": 55
|
||||
},
|
||||
"trim": {
|
||||
"type": "gain",
|
||||
"gain": 0.04
|
||||
}
|
||||
},
|
||||
"routes": [
|
||||
{
|
||||
"from": "tone",
|
||||
"to": "trim"
|
||||
},
|
||||
{
|
||||
"from": "trim",
|
||||
"to": "output"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"drone": {
|
||||
"name": "Passing resonance",
|
||||
"bus": "ambient",
|
||||
"usage": [
|
||||
"scenario"
|
||||
],
|
||||
"recipe": {
|
||||
"mode": "continuous",
|
||||
"release": "2s",
|
||||
"nodes": {
|
||||
"tone": {
|
||||
"type": "oscillator",
|
||||
"frequency": 165
|
||||
},
|
||||
"trim": {
|
||||
"type": "gain",
|
||||
"gain": 0.035
|
||||
}
|
||||
},
|
||||
"routes": [
|
||||
{
|
||||
"from": "tone",
|
||||
"to": "trim"
|
||||
},
|
||||
{
|
||||
"from": "trim",
|
||||
"to": "output"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"beat": {
|
||||
"name": "Soft impulse",
|
||||
"bus": "effects",
|
||||
"usage": [
|
||||
"automatic",
|
||||
"scenario",
|
||||
"manual"
|
||||
],
|
||||
"cadence": {
|
||||
"class": "routine",
|
||||
"overlap": false,
|
||||
"cooldown": "3s"
|
||||
},
|
||||
"recipe": {
|
||||
"mode": "oneshot",
|
||||
"release": "50ms",
|
||||
"nodes": {
|
||||
"hit": {
|
||||
"type": "impulse",
|
||||
"duration": "8ms",
|
||||
"amplitude": 0.06
|
||||
}
|
||||
},
|
||||
"routes": [
|
||||
{
|
||||
"from": "hit",
|
||||
"to": "output"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"cadence": {
|
||||
"intensity": {
|
||||
"ref": "parameters.activity"
|
||||
},
|
||||
"minGap": "1500ms"
|
||||
},
|
||||
"bindings": [
|
||||
{
|
||||
"source": "parameters.activity",
|
||||
"target": "visuals.camera.zoom",
|
||||
"scale": 0.2,
|
||||
"offset": 1
|
||||
}
|
||||
],
|
||||
"visuals": {
|
||||
"scene": {
|
||||
"coordinateSpace": "virtual",
|
||||
"width": 960,
|
||||
"height": 540,
|
||||
"background": "#101d25"
|
||||
},
|
||||
"systems": {
|
||||
"horizon": {
|
||||
"type": "graphic",
|
||||
"content": {
|
||||
"ring": {
|
||||
"type": "ring",
|
||||
"radius": 150,
|
||||
"innerRadius": 148,
|
||||
"position": {
|
||||
"x": 480,
|
||||
"y": 270
|
||||
},
|
||||
"style": {
|
||||
"fill": "#80beb5"
|
||||
}
|
||||
},
|
||||
"line": {
|
||||
"type": "line",
|
||||
"position": {
|
||||
"x": 240,
|
||||
"y": 270
|
||||
},
|
||||
"to": {
|
||||
"x": 480,
|
||||
"y": 0
|
||||
},
|
||||
"style": {
|
||||
"stroke": "#dfc18d",
|
||||
"strokeWidth": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"signal": {
|
||||
"type": "graphic",
|
||||
"lifecycle": "spawned",
|
||||
"spawn": {
|
||||
"lifetime": "4s",
|
||||
"release": "1s"
|
||||
},
|
||||
"content": {
|
||||
"ring": {
|
||||
"type": "ring",
|
||||
"radius": 165,
|
||||
"innerRadius": 160,
|
||||
"position": {
|
||||
"x": 480,
|
||||
"y": 270
|
||||
},
|
||||
"style": {
|
||||
"fill": "#efbe79"
|
||||
},
|
||||
"behaviors": [
|
||||
{
|
||||
"type": "rotate",
|
||||
"speed": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"signal": {
|
||||
"actions": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.beats",
|
||||
"value": {
|
||||
"op": "add",
|
||||
"args": [
|
||||
{
|
||||
"ref": "state.beats"
|
||||
},
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "sound",
|
||||
"sound": "beat"
|
||||
},
|
||||
{
|
||||
"type": "spawn",
|
||||
"target": "visuals.systems.signal"
|
||||
}
|
||||
]
|
||||
},
|
||||
"recover": {
|
||||
"actions": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.mode",
|
||||
"value": "normal"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"scenarios": {
|
||||
"journey": {
|
||||
"name": "Long passage",
|
||||
"priority": 70,
|
||||
"group": "passage",
|
||||
"trigger": {
|
||||
"type": "random-interval",
|
||||
"min": "45m",
|
||||
"max": "60m"
|
||||
},
|
||||
"concurrency": {
|
||||
"mode": "exclusive",
|
||||
"scope": "group",
|
||||
"policy": "defer"
|
||||
},
|
||||
"duration": "40m",
|
||||
"cooldown": "5m",
|
||||
"onStart": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.journeys",
|
||||
"value": {
|
||||
"op": "add",
|
||||
"args": [
|
||||
{
|
||||
"ref": "state.journeys"
|
||||
},
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.mode",
|
||||
"value": "approach"
|
||||
},
|
||||
{
|
||||
"type": "sound",
|
||||
"sound": "drone"
|
||||
},
|
||||
{
|
||||
"type": "override",
|
||||
"target": "parameters.activity",
|
||||
"value": 0.7,
|
||||
"scope": "scenario",
|
||||
"transition": {
|
||||
"in": "1s",
|
||||
"out": "2s",
|
||||
"easing": "ease-in-out"
|
||||
}
|
||||
}
|
||||
],
|
||||
"timeline": [
|
||||
{
|
||||
"id": "arrival",
|
||||
"at": "1m",
|
||||
"actions": [
|
||||
{
|
||||
"type": "event",
|
||||
"event": "signal"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"after": "arrival",
|
||||
"delay": {
|
||||
"random": {
|
||||
"min": "20s",
|
||||
"max": "50s"
|
||||
}
|
||||
},
|
||||
"repeat": {
|
||||
"count": 12,
|
||||
"every": {
|
||||
"random": {
|
||||
"min": "1m",
|
||||
"max": "2m"
|
||||
}
|
||||
}
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"type": "event",
|
||||
"event": "signal"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"at": "15m",
|
||||
"choose": [
|
||||
{
|
||||
"weight": 3,
|
||||
"actions": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.mode",
|
||||
"value": "drift"
|
||||
},
|
||||
{
|
||||
"type": "override",
|
||||
"target": "parameters.activity",
|
||||
"value": 0.5,
|
||||
"scope": "duration",
|
||||
"transition": {
|
||||
"in": "1s",
|
||||
"out": "2s",
|
||||
"easing": "ease-in-out"
|
||||
},
|
||||
"duration": "5m"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"weight": 1,
|
||||
"actions": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.mode",
|
||||
"value": "disturbance"
|
||||
},
|
||||
{
|
||||
"type": "override",
|
||||
"target": "parameters.activity",
|
||||
"value": 0.95,
|
||||
"scope": "duration",
|
||||
"transition": {
|
||||
"in": "1s",
|
||||
"out": "2s",
|
||||
"easing": "ease-in-out"
|
||||
},
|
||||
"duration": "5m"
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"event": "signal"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"at": "30m",
|
||||
"actions": [
|
||||
{
|
||||
"type": "event",
|
||||
"event": "recover"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"at": "40m",
|
||||
"actions": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.mode",
|
||||
"value": "normal"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"onComplete": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.mode",
|
||||
"value": "normal"
|
||||
}
|
||||
],
|
||||
"onCancel": [
|
||||
{
|
||||
"type": "set",
|
||||
"target": "state.mode",
|
||||
"value": "normal"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user