@pmelab/gtd 2.8.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -40
- package/bin/gtd-loop +43 -23
- package/dist/gtd.bundle.mjs +2281 -3486
- package/docs/cli.md +187 -288
- package/docs/configuration.md +335 -71
- package/docs/design/configurable-state-machine.md +1439 -0
- package/docs/design/delta-purity-plan.md +283 -0
- package/docs/design/pattern-machine-plan.md +164 -0
- package/docs/design/scripted-actor.md +289 -0
- package/docs/design/state-file-association.md +112 -0
- package/docs/design/steering-file-loops.md +164 -0
- package/docs/design/work-packages.md +194 -0
- package/docs/development.md +55 -36
- package/docs/examples/advanced-workflow.md +428 -0
- package/docs/loop.md +60 -60
- package/docs/upgrading.md +125 -0
- package/package.json +2 -2
- package/schema.json +6 -73
- package/docs/upgrading-from-v1.md +0 -45
- package/docs/workflow.md +0 -428
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# Example: the full grilling → architecting → decompose → picking → review machine
|
|
2
|
+
|
|
3
|
+
This is the fuller machine gtd shipped as its bundled default before the bundled
|
|
4
|
+
default was drastically simplified (see
|
|
5
|
+
[STATES.md §10](../../STATES.md#10-the-bundled-default-workflow) for what ships
|
|
6
|
+
today — including the two steering-file validation loops the current default
|
|
7
|
+
carries over `.gtd/TODO.md` and `.gtd/REVIEW.md`, which this example's own
|
|
8
|
+
`grilling`/`reviewing` phases predate and don't validate). It is preserved here
|
|
9
|
+
as a copy-paste-ready `.gtdrc` recipe for anyone who wants the heavier shape
|
|
10
|
+
back.
|
|
11
|
+
|
|
12
|
+
Compared to the simplified bundled default, this machine adds:
|
|
13
|
+
|
|
14
|
+
- **Two-phase human-in-the-loop planning with Q&A loops** — `grilling` ⇄
|
|
15
|
+
`grilling-answer` develops a product-level plan from `.gtd/TODO.md` one open
|
|
16
|
+
question at a time; `architecting` ⇄ `architecting-answer` repeats the same
|
|
17
|
+
shape for `.gtd/ARCHITECTURE.md`, the technical plan built on top of the
|
|
18
|
+
converged product plan.
|
|
19
|
+
- **Task decomposition** — `decompose` turns the converged architecture into an
|
|
20
|
+
ordered set of self-contained task files under `.gtd/tasks/`.
|
|
21
|
+
- **The deterministic `picking` queue arbiter** — a `script` state that feeds
|
|
22
|
+
tasks into `.gtd/NEXT.md` one at a time, with a per-task `building` →
|
|
23
|
+
`checking`/`fixing` loop, until the queue empties.
|
|
24
|
+
- **Agent-prepared review** — `reviewing` has the agent write `.gtd/REVIEW.md`
|
|
25
|
+
summarizing the full cycle diff for a human to check before `await-review`
|
|
26
|
+
resolves an approval or feedback.
|
|
27
|
+
- **A squash finale** — approval at `await-review` moves to `squashing` (the
|
|
28
|
+
agent authors `.gtd/COMMIT_MSG.md`) and then `done`, a `commit:` state that
|
|
29
|
+
squashes the whole cycle into one commit. The simplified bundled default drops
|
|
30
|
+
this: it rests at `idle` on approval instead and leaves every turn commit in
|
|
31
|
+
history for the human to squash (or not) however they choose.
|
|
32
|
+
|
|
33
|
+
This example also carries `file:`/`mode:` annotations on every state that rests
|
|
34
|
+
on a steering file (see the state table below and
|
|
35
|
+
[docs/design/state-file-association.md](../design/state-file-association.md)) —
|
|
36
|
+
it is the LSP-heavy flow, with `gtd lsp` dispatching document symbols/code
|
|
37
|
+
actions/diagnostics off those declarations rather than a hardcoded basename:
|
|
38
|
+
`grilling`/`grilling-answer` and `architecting`/`architecting-answer` are
|
|
39
|
+
`qa`-format (`vars.todoFile`/`vars.architectureFile` respectively — a new
|
|
40
|
+
`architectureFile` var joins `testCommand`), `reviewing`/`await-review` are
|
|
41
|
+
`review`-format (`vars.reviewFile`), and `fixing`/`escalate` declare `file:`
|
|
42
|
+
alone (`vars.feedbackFile` is plain text, no LSP format).
|
|
43
|
+
|
|
44
|
+
Paste the block below under a top-level `workflow:` key in your own `.gtdrc` (or
|
|
45
|
+
`.gtdrc.yaml`) — it's the complete definition, unmodified in content from the
|
|
46
|
+
version this example is frozen from, only re-indented to nest under `workflow:`.
|
|
47
|
+
See [Configuration](../configuration.md) for the `.gtdrc` schema this slots
|
|
48
|
+
into.
|
|
49
|
+
|
|
50
|
+
## State table
|
|
51
|
+
|
|
52
|
+
| State | Actor | Content | `on` | Retry | Model | File | Mode |
|
|
53
|
+
| --------------------- | ----- | ------- | --------------------------------------------------------------------------------- | ------------------ | ------- | ----------------------- | -------- |
|
|
54
|
+
| `idle` (initial) | human | message | `* **` → `grilling` | — | — | — | — |
|
|
55
|
+
| `grilling` | agent | prompt | `* **` → `grilling-answer` | — | `smart` | `vars.todoFile` | `qa` |
|
|
56
|
+
| `grilling-answer` | human | message | `C` → `architecting`; `* **` → `grilling` | — | — | `vars.todoFile` | `qa` |
|
|
57
|
+
| `architecting` | agent | prompt | `* **` → `architecting-answer` | — | `smart` | `vars.architectureFile` | `qa` |
|
|
58
|
+
| `architecting-answer` | human | message | `C` → `decompose`; `* **` → `architecting` | — | — | `vars.architectureFile` | `qa` |
|
|
59
|
+
| `decompose` | agent | prompt | `* .gtd/tasks/**` → `picking` | — | — | — | — |
|
|
60
|
+
| `picking` | check | script | `D .gtd/NEXT.md` → `reviewing`; `* .gtd/NEXT.md` → `building`; `C` → `reviewing` | — | — | — | — |
|
|
61
|
+
| `building` | agent | prompt | `* **` → `checking` | — | — | — | — |
|
|
62
|
+
| `checking` | check | script | `A .gtd/FEEDBACK.md` → `fixing`; `M .gtd/FEEDBACK.md` → `fixing`; `C` → `picking` | — | — | — | — |
|
|
63
|
+
| `fixing` | agent | prompt | `* **` → `checking` | max 3 → `escalate` | — | `vars.feedbackFile` | — |
|
|
64
|
+
| `escalate` | human | message | `* **` → `checking` | — | — | `vars.feedbackFile` | — |
|
|
65
|
+
| `reviewing` | agent | prompt | `* .gtd/REVIEW.md` → `await-review` | — | `smart` | `vars.reviewFile` | `review` |
|
|
66
|
+
| `await-review` | human | message | `D .gtd/REVIEW.md` → `squashing`; `* **` → `grilling` | — | — | `vars.reviewFile` | `review` |
|
|
67
|
+
| `squashing` | agent | prompt | `A .gtd/COMMIT_MSG.md` → `done`; `M .gtd/COMMIT_MSG.md` → `done` | — | — | — | — |
|
|
68
|
+
| `done` | — | commit | (final — squashes the whole cycle, message read from `.gtd/COMMIT_MSG.md`) | — | — |
|
|
69
|
+
|
|
70
|
+
## The `.gtdrc` recipe
|
|
71
|
+
|
|
72
|
+
````yaml
|
|
73
|
+
workflow:
|
|
74
|
+
vars:
|
|
75
|
+
testCommand: npm test
|
|
76
|
+
todoFile: .gtd/TODO.md
|
|
77
|
+
architectureFile: .gtd/ARCHITECTURE.md
|
|
78
|
+
reviewFile: .gtd/REVIEW.md
|
|
79
|
+
feedbackFile: .gtd/FEEDBACK.md
|
|
80
|
+
|
|
81
|
+
states:
|
|
82
|
+
idle:
|
|
83
|
+
actor: human
|
|
84
|
+
initial: true
|
|
85
|
+
message: |
|
|
86
|
+
No active gtd cycle.
|
|
87
|
+
|
|
88
|
+
To start one: write `.gtd/TODO.md` with a short sketch of what you want
|
|
89
|
+
built — a few sentences is enough — then run `gtd step human`.
|
|
90
|
+
on:
|
|
91
|
+
"* **": grilling
|
|
92
|
+
|
|
93
|
+
grilling:
|
|
94
|
+
actor: agent
|
|
95
|
+
file: <%= it.vars.todoFile %>
|
|
96
|
+
mode: qa
|
|
97
|
+
# `model` is an opaque harness hint — gtd never interprets this string, it
|
|
98
|
+
# only passes it through to `gtd next --json`/`gtd status --json` so the
|
|
99
|
+
# driving loop can map it onto whatever models its agent harness
|
|
100
|
+
# provides. "smart" here just names the harness-chosen tier for the
|
|
101
|
+
# heavier planning/reviewing turns; states without a `model` use the
|
|
102
|
+
# harness's default.
|
|
103
|
+
model: smart
|
|
104
|
+
prompt: |
|
|
105
|
+
You are an autonomous coding agent. `.gtd/` holds this workflow's own
|
|
106
|
+
state (plans, task specs, review records) — never create, edit, or
|
|
107
|
+
delete anything under `.gtd/` except `<%= it.vars.todoFile %>`, which
|
|
108
|
+
this prompt tells you to write.
|
|
109
|
+
|
|
110
|
+
`<%= it.vars.todoFile %>` holds the plan under development. Read it,
|
|
111
|
+
then develop it into a concrete, product-level plan in this one turn —
|
|
112
|
+
explore the codebase before asking anything, so every open question is
|
|
113
|
+
one the codebase genuinely cannot answer.
|
|
114
|
+
|
|
115
|
+
Scope: product and user-facing decisions only. Leave implementation
|
|
116
|
+
details (file/module structure, data models, tech-stack choices) for
|
|
117
|
+
the next phase (`.gtd/ARCHITECTURE.md`).
|
|
118
|
+
|
|
119
|
+
For every remaining open question, add it under a `## Open Questions`
|
|
120
|
+
heading, one `### <question>` sub-heading each, with a
|
|
121
|
+
`Suggested default: <answer>` line the human can accept as-is. Omit the
|
|
122
|
+
section entirely once there are none.
|
|
123
|
+
|
|
124
|
+
Leave `.gtd/TODO.md` uncommitted and finish your turn — do not commit,
|
|
125
|
+
and do not run `gtd step agent` yourself; the harness does that.
|
|
126
|
+
on:
|
|
127
|
+
"* **": grilling-answer
|
|
128
|
+
|
|
129
|
+
grilling-answer:
|
|
130
|
+
actor: human
|
|
131
|
+
file: <%= it.vars.todoFile %>
|
|
132
|
+
mode: qa
|
|
133
|
+
message: |
|
|
134
|
+
`<%= it.vars.todoFile %>` holds the plan under development, with any
|
|
135
|
+
open questions under `## Open Questions` — each carrying a suggested
|
|
136
|
+
default.
|
|
137
|
+
|
|
138
|
+
To answer a question, edit its entry in place (replace
|
|
139
|
+
`Suggested default: ...` with `Answer: ...`, or annotate further), then
|
|
140
|
+
run `gtd step human`.
|
|
141
|
+
|
|
142
|
+
To accept all suggested defaults as-is and move on to technical
|
|
143
|
+
architecting, run `gtd step human` with no edits.
|
|
144
|
+
on:
|
|
145
|
+
"C": architecting
|
|
146
|
+
"* **": grilling
|
|
147
|
+
|
|
148
|
+
architecting:
|
|
149
|
+
actor: agent
|
|
150
|
+
file: <%= it.vars.architectureFile %>
|
|
151
|
+
mode: qa
|
|
152
|
+
model: smart
|
|
153
|
+
prompt: |
|
|
154
|
+
You are an autonomous coding agent. `.gtd/` holds this workflow's own
|
|
155
|
+
state — never create, edit, or delete anything under `.gtd/` except
|
|
156
|
+
`<%= it.vars.architectureFile %>` and `<%= it.vars.todoFile %>`, which
|
|
157
|
+
this prompt tells you to write and delete respectively.
|
|
158
|
+
|
|
159
|
+
Read `<%= it.vars.todoFile %>` (the converged product plan) and
|
|
160
|
+
develop `<%= it.vars.architectureFile %>` from it in this one turn:
|
|
161
|
+
file/module structure, data models, library/tech-stack choices,
|
|
162
|
+
error-handling strategy — the *how*, building on the *what* already
|
|
163
|
+
settled. Do not re-open product-level decisions from
|
|
164
|
+
`<%= it.vars.todoFile %>`; treat them as settled.
|
|
165
|
+
|
|
166
|
+
For every remaining open question, add it under a `## Open Questions`
|
|
167
|
+
heading the same way as the grilling phase (one `### <question>`
|
|
168
|
+
sub-heading, a `Suggested default: <answer>` line). Omit the section
|
|
169
|
+
once there are none.
|
|
170
|
+
|
|
171
|
+
Once `<%= it.vars.architectureFile %>` is written, delete
|
|
172
|
+
`<%= it.vars.todoFile %>` — its content has been folded in and it must
|
|
173
|
+
not linger.
|
|
174
|
+
|
|
175
|
+
Leave everything uncommitted and finish your turn.
|
|
176
|
+
on:
|
|
177
|
+
"* **": architecting-answer
|
|
178
|
+
|
|
179
|
+
architecting-answer:
|
|
180
|
+
actor: human
|
|
181
|
+
file: <%= it.vars.architectureFile %>
|
|
182
|
+
mode: qa
|
|
183
|
+
message: |
|
|
184
|
+
`<%= it.vars.architectureFile %>` holds the technical plan under
|
|
185
|
+
development, with any open questions under `## Open Questions`.
|
|
186
|
+
|
|
187
|
+
To answer a question, edit its entry in place, then run
|
|
188
|
+
`gtd step human`.
|
|
189
|
+
|
|
190
|
+
To accept all suggested defaults as-is and move on to decomposing the
|
|
191
|
+
work, run `gtd step human` with no edits.
|
|
192
|
+
on:
|
|
193
|
+
"C": decompose
|
|
194
|
+
"* **": architecting
|
|
195
|
+
|
|
196
|
+
decompose:
|
|
197
|
+
actor: agent
|
|
198
|
+
prompt: |
|
|
199
|
+
You are an autonomous coding agent. `.gtd/` holds this workflow's own
|
|
200
|
+
state — never create, edit, or delete anything under `.gtd/` except the
|
|
201
|
+
task-spec files this prompt tells you to write (under `.gtd/tasks/`),
|
|
202
|
+
and `.gtd/ARCHITECTURE.md`, which it tells you to delete.
|
|
203
|
+
|
|
204
|
+
Read `.gtd/ARCHITECTURE.md` (the converged technical plan) and
|
|
205
|
+
decompose it into an ordered set of self-contained task files under
|
|
206
|
+
`.gtd/tasks/` (e.g. `.gtd/tasks/01-short-name.md`,
|
|
207
|
+
`.gtd/tasks/02-short-name.md`, ...). Order them so the test suite can
|
|
208
|
+
pass again after each one lands; each file is self-contained
|
|
209
|
+
(description, acceptance criteria as `- [ ]` checkboxes, relevant
|
|
210
|
+
paths) since a building turn receives only that one file as context.
|
|
211
|
+
|
|
212
|
+
No task file may reference any other `.gtd/` file, or a requirement to
|
|
213
|
+
preserve/update workflow state — `.gtd/` is machine-managed and gets
|
|
214
|
+
cleaned up as the cycle proceeds.
|
|
215
|
+
|
|
216
|
+
Once the task files are written, delete `.gtd/ARCHITECTURE.md`. Leave
|
|
217
|
+
everything uncommitted and finish your turn.
|
|
218
|
+
on:
|
|
219
|
+
"* .gtd/tasks/**": picking
|
|
220
|
+
|
|
221
|
+
picking:
|
|
222
|
+
actor: check
|
|
223
|
+
script: |
|
|
224
|
+
#!/usr/bin/env bash
|
|
225
|
+
# gtd check turn (the queue arbiter) — the driver (`gtd run`) executes
|
|
226
|
+
# this verbatim, then steps the check actor. Mechanics only: take the
|
|
227
|
+
# first task file (by name) under .gtd/tasks/ into .gtd/NEXT.md, or
|
|
228
|
+
# remove .gtd/NEXT.md when the queue is empty. What NEXT.md's
|
|
229
|
+
# presence/absence MEANS (another task to build vs. the queue closing
|
|
230
|
+
# out to review) is decided by this state's own `on` rules at capture
|
|
231
|
+
# time — never here.
|
|
232
|
+
set +e
|
|
233
|
+
next=$(ls .gtd/tasks/*.md 2>/dev/null | head -n 1)
|
|
234
|
+
if [ -n "$next" ]; then
|
|
235
|
+
printf '%s' "$next" > .gtd/NEXT.md
|
|
236
|
+
else
|
|
237
|
+
rm -f .gtd/NEXT.md
|
|
238
|
+
fi
|
|
239
|
+
on:
|
|
240
|
+
"D .gtd/NEXT.md": reviewing
|
|
241
|
+
"* .gtd/NEXT.md": building
|
|
242
|
+
"C": reviewing
|
|
243
|
+
|
|
244
|
+
building:
|
|
245
|
+
actor: agent
|
|
246
|
+
prompt: |
|
|
247
|
+
You are an autonomous coding agent. `.gtd/` holds this workflow's own
|
|
248
|
+
state — never create or edit anything under `.gtd/` except deleting the
|
|
249
|
+
one task file this prompt tells you to delete; never touch
|
|
250
|
+
`.gtd/NEXT.md` yourself — the `picking` state owns it.
|
|
251
|
+
|
|
252
|
+
The task file to implement is: <%~ it.read(".gtd/NEXT.md") %>
|
|
253
|
+
|
|
254
|
+
Read that file and implement EXACTLY the one task it describes — no
|
|
255
|
+
more, no less; leave every other task file under `.gtd/tasks/`
|
|
256
|
+
untouched. Use TDD discipline: one test, then the implementation that
|
|
257
|
+
passes it, then the next — never write all the tests first.
|
|
258
|
+
|
|
259
|
+
Delete the task file once its work is complete and verified. Leave
|
|
260
|
+
everything else uncommitted and finish your turn.
|
|
261
|
+
on:
|
|
262
|
+
"* **": checking
|
|
263
|
+
|
|
264
|
+
checking:
|
|
265
|
+
actor: check
|
|
266
|
+
script: |
|
|
267
|
+
#!/usr/bin/env bash
|
|
268
|
+
# gtd check turn — the driver (`gtd run`) executes this verbatim, then
|
|
269
|
+
# steps the check actor. Mechanics only: run the test suite and record a
|
|
270
|
+
# red run's output as .gtd/FEEDBACK.md. What that output MEANS (another
|
|
271
|
+
# fix round vs escalation) is decided by the workflow's own `on`/`retry`
|
|
272
|
+
# rules at capture time — never here.
|
|
273
|
+
#
|
|
274
|
+
# `it.vars.testCommand` defaults to "npm test" (this workflow's own
|
|
275
|
+
# `vars:` above) — override it with a top-level `.gtdrc`
|
|
276
|
+
# `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`
|
|
277
|
+
# environment variable (highest precedence).
|
|
278
|
+
set +e
|
|
279
|
+
mkdir -p .gtd
|
|
280
|
+
<%~ it.vars.testCommand %> > .gtd/.check-output 2>&1
|
|
281
|
+
code=$?
|
|
282
|
+
if [ "$code" -ne 0 ]; then
|
|
283
|
+
if [ -s .gtd/.check-output ]; then
|
|
284
|
+
mv .gtd/.check-output .gtd/FEEDBACK.md
|
|
285
|
+
else
|
|
286
|
+
rm -f .gtd/.check-output
|
|
287
|
+
printf 'npm test failed with exit code %s and produced no output.' "$code" > .gtd/FEEDBACK.md
|
|
288
|
+
fi
|
|
289
|
+
else
|
|
290
|
+
rm -f .gtd/.check-output
|
|
291
|
+
fi
|
|
292
|
+
on:
|
|
293
|
+
"A .gtd/FEEDBACK.md": fixing
|
|
294
|
+
"M .gtd/FEEDBACK.md": fixing
|
|
295
|
+
"C": picking
|
|
296
|
+
|
|
297
|
+
fixing:
|
|
298
|
+
actor: agent
|
|
299
|
+
file: <%= it.vars.feedbackFile %>
|
|
300
|
+
retry:
|
|
301
|
+
max: 3
|
|
302
|
+
otherwise: escalate
|
|
303
|
+
prompt: |
|
|
304
|
+
You are an autonomous coding agent. `.gtd/` holds this workflow's own
|
|
305
|
+
state — never create, edit, or delete anything under `.gtd/` except
|
|
306
|
+
`<%= it.vars.feedbackFile %>`, which this prompt tells you to address.
|
|
307
|
+
|
|
308
|
+
Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix
|
|
309
|
+
the code so the suite passes. Keep the change focused — do not
|
|
310
|
+
refactor unrelated code. If the feedback is wrong, empty or delete
|
|
311
|
+
`<%= it.vars.feedbackFile %>` instead of "fixing" a non-issue; the
|
|
312
|
+
machine picks the dispute up either way.
|
|
313
|
+
|
|
314
|
+
Leave everything uncommitted and finish your turn — do not commit.
|
|
315
|
+
on:
|
|
316
|
+
"* **": checking
|
|
317
|
+
|
|
318
|
+
escalate:
|
|
319
|
+
actor: human
|
|
320
|
+
file: <%= it.vars.feedbackFile %>
|
|
321
|
+
message: |
|
|
322
|
+
The agent could not get the check to pass after repeated attempts.
|
|
323
|
+
`<%= it.vars.feedbackFile %>` holds the last failing output.
|
|
324
|
+
|
|
325
|
+
Investigate and fix it yourself (editing code and/or
|
|
326
|
+
`<%= it.vars.feedbackFile %>`), then run `gtd step human` to try the
|
|
327
|
+
check again.
|
|
328
|
+
on:
|
|
329
|
+
"* **": checking
|
|
330
|
+
|
|
331
|
+
reviewing:
|
|
332
|
+
actor: agent
|
|
333
|
+
file: <%= it.vars.reviewFile %>
|
|
334
|
+
mode: review
|
|
335
|
+
model: smart
|
|
336
|
+
prompt: |
|
|
337
|
+
You are an autonomous coding agent. `.gtd/` holds this workflow's own
|
|
338
|
+
state — never create, edit, or delete anything under `.gtd/` except
|
|
339
|
+
`<%= it.vars.reviewFile %>`, which this prompt tells you to write.
|
|
340
|
+
|
|
341
|
+
Write `<%= it.vars.reviewFile %>` to help a human review the cycle's
|
|
342
|
+
full diff (inlined below): group hunks semantically (same
|
|
343
|
+
feature/refactor/fix, even across files), and for each group write a
|
|
344
|
+
short heading, an explanation of what changed and why, and
|
|
345
|
+
`- [ ] ./path/to/file.ts#42` style file pointers (checkboxes are for
|
|
346
|
+
the human to tick, not you).
|
|
347
|
+
|
|
348
|
+
Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.
|
|
349
|
+
<% if (it.processDiff.trim()) { %>
|
|
350
|
+
|
|
351
|
+
## Full cycle diff
|
|
352
|
+
|
|
353
|
+
```diff
|
|
354
|
+
<%~ it.processDiff %>
|
|
355
|
+
```
|
|
356
|
+
<% } %>
|
|
357
|
+
on:
|
|
358
|
+
"* .gtd/REVIEW.md": await-review
|
|
359
|
+
|
|
360
|
+
await-review:
|
|
361
|
+
actor: human
|
|
362
|
+
file: <%= it.vars.reviewFile %>
|
|
363
|
+
mode: review
|
|
364
|
+
message: |
|
|
365
|
+
`<%= it.vars.reviewFile %>` holds the review record for the completed
|
|
366
|
+
cycle.
|
|
367
|
+
|
|
368
|
+
To approve: delete `<%= it.vars.reviewFile %>` and run
|
|
369
|
+
`gtd step human`.
|
|
370
|
+
|
|
371
|
+
To request changes: edit `<%= it.vars.reviewFile %>` (or the code)
|
|
372
|
+
with what's wrong — including just ticking its checkboxes — then run
|
|
373
|
+
`gtd step human`; this sends the cycle back through grilling with your
|
|
374
|
+
feedback as the new input.
|
|
375
|
+
on:
|
|
376
|
+
"D .gtd/REVIEW.md": squashing
|
|
377
|
+
"* **": grilling
|
|
378
|
+
|
|
379
|
+
squashing:
|
|
380
|
+
actor: agent
|
|
381
|
+
prompt: |
|
|
382
|
+
You are an autonomous coding agent. The cycle is approved and done.
|
|
383
|
+
`.gtd/` holds this workflow's own state — never create, edit, or delete
|
|
384
|
+
anything under `.gtd/` except `.gtd/COMMIT_MSG.md`, which this prompt
|
|
385
|
+
tells you to write.
|
|
386
|
+
|
|
387
|
+
Write `.gtd/COMMIT_MSG.md` with ONE conventional-commits message for
|
|
388
|
+
the entire cycle (subject line `type(scope): subject`, imperative mood,
|
|
389
|
+
<= 72 characters; a body explaining the why, trade-offs, and key
|
|
390
|
+
decisions). Plain text, no markdown wrapper.
|
|
391
|
+
|
|
392
|
+
Leave `.gtd/COMMIT_MSG.md` uncommitted and finish your turn — entering
|
|
393
|
+
this file squashes the whole cycle into one commit using its content as
|
|
394
|
+
the message.
|
|
395
|
+
<% if (it.processDiff.trim()) { %>
|
|
396
|
+
|
|
397
|
+
## Full cycle diff
|
|
398
|
+
|
|
399
|
+
```diff
|
|
400
|
+
<%~ it.processDiff %>
|
|
401
|
+
```
|
|
402
|
+
<% } %>
|
|
403
|
+
on:
|
|
404
|
+
"A .gtd/COMMIT_MSG.md": done
|
|
405
|
+
"M .gtd/COMMIT_MSG.md": done
|
|
406
|
+
|
|
407
|
+
done:
|
|
408
|
+
commit: '<%~ it.read(".gtd/COMMIT_MSG.md") %>'
|
|
409
|
+
````
|
|
410
|
+
|
|
411
|
+
A clean `gtd step human` at `grilling-answer`/`architecting-answer` (the `C`
|
|
412
|
+
event) accepts the current phase's draft and moves on; any other pending change
|
|
413
|
+
loops back for another round. `picking` is a `script` state whose only job is to
|
|
414
|
+
inspect `.gtd/tasks/` (a tree property patterns can't see directly) and turn it
|
|
415
|
+
into a diff patterns CAN see — see the walkthrough in
|
|
416
|
+
[STATES.md §10](../../STATES.md#10-the-bundled-default-workflow) (the version of
|
|
417
|
+
that section frozen alongside this example) for the full state-by-state
|
|
418
|
+
narrative, including the `on`-declaration-order subtlety at `picking` and the
|
|
419
|
+
`fixing` retry-cap pooling caveat.
|
|
420
|
+
|
|
421
|
+
## See also
|
|
422
|
+
|
|
423
|
+
- [docs/design/work-packages.md](../design/work-packages.md) — the arbiter's
|
|
424
|
+
decision record: why the scripted `picking` state (Option A) was chosen over
|
|
425
|
+
the agent-encoded-verdict, tree-predicate-guard, and template-enumeration
|
|
426
|
+
alternatives, plus the process-per-task topology variant.
|
|
427
|
+
- [STATES.md](../../STATES.md) — the pattern-machine model this recipe compiles
|
|
428
|
+
against (pattern grammar, resolution, retry, the squash lifecycle).
|
package/docs/loop.md
CHANGED
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
# Driving the loop
|
|
2
2
|
|
|
3
|
-
gtd
|
|
3
|
+
gtd (v3, the pattern machine) exposes three commands a loop driver combines:
|
|
4
4
|
|
|
5
|
-
- **`gtd step
|
|
6
|
-
|
|
7
|
-
fixpoint
|
|
8
|
-
|
|
5
|
+
- **`gtd step <actor>`** — authenticate as `<actor>`, match the resolved rest's
|
|
6
|
+
declared patterns against the pending changes, and commit (or squash) the one
|
|
7
|
+
resulting transition. Performs AT MOST one transition — there is no fixpoint
|
|
8
|
+
chain to drive.
|
|
9
|
+
- **`gtd next`** — print the resolved rest's rendered script/prompt/message,
|
|
9
10
|
without mutating anything.
|
|
11
|
+
- **`gtd run`** — execute the resolved rest's emitted script (only for a
|
|
12
|
+
`script`-content rest), then step that state's own actor to capture the
|
|
13
|
+
outcome. The only place gtd spawns a subprocess.
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
A loop is a simple cycle:
|
|
12
16
|
|
|
13
|
-
1. Run `gtd
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
1. Run `gtd next --json` — see [`cli.md`](cli.md#gtd-next---json) for the exact
|
|
18
|
+
`{state, actor, kind, content, model?}` field shape. `kind` is the dispatch
|
|
19
|
+
key: `"message"` → halt (a human rest); `"script"` → run `gtd run`;
|
|
20
|
+
`"prompt"` → feed `content` to the agent, then `gtd step <actor>` yourself
|
|
21
|
+
once it's done acting. The optional `model` is an opaque string the workflow
|
|
22
|
+
author chose, which you map onto your own harness's model selection if you
|
|
23
|
+
use one.
|
|
24
|
+
2. Repeat until a `"message"` rest halts the loop, or a zero-commit `gtd run` at
|
|
25
|
+
idle settles it (the green terminal signal).
|
|
19
26
|
|
|
20
|
-
A human acts by editing files (
|
|
21
|
-
|
|
22
|
-
running `gtd step` to capture the edit as their turn and hand control back to
|
|
23
|
-
the agent side of the loop.
|
|
27
|
+
A human acts by editing files (e.g. writing/editing `.gtd/TODO.md`, fixing code)
|
|
28
|
+
and then running `gtd step human` to capture the edit as their turn.
|
|
24
29
|
|
|
25
30
|
```bash
|
|
26
|
-
gtd
|
|
27
|
-
gtd next --json # ask who's up and what they should do
|
|
31
|
+
gtd next --json # ask who's up and what they should do
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
See [`skills/loop/SKILL.md`](../skills/loop/SKILL.md) for the agent-facing
|
|
@@ -34,70 +38,66 @@ that same script for anyone who doesn't want to drive the loop by hand.
|
|
|
34
38
|
|
|
35
39
|
## The reference loop driver
|
|
36
40
|
|
|
37
|
-
A minimal bash implementation of the pinned
|
|
38
|
-
|
|
41
|
+
A minimal bash implementation of the pinned protocol, driving an agent CLI (e.g.
|
|
42
|
+
`claude -p`) against `gtd next --json` output. This is the authoritative
|
|
39
43
|
reference for what a loop driver must do; keep any other implementation
|
|
40
44
|
(including `skills/loop/SKILL.md`) consistent with it rather than editing both
|
|
41
|
-
independently.
|
|
45
|
+
independently. `bin/gtd-loop` is this exact script, packaged as the `gtd-loop`
|
|
46
|
+
binary, with three additions: it stops with a diagnostic if the same `"prompt"`
|
|
47
|
+
state/content repeat with no progress (see `skills/loop/SKILL.md`'s "Stall
|
|
48
|
+
detection"); it lets `GTD_LOOP_AGENT_CMD` swap in any coding agent CLI in place
|
|
49
|
+
of the default `claude -p`, receiving the prompt via `$GTD_LOOP_PROMPT`; and it
|
|
50
|
+
exports the resolved state's optional `model` hint as `$GTD_LOOP_MODEL`,
|
|
51
|
+
appending `--model "$GTD_LOOP_MODEL"` to the default `claude -p` invocation
|
|
52
|
+
whenever it's non-empty.
|
|
42
53
|
|
|
43
54
|
```bash
|
|
44
55
|
#!/usr/bin/env bash
|
|
45
56
|
set -euo pipefail
|
|
46
57
|
|
|
47
58
|
while true; do
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
break
|
|
59
|
+
next_json="$(gtd next --json)"
|
|
60
|
+
state="$(jq -r .state <<<"$next_json")"
|
|
61
|
+
actor="$(jq -r .actor <<<"$next_json")"
|
|
62
|
+
kind="$(jq -r .kind <<<"$next_json")"
|
|
63
|
+
content="$(jq -r .content <<<"$next_json")"
|
|
64
|
+
|
|
65
|
+
if [[ "$kind" == "message" ]]; then
|
|
66
|
+
echo "--- Your turn ($state) ---"
|
|
67
|
+
gtd next
|
|
68
|
+
exit 0
|
|
59
69
|
fi
|
|
60
70
|
|
|
61
|
-
if [[ "$
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
if [[ "$kind" == "script" ]]; then
|
|
72
|
+
head_before="$(git rev-parse HEAD 2>/dev/null || echo none)"
|
|
73
|
+
gtd run
|
|
74
|
+
head_after="$(git rev-parse HEAD 2>/dev/null || echo none)"
|
|
75
|
+
if [[ "$head_before" == "$head_after" ]]; then
|
|
76
|
+
echo "--- Settled ($state: check passed, nothing to do) ---"
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
64
79
|
continue
|
|
65
80
|
fi
|
|
66
81
|
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
# kind == "prompt": feed the prompt to the agent, then close out its turn.
|
|
83
|
+
claude -p "$content" --dangerously-skip-permissions
|
|
84
|
+
gtd step "$actor" >/dev/null
|
|
70
85
|
done
|
|
71
86
|
```
|
|
72
87
|
|
|
73
|
-
The
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
(routing commits, test runs) between agent turns.
|
|
77
|
-
|
|
78
|
-
The loop halts on `actor: "human"` alone: a human rest (`pending: false`, the
|
|
79
|
-
prompt body addresses the human) or a human-driven pending checkpoint
|
|
80
|
-
(`pending: true`, resumed by the human's own `gtd step`). Everything the agent
|
|
81
|
-
side can drive — agent rests and agent-driven checkpoints — reports
|
|
82
|
-
`actor: "agent"`, so multiple agent turns and commits (e.g. successive test/fix
|
|
83
|
-
cycles, a force-approved package close) chain without human involvement until an
|
|
84
|
-
actual human gate is hit.
|
|
85
|
-
|
|
86
|
-
`bin/gtd-loop`, installed as the `gtd-loop` binary, is the packaged
|
|
87
|
-
implementation of this exact script — kept in sync with it the same way
|
|
88
|
-
`skills/loop/SKILL.md` is. It additionally attempts `gtd step` (not just
|
|
89
|
-
`gtd step-agent`) every iteration, so a plain rerun after you've edited a file
|
|
90
|
-
at a human gate (no commit needed) picks up your edit and keeps going, and it
|
|
91
|
-
halts with a diagnostic if the same state and prompt repeat with no progress
|
|
92
|
-
(see `skills/loop/SKILL.md`'s "Stall detection").
|
|
88
|
+
The driver — not the prompt text — owns ending the agent's turn
|
|
89
|
+
(`gtd step "$actor"` right after the agent acts): every default-workflow agent
|
|
90
|
+
prompt says explicitly not to run `gtd step agent` itself.
|
|
93
91
|
|
|
94
92
|
## Using a different agent
|
|
95
93
|
|
|
96
94
|
`gtd-loop` defaults to
|
|
97
95
|
`claude -p "$GTD_LOOP_PROMPT" --dangerously-skip-permissions`, but the agent
|
|
98
96
|
invocation is swappable: set `GTD_LOOP_AGENT_CMD` to any shell command, and it
|
|
99
|
-
runs with the prompt available as `$GTD_LOOP_PROMPT`
|
|
100
|
-
|
|
97
|
+
runs with the prompt available as `$GTD_LOOP_PROMPT` (and the resolved state's
|
|
98
|
+
opaque `model` hint, if any, as `$GTD_LOOP_MODEL`) in its environment — an
|
|
99
|
+
adapter that ignores `$GTD_LOOP_MODEL` keeps working unchanged. For example, to
|
|
100
|
+
drive a different agent CLI:
|
|
101
101
|
|
|
102
102
|
```bash
|
|
103
103
|
GTD_LOOP_AGENT_CMD='my-agent-cli --prompt "$GTD_LOOP_PROMPT"' gtd-loop
|