@felixdotgo/aidlc-kit 0.1.1 → 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 (198) hide show
  1. package/DEVELOPMENT.md +14 -13
  2. package/README.md +37 -43
  3. package/dist/assets/.agents/aidlc/docker/Dockerfile.claude +7 -0
  4. package/dist/assets/.agents/aidlc/docker/Dockerfile.codex +9 -0
  5. package/dist/assets/.agents/aidlc/docker/Dockerfile.opencode +8 -0
  6. package/dist/assets/.agents/aidlc/orchestrator.md +2 -2
  7. package/dist/assets/.agents/aidlc/phase-clarify.md +1 -1
  8. package/dist/assets/.agents/aidlc/phase-plan.md +2 -2
  9. package/dist/assets/.agents/aidlc/schemas/config.schema.json +2 -1
  10. package/dist/assets/.agents/aidlc/schemas/state.schema.json +2 -0
  11. package/dist/assets/.agents/aidlc/scripts/lib/assignment-store.mjs +94 -48
  12. package/dist/assets/.agents/aidlc/scripts/lib/context-runtime.mjs +5 -4
  13. package/dist/assets/.agents/aidlc/scripts/lib/loop-authority.mjs +261 -0
  14. package/dist/assets/.agents/aidlc/scripts/lib/loop-commit-message.mjs +45 -0
  15. package/dist/assets/.agents/aidlc/scripts/lib/loop-daemon.mjs +206 -0
  16. package/dist/assets/.agents/aidlc/scripts/lib/loop-drivers.mjs +100 -14
  17. package/dist/assets/.agents/aidlc/scripts/lib/loop-env.mjs +279 -0
  18. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-cli.mjs +105 -32
  19. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-remote.mjs +17 -1
  20. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-supervisor.mjs +24 -7
  21. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet.mjs +42 -16
  22. package/dist/assets/.agents/aidlc/scripts/lib/loop-git.mjs +20 -6
  23. package/dist/assets/.agents/aidlc/scripts/lib/loop-holder.mjs +376 -0
  24. package/dist/assets/.agents/aidlc/scripts/lib/loop-intake.mjs +33 -7
  25. package/dist/assets/.agents/aidlc/scripts/lib/loop-lease.mjs +67 -61
  26. package/dist/assets/.agents/aidlc/scripts/lib/loop-leases.mjs +268 -0
  27. package/dist/assets/.agents/aidlc/scripts/lib/loop-local-workers.mjs +116 -28
  28. package/dist/assets/.agents/aidlc/scripts/lib/loop-runtime.mjs +114 -12
  29. package/dist/assets/.agents/aidlc/scripts/lib/loop-stream.mjs +117 -0
  30. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-local.mjs +16 -56
  31. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-run-local.mjs +149 -6
  32. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor.mjs +9 -1
  33. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-docker.mjs +44 -6
  34. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-image.mjs +64 -0
  35. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-log.mjs +158 -0
  36. package/dist/assets/.agents/aidlc/scripts/lib/repo-head.mjs +22 -0
  37. package/dist/assets/.agents/aidlc/scripts/lib/store.mjs +68 -2
  38. package/dist/assets/.agents/aidlc/scripts/lib/task-runtime-migrate.mjs +75 -0
  39. package/dist/assets/.agents/aidlc/scripts/lib/task-runtime.mjs +97 -0
  40. package/dist/assets/.agents/aidlc/scripts/loop-entry.mjs +168 -73
  41. package/dist/assets/.agents/aidlc/scripts/loop-gate.mjs +19 -7
  42. package/dist/assets/.agents/aidlc/scripts/loop.cmd +101 -0
  43. package/dist/assets/.agents/aidlc/scripts/loop.mjs +2 -1
  44. package/dist/assets/.agents/aidlc/scripts/loop.sh +71 -0
  45. package/dist/assets/.agents/aidlc/scripts/remote-state.mjs +10 -4
  46. package/dist/assets/.agents/aidlc/scripts/state.mjs +16 -8
  47. package/dist/assets/.agents/aidlc/templates/design.md +9 -0
  48. package/dist/assets/.agents/aidlc/templates/intent.md +4 -0
  49. package/dist/assets/.agents/aidlc/templates/workplan.md +1 -1
  50. package/dist/assets/.agents/skills/aidlc-plan/SKILL.md +1 -1
  51. package/dist/assets/ui/bulma.min.css +3 -0
  52. package/dist/assets/ui/changes.js +83 -0
  53. package/dist/assets/ui/common.js +664 -0
  54. package/dist/assets/ui/dashboard.css +636 -0
  55. package/dist/assets/ui/dashboard.js +77 -0
  56. package/dist/assets/ui/detail.js +159 -0
  57. package/dist/assets/ui/live-log.js +332 -0
  58. package/dist/services/aidlc-coordination/Dockerfile +11 -3
  59. package/dist/services/aidlc-coordination/compose.yaml +12 -0
  60. package/dist/services/aidlc-coordination/package-lock.json +3 -1
  61. package/dist/services/aidlc-coordination/package.json +9 -4
  62. package/dist/services/aidlc-coordination/src/lifecycle-core.mjs +68 -2
  63. package/dist/services/aidlc-coordination/src/repository.mjs +66 -0
  64. package/dist/services/aidlc-coordination/src/server.mjs +9 -3
  65. package/dist/services/aidlc-coordination/test/fleet.test.mjs +21 -0
  66. package/dist/services/aidlc-coordination/test/server-health-auth.test.mjs +67 -0
  67. package/dist/src/adapters.d.ts +0 -3
  68. package/dist/src/adapters.js +3 -5
  69. package/dist/src/cli/argv.d.ts +12 -0
  70. package/dist/src/cli/argv.js +68 -0
  71. package/dist/src/cli/commands.d.ts +8 -0
  72. package/dist/src/cli/commands.js +159 -0
  73. package/dist/src/cli/loop-launcher.d.ts +47 -0
  74. package/dist/src/cli/loop-launcher.js +322 -0
  75. package/dist/src/cli/options.d.ts +25 -0
  76. package/dist/src/cli/options.js +32 -0
  77. package/dist/src/cli/prompt.d.ts +9 -0
  78. package/dist/src/cli/prompt.js +66 -0
  79. package/dist/src/cli.js +28 -191
  80. package/dist/src/gate.js +3 -2
  81. package/dist/src/installer.d.ts +14 -7
  82. package/dist/src/installer.js +42 -143
  83. package/dist/src/legacy.js +1 -0
  84. package/dist/src/managed-content.d.ts +7 -0
  85. package/dist/src/managed-content.js +15 -4
  86. package/dist/src/managed-planning.d.ts +65 -0
  87. package/dist/src/managed-planning.js +219 -0
  88. package/dist/src/mcp-setup.js +3 -1
  89. package/dist/src/model/config-contracts.d.ts +65 -0
  90. package/dist/src/model/config-contracts.js +1 -0
  91. package/dist/src/model/install-contracts.d.ts +29 -0
  92. package/dist/src/model/install-contracts.js +1 -0
  93. package/dist/src/model/lifecycle-enums.d.ts +13 -0
  94. package/dist/src/model/lifecycle-enums.js +1 -0
  95. package/dist/src/model/loop.d.ts +20 -0
  96. package/dist/src/model/loop.js +1 -0
  97. package/dist/src/model/manifest.d.ts +16 -0
  98. package/dist/src/model/manifest.js +1 -0
  99. package/dist/src/model/records.d.ts +142 -0
  100. package/dist/src/model/records.js +1 -0
  101. package/dist/src/model.d.ts +11 -264
  102. package/dist/src/model.js +1 -1
  103. package/dist/src/profiles.d.ts +2 -0
  104. package/dist/src/profiles.js +53 -9
  105. package/dist/src/state/archive-record.d.ts +9 -0
  106. package/dist/src/state/archive-record.js +26 -0
  107. package/dist/src/state/commands.d.ts +18 -0
  108. package/dist/src/state/commands.js +27 -0
  109. package/dist/src/state/domain.d.ts +9 -0
  110. package/dist/src/state/domain.js +9 -0
  111. package/dist/src/state/guards.d.ts +7 -0
  112. package/dist/src/state/guards.js +17 -0
  113. package/dist/src/state/io.d.ts +10 -0
  114. package/dist/src/state/io.js +35 -0
  115. package/dist/src/state/items.d.ts +3 -4
  116. package/dist/src/state/items.js +58 -57
  117. package/dist/src/state/lessons.js +14 -7
  118. package/dist/src/state/lifecycle.js +2 -2
  119. package/dist/src/state/lock.js +7 -6
  120. package/dist/src/state/memory.js +24 -12
  121. package/dist/src/state/{archive.js → migrate.js} +7 -7
  122. package/dist/src/state/partition.d.ts +15 -0
  123. package/dist/src/state/partition.js +90 -0
  124. package/dist/src/state/paths.d.ts +11 -0
  125. package/dist/src/state/paths.js +12 -0
  126. package/dist/src/state/render.js +9 -6
  127. package/dist/src/state/store.js +9 -15
  128. package/dist/src/state/transitions.js +9 -7
  129. package/dist/src/state/validate.js +55 -7
  130. package/dist/src/state.d.ts +16 -11
  131. package/dist/src/state.js +16 -11
  132. package/dist/src/task-ui.d.ts +33 -0
  133. package/dist/src/task-ui.js +33 -0
  134. package/dist/src/ui/assets.d.ts +14 -0
  135. package/dist/src/ui/assets.js +45 -0
  136. package/dist/src/ui/changes.d.ts +83 -0
  137. package/dist/src/ui/changes.js +498 -0
  138. package/dist/src/ui/containers.d.ts +71 -0
  139. package/dist/src/ui/containers.js +214 -0
  140. package/dist/src/ui/daemon.d.ts +75 -0
  141. package/dist/src/ui/daemon.js +232 -0
  142. package/dist/src/ui/data.d.ts +42 -0
  143. package/dist/src/ui/data.js +89 -0
  144. package/dist/src/ui/docs.d.ts +13 -0
  145. package/dist/src/ui/docs.js +39 -0
  146. package/dist/src/ui/files.d.ts +3 -0
  147. package/dist/src/ui/files.js +20 -0
  148. package/dist/src/ui/http.d.ts +14 -0
  149. package/dist/src/ui/http.js +80 -0
  150. package/dist/src/ui/live.d.ts +5 -0
  151. package/dist/src/ui/live.js +43 -0
  152. package/dist/src/ui/markdown.d.ts +2 -0
  153. package/dist/src/ui/markdown.js +127 -0
  154. package/dist/src/ui/options.d.ts +48 -0
  155. package/dist/src/ui/options.js +81 -0
  156. package/dist/src/ui/security.d.ts +34 -0
  157. package/dist/src/ui/security.js +38 -0
  158. package/dist/src/ui/server.d.ts +39 -0
  159. package/dist/src/ui/server.js +347 -0
  160. package/dist/src/ui/sse.d.ts +14 -0
  161. package/dist/src/ui/sse.js +281 -0
  162. package/dist/src/ui/views/board.d.ts +7 -0
  163. package/dist/src/ui/views/board.js +131 -0
  164. package/dist/src/ui/views/changes.d.ts +19 -0
  165. package/dist/src/ui/views/changes.js +154 -0
  166. package/dist/src/ui/views/components.d.ts +56 -0
  167. package/dist/src/ui/views/components.js +113 -0
  168. package/dist/src/ui/views/docs.d.ts +15 -0
  169. package/dist/src/ui/views/docs.js +64 -0
  170. package/dist/src/ui/views/layout.d.ts +44 -0
  171. package/dist/src/ui/views/layout.js +233 -0
  172. package/dist/src/ui/views/task.d.ts +25 -0
  173. package/dist/src/ui/views/task.js +320 -0
  174. package/dist/src/upgrade-board.js +10 -10
  175. package/dist/src/upgrade.d.ts +0 -1
  176. package/dist/src/upgrade.js +24 -85
  177. package/dist/src/workflow.d.ts +4 -0
  178. package/dist/src/workflow.js +36 -4
  179. package/docs/README.md +41 -22
  180. package/docs/architecture.md +101 -37
  181. package/docs/command-reference.md +289 -52
  182. package/docs/configuration.md +70 -30
  183. package/docs/coordination-service.md +91 -30
  184. package/docs/design-decisions.md +87 -0
  185. package/docs/development.md +124 -49
  186. package/docs/loop-local-run.md +228 -0
  187. package/docs/loop-runbook.md +214 -0
  188. package/docs/operating-workflow.md +55 -42
  189. package/docs/testing-and-release.md +72 -49
  190. package/docs/troubleshooting.md +221 -0
  191. package/package.json +4 -1
  192. package/dist/src/ledger.d.ts +0 -22
  193. package/dist/src/ledger.js +0 -119
  194. package/dist/src/state/shared.d.ts +0 -29
  195. package/dist/src/state/shared.js +0 -71
  196. package/dist/src/tracker.d.ts +0 -36
  197. package/dist/src/tracker.js +0 -44
  198. /package/dist/src/state/{archive.d.ts → migrate.d.ts} +0 -0
