@pmelab/gtd 2.7.0 β 2.8.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 +81 -1107
- package/bin/gtd-loop +1 -1
- package/dist/gtd.bundle.mjs +140 -41
- package/docs/cli.md +356 -0
- package/docs/configuration.md +113 -0
- package/docs/development.md +82 -0
- package/docs/loop.md +104 -0
- package/docs/upgrading-from-v1.md +45 -0
- package/docs/workflow.md +428 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,86 +1,40 @@
|
|
|
1
1
|
# gi[t]hings.**done**
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
the
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
or `REVIEW.md` at the repository root is the project's own file β gtd never
|
|
39
|
-
reads, consumes, or deletes it. (Corollary: don't gitignore `.gtd/` β the
|
|
40
|
-
workflow commits its state through it.)
|
|
41
|
-
|
|
42
|
-
A squash commit's message can carry a `## Decisions` section β one entry per
|
|
43
|
-
architecture/product question resolved that cycle. Grilling/architecting read
|
|
44
|
-
every past squash commit's `## Decisions` section back as "Prior decisions"
|
|
45
|
-
context, oldest to newest. See `decisionLog` under Configuration.
|
|
46
|
-
|
|
47
|
-
## Quick start: the two-beat loop
|
|
48
|
-
|
|
49
|
-
gtd splits what used to be one mutating command into three:
|
|
50
|
-
|
|
51
|
-
- **`gtd step`** β advance the workflow as the **human** actor, to fixpoint.
|
|
52
|
-
- **`gtd step-agent`** β advance the workflow as the **agent** actor, to
|
|
53
|
-
fixpoint.
|
|
54
|
-
- **`gtd next`** β print the prompt for whichever actor is currently awaited,
|
|
55
|
-
without mutating anything.
|
|
56
|
-
|
|
57
|
-
An agent loop is a two-beat protocol repeated forever:
|
|
58
|
-
|
|
59
|
-
1. Run `gtd step-agent` to advance any agent-owned bookkeeping to a fixpoint.
|
|
60
|
-
2. Run `gtd next --json` and read the `actor` field. If it is `"human"`,
|
|
61
|
-
**halt** β the human owns the next move, and the agent's job is done for this
|
|
62
|
-
turn. If it is `"agent"`, feed `prompt` (when non-null) to the agent, let it
|
|
63
|
-
act, then go back to step 1; at a pending checkpoint (`prompt` is null) go
|
|
64
|
-
straight back to step 1.
|
|
65
|
-
|
|
66
|
-
A human acts by editing files (answering questions in `.gtd/TODO.md` or
|
|
67
|
-
`.gtd/ARCHITECTURE.md`, annotating `.gtd/REVIEW.md`, fixing code) and then
|
|
68
|
-
running `gtd step` to capture the edit as their turn and hand control back to
|
|
69
|
-
the agent side of the loop.
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
gtd step-agent # advance the machine's own bookkeeping
|
|
73
|
-
gtd next --json # ask who's up and what they should do
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
See [The reference loop driver](#the-reference-loop-driver) for a full script
|
|
77
|
-
implementing this protocol, and [`skills/loop/SKILL.md`](skills/loop/SKILL.md)
|
|
78
|
-
for the agent-facing instructions that follow the same pinned contract.
|
|
79
|
-
`gtd-loop`, installed alongside `gtd` (see below), is the packaged, ready-to-run
|
|
80
|
-
implementation of that same script for anyone who doesn't want to drive the loop
|
|
81
|
-
by hand.
|
|
82
|
-
|
|
83
|
-
## Installation
|
|
3
|
+
> βFix all the tests." ββ
All tests pass!" βThe E2E suite is red." βAh, you
|
|
4
|
+
> mean _those_ tests."
|
|
5
|
+
|
|
6
|
+
**Chat is a terrible source of truth. Git isn't.**
|
|
7
|
+
|
|
8
|
+
**gtd** is a git-aware CLI that derives the entire agentic workflow β capture,
|
|
9
|
+
plan, build, test, review β from your repository state, and prints the next
|
|
10
|
+
prompt for whatever agent you point at it. Every step is a commit. Tests are run
|
|
11
|
+
by the tool and branched on by exit code, so the agent never grades its own
|
|
12
|
+
homework.
|
|
13
|
+
|
|
14
|
+
No chat scrollback. No lost sessions. No infinite fix loops. Just git.
|
|
15
|
+
|
|
16
|
+
## Why
|
|
17
|
+
|
|
18
|
+
- **Durable & replayable.** The workflow state _is_ your git history β a pure
|
|
19
|
+
fold over commit subjects and the working tree. Kill the session, reboot, come
|
|
20
|
+
back next week: run `gtd` and it resumes exactly where it stopped.
|
|
21
|
+
- **Shareable.** Push the branch, and the workflow travels with it β the state
|
|
22
|
+
lives in the commits, so another machine (or another person) picks up exactly
|
|
23
|
+
where you left off.
|
|
24
|
+
- **Files, not chat.** Plans live in `.gtd/TODO.md`, reviews in
|
|
25
|
+
`.gtd/REVIEW.md`. Answer the agent's questions inline, approve by ticking
|
|
26
|
+
checkboxes β all in your own editor. There is no chat UI to lose.
|
|
27
|
+
- **Harness agnostic.** gtd emits prompts to stdout (or JSON). Claude Code, a
|
|
28
|
+
bash loop, a CI job, or you reading it out loud β the workflow doesn't care
|
|
29
|
+
who executes it.
|
|
30
|
+
- **Bounded, not runaway.** Fix attempts are budgeted. When the cap is hit, gtd
|
|
31
|
+
stops and escalates to a human instead of burning tokens rewriting the same
|
|
32
|
+
test for the 47th time.
|
|
33
|
+
- **Clean history.** When the feature ships, all the intermediate `gtd:` commits
|
|
34
|
+
squash into one conventional commit β as if a very disciplined engineer did it
|
|
35
|
+
in one sitting.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
84
38
|
|
|
85
39
|
```bash
|
|
86
40
|
npm install -g @pmelab/gtd
|
|
@@ -93,1036 +47,56 @@ npx @pmelab/gtd
|
|
|
93
47
|
```
|
|
94
48
|
|
|
95
49
|
No config file, no setup subcommand β `gtd` auto-initializes a `.gtdrc.json`
|
|
96
|
-
schema stub on first run (see [
|
|
97
|
-
|
|
98
|
-
## Command reference
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
Usage: gtd [command] [options]
|
|
102
|
-
|
|
103
|
-
Commands:
|
|
104
|
-
step Advance the workflow as the human actor (to fixpoint)
|
|
105
|
-
step-agent Advance the workflow as the agent actor (to fixpoint)
|
|
106
|
-
next Print the prompt for whichever actor is awaited (no mutation)
|
|
107
|
-
status Predict the next commit and state from the working tree (no mutation)
|
|
108
|
-
review <target> Anchor an ad-hoc human review against a git ref or branch
|
|
109
|
-
questions List open questions from the active grilling/architecting doc
|
|
110
|
-
changesets List changesets/files from the active review doc
|
|
111
|
-
format <file> Format a markdown file in place
|
|
112
|
-
|
|
113
|
-
Options:
|
|
114
|
-
--json Output structured JSON instead of plain text
|
|
115
|
-
--version, -v Print version and exit
|
|
116
|
-
--help, -h Print this help and exit
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
`--version` (`-v`) and `--help` (`-h`) short-circuit before any git or
|
|
120
|
-
repository-state work β they run outside a repo and in any repo state. Bare
|
|
121
|
-
`gtd` (no subcommand) is a usage error: it prints the help text and exits 1
|
|
122
|
-
without touching the repository. Every other command must be run from the
|
|
123
|
-
**repository root** β gtd derives steering files, diffs, and pathspecs relative
|
|
124
|
-
to cwd, so it refuses with a clear error if invoked from a subdirectory.
|
|
125
|
-
|
|
126
|
-
`--json` is the only long option. Any other `--` option (including a typo like
|
|
127
|
-
`--jsn`) is rejected with a usage error rather than silently ignored, so a
|
|
128
|
-
mistyped flag can never degrade a JSON caller to plain-text mode.
|
|
129
|
-
|
|
130
|
-
One nuance to "(no mutation)": `next` and `status` never author commits or
|
|
131
|
-
change workflow state, but while a human review is pending they do maintain the
|
|
132
|
-
review checkout window (closing it to read state, re-arming it on the way out β
|
|
133
|
-
see [Human review gate](#human-review-gate)), which transiently moves HEAD and
|
|
134
|
-
the index. The working tree is never touched.
|
|
135
|
-
|
|
136
|
-
### `gtd step` / `gtd step-agent`
|
|
137
|
-
|
|
138
|
-
Both drive the **same fixpoint loop** β gather β resolve β perform the returned
|
|
139
|
-
edge action β repeat β differing only in which actor's turn they are allowed to
|
|
140
|
-
capture:
|
|
141
|
-
|
|
142
|
-
- **`gtd step`** captures the **human** turn at whichever gate is awaiting one.
|
|
143
|
-
- **`gtd step-agent`** captures the **agent** turn.
|
|
144
|
-
|
|
145
|
-
**Fixpoint advance.** A single invocation may author several commits: it authors
|
|
146
|
-
the awaited actor's turn commit, then keeps performing any further mid-chain
|
|
147
|
-
routing (a test run, a routing commit, a package close, β¦) until it reaches a
|
|
148
|
-
rest where a prompt would be shown, or a fixpoint where nothing changed.
|
|
149
|
-
`gtd step`/`gtd step-agent` never print a prompt themselves β that's
|
|
150
|
-
`gtd next`'s job.
|
|
151
|
-
|
|
152
|
-
**Idempotence.** Re-running the same command again once the tree is settled at a
|
|
153
|
-
rest authors **zero** new commits. It exits 0 while the rest still awaits that
|
|
154
|
-
command's actor (an inert empty agent turn, the idle health check); once the
|
|
155
|
-
rest awaits the _other_ actor, the re-run is an out-of-turn refusal β still zero
|
|
156
|
-
commits, but non-zero exit.
|
|
157
|
-
|
|
158
|
-
**Out-of-turn refusal.** Human and agent turns are strictly separated: the wrong
|
|
159
|
-
mutator always errors, at every state, on clean and dirty trees alike.
|
|
160
|
-
`gtd step-agent` while a human turn is awaited refuses with
|
|
161
|
-
`"<state> awaits a human turn β run \`gtd step\`"`; `gtd
|
|
162
|
-
step`while an agent turn is awaited refuses with`"<state> awaits an agent turn β
|
|
163
|
-
run \`gtd
|
|
164
|
-
step-agent\`"`β exit non-zero, zero commits either way. Human edits made while the agent is awaited (e.g. amendment notes in`.gtd/`package files after the`gtd:
|
|
165
|
-
planning` commit lands) stay pending in the working tree and ride along as input
|
|
166
|
-
to the agent's next captured turn; left unamended, the build proceeds.
|
|
167
|
-
|
|
168
|
-
**Red-test fixpoints exit 0.** A red test run below the fix-attempt cap (or the
|
|
169
|
-
health-fix cap) still writes its findings and commits β it is a normal,
|
|
170
|
-
successful step of the loop, not a failure of the `step`/`step-agent`
|
|
171
|
-
invocation. `step`/`step-agent` only exit non-zero for a genuine refusal or an
|
|
172
|
-
operational error (bad config, missing test binary, corrupted state).
|
|
173
|
-
|
|
174
|
-
**Output.** Plain mode prints one `committed: <subject>` line per commit this
|
|
175
|
-
invocation authored (oldestβnewest), then a final `state: <state>` line:
|
|
176
|
-
|
|
177
|
-
```
|
|
178
|
-
committed: gtd(human): grilling
|
|
179
|
-
committed: gtd: architecting
|
|
180
|
-
state: architecting
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
`--json` emits `{state, actions, commits}` instead (see
|
|
184
|
-
[JSON schemas](#json-schemas)).
|
|
185
|
-
|
|
186
|
-
### `gtd next`
|
|
187
|
-
|
|
188
|
-
Pure prompt emitter β it **never mutates** the repository. It reports whichever
|
|
189
|
-
actor is currently awaited and, if the tree is at a genuine rest, the full
|
|
190
|
-
prompt for that actor.
|
|
191
|
-
|
|
192
|
-
**Purity.** No commits, no file writes, no test runs β `gtd next` only gathers
|
|
193
|
-
and resolves.
|
|
194
|
-
|
|
195
|
-
**Dirty-tree refusal.** If the working tree has pending changes outside the
|
|
196
|
-
steering-file set, `gtd next` refuses rather than guess at a prompt for a state
|
|
197
|
-
that hasn't been captured yet:
|
|
198
|
-
|
|
199
|
-
```
|
|
200
|
-
gtd next: working tree is dirty β run `gtd status` to inspect it, then advance with `gtd step` or `gtd step-agent` (whichever actor is awaited)
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**Pending.** If HEAD is mid-chain β bookkeeping the next `step`/`step-agent`
|
|
204
|
-
invocation would perform before reaching a rest β `gtd next` reports
|
|
205
|
-
`pending: true` with no prompt. Mid-chain bookkeeping is invoker-agnostic, so
|
|
206
|
-
either mutator resumes it; the report names the actor whose chain it is. In
|
|
207
|
-
plain mode an agent-driven checkpoint prints `"mid-chain checkpoint β run \`gtd
|
|
208
|
-
step-agent\` to continue, then run \`gtd next\`
|
|
209
|
-
again"`, a human-driven one prints `"mid-chain checkpoint β run \`gtd step\` to
|
|
210
|
-
continue"`.
|
|
211
|
-
|
|
212
|
-
**Agent tail lines.** In plain-mode output, a prompt for the **agent** actor
|
|
213
|
-
ends with the pinned tail:
|
|
214
|
-
|
|
215
|
-
```
|
|
216
|
-
Finish your turn by running `gtd step-agent`. Then run `gtd next` and follow
|
|
217
|
-
its output β repeat this cycle as long as the output is addressed to you (the
|
|
218
|
-
agent); when it awaits the human, stop and hand off.
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
The first sentence closes the current turn; the second closes the outer loop β
|
|
222
|
-
it is what lets a plain-text agent chain multiple iterations (e.g. successive
|
|
223
|
-
test/fix cycles) without an external driver, until a human gate is reached.
|
|
224
|
-
Human-actor prompts carry no tail. `--json` output never embeds the tail into
|
|
225
|
-
`prompt` either β the structured `actor` field (see JSON schemas below) carries
|
|
226
|
-
the same information: `"agent"` means another agent round, `"human"` means stop
|
|
227
|
-
and hand off.
|
|
228
|
-
|
|
229
|
-
### `gtd status`
|
|
230
|
-
|
|
231
|
-
Pure, read-only **dry-run prediction** β the same gather+resolve `gtd next`
|
|
232
|
-
runs, but reporting a prediction of the next turn rather than the actual prompt.
|
|
233
|
-
Performs no git mutation, no test run, no file write β guaranteed side-effect
|
|
234
|
-
free, including on a dirty tree.
|
|
235
|
-
|
|
236
|
-
Prints four fields:
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
State: grilling
|
|
240
|
-
Awaits: human
|
|
241
|
-
Predicted commit: gtd(human): grilling
|
|
242
|
-
Predicted state: grilling
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
- **State** β the currently resolved state.
|
|
246
|
-
- **Awaits** β the actor (`human` or `agent`) whose turn it is.
|
|
247
|
-
- **Predicted commit** β the subject `step`/`step-agent` would author next, or
|
|
248
|
-
`(none)` at a fixpoint (e.g. idle with nothing to do).
|
|
249
|
-
- **Predicted state** β the state that commit would land in.
|
|
250
|
-
|
|
251
|
-
`gtd status` takes no arguments β extra positional args are rejected.
|
|
252
|
-
|
|
253
|
-
### `gtd review <target>`
|
|
254
|
-
|
|
255
|
-
A pure mutator that **anchors, then exits** β it never prints a prompt itself.
|
|
256
|
-
Use it to start an ad-hoc human review against an explicit git ref or branch,
|
|
257
|
-
independent of the automatic review base the workflow otherwise computes.
|
|
258
|
-
|
|
259
|
-
1. Refuses on a dirty tree.
|
|
260
|
-
2. Resolves `<target>` via merge-base semantics and computes the diff HEAD adds
|
|
261
|
-
over `merge-base(<target>, HEAD)`.
|
|
262
|
-
3. Refuses if that diff is empty after filtering ("nothing to review").
|
|
263
|
-
4. Authors exactly one commit: `gtd: reviewing <full-hash-of-the-base>`.
|
|
264
|
-
5. Prints a short confirmation pointing at `gtd next` β it does **not** print
|
|
265
|
-
the review prompt itself.
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
gtd review main
|
|
269
|
-
# anchored review at <hash> β run `gtd next` to get the review prompt
|
|
270
|
-
gtd next --json
|
|
271
|
-
# {"actor":"agent", ...} β the review-record prompt scoped to that anchor
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Errors (all exit 1, message on stderr):
|
|
275
|
-
|
|
276
|
-
- Missing target: `gtd review: missing target argument`
|
|
277
|
-
- Extra arguments:
|
|
278
|
-
`gtd review: too many arguments β expected one target, got: β¦`
|
|
279
|
-
- Unresolvable ref: `gtd review: cannot resolve ref '<target>': <error message>`
|
|
280
|
-
- Empty diff:
|
|
281
|
-
`gtd review: nothing to review (<target> diff is empty after filtering)`
|
|
282
|
-
|
|
283
|
-
### `gtd questions` / `gtd changesets`
|
|
284
|
-
|
|
285
|
-
Pure, read-only reporters β no dirty-tree check, no mutation β that parse the
|
|
286
|
-
structured content out of the active grilling/architecting and review documents,
|
|
287
|
-
for a future UI:
|
|
288
|
-
|
|
289
|
-
- **`gtd questions`** reads whichever of `.gtd/TODO.md` / `.gtd/ARCHITECTURE.md`
|
|
290
|
-
is present and reports its `## Open Questions` list (see
|
|
291
|
-
[Structured grilling/architecting and review files](#structured-grillingarchitecting-and-review-files)
|
|
292
|
-
below). Reports an empty list when neither file exists.
|
|
293
|
-
- **`gtd changesets`** reads `.gtd/REVIEW.md`, if present, and reports its
|
|
294
|
-
chunks/file-pointer list. Reports an empty list when the file doesn't exist.
|
|
295
|
-
|
|
296
|
-
Both take no arguments and always exit 0 β a malformed file is reported via the
|
|
297
|
-
`errors` field/lines rather than failing the command (the same diagnosis
|
|
298
|
-
`gtd step-agent` would refuse the agent's next turn capture with).
|
|
299
|
-
|
|
300
|
-
```bash
|
|
301
|
-
gtd questions --json
|
|
302
|
-
# {"file":".gtd/TODO.md","questions":[{"question":"Which operations?","status":"suggested","text":"add and subtract."}],"errors":[]}
|
|
303
|
-
gtd changesets --json
|
|
304
|
-
# {"file":".gtd/REVIEW.md","shortHash":"abc1234","fullHash":"abc1234...","changesets":[...],"errors":[]}
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### `gtd format <file>`
|
|
308
|
-
|
|
309
|
-
Unchanged from v1: formats a markdown file in place with a bundled prettier
|
|
310
|
-
(`parser: "markdown"`, `printWidth: 80`, `proseWrap: "always"`), ignoring the
|
|
311
|
-
host repo's own `.prettierrc` so `.gtd/TODO.md`/`.gtd/REVIEW.md` stay
|
|
312
|
-
consistently formatted regardless of the host project's toolchain. Rejects
|
|
313
|
-
`--json` (exit 1, `gtd format does not accept --json`) β it is a plain file
|
|
314
|
-
operation, not a v2 state command.
|
|
315
|
-
|
|
316
|
-
Errors (all exit 1, message on stderr):
|
|
317
|
-
|
|
318
|
-
- Missing path: `gtd format: missing file path argument`
|
|
319
|
-
- Extra arguments: `gtd format: too many arguments β expected one path, got: β¦`
|
|
320
|
-
- Non-markdown file:
|
|
321
|
-
`gtd format: <file> is not a markdown file (expected .md or .markdown)`
|
|
322
|
-
- File not found: `gtd: skipped formatting <file>: not found`
|
|
323
|
-
|
|
324
|
-
## JSON schemas
|
|
325
|
-
|
|
326
|
-
Pass `--json` to `step`, `step-agent`, `next`, `status`, `review`, `questions`,
|
|
327
|
-
or `changesets` for machine-readable single-line JSON output instead of plain
|
|
328
|
-
text.
|
|
329
|
-
|
|
330
|
-
**`step` / `step-agent`** β `{state, actions, commits}`:
|
|
331
|
-
|
|
332
|
-
```json
|
|
333
|
-
{
|
|
334
|
-
"state": "architecting",
|
|
335
|
-
"actions": ["capture the human turn as \"gtd(human): grilling\""],
|
|
336
|
-
"commits": ["gtd(human): grilling", "gtd: architecting"]
|
|
337
|
-
}
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
- `state` β the final resolved state after the fixpoint loop settled.
|
|
341
|
-
- `actions` β human-readable descriptions of every edge action this invocation
|
|
342
|
-
performed, oldestβnewest.
|
|
343
|
-
- `commits` β every commit subject this invocation authored, oldestβnewest.
|
|
344
|
-
|
|
345
|
-
**`next`** β `{state, actor, pending, prompt}`:
|
|
346
|
-
|
|
347
|
-
```json
|
|
348
|
-
{
|
|
349
|
-
"state": "building",
|
|
350
|
-
"actor": "agent",
|
|
351
|
-
"pending": false,
|
|
352
|
-
"prompt": "..."
|
|
353
|
-
}
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
- `state` β the resolved state.
|
|
357
|
-
- `actor` β `"human"` or `"agent"`: who owns the next move. This is the single
|
|
358
|
-
loop-driver signal: `"agent"` means proceed with another round β act on
|
|
359
|
-
`prompt` when present, then run `gtd step-agent`; at an agent-driven pending
|
|
360
|
-
checkpoint (`prompt` is `null`, nothing to act on) just run `gtd step-agent`.
|
|
361
|
-
`"human"` means halt and hand off (a human rest, whose prompt body already
|
|
362
|
-
tells the human what to do, or a human-driven pending checkpoint resumed by
|
|
363
|
-
`gtd step`).
|
|
364
|
-
- `pending` β `true` at a mid-chain HEAD (no prompt yet β resume with a mutator
|
|
365
|
-
first); `false` at a genuine rest.
|
|
366
|
-
- `prompt` β the full prompt markdown when `pending` is `false`, else `null`.
|
|
367
|
-
|
|
368
|
-
**`status`** β `{state, actor, predictedCommit, predictedState}`:
|
|
369
|
-
|
|
370
|
-
```json
|
|
371
|
-
{
|
|
372
|
-
"state": "grilling",
|
|
373
|
-
"actor": "human",
|
|
374
|
-
"predictedCommit": "gtd(human): grilling",
|
|
375
|
-
"predictedState": "grilling"
|
|
376
|
-
}
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
`predictedCommit` is `null` when the next invocation would author nothing (e.g.
|
|
380
|
-
idle with a green health check).
|
|
381
|
-
|
|
382
|
-
**`questions`** β `{file, questions, errors}`:
|
|
383
|
-
|
|
384
|
-
```json
|
|
385
|
-
{
|
|
386
|
-
"file": ".gtd/TODO.md",
|
|
387
|
-
"questions": [
|
|
388
|
-
{
|
|
389
|
-
"question": "Which operations?",
|
|
390
|
-
"status": "suggested",
|
|
391
|
-
"text": "add and subtract."
|
|
392
|
-
}
|
|
393
|
-
],
|
|
394
|
-
"errors": []
|
|
395
|
-
}
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
`file` is `null` when neither `.gtd/TODO.md` nor `.gtd/ARCHITECTURE.md` is
|
|
399
|
-
present. `errors` lists any structural problems in the file β the same diagnosis
|
|
400
|
-
that would make `gtd step-agent` refuse the agent's next turn capture.
|
|
401
|
-
|
|
402
|
-
**`changesets`** β `{file, shortHash, fullHash, changesets, errors}`:
|
|
403
|
-
|
|
404
|
-
```json
|
|
405
|
-
{
|
|
406
|
-
"file": ".gtd/REVIEW.md",
|
|
407
|
-
"shortHash": "abc1234",
|
|
408
|
-
"fullHash": "abc1234def5678901234567890123456789abcd",
|
|
409
|
-
"changesets": [
|
|
410
|
-
{
|
|
411
|
-
"title": "Add calculator",
|
|
412
|
-
"description": "New add function for the calculator.",
|
|
413
|
-
"files": [{ "path": "./src/calc.ts", "line": 1, "checked": false }]
|
|
414
|
-
}
|
|
415
|
-
],
|
|
416
|
-
"errors": []
|
|
417
|
-
}
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
`file` is `null` when `.gtd/REVIEW.md` doesn't exist. `errors` mirrors
|
|
421
|
-
`questions`' field above.
|
|
422
|
-
|
|
423
|
-
**Error envelope** β every command, in `--json` mode, reports failures inside
|
|
424
|
-
the JSON object rather than as unstructured text, and still exits 1:
|
|
425
|
-
|
|
426
|
-
```json
|
|
427
|
-
{ "state": "error", "prompt": "<message>" }
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
There is no auto-advance flag anywhere in the wire format β `actor` replaces it.
|
|
431
|
-
The caller decides whether to keep looping based on `actor` (halt on `"human"`)
|
|
432
|
-
and `pending` (re-run `step`/`step-agent` first when `true`), not on a boolean
|
|
433
|
-
auto-advance flag.
|
|
434
|
-
|
|
435
|
-
## The reference loop driver
|
|
436
|
-
|
|
437
|
-
A minimal bash implementation of the pinned two-beat protocol, driving an agent
|
|
438
|
-
CLI (e.g. `claude -p`) against `gtd --json` output. This is the authoritative
|
|
439
|
-
reference for what a loop driver must do; keep any other implementation
|
|
440
|
-
(including `skills/loop/SKILL.md`) consistent with it rather than editing both
|
|
441
|
-
independently.
|
|
442
|
-
|
|
443
|
-
```bash
|
|
444
|
-
#!/usr/bin/env bash
|
|
445
|
-
set -euo pipefail
|
|
446
|
-
|
|
447
|
-
while true; do
|
|
448
|
-
# 1. Advance the machine's own agent-owned bookkeeping to a fixpoint.
|
|
449
|
-
gtd step-agent --json >/dev/null || true
|
|
450
|
-
|
|
451
|
-
# 2. Ask who's up next. `actor` is the single "proceed" signal.
|
|
452
|
-
next="$(gtd next --json)"
|
|
453
|
-
actor="$(jq -r .actor <<<"$next")"
|
|
454
|
-
prompt="$(jq -r .prompt <<<"$next")"
|
|
455
|
-
|
|
456
|
-
if [[ "$actor" != "agent" ]]; then
|
|
457
|
-
echo "Halting β the human owns the next move."
|
|
458
|
-
break
|
|
459
|
-
fi
|
|
460
|
-
|
|
461
|
-
if [[ "$prompt" == "null" ]]; then
|
|
462
|
-
# Agent-driven pending checkpoint: nothing to act on β loop back to
|
|
463
|
-
# step 1, whose `gtd step-agent` resumes the mid-chain bookkeeping.
|
|
464
|
-
continue
|
|
465
|
-
fi
|
|
466
|
-
|
|
467
|
-
# Agent's turn: feed the prompt to the agent, then let it finish with
|
|
468
|
-
# `gtd step-agent` itself (the prompt's tail instructs it to).
|
|
469
|
-
claude -p "$prompt" --dangerously-skip-permissions
|
|
470
|
-
done
|
|
471
|
-
```
|
|
50
|
+
schema stub on first run (see [Configuration](docs/configuration.md#auto-init)).
|
|
472
51
|
|
|
473
|
-
|
|
474
|
-
the prompt (the plain-mode tail says exactly this) β the driver's own
|
|
475
|
-
`step-agent` calls exist to advance any bookkeeping the agent doesn't own
|
|
476
|
-
(routing commits, test runs) between agent turns.
|
|
52
|
+
## How it works
|
|
477
53
|
|
|
478
|
-
|
|
479
|
-
prompt body addresses the human) or a human-driven pending checkpoint
|
|
480
|
-
(`pending: true`, resumed by the human's own `gtd step`). Everything the agent
|
|
481
|
-
side can drive β agent rests and agent-driven checkpoints β reports
|
|
482
|
-
`actor: "agent"`, so multiple agent turns and commits (e.g. successive test/fix
|
|
483
|
-
cycles, a force-approved package close) chain without human involvement until an
|
|
484
|
-
actual human gate is hit.
|
|
54
|
+
Three commands drive everything:
|
|
485
55
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
at a human gate (no commit needed) picks up your edit and keeps going, and it
|
|
491
|
-
halts with a diagnostic if the same state and prompt repeat with no progress
|
|
492
|
-
(see `skills/loop/SKILL.md`'s "Stall detection").
|
|
493
|
-
|
|
494
|
-
### Using a different agent
|
|
495
|
-
|
|
496
|
-
`gtd-loop` defaults to
|
|
497
|
-
`claude -p "$GTD_LOOP_PROMPT" --dangerously-skip-permissions`, but the agent
|
|
498
|
-
invocation is swappable: set `GTD_LOOP_AGENT_CMD` to any shell command, and it
|
|
499
|
-
runs with the prompt available as `$GTD_LOOP_PROMPT` in its environment. For
|
|
500
|
-
example, to drive a different agent CLI:
|
|
501
|
-
|
|
502
|
-
```bash
|
|
503
|
-
GTD_LOOP_AGENT_CMD='my-agent-cli --prompt "$GTD_LOOP_PROMPT"' gtd-loop
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
## States & subjects overview
|
|
507
|
-
|
|
508
|
-
`resolve()` lands on exactly one of **21 states**: `grilling`, `architecting`,
|
|
509
|
-
`grilled`, `planning`, `building`, `testing`, `fixing`, `escalate`,
|
|
510
|
-
`agentic-review`, `close-package`, `review`, `await-review`, `done`, `learning`,
|
|
511
|
-
`await-learning-review`, `learning-apply`, `learning-applied`, `squashing`,
|
|
512
|
-
`idle`, `health-check`, `health-fixing`. Each state has a fixed awaited actor
|
|
513
|
-
(see `awaitedActor` in `src/Machine.ts`): `idle`, `escalate`, `await-review`,
|
|
514
|
-
and `await-learning-review` await the **human**; every other state awaits the
|
|
515
|
-
**agent**.
|
|
516
|
-
|
|
517
|
-
For the full precedence ladder, illegal combinations, and the counter folds that
|
|
518
|
-
drive the fix loops, see [STATES.md](STATES.md) β this section is a summary.
|
|
519
|
-
|
|
520
|
-
### Turn commits β `gtd(<actor>): <gate>`
|
|
521
|
-
|
|
522
|
-
Authored by `gtd step`/`gtd step-agent` as the first commit of a fresh chain.
|
|
523
|
-
The closed set of gates:
|
|
524
|
-
|
|
525
|
-
| Gate | Authored by |
|
|
526
|
-
| ---------------- | ------------------------------------------------------------------ |
|
|
527
|
-
| `grilling` | human (answers) / agent (product-plan iteration) |
|
|
528
|
-
| `architecting` | human (answers) / agent (architecture iteration) |
|
|
529
|
-
| `grilled` | agent (converged, ready to decompose) |
|
|
530
|
-
| `building` | agent (package work, or human feedback while agent is out of turn) |
|
|
531
|
-
| `fixing` | agent (test-fix or review-fix round) |
|
|
532
|
-
| `agentic-review` | agent (writes .gtd/FEEDBACK.md verdict) |
|
|
533
|
-
| `review` | agent (writes .gtd/REVIEW.md) / human (approves or gives feedback) |
|
|
534
|
-
| `squashing` | agent (overwrites .gtd/SQUASH_MSG.md) |
|
|
535
|
-
| `learning` | agent (overwrites .gtd/LEARNINGS.md) / human (accepts or edits) |
|
|
536
|
-
| `learning-apply` | agent (integrates .gtd/LEARNINGS.md into CLAUDE.md/AGENTS.md/docs) |
|
|
537
|
-
| `health-fixing` | agent (idle health-check repair) |
|
|
538
|
-
| `escalate` | human (deletes .gtd/ERRORS.md to resume) |
|
|
539
|
-
|
|
540
|
-
### Routing commits β `gtd: <phase>`
|
|
541
|
-
|
|
542
|
-
Bookkeeping the machine authors itself between turns, never a turn a human or
|
|
543
|
-
agent "wins": `gtd: architecting`, `gtd: grilled`, `gtd: planning`,
|
|
544
|
-
`gtd: tests green`, `gtd: errors`, `gtd: package done`, `gtd: awaiting review`,
|
|
545
|
-
`gtd: review feedback`, `gtd: done`, `gtd: squash template`,
|
|
546
|
-
`gtd: reviewing <hash>` (parameterized, from `gtd review`), `gtd: health-check`,
|
|
547
|
-
`gtd: health-fix`, `gtd: learning template`, `gtd: learning drafted`,
|
|
548
|
-
`gtd: learning approved`, `gtd: learning applied`.
|
|
549
|
-
|
|
550
|
-
Everything else β any non-`gtd` subject, and any `gtd: *` subject outside this
|
|
551
|
-
closed set β is a **boundary commit**: inert as far as the machine's grammar is
|
|
552
|
-
concerned. See [Upgrading from v1](#upgrading-from-v1-breaking-change) for why
|
|
553
|
-
this matters on upgrade.
|
|
554
|
-
|
|
555
|
-
## Workflow walkthroughs
|
|
556
|
-
|
|
557
|
-
### Grilling: two phases, product then architecture
|
|
558
|
-
|
|
559
|
-
A dirty tree at a boundary HEAD (a fresh idea, sketched in a file or just left
|
|
560
|
-
as pending code) is captured in **one** human turn: `gtd step` commits
|
|
561
|
-
everything pending as `gtd(human): grilling` β nothing is reverted or seeded,
|
|
562
|
-
the captured files stay in history. `gtd next` hands the agent that turn's diff;
|
|
563
|
-
the agent develops `.gtd/TODO.md` into a concrete **product-level** plan **in
|
|
564
|
-
one turn** β user-facing decisions only, no architecture β proposing a
|
|
565
|
-
**suggested default** for every open question under an enforced
|
|
566
|
-
`## Open Questions` structure (see
|
|
567
|
-
[Structured grilling/architecting and review files](#structured-grillingarchitecting-and-review-files)),
|
|
568
|
-
and leaves `.gtd/TODO.md` uncommitted for `gtd(agent): grilling`.
|
|
569
|
-
|
|
570
|
-
There are no markers to answer β the human either:
|
|
571
|
-
|
|
572
|
-
- **Accepts the suggested defaults**: runs a clean `gtd step` at the answer
|
|
573
|
-
gate. An empty `gtd(human): grilling` turn plus routing `gtd: architecting`
|
|
574
|
-
lands automatically β `.gtd/ARCHITECTURE.md` is seeded from the converged
|
|
575
|
-
`.gtd/TODO.md` content and `.gtd/TODO.md` is deleted, in that one commit.
|
|
576
|
-
- **Edits `.gtd/TODO.md`** with real answers, then runs `gtd step`, which
|
|
577
|
-
captures the edit as a fresh `gtd(human): grilling` turn and hands it back to
|
|
578
|
-
the agent for another round.
|
|
579
|
-
|
|
580
|
-
Technical architecting works exactly the same way, one file later: the agent
|
|
581
|
-
develops `.gtd/ARCHITECTURE.md` into a concrete **technical** plan β file/module
|
|
582
|
-
structure, data model, tech-stack choices β and the human answers or accepts
|
|
583
|
-
defaults at the `architecting` gate. Accepting converges to `gtd: grilled` and
|
|
584
|
-
`gtd next` emits the decompose prompt (which now reads `.gtd/ARCHITECTURE.md`).
|
|
585
|
-
|
|
586
|
-
**Escape hatch for already-technical input:** if the human's initial dirty tree
|
|
587
|
-
already contains `.gtd/ARCHITECTURE.md` (their own technical sketch), `gtd step`
|
|
588
|
-
captures the entry turn as `gtd(human): architecting` directly, skipping product
|
|
589
|
-
grilling for that cycle entirely β no CLI flag needed, it's driven purely by
|
|
590
|
-
which steering file is present.
|
|
591
|
-
|
|
592
|
-
### Structured grilling/architecting and review files
|
|
593
|
-
|
|
594
|
-
`.gtd/TODO.md`, `.gtd/ARCHITECTURE.md`, and `.gtd/REVIEW.md` stay plain,
|
|
595
|
-
human-readable markdown, but each follows an enforced structure so the data can
|
|
596
|
-
be parsed out programmatically (`gtd questions` / `gtd changesets`, both
|
|
597
|
-
`--json`-able, for a future UI) instead of staying opaque prose.
|
|
598
|
-
|
|
599
|
-
**Grilling/architecting** (identical contract, one file and phase apart): an
|
|
600
|
-
OPTIONAL `## Open Questions` section β omitted entirely means zero open
|
|
601
|
-
questions, not an error. Every `###` sub-heading directly under it is one open
|
|
602
|
-
question; its first body line must be `Suggested default: <text>` (the agent's
|
|
603
|
-
proposal) or `Answer: <text>` (a human's answer):
|
|
604
|
-
|
|
605
|
-
```markdown
|
|
606
|
-
# Plan
|
|
607
|
-
|
|
608
|
-
Build a calculator that can add and subtract.
|
|
609
|
-
|
|
610
|
-
## Open Questions
|
|
611
|
-
|
|
612
|
-
### Which operations?
|
|
613
|
-
|
|
614
|
-
Suggested default: add and subtract.
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
**Review**: a `# Review: <short-hash>` header as the first line, an
|
|
618
|
-
`<!-- base: <full-hash> -->` comment, and at least one `##` chunk with a
|
|
619
|
-
non-empty title and at least one `- [ ]` / `- [x]` file-pointer line β the same
|
|
620
|
-
format `@review` already instructs the agent to write (see
|
|
621
|
-
[Human review gate](#human-review-gate) below).
|
|
622
|
-
|
|
623
|
-
Validation applies ONLY to the **agent's own authored draft** at the gate that
|
|
624
|
-
writes the file β never to a human's free-form edits (their answer at the
|
|
625
|
-
grilling/architecting gate, their feedback/approval at the review gate). When
|
|
626
|
-
the active file is malformed, `gtd step-agent` refuses (zero commits, a stderr
|
|
627
|
-
message listing every structural problem) instead of capturing the turn; the
|
|
628
|
-
agent fixes the file and reruns `gtd step-agent`. `gtd questions --json` /
|
|
629
|
-
`gtd changesets --json` surface the same `errors` without blocking anything, so
|
|
630
|
-
an agent (or a UI) can self-check before committing to a turn.
|
|
631
|
-
|
|
632
|
-
### Build lifecycle: budgets
|
|
633
|
-
|
|
634
|
-
Once decomposed, `.gtd/` holds ordered work packages. `gtd next` at
|
|
635
|
-
`gtd: planning`/`gtd: package done` selects the lowest-numbered remaining
|
|
636
|
-
package and inlines only its task files. The agent builds it and leaves the work
|
|
637
|
-
**uncommitted**; the next invocation's edge action commits it (the
|
|
638
|
-
`gtd(agent): building` turn commit) and runs `testCommand`.
|
|
639
|
-
|
|
640
|
-
- **Green** β Agentic Review.
|
|
641
|
-
- **Red, below `fixAttemptCap`** (default 3) β write findings, commit
|
|
642
|
-
`gtd: errors`, rest at **Fixing** for the agent.
|
|
643
|
-
- **Red, at/over the cap** β write `.gtd/ERRORS.md` instead, commit
|
|
644
|
-
`gtd: errors`, rest at **Escalate** β a human gate. Deleting `.gtd/ERRORS.md`
|
|
645
|
-
and landing that deletion as `gtd(human): escalate` resets the budget and
|
|
646
|
-
re-tests from zero in the same invocation.
|
|
647
|
-
|
|
648
|
-
### Agentic review
|
|
649
|
-
|
|
650
|
-
A green test run always rests at **Agentic Review**: the agent reviews the
|
|
651
|
-
package's accumulated diff against its task specs and writes `.gtd/FEEDBACK.md`.
|
|
652
|
-
An **empty** `.gtd/FEEDBACK.md` is the approval signal β the same
|
|
653
|
-
`gtd(agent): agentic-review` turn closes the package (`gtd: package done`,
|
|
654
|
-
removing `.gtd/FEEDBACK.md` and the finished package directory) in one
|
|
655
|
-
invocation. Non-empty findings rest for the fixing prompt; fixing loops back
|
|
656
|
-
through the test gate and re-reviews. Once `reviewFixCount >= reviewThreshold`
|
|
657
|
-
(default 3) within a package, Agentic Review **force-approves** without ever
|
|
658
|
-
writing `.gtd/FEEDBACK.md` β so a package can never review-loop forever. The
|
|
659
|
-
findings round that crosses the threshold still gets its fixing round; the
|
|
660
|
-
force-approve close then fires at the next green re-test instead of another
|
|
661
|
-
review. (Any agentic-review turn that touches `.gtd/FEEDBACK.md` counts toward
|
|
662
|
-
the threshold β including the approval write itself; an approval that crosses
|
|
663
|
-
the threshold simply closes the package as usual.) Setting
|
|
664
|
-
`agenticReview: false` force-approves every package immediately.
|
|
665
|
-
|
|
666
|
-
A **do-nothing agent invocation** β `gtd step-agent` on a clean tree at ANY
|
|
667
|
-
agent-awaited rest whose move is a file artifact (`grilling`, `architecting`,
|
|
668
|
-
`grilled`, `building`, `fixing`, `agentic-review`, `review`, `squashing` while
|
|
669
|
-
`.gtd/SQUASH_MSG.md` still holds the unmodified template, `learning` while
|
|
670
|
-
`.gtd/LEARNINGS.md` still holds the unmodified template, and `learning-apply`
|
|
671
|
-
unconditionally) β is inert: zero commits, no state consumed; `gtd next`
|
|
672
|
-
re-emits the same prompt. This is load-bearing for the loop protocol, whose
|
|
673
|
-
every iteration opens with `gtd step-agent` before the agent has acted: without
|
|
674
|
-
the guard that opening beat would author junk empty turns β and worse, consume
|
|
675
|
-
workflow state (an empty decompose turn would delete `.gtd/ARCHITECTURE.md` with
|
|
676
|
-
no packages written; an empty squashing turn would squash the cycle under the
|
|
677
|
-
placeholder template). The same guards hold at the classification layer for
|
|
678
|
-
histories that already carry such turns: a `gtd(agent): grilled` HEAD only
|
|
679
|
-
routes to `gtd: planning` when packages exist, a `gtd(agent): review` HEAD only
|
|
680
|
-
routes to `gtd: awaiting review` when `.gtd/REVIEW.md` exists, and a squashing
|
|
681
|
-
(or learning) turn only proceeds once its template has been overwritten. The one
|
|
682
|
-
deliberate exception is `health-fixing`, whose empty turn is meaningful (the
|
|
683
|
-
failure may have been environmental β the machine removes `.gtd/HEALTH.md` and
|
|
684
|
-
re-tests). Human gates are unaffected: an empty **human** turn stays a signal
|
|
685
|
-
(accept-defaults at grilling/architecting, clean approval at review,
|
|
686
|
-
accept-the-draft-as-is at the learning review gate).
|
|
687
|
-
|
|
688
|
-
### Human review gate
|
|
689
|
-
|
|
690
|
-
Once `.gtd/` is fully closed, the machine writes `.gtd/REVIEW.md` and rests at
|
|
691
|
-
**await-review**, awaiting the human. Approval is any of:
|
|
692
|
-
|
|
693
|
-
- A **clean** `gtd step` (nothing edited) β an empty `gtd(human): review` turn
|
|
694
|
-
plus routing `gtd: done`.
|
|
695
|
-
- Flipping only `- [ ]` β `- [x]` checkboxes in `.gtd/REVIEW.md` β checkbox-only
|
|
696
|
-
edits are also treated as clean approval.
|
|
697
|
-
- Deleting `.gtd/REVIEW.md` outright.
|
|
698
|
-
|
|
699
|
-
Any **substantive** edit β to `.gtd/REVIEW.md` prose, or to the reviewed code
|
|
700
|
-
itself β is feedback: `gtd(human): review` plus routing `gtd: review feedback`,
|
|
701
|
-
`.gtd/REVIEW.md` removed, and `gtd next` re-emits a grilling prompt to the agent
|
|
702
|
-
that inlines the human's finding.
|
|
703
|
-
|
|
704
|
-
**The review diff lives in your editor.** While the gate is pending, gtd holds
|
|
705
|
-
open a _review checkout window_: it saves the real head to
|
|
706
|
-
`refs/gtd/review-head`, then rewinds HEAD and the index to the review base with
|
|
707
|
-
`git reset --mixed`, leaving the working tree untouched. Every editor's standard
|
|
708
|
-
git integration now shows the entire reviewable diff as ordinary uncommitted
|
|
709
|
-
changes β SCM panel, gutter marks, per-file diffs. Review it there:
|
|
710
|
-
|
|
711
|
-
- **Edit** anything (code or `.gtd/REVIEW.md` prose) β feedback.
|
|
712
|
-
- **Discard a hunk** in the editor β that reversion IS the feedback: the agent
|
|
713
|
-
is re-grilled with it.
|
|
714
|
-
- **Delete a surfaced file** β reject-this-file feedback.
|
|
715
|
-
- Touch nothing (or tick checkboxes / delete `.gtd/REVIEW.md`) β approval.
|
|
716
|
-
|
|
717
|
-
Any gtd invocation closes the window first (restoring HEAD/index exactly, so
|
|
718
|
-
only your own edits remain dirty β they land as their own separate
|
|
719
|
-
`gtd(human): review` commit, never mixed into the reviewed work), and
|
|
720
|
-
`gtd next`/`gtd status` re-arm it on their way out. The mechanics are
|
|
721
|
-
crash-safe; details and invariants in STATES.md ("The review checkout window").
|
|
722
|
-
|
|
723
|
-
Caveats while a review is pending: don't push (the branch tip rests at the
|
|
724
|
-
review base β the real head is safe under `refs/gtd/review-head`); commits you
|
|
725
|
-
make manually survive as working-tree content and become review feedback, but
|
|
726
|
-
their commit message is discarded; linked `git worktree` checkouts are
|
|
727
|
-
unsupported. If you switch branches mid-review, gtd refuses to touch the foreign
|
|
728
|
-
branch and prints the manual recovery command.
|
|
729
|
-
|
|
730
|
-
### Learning
|
|
731
|
-
|
|
732
|
-
With `learning: true` (the default), `gtd: done` (or the health-fix path's green
|
|
733
|
-
re-test) is **not** a rest β the chain continues straight to
|
|
734
|
-
`gtd: learning template`, writing and committing a `.gtd/LEARNINGS.md` template,
|
|
735
|
-
running _before_ the squash decision so it still sees the pre-squash history.
|
|
736
|
-
`gtd next` then emits the learning prompt: the agent walks the cycle's test
|
|
737
|
-
failures, review feedback, and health-check rounds, keeps only
|
|
738
|
-
durable/generalizable lessons, and overwrites `.gtd/LEARNINGS.md` with them.
|
|
739
|
-
Once `gtd step-agent` captures that draft (`gtd(agent): learning`), it rests at
|
|
740
|
-
**await-learning-review** for a human β who either accepts the draft as-is (an
|
|
741
|
-
empty turn) or edits it; there is no reject path, so the very next `gtd step`
|
|
742
|
-
always proceeds (`gtd(human): learning` β `gtd: learning approved`), resting at
|
|
743
|
-
**learning-apply** for the agent. The agent integrates the approved learnings
|
|
744
|
-
into the project's own docs (`CLAUDE.md`/`AGENTS.md`/wherever fits, its
|
|
745
|
-
judgment); its turn (`gtd(agent): learning-apply`) removes `.gtd/LEARNINGS.md`
|
|
746
|
-
and lands at `gtd: learning applied`, which then runs the same squash decision
|
|
747
|
-
`gtd: done` runs today. With `learning: false`, `gtd: done` behaves exactly as
|
|
748
|
-
it does without this section: no `.gtd/LEARNINGS.md` is ever written. Learning
|
|
749
|
-
and squash are independent flags β either can be on without the other.
|
|
750
|
-
|
|
751
|
-
### Squash
|
|
752
|
-
|
|
753
|
-
With `squash: true` (the default), `gtd: done` (or, once learning has run,
|
|
754
|
-
`gtd: learning applied`) is **not** a rest β the same chain continues straight
|
|
755
|
-
to `gtd: squash template`, writing and committing a `.gtd/SQUASH_MSG.md`
|
|
756
|
-
template. `gtd next` then emits the squashing prompt: the agent overwrites
|
|
757
|
-
`.gtd/SQUASH_MSG.md` with a real conventional-commits message (drawing on
|
|
758
|
-
grilling- and architecting-round decisions from history, and, when this cycle
|
|
759
|
-
resolved any open questions, a `## Decisions` section recording them) and
|
|
760
|
-
finishes its turn. `gtd step-agent` then performs the squash itself:
|
|
761
|
-
`git reset --soft <base>` + `git commit`, collapsing every intermediate `gtd: *`
|
|
762
|
-
commit of the cycle into one β including any review-feedback detours, and the
|
|
763
|
-
learning phase's own commits if learning ran: the squash base is the cycle's
|
|
764
|
-
ORIGINAL start (the first grilling or, via the escape hatch, architecting turn
|
|
765
|
-
since the previous `gtd: done` boundary, or the `gtd: reviewing <hash>` anchor
|
|
766
|
-
for an ad-hoc review cycle), not the most recent re-grilling round β the
|
|
767
|
-
collapse folds the whole cycle into one, using the overwritten message's content
|
|
768
|
-
verbatim (turn position, not message content, triggers the squash). Doc edits
|
|
769
|
-
made during `learning-apply` survive in the squashed tree, not as their own
|
|
770
|
-
commit. With `squash: false`, `gtd: done` (or `gtd: learning applied`) is the
|
|
771
|
-
resting boundary and no template is ever written.
|
|
772
|
-
|
|
773
|
-
### Health check
|
|
774
|
-
|
|
775
|
-
Outside any process (idle, nothing to review, no steering files), `gtd step`
|
|
776
|
-
runs `testCommand` as a health check rather than settling immediately. Green
|
|
777
|
-
settles idle with zero commits. Red below `fixAttemptCap` writes
|
|
778
|
-
`.gtd/HEALTH.md` and rests at **Health Fixing** for the agent; the fixer's own
|
|
779
|
-
turn (`gtd(agent): health-fixing`) removes `.gtd/HEALTH.md` and re-tests in the
|
|
780
|
-
same chain β a green re-test continues to learning (if enabled), then squash (if
|
|
781
|
-
enabled), or idle; red repeats the health-fix loop; red at the cap writes
|
|
782
|
-
`.gtd/ERRORS.md` and escalates.
|
|
783
|
-
|
|
784
|
-
### Escalate / budget reset
|
|
785
|
-
|
|
786
|
-
`.gtd/ERRORS.md` present is always a human gate, regardless of which loop wrote
|
|
787
|
-
it (test-fix or health-fix). Deleting `.gtd/ERRORS.md` and running `gtd step`
|
|
788
|
-
records the deletion as the human's `gtd(human): escalate` turn, which
|
|
789
|
-
**immediately re-tests in the same invocation** β this resets the relevant
|
|
790
|
-
fix-attempt budget to zero.
|
|
791
|
-
|
|
792
|
-
## States & subjects: overview table
|
|
793
|
-
|
|
794
|
-
| State | Awaits | Turn/routing subject at rest |
|
|
795
|
-
| ----------------------- | -------------- | ---------------------------------------------------------------- |
|
|
796
|
-
| `grilling` | human or agent | `gtd(human): grilling` / `gtd(agent): grilling` |
|
|
797
|
-
| `architecting` | human or agent | `gtd: architecting` / `gtd(agent): architecting` |
|
|
798
|
-
| `grilled` | agent | `gtd: grilled` |
|
|
799
|
-
| `planning` | agent | `.gtd/` modified |
|
|
800
|
-
| `building` | agent | `gtd: planning` / `gtd: package done` |
|
|
801
|
-
| `testing` | β (edge-only) | mid-chain only |
|
|
802
|
-
| `fixing` | agent | `gtd: errors` |
|
|
803
|
-
| `escalate` | human | `.gtd/ERRORS.md` present |
|
|
804
|
-
| `agentic-review` | agent | `gtd: tests green` |
|
|
805
|
-
| `close-package` | β (edge-only) | mid-chain only |
|
|
806
|
-
| `review` | agent | `gtd: package done` (no more packages) / `gtd: reviewing <hash>` |
|
|
807
|
-
| `await-review` | human | `gtd: awaiting review` |
|
|
808
|
-
| `done` | β (edge-only) | `gtd: done` |
|
|
809
|
-
| `learning` | agent | `gtd: learning template` |
|
|
810
|
-
| `await-learning-review` | human | `gtd: learning drafted` |
|
|
811
|
-
| `learning-apply` | agent | `gtd: learning approved` |
|
|
812
|
-
| `learning-applied` | β (edge-only) | `gtd: learning applied` |
|
|
813
|
-
| `squashing` | agent | `gtd: squash template` |
|
|
814
|
-
| `idle` | human | no steering files, green health check |
|
|
815
|
-
| `health-check` | β (edge-only) | mid-chain only |
|
|
816
|
-
| `health-fixing` | agent | `.gtd/HEALTH.md` present |
|
|
817
|
-
|
|
818
|
-
See [STATES.md](STATES.md) for the full precedence ladder, the counter folds,
|
|
819
|
-
and every illegal steering-file combination.
|
|
820
|
-
|
|
821
|
-
## Configuration
|
|
822
|
-
|
|
823
|
-
gtd reads an optional `.gtdrc` config file via
|
|
824
|
-
[cosmiconfig](https://github.com/cosmiconfig/cosmiconfig). With no config, the
|
|
825
|
-
built-in defaults apply. Supported filenames (searched in this order):
|
|
826
|
-
|
|
827
|
-
- `.gtdrc`
|
|
828
|
-
- `.gtdrc.json`
|
|
829
|
-
- `.gtdrc.yaml`
|
|
830
|
-
- `.gtdrc.yml`
|
|
831
|
-
- `gtd.config.json`
|
|
832
|
-
- `gtd.config.yaml`
|
|
833
|
-
|
|
834
|
-
### Schema
|
|
835
|
-
|
|
836
|
-
- **`testCommand`** (string, default `npm run test`) β the command the edge runs
|
|
837
|
-
after a build turn, and on the idle health-check path.
|
|
838
|
-
- **`fixAttemptCap`** (non-negative integer, default `3`) β the test-fix budget:
|
|
839
|
-
how many `gtd: errors` attempts are allowed per sub-loop before the failure is
|
|
840
|
-
escalated to `.gtd/ERRORS.md` (Escalate). `0` disables the cap (escalates
|
|
841
|
-
immediately on the first red run). Also reused as the health-fix budget β no
|
|
842
|
-
separate config key.
|
|
843
|
-
- **`reviewThreshold`** (integer β₯ 1, default `3`) β the review-fix budget: how
|
|
844
|
-
many agentic-review findings rounds are allowed per package before Agentic
|
|
845
|
-
Review force-approves.
|
|
846
|
-
- **`agenticReview`** (boolean, default `true`) β kill-switch for the
|
|
847
|
-
per-package Agentic Review gate. Set `false` to force-approve every package
|
|
848
|
-
and proceed directly to human review.
|
|
849
|
-
- **`squash`** (boolean, default `true`) β after `gtd: done` (or, once learning
|
|
850
|
-
has run, `gtd: learning applied`), collapse the cycle's `gtd: *` commits into
|
|
851
|
-
a single conventional-commits commit. Set `false` to keep the granular
|
|
852
|
-
history.
|
|
853
|
-
- **`learning`** (boolean, default `true`) β after `gtd: done` (or the
|
|
854
|
-
health-fix path's green re-test), distill durable lessons from the cycle into
|
|
855
|
-
`.gtd/LEARNINGS.md`, have a human review them, then integrate them into the
|
|
856
|
-
project's own docs before the squash decision runs. Set `false` to skip the
|
|
857
|
-
phase entirely β independent of `squash`.
|
|
858
|
-
- **`decisionLog`** (boolean, default `true`) β squashing records this cycle's
|
|
859
|
-
resolved open questions as a `## Decisions` section in the squash commit
|
|
860
|
-
message; grilling/architecting inline every past squash commit's section,
|
|
861
|
-
oldest to newest, as prior-decision context. Set `false` to skip both.
|
|
862
|
-
- **`models`** β model selection for the subagent-spawning states:
|
|
863
|
-
- `planning` β high-reasoning tier (default `claude-opus-4-8`), used by
|
|
864
|
-
`decompose` (the `grilled`/`planning` states), `grilling`, `architecting`,
|
|
865
|
-
`agentic-review`, and `clean` (the `review`/`squashing`/`learning`/
|
|
866
|
-
`learning-apply` states).
|
|
867
|
-
- `execution` β everyday tier (default `claude-sonnet-4-8`), used by
|
|
868
|
-
`building` and `fixing`.
|
|
869
|
-
- `states.*` β per-state overrides keyed by `decompose`, `grilling`,
|
|
870
|
-
`architecting`, `building`, `fixing`, `agentic-review`, `clean`. Unknown
|
|
871
|
-
`states` keys are **rejected**.
|
|
872
|
-
- **`$schema`** (string, optional) β stripped before validation, so it never
|
|
873
|
-
counts as an unknown key. Point it at the published schema for editor-backed
|
|
874
|
-
autocompletion. A `schema.json` is generated from the config schema at build
|
|
875
|
-
time and ships with the package.
|
|
876
|
-
|
|
877
|
-
### Validation and errors
|
|
878
|
-
|
|
879
|
-
If a config file fails to load or is invalid, gtd **exits with code 1** and
|
|
880
|
-
writes a human-readable error to **stderr** (never stdout):
|
|
881
|
-
|
|
882
|
-
- **Parse errors** (malformed YAML/JSON) β message includes the offending
|
|
883
|
-
filename.
|
|
884
|
-
- **Non-object top-level** β a YAML list or `null` at the root is rejected with
|
|
885
|
-
the filename in the message.
|
|
886
|
-
- **Schema violations** β unknown keys or out-of-range values emit
|
|
887
|
-
`Invalid gtd config: <field>: <reason>`.
|
|
888
|
-
- **Missing test binary** β if `testCommand` names an executable that cannot be
|
|
889
|
-
found (`ENOENT`), gtd exits 1 with `gtd: test command not found: <command>` on
|
|
890
|
-
stderr. A non-zero test _exit code_ is not an error β it drives the normal red
|
|
891
|
-
path.
|
|
892
|
-
|
|
893
|
-
### Lookup and precedence
|
|
894
|
-
|
|
895
|
-
gtd walks from the current working directory **up to your home directory** (or
|
|
896
|
-
to the filesystem root when cwd is outside home), collecting every `.gtdrc` it
|
|
897
|
-
finds along the way. All found levels are **deep-merged**, with the **innermost
|
|
898
|
-
(cwd) config winning** on conflicts β so a shared `.gtdrc` in a worktree-parent
|
|
899
|
-
directory cascades to every checkout beneath it, while any individual checkout
|
|
900
|
-
can still override settings with its own `.gtdrc`.
|
|
901
|
-
|
|
902
|
-
### Auto-init
|
|
903
|
-
|
|
904
|
-
On every **state command** (`step`, `step-agent`, `next`, `status`, `review`)
|
|
905
|
-
that has passed the repo-root guard, if the cwdβroot walk finds **no** config
|
|
906
|
-
anywhere, gtd creates and commits a starter `.gtdrc.json` at the repository root
|
|
907
|
-
containing only a `$schema` link. Auto-init never runs for `--version`/`--help`,
|
|
908
|
-
`format`, bare/unknown commands, or an invocation refused by the repo-root guard
|
|
909
|
-
β those perform no repository mutation of any kind. On a repo with no commits
|
|
910
|
-
yet, or whose HEAD is a plain (non-`gtd:`) commit, the stub is committed as its
|
|
911
|
-
own `chore: add .gtdrc.json`. If HEAD is already a `gtd:`-owned commit
|
|
912
|
-
(mid-workflow), the stub is instead **amended into HEAD** β stacking a fresh
|
|
913
|
-
boundary commit there would produce an unrecognized HEAD most workflow states
|
|
914
|
-
can't resolve past.
|
|
915
|
-
|
|
916
|
-
### Example
|
|
917
|
-
|
|
918
|
-
```yaml
|
|
919
|
-
# .gtdrc.yaml
|
|
920
|
-
testCommand: pnpm test
|
|
921
|
-
fixAttemptCap: 3
|
|
922
|
-
reviewThreshold: 3
|
|
923
|
-
agenticReview: true
|
|
924
|
-
squash: true
|
|
925
|
-
learning: true
|
|
926
|
-
decisionLog: true
|
|
927
|
-
models:
|
|
928
|
-
planning: claude-opus-4-8
|
|
929
|
-
execution: claude-sonnet-4-8
|
|
930
|
-
states:
|
|
931
|
-
decompose: claude-opus-4-8
|
|
932
|
-
building: claude-sonnet-4-8
|
|
933
|
-
```
|
|
934
|
-
|
|
935
|
-
## Repository requirements
|
|
936
|
-
|
|
937
|
-
- **Single writer, linear branch.** State is folded from **first-parent**
|
|
938
|
-
history only. A merge commit at HEAD is unsupported (documented, not handled)
|
|
939
|
-
β it degrades gracefully on the default branch rather than crashing, but do
|
|
940
|
-
not rely on merge commits mid-cycle.
|
|
941
|
-
- **Test/build artifacts must be gitignored.** This is **load-bearing**, not a
|
|
942
|
-
style preference: every fixpoint hop in `gtd step`/`gtd step-agent` detects
|
|
943
|
-
"clean" via `git status --porcelain`, which silently omits anything matched by
|
|
944
|
-
`.gitignore`. If your `testCommand` (or the build it triggers) writes
|
|
945
|
-
tracked-but-untracked output β a `dist/`, a coverage report, a log file β into
|
|
946
|
-
the working tree, the tree never goes clean after a green test run, and the
|
|
947
|
-
fixpoint loop cannot converge: it will either loop forever re-detecting a
|
|
948
|
-
"dirty" boundary or misclassify build output as the human's next feature
|
|
949
|
-
capture. Gitignore every path your test/build toolchain writes before wiring
|
|
950
|
-
gtd into a repo.
|
|
951
|
-
- **Repository root invocation.** Every subcommand except `--help`/`--version`
|
|
952
|
-
must run from the git repository root β steering files and diffs are resolved
|
|
953
|
-
against the process cwd.
|
|
954
|
-
|
|
955
|
-
## Build orchestration
|
|
956
|
-
|
|
957
|
-
### Decompose
|
|
958
|
-
|
|
959
|
-
The Grilled/Planning states spawn a planning-model subagent that breaks
|
|
960
|
-
`.gtd/ARCHITECTURE.md` into executable work packages under `.gtd/`:
|
|
961
|
-
|
|
962
|
-
```
|
|
963
|
-
.gtd/
|
|
964
|
-
01-auth-module/
|
|
965
|
-
01-define-types.md
|
|
966
|
-
02-implement-login.md
|
|
967
|
-
02-api-endpoints/
|
|
968
|
-
01-create-routes.md
|
|
969
|
-
02-add-middleware.md
|
|
970
|
-
```
|
|
971
|
-
|
|
972
|
-
Rules:
|
|
973
|
-
|
|
974
|
-
- **Packages are sequential, in ordinal dependency order** β `01-`, `02-`, β¦;
|
|
975
|
-
the set is frozen once written. Package 02 cannot start until 01 is complete.
|
|
976
|
-
- **Each package is green on its own** β the test suite runs after every
|
|
977
|
-
package, so none may leave the tree red for a later package to fix.
|
|
978
|
-
- **Tasks within a package are parallel and file-disjoint** β one subagent per
|
|
979
|
-
task, no isolation; tasks that would touch the same file are merged into one.
|
|
980
|
-
- **Vertical slices, not horizontal** β each package is a thin, end-to-end
|
|
981
|
-
slice; prefer many thin packages over a "set up infrastructure" package.
|
|
982
|
-
- **Task files are self-contained** β description, acceptance-criteria
|
|
983
|
-
checkboxes, relevant file paths, constraints, and edge cases.
|
|
984
|
-
|
|
985
|
-
### Execute
|
|
986
|
-
|
|
987
|
-
Execution is **one package per cycle**. `gtd next` selects the single next
|
|
988
|
-
package itself, names it in the prompt, and inlines its task files' full
|
|
989
|
-
contents β the agent never browses `.gtd/` or picks a package itself. A single
|
|
990
|
-
cycle:
|
|
991
|
-
|
|
992
|
-
1. Spawn parallel execution-model workers for all tasks in the selected package.
|
|
993
|
-
2. Leave all changes **uncommitted**. Do not commit, do not delete the package
|
|
994
|
-
directory, do not run tests.
|
|
995
|
-
3. Finish the turn with `gtd step-agent` β the next hop's edge action commits
|
|
996
|
-
the work (`gtd(agent): building`) and runs `testCommand` to verify it.
|
|
997
|
-
|
|
998
|
-
## Upgrading from v1 (BREAKING CHANGE)
|
|
999
|
-
|
|
1000
|
-
v2 ships as a **major** semantic-release bump (`2.0.0`) so the binary and the
|
|
1001
|
-
loop-driving text (this README, `skills/loop/SKILL.md`) can never skew against
|
|
1002
|
-
each other. There is **no backward compatibility with the v1 command surface**:
|
|
1003
|
-
the single mutating `gtd` command, marker/sentinel files, the `autoAdvance` JSON
|
|
1004
|
-
field, and the `gtd: transport` handoff commit are all gone. `gtd` bare now
|
|
1005
|
-
errors rather than driving a loop; use `gtd step-agent` / `gtd next` /
|
|
1006
|
-
`gtd step` instead.
|
|
1007
|
-
|
|
1008
|
-
**Commit-history compatibility is one-way.** Any repo with v1-taxonomy history
|
|
1009
|
-
in it (`gtd: new task`, `gtd: grilling`, `gtd: transport`, a bare
|
|
1010
|
-
`gtd: reviewing` with no hash, β¦) upgrades cleanly: those subjects fall outside
|
|
1011
|
-
v2's closed turn/routing grammar and parse as inert **boundary commits** β they
|
|
1012
|
-
are never mistaken for v2 workflow state and never error.
|
|
1013
|
-
|
|
1014
|
-
**Finish or clean up any in-flight v1 cycle first.** If a repo has an
|
|
1015
|
-
**in-progress** v1 cycle β steering files present (root-level `TODO.md`,
|
|
1016
|
-
`REVIEW.md`, `FEEDBACK.md`, `ERRORS.md`, or `.gtd/`) whose HEAD carries v1-only
|
|
1017
|
-
commit subjects β the v2 binary does not know how to resume it: v1 steering
|
|
1018
|
-
files have no v2 turn commit backing them, so a cold v2 invocation on that tree
|
|
1019
|
-
can land in an unrecognized state. Either finish the v1 cycle to a clean
|
|
1020
|
-
boundary with your existing v1 binary before upgrading, or manually clean up
|
|
1021
|
-
(remove the steering files / `.gtd/`, commit the result) so the upgrade starts
|
|
1022
|
-
from a plain boundary HEAD.
|
|
1023
|
-
|
|
1024
|
-
**Steering files moved into `.gtd/`.** Earlier v2 builds kept `TODO.md`,
|
|
1025
|
-
`REVIEW.md`, `FEEDBACK.md`, `ERRORS.md`, `HEALTH.md`, and `SQUASH_MSG.md` at the
|
|
1026
|
-
repository root; they now live under `.gtd/`. Upgrade at a clean boundary (idle,
|
|
1027
|
-
post-squash): a repo at rest needs nothing. Mid-cycle repos should either finish
|
|
1028
|
-
the cycle on the old build first or move the root-level steering files into
|
|
1029
|
-
`.gtd/` by hand and commit. History classification is backward-compatible β the
|
|
1030
|
-
counter folds recognize both the old root paths and the new `.gtd/` paths in
|
|
1031
|
-
existing commits.
|
|
1032
|
-
|
|
1033
|
-
**Re-copy the loop skill.** If you vendor `skills/loop/` into a consuming repo
|
|
1034
|
-
or agent harness, upgrading the `gtd` binary also means re-copying that skill
|
|
1035
|
-
from this release β the v1 skill text still describes the old single-command
|
|
1036
|
-
loop and will drive the new binary incorrectly.
|
|
1037
|
-
|
|
1038
|
-
For maintainers: this repo releases via `semantic-release` reading Conventional
|
|
1039
|
-
Commits, and needs **no config change** for a major bump β but the release
|
|
1040
|
-
commit/PR **must carry a `BREAKING CHANGE:` footer** (or a `!` after the type)
|
|
1041
|
-
for `@semantic-release/commit-analyzer` to compute `2.0.0` rather than a
|
|
1042
|
-
minor/patch bump.
|
|
1043
|
-
|
|
1044
|
-
## Development
|
|
1045
|
-
|
|
1046
|
-
```bash
|
|
1047
|
-
npm install
|
|
1048
|
-
npm run dev # run from source, no build (node dev/run.mjs)
|
|
1049
|
-
npm run build # tsdown β dist/gtd.bundle.mjs
|
|
1050
|
-
npm test # format:check, typecheck, lint, unit + e2e tests, fallow
|
|
1051
|
-
npm run test:unit # vitest unit tests (the pure resolver) β --project unit
|
|
1052
|
-
npm run test:e2e # gherkin e2e via vitest + quickpickle β --project e2e
|
|
1053
|
-
npm run test:mutation # StrykerJS mutation testing (manual only, ~2 min)
|
|
1054
|
-
npm run typecheck
|
|
1055
|
-
npm run lint
|
|
1056
|
-
```
|
|
1057
|
-
|
|
1058
|
-
### Pre-commit hook
|
|
1059
|
-
|
|
1060
|
-
A pre-commit hook is installed automatically via the `prepare` script when you
|
|
1061
|
-
run `npm install` on a fresh clone β no manual setup needed. The hook runs
|
|
1062
|
-
[lint-staged](https://github.com/lint-staged/lint-staged) with
|
|
1063
|
-
[oxfmt](https://oxc.rs/docs/guide/usage/formatter.html), formatting every staged
|
|
1064
|
-
file before each commit (`oxfmt --no-error-on-unmatched-pattern --write`),
|
|
1065
|
-
mirroring the `format:check` step enforced in CI (`oxfmt --check .`).
|
|
1066
|
-
|
|
1067
|
-
### Prompt templates
|
|
1068
|
-
|
|
1069
|
-
Each prompt-bearing state has a self-contained Eta template in
|
|
1070
|
-
`src/prompts/*.md` that owns its full prompt β header, context, and body. Shared
|
|
1071
|
-
fragments live as partials in `src/prompts/partials/`: `header`, the context
|
|
1072
|
-
renderers (`diff`, `feedback`, `package`), and the single `agent-turn` tail
|
|
1073
|
-
partial (the pinned "Finish your turn by running `gtd step-agent`. Then run
|
|
1074
|
-
`gtd next` β¦" loop-closing instructions).
|
|
1075
|
-
|
|
1076
|
-
At module load, `src/Prompt.ts` registers every template on a single `new Eta()`
|
|
1077
|
-
instance via `loadTemplate`. `readFile` and `resolvePath` are nulled afterward
|
|
1078
|
-
so rendering resolves exclusively from the in-memory cache β the compiled ESM
|
|
1079
|
-
bundle carries no runtime `fs` dependency.
|
|
1080
|
-
|
|
1081
|
-
`buildPrompt(result, resolveModel?, output?)` selects the state's template,
|
|
1082
|
-
builds a view-model (model string, tail partial name, context), renders it,
|
|
1083
|
-
collapses runs of three or more blank lines to two, and ensures exactly one
|
|
1084
|
-
trailing newline. It throws for the five states that render no prompt at all
|
|
1085
|
-
(`testing`, `planning`, `close-package`, `done`, `health-check`) β those are
|
|
1086
|
-
performed entirely by the edge.
|
|
1087
|
-
|
|
1088
|
-
`npm run dev` runs `src/main.ts` directly via Node's native TypeScript
|
|
1089
|
-
type-stripping (requires Node 22.6+). It registers `dev/hooks.mjs`, which fills
|
|
1090
|
-
the two gaps the tsdown build otherwise covers: resolving `./Foo.js` specifiers
|
|
1091
|
-
to the on-disk `./Foo.ts`, and importing `*.md` prompt files as text. Pass CLI
|
|
1092
|
-
args after `--`, e.g. `npm run dev -- format <file>`.
|
|
1093
|
-
|
|
1094
|
-
The decision core (`src/Machine.ts`) is pure and IO-free, so the whole 16-state
|
|
1095
|
-
ladder and both counter folds are trivially unit-testable in isolation; all
|
|
1096
|
-
git/filesystem IO is confined to the edge (`src/Events.ts`).
|
|
1097
|
-
|
|
1098
|
-
`npm run build` produces `dist/gtd.bundle.mjs`, which npm exposes as the `gtd`
|
|
1099
|
-
binary via the `bin` field in `package.json`.
|
|
1100
|
-
|
|
1101
|
-
### Mutation testing
|
|
1102
|
-
|
|
1103
|
-
Run mutation testing on-demand with `npm run test:mutation` (StrykerJS, ~2 min)
|
|
1104
|
-
β never run it as part of routine development; it is a deliberate,
|
|
1105
|
-
manually-triggered check. The single `stryker.config.json` mutates six core
|
|
1106
|
-
files:
|
|
1107
|
-
|
|
1108
|
-
```
|
|
1109
|
-
src/Machine.ts src/Prompt.ts src/Config.ts
|
|
1110
|
-
src/Format.ts src/State.ts src/Events.ts
|
|
1111
|
-
```
|
|
1112
|
-
|
|
1113
|
-
`src/Git.ts` is excluded: the Cucumber harness stubs git at the Effect boundary,
|
|
1114
|
-
so `Git.ts` mutants have zero in-memory coverage.
|
|
1115
|
-
|
|
1116
|
-
The HTML report lands in `reports/mutation/mutation.html` (git-ignored).
|
|
1117
|
-
|
|
1118
|
-
## Releasing
|
|
56
|
+
- **`gtd step`** β advance the workflow as the **human** actor.
|
|
57
|
+
- **`gtd step-agent`** β advance the workflow as the **agent** actor.
|
|
58
|
+
- **`gtd next`** β print the prompt for whichever actor is currently awaited,
|
|
59
|
+
without mutating anything.
|
|
1119
60
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
`
|
|
1123
|
-
|
|
1124
|
-
`
|
|
1125
|
-
|
|
61
|
+
The loop is two beats, repeated: run `gtd step-agent`, then `gtd next --json`.
|
|
62
|
+
If the `actor` field says `"agent"`, feed the prompt to your agent and repeat;
|
|
63
|
+
if it says `"human"`, stop β it's your move. You act by editing files (answering
|
|
64
|
+
questions, reviewing the diff in your editor, fixing code) and running
|
|
65
|
+
`gtd step`.
|
|
66
|
+
|
|
67
|
+
Along the way, gtd grills your idea into a product plan, then a technical
|
|
68
|
+
architecture, decomposes it into work packages, builds them one at a time, runs
|
|
69
|
+
your tests after every package, has the agent review its own diff, walks you
|
|
70
|
+
through a final review, and squashes the whole cycle into one clean commit.
|
|
71
|
+
|
|
72
|
+
You don't have to start at the beginning: the steering file you hand the entry
|
|
73
|
+
turn picks the phase β plain notes start product grilling,
|
|
74
|
+
`.gtd/ARCHITECTURE.md` starts technical grilling, a final `.gtd/PLAN.md` goes
|
|
75
|
+
straight to decomposition, and a hand-written `.gtd/HEALTH.md` goes straight
|
|
76
|
+
into the error-fixing loop. See
|
|
77
|
+
[Entry points](docs/workflow.md#entry-points-which-file-starts-the-cycle-where).
|
|
78
|
+
|
|
79
|
+
`gtd-loop`, installed alongside `gtd`, is a ready-to-run driver for the whole
|
|
80
|
+
protocol β point it at a repo and it runs the loop until it's your turn. See
|
|
81
|
+
[Driving the loop](docs/loop.md).
|
|
82
|
+
|
|
83
|
+
Before wiring gtd into a repo, note the
|
|
84
|
+
[repository requirements](docs/cli.md#repository-requirements) β most
|
|
85
|
+
importantly: gitignore everything your test command writes.
|
|
86
|
+
|
|
87
|
+
## Documentation
|
|
88
|
+
|
|
89
|
+
- [CLI reference](docs/cli.md) β every command, exit codes, JSON schemas,
|
|
90
|
+
repository requirements
|
|
91
|
+
- [The workflow](docs/workflow.md) β states, grilling, budgets, the review gate,
|
|
92
|
+
learning, squash
|
|
93
|
+
- [Driving the loop](docs/loop.md) β the reference loop driver, `gtd-loop`,
|
|
94
|
+
custom agents
|
|
95
|
+
- [Configuration](docs/configuration.md) β `.gtdrc` schema, lookup, auto-init
|
|
96
|
+
- [Upgrading from v1](docs/upgrading-from-v1.md) β breaking changes and
|
|
97
|
+
migration
|
|
98
|
+
- [Development](docs/development.md) β building, testing, releasing
|
|
99
|
+
- [STATES.md](STATES.md) β the full state-machine specification
|
|
1126
100
|
|
|
1127
101
|
## License
|
|
1128
102
|
|