@pmelab/gtd 8.0.0 → 8.1.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 +402 -110
- package/bin/gtd +3 -4
- package/dist/gtd.bundle.mjs +184 -92
- package/package.json +1 -2
- package/schema.json +33 -9
- package/docs/cli.md +0 -675
- package/docs/configuration.md +0 -994
- package/docs/design/configurable-state-machine.md +0 -1439
- package/docs/design/delta-purity-plan.md +0 -283
- package/docs/design/pattern-machine-plan.md +0 -164
- package/docs/design/pluggable-steering-modes.md +0 -154
- package/docs/design/scripted-actor.md +0 -289
- package/docs/design/state-file-association.md +0 -120
- package/docs/design/state-machine-validation.md +0 -437
- package/docs/design/steering-file-loops.md +0 -182
- package/docs/design/steering-file-validation-command.md +0 -385
- package/docs/design/work-packages.md +0 -193
- package/docs/development.md +0 -109
- package/docs/loop.md +0 -219
- package/docs/upgrading.md +0 -293
package/docs/cli.md
DELETED
|
@@ -1,675 +0,0 @@
|
|
|
1
|
-
# CLI reference
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
Usage: gtd [command] [options]
|
|
5
|
-
|
|
6
|
-
Commands:
|
|
7
|
-
(no command), loop
|
|
8
|
-
Launch the loop driver (bin/gtd), which repeatedly drives
|
|
9
|
-
an agent through gtd next/gtd step calls until the
|
|
10
|
-
workflow rests at a human gate (a non-autonomous state)
|
|
11
|
-
or settles. A bare gtd invocation and gtd loop both
|
|
12
|
-
launch it identically
|
|
13
|
-
init Scaffold a minimal .gtdrc.json for this repo, seeding the
|
|
14
|
-
default variables you are most likely to change (the test
|
|
15
|
-
command) and a Prettier formatting suggestion. gtd runs its
|
|
16
|
-
built-in workflow by default, so no workflow is written —
|
|
17
|
-
add a workflow: key only to customize the machine itself.
|
|
18
|
-
Takes no argument. Run once per repo; refuses if a gtd
|
|
19
|
-
config already exists. Leaves the file uncommitted for you
|
|
20
|
-
to review and commit
|
|
21
|
-
step <actor> Authenticate as <actor>, match the resolved rest's
|
|
22
|
-
declared patterns against the pending changes, and commit
|
|
23
|
-
(or squash) the one resulting transition. Pass
|
|
24
|
-
--cost=<n> (optionally --model=<name>) to record the
|
|
25
|
-
just-finished invocation's token cost and model on the
|
|
26
|
-
turn commit (summed into it.processCost/processCostByModel)
|
|
27
|
-
review <commitish>
|
|
28
|
-
Start a NEW review process at the workflow's declared
|
|
29
|
-
review-entry state (reviewEntry: true), reviewing
|
|
30
|
-
<commitish>..HEAD — e.g. a colleague's PR branch. Requires
|
|
31
|
-
a clean tree resting at the workflow's initial state
|
|
32
|
-
fix Start a NEW process at the workflow's declared fix-entry
|
|
33
|
-
state (fixEntry: true) that goes straight into repairing the
|
|
34
|
-
current failing tests. Requires a clean tree resting at the
|
|
35
|
-
workflow's initial state
|
|
36
|
-
abandon End the process currently underway without completing it:
|
|
37
|
-
close any open review checkout window, then rewind HEAD to
|
|
38
|
-
the commit the process started from, keeping everything it
|
|
39
|
-
produced as uncommitted changes. A no-op when no process is
|
|
40
|
-
underway
|
|
41
|
-
restore Hard-reset HEAD back to the pre-squash tip retained by the
|
|
42
|
-
last squash/abandon (refs/worktree/gtd/history), undoing a
|
|
43
|
-
squash or bringing back an abandoned process's turns.
|
|
44
|
-
Refuses on a dirty working tree, when there is no retained
|
|
45
|
-
history, or when HEAD has advanced past the squash with
|
|
46
|
-
commits that would be lost
|
|
47
|
-
next Print the resolved rest's rendered script/prompt/message
|
|
48
|
-
(no mutation)
|
|
49
|
-
status Print the resolved rest's state/actor and which declared
|
|
50
|
-
pattern (if any) each pending change matches (no mutation)
|
|
51
|
-
validate Format and validate the steering file the resolved rest
|
|
52
|
-
declares, with its mode's commands (its file:/mode:);
|
|
53
|
-
exits non-zero with the findings when it is invalid
|
|
54
|
-
lsp Start the LSP server for .gtd/ steering files (stdio)
|
|
55
|
-
visualize Serve an interactive diagram of the active workflow on a
|
|
56
|
-
local web server (--port <n>, --no-open; --json prints the
|
|
57
|
-
model and exits)
|
|
58
|
-
version Print version and exit
|
|
59
|
-
help Print this help and exit
|
|
60
|
-
|
|
61
|
-
Options:
|
|
62
|
-
--json Output structured JSON instead of plain text
|
|
63
|
-
--port=<n> (gtd visualize only) port to serve on (default: a free port)
|
|
64
|
-
--no-open (gtd visualize only) do not open the browser
|
|
65
|
-
--cost=<n> (gtd step only) record the invocation's token cost
|
|
66
|
-
--model=<name> (gtd step only, with --cost) tag that cost's model
|
|
67
|
-
--once (bare gtd or gtd loop only) run exactly one loop beat (one
|
|
68
|
-
human-gate capture, one script check+step, or one agent
|
|
69
|
-
prompt+step), then exit
|
|
70
|
-
--version, -v Print version and exit
|
|
71
|
-
--help, -h Print this help and exit
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
`--version` (`-v`) / `gtd version` and `--help` (`-h`) / `gtd help`
|
|
75
|
-
short-circuit before any git or repository-state work — they run outside a repo
|
|
76
|
-
and in any repo state (the bare subcommands are exact equivalents of their flag
|
|
77
|
-
forms). Bare `gtd` (no subcommand) and `gtd loop` both launch the loop driver
|
|
78
|
-
(`bin/gtd`) immediately — neither is a usage error. Any other, truly unknown
|
|
79
|
-
subcommand remains a usage error: it prints the help text and exits 1 without
|
|
80
|
-
touching the repository. Every other (recognized) command must be run from the
|
|
81
|
-
**repository root** — gtd derives the workflow, pending changes, and process
|
|
82
|
-
history relative to cwd, so it refuses with a clear error if invoked from a
|
|
83
|
-
subdirectory.
|
|
84
|
-
|
|
85
|
-
`--json`, `--cost=<n>`, and `--model=<name>` (the latter two only for
|
|
86
|
-
`gtd step`) are the only long options the compiled bundle recognizes. Any other
|
|
87
|
-
`--` option (including a typo like `--jsn`) is rejected with a usage error
|
|
88
|
-
rather than silently ignored, so a mistyped flag can never degrade a JSON caller
|
|
89
|
-
to plain-text mode. A bare `--cost`/`--model` with no value, a non-numeric or
|
|
90
|
-
negative `--cost`, an empty `--model`, `--model` without `--cost`, or either
|
|
91
|
-
flag on any command other than `gtd step` are all usage errors.
|
|
92
|
-
|
|
93
|
-
`--once` is a separate, bash-level flag handled entirely by `bin/gtd` itself,
|
|
94
|
-
stripped before anything reaches the bundle — see below.
|
|
95
|
-
|
|
96
|
-
## `--once`
|
|
97
|
-
|
|
98
|
-
A flag on the loop driver only, recognized bare (`gtd --once`) or immediately
|
|
99
|
-
after `loop` (`gtd loop --once`) — the two positions are equivalent, since bare
|
|
100
|
-
`gtd` and `gtd loop` are themselves equivalent. Any other placement (e.g.
|
|
101
|
-
`gtd step --once`) or a duplicated flag (`gtd --once --once`) is a usage error,
|
|
102
|
-
surfaced via whatever guard the misplaced argument first reaches (the compiled
|
|
103
|
-
bundle's own unknown-option/unknown-command rejection for a misplaced flag, or
|
|
104
|
-
`gtd: 'loop' takes no arguments` for one misplaced after `loop`) — never
|
|
105
|
-
silently ignored.
|
|
106
|
-
|
|
107
|
-
**`--once`** restricts the loop to exactly one beat — one human-gate capture,
|
|
108
|
-
one script check+step, or one agent prompt+step — then exits, instead of driving
|
|
109
|
-
all the way back to idle/settled. Precisely: at most one commit/transition is
|
|
110
|
-
made; whichever of the three kinds the currently-resolved rest is, that one gets
|
|
111
|
-
processed (including any internal `gtd validate` fix-reprompt rounds a producing
|
|
112
|
-
agent turn needs — those are all part of finishing the ONE prompt beat, not
|
|
113
|
-
separate beats) and the loop exits 0 immediately after, without re-peeking at
|
|
114
|
-
what comes next. A clean human gate with nothing to capture (the opening move's
|
|
115
|
-
silent capture attempt) is not a beat and falls through to the driver's ordinary
|
|
116
|
-
halt, same as without `--once`.
|
|
117
|
-
|
|
118
|
-
See [Driving the loop](loop.md) and `skills/loop/SKILL.md` for the full
|
|
119
|
-
gate-flow description.
|
|
120
|
-
|
|
121
|
-
## `gtd init`
|
|
122
|
-
|
|
123
|
-
Scaffolds a **minimal** `.gtdrc.json` at the repository root, plus a `$schema`
|
|
124
|
-
link. It writes **no** `workflow:` key — gtd runs the bundled **unified**
|
|
125
|
-
workflow as its built-in default, so a state command works out of the box with
|
|
126
|
-
no config and no init at all. What `gtd init` seeds is the two things most
|
|
127
|
-
projects tune: a `vars: { "testCommand": "npm test" }` entry (the var the
|
|
128
|
-
bundled workflow's check script reads) and a ready-to-edit `modes:` block
|
|
129
|
-
suggesting a Prettier `format:` for each built-in steering-file mode
|
|
130
|
-
(`qa`/`review`). It takes **no argument** — passing one is a usage error
|
|
131
|
-
(`gtd init: too many arguments — init takes no argument`).
|
|
132
|
-
|
|
133
|
-
The bundled default has four entry points — each behind a green-baseline gate
|
|
134
|
-
that runs the suite before starting — into one shared review/squash tail (see
|
|
135
|
-
[STATES.md §10](../STATES.md#10-the-bundled-workflow-templates)): creating
|
|
136
|
-
`.gtd/TODO.md` starts the simple flow (planning → building → checking), creating
|
|
137
|
-
`.gtd/REQUIREMENTS.md` starts the advanced flow (two-phase Q&A planning,
|
|
138
|
-
per-package parallel build, agentic spec-review), `gtd review <commitish>`
|
|
139
|
-
enters review directly, and `gtd fix` goes straight into repairing failing
|
|
140
|
-
tests. A red baseline halts at a `*-start-blocked` gate rather than starting new
|
|
141
|
-
work. To CUSTOMIZE that machine, add your own `workflow:` key (a full definition
|
|
142
|
-
— there is no `extends`/merge); see
|
|
143
|
-
[Configuration](configuration.md#the-workflow-key).
|
|
144
|
-
|
|
145
|
-
The file is written **uncommitted**; review and commit it before your first
|
|
146
|
-
`gtd step` (an uncommitted `.gtdrc.json` is a pending change the initial state
|
|
147
|
-
would otherwise capture). `gtd init` refuses if the repo root already has its
|
|
148
|
-
own gtd config (a global/ancestor config, e.g. `~/.gtdrc`, does not count) and
|
|
149
|
-
requires the repository root (or a directory outside any repo). `--json` prints
|
|
150
|
-
`{"written":".gtdrc.json","inRepo":true}`. See
|
|
151
|
-
[Configuration](configuration.md#gtd-init).
|
|
152
|
-
|
|
153
|
-
## `gtd step <actor> [--cost=<n>] [--model=<name>]`
|
|
154
|
-
|
|
155
|
-
Authenticates `<actor>` against the resolved rest and performs the ONE resulting
|
|
156
|
-
transition. Unlike v2, there is no fixpoint chain to drive: the pattern
|
|
157
|
-
machine's `on` edges are direct one-hop transitions, so a single invocation
|
|
158
|
-
authors at most one commit (a normal turn) or performs one squash
|
|
159
|
-
(§[STATES.md](../STATES.md#8-the-squash-lifecycle)) — never both, never a chain
|
|
160
|
-
of several. A caller that wants several transitions issues several invocations.
|
|
161
|
-
|
|
162
|
-
`--cost=<n>` records the token cost of the invocation that produced the pending
|
|
163
|
-
changes (a non-negative number), and the optional `--model=<name>` tags it with
|
|
164
|
-
the model that ran, as a `Gtd-Cost: <n> <model>` trailer on the turn commit —
|
|
165
|
-
persisted in the git log, summed across the process into `it.processCost` and
|
|
166
|
-
grouped by model into `it.processCostByModel` (see
|
|
167
|
-
[Configuration: Token cost](configuration.md#token-cost)). `--model` requires
|
|
168
|
-
`--cost`. On a squash they are folded into the process total/breakdown the
|
|
169
|
-
`commit:` template renders rather than written as a trailer. Both are orthogonal
|
|
170
|
-
to `--json`.
|
|
171
|
-
|
|
172
|
-
- **Out-of-turn refusal** — `<actor>` isn't the resolved state's declared actor:
|
|
173
|
-
exit non-zero, zero commits.
|
|
174
|
-
`gtd step <actor>: out of turn — "<state>" awaits <awaited-actor>`
|
|
175
|
-
- **No-match refusal** — the tree is dirty and no declared `on` pattern matches:
|
|
176
|
-
exit non-zero, zero commits, naming every declared pattern.
|
|
177
|
-
`gtd step <actor>: no declared pattern matches the pending changes at "<state>" — declared patterns: <p1>, <p2>, …`
|
|
178
|
-
- **No-op** — the tree is clean and the state declares no `C` pattern: exit
|
|
179
|
-
**0**, zero commits. This is the default, silent case a loop driver relies on
|
|
180
|
-
(see [Driving the loop](loop.md)).
|
|
181
|
-
- **Commit/squash** — a pattern matched: exit 0, one commit (or one squash)
|
|
182
|
-
authored.
|
|
183
|
-
|
|
184
|
-
Plain-mode output is one line:
|
|
185
|
-
|
|
186
|
-
```
|
|
187
|
-
committed: gtd(human): idle → planning
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
or, at a no-op:
|
|
191
|
-
|
|
192
|
-
```
|
|
193
|
-
nothing to do at "idle"
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
`--json` emits `{state, subject}` — `subject` is `null` at a no-op — plus
|
|
197
|
-
`cost`/`model` keys echoing what `--cost`/`--model` recorded (each omitted when
|
|
198
|
-
not passed):
|
|
199
|
-
|
|
200
|
-
```json
|
|
201
|
-
{
|
|
202
|
-
"state": "idle",
|
|
203
|
-
"subject": "gtd(human): idle → planning",
|
|
204
|
-
"cost": 1450,
|
|
205
|
-
"model": "claude-opus-4-8"
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
## `gtd review <commitish> [--json]`
|
|
210
|
-
|
|
211
|
-
Starts a BRAND NEW review process at the active workflow's declared
|
|
212
|
-
`reviewEntry: true` state (see
|
|
213
|
-
[STATES.md §11](../STATES.md#11-the-review-checkout-window)), reviewing
|
|
214
|
-
`<commitish>..HEAD` — e.g. a colleague's PR branch pushed on top of a shared
|
|
215
|
-
base, with no gtd process of its own. Reuses the workflow's existing
|
|
216
|
-
review/feedback machinery unmodified; there is no separate review-entry command
|
|
217
|
-
surface to keep in sync.
|
|
218
|
-
|
|
219
|
-
Requires, in order (any failure is a plain refusal — exit non-zero, nothing
|
|
220
|
-
written):
|
|
221
|
-
|
|
222
|
-
- the machine currently resting at the workflow's **initial state** (a plain
|
|
223
|
-
non-gtd branch resolves there via the inert-subject rule — the normal case; a
|
|
224
|
-
process already underway refuses — finish it, or
|
|
225
|
-
[`gtd abandon`](#gtd-abandon---json) it);
|
|
226
|
-
- a **clean working tree**;
|
|
227
|
-
- the active workflow declaring a **`reviewEntry: true`** state (otherwise:
|
|
228
|
-
`gtd review: the active workflow declares no review entry state`);
|
|
229
|
-
- `<commitish>` resolving to a commit, being an **ancestor of HEAD**, and
|
|
230
|
-
**differing from HEAD** (nothing to review otherwise).
|
|
231
|
-
|
|
232
|
-
On success, writes ONE empty commit, `gtd(human): <review-entry-state>`,
|
|
233
|
-
carrying the resolved commit's full hash as a `Gtd-Review-Base: <hash>` trailer
|
|
234
|
-
(mirroring how `gtd step --cost` writes its own `Gtd-Cost:` trailer). Everything
|
|
235
|
-
downstream that renders a diff — `it.processDiff`, and the review checkout
|
|
236
|
-
window opened by a downstream `reviewWindow: true` state — keys off the
|
|
237
|
-
process's diff base, and this trailer is exactly how that base gets re-pointed
|
|
238
|
-
at `<commitish>..HEAD` (see
|
|
239
|
-
[STATES.md §7](../STATES.md#7-retry)/[§11](../STATES.md#11-the-review-checkout-window)).
|
|
240
|
-
|
|
241
|
-
Plain-mode output is one line, same shape as `gtd step`:
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
committed: gtd(human): review-start-check
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
`--json` emits `{state, subject}` — `state` is the entered review-entry state,
|
|
248
|
-
`subject` the bare commit subject (the trailer is not echoed).
|
|
249
|
-
|
|
250
|
-
Takes exactly one positional argument (`<commitish>`); missing or extra
|
|
251
|
-
arguments are usage errors.
|
|
252
|
-
|
|
253
|
-
In the bundled unified template the review-entry state is `review-start-check` —
|
|
254
|
-
a green-baseline gate that runs the suite and, once green, transitions to
|
|
255
|
-
`reviewing`; a red run halts at `review-start-blocked` (see
|
|
256
|
-
[STATES.md §10](../STATES.md#10-the-bundled-workflow-template)).
|
|
257
|
-
|
|
258
|
-
## `gtd fix [--json]`
|
|
259
|
-
|
|
260
|
-
Starts a BRAND NEW process at the active workflow's declared `fixEntry: true`
|
|
261
|
-
state (see [STATES.md §10](../STATES.md#10-the-bundled-workflow-template)) that
|
|
262
|
-
goes straight into repairing the current failing tests. It is the standalone
|
|
263
|
-
counterpart to the entry gates: the gates refuse to start new work on a red
|
|
264
|
-
baseline, and `gtd fix` is the dedicated way to get back to green — repair,
|
|
265
|
-
review, and squash a broken baseline into one commit.
|
|
266
|
-
|
|
267
|
-
Requires, in order (any failure is a plain refusal — exit non-zero, nothing
|
|
268
|
-
written):
|
|
269
|
-
|
|
270
|
-
- the machine currently resting at the workflow's **initial state** (a process
|
|
271
|
-
already underway refuses — finish it, or [`gtd abandon`](#gtd-abandon---json)
|
|
272
|
-
it);
|
|
273
|
-
- a **clean working tree**;
|
|
274
|
-
- the active workflow declaring a **`fixEntry: true`** state (otherwise:
|
|
275
|
-
`gtd fix: the active workflow declares no fix entry state`).
|
|
276
|
-
|
|
277
|
-
Takes no positional argument (extra arguments are a usage error). Unlike
|
|
278
|
-
`gtd review`, it writes NO `Gtd-Review-Base:` trailer — a fix reviews its own
|
|
279
|
-
fixes from the ordinary process start — so on success it writes just one empty
|
|
280
|
-
commit, `gtd(human): <fix-entry-state>`:
|
|
281
|
-
|
|
282
|
-
```
|
|
283
|
-
committed: gtd(human): fix-check
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
`--json` emits `{state, subject}`, same shape as `gtd review`. In the bundled
|
|
287
|
-
unified template the fix-entry state is `fix-check`: a red suite drops into the
|
|
288
|
-
shared `fixing` loop and out through the review + squash tail; a green suite is
|
|
289
|
-
a no-op back to `idle`.
|
|
290
|
-
|
|
291
|
-
## `gtd abandon [--json]`
|
|
292
|
-
|
|
293
|
-
Ends the process currently underway **without completing it** — the way out of a
|
|
294
|
-
process nobody is going to finish, and the command `gtd review`/`gtd fix` name
|
|
295
|
-
when they refuse ("finish it, or run `gtd abandon`, before starting a review").
|
|
296
|
-
A workflow's own exit is its squash finale
|
|
297
|
-
([STATES.md §8](../STATES.md#8-the-squash-lifecycle)); this is the human's, and
|
|
298
|
-
it targets the same boundary:
|
|
299
|
-
|
|
300
|
-
1. any open **review checkout window** is closed first (the bracket every state
|
|
301
|
-
subcommand runs — see
|
|
302
|
-
[STATES.md §11](../STATES.md#11-the-review-checkout-window)), so the rewind
|
|
303
|
-
starts from the real head, not the rewound base;
|
|
304
|
-
2. HEAD is `git reset --mixed`ed to the commit the process started from (its
|
|
305
|
-
start parent — the same target a squash resets to).
|
|
306
|
-
|
|
307
|
-
**Nothing is discarded.** Every turn commit the process wrote is dropped, and
|
|
308
|
-
everything they carried — the code, the `.gtd/` steering files — stays in the
|
|
309
|
-
working tree as uncommitted changes for you to keep, re-commit, or throw away
|
|
310
|
-
with ordinary git:
|
|
311
|
-
|
|
312
|
-
```
|
|
313
|
-
abandoned the process resting at "await-review" — HEAD is back at 1a2b3c4
|
|
314
|
-
("feat: add calculator"), resting at "idle".
|
|
315
|
-
Everything the process produced is kept as uncommitted changes (`git status`);
|
|
316
|
-
discard them with `git checkout -- . && git clean -fd .gtd` for a clean tree.
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
Takes no positional argument (extra arguments are a usage error). Resting at the
|
|
320
|
-
workflow's initial state is a **no-op success**, not a refusal — a recovery
|
|
321
|
-
command that fails when there is nothing to recover is a worse tool:
|
|
322
|
-
|
|
323
|
-
```
|
|
324
|
-
no gtd process is underway (resting at "idle") — nothing to abandon
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
The one refusal is a process whose first commit is the repository's own root
|
|
328
|
-
commit: there is no earlier commit to rewind to, so its commits have to be
|
|
329
|
-
removed by hand.
|
|
330
|
-
|
|
331
|
-
`--json` emits `{state, abandoned, from, head}` — `state` is the initial state
|
|
332
|
-
the machine returns to, `abandoned` whether anything was rewound, and (only when
|
|
333
|
-
it was) `from` the state the abandoned process rested at plus `head` the full
|
|
334
|
-
hash HEAD now points at:
|
|
335
|
-
|
|
336
|
-
```json
|
|
337
|
-
{
|
|
338
|
-
"state": "idle",
|
|
339
|
-
"abandoned": true,
|
|
340
|
-
"from": "await-review",
|
|
341
|
-
"head": "1a2b3c4…"
|
|
342
|
-
}
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
The no-op reports `{"state": "idle", "abandoned": false}` and still exits 0.
|
|
346
|
-
|
|
347
|
-
## `gtd restore [--json]`
|
|
348
|
-
|
|
349
|
-
Undoes the last squash or `gtd abandon` by hard-resetting HEAD back to the
|
|
350
|
-
pre-squash tip that either one retains, before acting, on the per-worktree
|
|
351
|
-
`refs/worktree/gtd/history` ref
|
|
352
|
-
([STATES.md §8](../STATES.md#8-the-squash-lifecycle)):
|
|
353
|
-
|
|
354
|
-
```
|
|
355
|
-
restored the retained history — HEAD is back at 1a2b3c4 ("gtd(agent): drafting
|
|
356
|
-
→ working"), resting at "await-review". Resume with the loop, or `git reset`
|
|
357
|
-
to any earlier turn to restart from there.
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Refuses on a dirty working tree — commit, stash, or discard your changes first.
|
|
361
|
-
Refuses when there is no retained history to restore (nothing has been squashed
|
|
362
|
-
or abandoned yet, or a previous `restore` already consumed it). Refuses when
|
|
363
|
-
HEAD has advanced past the retained tip with commits that would be discarded by
|
|
364
|
-
resetting:
|
|
365
|
-
|
|
366
|
-
```
|
|
367
|
-
gtd restore: HEAD has advanced past the squash — restoring would discard
|
|
368
|
-
commits built on top of it — HEAD 4d5e6f7 is ahead of the retained tip
|
|
369
|
-
1a2b3c4.
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
Takes no positional argument (extra arguments are a usage error).
|
|
373
|
-
|
|
374
|
-
`--json` emits `{state, restored, to, from}` — `state` is the resolved rest
|
|
375
|
-
after the reset, `restored` always `true` (a refusal exits non-zero instead),
|
|
376
|
-
`to` the full hash HEAD was reset to, and `from` the state the machine rested at
|
|
377
|
-
before the reset:
|
|
378
|
-
|
|
379
|
-
```json
|
|
380
|
-
{
|
|
381
|
-
"state": "await-review",
|
|
382
|
-
"restored": true,
|
|
383
|
-
"to": "1a2b3c4…",
|
|
384
|
-
"from": "idle"
|
|
385
|
-
}
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
## `gtd next [--json]`
|
|
389
|
-
|
|
390
|
-
Pure emitter of the resolved rest's rendered content — it **never mutates** the
|
|
391
|
-
repository (no commits, no file writes, no script execution). Resolves HEAD
|
|
392
|
-
exactly like `gtd step`, renders that state's declared
|
|
393
|
-
`script`/`prompt`/`message` template, and prints it. `kind` is never `"commit"`
|
|
394
|
-
here: resolution never rests at a commit state (entering one always ends the
|
|
395
|
-
process in the same step that entered it — see
|
|
396
|
-
[STATES.md §5](../STATES.md#5-resolution)).
|
|
397
|
-
|
|
398
|
-
Plain mode prints the rendered content verbatim (with exactly one trailing
|
|
399
|
-
newline) — never the `model`/`memory`/`file`/`mode`/`edges` structured keys,
|
|
400
|
-
which are JSON-only. `--json` emits
|
|
401
|
-
`{state, actor, kind, content, model?, memory?, file?, mode?, edges?}`:
|
|
402
|
-
|
|
403
|
-
```json
|
|
404
|
-
{
|
|
405
|
-
"state": "building",
|
|
406
|
-
"actor": "agent",
|
|
407
|
-
"kind": "prompt",
|
|
408
|
-
"content": "You are an autonomous coding agent. ..."
|
|
409
|
-
}
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
- `state` — the resolved state.
|
|
413
|
-
- `actor` — the state's declared actor.
|
|
414
|
-
- `kind` — `"script"` | `"prompt"` | `"message"` — the dispatch key a driver
|
|
415
|
-
switches on (see [Driving the loop](loop.md)).
|
|
416
|
-
- `content` — the fully rendered template.
|
|
417
|
-
- `model` — the state's opaque `model:` hint, RENDERED through the same template
|
|
418
|
-
context as `content` (see
|
|
419
|
-
[Configuration](configuration.md#model--the-opaque-harness-hint-template-rendered)),
|
|
420
|
-
present only when the state declares one; **omitted entirely** (never `null`)
|
|
421
|
-
when unset.
|
|
422
|
-
- `memory` — the state's opaque `memory:` scope label, RENDERED the same way
|
|
423
|
-
(see
|
|
424
|
-
[Configuration](configuration.md#memory--the-memory-scope-label-template-rendered)).
|
|
425
|
-
A memory-aware driver retains an agent's memory across consecutive agent turns
|
|
426
|
-
sharing this label and starts fresh when it changes. Present only when the
|
|
427
|
-
state declares one; **omitted entirely** (never `null`) when unset.
|
|
428
|
-
- `file` — the state's declared steering file, RENDERED the same way; `mode` —
|
|
429
|
-
its format's name, verbatim (a built-in `"qa"`/`"review"`, or a
|
|
430
|
-
workflow-declared mode) (see
|
|
431
|
-
[Configuration](configuration.md#filemode--the-steering-file-association)).
|
|
432
|
-
Both present only when the state declares them; **omitted entirely** (never
|
|
433
|
-
`null`) otherwise.
|
|
434
|
-
- `edges` — the resting state's `on` edges as `[{ pattern, target, describe? }]`
|
|
435
|
-
(declaration order) — the same list the content template sees as `it.edges`
|
|
436
|
-
(see
|
|
437
|
-
[Configuration](configuration.md#on-values--a-target-or-a--to-describe--route-description)).
|
|
438
|
-
A driver relaying a human gate's message has the routing (and each edge's
|
|
439
|
-
human-readable `describe`) alongside the rendered text. **Omitted entirely**
|
|
440
|
-
when the state has no `on` (a commit state); a per-edge `describe` is likewise
|
|
441
|
-
omitted when that edge declares none.
|
|
442
|
-
|
|
443
|
-
## Running `script` rests (no `gtd` subcommand)
|
|
444
|
-
|
|
445
|
-
There is no `gtd` subcommand that executes a workflow script — gtd never runs a
|
|
446
|
-
workflow script itself. When `gtd next` resolves to a `script`-content rest, the
|
|
447
|
-
**driver** (`bin/gtd`, or any loop harness) executes the emitted `content`
|
|
448
|
-
verbatim via `bash -c` — foreground, inherited stdio, exit code deliberately
|
|
449
|
-
ignored (a check script encodes its outcome in the tree, e.g. writing a findings
|
|
450
|
-
file, never in its exit status) — then runs `gtd step <actor>` for that state's
|
|
451
|
-
own actor to capture the outcome. See [Driving the loop](loop.md).
|
|
452
|
-
|
|
453
|
-
## `gtd status [--json]`
|
|
454
|
-
|
|
455
|
-
Pure, read-only dry-run reporter — the same resolution `gtd next` performs, but
|
|
456
|
-
reporting the resolved state/actor and, for every pending change, which declared
|
|
457
|
-
`on` pattern (if any) matches it — no mutation, and no CONTENT rendering (the
|
|
458
|
-
`script`/`prompt`/`message`/`commit` template is never rendered here, unlike
|
|
459
|
-
`gtd next`). It DOES render the resolved state's `model:`/`memory:`/`file:`
|
|
460
|
-
hints (if declared) through the same `it.vars`-carrying template context
|
|
461
|
-
`gtd next` uses — see
|
|
462
|
-
[Configuration](configuration.md#model--the-opaque-harness-hint-template-rendered)
|
|
463
|
-
— so a templated `model:`/`memory:`/`file:` failing to render fails `gtd status`
|
|
464
|
-
too, exactly like it would fail `gtd next`.
|
|
465
|
-
|
|
466
|
-
```
|
|
467
|
-
State: working
|
|
468
|
-
Awaits: agent
|
|
469
|
-
Pending:
|
|
470
|
-
A DONE.md -> A DONE.md
|
|
471
|
-
A scratch.txt -> (no match)
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
or, on a clean tree: `Pending: (clean)`. A `Model: <value>` line appears right
|
|
475
|
-
after `Awaits:` when the resolved state declares a `model:` hint, and
|
|
476
|
-
`Memory: <value>`/`File: <value>`/`Mode: <value>` lines appear after that (in
|
|
477
|
-
that order) when declared — each independently, only when set. A `Cost: <n>`
|
|
478
|
-
line appears after those when the current process has accumulated any
|
|
479
|
-
`Gtd-Cost:` (see [`gtd step --cost`](#gtd-step-actor---costn-model-name)),
|
|
480
|
-
omitted when the running total is `0`; when the breakdown adds information (more
|
|
481
|
-
than one model, or a single tagged model), indented ` <model>: <cost>` lines
|
|
482
|
-
follow it.
|
|
483
|
-
|
|
484
|
-
`--json` emits
|
|
485
|
-
`{state, actor, changes: [{status, path, pattern}], model?, memory?, file?, mode?, cost?, costByModel?, edges?}`
|
|
486
|
-
— `pattern` is `null` when no declared row matches that change;
|
|
487
|
-
`model`/`memory`/`file`/`mode` are present only when the resolved state declares
|
|
488
|
-
them; `cost`/`costByModel` (the `[{model, cost}]` breakdown) only when the
|
|
489
|
-
running process total is above `0`; and `edges` is the resting state's `on`
|
|
490
|
-
edges as `[{ pattern, target, describe? }]` (same as `gtd next --json`), omitted
|
|
491
|
-
when the state has no `on` (all omitted entirely, never `null`, otherwise):
|
|
492
|
-
|
|
493
|
-
```json
|
|
494
|
-
{
|
|
495
|
-
"state": "working",
|
|
496
|
-
"actor": "agent",
|
|
497
|
-
"changes": [
|
|
498
|
-
{ "status": "A", "path": "DONE.md", "pattern": "A DONE.md" },
|
|
499
|
-
{ "status": "A", "path": "scratch.txt", "pattern": null }
|
|
500
|
-
]
|
|
501
|
-
}
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
`gtd status` takes no arguments — extra positional args are rejected.
|
|
505
|
-
|
|
506
|
-
## `gtd validate [--json]`
|
|
507
|
-
|
|
508
|
-
Format **and** validate the steering file the resolved rest declares. It
|
|
509
|
-
resolves the current state exactly like `gtd status`, renders that state's
|
|
510
|
-
`file:`, formats that file in place, then validates it — both per its `mode:`:
|
|
511
|
-
|
|
512
|
-
- **formatting** happens only if the mode declares a `format:` shell command
|
|
513
|
-
(see [Configuration](configuration.md#modes--pluggable-steering-file-modes)) —
|
|
514
|
-
gtd ships no formatter, so nothing is rewritten until a project plugs one in;
|
|
515
|
-
- **validation** runs the mode's `validate:` command when it declares one (its
|
|
516
|
-
output becomes the findings), and otherwise, for the built-in `qa`/`review`
|
|
517
|
-
names, gtd's own pure parser (`src/OpenQuestions.ts` / `src/ReviewDoc.ts` —
|
|
518
|
-
the same parsers the LSP publishes as diagnostics, so there is one source of
|
|
519
|
-
truth per format).
|
|
520
|
-
|
|
521
|
-
Then:
|
|
522
|
-
|
|
523
|
-
- A well-formed file exits `0` (`<file>: valid`, or `{"valid":true, ...}` with
|
|
524
|
-
`--json`) — and is left formatted, if the mode formats at all.
|
|
525
|
-
- Violations exit **non-zero** with the findings, one per line — the signal a
|
|
526
|
-
producing agent, or the driving loop, loops on until the file is well-formed.
|
|
527
|
-
- A state that declares no `file:`/`mode:`, or whose file is **absent** (e.g.
|
|
528
|
-
`building` deleted `.gtd/TODO.md`, or a human deleted `.gtd/REVIEW.md` to
|
|
529
|
-
approve), has nothing to validate and exits `0`
|
|
530
|
-
(`nothing to validate at "<state>"`). Nothing is formatted in that case.
|
|
531
|
-
|
|
532
|
-
This is how the unified template keeps its steering files well-formed without an
|
|
533
|
-
in-machine validation state — and the check runs whoever last touched the file,
|
|
534
|
-
agent or human:
|
|
535
|
-
|
|
536
|
-
- **The producing agent self-validates.** Plain `gtd next` appends a "run
|
|
537
|
-
`gtd validate` and fix all violations" instruction to a `prompt` rest that
|
|
538
|
-
declares `file:`+`mode:`; `gtd next --json` withholds it and the driving loop
|
|
539
|
-
runs `gtd validate` after the turn instead (see `bin/gtd` /
|
|
540
|
-
[STATES.md §12](../STATES.md#12-steering-file-validation-gtd-validate)).
|
|
541
|
-
- **`gtd step` enforces the same gate.** Capturing a turn out of a state that
|
|
542
|
-
declares `file:`+`mode:` formats that file in place and validates it first
|
|
543
|
-
(with the very same mode commands), and **refuses the step** (committing
|
|
544
|
-
nothing) when it is invalid — so a human's edit at a gate (answering at
|
|
545
|
-
`adv-grilling-answer`, reviewing at `await-review`) is formatted and checked
|
|
546
|
-
exactly like an agent's draft, and a malformed steering file is never
|
|
547
|
-
committed.
|
|
548
|
-
|
|
549
|
-
`gtd validate` takes no arguments.
|
|
550
|
-
|
|
551
|
-
## `gtd lsp`
|
|
552
|
-
|
|
553
|
-
Starts an LSP server over stdio for `.gtd/` steering files — document symbols
|
|
554
|
-
for a `qa`-mode file's open questions and, for a `review`-mode file, one symbol
|
|
555
|
-
per chunk that still has an unchecked hunk (the outline lists only the packages
|
|
556
|
-
left to review, with no hunk children), code actions to check/uncheck a hunk or
|
|
557
|
-
a whole chunk, go-to-definition (`textDocument/definition`) from a `review`-mode
|
|
558
|
-
hunk pointer line into the file it points at (at its 1-based `#line`, or the top
|
|
559
|
-
of the file for a bare `./path`; the `./`-relative path resolves against the
|
|
560
|
-
repo's git toplevel), and diagnostics publishing the same parser findings
|
|
561
|
-
`gtd validate` reports (see `src/OpenQuestions.ts` / `src/ReviewDoc.ts` and
|
|
562
|
-
[STATES.md §12](../STATES.md#12-steering-file-validation-gtd-validate)).
|
|
563
|
-
|
|
564
|
-
**Config-driven** (see
|
|
565
|
-
[docs/design/state-file-association.md](design/state-file-association.md)): the
|
|
566
|
-
server locates the active gtd config the same way the CLI does, from the
|
|
567
|
-
`initialize` request's workspace root (falling back to the open document's own
|
|
568
|
-
directory), renders every state's `file:` into an absolute-path → `mode` map,
|
|
569
|
-
and dispatches on it — first declaring state wins a path conflict. A path the
|
|
570
|
-
map doesn't cover (or no config at all) falls back to the basename dispatch
|
|
571
|
-
(`TODO.md` → `qa`, `REVIEW.md` → `review`), so the server still works standalone
|
|
572
|
-
with no `.gtdrc` in sight. Also registers an `executeCommand`,
|
|
573
|
-
`gtd.openSteeringFile`: resolves the current state exactly like `gtd status`
|
|
574
|
-
(config + git HEAD) and asks the client to show its `file:`
|
|
575
|
-
(`window/showDocument`); a state with no `file:` gets an informational message
|
|
576
|
-
naming the state instead — bind it to an editor keybinding for a "jump to the
|
|
577
|
-
active steering file" command.
|
|
578
|
-
|
|
579
|
-
Dispatched before the repository-root guard and the config-reading path — the
|
|
580
|
-
server needs no git/workflow state of its own (like `gtd init`, it needs no
|
|
581
|
-
config to run). Rejects `--json` (exit 1, `gtd lsp does not accept --json`) and
|
|
582
|
-
extra positional arguments — it's a long-running server, not a state command.
|
|
583
|
-
Runs until the client disconnects (the LSP `exit` notification), then exits
|
|
584
|
-
cleanly.
|
|
585
|
-
|
|
586
|
-
## `gtd visualize [--port=<n>] [--no-open] [--json]`
|
|
587
|
-
|
|
588
|
-
Serve an interactive diagram of the ACTIVE workflow on a local web server: the
|
|
589
|
-
main flow as a graph (each sub-machine invocation collapsed into a single opaque
|
|
590
|
-
black-box node — click it to jump to that sub-machine's own diagram, rendered
|
|
591
|
-
separately below with its true member states/shapes/colours and a muted ghost
|
|
592
|
-
node for any edge leaving the group; every diagram supports scroll-to-zoom,
|
|
593
|
-
drag-to-pan, and a corner `+`/`−`/fit control cluster), a click-through
|
|
594
|
-
inspector with each state's actor, content kind, its own raw
|
|
595
|
-
prompt/message/script text, model/memory, steering file+mode, retry, flags, and
|
|
596
|
-
outgoing/incoming edges, and — read ONCE at page load, never polled — a "Current
|
|
597
|
-
state" panel showing where the active process rests, its pending changes, and
|
|
598
|
-
which `on` pattern (or retry redirect) currently leads where, with the resting
|
|
599
|
-
node highlighted in the diagrams. This is the replacement for the removed
|
|
600
|
-
`gtd mermaid` — a live viewer instead of a static diagram dump.
|
|
601
|
-
|
|
602
|
-
```
|
|
603
|
-
$ gtd visualize
|
|
604
|
-
gtd visualize running at http://127.0.0.1:53017 — Ctrl-C to stop
|
|
605
|
-
```
|
|
606
|
-
|
|
607
|
-
The server serves three routes: `/` (the self-contained HTML page),
|
|
608
|
-
`/workflow.json` (the model the page renders), and `/state.json` (the current
|
|
609
|
-
process's resting state, or `{}` when there isn't one — not a repo, no commits,
|
|
610
|
-
or an older server; the browser tolerates either). It runs until interrupted
|
|
611
|
-
(Ctrl-C), then closes cleanly. Options (orthogonal, `gtd visualize` only):
|
|
612
|
-
|
|
613
|
-
- `--port=<n>` (or `--port <n>`) — serve on a specific port (0–65535); the
|
|
614
|
-
default is a free ephemeral port, printed on start.
|
|
615
|
-
- `--no-open` — do not open the default browser (the URL is always printed).
|
|
616
|
-
- `--json` — print the workflow model to stdout and exit WITHOUT starting a
|
|
617
|
-
server (unchanged shape — live state is a server-only concern). The model is
|
|
618
|
-
`{ states, initial, groups, vars }`; each state carries its
|
|
619
|
-
`actor`/`kind`/`content`/`model`/`memory`/`file`/`mode`/`retry`/`flags`
|
|
620
|
-
(`content` is the state's own raw script/prompt/message text, omitted for a
|
|
621
|
-
commit state), its `on` edges, its computed `incoming` edges, and its
|
|
622
|
-
sub-machine `group`. `groups` lists each sub-machine invocation and the
|
|
623
|
-
concrete states it produced.
|
|
624
|
-
|
|
625
|
-
Dispatched before the repository-root guard and the config-reading path's review
|
|
626
|
-
window — it reads the active workflow (the built-in default when none is
|
|
627
|
-
configured) but touches no git/HEAD/review-window state ITSELF; the
|
|
628
|
-
`/state.json` route best-effort reads git state per request instead (any failure
|
|
629
|
-
— not a repo, no commits — serves `{}`), preferring the review checkout window's
|
|
630
|
-
saved head over HEAD so a request landing mid-window still reports the state the
|
|
631
|
-
process actually rests at. The diagram is rendered with Mermaid loaded from a
|
|
632
|
-
CDN, so the graph needs network access the first time a browser loads the page;
|
|
633
|
-
the inspector and current-state panel work offline regardless. Rejects unknown
|
|
634
|
-
options and unexpected positional arguments.
|
|
635
|
-
|
|
636
|
-
## Error envelope
|
|
637
|
-
|
|
638
|
-
Every command, in `--json` mode, reports a failure as a machine-readable
|
|
639
|
-
envelope on **stdout**, and still exits 1:
|
|
640
|
-
|
|
641
|
-
```json
|
|
642
|
-
{ "state": "error", "prompt": "<message>" }
|
|
643
|
-
```
|
|
644
|
-
|
|
645
|
-
A human-readable `gtd: <message>` line is still written to **stderr** regardless
|
|
646
|
-
of `--json` — the envelope adds a structured stdout channel, it does not replace
|
|
647
|
-
the plain-text one.
|
|
648
|
-
|
|
649
|
-
## Repository requirements
|
|
650
|
-
|
|
651
|
-
- **Single writer, linear branch.** A process's history is walked via
|
|
652
|
-
**first-parent** commits only.
|
|
653
|
-
- **Test/build artifacts must be gitignored.** This is **load-bearing**, not a
|
|
654
|
-
style preference: every step decision detects "clean" via
|
|
655
|
-
`git diff --name-status HEAD` (tracked changes) unioned with
|
|
656
|
-
`git ls-files --others --exclude-standard` (untracked files), which silently
|
|
657
|
-
omits anything matched by `.gitignore`. If a `script` state's command (or the
|
|
658
|
-
build it triggers) writes tracked-but-untracked output — a `dist/`, a coverage
|
|
659
|
-
report, a log file — into the working tree, the tree never goes clean after a
|
|
660
|
-
green run, and the check's `"C"` pattern never fires. Gitignore every path
|
|
661
|
-
your scripts write before wiring gtd into a repo.
|
|
662
|
-
- **Repository root invocation.** Every state subcommand (`step`/`review`/
|
|
663
|
-
`next`/`status`) must run from the git repository root — the workflow, pending
|
|
664
|
-
changes, and process history are resolved against the process cwd.
|
|
665
|
-
`--help`/`--version` (and the `help`/`version` subcommands), `lsp`, and
|
|
666
|
-
`visualize` skip this guard entirely (`visualize` still reads the `.gtdrc`
|
|
667
|
-
workflow, but needs no git state).
|
|
668
|
-
- **Linked worktrees are independent.** N `git worktree` worktrees of one
|
|
669
|
-
repository (sharing a single `.git`) each run their own gtd process: state is
|
|
670
|
-
derived from that worktree's own HEAD, and the review checkout window's refs
|
|
671
|
-
live in git's per-worktree `refs/worktree/gtd/*` namespace, so a review
|
|
672
|
-
resting in one worktree neither blocks nor rewrites any other
|
|
673
|
-
([STATES.md §11](../STATES.md#11-the-review-checkout-window)). This holds from
|
|
674
|
-
7.2 on; gtd ≤ 7.1 kept the window under the shared `refs/gtd/*` refs, where
|
|
675
|
-
the first worktree to open one clobbered every sibling's branch.
|