Skip to content

feat(actions): stop_project ActionCue, the authored end of an unattended show (869fhjdq5) - #35

Merged
ibiltari merged 2 commits into
rc_1from
feat/stop-project-actioncue
Oct 15, 2026
Merged

ibiltari merged 2 commits into
rc_1from
feat/stop-project-actioncue

Conversation

@ibiltari

Copy link
Copy Markdown
Member

A stop_project ActionCue is the authored end of an unattended show (museums, kiosks; ClickUp 869fhjdq5). When revealed, it stops the show exactly as an operator STOP does: running no, every cue reset to 0, nodes re-armed. The next GO plays from the top. The engine still never infers an end. After the last cue it keeps running = yes by design, which is now documented.

How it works

  • Every node reveals the cue, because ActionCues are local everywhere. The handler is pure.
  • NodeEngine._action_result_sink sends the controller a STATUS op stop_project {cue, run_seq} without waiting. It skips the send when a STOP or load is already pending, or when no run is in progress.
  • The controller validates the op like _relay_follow: adopted sender, cue in the project and of the right type, show running, current run_seq. It then releases the lock and calls stop_script. The first valid op wins; the other nodes' copies are dropped at INFO.
  • The node never stops itself. A 3 s watchdog compares STOP/load receipts and only logs a WARNING if no STOP arrived.
  • On the node, the cue is a hard chain break: nothing after it is dispatched, and no go_at_end fires from it. A disabled stop cue is transparent, which gives a rehearsal mode.

Hardenings shipped with it

  • Cue ADD/UPDATE ops are ignored while running != yes. Before this, a node's late start report after a STOP could leave a cue at 1, then 100.
  • stop_script restarts the arm watchdog, so a failed re-arm logs Re-arm after STOP stalled instead of every /go getting a silent 409.

Cleanup

  • Removes the dead script_finished aggregator and _finished_nodes, left over since dec95e9 (ClickUp 869fhjdp8).

Packaging

  • Requires cuemsutils >= 0.1.0rc17 (utils PR) for the schema value. The whole cluster must run the same engine, as with the follow relay.

Docs

  • CLAUDE.md describes the contract and the journal lines.
  • docs/unattended-playback.md gives the operator recipes: stop at the end, the play loop-back, rehearsal mode, an end-show button, versions.

Tests

  • test_action_cue, test_controller_stop_project and test_node_stop_project; test_controller_gating cleaned up.
  • The full suite passes on the .111 test box: 1428 passed.

Rig
On test2 (controller + node01), drills D0–D8 all pass:

  • the stop lands about 70 ms after the last media ends, and the cluster re-arms in about 150 ms;
  • the cross-node case works through the follow relay;
  • the remaining drills cover rehearsal mode, /gocue on the stop cue, the Auto-continue chain break, a simultaneous operator STOP and the kiosk flow.

Details are in cuems-RELATIONS/Plans/2026-10-15-engine-stop-project-actioncue.md §12. The plan was reviewed by Opus: APPROVE-WITH-CHANGES, with all findings folded in.

…ded show (869fhjdq5)

A stop_project ActionCue (cuems-utils >= 0.1.0rc17 carries the XSD value)
stops the show exactly as an operator STOP does. Every node reveals it;
the handler is pure and NodeEngine._action_result_sink sends the
controller a STATUS op {cue, run_seq} (nowait, like a follow message).
The controller validates it like _relay_follow (adopted sender, cue in the
project and of the right type, running, current run_seq), releases the
lock and runs stop_script: running=no, every cue 0, nodes re-arm. The
first valid message wins; the other nodes' messages are dropped at INFO.
The node never stops itself: a 3 s watchdog compares STOP/load receipts
and only logs when none arrived.

On the node the cue is a hard chain break: nothing after it is unrolled
at arrival and no go_at_end follow fires from it. Disabled, it is
transparent (rehearsal mode).

Two hardenings the unattended case needs: cue ADD/UPDATE operations are
ignored while the show is not running (a node's late start report after
a STOP could leave the stop cue at 1 or 100), and STOP restarts the arm
watchdog ("Re-arm after STOP stalled") so a failed re-arm is logged.

Removes the dead script_finished aggregator and _finished_nodes that
dec95e9 left on the controller (869fhjdp8). Requires cuemsutils >= rc17.

Tests: test_action_cue (stop_project, other project actions still
rejected), test_controller_stop_project (relay guards, ADD gate, arm
watchdog after STOP), test_node_stop_project (notify, watchdog, sink,
chain break), test_controller_gating cleaned. Targeted run on .111: 218
passed; the full suite runs when the rig window allows.

Design: cuems-RELATIONS Plans/2026-10-15-engine-stop-project-actioncue.md
…(869fhjdq5)

CLAUDE.md: running=yes after the last cue is by design; the stop_project
contract end to end, its journal lines, the chain break, the cue ADD gate
and the arm watchdog after STOP. docs/unattended-playback.md: the two
operator recipes (stop_project for play-once kiosks, play loop-back for
attract loops), placement, rehearsal, the re-arm window, persistent
auto-load and version requirements. docs/index.md links it.
@ibiltari
ibiltari requested a review from backenv as a code owner October 15, 2026 16:39
@ibiltari
ibiltari merged commit 698e777 into rc_1 Oct 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant