devlyn-cli 4.1.0 → 4.2.1

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 (201) hide show
  1. package/AGENTS.md +10 -94
  2. package/CLAUDE.md +7 -160
  3. package/LICENSE +21 -0
  4. package/README.md +68 -111
  5. package/bin/devlyn.js +265 -259
  6. package/bin/instruction-templates.json +43 -2
  7. package/bin/instructions.js +29 -8
  8. package/bin/skill-history.json +140 -0
  9. package/bin/skill-ownership.js +67 -0
  10. package/config/skills/_shared/adapters/claude.md +8 -85
  11. package/config/skills/_shared/adapters/codex.md +14 -34
  12. package/config/skills/_shared/adapters/omp.md +1 -11
  13. package/config/skills/_shared/codex-monitored.sh +4 -54
  14. package/config/skills/_shared/engine-doctor.sh +18 -58
  15. package/config/skills/_shared/engine-preflight.md +15 -47
  16. package/config/skills/_shared/expected-contract.py +242 -0
  17. package/config/skills/_shared/expected.schema.json +10 -95
  18. package/config/skills/_shared/invocation-receipt.py +26 -757
  19. package/config/skills/_shared/platform-support.py +37 -28
  20. package/config/skills/_shared/role-config.py +100 -421
  21. package/config/skills/_shared/runtime-principles.md +17 -93
  22. package/config/skills/_shared/task-complete.py +490 -285
  23. package/config/skills/_shared/task-completion.md +235 -0
  24. package/config/skills/devlyn-engines/SKILL.md +9 -11
  25. package/config/skills/devlyn-ideate/SKILL.md +57 -107
  26. package/config/skills/devlyn-ideate/references/elicitation.md +18 -99
  27. package/config/skills/devlyn-ideate/references/loop.md +110 -0
  28. package/config/skills/devlyn-ideate/references/package-format.md +128 -0
  29. package/config/skills/devlyn-ideate/scripts/acceptance.py +795 -0
  30. package/config/skills/devlyn-ideate/scripts/queue.py +1780 -0
  31. package/node_modules/@inquirer/ansi/LICENSE +22 -0
  32. package/node_modules/@inquirer/ansi/README.md +121 -0
  33. package/node_modules/@inquirer/ansi/dist/index.d.ts +14 -0
  34. package/node_modules/@inquirer/ansi/dist/index.js +21 -0
  35. package/node_modules/@inquirer/ansi/package.json +79 -0
  36. package/node_modules/@inquirer/checkbox/LICENSE +22 -0
  37. package/node_modules/@inquirer/checkbox/README.md +265 -0
  38. package/node_modules/@inquirer/checkbox/dist/index.d.ts +67 -0
  39. package/node_modules/@inquirer/checkbox/dist/index.js +210 -0
  40. package/node_modules/@inquirer/checkbox/package.json +93 -0
  41. package/node_modules/@inquirer/core/LICENSE +22 -0
  42. package/node_modules/@inquirer/core/README.md +424 -0
  43. package/node_modules/@inquirer/core/dist/index.d.ts +13 -0
  44. package/node_modules/@inquirer/core/dist/index.js +12 -0
  45. package/node_modules/@inquirer/core/dist/lib/Separator.d.ts +10 -0
  46. package/node_modules/@inquirer/core/dist/lib/Separator.js +21 -0
  47. package/node_modules/@inquirer/core/dist/lib/__probe/p1.d.ts +9 -0
  48. package/node_modules/@inquirer/core/dist/lib/__probe/p1.js +4 -0
  49. package/node_modules/@inquirer/core/dist/lib/__probe/p2.d.ts +9 -0
  50. package/node_modules/@inquirer/core/dist/lib/__probe/p2.js +3 -0
  51. package/node_modules/@inquirer/core/dist/lib/__probe/p3.d.ts +9 -0
  52. package/node_modules/@inquirer/core/dist/lib/__probe/p3.js +5 -0
  53. package/node_modules/@inquirer/core/dist/lib/create-prompt.d.ts +11 -0
  54. package/node_modules/@inquirer/core/dist/lib/create-prompt.js +185 -0
  55. package/node_modules/@inquirer/core/dist/lib/errors.d.ts +20 -0
  56. package/node_modules/@inquirer/core/dist/lib/errors.js +21 -0
  57. package/node_modules/@inquirer/core/dist/lib/hook-engine.d.ts +17 -0
  58. package/node_modules/@inquirer/core/dist/lib/hook-engine.js +109 -0
  59. package/node_modules/@inquirer/core/dist/lib/key.d.ts +15 -0
  60. package/node_modules/@inquirer/core/dist/lib/key.js +34 -0
  61. package/node_modules/@inquirer/core/dist/lib/make-theme.d.ts +3 -0
  62. package/node_modules/@inquirer/core/dist/lib/make-theme.js +33 -0
  63. package/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.d.ts +15 -0
  64. package/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js +121 -0
  65. package/node_modules/@inquirer/core/dist/lib/screen-manager.d.ts +14 -0
  66. package/node_modules/@inquirer/core/dist/lib/screen-manager.js +84 -0
  67. package/node_modules/@inquirer/core/dist/lib/theme.d.ts +166 -0
  68. package/node_modules/@inquirer/core/dist/lib/theme.js +29 -0
  69. package/node_modules/@inquirer/core/dist/lib/use-effect.d.ts +2 -0
  70. package/node_modules/@inquirer/core/dist/lib/use-effect.js +11 -0
  71. package/node_modules/@inquirer/core/dist/lib/use-keypress.d.ts +3 -0
  72. package/node_modules/@inquirer/core/dist/lib/use-keypress.js +20 -0
  73. package/node_modules/@inquirer/core/dist/lib/use-memo.d.ts +1 -0
  74. package/node_modules/@inquirer/core/dist/lib/use-memo.js +14 -0
  75. package/node_modules/@inquirer/core/dist/lib/use-prefix.d.ts +5 -0
  76. package/node_modules/@inquirer/core/dist/lib/use-prefix.js +35 -0
  77. package/node_modules/@inquirer/core/dist/lib/use-ref.d.ts +6 -0
  78. package/node_modules/@inquirer/core/dist/lib/use-ref.js +4 -0
  79. package/node_modules/@inquirer/core/dist/lib/use-state.d.ts +7 -0
  80. package/node_modules/@inquirer/core/dist/lib/use-state.js +28 -0
  81. package/node_modules/@inquirer/core/dist/lib/utils.d.ts +13 -0
  82. package/node_modules/@inquirer/core/dist/lib/utils.js +25 -0
  83. package/node_modules/@inquirer/core/package.json +98 -0
  84. package/node_modules/@inquirer/figures/LICENSE +22 -0
  85. package/node_modules/@inquirer/figures/dist/index.d.ts +275 -0
  86. package/node_modules/@inquirer/figures/dist/index.js +315 -0
  87. package/node_modules/@inquirer/figures/package.json +81 -0
  88. package/node_modules/@inquirer/select/LICENSE +22 -0
  89. package/node_modules/@inquirer/select/README.md +258 -0
  90. package/node_modules/@inquirer/select/dist/index.d.ts +42 -0
  91. package/node_modules/@inquirer/select/dist/index.js +191 -0
  92. package/node_modules/@inquirer/select/package.json +93 -0
  93. package/node_modules/@inquirer/type/LICENSE +22 -0
  94. package/node_modules/@inquirer/type/dist/index.d.ts +2 -0
  95. package/node_modules/@inquirer/type/dist/index.js +2 -0
  96. package/node_modules/@inquirer/type/dist/inquirer.d.ts +35 -0
  97. package/node_modules/@inquirer/type/dist/inquirer.js +1 -0
  98. package/node_modules/@inquirer/type/dist/utils.d.ts +45 -0
  99. package/node_modules/@inquirer/type/dist/utils.js +16 -0
  100. package/node_modules/@inquirer/type/package.json +88 -0
  101. package/node_modules/cli-width/LICENSE +13 -0
  102. package/node_modules/cli-width/README.md +71 -0
  103. package/node_modules/cli-width/index.d.ts +13 -0
  104. package/node_modules/cli-width/index.js +49 -0
  105. package/node_modules/cli-width/package.json +40 -0
  106. package/node_modules/fast-string-truncated-width/dist/index.d.ts +4 -0
  107. package/node_modules/fast-string-truncated-width/dist/index.js +111 -0
  108. package/node_modules/fast-string-truncated-width/dist/types.d.ts +19 -0
  109. package/node_modules/fast-string-truncated-width/dist/types.js +2 -0
  110. package/node_modules/fast-string-truncated-width/dist/utils.d.ts +4 -0
  111. package/node_modules/fast-string-truncated-width/dist/utils.js +20 -0
  112. package/node_modules/fast-string-truncated-width/license +21 -0
  113. package/node_modules/fast-string-truncated-width/package.json +35 -0
  114. package/node_modules/fast-string-truncated-width/readme.md +59 -0
  115. package/node_modules/fast-string-width/dist/index.d.ts +4 -0
  116. package/node_modules/fast-string-width/dist/index.js +14 -0
  117. package/node_modules/fast-string-width/license +21 -0
  118. package/node_modules/fast-string-width/package.json +34 -0
  119. package/node_modules/fast-string-width/readme.md +42 -0
  120. package/node_modules/fast-wrap-ansi/LICENSE +23 -0
  121. package/node_modules/fast-wrap-ansi/README.md +26 -0
  122. package/node_modules/fast-wrap-ansi/lib/main.d.ts +6 -0
  123. package/node_modules/fast-wrap-ansi/lib/main.js +218 -0
  124. package/node_modules/fast-wrap-ansi/package.json +51 -0
  125. package/node_modules/mute-stream/LICENSE +15 -0
  126. package/node_modules/mute-stream/README.md +68 -0
  127. package/node_modules/mute-stream/lib/index.js +142 -0
  128. package/node_modules/mute-stream/package.json +54 -0
  129. package/node_modules/signal-exit/LICENSE.txt +16 -0
  130. package/node_modules/signal-exit/README.md +74 -0
  131. package/node_modules/signal-exit/dist/cjs/browser.d.ts +12 -0
  132. package/node_modules/signal-exit/dist/cjs/browser.d.ts.map +1 -0
  133. package/node_modules/signal-exit/dist/cjs/browser.js +10 -0
  134. package/node_modules/signal-exit/dist/cjs/browser.js.map +1 -0
  135. package/node_modules/signal-exit/dist/cjs/index.d.ts +48 -0
  136. package/node_modules/signal-exit/dist/cjs/index.d.ts.map +1 -0
  137. package/node_modules/signal-exit/dist/cjs/index.js +279 -0
  138. package/node_modules/signal-exit/dist/cjs/index.js.map +1 -0
  139. package/node_modules/signal-exit/dist/cjs/package.json +3 -0
  140. package/node_modules/signal-exit/dist/cjs/signals.d.ts +29 -0
  141. package/node_modules/signal-exit/dist/cjs/signals.d.ts.map +1 -0
  142. package/node_modules/signal-exit/dist/cjs/signals.js +42 -0
  143. package/node_modules/signal-exit/dist/cjs/signals.js.map +1 -0
  144. package/node_modules/signal-exit/dist/mjs/browser.d.ts +12 -0
  145. package/node_modules/signal-exit/dist/mjs/browser.d.ts.map +1 -0
  146. package/node_modules/signal-exit/dist/mjs/browser.js +4 -0
  147. package/node_modules/signal-exit/dist/mjs/browser.js.map +1 -0
  148. package/node_modules/signal-exit/dist/mjs/index.d.ts +48 -0
  149. package/node_modules/signal-exit/dist/mjs/index.d.ts.map +1 -0
  150. package/node_modules/signal-exit/dist/mjs/index.js +275 -0
  151. package/node_modules/signal-exit/dist/mjs/index.js.map +1 -0
  152. package/node_modules/signal-exit/dist/mjs/package.json +3 -0
  153. package/node_modules/signal-exit/dist/mjs/signals.d.ts +29 -0
  154. package/node_modules/signal-exit/dist/mjs/signals.d.ts.map +1 -0
  155. package/node_modules/signal-exit/dist/mjs/signals.js +39 -0
  156. package/node_modules/signal-exit/dist/mjs/signals.js.map +1 -0
  157. package/node_modules/signal-exit/package.json +106 -0
  158. package/package.json +17 -4
  159. package/config/commit-conventions.md +0 -28
  160. package/config/skills/_shared/adapters/README.md +0 -74
  161. package/config/skills/_shared/adapters/grok.md +0 -100
  162. package/config/skills/_shared/archive_run.py +0 -969
  163. package/config/skills/_shared/codex-config.md +0 -81
  164. package/config/skills/_shared/collect-codex-findings.py +0 -505
  165. package/config/skills/_shared/finish-gate.py +0 -521
  166. package/config/skills/_shared/grok-anchor-guard.py +0 -78
  167. package/config/skills/_shared/judge-output-parser.py +0 -200
  168. package/config/skills/_shared/judge-role-evidence.py +0 -320
  169. package/config/skills/_shared/phase-prompt-render.py +0 -183
  170. package/config/skills/_shared/process-evidence.py +0 -926
  171. package/config/skills/_shared/resolve-bootstrap.py +0 -1410
  172. package/config/skills/_shared/resolve-stop-hook.py +0 -359
  173. package/config/skills/_shared/run-bounded.py +0 -58
  174. package/config/skills/_shared/spec-verify-check.py +0 -5083
  175. package/config/skills/_shared/state-phase-write.py +0 -5989
  176. package/config/skills/_shared/terminal-claim-check.py +0 -777
  177. package/config/skills/_shared/verify-merge-findings.py +0 -3528
  178. package/config/skills/devlyn-design-ui/SKILL.md +0 -650
  179. package/config/skills/devlyn-ideate/references/from-spec-mode.md +0 -61
  180. package/config/skills/devlyn-ideate/references/project-mode.md +0 -80
  181. package/config/skills/devlyn-ideate/references/spec-template.md +0 -121
  182. package/config/skills/devlyn-ideate/references/templates/decision.md +0 -48
  183. package/config/skills/devlyn-ideate/references/templates/roadmap.md +0 -50
  184. package/config/skills/devlyn-ideate/references/templates/vision.md +0 -44
  185. package/config/skills/devlyn-queue/SKILL.md +0 -66
  186. package/config/skills/devlyn-queue/scripts/append.py +0 -94
  187. package/config/skills/devlyn-resolve/SKILL.md +0 -379
  188. package/config/skills/devlyn-resolve/references/free-form-mode.md +0 -71
  189. package/config/skills/devlyn-resolve/references/outer-loop.md +0 -23
  190. package/config/skills/devlyn-resolve/references/phases/build-gate.md +0 -75
  191. package/config/skills/devlyn-resolve/references/phases/cleanup.md +0 -33
  192. package/config/skills/devlyn-resolve/references/phases/implement.md +0 -44
  193. package/config/skills/devlyn-resolve/references/phases/plan.md +0 -39
  194. package/config/skills/devlyn-resolve/references/phases/probe-derive.md +0 -261
  195. package/config/skills/devlyn-resolve/references/phases/surface-close.md +0 -34
  196. package/config/skills/devlyn-resolve/references/phases/verify.md +0 -310
  197. package/config/skills/devlyn-resolve/references/state-schema.md +0 -152
  198. package/config/skills/devlyn-resolve/references/task-completion.md +0 -160
  199. package/config/templates/prompt-templates.md +0 -71
  200. package/config/templates/template-feature.spec.md +0 -255
  201. package/config/templates/template-product-spec.md +0 -680
@@ -0,0 +1,235 @@
1
+ # Outer-owner task completion
2
+
3
+ Completion belongs to the outer task owner after source acceptance; it does not
4
+ change product verdicts or worker isolation. Direct work edits the current
5
+ checkout, then delivers each completed, verified request with attributable
6
+ changes. Finish the whole request, including steering received before acceptance;
7
+ internal subtasks, messages and conversation end are not delivery boundaries.
8
+ Honor explicit batching or delivery holds; otherwise deliver completed requests
9
+ without waiting for later requests.
10
+
11
+ Without a delivery instruction, use project policy below, default `auto`. A bare
12
+ commit request uses `--local-only`, a PR request `--mode pr`, and a merge request
13
+ `--mode auto`. Local-only/no-push restrictions prevent publication; no-commit or
14
+ just-edit instructions skip delivery. Existing session-wide restrictions remain
15
+ in force until changed. Read-only work, unchanged work and incidental generated
16
+ files do not trigger delivery. An ideate drain delivers every task.
17
+
18
+ ## Concurrent writers
19
+
20
+ When other sessions or agents are known to write this checkout (the user says
21
+ so, or you see them), allocate a worktree below before editing. Changes present
22
+ at the start are the user's work in progress: preserve them, and continue unless
23
+ their ownership or the task's dependence on them is unclear. Re-read a file
24
+ before overwriting it, and check `git status` and the diff at verification and
25
+ commit points. On changes you cannot explain, stop writing to the shared
26
+ checkout and ask whether to continue there or isolate. With no one to ask, move
27
+ only your own edits, and only when the task's context can be rebuilt in the
28
+ worktree; otherwise leave the checkout as it is and report the task blocked.
29
+ Isolation changes the work location, not delivery scope. Allocate for the
30
+ resolved delivery policy and reuse that worktree when suitable. Isolation
31
+ without delivery uses `--local-base`. A local receipt remains local; later
32
+ publication requires a fresh publication allocation, candidate and acceptance.
33
+
34
+ ## Allocate for delivery or isolation
35
+
36
+ Use the caller's DEVLYN_SHARED_DIR. When this reference is opened
37
+ directly, bind it to this reference's reader-supplied containing
38
+ directory, resolving directory symlinks first. Missing source identity is
39
+ BLOCKED:skill-source-unresolved; a missing task-complete.py is
40
+ BLOCKED:shared-dir-unresolved. Never select another installation.
41
+
42
+ For direct delivery, run the bound task-complete.py after completing the request's
43
+ edits and checks, before committing the delivery candidate. Allocate before
44
+ editing when concurrency requires isolation; if isolation is unavailable, do
45
+ not write to the shared checkout. Queue drains retain their allocation order.
46
+
47
+ ```sh
48
+ python3 "$DEVLYN_SHARED_DIR/task-complete.py" allocate --repo . \
49
+ --task '<task identity>' --branch '<absent task branch>' \
50
+ --worktree '<absent path>' --repository '<owner/repo>' --remote origin --base main
51
+ ```
52
+
53
+ Every delivery allocation owns a linked worktree; `--worktree` is required.
54
+ A publication allocation normally starts at the exact fetched remote base,
55
+ independent of the anchor's branch or dirty state, and leaves the anchor's
56
+ HEAD, index and files untouched. For a commit request, local-only work or
57
+ isolation without publication, use `--local-base` with the exact current HEAD
58
+ and omit `--repository`/`--remote`. Nothing is fetched or pushed; complete with
59
+ `--local-only` only when committing is allowed.
60
+
61
+ When delivery is implicit and no GitHub origin is configured, use the existing
62
+ local-only route and report `LOCAL_ONLY`, the commit and why no PR/merge occurred.
63
+ An explicit PR/merge request remains blocked. Authentication, network and
64
+ configuration failures are not grounds for this fallback.
65
+
66
+ After local completion or confirmed PR merge, reconcile the original checkout
67
+ only when its branch and changes remain understood and can be preserved.
68
+ After remote delivery, fetch first. If the branch can fast-forward to the
69
+ delivered result, recheck the copied edits' current ownership and contents,
70
+ then remove them: `git restore --source=HEAD --staged --worktree -- <paths>`
71
+ for tracked paths holding only your edits, and delete copied untracked files.
72
+ Then use `git merge --ff-only <task branch>` for local delivery, or
73
+ `git merge --ff-only <remote>/<base>` on the base branch after remote delivery;
74
+ a drain's `Bring into` command is its own. Once a local delivery is reconciled,
75
+ remove its worktree and task branch (`git worktree remove <worktree>`,
76
+ `git branch -d <task branch>`). Do not switch branches, create a reconciliation
77
+ merge commit or discard WIP to force this step. If reconciliation is unsafe,
78
+ retain and report the edits, delivered result and remaining bring-in action.
79
+
80
+ Save the returned receipt path under the common Gitdir. `reconciled` reports earlier accepted,
81
+ PR-delivered tasks whose merged resources were cleaned or retained; it is
82
+ informational, so never resume or release a receipt you do not own. Existing
83
+ branches/trees cannot be adopted, even when their names look generated. Nor
84
+ can a receipt that never reached `allocation: owned`: remove its worktree and
85
+ branch if present, delete its receipt directory, then allocate again.
86
+ Unreceipted tasks remain owner-managed.
87
+
88
+ Copy attributable task edits into the allocated worktree as a patch, never a
89
+ stash. Establish attribution from the pre-edit contents and starting Git state,
90
+ including staged, unstaged and untracked work. A path-scoped
91
+ `git diff --binary HEAD` (after `git add -N` for new files), applied with
92
+ `git -C <worktree> apply --3way`, is suitable only when every included change
93
+ belongs to this task and its prerequisites exist in the candidate baseline. Otherwise construct the task-only
94
+ delta; if attribution or independence from unshipped work is unclear, preserve
95
+ the checkout and report delivery blocked.
96
+
97
+ Review the resulting candidate diff and verify that candidate. Reuse prior
98
+ check evidence only when the checked source and relevant execution inputs are
99
+ unchanged; changed bases, conflict resolutions or other relevant differences
100
+ require the affected checks again.
101
+
102
+ Keep the original edits through pending or failed delivery; only reconciliation
103
+ removes them. Preserve all other work and report anything left behind.
104
+
105
+ Allocation also returns a receipt-owned `scratch` directory. Put disposable
106
+ build intermediates there (for example, set
107
+ `CARGO_TARGET_DIR` to `<scratch>/target`). Keep source checkouts, Git data,
108
+ lockfiles, reports and restart evidence outside scratch. Do not create unowned
109
+ temporary build trees or preserve them by copying them into evidence custody.
110
+ Prefer `TemporaryDirectory`/`finally` for short-lived test fixtures.
111
+
112
+ After waiting for task writers, `complete --writers-stopped` empties this
113
+ scratch on delivery returns, including local-only and pending-PR routes. To
114
+ release build caches when parking or after a failed run, use:
115
+
116
+ ```sh
117
+ python3 "$DEVLYN_SHARED_DIR/task-complete.py" clean-scratch \
118
+ --receipt '<returned receipt.json>' --writers-stopped
119
+ ```
120
+
121
+ This empties only the prospectively owned scratch, preserves its directory
122
+ identity for interrupted cleanup and later builds, checks live users and reports
123
+ the logical byte count separately from actual free disk space. It does not depend on a product PASS or rewrite that verdict.
124
+ Unknown historical roots, source/recovery data, shared caches and terminal
125
+ history are never adopted or swept. A refused cleanup does not block source
126
+ delivery; it stays visible in the handoff with its receipt and retry command
127
+ (`CLEANUP_PENDING` after delivered source). No task is described as cleaned
128
+ while owned disposable files remain. On resumption, finish any pending scratch
129
+ cleanup before allocating more temporary storage; the next allocation also
130
+ retries it for completed deliveries with released writers. Rebuild from retained
131
+ inputs when needed; cleanup is not an instruction to restart parked work.
132
+
133
+ ## Accept a scoped commit
134
+
135
+ In the allocated worktree, finish the candidate's decisive checks and diff
136
+ review, then stage and commit only accepted task changes. The helper never
137
+ stages product files. Write a
138
+ root acceptance file in the checkout (usually ignored `.devlyn/acceptance.json`):
139
+
140
+ ```json
141
+ {"kind":"direct","task":"<task identity>","source_sha":"<full commit>","checks":[{"command":"<actual check>","evidence":".devlyn/checks.log"}]}
142
+ ```
143
+
144
+ The owner accepts these checks; the helper preserves evidence bytes and does
145
+ not independently prove the assertions. Acceptance binds exact source and
146
+ evidence before publication. Direct `complete` binds acceptance itself; no
147
+ separate `accept` call is needed.
148
+
149
+ Changed accepted source or evidence requires a new accepted task, never implicit
150
+ descendant approval. Resume an existing receipt only for its unchanged candidate.
151
+ After merge, implement follow-ups from the updated base. An additive follow-up
152
+ depending on an open PR waits for that predecessor to merge.
153
+
154
+ If a correction invalidates an open candidate, run `complete --mode pr` against
155
+ its unchanged receipt, with its task tree clean, to cancel owned auto-merge, then
156
+ reobserve the PR. If it
157
+ remains open, close it as superseded and retain its receipt and custody; do not
158
+ resume its delivery. Allocate a replacement from the current remote base,
159
+ include only the still-needed task changes and correction, and verify and
160
+ accept it anew. If the predecessor has merged, make a new follow-up instead.
161
+
162
+ Queue drains follow ideate's loop protocol
163
+ (`../devlyn-ideate/references/loop.md`): its evidence-derived `loop` result is
164
+ bound with `accept` before the queue-only terminal commit is attached with
165
+ `attach`, and dependent local tasks allocate from the accepted predecessor's
166
+ source. Failed results keep custody and a recovery ref but are never published.
167
+
168
+ ## Deliver and resume
169
+
170
+ Wait for your children, stop your dev servers and task writers, then leave the
171
+ task tree. Make the FIRST completion call from outside it with the installed
172
+ helper and `--writers-stopped`; this releases the tree for cleanup after merge:
173
+
174
+ ```sh
175
+ python3 "$DEVLYN_SHARED_DIR/task-complete.py" complete \
176
+ --receipt '<returned receipt.json>' \
177
+ --acceptance '<task worktree>/.devlyn/acceptance.json' --writers-stopped
178
+ ```
179
+
180
+ Project policy is `git config --local devlyn.completionMode auto|pr`; absent means
181
+ `auto`. Invalid local values fail before external effects, even with an override.
182
+ Use `complete --mode auto|pr` for one task, or `--local-only`/`--no-push` to honor
183
+ the user's delivery restriction. These per-task choices persist in the receipt; `--local-only` is refused once the task ref is pushed.
184
+
185
+ `pr` pushes the exact accepted task ref and creates/reuses its exact repository,
186
+ head and base PR. While OPEN, it cancels owned auto-merge, reports `PR` with its URL
187
+ and retains the checkout. Once MERGED by any method, either mode cleans released
188
+ resources in that call, on resume or at the next allocation. Default `auto` also requests
189
+ `gh pr merge --auto --merge --match-head-commit <accepted SHA>`. Repository
190
+ checks/reviews and merge policy remain authoritative: no admin bypass, strategy
191
+ fallback or repository setting changes. When the repository disallows merge
192
+ commits or refuses the request, delivery reports `PR` with `merge_refused` and
193
+ the PR waits for a person. Command success alone never proves merge.
194
+
195
+ `PENDING` retains the workspace and reports a receipt-based resume command.
196
+ `BLOCKED` names the cause and retry action; repair that condition before retrying.
197
+ Resume reobserves Git/PR state under a per-receipt lock, reuses the original
198
+ acceptance and performs only missing eligible effects.
199
+
200
+ Verification and delivery obey the session's actual permissions. When an
201
+ operation needs unavailable approval, finish permitted work, preserve the edits
202
+ and evidence, and report that operation and its retry action. Before allocation,
203
+ identify the original checkout and outstanding operation; after allocation,
204
+ include the receipt-based resume command. Headless execution neither waives
205
+ permissions nor silently changes delivery policy.
206
+
207
+ Report verification, delivery and checkout reconciliation separately. A delivery
208
+ error does not rewrite an accepted product result; unperformed verification
209
+ must never be reported as accepted.
210
+
211
+ ## Yield and retain recoverability
212
+
213
+ Cleanup requires actual matching MERGED evidence; linked-tree removal also
214
+ requires the owner's recorded release. OS observation supplements it; neither the receipt
215
+ nor a scan guarantees exclusion of future writers. Processes with cwd or open
216
+ files inside the tree, inaccessible process state (on Linux, other users'
217
+ processes unless run as root), caller cwd inside the tree, dirty/untracked files,
218
+ a nested repository or worktree, or changed refs/Gitdir/registration retain
219
+ affected resources. Use `git worktree lock` to keep a tree.
220
+ On native Windows, locking and file durability are supported, but the helper cannot prove writer cessation and reports `writer observation unsupported on this platform; retain workspace`. Even `--writers-stopped` cannot authorize deletion without that observation: retain the workspace, its task refs and external receipt/custody, report delivery separately, and preserve the receipt-based resume command. A merged delivery therefore reports `CLEANUP_PENDING` (delivery `COMPLETE`) with `workspace_cleanup` naming the reason and resume. Do not kill unknown processes or force worktree removal to make completion pass.
221
+
222
+ The receipt directory holds byte-verified `custody/`, `manifest.json` and a guarded
223
+ `refs/devlyn/completed/<id>` recovery ref. Check evidence is copied there
224
+ before publication; removal rechecks it, the recovery ref and the merge commit on base.
225
+ Ignored build output and other ignored files are disposable under native
226
+ non-force worktree removal. The tree's `.devlyn/` files are byte/mode-verified
227
+ and preserved as `<receipt dir>/records/.devlyn`; non-regular files or symlinks
228
+ there retain the tree. Partial/corrupt custody or records retain it for repair.
229
+
230
+ Legacy in-place receipts retire refs only once their task branch is no longer
231
+ checked out; their checkout is never modified. Local ref deletion is guarded by
232
+ the expected SHA; remote deletion uses an exact force-with-lease solely as
233
+ compare-and-delete, never for product publication. A changed remote branch is
234
+ retained. Retry uses the external receipt/evidence after removal. Recovery
235
+ refs/evidence have no automatic expiry.
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: devlyn-engines
3
- description: Show and pin engine roles for the devlyn pipeline (executor / pair judge). Reads and writes machine-local .devlyn/engines.json with fail-closed validation. Use when the user asks which models are configured, wants to force a specific model for pipeline work ("수동모드", "engine 고정", "use codex to implement"), or wants to clear pins back to auto-detection.
3
+ description: Show and pin the engine that executes devlyn implementation work. Reads and writes machine-local .devlyn/engines.json with fail-closed validation. Use when the user asks which engine is configured, wants to force a specific engine for implementation ("수동모드", "engine 고정", "use codex to implement"), or wants to clear the pin back to the default.
4
4
  ---
5
5
 
6
- Utility front-end for the role-resolution contract in `_shared/engine-preflight.md#role-resolution`. It adds no semantics of its own: everything it writes is exactly what `/devlyn-resolve` PHASE 0 reads.
6
+ Utility front-end for the executor contract in `_shared/engine-preflight.md`. It adds no semantics of its own.
7
7
 
8
8
  <args>
9
9
  $ARGUMENTS
@@ -48,18 +48,16 @@ with the failed path. Never search another installation.
48
48
  Verify DEVLYN_SHARED_DIR/role-config.py and DEVLYN_SHARED_DIR/engine-doctor.sh before their respective commands. In omp, use `printf '%s\n' skill://devlyn-engines`.
49
49
  </runtime_paths>
50
50
 
51
- ## No args — status + how to choose
51
+ ## No args — status
52
52
 
53
- 1. Run `python3 "$DEVLYN_SHARED_DIR/role-config.py" --workdir "$PWD" --default-engine <orchestrator-supported-default>` and print each resolved role's engine, requested model/effort, source and channel. Null model/effort means inherited/unresolved, not an attested identity. Show unavailable pins and requested priority even when no OTHER is available; status does not authorize dispatch. A current run can instead be inspected with `--state .devlyn/pipeline.state.json`; do not reread config as though it changed the active run. Show returned observations with their evidence basis; effective effort remains unknown when only argv is bound.
54
- 2. Run `bash "$DEVLYN_SHARED_DIR/engine-doctor.sh"` and show its availability/eligibility table. This does not prove authentication or model fitness.
53
+ 1. Run `python3 "$DEVLYN_SHARED_DIR/role-config.py" --workdir "$PWD" --default-engine <this CLI's engine>` and print the executor's engine, source (`engines.json` pin or `default`) and availability. `inactive` lists keys earlier releases wrote for retired pipeline roles: they select nothing, and `clear` removes them. CLI presence is not authentication.
54
+ 2. Run `bash "$DEVLYN_SHARED_DIR/engine-doctor.sh"` and show its availability/eligibility table.
55
55
  3. Show the subcommands below. Status never launches a model.
