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:
+547
-3
@@ -404,10 +404,10 @@
|
||||
},
|
||||
"scenarios": {
|
||||
"type": "object",
|
||||
"description": "Autonomous orchestrated scenarios and timelines.",
|
||||
"maxProperties": 64,
|
||||
"patternProperties": {
|
||||
"^[a-z][a-z0-9_-]*$": {
|
||||
"type": "object"
|
||||
"$ref": "#/definitions/ScenarioDefinition"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -2141,8 +2141,14 @@
|
||||
},
|
||||
"transition": {
|
||||
"type": "object"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer",
|
||||
"minimum": -1000,
|
||||
"maximum": 1000
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"EventDefinition": {
|
||||
"type": "object",
|
||||
@@ -3648,6 +3654,544 @@
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ScenarioTrigger": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "manual"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "once"
|
||||
},
|
||||
"at": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "interval"
|
||||
},
|
||||
"every": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"every"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "random-interval"
|
||||
},
|
||||
"min": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"max": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"min",
|
||||
"max"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "probability"
|
||||
},
|
||||
"every": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"chance": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"every",
|
||||
"chance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "condition"
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/definitions/ConditionSpec"
|
||||
},
|
||||
"for": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"when"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "event"
|
||||
},
|
||||
"event": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_-]*$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"event"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"ScenarioEntry": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_-]*$"
|
||||
},
|
||||
"at": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"after": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_-]*$"
|
||||
},
|
||||
"delay": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"random": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"min": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"max": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"min",
|
||||
"max"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"random"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"repeat": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 1024
|
||||
},
|
||||
"every": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"random": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"min": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"max": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"min",
|
||||
"max"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"random"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"count",
|
||||
"every"
|
||||
]
|
||||
},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ActionSpec"
|
||||
}
|
||||
},
|
||||
"choose": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"weight": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/definitions/ConditionSpec"
|
||||
},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ActionSpec"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"weight",
|
||||
"actions"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"required": [
|
||||
"at"
|
||||
],
|
||||
"not": {
|
||||
"required": [
|
||||
"after"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"after"
|
||||
],
|
||||
"not": {
|
||||
"required": [
|
||||
"at"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"required": [
|
||||
"actions"
|
||||
],
|
||||
"not": {
|
||||
"required": [
|
||||
"choose"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"choose"
|
||||
],
|
||||
"not": {
|
||||
"required": [
|
||||
"actions"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"ScenarioDefinition": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 100
|
||||
},
|
||||
"group": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_-]*$"
|
||||
},
|
||||
"trigger": {
|
||||
"$ref": "#/definitions/ScenarioTrigger"
|
||||
},
|
||||
"eligibility": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"when": {
|
||||
"$ref": "#/definitions/ConditionSpec"
|
||||
},
|
||||
"timeout": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"concurrency": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"mode": {
|
||||
"enum": [
|
||||
"parallel",
|
||||
"exclusive"
|
||||
]
|
||||
},
|
||||
"scope": {
|
||||
"enum": [
|
||||
"group",
|
||||
"global"
|
||||
]
|
||||
},
|
||||
"policy": {
|
||||
"enum": [
|
||||
"defer",
|
||||
"reject",
|
||||
"replace"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode"
|
||||
]
|
||||
},
|
||||
"cooldown": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"duration": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DurationSpec"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"onStart": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ActionSpec"
|
||||
}
|
||||
},
|
||||
"onComplete": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ActionSpec"
|
||||
}
|
||||
},
|
||||
"onCancel": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ActionSpec"
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"type": "array",
|
||||
"maxItems": 1024,
|
||||
"items": {
|
||||
"$ref": "#/definitions/ScenarioEntry"
|
||||
}
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"maxItems": 16,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"maxLength": 32
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"timeline"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user