@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.
Files changed (109) hide show
  1. package/DEVELOPMENT.md +13 -26
  2. package/README.md +35 -39
  3. package/dist/assets/.agents/aidlc/orchestrator.md +1 -1
  4. package/dist/assets/.agents/aidlc/schemas/state.schema.json +2 -0
  5. package/dist/assets/.agents/aidlc/scripts/lib/assignment-store.mjs +94 -48
  6. package/dist/assets/.agents/aidlc/scripts/lib/context-runtime.mjs +5 -4
  7. package/dist/assets/.agents/aidlc/scripts/lib/loop-authority.mjs +21 -5
  8. package/dist/assets/.agents/aidlc/scripts/lib/loop-daemon.mjs +52 -78
  9. package/dist/assets/.agents/aidlc/scripts/lib/loop-drivers.mjs +88 -14
  10. package/dist/assets/.agents/aidlc/scripts/lib/loop-env.mjs +279 -0
  11. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-cli.mjs +20 -5
  12. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-remote.mjs +10 -1
  13. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-supervisor.mjs +2 -1
  14. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet.mjs +3 -2
  15. package/dist/assets/.agents/aidlc/scripts/lib/loop-git.mjs +9 -3
  16. package/dist/assets/.agents/aidlc/scripts/lib/loop-holder.mjs +376 -0
  17. package/dist/assets/.agents/aidlc/scripts/lib/loop-intake.mjs +11 -3
  18. package/dist/assets/.agents/aidlc/scripts/lib/loop-lease.mjs +67 -61
  19. package/dist/assets/.agents/aidlc/scripts/lib/loop-leases.mjs +268 -0
  20. package/dist/assets/.agents/aidlc/scripts/lib/loop-local-workers.mjs +78 -17
  21. package/dist/assets/.agents/aidlc/scripts/lib/loop-runtime.mjs +42 -10
  22. package/dist/assets/.agents/aidlc/scripts/lib/loop-stream.mjs +66 -9
  23. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-local.mjs +16 -56
  24. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-run-local.mjs +12 -6
  25. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-docker.mjs +14 -2
  26. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-log.mjs +158 -0
  27. package/dist/assets/.agents/aidlc/scripts/lib/repo-head.mjs +22 -0
  28. package/dist/assets/.agents/aidlc/scripts/lib/store.mjs +11 -0
  29. package/dist/assets/.agents/aidlc/scripts/lib/task-runtime-migrate.mjs +75 -0
  30. package/dist/assets/.agents/aidlc/scripts/lib/task-runtime.mjs +97 -0
  31. package/dist/assets/.agents/aidlc/scripts/loop-entry.mjs +87 -4
  32. package/dist/assets/.agents/aidlc/scripts/loop.cmd +101 -0
  33. package/dist/assets/.agents/aidlc/scripts/loop.sh +71 -0
  34. package/dist/assets/.agents/aidlc/scripts/remote-state.mjs +10 -4
  35. package/dist/assets/.agents/aidlc/scripts/state.mjs +16 -8
  36. package/dist/assets/ui/changes.js +83 -0
  37. package/dist/assets/ui/common.js +664 -0
  38. package/dist/assets/ui/dashboard.css +281 -59
  39. package/dist/assets/ui/dashboard.js +77 -0
  40. package/dist/assets/ui/detail.js +159 -0
  41. package/dist/assets/ui/live-log.js +332 -0
  42. package/dist/services/aidlc-coordination/package.json +1 -1
  43. package/dist/services/aidlc-coordination/src/lifecycle-core.mjs +11 -0
  44. package/dist/src/cli/argv.js +10 -4
  45. package/dist/src/cli/commands.js +52 -22
  46. package/dist/src/cli/loop-launcher.d.ts +47 -0
  47. package/dist/src/cli/loop-launcher.js +322 -0
  48. package/dist/src/cli.js +3 -0
  49. package/dist/src/installer.js +4 -2
  50. package/dist/src/model/records.d.ts +4 -0
  51. package/dist/src/state/validate.js +5 -0
  52. package/dist/src/task-ui.d.ts +31 -52
  53. package/dist/src/task-ui.js +25 -1562
  54. package/dist/src/ui/assets.d.ts +14 -0
  55. package/dist/src/ui/assets.js +45 -0
  56. package/dist/src/ui/changes.d.ts +83 -0
  57. package/dist/src/ui/changes.js +498 -0
  58. package/dist/src/ui/containers.d.ts +71 -0
  59. package/dist/src/ui/containers.js +214 -0
  60. package/dist/src/ui/daemon.d.ts +75 -0
  61. package/dist/src/ui/daemon.js +232 -0
  62. package/dist/src/ui/data.d.ts +42 -0
  63. package/dist/src/ui/data.js +89 -0
  64. package/dist/src/ui/docs.d.ts +13 -0
  65. package/dist/src/ui/docs.js +39 -0
  66. package/dist/src/ui/files.d.ts +3 -0
  67. package/dist/src/ui/files.js +20 -0
  68. package/dist/src/ui/http.d.ts +14 -0
  69. package/dist/src/ui/http.js +80 -0
  70. package/dist/src/ui/live.d.ts +5 -0
  71. package/dist/src/ui/live.js +43 -0
  72. package/dist/src/ui/markdown.d.ts +2 -0
  73. package/dist/src/ui/markdown.js +127 -0
  74. package/dist/src/ui/options.d.ts +48 -0
  75. package/dist/src/ui/options.js +81 -0
  76. package/dist/src/ui/security.d.ts +34 -0
  77. package/dist/src/ui/security.js +38 -0
  78. package/dist/src/ui/server.d.ts +39 -0
  79. package/dist/src/ui/server.js +347 -0
  80. package/dist/src/ui/sse.d.ts +14 -0
  81. package/dist/src/ui/sse.js +281 -0
  82. package/dist/src/ui/views/board.d.ts +7 -0
  83. package/dist/src/ui/views/board.js +131 -0
  84. package/dist/src/ui/views/changes.d.ts +19 -0
  85. package/dist/src/ui/views/changes.js +154 -0
  86. package/dist/src/ui/views/components.d.ts +56 -0
  87. package/dist/src/ui/views/components.js +113 -0
  88. package/dist/src/ui/views/docs.d.ts +15 -0
  89. package/dist/src/ui/views/docs.js +64 -0
  90. package/dist/src/ui/views/layout.d.ts +44 -0
  91. package/dist/src/ui/views/layout.js +233 -0
  92. package/dist/src/ui/views/task.d.ts +25 -0
  93. package/dist/src/ui/views/task.js +320 -0
  94. package/dist/src/upgrade.js +5 -2
  95. package/dist/src/workflow.d.ts +4 -0
  96. package/dist/src/workflow.js +33 -1
  97. package/docs/README.md +48 -33
  98. package/docs/architecture.md +101 -38
  99. package/docs/command-reference.md +269 -93
  100. package/docs/configuration.md +62 -42
  101. package/docs/coordination-service.md +85 -36
  102. package/docs/design-decisions.md +35 -31
  103. package/docs/development.md +111 -61
  104. package/docs/loop-local-run.md +135 -402
  105. package/docs/loop-runbook.md +84 -105
  106. package/docs/operating-workflow.md +55 -42
  107. package/docs/testing-and-release.md +70 -51
  108. package/docs/troubleshooting.md +165 -69
  109. package/package.json +1 -1
@@ -1,23 +1,17 @@
1
1
  # Loop setup runbook
2
2
 
