feat(trigger-watcher): add chain field for sequential injection - #27
Merged
Conversation
JeanBaptisteRenard
changed the base branch from
feat/trigger-timeout-field
to
main
May 31, 2026 17:56
JeanBaptisteRenard
force-pushed
the
feat/trigger-chain
branch
from
May 31, 2026 19:35
e7db2dd to
80146be
Compare
Extends the trigger schema with a `chain` field allowing multi-step sequential PTY injection. Each step is waited on (busy→true→false transition) before the next is sent. The global timeout_ms covers the entire chain; per-step timeout_ms overrides it for that step's turn wait. New constants: MAX_CHAIN_LENGTH=20, BUSY_RISE_TIMEOUT_MS=2000. New helper: waitForTurnComplete() — detects busy rising edge then idle; handles the TOCTOU case where Claude answers so fast busy=true is never observed (2 s grace window, then assume instant-reply). Adds 11 new tests (chain happy path, mutual-exclusion, validation, timeout, session-exit mid-chain, per-step timeout_ms). All 33 tests pass.
JeanBaptisteRenard
force-pushed
the
feat/trigger-chain
branch
from
May 31, 2026 20:55
80146be to
01d14d7
Compare
JeanBaptisteRenard
added a commit
that referenced
this pull request
Jun 9, 2026
…-27-ipc-xss security: validate IPC file paths, sanitize viewer HTML, add CSP (port upstream #27)
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a
chainfield to the trigger JSON for sequential multi-step injection, mutually exclusive withcommand. Each step waits for the previous turn to complete (busy-rise → busy-fall) before the next command is injected.Stack note (REBASED 2026-05-31 21:34 CEST): Originally stacked on #26 (timeout default + per-trigger timeout_ms), this branch has been rebased onto main now that #26 (
ffbeb44) and #28 (8746466— liveness check) are merged. The chain loop now also performs the W7 liveness check before each step's write — defense-in-depth across PRs.Schema
{ "sessionId": "...", "wait": "idle", "chain": [ {"command": "/compact"}, {"command": "verify and commit"}, {"command": "open PR"} ], "timeout_ms": 600000 }chainis a non-empty array,length ≤ 20command(sameMAX_COMMAND_LENand forbidden-chars rules as the single-command path)timeout_msoverrides the global for that step only (capped at remaining global deadline)chainandcommandare mutually exclusive — both present →ok:false, error:"command and chain are mutually exclusive"Execution semantics
waitfield), inject step 0_cliBusyto flip true (rise, max 2s — TOCTOU window for instant replies), then false (turn complete) before injecting step N+1timeout_msis the deadline for the whole chain. If exceeded mid-chain → abort with{ok:false, partial:true, steps_completed:N, error:"chain timeout"}timeout_msbounds only that step's turn-completion wait (independent of remaining global, but capped by it)steps_completed: N(fully-completed step count, not including the failing one)Result shape
Success:
{ "ok": true, "sessionId": "...", "sent_at": "<step 0 sent_at>", "steps": [ {"idx": 0, "command": "/compact", "sent_at": "...", "waited_ms": 0}, {"idx": 1, "command": "verify and commit", "sent_at": "...", "waited_ms": 1234} ], "total_waited_ms": 1234 }Partial failure:
ok:false, partial:true, steps_completed:N, error:"...", steps:[...], total_waited_ms:NTests
36 trigger-watcher tests pass: 22 existing + 11 chain (CHAIN-1..CHAIN-11) + 3 W7 liveness (from #28).
The
makeChainCtxhelper now also stubspid: process.pidandisPtyAlive: () => trueso the new W7 liveness checks (pre-flight + per-step in the chain loop) don't break chain tests.Out-of-scope follow-ups
chmod +x .husky/pre-commitwould re-enable auto-lint+test on commits (separate cleanup PR)Taskfile.yamltest task description says "24 tests" but the suite is now at 36+