56
56
 
57
57
  ## Subcommands
58
58
 
59
- - `executor <name>` — pin the legacy executor; optional worker/primary profiles take their documented precedence. PLAN is orchestrator-fixed and never follows the pin. Refuse names with no `_shared/adapters/<name>.md`, or whose adapter's `## Role eligibility` section declares `executor: no` (judge-only backends), listing the valid names either way. If the engine's CLI is not currently available, still write the pin but warn: pins are promises — the run will stop with `BLOCKED:<name>-unavailable` until it is installed.
60
- - `pair <name>[,<name>...]` — set `pair_judge_priority` (ordered; first adapter-valid, pair-judge-eligible, non-primary, available entry wins at VERIFY/risk-probe time). Refuse names with no `_shared/adapters/<name>.md`, or whose adapter declares `pair_judge: no`.
61
- - `role <worker|primary_judge|pair_judge> <JSON object>` — write one atomic role entry, e.g. `{"engine":"codex","model":"gpt-6-astra","effort":"high"}`. Invoke `python3 "$DEVLYN_SHARED_DIR/role-config.py" --workdir "$PWD" --default-engine <orchestrator-supported-default> --set-role <role> --value '<JSON object>'` using structured argv, never shell interpolation of user text. Unknown fields/types and ineligible roles fail without changing prior bytes.
62
- - `role <name> clear` — same command with `--value clear` removes only that override.
63
- - `clear` — invoke the helper with `--set-role clear` to remove legacy and role pins; preserve unrelated keys and delete an empty file.
59
+ - `executor <name>` — run the status command with `--set-executor <name>`. It refuses a name with no `_shared/adapters/<name>.md`, or whose adapter declares `executor: no`, and lists the valid names. An engine whose CLI is not available is still pinned, with a warning: pins are promises, and dispatch stops with `BLOCKED:<name>-unavailable` until it is installed.
60
+ - `clear` — run the status command with `--clear`: it removes the executor pin and the inactive keys, preserves unrelated keys, and deletes an empty file.
61
+ - `pair` and `role` were removed with the retired pipeline roles: say so and change nothing.
64
62
 
