Added chatterbox connections
This commit is contained in:
1 parent
41ef12f954
commit
e58ceeb192
58 files changed
+8931
-8
No files matched your search
@@ -0,0 +1,56 @@
|
||||
# Glitch: the Dark Machine - design updates
|
||||
|
||||
## October 18, 2026: opening, reveal, and cooperative cabinet play
|
||||
|
||||
These updates supplement the imported GDD and implementation contract. They record current design direction; they do not claim that the running simulation implements these changes. Preserve the imported references as the baseline.
|
||||
|
||||
### Confirmed opening: restore apparent room power
|
||||
|
||||
Players enter to investigate strange happenings in an arcade believed to be haunted. Teddy is the only apparently powered interactive character at entry. He delivers the opening story, establishes the mood, and can guide players toward their first task. Cabinets and other show-controlled effects initially appear inactive. Real electrical supply remains on; this is a room-sequencing state, not a request to interrupt building power.
|
||||
|
||||
The opening objective is:
|
||||
|
||||
1. Locate the junction box.
|
||||
2. Find the physical key.
|
||||
3. Use the key to remove the lock preventing operation of the large switch.
|
||||
4. Physically move the switch upward.
|
||||
5. The controller accepts the switch observation and begins the powered arcade portion of the experience.
|
||||
|
||||
Unlocking alone does not restore apparent power. The switch action is the completion trigger. Do not assume that key discovery or lock removal has an electronic sensor; the mechanical lock may enforce those prerequisites. Confirm the switch input hardware before assigning a GPIO or I2C channel. BCM23 remains an LED output, not this input.
|
||||
|
||||
Suggested controller states: prepared, opening investigation, power restoration accepted, arcade active. Opening narration and hint delivery must work before power restoration. Starting the GM session and starting powered arcade play are distinct actions. Whether the room timer starts on entry or on switch activation remains a design decision.
|
||||
|
||||
A proposed GM panel shows the reported switch position, observation freshness, and room-power story state separately. Provide an explicit, logged override for a failed prop. Repeated switch observations must not replay the opening or reset progress. A switch already up when a new run starts should produce a setup warning; do not silently skip the puzzle. The effect of lowering the switch during an active run remains to be decided; it must not implicitly erase progress.
|
||||
|
||||
Restoring room power does not automatically award RFID credits or bypass individual cabinet prerequisites. Decide which cabinet boot sequences and lighting cues accompany restoration when authoring the opening sequence.
|
||||
|
||||
### Confirmed narrative direction: haunted appearance, alien explanation
|
||||
|
||||
Early activity supports a plausible haunted-arcade interpretation: unusual machine behavior, unexplained sounds, and unsettling coincidences. Teddy sets the tone without explicitly explaining an alien cause. The alien manipulation is revealed when the secret room opens.
|
||||
|
||||
Review player-facing Teddy dialogue, puzzle text, cabinet art, and hint categories for premature alien, spacecraft, or launch references. GM-only information can describe the complete plot. Pre-reveal hints should remain available without exposing post-reveal material. After the reveal, prior events can be reinterpreted in light of what players have discovered.
|
||||
|
||||
### Proposal for playtesting: one cabinet controls another
|
||||
|
||||
During the later return to the arcade cabinets, a player's controls could operate a task displayed at another cabinet. The player with the useful view must communicate with the player controlling that view. This is a proposed mechanic, not yet a fixed routing plan or acceptance requirement.
|
||||
|
||||
Start with a two-cabinet test: player A operates controls while player B sees the target and gives directions; then exchange roles. Give both players meaningful feedback without showing the operator enough information to solve alone. Keep routing stable during an attempt and clearly announce changes between rounds. A larger circular arrangement can be tested after the pair works reliably.
|
||||
|
||||
Retain the secret-room navigator's role by giving that player the objective or target information while the arcade players coordinate its execution. Test whether this creates useful collaboration rather than excessive layers of instruction. Account for sightlines, room noise, latency, available controls, and smaller parties. Avoid requiring all six cabinets simultaneously for a small group.
|
||||
|
||||
Implementation candidate: the room controller authorizes source-to-target assignments for each round; cabinet clients relay bounded gameplay input through the agreed transport. Discard stale-round input and release held controls on disconnect, pause, or reassignment. This routing is for gameplay, not arbitrary remote physical outputs. GM diagnostics should show the control route and both cabinet connection states.
|
||||
|
||||
### Confirmed content direction: original arcade identities
|
||||
|
||||
Replace the current recognizable game names and sprites with original names and artwork for the room's arcade games. Track final names, character designs, marquees, screen art, sound, music, and text as authored assets rather than assuming a sprite swap completes the work. Existing game identifiers can remain internal during migration so saves, scenarios, and hardware assignments do not break unnecessarily.
|
||||
|
||||
This records the intended creative direction, not a legal clearance determination. Do not describe renaming and reskinning alone as a guarantee of clearance.
|
||||
|
||||
### Next simulation work
|
||||
|
||||
- Add the opening power gate, switch simulation, and logged GM override.
|
||||
- Keep Teddy available while the arcade appears unpowered.
|
||||
- Add stage-aware, spoiler-aware hint eligibility before the secret-room reveal.
|
||||
- Test repeated switch events, startup with switch already up, recovery, and no automatic RFID credit.
|
||||
- Prototype paired cabinet control with a clear GM routing display and small-party fallback.
|
||||
- Inventory replacement game presentation assets without changing stable scenario IDs prematurely.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,782 @@
|
||||
{
|
||||
"design_version": "1.0",
|
||||
"status": "proposed_semantic_contract_not_existing_wire_schema",
|
||||
"target_architecture": {
|
||||
"authority": "Rust Glitch room controller",
|
||||
"transport": "NATS",
|
||||
"operator_ui": "Flutter",
|
||||
"game_runtime": "Godot",
|
||||
"persistence_proposal": "durable transactional journal and outbox with JetStream observation delivery"
|
||||
},
|
||||
"profiles": {
|
||||
"guided": {
|
||||
"time_limit_ms": 3600000,
|
||||
"passes_per_station": 1,
|
||||
"response_window_ms": 60000,
|
||||
"stable_target_hold_ms": 1000,
|
||||
"final_ack_window_ms": 30000,
|
||||
"hint_1_inactivity_ms": 90000,
|
||||
"next_hint_interval_ms": 60000,
|
||||
"score_target_multiplier": 0.6,
|
||||
"frogger_homes": 1
|
||||
},
|
||||
"standard": {
|
||||
"time_limit_ms": 3600000,
|
||||
"passes_per_station": 2,
|
||||
"response_window_ms": 40000,
|
||||
"stable_target_hold_ms": 2000,
|
||||
"final_ack_window_ms": 20000,
|
||||
"hint_1_inactivity_ms": 120000,
|
||||
"next_hint_interval_ms": 90000,
|
||||
"score_target_multiplier": 1.0,
|
||||
"frogger_homes": 1
|
||||
},
|
||||
"challenge": {
|
||||
"time_limit_ms": 3600000,
|
||||
"passes_per_station": 3,
|
||||
"response_window_ms": 25000,
|
||||
"stable_target_hold_ms": 3000,
|
||||
"final_ack_window_ms": 12000,
|
||||
"hint_1_inactivity_ms": 180000,
|
||||
"next_hint_interval_ms": 120000,
|
||||
"score_target_multiplier": 1.4,
|
||||
"frogger_homes": 1
|
||||
}
|
||||
},
|
||||
"entities": [
|
||||
{
|
||||
"cabinet_id": "cabinet_01",
|
||||
"first_state_id": "A01",
|
||||
"game": "pacman",
|
||||
"token_id": "T01",
|
||||
"cell_id": "CELL01",
|
||||
"socket_id": "SOCKET01",
|
||||
"status": "existing_assignment"
|
||||
},
|
||||
{
|
||||
"cabinet_id": "cabinet_02",
|
||||
"first_state_id": "A02",
|
||||
"game": "galaga",
|
||||
"token_id": "T02",
|
||||
"cell_id": "CELL02",
|
||||
"socket_id": "SOCKET02",
|
||||
"status": "existing_assignment"
|
||||
},
|
||||
{
|
||||
"cabinet_id": "cabinet_03",
|
||||
"first_state_id": "A03",
|
||||
"game": "tempest",
|
||||
"token_id": "T03",
|
||||
"cell_id": "CELL03",
|
||||
"socket_id": "SOCKET03",
|
||||
"status": "existing_assignment"
|
||||
},
|
||||
{
|
||||
"cabinet_id": "cabinet_04",
|
||||
"first_state_id": "A04",
|
||||
"game": "missile_command",
|
||||
"token_id": "T04",
|
||||
"cell_id": "CELL04",
|
||||
"socket_id": "SOCKET04",
|
||||
"status": "existing_assignment"
|
||||
},
|
||||
{
|
||||
"cabinet_id": "cabinet_05",
|
||||
"first_state_id": "A05",
|
||||
"game": "frogger",
|
||||
"token_id": "T05",
|
||||
"cell_id": "CELL05",
|
||||
"socket_id": "SOCKET05",
|
||||
"status": "proposed_assignment"
|
||||
},
|
||||
{
|
||||
"cabinet_id": "cabinet_06",
|
||||
"first_state_id": "A06",
|
||||
"game": "space_invaders",
|
||||
"token_id": "T06",
|
||||
"cell_id": "CELL06",
|
||||
"socket_id": "SOCKET06",
|
||||
"status": "proposed_assignment"
|
||||
}
|
||||
],
|
||||
"boss": {
|
||||
"cabinet_id": "cabinet_07",
|
||||
"id": "B07",
|
||||
"game_proposal": "robotron_or_bespoke_variant",
|
||||
"unlock": "all_six_distinct_first_state_wins"
|
||||
},
|
||||
"durations_ms": {
|
||||
"charge": 30000,
|
||||
"passage_debounce": 300,
|
||||
"cell_debounce": 500,
|
||||
"ship_power_stable": 2000,
|
||||
"retry_delay": 3000,
|
||||
"countdown": 5000,
|
||||
"agent_stale": 3000,
|
||||
"agent_offline": 8000,
|
||||
"command_accept": 2000,
|
||||
"command_expiry": 5000,
|
||||
"boot_completion": 10000
|
||||
},
|
||||
"staffing": {
|
||||
"operator_count_rule": "max(1, min(party_size - 1, 6))",
|
||||
"calibration_concurrency": "operator_count",
|
||||
"solo": "assisted sequential ship/arcade interaction",
|
||||
"finale": "sequential station arm, group readiness, navigator commit",
|
||||
"solo_final_ack_window_ms": 90000
|
||||
},
|
||||
"event_envelope_schema": {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "Proposed Glitch normalized event envelope",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"event_id",
|
||||
"type",
|
||||
"room_id",
|
||||
"run_id",
|
||||
"entity_id",
|
||||
"source_id",
|
||||
"boot_id",
|
||||
"source_seq",
|
||||
"assignment_id",
|
||||
"occurred_at_ms",
|
||||
"received_at_ms",
|
||||
"payload"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"const": 1
|
||||
},
|
||||
"event_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"room_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"run_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"entity_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"source_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"boot_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"source_seq": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"assignment_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"occurred_at_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"received_at_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"payload": {
|
||||
"type": "object"
|
||||
},
|
||||
"correlation_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"causation_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"actor_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"room_state_example": {
|
||||
"schema_version": 1,
|
||||
"room_id": "glitch",
|
||||
"run_id": "example-run-001",
|
||||
"revision": 0,
|
||||
"config_hash": "EXAMPLE_REPLACE_WITH_CONTENT_HASH",
|
||||
"lifecycle": "READY",
|
||||
"phase": "BRIEFING",
|
||||
"outcome": null,
|
||||
"active_elapsed_ms": 0,
|
||||
"time_limit_ms": 3600000,
|
||||
"difficulty": "standard",
|
||||
"party_size": 2,
|
||||
"controller_epoch": 1,
|
||||
"seed": 42,
|
||||
"cabinet_first_wins": [],
|
||||
"cells_installed": [],
|
||||
"calibration_passes": {},
|
||||
"launch": {
|
||||
"launch_epoch": 0,
|
||||
"armed_stations": [],
|
||||
"acknowledged_groups": [],
|
||||
"committed": false
|
||||
}
|
||||
},
|
||||
"simulation_cases": [
|
||||
{
|
||||
"id": "SIM01",
|
||||
"scenario": "Golden path with 6 players, standard",
|
||||
"assertion": "All acts, six cells and two calibration passes; one launch commit",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM02",
|
||||
"scenario": "2 players, guided; one roaming operator",
|
||||
"assertion": "All six stations completed; no simultaneous multi-station human input required",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM03",
|
||||
"scenario": "1 assisted player; sequential ship and arcade interactions",
|
||||
"assertion": "No deadlock; clearly assisted outcome/metadata",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM04",
|
||||
"scenario": "8 players, challenge; six stations active",
|
||||
"assertion": "Unused helper never required for a guard; three passes per station",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM05",
|
||||
"scenario": "Wrong token, repeated scan, stale historical scan",
|
||||
"assertion": "No credit for wrong/stale; only one authorization for correct scan",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM06",
|
||||
"scenario": "Lose A03 twice then retry",
|
||||
"assertion": "No extra token needed; other wins and charge retained",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM07",
|
||||
"scenario": "Duplicate A01 win and missing A06 win",
|
||||
"assertion": "Boss remains dark; unique set count stays 5",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM08",
|
||||
"scenario": "Claw reward ACK but token delivery jam",
|
||||
"assertion": "Reward pending; GM hand-delivery logged; no duplicate dispense",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM09",
|
||||
"scenario": "Boss won; passage ACK without open sensor",
|
||||
"assertion": "Reveal hold after 5 s; no assumed opening",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM10",
|
||||
"scenario": "Wrong socket, duplicate cell identity, missing cell",
|
||||
"assertion": "Ship power guard false; explicit diagnostic per conflict",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM11",
|
||||
"scenario": "Cell removed during calibration and countdown",
|
||||
"assertion": "Current wave/countdown canceled; completed passes retained; fresh IDs",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM12",
|
||||
"scenario": "Late Ready for old challenge; Execute exactly at deadline",
|
||||
"assertion": "Both rejected; current wave remains consistent",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM13",
|
||||
"scenario": "One final group late, then retry",
|
||||
"assertion": "Acknowledgements clear; calibration retained; launch once on valid retry",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM14",
|
||||
"scenario": "Restart controller after durable boss win before output publish",
|
||||
"assertion": "Recovered outbox sends same command ID; no repeated physical release",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM15",
|
||||
"scenario": "Agent restarts after uncertain bay release",
|
||||
"assertion": "No blind pulse replay; reconcile or GM inspect",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM16",
|
||||
"scenario": "Network drop, duplicate and reordered events",
|
||||
"assertion": "No regression/double reward; snapshot reconciliation reaches same state",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM17",
|
||||
"scenario": "Teddy unavailable or stale queued hint",
|
||||
"assertion": "Fallback text; stale hint discarded; gameplay can finish",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM18",
|
||||
"scenario": "Pause 5 min; expire action while paused",
|
||||
"assertion": "Active timer frozen; expired wall-time command rejected",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM19",
|
||||
"scenario": "Time expires in calibration; extend 5 min",
|
||||
"assertion": "TIME_EXPIRED then preserved phase; no automatic normal win",
|
||||
"execution_status": "specified_not_executed"
|
||||
},
|
||||
{
|
||||
"id": "SIM20",
|
||||
"scenario": "Reset and inject old-run win/scan/launch",
|
||||
"assertion": "All rejected; fresh run remains pristine",
|
||||
"execution_status": "specified_not_executed"
|
||||
}
|
||||
],
|
||||
"calibration_selections": {
|
||||
"cabinet_01": {
|
||||
"min": 0,
|
||||
"max": 3
|
||||
},
|
||||
"cabinet_02": {
|
||||
"min": 1,
|
||||
"max": 5
|
||||
},
|
||||
"cabinet_03": {
|
||||
"min": 0,
|
||||
"max": 7
|
||||
},
|
||||
"cabinet_04": {
|
||||
"min": 1,
|
||||
"max": 3
|
||||
},
|
||||
"cabinet_05": {
|
||||
"min": 1,
|
||||
"max": 4
|
||||
},
|
||||
"cabinet_06": {
|
||||
"min": 1,
|
||||
"max": 4
|
||||
}
|
||||
},
|
||||
"payload_schemas": {
|
||||
"puzzle.solved": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"puzzle_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"evidence": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"puzzle_id",
|
||||
"evidence"
|
||||
]
|
||||
},
|
||||
"reward.delivered": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reward_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"evidence": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reward_id",
|
||||
"evidence"
|
||||
]
|
||||
},
|
||||
"token.observed": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reader_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"token_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reader_id",
|
||||
"token_id"
|
||||
]
|
||||
},
|
||||
"game.started": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"attempt_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attempt_id"
|
||||
]
|
||||
},
|
||||
"game.progress": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"attempt_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"value": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attempt_id",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
"game.won": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"attempt_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"objective_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"value": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attempt_id",
|
||||
"objective_id",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
"game.lost": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"attempt_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attempt_id",
|
||||
"reason"
|
||||
]
|
||||
},
|
||||
"cell.observed": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"cell_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"present": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cell_id",
|
||||
"location",
|
||||
"present"
|
||||
]
|
||||
},
|
||||
"passage.observed": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"open": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sensor_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"open",
|
||||
"sensor_id"
|
||||
]
|
||||
},
|
||||
"calibration.ready": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"challenge_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"selection": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"stable_for_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"challenge_id",
|
||||
"selection",
|
||||
"stable_for_ms"
|
||||
]
|
||||
},
|
||||
"calibration.ready_revoked": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"challenge_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"challenge_id",
|
||||
"reason"
|
||||
]
|
||||
},
|
||||
"calibration.execute": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"challenge_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"challenge_id"
|
||||
]
|
||||
},
|
||||
"launch.group_ready": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"launch_epoch": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"group_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"launch_epoch",
|
||||
"group_id"
|
||||
]
|
||||
},
|
||||
"launch.commit_requested": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"launch_epoch": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"launch_epoch"
|
||||
]
|
||||
},
|
||||
"teddy.playback_status": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"cue_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"status": {
|
||||
"enum": [
|
||||
"accepted",
|
||||
"started",
|
||||
"completed",
|
||||
"failed"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cue_id",
|
||||
"status"
|
||||
]
|
||||
}
|
||||
},
|
||||
"payload_validation": "Validate envelope, then select payload schema by event.type. Reject unknown event types unless separately defined as controller-internal events. Apply semantic guards after schema validation.",
|
||||
"command_envelope_schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"const": 1
|
||||
},
|
||||
"command_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"room_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"run_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"target_entity": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"target_boot_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"controller_epoch": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"expected_revision": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"expires_at_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"payload": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"schema_version",
|
||||
"command_id",
|
||||
"type",
|
||||
"room_id",
|
||||
"run_id",
|
||||
"target_entity",
|
||||
"target_boot_id",
|
||||
"controller_epoch",
|
||||
"expected_revision",
|
||||
"expires_at_ms",
|
||||
"payload"
|
||||
]
|
||||
},
|
||||
"command_result_schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"command_id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"status": {
|
||||
"enum": [
|
||||
"ACCEPTED",
|
||||
"REJECTED",
|
||||
"COMPLETED",
|
||||
"FAILED",
|
||||
"DELIVERY_UNKNOWN"
|
||||
]
|
||||
},
|
||||
"reason_code": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"snapshot_revision": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command_id",
|
||||
"status",
|
||||
"reason_code",
|
||||
"snapshot_revision"
|
||||
]
|
||||
},
|
||||
"event_example": {
|
||||
"schema_version": 1,
|
||||
"event_id": "evt-example-001",
|
||||
"type": "game.won",
|
||||
"room_id": "glitch",
|
||||
"run_id": "example-run-001",
|
||||
"entity_id": "cabinet_01",
|
||||
"source_id": "agent-cabinet-01",
|
||||
"boot_id": "boot-example-001",
|
||||
"source_seq": 14,
|
||||
"assignment_id": "assignment-a01-001",
|
||||
"occurred_at_ms": 1792260000000,
|
||||
"received_at_ms": 1792260000010,
|
||||
"payload": {
|
||||
"attempt_id": "attempt-a01-001",
|
||||
"objective_id": "score_500",
|
||||
"value": 500
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user