@@ -1,91 +1,274 @@
1
1
  # Command reference
2
2
 
3
- All package commands operate on local files. The examples run version `0.1.1` through npm; `npx` may ask permission to fetch that package on first use. Replace `.` with the target project path when needed. For a source checkout, see the [development guide](./development.md).
3
+ Lookup reference for every `aidlc-kit` command, flag, and loop environment variable, plus the lifecycle scripts installed into a project. Concepts: [Operating the workflow](./operating-workflow.md); `.agents/config.json` fields: [Configuration](./configuration.md).
4
+
5
+ - All commands operate on local files. Examples run version `0.3.0` through npm (`npx` may ask to fetch the package once); replace `.` with the target project path. Source checkout: [development guide](./development.md).
6
+ - Global flags: `--version` (`-v`) prints the package version and exits; `--help` prints usage.
7
+
8
+ Contents:
9
+
10
+ - [`init`](#init) — install the workflow into a project.
11
+ - [`status`](#status) — report the installed version.
12
+ - [`doctor`](#doctor) — check manifest, configuration, and state.
13
+ - [`profile validate`](#profile-validate) — print the resolved profile chain.
14
+ - [`uninstall`](#uninstall) — remove managed assets.
15
+ - [`mcp setup`](#mcp-setup) — configure the optional coordination service.
16
+ - [`upgrade`](#upgrade) — human-only package upgrade.
17
+ - [`loop`](#loop) — run and inspect the end-to-end loop daemon.
18
+ - [`ui`](#ui) — web dashboard.
19
+ - [Installed lifecycle scripts](#installed-lifecycle-scripts) — `state.mjs`, `task-next.mjs`, `loop.mjs`, and fleet scripts inside the project.
4
20
 
5
21
  ## `init`
6
22
 
7
23
  ```sh
8
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit init [path] [--agent <name[,name]> | --all] [--loop-mode off|local|fleet] [--loop-lead codex|claude|opencode] [--loop-workers <id=provider,...>] [--yes] [--dry-run] [--force]
24
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit init [path] [--agent <name[,name]> | --all] [--loop-mode off|local|fleet] [--loop-lead codex|claude|opencode] [--loop-workers <id=provider,...>] [--yes] [--dry-run] [--force]
9
25
  ```
10
26
 
11
- Plans the installation, prints a preview, and then writes the workflow only after confirmation (or `--yes`). `--dry-run` prints the same plan without writing. If exactly one installed agent is detected, it can be selected automatically. In an interactive terminal, choose multiple agents with the checkbox prompt: use arrow keys to move, Space to toggle, A to toggle all, and Enter to confirm. For scripts and non-interactive terminals, use `--agent <name[,name]>` or `--all`.
12
-
13
- In interactive setup, choose a loop mode and, when enabled, the lead and worker providers. For non-interactive setup, omit loop options to keep the default off, or specify `--loop-mode local|fleet` together with `--loop-lead` and `--loop-workers` (for example, `--loop-workers a=codex,b=opencode`). The preview includes the project config change. These settings only configure the loop; run `aidlc-kit loop start` to actually start it. The loop and the coordination service are experimental: their flags and defaults may change incompatibly in any release before `1.0.0`.
14
-
15
- `--force` is for an intentional initial replacement of an unmanaged conflicting file. It is not an upgrade mechanism. If the project already has another workflow package version, use the human-run upgrade flow instead.
27
+ - Prints a preview and writes only after confirmation (or `--yes`); `--dry-run` prints the plan without writing.
28
+ - One detected agent is selected automatically. Interactive terminals get a checkbox prompt (arrows move, Space toggles, A toggles all, Enter confirms); scripts pass `--agent <name[,name]>` or `--all`.
29
+ - Interactive setup asks for a loop mode and providers. Non-interactive: omit loop options to keep `off`, or pass `--loop-mode local|fleet` with `--loop-lead` and `--loop-workers` (for example `--loop-workers a=codex,b=opencode`). This only configures the loop; `aidlc-kit loop start` starts it.
30
+ - Loop and coordination flags are experimental ([Status and stability](./loop-runbook.md#status-and-stability)).
31
+ - `--force` replaces an unmanaged conflicting file on an intentional initial install only; it is not an upgrade mechanism. Another installed package version needs the human-run upgrade.
16
32
 
17
33
  ## `status`
18
34
 
19
35
  ```sh
20
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit status [path]
36
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit status [path] [--json]
21
37
  ```
22
38
 
23
- Reports the installed version and local installation status. It does not query a registry.
39
+ - Reports the installed version and local installation status; never queries a registry.
40
+ - `--json` prints `workflow`, `installedVersion`, `schema`, `detectedAgents`.
24
41
 
25
42
  ## `doctor`
26
43
 
27
44
  ```sh
28
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit doctor [path] [--strict]
45
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit doctor [path] [--strict] [--json]
29
46
  ```
30
47
 
31
- Checks the local manifest, configuration, and canonical state. `--strict` turns compatibility warnings such as a legacy manifest into errors. It does not query a registry.
48
+ - Checks the local manifest, configuration, and canonical state; never queries a registry.
49
+ - `--strict` turns compatibility warnings (for example a legacy manifest) into errors.
50
+ - `--json` prints `{level, message, strict}`; an `error` level exits non-zero.
32
51
 
33
52
  ## `profile validate`
34
53
 
35
54
  ```sh
36
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit profile validate [path]
55
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit profile validate [path]
37
56
  ```
38
57
 
39
- Loads `.agents/config.json`, resolves its profile chain, and prints the effective profile order. Use it after changing `extends` or local profiles.
58
+ - Resolves the `.agents/config.json` profile chain and prints the effective order. Run it after changing `extends` or local profiles.
40
59
 
41
60
  ## `uninstall`
42
61
 
43
62
  ```sh
44
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit uninstall [path] [--yes] [--dry-run]
63
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit uninstall [path] [--yes] [--dry-run]
45
64
  ```
46
65
 
47
- Prints the removal plan before applying it. It removes eligible unchanged managed assets but preserves project configuration and state. Prefer `--dry-run` first when working in an existing project.
66
+ - Prints the removal plan, then removes eligible unchanged managed assets; project configuration and state are preserved. Run `--dry-run` first in an existing project.
48
67
 
49
68
  ## `mcp setup`
50
69
 
51
70
  ```sh
52
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit mcp setup [path] [--dry-run] [--yes] [--storage sqlite|postgres] [--deployment docker|remote] [--bind localhost|network] [--workspace <id>] [--poll-ms <n>] [--enable]
71
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit mcp setup [path] [--dry-run] [--yes] [--storage sqlite|postgres] [--deployment docker|remote] [--bind localhost|network] [--workspace <id>] [--poll-ms <n>] [--token-env <name>] [--providers <p,...>] [--enable]
53
72
  ```
54
73
 
55
- Previews the optional AI-DLC Coordination service configuration, then writes only after confirmation. Non-interactive use requires `--deployment`, `--storage`, `--bind`, and `--workspace`. It never starts Docker; `--enable` is explicit and remote mode has no local fallback. See [AI-DLC Coordination service](./coordination-service.md) for deployment and credential requirements.
74
+ - Previews the coordination service configuration and writes only after confirmation. Non-interactive use requires `--deployment`, `--storage`, `--bind`, and `--workspace`.
75
+ - Never starts Docker; `--enable` is explicit; remote mode has no local fallback. Deployment and credentials: [AI-DLC Coordination service](./coordination-service.md).
76
+ - `--token-env <name>` overrides the default `AIDLC_MCP_TOKEN` variable name in the generated compose file.
77
+ - `--providers <p,...>` selects connectors non-interactively: `jira`, `trello`, `github-issues`.
56
78
 
57
79
  ## `upgrade`
58
80
 
59
81
  ```sh
60
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit upgrade [path] [--loop-mode off|local|fleet] [--loop-lead codex|claude|opencode] [--loop-workers <id=provider,...>] [--dry-run]
82
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit upgrade [path] [--loop-mode off|local|fleet] [--loop-lead codex|claude|opencode] [--loop-workers <id=provider,...>] [--dry-run]
61
83
  ```
62
84
 
63
- Upgrade is deliberately human-only. The command rejects `--yes` and `--force`; applying it requires an interactive terminal and an exact typed confirmation of the package version. Interactive confirmations use the same styled terminal prompt as `init`. Agents must not run, preview, detect, or suggest package upgrades on their own.
64
-
65
- An omitted loop selection preserves the existing config; an explicit selection appears in the preview and is included in the upgrade backup and rollback. Enabling a mode requires a lead and worker mapping.
66
-
67
- The upgrade plan handles supported legacy `.aidlc/` project data transactionally: identical paths are deduplicated, differing content or unsafe entries stop the plan, and an audit backup supports rollback. Review the preview before an authorised human applies it.
85
+ - Human-only: rejects `--yes` and `--force`, requires an interactive terminal and an exact typed confirmation of the package version (same styled prompt as `init`). Agents must never run, preview, detect, or suggest upgrades.
86
+ - An omitted loop selection preserves the existing config; an explicit one appears in the preview and in the backup and rollback. Enabling a mode requires a lead and worker mapping.
87
+ - Supported legacy `.aidlc/` data is handled transactionally: identical paths are deduplicated, differing content or unsafe entries stop the plan, and an audit backup supports rollback.
68
88
 
69
89
  ## `loop`
70
90
 
71
91
  ```sh
72
- npx --package @felixdotgo/aidlc-kit@0.1.1 aidlc-kit loop start|status|resume [options]
92
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop up [--root PATH] [--loop-env PATH] [--port 4173] [--host 127.0.0.1] [--open] [--no-ui]
93
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop down|stop [--root PATH] [--now]
94
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop env [--root PATH] [--loop-env PATH] [--json]
95
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop status [--root PATH] [--json]
96
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop start [--root PATH] [--mode local|fleet] [--loop-env PATH]
97
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop intake [--task-id ID] [--title TITLE] [--root PATH] [--mode local|fleet]
98
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop status --task-id ID [--root PATH] [--mode local|fleet]
99
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop worker-image [--provider opencode|codex|claude] [--tag TAG] [--root PATH]
100
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit loop leases [--task-id ID] [--root PATH] [--json] [--clear-stale]
73
101
  ```
74
102
 
75
103
  > [!WARNING]
76
- > The loop commands and fleet mode are **experimental and unfinished**: they contain known bugs and rough edges, and — because the package is still pre-1.0 (`0.x`) — their options, environment variables, and diagnostics can change incompatibly in any release before `1.0.0`.
77
-
78
- Options: `--task-id <id>` (optional for `start`, which derives one; required for `status`/`resume`), `--root <path>`, and `--mode local|fleet` (defaults to the configured `loop.mode`). `start` reads the requirement from an interactive prompt or stdin — the requirement is never passed as an argument. The command fails closed when the requested mode does not match the configured authority, when another task is actionable, or when a resume record is missing.
79
-
80
- `status` prints the canonical task, its derived next action, and — in fleet mode — the durable gate checkpoint. `start` and `resume` run the supervisor in the foreground until the next gate, a pause, a blocked state, or completion; the emitted events include each gate view and the waiting state.
104
+ > Experimental, pre-1.0. See [Status and stability](./loop-runbook.md#status-and-stability).
105
+
106
+ - `--mode` defaults to the configured `loop.mode` and fails closed on a mismatch (`Requested mode does not match configured authority`).
107
+ - Every action except `worker-image`, `leases`, and `migrate-data` requires an enabled `loop.mode` with a lead and worker mapping. Local and fleet mode share one daemon and the same actions.
108
+
109
+ | Action | Behaviour |
110
+ | --- | --- |
111
+ | `up` | Local mode only. Checks `loop.mode` is `local` (otherwise prints the config to add) and `--port` is valid, runs the `env` report and stops on any error, starts the daemon detached (stderr → `.agents/data/loop/daemon.log`; reports `already running` rather than starting a second; warns when the env file changed after the daemon started), then serves the dashboard in the foreground like `ui`, recording `{ pid, url }` (never the token) in `.agents/data/loop/ui.json`. `Ctrl-C` closes only the dashboard. `--no-ui` starts only the daemon; a recorded dashboard still answering at its URL is reported, not restarted (a stale record is ignored). |
112
+ | `down` | Stops the dashboard recorded by `up` — only when its URL answers `GET /api/instance` with the random id in `ui.json`, so another project's dashboard or a reused pid is never signalled — then the daemon (as `stop`). |
113
+ | `stop` | One `SIGTERM`: finish the current agent turn and exit, waiting up to 15 s; `--now` sends the second, cancelling the in-flight turn. The requested stage is recorded in `.agents/data/loop/daemon.stop` for that daemon run (pid and start time), so repeating `stop` or `stop --now` never sends the third signal that kills the daemon outright; a terminal `Ctrl-C` on a foreground `loop start` is not counted. An expired lease or a daemon held by another host is never signalled. On Windows the signal ends the process immediately. |
114
+ | `env` | Prints what the daemon will see: providers from `loop.agents`, the env file, and each variable with its source (`shell`, `file`, `derived:<path>`) and whether it is set. Only `AIDLC_OPENCODE_MODEL`, `AIDLC_LOOP_EVENT_LOG`, `AIDLC_WORKER_DOCKER_IMAGE`, `AIDLC_LOCAL_WORKTREES_ROOT`, and `AIDLC_ENV_FILE` show their value; others show `set` or `missing`; unreadable config files are reported without quoting content. Exits `1` when the daemon could not start (for example a missing OpenCode model). `--json` prints the same report. |
115
+ | `start` | Starts the singleton daemon in the foreground (`daemon` lease in `.agents/data/loop/daemon.lock`, renewed every 15 s; a second `start` fails with `Loop daemon already running (pid N): …` naming the holder). Reads **no** requirement. Fleet `start` preflights the coordination service (`fleet_get`) and the remote integration branch and fails closed instead of falling back to local. |
116
+ | `intake` | Creates one loop-owned task without running it. The requirement comes from stdin (interactive prompt on a TTY), at most 8192 bytes; id and title derive from its first line unless `--task-id`/`--title` are given. Local intake refuses while an interactive (non-loop) task is actionable; fleet intake creates the remote task under a short lead claim. Both write `.agents/data/tasks/<id>/runtime/intake.json` (`authority: "local"` or `"fleet"`) and `runtime/requirement.md`. |
117
+ | `status` | With `--task-id`: the canonical task and its derived next action, plus the loop run record (local) or the durable gate checkpoint (fleet). Without it: daemon (pid, start time, unresolved errors), dashboard, and the `env` report (`--json` combines them). |
118
+ | `leases` | Read-only diagnostic for every loop lease, lock, and claim (daemon lease, `.agents/data/loop/<task>.lease` with `activity`, assignment locks and claims with `effectiveState` from `.agents/data/tasks/<task>/runtime/assignments.*` — and from `.agents/data/loop/assignments/` until migrated — the state lock, leftovers from older versions): state (`live`, `stale`, `expired`, `corrupt`), holder (pid, host, command, activity), heartbeat, expiry, what it blocks, and the fix. With `loop.mode: fleet` and the lead credential (`AIDLC_FLEET_URL`, `AIDLC_FLEET_TOKEN`, `AIDLC_FLEET_WORKSPACE`) it also lists the `fleet_get` supervisor lease, lead lease (`run_claim`, lead epoch; supervisor epoch only when different), and job claims. `--task-id` filters; `--json` is stable (`schemaVersion: 1`); `--clear-stale` removes only stale or TTL-expired corrupt files, never a live holder, a claim, or the state lock. Works with any `loop.mode`; see [Troubleshooting](./troubleshooting.md#loop-leases-locks-and-claims). |
119
+ | `migrate-data` | Moves per-task files written by versions before the `runtime/` layout (`.agents/data/loop/assignments/<task>.json`, `loop/events/<task>.jsonl` and `.1`, `loop/<task>.json` run record, `tasks/<task>/loop-intake.json` and `requirement.md`) to `.agents/data/tasks/<task>/runtime/` (`assignments.json`, `events.jsonl`, `run.json`, `intake.json`, `requirement.md`). Idempotent: a file moves only when its destination is absent, an existing destination is reported `skipped` and the source kept; nothing is deleted or overwritten; locks, leases, guards, `<task>.supervisor.json`, and `<task>.gate-receipt.json` stay in `.agents/data/loop/`. `--dry-run` lists without moving; `--json` is stable (`schemaVersion: 1`, `entries[{ taskId, name, from, to, action: moved \| skipped \| would-move, reason? }]`, `moved`, `skipped`). The local daemon runs the same migration once at start (one `diagnostic` event when it moved or skipped anything), and each writer moves its own file before its first write, so running it by hand is optional. Works with any `loop.mode`. |
120
+ | `worker-image` | Builds the shipped worker image without loop configuration: `--provider` defaults to `opencode`, `--tag` to `aidlc-worker-<provider>:local`. Runs `docker build` on the packaged `assets/aidlc/docker/Dockerfile.<provider>` and records the tag in `config.loop.workerImage`. |
121
+
122
+ ### Daemon behaviour
123
+
124
+ - `loop resume` is removed (`loop resume is removed; the daemon auto-resumes actionable tasks — run 'loop start' …`). Re-activate a paused task with the dashboard **resume**, `state.mjs task status <id> --status active` (local), or `loop-entry.mjs resume-task <id> .` (either mode).
125
+ - **Ownership.** Only **loop-owned** tasks run: locally, tasks with an intake record or a loop run record; in fleet mode, only tasks whose local intake record says `authority: "fleet"`. Tasks created by an interactive lead are never picked up.
126
+ - **Scheduling.** Every `loop.pollMs` (default `5000` ms) the daemon lists actionable loop-owned tasks and runs one bounded supervised run per task in round-robin order (bounded by `loop.limits.maxTurns`).
127
+ - **Retries.** A run that throws, or ends `blocked` or `reconcile`, is retried with exponential backoff (poll interval doubled per failure, capped at 10 minutes). A gate wait or completion does not stop the daemon; an unreachable authority is reported as `daemon_poll_error` and retried next poll.
128
+ - **Fleet gates.** A fleet run returns at a gate (`gate`/`waiting`) and releases the supervisor lease; after reviewer approval the next poll re-claims the task.
129
+ - **Shutdown.** First `SIGINT`/`SIGTERM` stops after the current turn, second cancels the in-flight turn (and any build worker batch), third exits immediately. A terminal `Ctrl-C` also reaches the agent child, so the turn usually ends on the first press. Stopped runs are recorded `stopped` (not paused) and continue on the next `start`.
130
+ - **Events.** Events go to stderr with their `taskId` and are appended to the JSONL file named by `AIDLC_LOOP_EVENT_LOG` when set. Daemon events: `daemon_start`, `daemon_poll`, `daemon_poll_error`, `daemon_turn`, `daemon_turn_error`, `build_deferred` (a ready build item waiting for a later batch), `gate`, `loop_stopped`.
131
+
132
+ ### Loop environment (local mode)
133
+
134
+ `loop start`/`up` and a dashboard-started daemon resolve the environment in this order:
135
+
136
+ 1. **The invoking shell** — an exported variable is never overridden, even when empty.
137
+ 2. **The env file** — `AIDLC_ENV_FILE` (relative to the project root) or `--loop-env PATH` (relative to the current directory), default `.agents/loop.env`. Minimal dotenv: `KEY=VALUE`, optional `export `, `#` comments, quotes, no variable expansion. Values act like shell exports and reach the lead and the workers.
138
+ 3. **Values derived from the configured providers only:**
139
+
140
+ | Variable | Derived from |
141
+ | --- | --- |
142
+ | `AIDLC_LOOP_EVENT_LOG` | `.agents/data/loop/ui-events.jsonl` |
143
+ | `AIDLC_OPENCODE_MODEL` | `model` of the OpenCode config (project `opencode.json[c]` over `OPENCODE_CONFIG` over `~/.config/opencode`) |
144
+ | OpenCode worker keys | API-key entries in `~/.local/share/opencode/auth.json` |
145
+ | Codex worker key | `$CODEX_HOME/auth.json` (`OPENAI_API_KEY`; a ChatGPT-only login produces a warning) |
146
+ | Claude Code worker key | `env.ANTHROPIC_API_KEY` in `.claude/settings.local.json`, `.claude/settings.json`, or `~/.claude/settings.json` |
147
+
148
+ - Detected worker keys reach the Docker workers only; host lead turns do not receive them (`AIDLC_LEAD_ENV_EXCLUDE`), so a `claude` or `codex` lead keeps its own login.
149
+ - **Errors (daemon does not start):** a missing or invalid OpenCode model, an explicit env file that does not exist, or a malformed env file.
150
+ - **Warnings:** a missing worker key, a missing `docker`, or an env file that `git check-ignore` would not ignore.
151
+ - The option is `--loop-env`, not `--env-file` (Node.js reserves `--env-file`). Fleet mode does not read the env file.
152
+ - Optional overrides: `AIDLC_WORKER_DOCKER_IMAGE` (single worker image instead of the per-provider default) and `AIDLC_LOCAL_WORKTREES_ROOT` (worker worktrees root; default a system temp directory; must be outside the integration checkout).
153
+ - Local mode requires Docker plus provider credentials. The worker image is auto-built on first dispatch and its tag recorded; `AIDLC_WORKER_DOCKER_IMAGE` only overrides the default.
154
+ - Local approval: the trusted host terminal command `node .agents/aidlc/scripts/loop-gate.mjs <task-id>` (refuses piped input) or the dashboard.
155
+
156
+ ### Launchers (loop.sh / loop.cmd)
157
+
158
+ `init` and `upgrade` install `.agents/aidlc/scripts/loop.sh` (executable) and `loop.cmd` for every loop mode, plus `.agents/loop.env` (commented template) and `.agents/.gitignore` (`loop.env`) when missing; all are project-owned and never overwritten.
159
+
160
+ | Launcher command | Runs |
161
+ | --- | --- |
162
+ | `up` (default) | `aidlc-kit loop up` |
163
+ | `down` | `aidlc-kit loop down` |
164
+ | `stop` | `aidlc-kit loop stop` |
165
+ | `status` | `aidlc-kit loop status` |
166
+ | `check` | `aidlc-kit loop env` |
167
+ | `logs` | follows `.agents/data/loop/daemon.log` |
168
+
169
+ Each forwarded command runs with `--root` set to the project. CLI lookup order (never installs anything):
170
+
171
+ 1. The project's `node_modules/.bin`.
172
+ 2. The CLI that last applied `init`/`upgrade`, recorded as `{ cli, version, recordedAt }` in machine-local `.agents/data/loop/cli.json` (not in the manifest) while that file exists; covers `npx --package` and `.tgz` installs that `npx --no-install @felixdotgo/aidlc-kit` cannot find.
173
+ 3. `aidlc-kit` on `PATH`.
174
+ 4. `npx --no-install`.
175
+
176
+ ### Fleet environment
177
+
178
+ | Variable | Requirement |
179
+ | --- | --- |
180
+ | `AIDLC_FLEET_URL`, `AIDLC_FLEET_WORKSPACE` | Required. |
181
+ | `AIDLC_FLEET_TOKEN` | Required: the lead credential. |
182
+ | `AIDLC_FLEET_INTEGRATION_BRANCH` | Required. |
183
+ | `AIDLC_FLEET_GIT_REMOTE` | Optional. |
184
+ | `AIDLC_FLEET_PROJECT_ROOT`, `AIDLC_FLEET_WORKER_IDS`, `AIDLC_FLEET_WORKER_PROVIDERS`, lead agent | Derived by the facade from the root and `loop.agents`; explicitly set values must match. |
185
+ | `AIDLC_FLEET_MAX_TURNS`, `AIDLC_FLEET_TURN_TIMEOUT_MS`, `AIDLC_FLEET_MAX_STALL_TURNS`, `AIDLC_FLEET_POLL_MS` | Optional overrides. `loop.limits` (`maxTurns`, `turnTimeoutMs`, `maxStallTurns`) and `loop.pollMs` are the fleet defaults; an explicit value overrides them. |
186
+ | `AIDLC_FLEET_REVIEWER_TOKEN` | Never given to lead and worker processes. |
187
+
188
+ Fleet workers run through the fleet runner on each worker machine; a reviewer approves gates with the reviewer credential ([Coordination service](./coordination-service.md)).
189
+
190
+ ### Loop entry script (`loop-entry.mjs`)
191
+
192
+ - `loop-entry.mjs` is the single entry point behind the CLI and the dashboard. Positional form: `loop-entry.mjs <action> [task-id] [root] [mode] [provider] [tag] [title]`, for example `echo "<requirement>" | node .agents/aidlc/scripts/loop-entry.mjs intake "" .`.
193
+ - Diagnostic form: `loop-entry.mjs leases [task-id] [root] [--json] [--clear-stale]` (an empty task id lists every task).
194
+ - Extra actions: `resume-task <id>` (both modes) and the fleet-only dashboard JSON actions `tasks`, `task <id>`, `gate <id>` (current review snapshot with its checkpoint), `approve <id>`, `feedback <id>`. A local dashboard reads local state in-process, so these fail in local mode.
195
+ - `approve <id>` reads the approval source on stdin; the reviewer credential comes only from that process's `AIDLC_FLEET_REVIEWER_TOKEN`.
196
+ - `feedback <id>` reads stdin JSON `{"reason":"<feedback>","source":"<provenance>"}` and keeps the task at its gate via `remote-state.mjs task status <id> --status active --mode audited` under the lead claim; it never needs the reviewer credential.
197
+
198
+ ## `ui`
81
199
 
82
- Local mode requires the Docker worker image configuration described in [Testing and release](./testing-and-release.md) plus the provider credential environment; approval happens through the trusted host terminal command `node .agents/aidlc/scripts/loop-gate.mjs <task-id>`, which refuses piped input.
200
+ ```sh
201
+ npx --package @felixdotgo/aidlc-kit@0.3.0 aidlc-kit ui [path] [--port 4173] [--host 127.0.0.1] [--open] [--reviewer-token-file PATH]
202
+ ```
83
203
 
84
- Fleet mode requires the running coordination service (`AIDLC_FLEET_URL`, `AIDLC_FLEET_WORKSPACE`, lead `AIDLC_FLEET_TOKEN`, `AIDLC_FLEET_INTEGRATION_BRANCH`, and optionally `AIDLC_FLEET_GIT_REMOTE`); worker IDs must match the configured `loop.agents.workers`, and `AIDLC_FLEET_WORKER_PROVIDERS` may map each worker to `codex`, `claude`, or `opencode`. The facade preflights the service and the integration branch and fails closed with a diagnosis instead of falling back to local. Fleet worker containers reject `opencode` with the container diagnostic above; assignment validation accepts it so that blocker surfaces when the job executes rather than being reported as an invalid provider. Fleet workers run separately through the fleet runner (`worker --once`) on each worker machine with `AIDLC_WORKER_DOCKER_IMAGE` and their own worker credential; a reviewer approves gates through the reviewer credential as documented in [Coordination service](./coordination-service.md).
204
+ - Web dashboard on `node:http` (no extra dependencies). The project is the positional `path` (default `.`); there is no `--root` flag.
205
+ - Authority comes from `loop.mode` (header: `authority · local` or `authority · fleet`). Local dashboards read canonical state in-process; fleet dashboards read tasks, details, and gate snapshots through the `loop-entry.mjs` JSON actions.
206
+ - Dashboard usage (board, side panel, live log, containers, changes, settings, feedback): [Local loop walkthrough](./loop-local-run.md#use-the-web-dashboard).
207
+ - No session token: the dashboard is meant for a trusted local or LAN network and relies on request-shape guards ([Dashboard access](#dashboard-access)).
208
+
209
+ | Flag | Effect |
210
+ | --- | --- |
211
+ | `--port`, `--host` | Bind address; defaults to `127.0.0.1:4173`. Pass `--host 0.0.0.0` only as an explicit opt-in; a non-loopback bind prints `Warning: the dashboard has no authentication; expose it only on a trusted network.` |
212
+ | `--open` | Launches the system browser with the dashboard URL (best effort; the URL is printed anyway). |
213
+ | `--reviewer-token-file PATH` | Fleet only: reads the reviewer credential from `PATH` (same file rules, never created). `AIDLC_FLEET_REVIEWER_TOKEN` in the `ui` environment works the same way. |
214
+
215
+ ### Routes
216
+
217
+ - `GET /` — kanban board by `phase` with list toggle, **Settings**, and **New task**; `/?task=<id>` opens the task side panel.
218
+ - `GET /docs[/<slug>]` — the packaged guides; only whitelisted slugs are served (`404` otherwise).
219
+ - `POST /api/markdown` (field `markdown`) — `{ ok, html }` from the same escaping renderer as task artifacts.
220
+ - `GET /tasks/:id` — detail page (stepper, gate view or fleet snapshot text, rendered `intent`/`design`/`workplan`, decisions, items, **Containers**, evidence, live log). `GET /partial/tasks/:id` — the same body as an HTML fragment for the side panel (last 20 important log lines).
221
+ - `GET /tasks/:id/changes[?item=<item-id>][&ws=ignore]` — code changes (file list with +/− counts and status badges, unified diff) for the whole task or one item. **Wrap lines** and **Ignore whitespace** toggles on the page mirror the `diffWrap`/`diffIgnoreWs` settings.
222
+ - `GET /api/tasks/:id/changes[?item=][&ws=ignore]` — the same data: `{ ok, source, items: [{ itemId, workerId?, commit, base?, workingTree?, files: [{ path, oldPath?, status, added, removed, binary, whitespaceOnly? }], patch, truncated, note? }], note? }`. `ws=ignore` diffs with `git diff -w` for that request (whitespace-only files stay listed with `whitespaceOnly: true` and no patch section); any other `ws` value is `400`.
223
+ - One source order for every mode: **fleet** (fleet only) — the current gate snapshot's `integrationCommit` diffed against its first parent; **assignments** (local) — `.agents/data/tasks/<task>/runtime/assignments.json` (or the pre-runtime `.agents/data/loop/assignments/<task>.json` until migrated), per item the latest reported/integrated attempt, preferring its `integrationCommit`, else `baseCommit..commit`; **task-range** (any mode, when the task state carries `baseCommit`) — one item `task` diffing `baseCommit..finalCommit` for a `done` task, or `baseCommit..HEAD` plus the working tree (`workingTree: true`) while the task is open; **working-tree** — `git diff HEAD` plus untracked files, labelled uncommitted and not task-scoped.
224
+ - `task-range` is what makes changes durable: it needs only two SHAs recorded in the canonical task state ([Installed lifecycle scripts](#installed-lifecycle-scripts)), so it works for tasks driven from a terminal without the loop and after worker worktrees are gone. Its note says the range may include commits made outside the task. Assignments fall through to it when none of their commits is in the local repository; a fleet snapshot without an integration commit does the same. Outside a Git repository `source` is `none`.
225
+ - Only task and item ids come from the URL; commits come from records, are validated as hex SHAs and resolved with `git rev-parse`; Git runs without a shell.
226
+ - Limits: 300 files and 1 MiB of patch per item (`truncated: true` beyond), 4 MiB of patch per whole-task view; further items list files only and load their diff on selection.
227
+ - A recorded integration commit missing locally falls back to the worker commit; a commit missing entirely is a note, not an error.
228
+ - `GET /api/tasks/:id/containers` — worker containers recorded for the task: `{ ok, docker: "ok" | "unavailable", host, containers: [{ name, assignmentId, itemId, workerId, agent, mode, host, turn, startedAt, endedAt?, exitCode?, log, running, local }] }`, read from `.agents/data/tasks/<id>/runtime/workers/index.json` (same file in local and fleet mode; empty for tasks the loop never built). `running` combines the index with `docker ps --filter label=aidlc.task=<id>` (no shell, 4 s timeout, result shared for 1.5 s); without Docker the state falls back to the index and `docker` is `unavailable`. `local` is false for entries another fleet worker host recorded.
229
+ - `GET /api/tasks/:id/containers/:assignment/log[?tail=<bytes>]` — the raw container output of one assignment as `text/plain` (default tail 64 KiB, max 1 MiB, cut at a line boundary and prefixed with `… (earlier output truncated)`; headers `x-aidlc-log-size`, `x-aidlc-log-truncated`). Serves `<assignment>.log.1` when the current generation is missing. The file holds every turn's stdout and stderr unredacted between `--- turn N container <name> <time> ---` / `--- end turn … ---` lines; it never leaves the host.
230
+ - `GET /api/live?known=<region>:<hash>,…[&task=<id>][&drawer=<id>][&notify=<n>]` — in-place updates. Regions: `notify` (header bell; `notify` items, default 5, max 100), `daemon` (header pill), `board`, `detail` (needs `task`), `drawer` (needs `drawer`).
231
+ - Re-renders the listed regions from one state read and returns `{ regions: { <name>: { hash, html } }, reviews: { count, items } }` with only changed regions; unknown names are ignored.
232
+ - Pages poll about every 1.5 s and morph the HTML in place. In fleet mode reads share a result up to 1 s old instead of spawning `loop-entry.mjs` per request.
233
+ - `GET /api/tasks` (`?archive=1`, `?statuses=`, `?query=`, `?limit=`, `?cursor=`) — task summaries; `GET /api/tasks/:id` — one task; `GET /api/tasks/:id/gate` — gate view or fleet snapshot (`409` when not waiting); `GET /api/tasks/:id/artifact/:name` — raw artifact content.
234
+ - `GET /api/loop/status?task-id=` — `loop status` as JSON.
235
+ - `POST /api/loop/start` (field `requirement`) — loop intake, starting the daemon if none runs; `201` with `taskId`, `title`, `daemon`; `409` with the intake error.
236
+ - `POST /api/loop/resume` (field `taskId`) — re-activates a `paused` task; `409` for any other status.
237
+ - `POST /api/gate/approve` (fields `taskId`, `source`, optional `gate` — the gate the reviewer saw; `409` if the task now waits at another) — the atomic `state.mjs gate approve` locally, or the fleet reviewer approval of the current snapshot.
238
+ - `POST /api/gate/feedback` (fields `taskId`, `feedback`, optional `source`) — keeps the task at its gate: locally `state.mjs task status <id> --status active --mode audited --reason <feedback> --source <provenance>`, fleet `loop-entry.mjs feedback <id>`; `400` on missing `feedback`, `409` when not at a gate.
239
+ - All `POST` routes spawn the installed scripts asynchronously as thin facades; a malformed or non-object JSON body is `400`.
240
+ - `GET /api/events[?task-id=]` — SSE loop events: on connect the last 200 matching lines within the most recent 256 KB, then new complete lines; follows rotation/truncation and resumes from `Last-Event-ID`.
241
+ - With `task-id` (must match the task-id pattern, else `400`) it reads `.agents/data/tasks/<task-id>/runtime/events.jsonl` (`.1` generation first; the pre-runtime `.agents/data/loop/events/<task-id>.jsonl` until migrated); ids are `t:<inode>:<offset>` and a full replay is preceded by `event: reset`.
242
+ - Without a history file it filters the global `ui-events.jsonl` by `taskId`. A symlinked per-task file or `events` directory is never followed (falls back to the global file).
243
+
244
+ ### Dashboard access
245
+
246
+ The dashboard has no session token and no login: it is built for a trusted local machine or internal network. At start the CLI prints `Open: http://127.0.0.1:4173`. What still guards it:
247
+
248
+ - A `Host` header that does not name the bound address is rejected `403` (any loopback name — `127.0.0.1`, `localhost`, `[::1]` — is accepted when bound to loopback). A wildcard bind (`0.0.0.0`, `::`) cannot pin the Host and relies on the request-shape checks below.
249
+ - Every request other than `GET`/`HEAD`/`OPTIONS` must have the shape of a same-origin `fetch` from the dashboard page: an `Origin` header equal to the dashboard's own origin, `Sec-Fetch-Site` (when the browser sends it) of `same-origin` or `none`, and the custom header `x-aidlc-request`. Any missing or foreign value is `403`; the dashboard scripts send all three.
250
+ - In fleet mode `POST /api/gate/approve` returns `403` unless the UI holds a reviewer credential (`AIDLC_FLEET_REVIEWER_TOKEN` or `--reviewer-token-file`); without one the detail page shows the `remote-state.mjs gate inbox` / `gate approve` reviewer commands instead. The credential goes only to that one approve child process. `POST /api/gate/feedback` never needs it.
251
+ - The daemon and every other child process the UI spawns never inherit the reviewer credential.
252
+
253
+ Why (a browser sends requests to `127.0.0.1` on behalf of any web page):
254
+
255
+ - A cross-site form post cannot set a custom header or forge `Origin`, and a `fetch` with a custom header triggers a CORS preflight the dashboard never answers, so another page cannot create tasks or approve gates (CSRF). The Host check defeats DNS rebinding on a pinned bind; on a wildcard bind only IP-literal or `localhost` Host values are accepted, so a rebound DNS name is still refused.
256
+ - Residual risk: anyone who can reach the port can read and act; keep the default loopback bind unless the network is trusted, and remember that the reviewer credential (fleet) is the only secret the dashboard holds.
257
+
258
+ ### Operational notes
259
+
260
+ - The gate panel renders only on `/tasks/:id` while the task is `blocked_on_user`. Feedback records `Cancelled gate wait at <gate>: <feedback>`, sets the task `active` at the same gate, and the loop re-presents the revised artifact, exactly like `loop-gate.mjs` feedback; approval is never blocked by pending feedback.
261
+ - Live log events carry optional `actor` (`lead` or a worker id), `phase`, `itemId`, and a redacted `summary` (at most 240 characters; command output is never logged in the event stream — the raw per-container output lives only in the task's `runtime/workers/` log files). The **Important**/**All**/**Raw JSON** choice is kept in `localStorage` (`aidlc-live-log`); its default comes from **Settings**.
262
+ - **Settings** (header ⚙) are browser-only, kept in `localStorage` (`aidlc-settings`) and applied immediately: theme (system/light/dark), live-update interval (1.5 s, 3 s, paused), browser notifications when a task starts waiting for review, live log default filter and Raw JSON, diff wrap and ignore-whitespace, container log tail size (64/256/1024 KiB), and whether a card click opens the side panel or the full page. Nothing is stored server-side.
263
+ - **Task runtime data:** every per-task operational file lives under `.agents/data/tasks/<task-id>/runtime/`: `assignments.json`/`assignments.lock` (local worker claims), `events.jsonl` (+ `.1`, the task's event history), `run.json` (loop run record), `intake.json` and `requirement.md` (loop intake), and `workers/index.json` plus `workers/<assignment>.log` (5 MiB with one `.log.1` generation). The task directory root keeps only review artifacts. `runtime/` is treated like `.agents/data/loop/`: never part of a commit, handoff, or clean check, and listed in the installer's `.agents/.gitignore` (`data/loop/`, `data/tasks/*/runtime/`). The same layout serves the no-loop workflow, the local loop, and fleet (fleet claims live in the service; the lead host writes events, run record, and intake; worker hosts write `workers/`); without the loop only the files an interactive lead needs exist. Files from older versions: `migrate-data` above.
264
+ - Event files: every event goes to `.agents/data/loop/ui-events.jsonl` (rotated to `.jsonl.1` at 5 MB; feeds the daemon health banner), every task event also to `.agents/data/tasks/<task-id>/runtime/events.jsonl` (rotated to `.1` at 1 MiB; written only when the global file is the standard `<root>/.agents/data/loop/` sidecar, so the task is known). `daemon_poll` is written only when the actionable set, back-off set, or error state changes.
265
+ - Every local daemon (`loop up`, `loop start`, **New task**) sets `AIDLC_LOOP_EVENT_LOG` to the global file unless the shell does; `loop up` and **New task** daemons write stderr to `.agents/data/loop/daemon.log`.
266
+ - **Exposure:** every route relies on the bind address, the Host check, and the request-shape guards above. `--host 0.0.0.0` lets anyone reaching the port read task diffs, artifacts, container logs, and repository changes, and act on gates.
267
+ - **resume** appears only on `paused` tasks and runs the re-activation command for the mode; the daemon picks a loop-owned task up on its next poll.
85
268
 
86
269
  ## Installed lifecycle scripts
87
270
 
88
- After `init`, task lifecycle commands live in the target project, not in the package CLI:
271
+ After `init`, lifecycle commands live in the target project, not in the package CLI:
89
272
 
90
273
  ```sh
91
274
  node .agents/aidlc/scripts/state.mjs task list --limit 20
@@ -100,7 +283,9 @@ node .agents/aidlc/scripts/task-next.mjs <task-id> --require-stop
100
283
  node .agents/aidlc/scripts/gate-view.mjs <task-id>
101
284
  ```
102
285
 
103
- The normal interactive loop runs in the current Codex, Claude Code, or OpenCode conversation, using native agents and the installed lifecycle commands. The optional `loop.mjs` command is for unattended CLI execution:
286
+ ### Unattended runner (`loop.mjs`)
287
+
288
+ The interactive loop runs in the current Codex, Claude Code, or OpenCode conversation; `loop.mjs` runs one task unattended from the CLI:
104
289
 
105
290
  ```sh
106
291
  node .agents/aidlc/scripts/loop.mjs run <task-id> --agent codex|claude|opencode [--max-turns N] [--turn-timeout-ms N] [--max-stall-turns N] [--root PATH]
@@ -108,13 +293,16 @@ node .agents/aidlc/scripts/loop.mjs resume <task-id> [--max-turns N] [--turn-tim
108
293
  node .agents/aidlc/scripts/loop.mjs status <task-id> [--root PATH]
109
294
  ```
110
295
 
111
- `--agent opencode` requires `AIDLC_OPENCODE_MODEL` in `provider/model[#variant]` form; the turn fails closed without it. Docker-isolated lead turns, local Docker worker batches, and fleet worker containers reject OpenCode with `OpenCode workers require file-based credentials and are not available in isolated containers yet` and do not fall back to the host. Use `loop.mjs run --agent opencode` for host-executed lead turns, or use Codex or Claude Code where container isolation is required.
296
+ - `--agent opencode` requires `AIDLC_OPENCODE_MODEL` in `provider/model[#variant]` form; the turn fails closed without it. OpenCode works for host-executed lead turns and Docker workers, never the container-isolated lead ([Provider credentials and OpenCode](./configuration.md#provider-credentials-and-opencode)).
297
+ - **Limits.** Defaults: 12 turns, 10 minutes per turn; two completed turns without observable progress stop the run.
298
+ - **Provider.** Each run records its provider; `resume` rejects a different agent. The runner never grants human approval.
299
+ - **Lease.** A run holds `.agents/data/loop/<task-id>.lease` with activity `turn`, so `state.mjs gate approve <task-id>` refuses until it stops at the gate. `status` prints `liveLease` (the holder while a turn runs, else `null`) and `lease` (state, holder, activity, expiry, fix).
300
+ - **Resuming.** An interactive client resumes by reading `task next` and reconciling local assignment metadata; fleet execution uses fenced service leases and remote canonical state.
301
+ - If context preparation fails before a turn starts, the loop pauses with a reason; fix it and `resume`. An interrupted turn with no captured session ID needs inspection of canonical state before recovery.
112
302
 
113
- The defaults are 12 turns and 10 minutes per turn; two completed turns without observable progress stop the run. Each run records its provider, and `resume` rejects a different agent. The runner never grants human approval. An interactive client can resume by reading `task next` and reconciling local assignment metadata; fleet execution uses fenced service leases and the remote canonical state.
303
+ ### Fleet runner and remote state
114
304
 
115
- If context preparation fails before an agent turn starts, the loop pauses with a reason; fix the context problem and use `resume`. An interrupted running turn with no captured session ID still requires inspection of canonical state before recovery.
116
-
117
- The fleet runner drives the supervised multi-worker flow against a coordination service. From the service deployment (a source checkout or the installed `.agents/aidlc-coordination/`), with the lead credential plus `AIDLC_FLEET_WORKER_IDS`, `AIDLC_FLEET_INTEGRATION_BRANCH`, and `AIDLC_FLEET_PROJECT_ROOT` set:
305
+ From the service deployment (a source checkout or the installed `.agents/aidlc-coordination/`), with the lead credential plus `AIDLC_FLEET_WORKER_IDS`, `AIDLC_FLEET_INTEGRATION_BRANCH`, and `AIDLC_FLEET_PROJECT_ROOT`:
118
306
 
119
307
  ```sh
120
308
  node .agents/aidlc-coordination/src/fleet-run.mjs supervisor <task-id>
@@ -122,9 +310,12 @@ node .agents/aidlc-coordination/src/fleet-run.mjs coordinator <task-id> --once
122
310
  node .agents/aidlc-coordination/src/fleet-run.mjs worker --once
123
311
  ```
124
312
 
125
- `supervisor` claims the task's supervisor lease, runs fenced lead turns through the coordinator, publishes each gate snapshot with its checkpoint in one service transaction, waits for the reviewer approval, and resumes automatically; it returns at a pause, blocked state, or completion, and never approves a gate. `coordinator --once` runs a single unattended pass without the supervisor lease. `worker --once` claims one ready assignment on a worker machine; it requires `AIDLC_WORKER_DOCKER_IMAGE` and that machine's worker credential and fails closed without them. `aidlc-kit loop start --mode fleet` wraps the same supervisor with requirement intake and preflight.
313
+ - `supervisor` claims the supervisor lease, runs fenced lead turns through the coordinator, publishes each gate snapshot with its checkpoint in one service transaction, waits for reviewer approval, and resumes. It returns at a pause, blocked state, or completion and never approves a gate.
314
+ - `coordinator --once` runs one unattended pass without the supervisor lease.
315
+ - `worker --once` claims one ready assignment on a worker machine and fails closed without a usable worker image or that machine's worker credential ([image resolution](./coordination-service.md#multi-machine-loop-deployment)).
316
+ - `aidlc-kit loop start --mode fleet` runs the same supervisor inside the loop daemon, returning at each gate instead of waiting.
126
317
 
127
- Fleet mode uses `remote-state.mjs` instead of local `state.mjs`. Set `AIDLC_FLEET_URL`, `AIDLC_FLEET_WORKSPACE`, and `AIDLC_FLEET_PROJECT_ROOT`; lead mutations additionally require `AIDLC_FLEET_TOKEN` and the current `AIDLC_FLEET_LEAD_EPOCH`. Claim an epoch before creating or changing a task:
318
+ Fleet mode uses `remote-state.mjs` instead of `state.mjs`. Set `AIDLC_FLEET_URL`, `AIDLC_FLEET_WORKSPACE`, and `AIDLC_FLEET_PROJECT_ROOT`; lead mutations also need `AIDLC_FLEET_TOKEN` and the current `AIDLC_FLEET_LEAD_EPOCH`. Claim an epoch before creating or changing a task:
128
319
 
129
320
  ```sh
130
321
  node .agents/aidlc/scripts/remote-state.mjs run claim <task-id>
@@ -133,34 +324,75 @@ node .agents/aidlc/scripts/remote-state.mjs phase context <task-id>
133
324
  node .agents/aidlc/scripts/remote-state.mjs run release <task-id> --epoch <epoch>
134
325
  ```
135
326
 
136
- The same client supports task items, evidence, decisions, status, audited transitions, wrap lessons, and feature manifests through revision-checked remote mutations. It cannot approve gates with a lead token. A connected reviewer uses `gate inbox` and, only after an explicit later user reply, `gate approve <task-id> --snapshot <id> --source <reply>` with `AIDLC_FLEET_REVIEWER_TOKEN`. See [Coordination service](./coordination-service.md#multi-machine-loop-deployment) for bootstrap, fleet processes, and credentials.
137
- 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 it only when deliberately returning to a local run.
327
+ - The client covers task items, evidence, decisions, status, audited transitions, wrap lessons, and feature manifests through revision-checked remote mutations. It cannot approve gates with a lead token.
328
+ - A connected reviewer uses `gate inbox` and, only after an explicit later user reply, `gate approve <task-id> --snapshot <id> --source <reply>` with `AIDLC_FLEET_REVIEWER_TOKEN`.
329
+ - While `AIDLC_FLEET_URL` is set, local lifecycle, context, gate, assignment, and standalone loop commands reject use, so an unattended lead cannot mutate a second local authority. Unset it only when deliberately returning to a local run.
330
+
331
+ ### Options and project root
332
+
333
+ - Options may appear before or after positionals as `--name value` or `--name=value`. Unknown, duplicate, command-irrelevant, missing-value, and surplus positional arguments are rejected before state I/O.
334
+ - Boolean options (`--all`, `--include-archive`, `--require-stop`) take no value. A literal value starting with `--` needs the equals form.
335
+ - An explicit `--root <path>` wins and must contain `.agents/`. Otherwise the runtime walks upward to the nearest ancestor containing `.agents/aidlc/`; with no marker it fails without creating local state.
336
+ - Manual calls from a nested directory need an absolute or upward-relative script path. Runtime-generated actions always carry an absolute script path and an absolute `--root`.
138
337
 
139
- Installed lifecycle options may appear before or after positionals and accept both `--name value` and `--name=value`. Unknown, duplicate, command-irrelevant, missing-value, and surplus positional arguments are rejected before state I/O. Boolean options such as `--all`, `--include-archive`, and `--require-stop` do not accept values. When a literal value begins with `--`, use the equals form so it is not confused with a missing value.
338
+ ### Output envelope and exit codes
140
339
 
141
- An explicit `--root <path>` wins and must identify a directory containing `.agents/`. Without `--root`, the runtime walks upward from the current working directory and selects the nearest ancestor containing `.agents/aidlc/`. If no installed-workflow marker exists, the command fails without creating local state. Manual calls from a nested directory need an absolute or upward-relative script path so Node can locate the entry point. Runtime-generated actions always include both an absolute script path and an absolute `--root`, so they remain executable from any working directory.
340
+ Every `state.mjs` and `task-next.mjs` command prints one JSON envelope: `{ok: true, result, nextAction?}`.
142
341
 
143
- Every `state.mjs` and `task-next.mjs` command prints one JSON envelope: `{ok: true, result, nextAction?}`. `result` carries the command payload (a mutated command nests it as `{task, ...extra}`; a read returns the read object), and `nextAction` is present whenever the command is task-scoped. Task-less commands (`memory list|promote|retire`, `lesson rebuild|search`, `state migrate`, `task list|find`) return no `nextAction`. A success envelope may additionally carry `warnings: [{code, message, hint?}]` when the mutation persisted but a derived step failed afterwards — `LESSON_INDEX_STALE` (lesson-index rebuild) or `RENDER_FAILED` (workplan render); the mutation is committed and the exit code stays `0`, so callers follow the warning hint instead of retrying the mutation, while the explicit repair commands (`lesson rebuild`, `render.mjs`) and `state migrate` still fail loudly. Failures print a one-line `{ok: false, error: {message, hint?}}` on stderr — never a stack trace. Exit codes are typed: `0` success, `1` expected validation or gate error, `2` the continuation guard, `3` an unexpected crash. Callers must execute `run_phase` actions immediately; a successful mutation is not permission to stop. In build, the action includes `itemId`, `remainingItems`, and an item-focused context command while work remains, and every embedded command carries an explicit `--root` so it runs from any working directory.
342
+ - **`result`** carries the payload (a mutation nests it as `{task, ...extra}`; a read returns the read object).
343
+ - **`nextAction`** is present for every task-scoped command. Task-less commands (`memory list|promote|retire`, `lesson rebuild|search`, `state migrate`, `task list|find`) return none.
344
+ - **`warnings`** `[{code, message, hint?}]` may accompany a success when the mutation persisted but a derived step failed: `LESSON_INDEX_STALE` (lesson-index rebuild) or `RENDER_FAILED` (workplan render). The exit code stays `0`; follow the hint, do not retry. The repair commands (`lesson rebuild`, `render.mjs`) and `state migrate` still fail loudly.
345
+ - **Failures** print one line `{ok: false, error: {message, hint?}}` on stderr — never a stack trace.
346
+ - **Exit codes:** `0` success, `1` expected validation or gate error, `2` continuation guard, `3` unexpected crash.
347
+ - Execute `run_phase` actions immediately; a successful mutation is not permission to stop. In build the action includes `itemId`, `remainingItems`, and an item-focused context command while work remains; every embedded command carries an explicit `--root`.
144
348
 
145
- `task-next.mjs --require-stop` prints the current action plus a machine-readable `continuation` object in the stdout envelope — `{required, code, taskId, classification}` and, when work remains, `command`, `reason`, `itemId`, and `remainingItems` — and exits `2` when the classification is `run_phase`. The first stderr line is `CONTINUATION_REQUIRED: {json}` carrying the same task id, command, and reason (followed by an explicit "expected pause, not a failure" note); it is a local guard against a premature final response, and the caller must execute `continuation.command` instead of replying. It exits normally (`continuation.code = STOP_ALLOWED`) for a valid human gate, durable blocker, terminal outcome, or completion. The guard is detection at the package boundary: it cannot technically intercept a message a model host has already emitted, so hosts recover by running `task next <task-id>` in the next turn and executing its command. `task status ... --status blocked_on_user` fails instead of persisting when the current gate is not ready, and `gate-view.mjs` only renders tasks already in that validated status.
349
+ ### Continuation guard
146
350
 
147
- Human approval is a dedicated atomic operation. The displayed review steps map to stable `--gate` values: **Confirm requirements** → `G0_confirm`, **Approve plan** → `G1_review`, **Review implementation** → `G2_codereview`. Display labels are always English; task prose may follow the task language:
351
+ - `task-next.mjs --require-stop` prints the current action plus a `continuation` object — `{required, code, taskId, classification}` and, when work remains, `command`, `reason`, `itemId`, `remainingItems` — and exits `2` when the classification is `run_phase`.
352
+ - The first stderr line is `CONTINUATION_REQUIRED: {json}` with the same task id, command, and reason, followed by an explicit "expected pause, not a failure" note. The caller must execute `continuation.command` instead of replying.
353
+ - It exits normally (`continuation.code = STOP_ALLOWED`) for a valid human gate, durable blocker, terminal outcome, or completion.
354
+ - The guard detects at the package boundary and cannot intercept an already-emitted message; hosts recover by running `task next <task-id>` in the next turn and executing its command.
355
+ - `task status ... --status blocked_on_user` fails instead of persisting when the current gate is not ready; `gate-view.mjs` renders only tasks already in that validated status.
356
+
357
+ ### Gate approval
358
+
359
+ Human approval is a dedicated atomic operation. Review steps map to stable `--gate` values: **Confirm requirements** → `G0_confirm`, **Approve plan** → `G1_review`, **Review implementation** → `G2_codereview`. Display labels are always English; task prose may follow the task language.
148
360
 
149
361
  ```sh
150
362
  node .agents/aidlc/scripts/state.mjs gate approve <task-id> --gate <gate> --source "<explicit approval>"
151
363
  ```
152
364
 
153
- `--source` is audit provenance, not authentication or proof of consent. The host agent must invoke this command only in a later user turn that explicitly approves the gate currently presented.
365
+ `--source` is audit provenance, not authentication or proof of consent. Invoke it only in a later user turn that explicitly approves the gate currently presented.
366
+
367
+ ### Evidence, status, and transitions
154
368
 
155
- `evidence add` accepts `spec`, `test`, `lint`, `review`, and `diagnostic`; it rejects `approval`. An evidence `--area` must belong to the task's affected areas, and multi-area test or lint evidence must name its area. `task status` accepts `active`, `blocked_on_user`, and `paused` (`done` is not a status command; finish with `task transition --to done` or `task archive`), and rejects `blocked_on_user` at wrap, which has no human gate. Every route out of a validated `blocked_on_user` wait, including `paused`, requires audited `--reason` and `--source` metadata and appends diagnostic evidence; entering `paused` from `active` requires the same audited `--mode audited --reason --source` triple and appends a `Paused while active` diagnostic, while resuming `paused → active` needs no audit metadata. Repair bounds are machine-enforced: the third failed verify record per area, or the second failed review record, in the current build flips `nextAction` to `blocked` and adds a `REPAIR_BOUND` error to the Review implementation gate check. Normal phase advancement uses `gate approve`, and wrap completion uses `task transition --to done` or `task archive <task-id> --reason "<reason>" --source "<source>"`, which applies the same transition checks and appends an `Archive to done` diagnostic. The low-level transition escape hatch is intentionally noisy, records diagnostic evidence, still applies all transition checks, and requires audit metadata:
369
+ - **Evidence.** `evidence add` accepts `spec`, `test`, `lint`, `review`, and `diagnostic`; it rejects `approval`. `--area` must belong to the task's affected areas; multi-area test or lint evidence must name its area.
370
+ - **Status.** `task status` accepts `active`, `blocked_on_user`, and `paused` (`done` is not a status; finish with `task transition --to done` or `task archive`). It rejects `blocked_on_user` at wrap, which has no human gate.
371
+ - **Audited exits.** Every route out of a validated `blocked_on_user` wait, including `paused`, requires audited `--reason` and `--source` and appends diagnostic evidence. `active → paused` requires the same `--mode audited --reason --source` triple and appends a `Paused while active` diagnostic; `paused → active` needs no audit metadata.
372
+ - **Repair bounds.** The third failed verify record per area, or the second failed review record, in the current build flips `nextAction` to `blocked` and adds a `REPAIR_BOUND` error to the Review implementation gate check.
373
+ - **Advancing and finishing.** Phases advance with `gate approve`; wrap completes with `task transition --to done` or `task archive <task-id> --reason "<reason>" --source "<source>"`, which applies the same transition checks and appends an `Archive to done` diagnostic. Both record `finalCommit` (the checkout's `HEAD`, or `--final-commit <sha>`) on the task; `--final-commit` is rejected for any other target phase.
374
+ - **Commit tracking.** `baseCommit` (recorded by `task create` from `HEAD`, or `--base-commit <sha>`) and `finalCommit` are optional lowercase hex SHAs in the canonical task state, shared by `state.mjs` and the fleet `remote-state.mjs` and kept in the archive record. The core never runs git; outside a repository the fields stay unset. They let the dashboard rebuild a task's changes from history alone ([`ui` routes](#routes)).
375
+
376
+ The low-level transition escape hatch is intentionally noisy: it records diagnostic evidence, applies all transition checks, requires audit metadata, and rejects self-transitions:
156
377
 
157
378
  ```sh
158
379
  node .agents/aidlc/scripts/state.mjs task transition <task-id> --to <phase> --mode audited --reason "<reason>" --source "<source>"
159
380
  ```
160
381
 
161
- Self-transitions are rejected, and `task create` rejects an id that collides case-insensitively with an existing task or archive record. `task create` also fails while another unrelated task is actionable; its `--switch-from <ids>` acknowledgement still requires explicit user direction. `--feature <feature-id>` permits sibling tasks in an existing feature without abandoning them. `feature link` checks membership and task dependencies; `task item ... --depends-on <item-id,...> --owns <path,...>` adds item edges and an optional Git path scope. Fleet dispatch requires a nonempty path scope. Path scopes are normalized (trailing slashes stripped) and may name either a file or a directory; directory scopes cover every file beneath them. Missing and cyclic dependencies fail, and an item or feature task cannot finish before its prerequisites. After reopening the Approve plan step, all non-deferred execution items return to `todo`; prior Review implementation, verification, and review evidence cannot satisfy the new build boundary, and repair-bound counters reset with it.
382
+ ### Task creation, features, and item scopes
383
+
384
+ - **Creation.** `task create` rejects an id that collides case-insensitively with an existing task or archive record, and fails while another unrelated task is actionable; its `--switch-from <ids>` acknowledgement still requires explicit user direction. `--feature <feature-id>` permits sibling tasks in an existing feature without abandoning them.
385
+ - **Dependencies.** `feature link` checks membership and task dependencies; `task item ... --depends-on <item-id,...> --owns <path,...>` adds item edges and an optional Git path scope. Missing and cyclic dependencies fail; an item or feature task cannot finish before its prerequisites.
386
+ - **Path scopes.** Loop dispatch (local and fleet) requires a nonempty path scope. With `loop.mode` `local` or `fleet`, the Approve plan check fails with `PARTITION_SCOPE` for an open item without `--owns` and `PARTITION_OVERLAP` when two items that can run concurrently (no direct or transitive `--depends-on`) own overlapping paths; with the loop off both are warnings.
387
+ - **Overlap rules.** Per path segment: `src` overlaps `src/a.ts` but not `srcx`. Scopes are normalized (trailing slashes stripped), may name a file or a directory, and directory scopes cover every file beneath. The rendered workplan shows `owns: … · after: …` per item.
388
+ - **Reopening.** After reopening Approve plan, all non-deferred execution items return to `todo`; prior Review implementation, verification, and review evidence cannot satisfy the new build boundary, and repair-bound counters reset.
389
+
390
+ ### Atomic writes and archives
162
391
 
163
- State writes and generated workplans use symlink-checked atomic replacement. State-lock release is owner-token checked and never removes a replacement owner's lock. If a process stops after writing a terminal archive record but before committing the catalog, a retry replaces that orphan only when the persisted catalog still contains the same active task identity and does not reference an archive record; malformed, referenced, or identity-conflicting records fail closed.
392
+ - State writes and generated workplans use symlink-checked atomic replacement. State-lock release is owner-token checked and never removes a replacement owner's lock.
393
+ - A process that stops after writing a terminal archive record but before committing the catalog leaves an orphan; a retry replaces it only when the persisted catalog still holds the same active task identity and references no archive record. Malformed, referenced, or identity-conflicting records fail closed.
394
+
395
+ ### Memory promotion
164
396
 
165
397
  Promoting an agent-memory candidate requires traceable source records and an explicit approver:
166
398
 
@@ -168,4 +400,9 @@ Promoting an agent-memory candidate requires traceable source records and an exp
168
400
  node .agents/aidlc/scripts/state.mjs memory promote <memory-id> --summary "<summary>" --guidance "<guidance>" --source-task <task-id> --source-lesson <lesson-id> --approved-by "<human>"
169
401
  ```
170
402
 
171
- Use [Operating the workflow](./operating-workflow.md) for gates, approvals, handoffs, and task ownership.
403
+ ## Related
404
+
405
+ - [Operating the workflow](./operating-workflow.md) — gates, approvals, handoffs, and task ownership.
406
+ - [Configuration](./configuration.md) — `.agents/config.json`, `loop.*`, `mcp`, and adapter permissions.
407
+ - [Loop setup runbook](./loop-runbook.md) — step-by-step loop setup.
408
+ - [Troubleshooting](./troubleshooting.md) — error codes and recovery.