65
- Writes preserve unrelated top-level keys already in the file; unknown fields inside roles are errors. After every change, re-print the resolved role table. Never modify anything outside `.devlyn/engines.json`, and never launch a pipeline from this skill.
63
+ Pass the engine name as one structured argument, never by shell interpolation of user text. After every change, re-print the status. Never modify anything outside `.devlyn/engines.json`.
@@ -1,33 +1,21 @@
1
1
  ---
2
2
  name: devlyn-ideate
3
- description: Extract a verifiable spec from a user's idea by driving the conversation with focused questions. Output is a single-feature `spec.md` + `spec.expected.json` that `/devlyn-resolve --spec` consumes directly. Use when the user has an idea but not a spec, or wants AI to elicit the missing engineering context. Modes — default (single spec, AI drives Q&A), `--quick` (assume-and-confirm from one-line goal), `--from-spec <path>` (normalize external spec), `--project` (plan.md index + N specs). Optional in the pipeline — `/devlyn-resolve` works standalone via free-form mode for users who skip ideate.
3
+ description: Loop designer and intent queue. Turns an intent or a document into a validated loop package (a meta-prompt plus self-contained task contracts), queues its tasks, reports queue status, and drains the queue serially with evidence-derived acceptance, recovery and delivery. Operations — plan, add, status, drain; a bare intent is planned and, when the request authorizes implementation, continues through add and drain; no arguments shows status. Use when the user wants an idea, goal or document planned into tasks, wants to stack work ("queue this", "큐에 넣어줘"), asks what is queued, or wants unattended execution ("drain the queue", "큐 드레인 시작", "밤새 돌려줘").
4
4
  ---