3
- > [!WARNING]
4
- > The loop is **experimental** and pre-1.0 (`0.x`): the `loop.*` fields, provider mappings, environment variables, and diagnostics can change incompatibly in any release before `1.0.0`. **Local mode is usable** on a single Linux host today; **fleet mode is still under active development** and is not yet stable.
5
-
6
- This runbook walks through the three most common operational journeys for the end-to-end loop, in order:
7
-
8
- 1. [Enable the loop from `off`](#enable-the-loop-from-off)
9
- 2. [Run the loop in `local` mode](#local-mode)
10
- 3. [Run the loop across multiple machines (`fleet`)](#fleet-multi-machine)
11
-
12
- It is a step-by-step guide, not a reference. For the full field, flag, and environment reference, see [Configuration](./configuration.md), [Command reference](./command-reference.md), and [AI-DLC Coordination service](./coordination-service.md); this runbook links to those pages for depth instead of repeating them.
3
+ Setup for the end-to-end loop: a **lead** agent runs clarify, plan, and wrap, **workers** run build items in Docker, and the loop stops at every gate for a human. Journeys, in order: [Enable the loop from `off`](#enable-the-loop-from-off), [Local mode](#local-mode), [Fleet (multi-machine)](#fleet-multi-machine); day-to-day operation is the [Local loop walkthrough](./loop-local-run.md).
13
4
 
14
- ## The loop in one paragraph
5
+ ## Status and stability
15
6
 
16
- The loop drives a task end-to-end. A **lead** agent runs the clarify, plan, and wrap phases, while **workers** execute build items. `local` mode uses the project's canonical local state (`state.mjs`) with a host-executed lead and Docker-isolated workers on one Linux host. `fleet` mode delegates authority to a coordination service and can spread workers across machines. Both modes use the same loop daemon, intake, and dashboard; only the authority differs. Selecting a mode only configures the loop; nothing runs until you call `aidlc-kit loop start` explicitly.
7
+ > [!WARNING]
8
+ > **Experimental, pre-1.0 (`0.x`).** Local mode is usable on one Linux host; fleet mode and the Coordination service are under active development with known bugs.
9
+ > CLI flags, `loop.*`/`mcp.*` fields, environment variables, diagnostics, and installed layouts can change incompatibly before `1.0.0`.
10
+ > Selecting a mode never starts or approves anything; only `aidlc-kit loop start` (or `loop.sh up`) runs the loop.
17
11
 
18
12
  ## Enable the loop from `off`
19
13
 
20
- `loop.mode` defaults to `off` (an absent `loop` field also means `off`). Enabling it means setting `loop.mode` to `local` or `fleet` and providing `loop.agents` with one `lead` and one or more named `workers`, each mapped to `codex`, `claude`, or `opencode`:
14
+ `loop.mode` defaults to `off` (absent `loop` field included). Set it to `local` or `fleet` and give `loop.agents` one `lead` and one or more named `workers`, each `codex`, `claude`, or `opencode`:
21
15
 
22
16
  ```json
23
17
  {
@@ -28,124 +22,108 @@ The loop drives a task end-to-end. A **lead** agent runs the clarify, plan, and
28
22
  }
29
23
  ```
30
24
 
31
- ### Step 1 — Choose how to write the config
32
-
33
- Pick one of three ways to set `loop.mode` and `loop.agents`:
34
-
35
- - **Edit `.agents/config.json` directly.** This is the project-owned config; the fields are described in [Configuration](./configuration.md#optional-loop-configuration).
36
- - **Use `init`** for a new install:
25
+ - Edit `.agents/config.json` directly; fields in [Configuration](./configuration.md#optional-loop-configuration).
26
+ - New install, with `init`:
37
27
  ```sh
38
- npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit init . \
28
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit init . \
39
29
  --loop-mode local --loop-lead codex --loop-workers a=codex,b=opencode
40
30
  ```
41
- - **Use the human-only `upgrade`** for an existing install, which preserves the existing config when you omit the loop flags and lets an authorised human review the change before applying:
31
+ - Existing install, with the human-only `upgrade` (omitting the loop flags preserves the config). Stop the daemon first; a newer loop refuses to start while an older one holds a task (`A loop from a previous aidlc-kit version is still running …`).
42
32
  ```sh
43
- npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit upgrade . \
33
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit upgrade . \
44
34
  --loop-mode local --loop-lead codex --loop-workers a=codex,b=opencode --dry-run
45
35
  ```
46
36
 
47
- ### Step 2 — Verify the loop is enabled
37
+ Verify: every `aidlc-kit loop` invocation fails closed before anything starts unless:
48
38
 
49
- `aidlc-kit loop start` fails closed unless the config is complete:
39
+ - `loop.mode` is `local` or `fleet`, and `loop.agents` has a valid `lead` and at least one valid worker (`Loop requires a configured lead and worker providers`).
40
+ - Any `--mode` flag matches `loop.mode` (`Requested mode does not match configured authority`).
50
41
 
51
- - `loop.mode` must be `local` or `fleet`.
52
- - `loop.agents` must have a valid `lead` provider and at least one valid `worker` mapping (`Loop requires a configured lead and worker providers`).
53
- - The requested `--mode` must match the configured `loop.mode` (`Requested mode does not match configured authority`).
54
-
55
- These checks run on any `aidlc-kit loop` invocation before anything starts, so a wrong configuration fails closed with a clear message rather than silently running. A valid configuration is only a selection: it does not install or start a service, authorise an upgrade, or grant gate approval. Run `aidlc-kit loop start` to actually start the loop, and keep provider credentials out of the config object.
42
+ A valid config is only a selection: it installs and starts nothing and grants no approval. Keep credentials out of the config object.
56
43
 
57
44
  ## Local mode
58
45
 
59
- Local mode is the single-machine journey. The lead runs on the host (Codex, Claude Code, or OpenCode) for clarify/plan/wrap, and build items fan out to Docker-isolated workers. It uses the canonical local state and requires local authority; see [Command reference](./command-reference.md#loop) for the authority boundary.
46
+ One Linux host: the lead runs on the host (Codex, Claude Code, or OpenCode), build items fan out to Docker-isolated workers, and the canonical state is the local `state.mjs`.
60
47
 
61
48
  ### Prerequisites
62
49
 
63
50
  | Requirement | Notes |
64
51
  | --- | --- |
65
- | Linux host | Loop/fleet features require Docker and a POSIX shell; `loop-local-workers.mjs` rejects non-Linux hosts. |
52
+ | Linux host, non-root user | `loop-local-workers.mjs` rejects non-Linux hosts; Docker workers need a non-root uid/gid. |
66
53
  | Docker engine | The worker batch preflights `docker info` and the worker image. |
67
- | Non-root host user | Docker workers require a non-root uid/gid. |
68
- | Worker Docker image | Auto-built from the packaged Dockerfile on first build dispatch (`aidlc-kit loop worker-image`); set `AIDLC_WORKER_DOCKER_IMAGE` only to override the per-provider default. |
69
- | Provider credentials | Exported in the environment; never written into `.agents/config.json`. |
54
+ | Worker Docker image | Auto-built on first build dispatch; `AIDLC_WORKER_DOCKER_IMAGE` only overrides the default. |
55
+ | Provider credentials | In `.agents/loop.env` (git-ignored) or exported; never in `.agents/config.json`. |
70
56
 
71
57
  ### Step 1 — Configure `local`
72
58
 
73
- Set `loop.mode` to `local` with a lead and workers (see [Enable the loop from `off`](#enable-the-loop-from-off)):
59
+ Set `loop.mode` to `local` with a lead and workers, as shown in [Enable the loop from `off`](#enable-the-loop-from-off).
74
60
 
75
- ```json
76
- {
77
- "loop": {
78
- "mode": "local",
79
- "agents": { "lead": "codex", "workers": { "worker-a": "codex", "worker-b": "opencode" } }
80
- }
81
- }
82
- ```
61
+ ### Step 2 — Fill in `.agents/loop.env`
83
62
 
84
- ### Step 2 — Set the environment
63
+ `init`/`upgrade` install `.agents/loop.env` as a commented template (git-ignored through `.agents/.gitignore`). Uncomment what you need; exported shell variables win, and values your tools already store are detected for the configured providers only:
85
64
 
86
- | Variable | Required | Purpose |
65
+ | Variable | Required | Purpose and detected from |
87
66
  | --- | --- | --- |
88
- | `AIDLC_WORKER_DOCKER_IMAGE` | no | Optional single-image override. The per-provider default `aidlc-worker-<provider>:local` is auto-built and recorded in `loop.workerImage`. |
89
- | `AIDLC_OPENCODE_MODEL` | if any provider is `opencode` | `provider/model[#variant]` (for example `opencode-go/gpt-6-luna`). The turn fails closed without a valid value. |
90
- | `OPENAI_API_KEY` | if a provider is `codex` | Codex worker credential. |
91
- | `ANTHROPIC_API_KEY` | if a provider is `claude` | Claude Code worker credential. |
92
- | `OPENCODE_API_KEY` | if a provider is `opencode` | OpenCode worker credential. The key follows the model provider: `openai/` → `OPENAI_API_KEY`, `anthropic/` → `ANTHROPIC_API_KEY`, otherwise `OPENCODE_API_KEY`. |
93
- | `AIDLC_LOCAL_WORKTREES_ROOT` | no | Root for worker worktrees; defaults to a system temp directory. It must be outside the integration checkout. |
94
- | `AIDLC_LOOP_EVENT_LOG` | no (see note) | Path to a JSONL event-log sidecar that feeds the web dashboard live log. The `aidlc-kit ui` **New task** action (when it starts the daemon) sets it to `.agents/data/loop/ui-events.jsonl` automatically; a **manually started** daemon must set it to the same path or the dashboard live log stays empty. |
67
+ | `AIDLC_OPENCODE_MODEL` | if any provider is `opencode` | `provider/model[#variant]` (for example `opencode-go/gpt-6-luna`); the turn fails closed without it. Detected: `"model"` in `opencode.json` (project, `OPENCODE_CONFIG`, or `~/.config/opencode`). |
68
+ | `OPENAI_API_KEY` | if a provider is `codex` | Codex worker credential. Detected: `~/.codex/auth.json` after `codex login --with-api-key` (a ChatGPT-only login is not enough). |
69
+ | `ANTHROPIC_API_KEY` | if a provider is `claude` | Claude Code worker credential. Detected: `"env"` in `.claude/settings.local.json`, `.claude/settings.json`, or `~/.claude/settings.json`. |
70
+ | `OPENCODE_API_KEY` | if a provider is `opencode` | OpenCode worker credential; the key follows the model prefix (`openai/` → `OPENAI_API_KEY`, `anthropic/` → `ANTHROPIC_API_KEY`, otherwise `OPENCODE_API_KEY`). Detected: `~/.local/share/opencode/auth.json`. |
71
+ | `AIDLC_WORKER_DOCKER_IMAGE` | no | Single-image override; the default `aidlc-worker-<provider>:local` is auto-built and recorded in `loop.workerImage`. |
95
72
 
96
- Docker workers (local and fleet) authenticate OpenCode from the environment and redirect OpenCode's XDG data/config roots into the worker's ephemeral HOME. Only the **isolated lead** container does not support OpenCode yet (`OpenCode workers require file-based credentials and are not available in isolated containers yet`); the daemon runs the lead on the host, so an OpenCode lead works there.
73
+ Check the result (secrets never printed) with `./.agents/aidlc/scripts/loop.sh check` (= `aidlc-kit loop env`).
97
74
 
98
- ### Step 3 — Build the worker image (usually automatic)
75
+ Rarely set: `AIDLC_LOCAL_WORKTREES_ROOT` (worker worktrees root, default a system temp directory, must be outside the integration checkout); `AIDLC_LOOP_EVENT_LOG` (always `.agents/data/loop/ui-events.jsonl` for a local daemon); `AIDLC_ENV_FILE` or `--loop-env PATH` (another env file). Lookup order: [Command reference](./command-reference.md#loop). Credential rule: [Provider credentials and OpenCode](./configuration.md#provider-credentials-and-opencode).
99
76
 
100
- Build the worker image for each provider you use, or let the supervisor auto-build it on the first build dispatch:
77
+ ### Step 3 — Build the worker image (usually automatic)
101
78
 
102
79
  ```sh
103
80
  npx @felixdotgo/aidlc-kit loop worker-image --provider codex # → aidlc-worker-codex:local
104
81
  npx @felixdotgo/aidlc-kit loop worker-image --provider opencode # → aidlc-worker-opencode:local
105
82
  ```
106
83
 
107
- The command records the tag into `loop.workerImage`; the local supervisor reuses it and auto-builds any missing per-provider image before dispatch. The batch preflight still inspects the image and runs each provider CLI with `--version` inside the container, so a missing or mismatched image fails before any worker starts. See [Testing and release](./testing-and-release.md#loop-docker-and-postgresql-verification) for the fixture build pattern used by the test suite.
84
+ - Records the tag in `loop.workerImage`; the supervisor auto-builds any missing per-provider image before dispatch.
85
+ - Batch preflight inspects the image and runs each provider CLI with `--version` in the container; a missing or mismatched image fails before any worker starts. Test fixtures: [Testing and release](./testing-and-release.md#loop-docker-and-postgresql-verification).
108
86
 
109
87
  ### Step 4 — Start the daemon, add tasks, and watch
110
88
 
111
- `start` launches the singleton daemon (one per project) and reads no requirement. Add tasks with the web dashboard **New task** or loop intake, which reads the requirement from stdin (capped at 8192 bytes) and never from an argument:
112
-
113
89
  ```sh
114
- npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit loop start
115
- echo "Add PDF report export" | npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit loop intake
90
+ ./.agents/aidlc/scripts/loop.sh up # env check + daemon + dashboard; --open launches the browser, --no-ui skips the dashboard
91
+ ./.agents/aidlc/scripts/loop.sh down # stop both (--now cancels the running turn); also: status, logs, check
116
92
  ```
117
93
 
118
- The daemon runs only loop-owned tasks (created through intake), one bounded run per task in turn, and keeps polling after a task reaches a gate or completes. Stop it with `Ctrl-C`: the first signal stops after the current turn, the second cancels the turn, the third exits. A stopped run is not a pause; the task continues on the next `start`.
94
+ `Ctrl-C` in the `up` terminal closes only the dashboard. On Windows use `.agents\aidlc\scripts\loop.cmd`.
119
95
 
120
- `status` prints the canonical task and its derived next action:
96
+ Underneath, `loop start` runs the singleton daemon (one per project) and reads no requirement. Add tasks with the dashboard **New task** or with intake (stdin only, capped at 8192 bytes):
121
97
 
122
98
  ```sh
123
- npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit loop status --task-id <task-id>
99
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop start
100
+ echo "Add PDF report export" | npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop intake
124
101
  ```
125
102
 
126
- There is no `loop resume`. After a gate approval the daemon continues the task on its next poll. A **paused** task is not actionable: fix the cause, then press **resume** on the dashboard or run `node .agents/aidlc/scripts/state.mjs task status <task-id> --status active`.
127
-
128
- As an alternative to typing these commands repeatedly, `aidlc-kit ui` starts a web dashboard to view task status, add tasks, resume paused tasks, and approve gates; it prints a login URL that signs the browser in. See [Command reference](./command-reference.md#ui) and [Loop local run](./loop-local-run.md#57-web-dashboard-aidlc-kit-ui).
103
+ - The daemon runs only loop-owned tasks, keeps polling after a gate or completion, and auto-resumes approved tasks; there is no `loop resume`.
104
+ - Stuck: `aidlc-kit loop leases`, then [Loop leases, locks and claims](./troubleshooting.md#loop-leases-locks-and-claims).
105
+ - Upgraded from a version that kept assignments, event logs, run records, and intake files under `.agents/data/loop/` or at the task directory root: the daemon moves them under `.agents/data/tasks/<id>/runtime/` when it starts; `aidlc-kit loop migrate-data --dry-run` previews, `aidlc-kit loop migrate-data` runs it by hand ([Command reference](./command-reference.md#loop)).
106
+ - Status, stopping, resuming, the streaming log, and the dashboard: [Local loop walkthrough](./loop-local-run.md#start-the-daemon-and-add-tasks).
129
107
 
130
- ### Step 5 — Approve gates from the trusted host terminal
108
+ ### Step 5 — Approve gates, or send feedback, from the trusted host terminal
131
109
 
132
- Gate approval happens only through a human — the trusted host terminal or the signed-in dashboard — never from a lead or worker container, and never via piped input:
110
+ Only a human approves a gate, on the trusted host terminal or the signed-in dashboard; never a lead or worker container, never piped input:
133
111
 
134
112
  ```sh
135
- node .agents/aidlc/scripts/loop-gate.mjs <task-id>
113
+ node .agents/aidlc/scripts/loop-gate.mjs <task-id> # type approve, or any other text as feedback (task stays at the gate)
136
114
  ```
137
115
 
138
- The command 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:`. Type `approve` to approve that exact review. If the review changes while you type, it fails closed and asks you to inspect the new review.
116
+ The dashboard detail page offers the same two actions ([details](./loop-local-run.md#approve-a-gate-or-send-feedback)).
139
117
 
140
118
  ## Fleet (multi-machine)
141
119
 
142
- Fleet mode spreads the loop across machines through the coordination service. It uses `remote-state.mjs` instead of the local `state.mjs`, and the remote workspace is canonical. Deployment, storage (SQLite for one host, PostgreSQL for multiple hosts), and credentials are covered in [Coordination service](./coordination-service.md); this section keeps the loop-specific steps and links there for the rest.
120
+ Fleet mode spreads the loop across machines through the coordination service: `remote-state.mjs` replaces the local `state.mjs`, and the remote workspace is canonical. Deployment, storage, and credentials: [Coordination service](./coordination-service.md#multi-machine-loop-deployment).
143
121
 
144
122
  ### Prerequisites
145
123
 
146
- - A deployed coordination service with PostgreSQL for a multi-host topology, and a shared Git remote — see [Coordination service](./coordination-service.md#multi-machine-loop-deployment).
147
- - `loop.mode` set to `fleet` with a lead and workers matching your worker machines.
148
- - Three distinct credential classes (`MCP_FLEET_LEAD_TOKEN`, `MCP_FLEET_REVIEWER_TOKEN`, and `MCP_FLEET_WORKER_TOKENS`) configured on the service.
124
+ - A deployed coordination service (PostgreSQL for multi-host) and a shared Git remote.
125
+ - `loop.mode` set to `fleet`, with workers matching your worker machines.
126
+ - Three distinct credential classes on the service: `MCP_FLEET_LEAD_TOKEN`, `MCP_FLEET_REVIEWER_TOKEN`, `MCP_FLEET_WORKER_TOKENS`.
149
127
 
150
128
  ### Step 1 — Configure `fleet`
151
129
 
@@ -162,74 +140,75 @@ Fleet mode spreads the loop across machines through the coordination service. It
162
140
 
163
141
  | Variable | Required | Purpose |
164
142
  | --- | --- | --- |
165
- | `AIDLC_FLEET_URL` | yes | The full HTTPS `/mcp` URL of the service. |
166
- | `AIDLC_FLEET_WORKSPACE` | yes | The remote workspace id. |
167
- | `AIDLC_FLEET_TOKEN` | yes | The lead credential. |
168
- | `AIDLC_FLEET_INTEGRATION_BRANCH` | yes | The shared integration branch; it must exist on the remote. |
169
- | `AIDLC_FLEET_PROJECT_ROOT` | no | Set automatically by `aidlc-kit loop`; required only for the direct `remote-state.mjs` / fleet-runner client. When set explicitly it must match the loop root. |
170
- | `AIDLC_FLEET_WORKER_IDS` / `AIDLC_FLEET_WORKER_PROVIDERS` | no | Derived from `loop.agents.workers`; when set explicitly they must match it. |
171
- | `AIDLC_FLEET_GIT_REMOTE` | no | Git remote name; defaults to `origin`. |
172
- | `AIDLC_FLEET_MAX_TURNS`, `AIDLC_FLEET_TURN_TIMEOUT_MS`, `AIDLC_FLEET_MAX_STALL_TURNS`, `AIDLC_FLEET_POLL_MS` | no | Override `loop.limits` and `loop.pollMs`, which are the defaults. |
173
-
174
- The lead agent comes from `loop.agents.lead`. Do not export `AIDLC_FLEET_REVIEWER_TOKEN` in the lead shell; the daemon strips it from every lead and worker process anyway.
143
+ | `AIDLC_FLEET_URL` | yes | Full HTTPS `/mcp` URL of the service. |
144
+ | `AIDLC_FLEET_WORKSPACE` | yes | Remote workspace id. |
145
+ | `AIDLC_FLEET_TOKEN` | yes | Lead credential. |
146
+ | `AIDLC_FLEET_INTEGRATION_BRANCH` | yes | Shared integration branch; must exist on the remote. |
147
+ | `AIDLC_FLEET_PROJECT_ROOT` | no | Set by `aidlc-kit loop`; needed only for the direct `remote-state.mjs` / fleet-runner client. Must match the loop root. |
148
+ | `AIDLC_FLEET_WORKER_IDS` (comma-separated) / `AIDLC_FLEET_WORKER_PROVIDERS` | no | Derived from `loop.agents.workers`; must match it. |
149
+ | `AIDLC_FLEET_GIT_REMOTE` | no | Git remote name; default `origin`. |
150
+ | `AIDLC_FLEET_AGENT` | direct runner only | Lead provider when running `fleet-run.mjs` directly (default `codex`); `aidlc-kit loop` sets it from `loop.agents.lead`. Also the per-worker provider fallback. |
151
+ | `AIDLC_FLEET_MAX_TURNS`, `AIDLC_FLEET_TURN_TIMEOUT_MS`, `AIDLC_FLEET_MAX_STALL_TURNS`, `AIDLC_FLEET_POLL_MS` | no | Override `loop.limits` and `loop.pollMs`. |
152
+
153
+ The lead agent is `loop.agents.lead`. Do not export `AIDLC_FLEET_REVIEWER_TOKEN` in the lead shell; the daemon strips it from every lead and worker process.
175
154
 
176
155
  ### Step 3 — Start the daemon and add tasks
177
156
 
178
- `aidlc-kit loop start --mode fleet` preflights the service (`fleet_get`) and the remote integration branch, then starts the same daemon as local mode, failing closed instead of falling back to local:
157
+ `loop start --mode fleet` preflights the service (`fleet_get`) and the remote integration branch, then runs the same daemon as local mode, failing closed instead of falling back to local:
179
158
 
180
159
  ```sh
181
- npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit loop start --mode fleet
182
- echo "Add PDF report export" | npx --package @felixdotgo/aidlc-kit@0.2.0 aidlc-kit loop intake --mode fleet
160
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop start --mode fleet
161
+ echo "Add PDF report export" | npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop intake --mode fleet
183
162
  ```
184
163
 
185
- Intake creates the remote task under a short lead claim and writes `.agents/data/tasks/<task-id>/loop-intake.json` with `authority: "fleet"` on this lead machine. Only those tasks are fleet loop-owned; a remote task created any other way is never picked up. For each actionable task the daemon runs the fleet supervisor in a bounded mode: it claims the supervisor lease, runs fenced lead turns and worker dispatch through the coordinator, publishes the gate snapshot with its checkpoint, then returns and releases the lease. After the reviewer approves, the next poll re-claims the task and continues. An unreachable service shows up as `daemon_poll_error` and does not stop the daemon. Shutdown, backoff, and `status` behave as in local mode; there is no `loop resume` (re-activate a paused task with the dashboard **resume**).
164
+ - **Intake** creates the remote task under a short lead claim and writes `.agents/data/tasks/<task-id>/runtime/intake.json` with `authority: "fleet"`; only those tasks are fleet loop-owned.
165
+ - **Each actionable task** runs the fleet supervisor bounded (claim the supervisor lease, fenced lead turns and worker dispatch, publish the gate snapshot, release); after reviewer approval the next poll re-claims it.
166
+ - An unreachable service shows as `daemon_poll_error`; the daemon keeps running.
186
167
 
187
- The underlying fleet runner is also available directly from the service deployment (the installed `.agents/aidlc-coordination/`, or `dist/services/aidlc-coordination/` from a source checkout):
168
+ The fleet runner also runs directly from the service deployment (`.agents/aidlc-coordination/`, or `dist/services/aidlc-coordination/` in a source checkout); `supervisor` waits at each gate and never approves:
188
169
 
189
170
  ```sh
190
171
  node .agents/aidlc-coordination/src/fleet-run.mjs supervisor <task-id>
191
172
  node .agents/aidlc-coordination/src/fleet-run.mjs coordinator <task-id> --once
192
173
  ```
193
174
 
194
- Run directly, `supervisor` waits at each gate for the reviewer approval and resumes automatically; it never approves a gate.
195
-
196
175
  ### Step 4 — Run a worker on each worker machine
197
176
 
198
- On each worker machine, point at the same `AIDLC_FLEET_URL`, workspace, and `AIDLC_FLEET_PROJECT_ROOT` (a checkout of the project), use that worker's own `AIDLC_FLEET_TOKEN`, then set:
177
+ Same `AIDLC_FLEET_URL`, workspace, and `AIDLC_FLEET_PROJECT_ROOT` (a project checkout); this worker's own `AIDLC_FLEET_TOKEN`; and:
199
178
 
200
179
  | Variable | Required | Purpose |
201
180
  | --- | --- | --- |
202
- | `AIDLC_FLEET_WORKER_ID` | yes | This machine's worker id (must be a configured worker). |
181
+ | `AIDLC_FLEET_WORKER_ID` | yes | This machine's worker id (a configured worker). |
203
182
  | `AIDLC_FLEET_WORKTREES_ROOT` | yes | Root for this worker's isolated worktrees. |
204
- | `AIDLC_FLEET_WORKER_AGENT` | recommended | This worker's provider (`codex`, `claude`, or `opencode`); falls back to this worker's entry in `AIDLC_FLEET_WORKER_PROVIDERS`, then to `AIDLC_FLEET_AGENT`. A worker with a provider rejects jobs for another provider. |
205
- | `AIDLC_WORKER_DOCKER_IMAGE` | no | Image override. Otherwise the image is `loop.workerImage[provider]` from the project config or `aidlc-worker-<provider>:local`, auto-built from the packaged Dockerfile when missing. Without a known provider this variable is required. |
183
+ | `AIDLC_FLEET_WORKER_AGENT` | recommended | Provider (`codex`, `claude`, or `opencode`); falls back to this worker's entry in `AIDLC_FLEET_WORKER_PROVIDERS`, then `AIDLC_FLEET_AGENT`. A worker rejects jobs for another provider. |
184
+ | `AIDLC_WORKER_DOCKER_IMAGE` | no | Image override; otherwise `loop.workerImage[provider]` or `aidlc-worker-<provider>:local`, auto-built. Required when the provider is unknown. |
206
185
  | `AIDLC_OPENCODE_MODEL` | if the provider is `opencode` | `provider/model[#variant]`. |
207
- | worker credential | yes | `OPENAI_API_KEY` (codex), `ANTHROPIC_API_KEY` (claude), or for opencode the key matching the model prefix (`openai/`, `anthropic/`, otherwise `OPENCODE_API_KEY`). |
208
-
209
- Run one bounded assignment per invocation, or omit `--once` to keep polling:
186
+ | worker credential | yes | `OPENAI_API_KEY` (codex), `ANTHROPIC_API_KEY` (claude), or the key matching the opencode model prefix (`openai/`, `anthropic/`, otherwise `OPENCODE_API_KEY`). |
210
187
 
211
188
  ```sh
212
- node .agents/aidlc-coordination/src/fleet-run.mjs worker --once
189
+ node .agents/aidlc-coordination/src/fleet-run.mjs worker --once # omit --once to keep polling
213
190
  ```
214
191
 
215
192
  The worker resolves the image to its immutable `sha256:` id and preflights Docker and the provider CLI before claiming work.
216
193
 
217
194
  ### Step 5 — Approve gates as the reviewer
218
195
 
219
- Use the reviewer credential in a connected reviewer conversation:
220
-
221
196
  ```sh
222
197
  node .agents/aidlc/scripts/remote-state.mjs gate inbox
223
198
  node .agents/aidlc/scripts/remote-state.mjs gate approve <task-id> --snapshot <snapshot-id> --source "<explicit user approval>"
224
199
  ```
225
200
 
226
- The approve command checks that the snapshot is still current and uses the reviewer-only service operation. Run it only after the human explicitly approves the packet. Alternatively, start `aidlc-kit ui` with the fleet environment from Step 2 plus the reviewer credential (`AIDLC_FLEET_REVIEWER_TOKEN` or `--reviewer-token-file`): the dashboard then approves the current snapshot itself, passing the credential only to that one approve process. Without a reviewer credential the dashboard shows these commands instead and its approve API returns `403`.
201
+ - `gate approve` checks the snapshot is still current and uses the reviewer-only operation; run it only after the human explicitly approves the packet.
202
+ - Dashboard: start `aidlc-kit ui` with the Step 2 environment plus `AIDLC_FLEET_REVIEWER_TOKEN` or `--reviewer-token-file`; without it the approve API returns `403` and the page shows these commands.
203
+ - **Send feedback (stay at gate)** needs no reviewer credential: it runs `remote-state.mjs task status <task-id> --status active --mode audited` under the lead claim; the task stays at the gate and the supervisor publishes a revised snapshot.
227
204
 
228
205
  ## Authority boundary
229
206
 
230
- `local` mode uses the canonical local state and requires local authority; `fleet` mode uses `remote-state.mjs`. When `AIDLC_FLEET_URL` is set, local lifecycle, context, gate, assignment, and standalone loop commands reject use so an unattended lead cannot accidentally mutate a second local authority. Unset `AIDLC_FLEET_URL` only when deliberately returning to a local run. See [Coordination service](./coordination-service.md#state-and-synchronization-contract) for the remote canonical-state contract.
207
+ `local` uses the canonical local state; `fleet` uses `remote-state.mjs`. While `AIDLC_FLEET_URL` is set, local lifecycle, context, gate, assignment, and standalone loop commands reject use; unset it only when deliberately returning to a local run. Contract: [State and synchronization contract](./coordination-service.md#state-and-synchronization-contract).
231
208
 
232
209
  ## Where to go next
233
210
 
234
- - [Operating the workflow](./operating-workflow.md) — gates, approvals, handoffs, and task ownership.
235
- - [Troubleshooting](./troubleshooting.md) — symptom/error-code recovery, including fleet authority and Docker worker image diagnostics.
211
+ - [Local loop walkthrough](./loop-local-run.md) — day-to-day operation.
212
+ - [AI-DLC Coordination service](./coordination-service.md) — deploying the fleet service.
213
+ - [Operating the workflow](./operating-workflow.md) — gates, approvals, handoffs.
214
+ - [Troubleshooting](./troubleshooting.md) — symptom and error-code recovery.
@@ -1,6 +1,6 @@
1
1
  # Operating the workflow
2
2
 
3
- `aidlc-kit` gives an agent a repeatable delivery lifecycle. It separates intent, design, implementation, and final review so a human explicitly approves the points where scope or risk changes.
3
+ `aidlc-kit` gives an agent a repeatable delivery lifecycle — intent, design, implementation, final review — with a human approving each point where scope or risk changes. Settings: [Configuration](./configuration.md); exact flags: [Command reference](./command-reference.md).
4
4
 
5
5
  ## Lifecycle at a glance
6
6
 
@@ -15,11 +15,10 @@ request → clarify → Confirm requirements → plan → Approve plan → build
15
15
  | Build | Approved change, verification, and adversarial review | Review the completed change at Review implementation. |
16
16
  | Wrap | Delivery notes, lessons, and residual risk | Runs only after Review implementation approval. |
17
17
 
18
- An agent continues after each non-terminal transition and after every item or evidence mutation. Completing one work item is a progress update, not a turn boundary: the agent consumes the returned `nextAction` and continues through the remaining items, verification, and review. It stops only for a gate that is ready for human action, a durable blocker, a terminal non-success outcome, or successful completion.
18
+ - The agent continues after every non-terminal transition and item or evidence mutation (completing one item is progress, not a turn boundary) and stops only for a gate ready for human action, a durable blocker, a terminal non-success outcome, or completion.
19
+ - The client conversation (Codex, Claude Code, or OpenCode) is the lead: it dispatches native agents for independent items and presents each gate. After a restart, ask it to resume the task ID; it rereads `task next`, inspects assignment records and worktree results, and continues dependency-ready work only.
19
20
 
20
- In ordinary use, ask Codex, Claude Code, or OpenCode to work on the feature in the same conversation. The client remains the lead, starts native agents for independent items, and presents each review gate in that conversation. After a restart, open the project and ask the client to resume the task ID. It rereads `task next`, inspects assignment records and worktree results, and continues only dependency-ready work. A human approval is still a later reply to the gate shown in that conversation.
21
-
22
- For example, a feature with API, UI, and integration tasks can be recorded as a feature graph:
21
+ Related tasks can form a feature graph:
23
22
 
24
23
  ```sh
25
24
  node .agents/aidlc/scripts/state.mjs feature create checkout --branch feature/checkout
@@ -30,27 +29,24 @@ node .agents/aidlc/scripts/state.mjs feature ready checkout
30
29
  node .agents/aidlc/scripts/state.mjs task ready checkout-api
31
30
  ```
32
31
 
33
- The task IDs must already exist before `feature link`. To create a new sibling in an existing feature, use `task create <id> --title <title> --feature checkout` and optionally `--depends-on <task-id,...>`. Each task still goes through its own G0/G1/G2. Build items can declare `--depends-on <item-id,...>` through `task item`; `task ready` reports which items can be dispatched. Dependencies that are missing, cyclic, or incomplete at completion are rejected.
32
+ - Task IDs must exist before `feature link`; add a sibling with `task create <id> --title <title> --feature checkout [--depends-on <task-id,...>]`. Each task passes its own G0/G1/G2.
33
+ - Build items declare `--depends-on <item-id,...>` via `task item`; `task ready` lists dispatchable items. Missing, cyclic, or incomplete dependencies are rejected.
34
34
 
35
- For unattended work on multiple machines, deploy the optional coordination service with PostgreSQL, distinct lead/worker/reviewer credentials, a shared Git remote, and supervised coordinator/worker processes. The remote workspace is the sole canonical authority for that run. A worker claims a bounded assignment, commits and pushes within its owned paths, and reports its commit. The lead verifies and integrates it before marking the item done. Restarted processes reread canonical state and fenced leases; uncertain results are checked before retry. At G0/G1/G2 the coordinator publishes a review snapshot and waits for a reviewer in a connected client. It cannot grant its own approval.
35
+ Unattended multi-machine work uses the optional coordination service as sole canonical authority: [Coordination service](./coordination-service.md#multi-machine-loop-deployment).
36
36
 
37
37
  ## Parallel workstreams
38
38
 
39
- At any phase, the lead agent may use the orchestration contract to delegate independent, bounded workstreams when the host has spare worker capacity. The lead keeps one slot, assigns explicit ownership and completion criteria, and integrates returned work before relying on it. It remains the only writer for task state, evidence, review artifacts, and gates. In build, a batch may contain only items with non-overlapping file/area ownership; shared surfaces, integration, task-wide verification, and adversarial review remain lead-owned. Parallel work never changes the approval or lifecycle requirements described below.
39
+ - The lead may delegate independent, bounded workstreams when the host has spare worker capacity: keep one slot, assign explicit ownership and completion criteria, integrate returned work before relying on it.
40
+ - The lead is the only writer for task state, evidence, review artifacts, and gates; parallel work never relaxes approvals.
41
+ - A build batch holds only items with non-overlapping file/area ownership; shared surfaces, integration, task-wide verification, and adversarial review stay lead-owned.
40
42
 
41
43
  ## Starting work
42
44
 
43
- After installation, make a normal change request to the selected coding agent. For example:
44
-
45
- ```text
46
- Add rate limiting to the login endpoint using the AI-DLC workflow.
47
- ```
48
-
49
- The adapter creates a task, writes an intent brief, and presents Confirm requirements. Do not treat a partial implementation as approved work before Approve plan, and do not treat a passing test as approval at Review implementation.
45
+ Make a normal change request, for example `Add rate limiting to the login endpoint using the AI-DLC workflow.` The adapter creates the task, writes an intent brief, and presents Confirm requirements. A partial implementation is not approved work; a passing test is not approval at Review implementation.
50
46
 
51
47
  ## State and review artifacts
52
48
 
53
- Each installed project owns its data under `.agents/data/`. Package-managed workflow instructions live under `.agents/aidlc/`; project configuration, local rules, and evidence are project-owned. The package supports Codex, Claude Code, and OpenCode. Do not hand-edit lifecycle state: use the installed scripts instead.
49
+ Project data: `.agents/data/`; package-managed workflow: `.agents/aidlc/`. Never hand-edit lifecycle state:
54
50
 
55
51
  ```sh
56
52
  node .agents/aidlc/scripts/state.mjs task list --limit 20
@@ -60,15 +56,26 @@ node .agents/aidlc/scripts/state.mjs task next <task-id>
60
56
  node .agents/aidlc/scripts/gate-view.mjs <task-id>
61
57
  ```
62
58
 
63
- `task next` is the authoritative instruction for what happens next. `gate-view` renders the review packet consistently for Confirm requirements, Approve plan, and Review implementation.
59
+ `task next` is the authoritative next instruction; `gate-view` renders the review packet for every gate.
60
+
61
+ Each task owns `.agents/data/tasks/<task-id>/`: review artifacts (`intent.md`, `design.md`, `workplan.md`) at its root, operational files (assignment claims, event history, loop run record, intake, worker logs) under `runtime/`, which is never committed. Layout and the migration from older versions: [Architecture](./architecture.md#loop-runtime).
62
+
63
+ ### Script contract in brief
64
+
65
+ - Every `state.mjs` and `task-next.mjs` command prints one JSON envelope `{ok, result, nextAction?}`; failures are one-line `{ok: false, error}` on stderr with exit code `1` (expected), `2` (continuation guard), or `3` (crash).
66
+ - Before any final response, run `task-next.mjs <task-id> --require-stop`; exit code `2` means execute `continuation.command` instead of replying. Recover from a premature reply with `task next <task-id>` in the next turn — never by re-approving a gate.
67
+ - Rendering, gate-check, and context commands may print Markdown or plain text instead of JSON.
68
+ - In build, `nextAction` names the next `in_progress` or `todo` item and stays `run_phase` after the last item until verification, adversarial review, and gate preparation finish.
69
+ - Options, root discovery, warnings, and the full envelope are in [Installed lifecycle scripts](./command-reference.md#installed-lifecycle-scripts).
64
70
 
65
- Lifecycle options support both `--name value` and `--name=value` in any order. Invalid options and command shapes fail before lock or state access. From a project subdirectory, an omitted `--root` selects the nearest ancestor containing `.agents/aidlc/`; outside an installed project the command fails without creating `.agents`. Use explicit `--root` to select a different installed project.
71
+ ### Task switch guard
66
72
 
67
- Every `state.mjs` and `task-next.mjs` command returns one JSON envelope `{ok, result, nextAction?}`. Rendering, gate-check, and context commands may produce Markdown or plain text. All failures use one-line `{ok: false, error}` records on stderr with typed exit codes (`1` expected, `2` continuation guard, `3` crash). During build, the action identifies the next `in_progress` or `todo` item; after all items are terminal it still returns `run_phase` until verification, adversarial review, and Review implementation preparation finish. Before any final response, the agent runs `task-next.mjs <task-id> --require-stop` and parses its machine-readable `continuation` object; exit code `2` (`continuation.code = CONTINUATION_REQUIRED`) means it must execute `continuation.command` instead of replying. This guard is detection, not hard prevention: no package-owned hook can intercept a message the model host has already emitted, so the residual risk is a premature final response that the host must recover from by running `task next <task-id>` in its very next turn and executing the returned command — never by re-approving a gate. Creating a new task while another is actionable is likewise fail-closed at the local CLI: `task create` rejects it until the agent passes the returned `--switch-from` acknowledgement with explicit user direction, which stamps a resume-marker diagnostic on the acknowledged task instead of mutating it. The optional AI-DLC Coordination service does not enforce this switch guard; remote `upsertTask`/`replaceState` can still add tasks alongside actionable work, so MCP-backed hosts rely on the adapter protocol for switch discipline.
73
+ - `task create` fails closed while another task is actionable until the agent passes the returned `--switch-from` acknowledgement with explicit user direction; this stamps a resume-marker diagnostic on the acknowledged task without mutating it.
74
+ - The coordination service does not enforce this guard (remote `upsertTask`/`replaceState` can add tasks alongside actionable work); MCP-backed hosts rely on the adapter protocol.
68
75
 
69
76
  ## Review steps and approvals
70
77
 
71
- Review-step names are English in every task. Internal IDs remain unchanged for commands and structured state:
78
+ Review-step names are English in every task; internal IDs are stable. Identify gates by `gate`, never by display text (`title`, `action`).
72
79
 
73
80
  | Review step | Internal gate ID |
74
81
  | --- | --- |
@@ -76,25 +83,27 @@ Review-step names are English in every task. Internal IDs remain unchanged for c
76
83
  | Approve plan | `G1_review` |
77
84
  | Review implementation | `G2_codereview` |
78
85
 
79
- Display text such as JSON `title` and `action` uses these names; integrations should identify gates by `gate`, not by display text.
80
-
81
- Approval is an explicit human action. When the agent receives an approval, it records the approval and advances the lifecycle atomically:
82
-
83
86
  ```sh
84
87
  node .agents/aidlc/scripts/state.mjs gate approve <task-id> --gate <gate-name> --source "<explicit approval>"
85
88
  ```
86
89
 
87
- Do not invent approvals or approve unresolved design decisions. Approval evidence can be created only by `gate approve`; generic evidence recording cannot manufacture it. A passing approval at Approve plan starts a build boundary. Verification, adversarial review, and approval at Review implementation used to enter wrap must all belong to the current boundary.
88
-
89
- `--source` records provenance; it is not authentication or proof of consent. The local CLI enforces lifecycle structure, while the host agent must call `gate approve` only in a later user turn that explicitly assents to the gate currently shown.
90
-
91
- A reopened plan invalidates prior approvals at Approve plan and Review implementation, resets every non-deferred build item to `todo`, and requires current-build verification and review. Evidence is append-only, so the runtime identifies the current boundary by evidence order instead of trusting timestamps. For each affected area, at least one `test` or `lint` result is required and the latest result of every verification kind present must pass; one kind cannot hide a failure in the other.
92
-
93
- Terminal archiving commits the immutable record before the compact catalog. A retry may recover the narrow interrupted-write window only when the catalog still proves the same task is active and the unreferenced record has the same stable identity. Other archive conflicts require investigation rather than overwrite. Rendered workplans are derived views and are replaced atomically under the same state lock when rendered by the standalone command.
90
+ - Approval is an explicit human action, recorded and advanced atomically by `gate approve` — the only command that creates approval evidence. Never invent approvals or approve unresolved design decisions.
91
+ - `--source` is provenance, not authentication. Call `gate approve` only in a later user turn that explicitly assents to the gate currently shown.
92
+ - Approve plan starts a build boundary; the verification, adversarial review, and Review implementation approval that enter wrap must belong to the current boundary.
93
+ - Reopening the plan invalidates Approve plan and Review implementation approvals, resets every non-deferred build item to `todo`, and requires current-build verification and review.
94
+ - Evidence is append-only; the current boundary is identified by evidence order, not timestamps.
95
+ - Per affected area: at least one `test` or `lint` result, and the latest result of every verification kind present must pass.
96
+ - Archiving commits the immutable record before the compact catalog; a retry recovers the interrupted-write window only when the catalog still proves the same active task and the orphan record has the same stable identity. Other conflicts need investigation, not overwrite.
97
+ - Rendered workplans are derived views, replaced atomically under the state lock by the standalone render command.
94
98
 
95
99
  ## Blocked work and successors
96
100
 
97
- `blocked_on_user` means a valid human gate is ready; wrap has no human gate and rejects it. The status command validates gate prerequisites before persisting it, and `gate-view` refuses to present an active or unready task. Ordinary exits from a validated human-gate wait require audited reason and source metadata plus diagnostic evidence; sourced closure and handoff records provide the corresponding terminal trail. The two compatibility paths are migration-stamped legacy Review implementation waits and recovery of an invalid `wrap`/`none` wait; neither is a human approval. The `legacyG2Wait` marker is written only by state-schema migration (`state.mjs state migrate` or a human-run installer upgrade), only exempts a still-ready pre-existing wait from the repair bound, and is cleared by every route out of the wait. Repair bounds are machine-enforced: three failed verify records per area or two failed review records in the current build flip `nextAction` to `blocked` and close Review implementation with `REPAIR_BOUND` until a durable handoff is recorded. It does not mean a failed change is waiting for a rubber stamp. When verification or review cannot pass, the workflow records a durable handoff and offers structured options.
101
+ `blocked_on_user` means a valid human gate is ready, never that a failed change awaits a rubber stamp. When verification or review cannot pass, record a durable handoff:
102
+
103
+ - **Validation.** Wrap has no human gate and rejects `blocked_on_user`; `task status` validates gate prerequisites before persisting it, and `gate-view` refuses an active or unready task.
104
+ - **Leaving a gate wait.** Requires audited reason and source metadata plus diagnostic evidence; sourced closure and handoff records give the terminal trail.
105
+ - **Compatibility paths.** Only migration-stamped legacy Review implementation waits and recovery of an invalid `wrap`/`none` wait are exempt; neither is an approval. `legacyG2Wait` is written only by state-schema migration (`state.mjs state migrate` or a human-run installer upgrade), exempts only a still-ready pre-existing wait from the repair bound, and is cleared by every route out of the wait.
106
+ - **Repair bounds.** Three failed verify records per area or two failed review records in the current build flip `nextAction` to `blocked` and close Review implementation with `REPAIR_BOUND` until a durable handoff is recorded.
98
107
 
99
108
  ```sh
100
109
  node .agents/aidlc/scripts/state.mjs task handoff <task-id> --kind <kind> --reason "<reason>" --source "<evidence>"
@@ -102,25 +111,29 @@ node .agents/aidlc/scripts/state.mjs task reopen <task-id> --to plan --reason "<
102
111
  node .agents/aidlc/scripts/state.mjs task close <task-id> --reason "<reason>" --source "<explicit request>"
103
112
  ```
104
113
 
105
- If work continues in a fresh task, create that task at Confirm requirements and link it as a successor. `closed` and `superseded` are terminal non-success outcomes; they do not transfer approvals or imply a completed delivery.
114
+ To continue in a fresh task, create it at Confirm requirements and link it as a successor. `closed` and `superseded` are terminal non-success outcomes: no approvals transfer, no delivery is implied.
106
115
 
107
116
  ## Operational rules
108
117
 
109
118
  - The installed workflow never downloads runtime assets or checks a registry.
110
119
  - Only a human may initiate or apply workflow upgrades.
111
- - Keep task artifacts and verification evidence honest; a status label never substitutes for test or review evidence.
112
- - Put project-specific behaviour in project configuration or local rules, not in the package-managed workflow kernel.
113
-
114
- See [Configuration](./configuration.md) for project customisation and [Command reference](./command-reference.md) for package commands.
115
-
120
+ - A status label never substitutes for test or review evidence.
121
+ - Put project-specific behaviour in project configuration or local rules, never in the package-managed kernel.
116
122
 
117
123
  ## Optional end-to-end loop
118
124
 
119
125
  > [!WARNING]
120
- > **Local loop mode is usable** today; **fleet mode and the coordination service are still under active development**. The loop is **experimental** — because the package is still pre-1.0 (`0.x`), its commands, configuration, and recovery behaviour can change incompatibly in any release before `1.0.0`.
126
+ > Experimental, pre-1.0. See [Status and stability](./loop-runbook.md#status-and-stability).
121
127
 
122
- When the project enables `loop.mode`, `aidlc-kit loop start` accepts a requirement once (interactive prompt or stdin), creates exactly one task under the configured authority, and runs the loop to the first gate or to completion. `loop status` reports the canonical task and gate checkpoint; `loop resume` continues after an interruption. The intake is idempotent: re-running `start` with the same task ID and requirement reuses the existing task, and it refuses to create a second task while another one is actionable.
128
+ - With `loop.mode` enabled, `aidlc-kit loop start` (local: `./.agents/aidlc/scripts/loop.sh up`) runs one singleton daemon per project; it reads no requirement, runs only loop-owned tasks, and auto-resumes actionable ones.
129
+ - Add tasks with `aidlc-kit loop intake` (requirement on stdin) or the dashboard **New task**; the same ID and requirement reuse the task. There is no `loop resume`: re-activate with the dashboard **resume** or `state.mjs task status <id> --status active`.
130
+ - After a restart the daemon reconciles from canonical state; a consumed, stale, or mismatched checkpoint stops for manual reconciliation. A paused or handed-off task, outdated snapshot, or uncertain Git result is never auto-resumed.
131
+ - The loop never approves a gate: local mode uses the trusted terminal `loop-gate.mjs` or the signed-in dashboard, fleet mode only the reviewer credential.
132
+ - Leads and workers may be `codex`, `claude`, or `opencode`; only the container-isolated lead rejects OpenCode. Any `opencode` provider needs `AIDLC_OPENCODE_MODEL` ([Provider credentials and OpenCode](./configuration.md#provider-credentials-and-opencode)).
123
133
 
124
- The loop never approves a gate itself. At each gate it publishes the review packet and waits; in local mode approval happens only through the trusted host terminal command, and in fleet mode only through the reviewer credential against the published snapshot and revision. After a real approval the running supervisor re-reads the canonical state and checkpoint, re-acquires its fenced lease, and resumes automatically. If the supervisor is not running at approval time, restart it and it reconciles from the checkpoint; a consumed, stale, or mismatched checkpoint stops for manual reconciliation instead of guessing. Restarting never resumes a paused or handed-off task, an outdated snapshot, or an uncertain Git result — those require the documented recovery actions.
134
+ ## Related
125
135
 
126
- The supervisor runs in the foreground or under a process supervisor you choose; there is no background daemon. Workers execute in Docker with their own scoped credentials and never inherit host access. Host-executed lead turns support `codex`, `claude`, or `opencode`; container-isolated lead turns and fleet worker containers reject `opencode` because it requires file-based credentials, returning `OpenCode workers require file-based credentials and are not available in isolated containers yet` instead of falling back to the host. Local Docker worker batches accept `opencode` via environment credentials with OpenCode's XDG roots redirected into the worker's ephemeral HOME. When the loop uses `opencode`, set `AIDLC_OPENCODE_MODEL` to a `provider/model[#variant]` value. See [Command reference](./command-reference.md) for the loop commands and environment, and [Coordination service](./coordination-service.md) for fleet deployment, backends, and recovery.
136
+ - [Loop setup runbook](./loop-runbook.md) — loop setup.
137
+ - [Local loop walkthrough](./loop-local-run.md) — local loop operation.
138
+ - [Command reference: `loop`](./command-reference.md#loop) — loop actions and environment.
139
+ - [Configuration](./configuration.md) — project, loop, and adapter settings.