Appearance
A Trigger is the thing that makes work start without you — a polling loop or webhook listener that detects eligible work, claims it atomically, and spawns an ADW Script in a detached process.
Primitive
Trigger
Why it exists
Without a Trigger, you are the Trigger.
in-loop
You sit at the terminal
1check queue
2read ticket
3run plan command
4watch output
5kick off next phase
Throughput ceiling = your attention. The engineer is a bottleneck who has to be awake.
out-loop
Trigger sits at the terminal
1trigger polls source
2detects eligible work
3claims before spawn
4spawns detached ADW
5goes back to polling
Throughput ceiling = the machine. Presence drops. The system ships while you sleep.
The load-bearing invariant
Claim before spawn. Atomically.
01
Watch
detect eligible task
→
02
Claim
mark in-progress
→
03
Spawn
detached ADW
If you skip step 2
Two trigger instances double-process the same task.
Both see it eligible. Both spawn. The first ADW produces correct output; the second overwrites it or opens a duplicate PR. The claim is the critical section. Everything downstream assumes atomicity with the source system — GitHub label, Notion status, DB row lock, file rename. Pick a mechanism that can't race.
Two shapes
Cron vs Webhook. Pick by latency + source-readability.
Latency
5s – 60s (poll interval)
near-zero (event-driven)
Shape
while + sleep loop
HTTP server (FastAPI :8001)
Reliability
Self-healing — next poll catches missed events
Needs retry/replay; events can be lost
Use when
Source is readable (issue list, task board); latency OK
Source pushes (GitHub events); latency critical
Both converge on Work Claim semantics — whichever mechanism detects the work, it must mark in-progress atomically before spawning.
How the ADW is spawned
Detached. Always.
subprocess.run()
subprocess.run(cmd)
-- blocks until done --
Trigger stalls. Can't poll for new work while ADW runs. If trigger dies, ADW dies too.
VS
subprocess.Popen()
Popen(cmd,
start_new_session=True)
Trigger keeps polling. ADW runs independently. Observability comes through GitHub comments, not parent process.
Detached means the Trigger can't see what the ADW does. That's the right tradeoff — the ADW posts to GitHub/Slack/task board; the Trigger goes back to looking for the next job.
The discipline
The Trigger's job is to not be you.
Presence KPI drops when the system starts work on its own. Claim before spawn, or two workers do the same job. Detach the spawn, or the trigger can't keep watching. The Trigger is simple — but the atomicity and detachment decisions are the whole difference between "this works when I'm at the desk" and "this ships overnight."