5
5
 
6
- Spec-elicitation surface for users who have ideas but not engineering specifications. AI drives the conversation with focused questions until a structurally-valid, verifiable spec exists. Output consumed directly by `/devlyn-resolve --spec`.
6
+ Ideate owns planning and durable serial execution. Each task runs under the installed methodology, the CLAUDE.md/AGENTS.md instruction block; ideate adds no phase graph, reviewer quota, engine router or restart cycle.
7
7
 
8
- <elicit_config>
8
+ <ideate_args>
9
9
  $ARGUMENTS
10
- </elicit_config>
11
-
12
- <orchestrator_context>
13
- This skill is OPTIONAL. `/devlyn-resolve` is standalone-capable: free-form mode handles trivial/medium tasks without a spec, `--spec` mode accepts handwritten specs from any source. Use ideate when the user wants AI to do the elicitation work.
14
- </orchestrator_context>
15
-
16
- <elicitation_contract>
17
- The user does not know context engineering. They will under-specify and over-assume. AI's job is to ask focused, specific questions that surface the missing engineering decisions.
18
-
19
- 1. Ask one or two questions per turn, not more. Multi-question lists overwhelm and produce shallow answers.
20
- 2. Questions are concrete and decision-grade — what is the input, what is the expected output, what command verifies success, what files are out of scope.
21
- 3. Do not ask design preferences the user clearly does not have. Infer the simplest reasonable default and confirm in one line.
22
- 4. Stop when the spec passes structural lint AND the user explicitly confirms or 8 turns have elapsed (whichever comes first). Eight turns is a hard ceiling — beyond that, the spec is either ready or the task is too large for ideate.
23
- 5. The output is the spec, not a transcript. Do not include the conversation in the saved files.
24
- </elicitation_contract>
10
+ </ideate_args>
25
11
 
26
12
  <harness_principles>
27
- Read `_shared/runtime-principles.md` (Subtractive-first / Goal-locked / Evidence-over-claim). The principles bind the spec content as well as your conversation. A spec that says "for future flexibility" is a Subtractive-first violation. A spec that asks for `try { ... } catch { return null }` is a No-workaround violation. AI flags these in elicitation, not after `/devlyn-resolve` has built them.
13
+ `_shared/runtime-principles.md`, mirrored in the installed instruction block (read the file only when no block is loaded), binds package content as well as the conversation: a requirement "for future flexibility" violates Subtractive-first, and acceptance that permits a silent fallback violates No-workaround. Flag these while planning, not after execution.
28
14
  </harness_principles>
29
15
 
30
16
  <runtime_paths>
17
+ Before any operation, establish the bindings below.
18
+
31
19
  Resolve bundled resources from the SKILL.md loaded for this invocation.
32
20
 
33
21
  Reader-rendered directory hint:
@@ -61,116 +49,78 @@ written as _shared/... use this binding. Verify the directory and each
61
49
  required resource before use; failure is BLOCKED:shared-dir-unresolved
62
50
  with the failed path. Never search another installation.
63
51
 
64
- Verify DEVLYN_SHARED_DIR/spec-verify-check.py before validation. Use `python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py"` for spec validation commands after binding the path in that shell. In omp, use `printf '%s\n' skill://devlyn-ideate`.
52
+ Verify DEVLYN_SKILL_DIR/scripts/queue.py before running it. In omp, use `printf '%s\n' skill://devlyn-ideate`.
65
53
  </runtime_paths>
66
54
 
67
- <engine_routing>
68
- Default engine: Claude. The per-engine adapter from `_shared/adapters/<engine>.md` is prepended to the elicitation prompt so the model honors its own official prompt-engineering guidance during the Q&A.
69
- </engine_routing>
70
-
71
- <modes>
72
- Four modes, selected by flag:
73
-
74
- 1. **Default** (no flag) — single-spec elicitation. AI asks questions in-conversation until lint passes. Output: `<spec-dir>/<id>-<slug>/spec.md` + `<spec-dir>/<id>-<slug>/spec.expected.json`. Default spec dir: `docs/specs/` (configurable via `--spec-dir <path>`).
75
- 2. **`--quick`** — one-line goal, AI synthesizes a spec with explicit assumptions block, asks the user to confirm or correct in a single turn. Use when the user wants speed over thoroughness.
76
- 3. **`--from-spec <path>`** — external spec exists. AI lints it for the canonical structure, normalizes section names, generates a missing `spec.expected.json` if absent, fixes minor schema issues, and stops. Does NOT reshape Requirements / Out-of-Scope content; structural changes only.
77
- 4. **`--project`** — multi-feature project. AI elicits a project description, decomposes it into 3-7 feature specs, writes `<spec-dir>/plan.md` (the index) and one `<spec-dir>/<id>/spec.md` + `<spec-dir>/<id>/spec.expected.json` per feature. See `references/project-mode.md`.
55
+ ## Operations
78
56
 
79
- `--spec-dir <path>` overrides the default output directory. `--engine <model>` selects the adapter.
80
- </modes>
57
+ | Invocation | Behavior |
58
+ |---|---|
59
+ | `plan <intent or absolute document path>` | Inspect, elicit what is necessary and write a validated loop package. Does not enqueue or execute. |
60
+ | `add <intent or absolute package path>` | Plan when necessary, then capture the package and queue its tasks in dependency order. Does not execute. |
61
+ | `status` | Reconciled pending, active, accepted and failed counts; the next runnable task; delivery and recovery blockers. |
62
+ | `drain` | Resume or drain the queue serially under existing execution authorization. |
63
+ | Bare intent | Plan; when the request authorizes implementation, continue through add and drain without reconfirmation. |
64
+ | No arguments | Status. |
81
65
 
