@pmelab/gtd 8.0.0 → 8.2.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/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.