@felixdotgo/aidlc-kit 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEVELOPMENT.md +13 -26
- package/README.md +35 -39
- package/dist/assets/.agents/aidlc/orchestrator.md +1 -1
- package/dist/assets/.agents/aidlc/schemas/state.schema.json +2 -0
- package/dist/assets/.agents/aidlc/scripts/lib/assignment-store.mjs +94 -48
- package/dist/assets/.agents/aidlc/scripts/lib/context-runtime.mjs +5 -4
- package/dist/assets/.agents/aidlc/scripts/lib/loop-authority.mjs +21 -5
- package/dist/assets/.agents/aidlc/scripts/lib/loop-daemon.mjs +52 -78
- package/dist/assets/.agents/aidlc/scripts/lib/loop-drivers.mjs +88 -14
- package/dist/assets/.agents/aidlc/scripts/lib/loop-env.mjs +279 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-cli.mjs +20 -5
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-remote.mjs +10 -1
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-supervisor.mjs +2 -1
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet.mjs +3 -2
- package/dist/assets/.agents/aidlc/scripts/lib/loop-git.mjs +9 -3
- package/dist/assets/.agents/aidlc/scripts/lib/loop-holder.mjs +376 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-intake.mjs +11 -3
- package/dist/assets/.agents/aidlc/scripts/lib/loop-lease.mjs +67 -61
- package/dist/assets/.agents/aidlc/scripts/lib/loop-leases.mjs +268 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-local-workers.mjs +78 -17
- package/dist/assets/.agents/aidlc/scripts/lib/loop-runtime.mjs +42 -10
- package/dist/assets/.agents/aidlc/scripts/lib/loop-stream.mjs +66 -9
- package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-local.mjs +16 -56
- package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-run-local.mjs +12 -6
- package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-docker.mjs +14 -2
- package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-log.mjs +158 -0
- package/dist/assets/.agents/aidlc/scripts/lib/repo-head.mjs +22 -0
- package/dist/assets/.agents/aidlc/scripts/lib/store.mjs +11 -0
- package/dist/assets/.agents/aidlc/scripts/lib/task-runtime-migrate.mjs +75 -0
- package/dist/assets/.agents/aidlc/scripts/lib/task-runtime.mjs +97 -0
- package/dist/assets/.agents/aidlc/scripts/loop-entry.mjs +87 -4
- package/dist/assets/.agents/aidlc/scripts/loop.cmd +101 -0
- package/dist/assets/.agents/aidlc/scripts/loop.sh +71 -0
- package/dist/assets/.agents/aidlc/scripts/remote-state.mjs +10 -4
- package/dist/assets/.agents/aidlc/scripts/state.mjs +16 -8
- package/dist/assets/ui/changes.js +83 -0
- package/dist/assets/ui/common.js +664 -0
- package/dist/assets/ui/dashboard.css +281 -59
- package/dist/assets/ui/dashboard.js +77 -0
- package/dist/assets/ui/detail.js +159 -0
- package/dist/assets/ui/live-log.js +332 -0
- package/dist/services/aidlc-coordination/package.json +1 -1
- package/dist/services/aidlc-coordination/src/lifecycle-core.mjs +11 -0
- package/dist/src/cli/argv.js +10 -4
- package/dist/src/cli/commands.js +52 -22
- package/dist/src/cli/loop-launcher.d.ts +47 -0
- package/dist/src/cli/loop-launcher.js +322 -0
- package/dist/src/cli.js +3 -0
- package/dist/src/installer.js +4 -2
- package/dist/src/model/records.d.ts +4 -0
- package/dist/src/state/validate.js +5 -0
- package/dist/src/task-ui.d.ts +31 -52
- package/dist/src/task-ui.js +25 -1562
- package/dist/src/ui/assets.d.ts +14 -0
- package/dist/src/ui/assets.js +45 -0
- package/dist/src/ui/changes.d.ts +83 -0
- package/dist/src/ui/changes.js +498 -0
- package/dist/src/ui/containers.d.ts +71 -0
- package/dist/src/ui/containers.js +214 -0
- package/dist/src/ui/daemon.d.ts +75 -0
- package/dist/src/ui/daemon.js +232 -0
- package/dist/src/ui/data.d.ts +42 -0
- package/dist/src/ui/data.js +89 -0
- package/dist/src/ui/docs.d.ts +13 -0
- package/dist/src/ui/docs.js +39 -0
- package/dist/src/ui/files.d.ts +3 -0
- package/dist/src/ui/files.js +20 -0
- package/dist/src/ui/http.d.ts +14 -0
- package/dist/src/ui/http.js +80 -0
- package/dist/src/ui/live.d.ts +5 -0
- package/dist/src/ui/live.js +43 -0
- package/dist/src/ui/markdown.d.ts +2 -0
- package/dist/src/ui/markdown.js +127 -0
- package/dist/src/ui/options.d.ts +48 -0
- package/dist/src/ui/options.js +81 -0
- package/dist/src/ui/security.d.ts +34 -0
- package/dist/src/ui/security.js +38 -0
- package/dist/src/ui/server.d.ts +39 -0
- package/dist/src/ui/server.js +347 -0
- package/dist/src/ui/sse.d.ts +14 -0
- package/dist/src/ui/sse.js +281 -0
- package/dist/src/ui/views/board.d.ts +7 -0
- package/dist/src/ui/views/board.js +131 -0
- package/dist/src/ui/views/changes.d.ts +19 -0
- package/dist/src/ui/views/changes.js +154 -0
- package/dist/src/ui/views/components.d.ts +56 -0
- package/dist/src/ui/views/components.js +113 -0
- package/dist/src/ui/views/docs.d.ts +15 -0
- package/dist/src/ui/views/docs.js +64 -0
- package/dist/src/ui/views/layout.d.ts +44 -0
- package/dist/src/ui/views/layout.js +233 -0
- package/dist/src/ui/views/task.d.ts +25 -0
- package/dist/src/ui/views/task.js +320 -0
- package/dist/src/upgrade.js +5 -2
- package/dist/src/workflow.d.ts +4 -0
- package/dist/src/workflow.js +33 -1
- package/docs/README.md +48 -33
- package/docs/architecture.md +101 -38
- package/docs/command-reference.md +269 -93
- package/docs/configuration.md +62 -42
- package/docs/coordination-service.md +85 -36
- package/docs/design-decisions.md +35 -31
- package/docs/development.md +111 -61
- package/docs/loop-local-run.md +135 -402
- package/docs/loop-runbook.md +84 -105
- package/docs/operating-workflow.md +55 -42
- package/docs/testing-and-release.md +70 -51
- package/docs/troubleshooting.md +165 -69
- package/package.json +1 -1
package/docs/loop-local-run.md
CHANGED
|
@@ -1,228 +1,124 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Local loop walkthrough
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
single machine (`local` mode). All lead/workers use **OpenCode**.
|
|
3
|
+
Day-to-day operation of the loop in `local` mode on one machine: start the daemon, add tasks, watch, answer gates, resume. To enable the loop first, follow the [Loop setup runbook](./loop-runbook.md#local-mode).
|
|
5
4
|
|
|
6
|
-
>
|
|
5
|
+
> [!WARNING]
|
|
6
|
+
> Experimental, pre-1.0. See [Status and stability](./loop-runbook.md#status-and-stability).
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Commands use the published package (`npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit …`) or the installed launcher `./.agents/aidlc/scripts/loop.sh`; both drive the installed `loop-entry.mjs`. Source checkout: [Dogfooding this repository](./development.md#dogfooding-this-repository).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## How the loop works
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
- The **lead** runs `clarify` (gate `G0_confirm`), `plan` (`G1_review`), and `wrap` on the host, no Docker; **workers** run only `build` items (`G2_codereview`), isolated in Docker. Gates: [Operating the workflow](./operating-workflow.md).
|
|
13
|
+
- Each iteration reads `state.mjs task next`, runs one agent turn on the returned `nextAction`, re-reads canonical state, and updates the checkpoint/fingerprint.
|
|
14
|
+
- The loop **stops at every gate** and **never self-approves**; only a human on the trusted terminal or the signed-in dashboard approves.
|
|
15
|
+
- It also stops after the per-run `maxTurns` budget (a resumed run gets a fresh one), after `maxStallTurns` unchanged turns, or at `blocked`/`terminal`/`complete` (`loop.limits`: [Configuration](./configuration.md#optional-loop-configuration)).
|
|
16
|
+
- Config alone runs nothing; only `loop start` or `loop.sh up` runs the loop.
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
## Prerequisites
|
|
15
19
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
- The loop **stops at every gate** and **never self-approves** — approval happens only
|
|
21
|
-
through the trusted terminal.
|
|
22
|
-
- The loop also stops on its own when: the per-run `maxTurns` budget is exhausted (it
|
|
23
|
-
bounds one supervised run, not the task's lifetime — a resumed run gets a fresh budget),
|
|
24
|
-
`maxStallTurns` consecutive turns show no change, or the state is
|
|
25
|
-
`blocked`/`terminal`/`complete`. Both limits come from `loop.limits` (see
|
|
26
|
-
[configuration](./configuration.md#optional-loop-configuration)).
|
|
20
|
+
- Linux host with Docker (`docker info` must pass for the build phase) and a POSIX shell; Node.js ≥ 20.17.
|
|
21
|
+
- Lead provider CLI (`opencode`, `codex`, or `claude`) on the host `PATH`, matching `loop.agents.lead`.
|
|
22
|
+
- If any provider is `opencode`: `AIDLC_OPENCODE_MODEL` naming a model listed by `opencode models`.
|
|
23
|
+
- Worker credentials per provider/model: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `OPENCODE_API_KEY`. The worker image is built automatically ([Worker Docker image](#worker-docker-image)).
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
`loop start`.
|
|
25
|
+
## Set the environment
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## 2. Current configuration (already set up)
|
|
34
|
-
|
|
35
|
-
`.agents/config.json`:
|
|
36
|
-
|
|
37
|
-
```json
|
|
38
|
-
{
|
|
39
|
-
"loop": {
|
|
40
|
-
"mode": "local",
|
|
41
|
-
"agents": {
|
|
42
|
-
"lead": "opencode",
|
|
43
|
-
"workers": { "worker-a": "opencode", "worker-b": "opencode" }
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Quick check:
|
|
27
|
+
Put loop variables in `.agents/loop.env` (installed as a commented template, git-ignored through `.agents/.gitignore`) or `export` them in the shell that starts the daemon; exported values win. `loop start`, `loop up`, and a dashboard-started daemon load the file.
|
|
50
28
|
|
|
51
29
|
```sh
|
|
52
|
-
|
|
30
|
+
# .agents/loop.env
|
|
31
|
+
# Required for opencode unless "model" is set in opencode.json; use a model from `opencode models`:
|
|
32
|
+
AIDLC_OPENCODE_MODEL=<provider/model>
|
|
33
|
+
# Worker key for the build phase; read from ~/.local/share/opencode/auth.json when unset:
|
|
34
|
+
# OPENCODE_API_KEY=...
|
|
53
35
|
```
|
|
54
36
|
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## 3. Prerequisites
|
|
58
|
-
|
|
59
|
-
| Item | Requirement | Notes |
|
|
60
|
-
| --- | --- | --- |
|
|
61
|
-
| Linux host | required | Loop/fleet needs Docker + POSIX shell. |
|
|
62
|
-
| Node | ≥ 20.17 | The repo is currently on v24. |
|
|
63
|
-
| Docker engine | for build/worker | `docker info` must pass. |
|
|
64
|
-
| OpenCode CLI | `opencode` on PATH | `opencode --version` (currently v2.2.5). |
|
|
65
|
-
| Valid model | `AIDLC_OPENCODE_MODEL` | **Must be present in `opencode models`.** |
|
|
66
|
-
| Worker image | for build phase | Image containing the real `opencode` CLI (see §7). |
|
|
67
|
-
| Credentials | per model | `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` for workers. |
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## 4. Check configuration & sync
|
|
72
|
-
|
|
73
|
-
### 4.1 Check for drift (installed `.agents/` vs source `assets/`)
|
|
74
|
-
|
|
75
37
|
```sh
|
|
76
|
-
|
|
38
|
+
./.agents/aidlc/scripts/loop.sh check # what the daemon will see; secrets are never printed
|
|
77
39
|
```
|
|
78
40
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
loop: Isolated local worker dispatcher is not integrated; loop execution is unavailable
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### 4.2 Re-sync (human-only — requires a TTY)
|
|
86
|
-
|
|
87
|
-
```sh
|
|
88
|
-
npm run build
|
|
89
|
-
node dist/src/cli.js upgrade . --dry-run # preview the plan
|
|
90
|
-
node dist/src/cli.js upgrade . # apply, type "0.2.0" when prompted
|
|
91
|
-
```
|
|
41
|
+
`AIDLC_LOOP_EVENT_LOG` is set to `.agents/data/loop/ui-events.jsonl` automatically. All variables: [runbook](./loop-runbook.md#step-2--fill-in-agentsloopenv); lookup order: [Command reference](./command-reference.md#loop).
|
|
92
42
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
```sh
|
|
96
|
-
node dist/src/cli.js loop status --root . --task-id <task-id>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## 5. Run the loop end-to-end (local)
|
|
102
|
-
|
|
103
|
-
### 5.1 Set environment variables
|
|
104
|
-
|
|
105
|
-
```sh
|
|
106
|
-
# REQUIRED — use a model that is actually in the list:
|
|
107
|
-
export AIDLC_OPENCODE_MODEL=opencode-go/deepseek-v4-pro
|
|
108
|
-
|
|
109
|
-
# OPTIONAL — required ONLY for the web dashboard live log when you start the
|
|
110
|
-
# daemon manually. Must point at the exact file the UI reads:
|
|
111
|
-
export AIDLC_LOOP_EVENT_LOG="$PWD/.agents/data/loop/ui-events.jsonl"
|
|
112
|
-
|
|
113
|
-
# No need to set AIDLC_WORKER_DOCKER_IMAGE — the loop builds the image itself (see §7).
|
|
114
|
-
# Only the worker credential is needed when it reaches the build phase:
|
|
115
|
-
# export OPENAI_API_KEY=... or export ANTHROPIC_API_KEY=... (per model)
|
|
116
|
-
```
|
|
43
|
+
> [!IMPORTANT]
|
|
44
|
+
> A running daemon keeps the environment it started with. After editing `.agents/loop.env`, run `loop.sh down`, then `loop.sh up`; `loop up` warns when the file changed after the daemon started.
|
|
117
45
|
|
|
118
|
-
|
|
46
|
+
## Start the daemon and add tasks
|
|
119
47
|
|
|
120
48
|
```sh
|
|
121
|
-
|
|
49
|
+
./.agents/aidlc/scripts/loop.sh up # --open launches the browser; --no-ui starts only the daemon
|
|
50
|
+
./.agents/aidlc/scripts/loop.sh status # daemon, dashboard, environment
|
|
51
|
+
./.agents/aidlc/scripts/loop.sh logs # follow the daemon log
|
|
52
|
+
./.agents/aidlc/scripts/loop.sh down # stop both; --now cancels the running turn
|
|
122
53
|
```
|
|
123
54
|
|
|
124
|
-
|
|
125
|
-
> Both variables must be exported **in the same shell that starts the daemon** — the
|
|
126
|
-
> daemon and every lead/worker turn it spawns inherit only that process's environment.
|
|
127
|
-
> A daemon started *before* you exported `AIDLC_OPENCODE_MODEL` will keep failing with
|
|
128
|
-
> `opencode provider requires AIDLC_OPENCODE_MODEL` until it is restarted.
|
|
129
|
-
|
|
130
|
-
### 5.2 Start the daemon, then add tasks
|
|
55
|
+
`Ctrl-C` in the `up` terminal closes only the dashboard. Windows: `.agents\aidlc\scripts\loop.cmd`, same commands.
|
|
131
56
|
|
|
132
|
-
|
|
133
|
-
`loop start` fails with `Loop daemon already running (pid N)`). It does **not** read a
|
|
134
|
-
requirement:
|
|
57
|
+
Underneath, `loop start` runs the persistent daemon in the foreground and reads no requirement; one per project (a second fails with `Loop daemon already running (pid N)`):
|
|
135
58
|
|
|
136
59
|
```sh
|
|
137
|
-
|
|
138
|
-
npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit loop start --root .
|
|
139
|
-
|
|
140
|
-
# or from a source checkout (after `npm run build`):
|
|
141
|
-
node dist/src/cli.js loop start --root .
|
|
60
|
+
npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop start
|
|
142
61
|
```
|
|
143
62
|
|
|
144
|
-
The daemon only
|
|
145
|
-
|
|
146
|
-
you create interactively (Claude Code/Codex/OpenCode via `state.mjs task create`) is never
|
|
147
|
-
picked up, so the daemon cannot race an interactive lead on the same task.
|
|
63
|
+
- The daemon runs only **loop-owned** tasks: created through loop intake (`.agents/data/tasks/<id>/runtime/intake.json`) or holding a loop run record (`runtime/run.json`). An interactively created task (`state.mjs task create`) is never picked up, so the daemon cannot race an interactive lead.
|
|
64
|
+
- It runs one bounded run per actionable task in turn and keeps polling after a gate or completion.
|
|
148
65
|
|
|
149
|
-
Add a loop-owned task
|
|
66
|
+
Add a loop-owned task:
|
|
150
67
|
|
|
151
|
-
- **
|
|
152
|
-
|
|
153
|
-
- **Terminal** — the requirement is read from stdin (never an argument), max 8192 bytes; the
|
|
154
|
-
task id/title are derived from its first line (override with `--task-id`/`--title`):
|
|
68
|
+
- **Dashboard → New task** creates the task and starts the daemon if none is running.
|
|
69
|
+
- **Terminal intake** reads the requirement from stdin (never an argument), at most 8192 bytes; id and title derive from the first line (`--task-id`/`--title` override).
|
|
155
70
|
|
|
156
71
|
```sh
|
|
157
|
-
echo "Add PDF report export" | npx --package @felixdotgo/aidlc-kit@0.
|
|
158
|
-
echo "Add PDF report export" | node
|
|
159
|
-
# or the installed entry point directly:
|
|
160
|
-
echo "Add PDF report export" | node .agents/aidlc/scripts/loop-entry.mjs intake "" .
|
|
72
|
+
echo "Add PDF report export" | npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop intake
|
|
73
|
+
echo "Add PDF report export" | node .agents/aidlc/scripts/loop-entry.mjs intake "" . # installed entry point
|
|
161
74
|
```
|
|
162
75
|
|
|
163
|
-
Intake refuses (
|
|
164
|
-
pause it first. Other actionable loop-owned tasks are fine — the daemon runs them in turn.
|
|
76
|
+
- Intake refuses (creates nothing) while an **interactive** task is actionable; finish or pause it first.
|
|
165
77
|
|
|
166
|
-
Stopping
|
|
167
|
-
current turn, the second cancels the in-flight agent turn, the third exits immediately. A
|
|
168
|
-
stopped run is recorded as `stopped` (the task is **not** paused) and resumes on the next
|
|
169
|
-
`loop start`. Note that a terminal `Ctrl-C` is also delivered to the agent child process, so
|
|
170
|
-
the in-flight turn usually ends right away even on the first press; it is still recorded as
|
|
171
|
-
`stopped`, not as a transport failure. `aidlc-kit loop start` stays in the foreground for
|
|
172
|
-
the whole shutdown (it forwards `SIGTERM` to the daemon and lets the terminal deliver
|
|
173
|
-
`Ctrl-C`), so the second and third presses still reach the daemon.
|
|
78
|
+
Stopping (`Ctrl-C` or `SIGTERM`) is staged: first signal stops after the current turn, second cancels the in-flight agent turn, third exits immediately.
|
|
174
79
|
|
|
175
|
-
|
|
80
|
+
- A stopped run is recorded as `stopped` (the task is **not** paused) and resumes on the next `loop start`. A terminal `Ctrl-C` also reaches the agent child, so the turn usually ends on the first press; still `stopped`, not a transport failure.
|
|
81
|
+
- `aidlc-kit loop start` stays in the foreground for the whole shutdown (forwards `SIGTERM`, lets the terminal deliver `Ctrl-C`), so later presses reach the daemon.
|
|
176
82
|
|
|
177
|
-
|
|
178
|
-
# via npx:
|
|
179
|
-
npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit loop status --task-id <task-id> --root .
|
|
83
|
+
## Watch status
|
|
180
84
|
|
|
181
|
-
|
|
182
|
-
|
|
85
|
+
```sh
|
|
86
|
+
npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop status --task-id <task-id>
|
|
183
87
|
```
|
|
184
88
|
|
|
185
|
-
Prints `authority`, `record` (run record), and `nextAction`
|
|
186
|
-
(`classification` = `run_phase` / `await_user` / `blocked` / `complete`...).
|
|
89
|
+
Prints `authority`, `record` (the loop run record), and `nextAction` (`classification`: `run_phase`, `await_user`, `blocked`, `complete`, …).
|
|
187
90
|
|
|
188
|
-
|
|
91
|
+
## Approve a gate or send feedback
|
|
92
|
+
|
|
93
|
+
Answer a gate on the trusted host terminal or the signed-in dashboard, never from the lead or a worker, never with piped input:
|
|
189
94
|
|
|
190
95
|
```sh
|
|
191
96
|
node .agents/aidlc/scripts/loop-gate.mjs <task-id>
|
|
192
|
-
# type: approve
|
|
97
|
+
# type: approve -> approves this exact review and advances the phase
|
|
98
|
+
# type: <any other text> -> feedback: the task stays at this gate
|
|
193
99
|
```
|
|
194
100
|
|
|
195
|
-
|
|
196
|
-
|
|
101
|
+
- Prints the exact review (task, phase, gate, artifact digests, and at `G2_codereview` the integration commit), then prompts `Type approve to approve this exact review, or type feedback to send guidance back to the loop:`.
|
|
102
|
+
- **`approve`** is the only answer that moves the task forward; if the review changes while you type, it fails closed.
|
|
103
|
+
- **Any other text is feedback**: recorded as evidence `Cancelled gate wait at <gate>: <feedback>`; the task returns to `active` at the same gate, and the next lead turn revises the review and re-presents the **same** gate.
|
|
104
|
+
- The dashboard detail page offers the same actions, **Send feedback (stay at gate)** and **✓ Approve** ([dashboard](#use-the-web-dashboard)).
|
|
197
105
|
|
|
198
|
-
|
|
106
|
+
## Resume after a gate or a pause
|
|
199
107
|
|
|
200
|
-
There is **no `loop resume`**
|
|
201
|
-
and it auto-resumes every task whose derived `nextAction` is `run_phase` (an *actionable*
|
|
202
|
-
task). What you do depends on why the task stopped:
|
|
108
|
+
There is **no `loop resume`** in either mode; the daemon auto-resumes every task whose `nextAction` is `run_phase` (*actionable*).
|
|
203
109
|
|
|
204
|
-
- **After approving a gate
|
|
205
|
-
|
|
206
|
-
- **After a pause** (e.g. an agent transport failure or the per-run turn limit) — the loop
|
|
207
|
-
marks the task `paused` (`nextAction` becomes `blocked`), which is **not** actionable, so
|
|
208
|
-
the daemon skips it. Fix the root cause, then set the task back to `active` (or press
|
|
209
|
-
**resume** on the dashboard, which does exactly this):
|
|
110
|
+
- **After approving a gate**: nothing; the next poll runs the next lead turn.
|
|
111
|
+
- **After a pause** (agent transport failure, per-run turn limit): the task is `paused` (`nextAction` `blocked`) and skipped. Fix the cause, then press **resume** on the dashboard or run the command below; the next poll (default about 5 s) picks it up.
|
|
210
112
|
|
|
211
113
|
```sh
|
|
212
|
-
node .agents/aidlc/scripts/state.mjs task status <task-id> --status active
|
|
114
|
+
node .agents/aidlc/scripts/state.mjs task status <task-id> --status active # or: loop-entry.mjs resume-task <task-id> .
|
|
213
115
|
```
|
|
214
116
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
> `aidlc-kit loop resume`/`loop-entry.mjs resume` fails closed with
|
|
218
|
-
> `loop resume is removed; the daemon auto-resumes actionable tasks — run 'loop start', and re-activate a paused task from the dashboard (resume) or with the task status command`.
|
|
219
|
-
> Use `state.mjs task status --status active` (or `loop-entry.mjs resume-task <task-id> .`)
|
|
220
|
-
> instead of trying to "resume the loop".
|
|
117
|
+
- `aidlc-kit loop resume` and `loop-entry.mjs resume` fail closed with `loop resume is removed; the daemon auto-resumes actionable tasks — run 'loop start', and re-activate a paused task from the dashboard (resume) or with the task status command`.
|
|
221
118
|
|
|
222
|
-
|
|
119
|
+
## Follow the streaming log
|
|
223
120
|
|
|
224
|
-
|
|
225
|
-
what the lead is doing during a long turn:
|
|
121
|
+
Progress goes to **stderr** (stdout stays the final JSON):
|
|
226
122
|
|
|
227
123
|
```
|
|
228
124
|
━━ turn 1 · phase clarify · agent opencode ━━
|
|
@@ -233,263 +129,100 @@ what the lead is doing during a long turn:
|
|
|
233
129
|
━━ turn done ━━
|
|
234
130
|
```
|
|
235
131
|
|
|
236
|
-
|
|
237
|
-
instructions) and moves on to the next actionable task; after you approve in a second
|
|
238
|
-
terminal via `loop-gate.mjs <id>` (or on the dashboard), the next poll resumes that task.
|
|
239
|
-
The loop never self-approves.
|
|
240
|
-
|
|
241
|
-
Streamed events: `turn_start`/`turn_end` (turn boundary + phase + agent), `agent_text`
|
|
242
|
-
(lead text, capped at 4096 chars/chunk), `agent_tool` (tool being used such as
|
|
243
|
-
`grep`/`read`/`glob`/`shell`), `lifecycle_command` (shell result + exit code), and `gate`
|
|
244
|
-
(gate view), plus daemon events `daemon_start`, `daemon_poll`, `daemon_poll_error` (the task
|
|
245
|
-
list could not be read; the daemon keeps polling), `daemon_turn`, `daemon_turn_error`, and
|
|
246
|
-
`loop_stopped`. A task whose run throws, or ends `blocked`/`reconcile`, is retried with
|
|
247
|
-
exponential backoff (poll interval doubled per failure, capped at 10 minutes). In the build
|
|
248
|
-
phase, `build_deferred` names a ready item held back for a later batch (`reason`: overlaps
|
|
249
|
-
another item, a busy path held by an active assignment, an unresolved assignment, or
|
|
250
|
-
`capacity` — at most one item per configured worker per batch). Every event of a run
|
|
251
|
-
carries its `taskId`.
|
|
252
|
-
|
|
253
|
-
### 5.7 Web dashboard (`aidlc-kit ui`)
|
|
132
|
+
A clarify or plan turn can take minutes without output. At a gate the daemon prints the **gate view** and moves on. Every event carries its `taskId`:
|
|
254
133
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
134
|
+
| Event | Meaning |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| `turn_start` / `turn_end` | Turn boundary, with phase and agent. |
|
|
137
|
+
| `agent_text` | Lead text, capped at 4096 characters per chunk. |
|
|
138
|
+
| `agent_tool` | Tool in use (`grep`, `read`, `glob`, `shell`, …). |
|
|
139
|
+
| `lifecycle_command` | Shell result and exit code. |
|
|
140
|
+
| `gate` | Gate view. |
|
|
141
|
+
| `daemon_start`, `daemon_poll`, `daemon_turn`, `loop_stopped` | Daemon lifecycle. |
|
|
142
|
+
| `daemon_poll_error` | The task list could not be read; the daemon keeps polling. |
|
|
143
|
+
| `daemon_turn_error` | A task run threw (or ended `blocked`/`reconcile`); retried with exponential backoff (poll interval doubled per failure, capped at 10 minutes). |
|
|
144
|
+
| `build_deferred` | A ready build item held for a later batch. `reason`: overlaps another item, busy path held by an active assignment, unresolved assignment, or `capacity` (one item per configured worker per batch). |
|
|
262
145
|
|
|
263
|
-
|
|
264
|
-
URL** (`http://127.0.0.1:4173/#token=…`). Open it (or pass `--open` to launch the browser):
|
|
265
|
-
the page stores the token in `localStorage` and strips it from the address bar, so mutating
|
|
266
|
-
actions (new task, resume, gate approve) work without pasting anything. The token is new on
|
|
267
|
-
every start; use `--token-file ~/.aidlc-ui-token` (outside the project, mode `600`, created
|
|
268
|
-
if missing) to keep the browser signed in across restarts. **⚙ Settings** still
|
|
269
|
-
accepts a pasted token. Requests from another origin or with a foreign `Host` header are
|
|
270
|
-
rejected `403` (see [Command reference](./command-reference.md#dashboard-authentication)).
|
|
271
|
-
The header shows the authority (`authority · local`) and whether the daemon is running. The page follows the system light/dark preference
|
|
272
|
-
automatically (Bulma plus the flat `assets/ui/dashboard.css` theme layer) and uses the full
|
|
273
|
-
window width; results of actions appear as toasts in the bottom-right corner. Shortcuts:
|
|
274
|
-
<kbd>N</kbd> new task, <kbd>/</kbd> search, <kbd>Esc</kbd> close the side panel or a dialog.
|
|
275
|
-
|
|
276
|
-
Where things live (this is the #1 source of confusion):
|
|
277
|
-
|
|
278
|
-
- **Gate approval button is only on the full task detail page** (`/tasks/<task-id>`), **not
|
|
279
|
-
on the dashboard**. Tasks waiting at a gate are listed under **Needs your review** at the
|
|
280
|
-
top of the dashboard; **Open review →** jumps to their detail page. Otherwise click a task to
|
|
281
|
-
open it in the **side panel** (it slides in from the right and adds `?task=<task-id>` to the
|
|
282
|
-
URL, so refresh or a shared link reopens it and Back closes it) and press **Open full page ↗**,
|
|
283
|
-
or ctrl/cmd-click / middle-click the task link. Both the side panel and the detail page show a
|
|
284
|
-
horizontal **progress** stepper (clarify → plan → build → wrap → done) above the artifacts. On the detail page the **Approve · `<review step>`** panel (approval note + green
|
|
285
|
-
**✓ Approve** button) appears only while the task is `blocked_on_user`. If the gate's
|
|
286
|
-
structural checks no longer pass, the page lists the failing checks instead of the gate view.
|
|
287
|
-
- **New task → Create task** runs loop intake (§5.2) and starts the daemon only if none is
|
|
288
|
-
running (its stderr goes to `.agents/data/loop/daemon.log`). A toast shows the new task id,
|
|
289
|
-
or the real intake error (for example an actionable interactive task).
|
|
290
|
-
- **Stat cards, search, and the status/risk filters** narrow the Kanban and List views in the
|
|
291
|
-
browser only; they never call the API or change state.
|
|
292
|
-
- **Task buttons follow the status:** a `paused` task shows **resume** (sets it back to
|
|
293
|
-
`active`); a `blocked_on_user` task shows **approve**, which opens the detail page.
|
|
294
|
-
- **The live log (bottom of the detail page)** shows only that task's events (on connect, the
|
|
295
|
-
last 200 of them found in the most recent 256 KB of the file, then live). It reads the fixed file `.agents/data/loop/ui-events.jsonl`, which
|
|
296
|
-
rotates to `.jsonl.1` at 5 MB. The daemon only writes there when `AIDLC_LOOP_EVENT_LOG`
|
|
297
|
-
points at that exact path: a daemon started from the dashboard sets it automatically; a
|
|
298
|
-
**manually started** daemon needs the export from §5.1.
|
|
299
|
-
|
|
300
|
-
Gate approval stays equally available on the trusted terminal (`loop-gate.mjs`, §5.4), which
|
|
301
|
-
needs no token.
|
|
302
|
-
|
|
303
|
-
---
|
|
304
|
-
|
|
305
|
-
## 6. Lifecycle (phases / gates)
|
|
306
|
-
|
|
307
|
-
| Phase | Who runs it | Stops at gate |
|
|
308
|
-
| --- | --- | --- |
|
|
309
|
-
| clarify | lead | `G0_confirm` |
|
|
310
|
-
| plan | lead | `G1_review` |
|
|
311
|
-
| build | workers (Docker) | `G2_codereview` |
|
|
312
|
-
| wrap | lead | → `complete` |
|
|
313
|
-
|
|
314
|
-
`clarify`, `plan`, `wrap` run on the host, **no Docker needed**.
|
|
315
|
-
Only `build` needs the worker image + credentials (§7).
|
|
316
|
-
|
|
317
|
-
---
|
|
318
|
-
|
|
319
|
-
## 7. Worker Docker image (build phase only)
|
|
320
|
-
|
|
321
|
-
The build phase fans workers out into isolated Docker containers and needs an image
|
|
322
|
-
containing the worker provider CLI (`opencode`/`codex`/`claude`). **You no longer need to
|
|
323
|
-
build it by hand following a guide**:
|
|
324
|
-
|
|
325
|
-
- The official worker image is **shipped with the package**
|
|
326
|
-
(`assets/aidlc/docker/Dockerfile.<provider>`).
|
|
327
|
-
- Run a single command to build it (default provider `opencode`):
|
|
146
|
+
## Use the web dashboard
|
|
328
147
|
|
|
329
148
|
```sh
|
|
330
|
-
npx @felixdotgo/aidlc-kit loop
|
|
331
|
-
# --provider codex | --provider claude ; default tag aidlc-worker-<provider>:local
|
|
149
|
+
npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit ui . # loop.sh up starts the same dashboard
|
|
332
150
|
```
|
|
333
151
|
|
|
334
|
-
|
|
335
|
-
(`loop.workerImage`); the supervisor reads it automatically, so you **don't need to
|
|
336
|
-
`export AIDLC_WORKER_DOCKER_IMAGE`** manually.
|
|
337
|
-
- When the loop reaches the build phase and an image is missing, the supervisor
|
|
338
|
-
**auto-builds** the image for the right provider before preflight, so you usually don't
|
|
339
|
-
need to run the command above proactively.
|
|
152
|
+
Branded **Loop**, binds `127.0.0.1:4173` by default and prints `Open: http://127.0.0.1:4173` (or pass `--open`).
|
|
340
153
|
|
|
341
|
-
|
|
342
|
-
tests**; the real image is built from the shipped Dockerfile (base `node:24-bookworm-slim`,
|
|
343
|
-
CLI installed via `npm install -g`).
|
|
154
|
+
**Access**
|
|
344
155
|
|
|
345
|
-
|
|
346
|
-
-
|
|
347
|
-
runs non-root + `--read-only`, so the CLI must be on the system `PATH` (npm global →
|
|
348
|
-
`/usr/local/bin`).
|
|
349
|
-
- `opencode` uses `@opencode/cli` (OpenCode 2), **not** `opencode-ai` (OpenCode 1).
|
|
350
|
-
- Worker credentials still need to be exported (per model): `OPENAI_API_KEY` /
|
|
351
|
-
`ANTHROPIC_API_KEY` / `OPENCODE_API_KEY`.
|
|
352
|
-
- Preflight runs `docker run ... --entrypoint <cli> --version`; a missing or invalid
|
|
353
|
-
binary fails before any worker starts.
|
|
156
|
+
- There is no login or session token: the dashboard is for a trusted local machine or internal network. Mutating actions (new task, resume, gate feedback, gate approve) work right away from the page.
|
|
157
|
+
- Another origin, a foreign `Host` header, or a request that does not look like the dashboard's own `fetch` gets `403` ([Dashboard access](./command-reference.md#dashboard-access)). Binding to a non-loopback address prints a warning that the dashboard has no authentication.
|
|
354
158
|
|
|
355
|
-
|
|
159
|
+
**Header and updates**
|
|
356
160
|
|
|
357
|
-
|
|
161
|
+
- Header: authority (`authority · local`), daemon state, and a bell listing tasks needing review. The daemon pill turns amber (**daemon · N errors**) while a turn or poll keeps failing; hover for messages.
|
|
162
|
+
- Pages poll about every 1.5 s and patch only what changed. An unreachable server shows a **reconnecting…** pill and polling backs off.
|
|
163
|
+
- A new gate updates the bell, the tab title (`(2) Loop`), and a **Review needed** toast; with **Settings → notifications** on, a browser notification too (permission is asked only then).
|
|
164
|
+
- Light/dark follows the system unless pinned in **Settings**. Shortcuts: <kbd>N</kbd> new task, <kbd>/</kbd> search, <kbd>Esc</kbd> close.
|
|
358
165
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
```sh
|
|
362
|
-
export AIDLC_OPENCODE_MODEL=opencode-go/deepseek-v4-pro
|
|
363
|
-
|
|
364
|
-
node .agents/aidlc/scripts/loop.mjs run <task-id> --agent opencode --max-turns 12 --root .
|
|
365
|
-
node .agents/aidlc/scripts/loop.mjs status <task-id> --root .
|
|
366
|
-
node .agents/aidlc/scripts/loop.mjs resume <task-id> --root .
|
|
367
|
-
```
|
|
166
|
+
**Where things live**
|
|
368
167
|
|
|
369
|
-
|
|
370
|
-
|
|
168
|
+
| Where | What |
|
|
169
|
+
| --- | --- |
|
|
170
|
+
| Header bell | Tasks waiting at a gate (5 newest; **Load more**). A `blocked_on_user` card shows **review**, which opens the detail page. |
|
|
171
|
+
| Card | Title only (id on hover and in search). Click opens the side panel and adds `?task=<task-id>` to the URL (or the full page, per **Settings**); ctrl/cmd/middle-click opens the full page in a new tab, shift-click in this tab. |
|
|
172
|
+
| Side panel | Stepper (clarify → plan → build → wrap → done), artifacts, last 20 important log lines, a copy button for the id, **Open full page ↗**; at a gate, **Open review →**. |
|
|
173
|
+
| Detail page `/tasks/<task-id>` | The only place with gate approval and feedback; containers, full live log — the one place to follow everything a task does. |
|
|
174
|
+
| Settings (header ⚙) | Browser-only preferences: theme, live-update interval or pause, browser notifications for reviews, live log defaults, diff wrap / ignore whitespace, container log tail size, card click target. **Reset to defaults** restores them. |
|
|
175
|
+
| Containers (detail page) | Every worker container the loop ran for the task (local or fleet; same layout), newest first: worker, item, turn, `running` / `exited <code>` / `signal`, start time and duration, host when recorded elsewhere. **Log** opens the raw output of that assignment (all turns, stdout and stderr unredacted) with **Follow** while it runs; the tail size comes from Settings. `docker · unavailable` means the state comes from the index only. |
|
|
176
|
+
| Review panel (while `blocked_on_user`) | **Feedback** textarea + **Send feedback (stay at gate)**; **Approve** note + **✓ Approve** (popup; only **Confirm approve** sends). |
|
|
177
|
+
| Approve semantics | The note is audit provenance, never feedback. A moved gate is refused with `409`. After feedback a **feedback pending** pill shows until approval; failing structural checks replace the gate view. |
|
|
178
|
+
| New task (side panel) | Markdown editor. **Create task** runs loop intake and starts the daemon if none runs (stderr → `.agents/data/loop/daemon.log`); a toast shows the id or the intake error. |
|
|
179
|
+
| Search and filters | Browser-only; never call the API. The **done** column shows 8 recent tasks; **Show N more** expands it. |
|
|
180
|
+
| resume | On `paused` tasks; sets them back to `active`. |
|
|
181
|
+
| Live log (detail page) | Lines `time · actor · what happened`, grouped by turn. **Important** (default) hides bookkeeping, **All** shows everything, **Raw JSON** shows the events. |
|
|
182
|
+
| Changes `/tasks/<id>/changes` | Files and diff per work item from the commits workers recorded; otherwise the task range from the task's `baseCommit` to its `finalCommit` (or `HEAD` plus the working tree while open) — so a task driven from the terminal, or a finished task whose worker worktrees are gone, still shows its changes; last resort, the uncommitted working tree. **Wrap lines** and **Ignore whitespace** toggles. |
|
|
371
183
|
|
|
372
|
-
|
|
184
|
+
Live log files: the log replays the last 200 events of `.agents/data/tasks/<task-id>/runtime/events.jsonl` (1 MiB, one `.1` generation; a file an older version left in `.agents/data/loop/events/` is read until `loop migrate-data` moves it), then follows live; older tasks fall back to the global `.agents/data/loop/ui-events.jsonl` (rotated to `.jsonl.1` at 5 MB), written only when `AIDLC_LOOP_EVENT_LOG` points at it. Container output is separate: `.agents/data/tasks/<task-id>/runtime/workers/<assignment>.log` (5 MiB, one `.log.1` generation) next to `index.json`, never committed. **Docs** in the header opens these guides.
|
|
373
185
|
|
|
374
|
-
##
|
|
186
|
+
## Worker Docker image
|
|
375
187
|
|
|
376
|
-
|
|
188
|
+
The build phase runs workers in Docker containers whose image contains the provider CLI (`opencode`, `codex`, or `claude`):
|
|
377
189
|
|
|
378
|
-
|
|
190
|
+
- Dockerfiles ship with the package (`assets/aidlc/docker/Dockerfile.<provider>`); the supervisor **auto-builds** a missing image before preflight and records the name in `.agents/config.json` (`loop.workerImage`), so `AIDLC_WORKER_DOCKER_IMAGE` is not needed.
|
|
191
|
+
- Build ahead of time (default provider `opencode`; default tag `aidlc-worker-<provider>:local`):
|
|
379
192
|
|
|
380
|
-
```sh
|
|
381
|
-
|
|
382
|
-
```
|
|
193
|
+
```sh
|
|
194
|
+
npx @felixdotgo/aidlc-kit loop worker-image --provider opencode # or codex | claude
|
|
195
|
+
```
|
|
383
196
|
|
|
384
|
-
|
|
385
|
-
`
|
|
197
|
+
- Images named `aidlc-worker-*-test:local` contain only a fake CLI for tests. The real image is `node:24-bookworm-slim` (Debian/glibc, because `opencode` is a dynamically linked ELF) with the CLI from `npm install -g`.
|
|
198
|
+
- Each worker container is started with labels `aidlc.task`, `aidlc.item`, `aidlc.worker`, and `aidlc.assignment` (`docker ps --filter label=aidlc.task=<task-id>` lists a task's workers), and its stdout/stderr are teed unredacted into the task's `runtime/workers/` log while the live log keeps only summaries.
|
|
199
|
+
- The container runs non-root and `--read-only`, so the CLI must be on the system `PATH` (npm global → `/usr/local/bin`). `opencode` uses `@opencode/cli` (OpenCode 2), **not** `opencode-ai` (OpenCode 1).
|
|
200
|
+
- Worker credentials come from the environment, per model: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `OPENCODE_API_KEY`. Preflight runs `docker run … --entrypoint <cli> --version`; a missing or invalid binary fails before any worker starts.
|
|
386
201
|
|
|
387
|
-
|
|
388
|
-
"agent transport failure: opencode reported an error: Model unavailable: opencode-go/flint-40b-free"
|
|
389
|
-
```
|
|
202
|
+
## Quick lead-only run
|
|
390
203
|
|
|
391
|
-
|
|
392
|
-
the daemon, then re-activate the task (§5.5).
|
|
393
|
-
|
|
394
|
-
Raw OpenCode log (full stacktrace) if needed:
|
|
204
|
+
A single lead with no Docker or workers, using the installed loop runner directly:
|
|
395
205
|
|
|
396
206
|
```sh
|
|
397
|
-
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
> Note: if the lead runs for a long time without output, it is **not hanging** — a
|
|
401
|
-
> clarify/plan turn with a free model can take a few minutes. Streaming (§5.6) now lets
|
|
402
|
-
> you see each tool/text the lead is running.
|
|
403
|
-
|
|
404
|
-
### 9.2 `Isolated local worker dispatcher is not integrated`
|
|
405
|
-
|
|
406
|
-
The installed `.agents/` is stale (missing `createIsolatedLocalSupervisor`). Re-sync per
|
|
407
|
-
§4.2.
|
|
408
|
-
|
|
409
|
-
### 9.3 `Loop requires a configured lead and worker providers`
|
|
410
|
-
|
|
411
|
-
`loop.mode` is enabled but `loop.agents.lead` or `loop.agents.workers` is missing. Check §2.
|
|
412
|
-
|
|
413
|
-
### 9.4 `Requested mode does not match configured authority`
|
|
414
|
-
|
|
415
|
-
The `--mode` passed in differs from `loop.mode` in config. Drop `--mode` to use the config
|
|
416
|
-
value.
|
|
207
|
+
export AIDLC_OPENCODE_MODEL=<provider/model>
|
|
417
208
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
without it keeps failing until restarted.
|
|
423
|
-
|
|
424
|
-
### 9.6 Web dashboard live log is empty / stuck on "connecting…"
|
|
209
|
+
node .agents/aidlc/scripts/loop.mjs run <task-id> --agent opencode --max-turns 12 --root .
|
|
210
|
+
node .agents/aidlc/scripts/loop.mjs status <task-id> --root .
|
|
211
|
+
node .agents/aidlc/scripts/loop.mjs resume <task-id> --root .
|
|
212
|
+
```
|
|
425
213
|
|
|
426
|
-
|
|
427
|
-
writes there when `AIDLC_LOOP_EVENT_LOG` points at that exact path. A manually started
|
|
428
|
-
daemon without that export produces no events — see §5.1. Restart the daemon after setting
|
|
429
|
-
it.
|
|
430
|
-
- The live log is only on the task **detail** page (`/tasks/<id>`), not the dashboard.
|
|
431
|
-
- A stopped daemon produces no events. The dashboard header shows whether it is running;
|
|
432
|
-
check `.agents/data/loop/daemon.log` for start-up errors.
|
|
433
|
-
- The detail-page log is filtered to that task; daemon-wide events (`daemon_poll`) appear
|
|
434
|
-
only in the raw file.
|
|
435
|
-
- Check `tail -f .agents/data/loop/ui-events.jsonl` directly: if the file grows with
|
|
436
|
-
`daemon_poll` lines, the daemon is healthy and only the browser side is stale (hard refresh).
|
|
214
|
+
The JSON output reports `status` (`gate`, `paused`, `blocked`, or `complete`) with `stopReason` and `nextAction`.
|
|
437
215
|
|
|
438
|
-
|
|
216
|
+
## Troubleshooting
|
|
439
217
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
218
|
+
- [Loop stops, pauses, or never starts](./troubleshooting.md#loop-stops-pauses-or-never-starts)
|
|
219
|
+
- [Dashboard live log or actions do nothing](./troubleshooting.md#dashboard-live-log-or-actions-do-nothing)
|
|
220
|
+
- [Loop leases, locks and claims](./troubleshooting.md#loop-leases-locks-and-claims) — "already running", unapprovable gate, stuck claims
|
|
221
|
+
- [Build items deferred](./troubleshooting.md#build-items-deferred-or-build-dispatch-failure-unresolved-assignment) — `build_deferred`, `build dispatch failure`
|
|
443
222
|
|
|
444
|
-
|
|
445
|
-
node .agents/aidlc/scripts/state.mjs task show <task-id>
|
|
446
|
-
```
|
|
223
|
+
## Related
|
|
447
224
|
|
|
448
|
-
|
|
449
|
-
cause is almost always the missing/invalid `AIDLC_OPENCODE_MODEL` (or an unavailable model).
|
|
450
|
-
For `turn limit reached` the run used its whole per-run `maxTurns` budget without reaching a
|
|
451
|
-
gate; raise `loop.limits.maxTurns` if the phase legitimately needs more turns. Then:
|
|
452
|
-
|
|
453
|
-
1. Fix the environment (`opencode models`, export `AIDLC_OPENCODE_MODEL`).
|
|
454
|
-
2. Kill and restart the daemon with the corrected environment (§5.1).
|
|
455
|
-
3. Set the task back to actionable:
|
|
456
|
-
|
|
457
|
-
```sh
|
|
458
|
-
node .agents/aidlc/scripts/state.mjs task status <task-id> --status active
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
### 9.8 Clicking "approve" (or "resume") on the web UI does nothing
|
|
462
|
-
|
|
463
|
-
- The gate **approve** form exists only on the full detail page `/tasks/<id>`; the
|
|
464
|
-
dashboard's **approve** button on a `blocked_on_user` card just opens that page.
|
|
465
|
-
- Mutating actions need the session token; without it they return `401` (shown inline under
|
|
466
|
-
the button). Open the login URL printed by `aidlc-kit ui` (the token changes on every
|
|
467
|
-
restart unless you use `--token-file`), or paste the token into **Settings**.
|
|
468
|
-
- A `403` means the request was refused before the token check: the page was opened under a
|
|
469
|
-
different host name than the one the server is bound to (use the printed URL; any loopback
|
|
470
|
-
name works when bound to loopback), or the request came from another origin.
|
|
471
|
-
- **resume** only applies to a `paused` task; on any other status it returns `409` with the
|
|
472
|
-
reason (a gate wait must be approved instead). A resumed task runs only if it is
|
|
473
|
-
loop-owned and a daemon is running (§5.2).
|
|
474
|
-
- If approve does *literally nothing* (no inline result, no error, no reload) and you are on
|
|
475
|
-
an old build: open the browser DevTools console and look for
|
|
476
|
-
`SyntaxError: Identifier 'post' has already been declared`. That was a UI bug (the detail
|
|
477
|
-
page declared `const post` twice, silently disabling the approve handler) fixed in source —
|
|
478
|
-
rebuild/repack from a checkout that includes the fix, restart `ui`, and hard-refresh
|
|
479
|
-
(Ctrl+Shift+R) to drop the cached page.
|
|
480
|
-
|
|
481
|
-
### 9.9 Build items wait (`build_deferred`) or the task pauses with `build dispatch failure`
|
|
482
|
-
|
|
483
|
-
`build_deferred` is normal: ready items whose owned paths overlap, or that exceed the number
|
|
484
|
-
of workers, run in a later batch. A pause with `build dispatch failure: Unresolved assignment …`
|
|
485
|
-
means an earlier assignment still holds the paths every ready item needs; the loop never
|
|
486
|
-
releases it on its own. See [Troubleshooting](./troubleshooting.md#build-items-deferred-or-build-dispatch-failure-unresolved-assignment).
|
|
487
|
-
|
|
488
|
-
---
|
|
489
|
-
|
|
490
|
-
## 10. References
|
|
491
|
-
|
|
492
|
-
- [Loop setup runbook](./loop-runbook.md) — the official runbook.
|
|
225
|
+
- [Loop setup runbook](./loop-runbook.md) — enabling and configuring the loop.
|
|
493
226
|
- [Configuration](./configuration.md#optional-loop-configuration) — `loop.*` fields.
|
|
494
|
-
- [Command reference](./command-reference.md#loop) —
|
|
495
|
-
- [Coordination service](./coordination-service.md) — fleet (multi-machine).
|
|
227
|
+
- [Command reference](./command-reference.md#loop) — all loop flags and environment variables.
|
|
228
|
+
- [AI-DLC Coordination service](./coordination-service.md) — fleet (multi-machine) deployment.
|