82
- <spec_kind_escape_hatch>
83
- The spec carries `spec.kind ∈ {feature, spike, prototype}` in its frontmatter. The kind changes downstream behavior:
66
+ Two controls only: `--autonomous` applies the autonomous policy to plan or add (drain always applies it), and `--local-only` keeps a drain's delivery local (`--no-push` is equivalent). A delivery restriction already established for a loop persists. Engine selection and pins stay project and host settings (`/devlyn-engines`).
84
67
 
85
- - **feature** — production-quality implementation expected. `/devlyn-resolve --spec` runs the full pipeline (PLAN → IMPLEMENT → BUILD_GATE → CLEANUP → VERIFY).
86
- - **spike** — exploratory work; deliverable is learning, evidence, or a disposable demo. `/devlyn-resolve --spec` proceeds but VERIFY's quality bar is relaxed for code that the spike says is throwaway.
87
- - **prototype** — between feature and spike. Production-shape but not production-grade. CLEANUP runs; VERIFY's quality bar is stricter than spike, looser than feature.
68
+ A removed flag stops with its instruction and selects no other behavior.
88
69
 
89
- The user picks the kind during elicitation. Default = feature when not specified. `--quick` infers from the goal text (verbs like "explore", "investigate", "spike" → spike; "implement", "ship", "add" → feature).
90
- </spec_kind_escape_hatch>
70
+ | Flag | Instruction |
71
+ |---|---|
72
+ | `--quick` | Removed: use `plan <intent>`, adding `--autonomous` to plan without questions. |
73
+ | `--from-spec <path>` | Removed: use `plan <absolute path>`; the document stays unchanged as the input contract. |
74
+ | `--project` | Removed: every plan is a loop package with as many tasks as the intent needs. |
75
+ | `--spec-dir`, `--spec-id`, `--in-place` | Removed: packages live at `docs/specs/<loop-id>/` with generated IDs, and input documents are never rewritten. |
76
+ | `--engine` | Removed: drain uses the configured executor; pin it with `/devlyn-engines executor <name>`. |
91
77
 
92
- ## PHASE 0: PARSE + ROUTE
78
+ ## Question policy
93
79
 
94
- 1. Parse flags from `<elicit_config>`:
95
- - `--quick`
96
- - `--from-spec <path>`
97
- - `--project`
98
- - `--spec-dir <path>` (default `docs/specs/`)
99
- - `--engine MODE` (default `claude`)
100
- - `--spec-id <id>` — optional explicit id; auto-generated when absent.
80
+ > Inspect available project facts before asking. Ask only when the unresolved answer changes authorized behavior, scope, data semantics, acceptance or delivery. State the recommended answer and its consequence. Ask the smallest useful question. Stop eliciting when the contract is executable and verifiable; no turn target or mandatory confirmation applies. Existing authorization remains effective.
101
81
 
102
- 2. Engine pre-flight: `_shared/engine-preflight.md`.
82
+ ## Autonomous policy
103
83
 
104
- 3. Mode dispatch:
105
- - default → PHASE 1.
106
- - `--quick` → PHASE 1Q (single turn assume-and-confirm).
107
- - `--from-spec` → PHASE 1F (lint + normalize external).
108
- - `--project` → PHASE 1P (project decomposition).
84
+ > For ordinary details the intent leaves open within authorized scope, follow established project conventions, otherwise the narrowest literal or conventional reading consistent with the request; these defaults may be user-visible but must be low-consequence and reversible. Record each choice and reason once. Material ambiguity means competing readings with materially different intended outcomes, unresolved persistent data or state semantics, or public surface beyond the request; stop affected work as needs-review with a concrete question. Independent authorized work may continue. Never omit requested work or weaken acceptance to obtain completion.
109
85
 
110
- ## PHASE 1: ELICITATION (default mode)
86
+ ## plan
111
87
 
112
- Prompt body: `references/elicitation.md`. Adapter prepended.
88
+ 1. Inspect, then elicit, per [elicitation.md](references/elicitation.md). A document argument is the input contract: carry each substantive requirement into a task without weakening it, cite the document in `## Intent`, and never modify it.
89
+ 2. Write `docs/specs/<loop-id>/meta.md` and each task's `spec.md` and `spec.expected.json` per [package-format.md](references/package-format.md). In the manifest, `base_ref` is the delivery branch and `base_sha` the exact commit the loop builds on; `delivery` is `local-only` when the user restricted delivery or, recorded as an assumption, when `origin` does not name one GitHub repository; `pr` when the user asked to stop at the PR; `auto` when the user asked to merge, even under a `pr` project policy; else the project's `git config --local devlyn.completionMode` (absent means `auto`). An explicit PR or merge request whose `origin` does not name one GitHub repository stops planning with that question. `## Execution policy` quotes the autonomous policy, which binds every task's executor.
90
+ 3. Run `python3 "$DEVLYN_SKILL_DIR/scripts/queue.py" check '<absolute meta.md>'` and repair the package until it reports `VALID`.
91
+ 4. Report the package path, the tasks with their dependencies, and every recorded assumption.
113
92
 
114
- The elicitation agent:
115
- 1. Reads the user's initial goal from `<elicit_config>`.
116
- 2. Identifies the missing engineering decisions (input shape, output shape, success command, scope boundary, constraints).
117
- 3. Asks 1-2 focused questions per turn until each blank is filled or the user accepts an inferred default.
118
- 4. Maintains a running draft spec in `.devlyn/ideate-draft.md` (run-scoped, gitignored).
119
- 5. Stops when the structural lint passes AND user confirms, or 8 turns elapsed.
93
+ ## add
120
94
 
121
- Structural lint (inline check, no script needed):
122
- - Frontmatter has `id`, `title`, `kind`, `status: planned`, `complexity`.
123
- - `## Context` non-empty (≥ 1 sentence).
124
- - `## Requirements` has ≥ 1 `- [ ]` bullet.
125
- - `## Out of Scope` present (may list "none" if truly nothing).
126
- - `## Verification` is preceded by a `<!-- devlyn:verification -->` sentinel and has either ≥ 1 named command OR sibling `spec.expected.json` declares `"pure_design": true`.
95
+ An absolute path to a package's `meta.md` is added as it is; anything else is planned first. Add with `python3 "$DEVLYN_SKILL_DIR/scripts/queue.py" add '<absolute meta.md>'`, the only writer of a loop's queue file `docs/specs/<loop-id>/queue.md`; never edit one by hand. In every delivery mode add makes no commit on the checked-out branch and leaves the branch, the index and tracked files as they are: it holds the package and its rows at `refs/devlyn/captures/<loop-id>`, records the add and removes the package copies equal to that capture. Report the capture ref and its `git show` command, any `cleanup` entry, and that a revision needs a new loop id. It refuses package changes staged in the index (unstage them and add again), and a retry of the same add reports it as added, also once the copies are gone. Tasks start from committed state, a local loop from the branch it was added on and `auto`/`pr` from the remote base, so commit, and for `auto`/`pr` push, whatever the plan depends on. A pending legacy raw-intent row of `docs/specs/queue.md` is replaced in place by a package whose `## Intent` reproduces the row verbatim, added with `--materialize <line>`.
127
96
 
128
- After lint passes:
129
- 1. Write `<spec-dir>/<id>-<slug>/spec.md` (the spec).
130
- 2. Generate `<spec-dir>/<id>-<slug>/spec.expected.json` following `references/spec-template.md` § "Sibling file: `spec.expected.json`" for constraint coverage, diff scope and guard controls.
131
- 3. Run `python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py" --check <spec-path>` to validate the actual spec's carrier shape and supported `complexity` frontmatter. Sibling `spec.expected.json` takes precedence over the legacy inline `## Verification` JSON carrier. If exit 2, fix the file named in the error and re-run.
132
- 4. Run `python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py" --check-expected <expected-path>` to validate sibling `spec.expected.json` against `_shared/expected.schema.json` plus sibling spec `complexity` frontmatter. If exit 2, fix the JSON/frontmatter and re-run.
133
- 5. Print: `spec ready — /devlyn-resolve --spec <spec-path>`.
97
+ ## status
134
98
 
135
- ## PHASE 1Q: QUICK MODE
99
+ Run `python3 "$DEVLYN_SKILL_DIR/scripts/queue.py" status --repo .` and report its counts, `next`, `blockers`, pending deliveries with their resume commands and any `cleanup` entry.
136
100
 
137
- Single-turn assume-and-confirm. Prompt body: see `references/elicitation.md` § "Quick mode".
101
+ ## drain
138
102
 
139
- 1. AI synthesizes a spec from the one-line goal.
140
- 2. AI surfaces an explicit "Assumptions made" section listing every inferred decision.
141
- 3. User responds with "go" / "fix X" / "no, different".
142
- 4. On "go": write spec + spec.expected.json + lint + announce.
143
- 5. On "fix X": apply correction, re-show, ask again. Maximum 3 correction rounds before escalating to default mode.
103
+ Follow [loop.md](references/loop.md). The executor is the configured route, the `.devlyn/engines.json` `executor` pin or else this CLI, checked per `_shared/engine-preflight.md`. Pass its argv after `--`. `<git dir>` is the output of `git rev-parse --path-format=absolute --git-common-dir`, where the executor commits and writes its submission; the drain fills `{worktree_git_dir}` with the task worktree's own Git directory, which Codex's sandbox keeps read-only unless that exact directory is listed:
144
104
 
145
- ## PHASE 1F: FROM-SPEC MODE
105
+ | Executor | argv |
106
+ |---|---|
107
+ | Claude | `claude -p "<prompt>" --dangerously-skip-permissions --add-dir "<git dir>"` |
108
+ | Codex | `bash "<DEVLYN_SHARED_DIR>/codex-monitored.sh" --skip-git-repo-check -s workspace-write -c 'sandbox_workspace_write.writable_roots=["<git dir>","{worktree_git_dir}"]' -c 'sandbox_workspace_write.network_access=true' "<prompt>"` |
146
109
 
147
- Prompt body: `references/from-spec-mode.md`.
110
+ Another engine needs an argv that starts one fresh non-interactive session able, without prompts, to edit, run commands and commit in its task worktree and to write the packet's submission file. `<prompt>` carries the absolute binding values, while `{packet}` stays literal for the drain to fill:
148
111
 
149
- 1. Read the external spec at `<path>`.
150
- 2. Lint structure (same checks as default mode).
151
- 3. Identify missing pieces (no frontmatter, missing sections, malformed Verification block).
152
- 4. Apply structural fixes only — do NOT reshape Requirements / Out-of-Scope content. The user's substantive intent is preserved.
153
- 5. Generate `spec.expected.json` if absent, following the same template carrier guidance as default mode.
154
- 6. Write the normalized spec back to `<spec-dir>/<id>-<slug>/` (preserves original at `<path>` untouched unless user passes `--in-place`).
155
- 7. Run both lint checks: `--check <spec-path>` and `--check-expected <expected-path>`.
156
- 8. Lint pass → announce. Lint fail → surface the unfixable issue and exit non-zero.
157
-
158
- ## PHASE 1P: PROJECT MODE
159
-
160
- Prompt body: `references/project-mode.md`.
161
-
162
- 1. AI elicits a project description (longer Q&A — multi-feature scope warrants more turns).
163
- 2. AI decomposes the project into 3-7 feature specs. Each feature is independently shippable; cross-feature dependencies surface explicitly in the spec frontmatter `depends_on:` field.
164
- 3. AI writes `<spec-dir>/plan.md` — index file with: project name, decomposition rationale, list of feature specs with id + title + dependency, suggested implementation order.
165
- 4. AI writes one `<spec-dir>/<id>/spec.md` + `<spec-dir>/<id>/spec.expected.json` per feature, each lint-validated.
166
- 5. Announce: `project ready — N specs at <spec-dir>/. Start with /devlyn-resolve --spec <first-spec-path>`.
112
+ ```text
113
+ Execute the devlyn loop task packet {packet}: work only in its owned worktree under the installed instructions; meet its obligations, then write its submission and any review records as "Executor exchange" and "Review records" in <DEVLYN_SKILL_DIR>/references/loop.md specify. Set DEVLYN_SKILL_DIR=<DEVLYN_SKILL_DIR> and DEVLYN_SHARED_DIR=<DEVLYN_SHARED_DIR> from these literal values, never from your inherited environment. Never push, open a pull request or merge: the drain delivers.
114
+ ```
167
115
 
168
- `/devlyn-resolve` consumes one spec at a time; the user works through `plan.md`'s suggested order. Multi-feature parallel runs are Mission 2 work.
116
+ ```sh
117
+ python3 "$DEVLYN_SKILL_DIR/scripts/queue.py" drain --repo . [--local-only] -- <executor argv>
118
+ ```
169
119
 
170
- ## State management
120
+ A drain can run for hours. Do not end the turn until it exits: run it in the foreground with the longest allowed timeout, or in the background and await its completion notice, because a headless host kills background tasks at its final response.
171
121
 
172
- ideate is conversational, not pipeline-staged. State lives in:
173
- - `.devlyn/ideate-draft.md` — current draft spec during elicitation (run-scoped, gitignored).
174
- - `<spec-dir>/<id>-<slug>/` — final output (committed to repo by user choice).
122
+ - `WAITING` on legacy rows: plan and materialize each under the autonomous policy, then drain again; a row whose planning stops on material ambiguity stays pending and its question is reported.
123
+ - `WAITING` on anything else, or `BLOCKED`: report the reason and resume commands; never edit receipts, refs or queue rows to get past them.
124
+ - An interrupted drain is resumed by running `drain` again; accepted work is never replayed, and a failed task is never rerun: plan its work again as a new loop.
175
125
 
176
- No `pipeline.state.json` here — that's resolve's surface.
126
+ Report each task's product result, delivery status, PR URL, resume command, assumptions and unresolved questions, plus whole-loop acceptance, the package's `## Decisions and assumptions`, the drain report paths and its exact `Bring into` command; leave running it to the user. Report any `cleanup` entry too: a package copy left in the checkout stops that command until it is removed.