@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 CHANGED
@@ -70,55 +70,27 @@ review and commit the file before your first `gtd step`. `gtd init` takes no
70
70
  argument and refuses to clobber an existing config; it may also run in a plain
71
71
  parent directory (not a git repo) to seed a shared config a nested repo picks
72
72
  up. To customize the machine itself, add a `workflow:` key (there is no default
73
- fallback to merge over — a `workflow:` is the whole definition). See
74
- [Configuration](docs/configuration.md#gtd-init) for the details.
73
+ fallback to merge over — a `workflow:` is the whole definition).
75
74
 
76
75
  ## How it works
77
76
 
78
77
  gtd is a small **pattern machine**: named states, each awaiting one actor and
79
78
  carrying one piece of content (a script, a prompt, a message, or a squash commit
80
- template), with an ordered set of change-patterns routing to the next state. A
81
- handful of commands drive it:
82
-
83
- - **`gtd step <actor>`** — authenticate as `<actor>` and perform the one
84
- transition the pending changes match.
85
- - **`gtd next [--json]`** — print whichever actor is awaited and what they
86
- should do, without mutating anything.
87
- - **`gtd status`** — a dry-run report of the resolved state and which pattern
88
- each pending change matches.
89
- - **`gtd review <commitish>`** — start a brand new review process reviewing
90
- `<commitish>..HEAD` (e.g. a colleague's PR branch), reusing the workflow's
91
- existing review/feedback machinery over that diff.
92
- - **`gtd fix`** — start a brand new process that goes straight into repairing
93
- the current failing tests, then runs the shared review/squash tail. If the
94
- suite is already green there is nothing to fix, and the log is left untouched
95
- — no commit is left behind.
96
- - **`gtd abandon`** — end the process underway without completing it: rewind to
97
- the commit it started from, keeping everything it produced as uncommitted
98
- changes (nothing is discarded).
99
- - **`gtd restore`** — undo the last squash (or `gtd abandon`) by hard-resetting
100
- HEAD back to its retained pre-squash tip, bringing the turn-by-turn history
101
- back. Refuses on a dirty working tree, when there is nothing retained to
102
- restore, or when HEAD has since moved past it with commits that would be lost.
103
- - **`gtd visualize`** — serve an interactive diagram of the active workflow on a
104
- local web server: the main flow (each sub-machine collapsed to one box, with
105
- its own diagram below — pan/zoom with scroll, drag, or the corner controls),
106
- per-state details including the state's own raw prompt/message/ script text,
107
- and a "Current state" panel showing where the active process rests, its
108
- pending changes, and which action leads where. The panel and diagram highlight
109
- refresh live (~every 3s) while the page is open, so advancing the process
110
- elsewhere shows up without a manual refresh. `gtd version` (or
111
- `gtd --version`/`-v`) prints the installed version and exits; `gtd help` (or
112
- `gtd --help`/`-h`) prints the command list. Both short-circuit before any repo
113
- work, so they run anywhere.
79
+ template), with an ordered set of change-patterns routing to the next state.
114
80
 
115
81
  The loop is one beat, repeated: run `gtd next --json` and dispatch on `kind` —
116
82
  `"message"` means it's a human's move (stop and hand off); `"script"` means the
117
83
  driver runs `content` itself, then steps its actor; `"prompt"` means feed
118
84
  `content` to your agent, then run `gtd step <actor>` once it's done. gtd itself
119
- never executes anything — the driver owns running scripts. See
120
- [STATES.md](STATES.md) for the model and [Driving the loop](docs/loop.md) for
121
- the full protocol.
85
+ never executes anything — the driver owns running scripts.
86
+
87
+ An `on` edge may also carry a short imperative `action` (e.g. `Accept plan`)
88
+ alongside its existing `describe` sentence — a human-facing name for the choice
89
+ itself, not just the underlying glob pattern. `gtd status` (plain and `--json`)
90
+ and `gtd visualize`'s diagram and inspector all render the two composed
91
+ together: the `action` leads when the edge declares one, with the raw pattern
92
+ (and `describe`) still shown alongside it, so a human choosing between routes
93
+ reads intent first, glob second.
122
94
 
123
95
  The unified workflow has **entry points behind a green-baseline gate, into one
124
96
  shared tail**. Every entry first runs your test suite and only starts once it's
@@ -154,27 +126,154 @@ dropped — a build turn that addresses nothing is refused). Ticking every box
154
126
  with no comment is the sign-off, which collapses the whole cycle into one commit
155
127
  (a **squash finale** whose message an agent drafts). Stepping with a box still
156
128
  unticked and no comment is refused (finish reviewing first), as is deleting
157
- `.gtd/REVIEW.md`. The same review tail also has a direct entry point —
158
- `gtd review <commitish>` starts a brand new process reviewing
159
- `<commitish>..HEAD` with no cycle of its own, e.g. a colleague's PR branch. Its
160
- squash keeps and describes only the fixes made _during_ the review (not the
161
- reviewed changeset); a clean sign-off with no fixes becomes an empty
162
- `chore: human review` commit. A fourth entry, `gtd fix`, starts from a clean
163
- `idle` and goes straight into repairing a red baseline — repair, review, and
164
- squash into one commit. If the suite is already green there is nothing to fix,
165
- and the log is left untouched — no commit is left behind. See
166
- [STATES.md](STATES.md#10-the-bundled-workflow-template) for the full shape. The
167
- workflow is just `.gtdrc` config — edit it or write your own (see
168
- [Configuration](docs/configuration.md)). Every agent state routes its model
169
- through two `vars` tiers — `plannerModel` (heavier planning and review) and
170
- `coderModel` (the coding turns) — so you can repoint the models globally in one
171
- place (a `vars:` edit or a `GTD_PLANNERMODEL` override) instead of per state.
172
- Steering-file path vars (`feedbackFile`, `reviewFile`, …) work the same way, and
173
- now propagate to the `on` patterns that route on them too — a repointed path var
174
- actually reroutes the machine, not just the templates that read/write the file.
175
- A separate `stateDir` var (default `.gtd`) names only where the check scripts
176
- keep their own scratch/bookkeeping, independent of the per-file vars — relocate
177
- one steering file without touching it.
129
+ `.gtd/REVIEW.md`.
130
+
131
+ The same review tail also has a direct entry point — `gtd review <commitish>`
132
+ starts a brand new process reviewing `<commitish>..HEAD` with no cycle of its
133
+ own, e.g. a colleague's PR branch. Its squash keeps and describes only the fixes
134
+ made _during_ the review (not the reviewed changeset); a clean sign-off with no
135
+ fixes becomes an empty `chore: human review` commit. A fourth entry, `gtd fix`,
136
+ starts from a clean `idle` and goes straight into repairing a red baseline —
137
+ repair, review, and squash into one commit. If the suite is already green there
138
+ is nothing to fix, and the log is left untouched — no commit is left behind.
139
+
140
+ Every agent state routes its model through two `vars` tiers — `plannerModel`
141
+ (heavier planning and review) and `coderModel` (the coding turns) — so you can
142
+ repoint the models globally in one place (a `vars:` edit or a `GTD_PLANNERMODEL`
143
+ override) instead of per state. Steering-file path vars (`feedbackFile`,
144
+ `reviewFile`, …) work the same way, and propagate to the `on` patterns that
145
+ route on them too — a repointed path var actually reroutes the machine, not just
146
+ the templates that read/write the file. A separate `stateDir` var (default
147
+ `.gtd`) names only where the check scripts keep their own scratch/bookkeeping,
148
+ independent of the per-file vars — relocate one steering file without touching
149
+ it.
150
+
151
+ To inspect or change the machine itself, see [Configuration](#configuration) —
152
+ the workflow is just `.gtdrc` config.
153
+
154
+ ## Commands
155
+
156
+ ```
157
+ Usage: gtd [command] [options]
158
+
159
+ Commands:
160
+ (no command), loop
161
+ Launch the loop driver (bin/gtd), which repeatedly drives
162
+ an agent through gtd next/gtd step calls until the
163
+ workflow rests at a human gate (a non-autonomous state)
164
+ or settles. A bare gtd invocation and gtd loop both
165
+ launch it identically
166
+ init Scaffold a minimal .gtdrc.json for this repo, seeding the
167
+ default variables you are most likely to change (the test
168
+ command) and a Prettier formatting suggestion. gtd runs its
169
+ built-in workflow by default, so no workflow is written —
170
+ add a workflow: key only to customize the machine itself.
171
+ Takes no argument. Run once per repo; refuses if a gtd
172
+ config already exists. Leaves the file uncommitted for you
173
+ to review and commit
174
+ step <actor> Authenticate as <actor>, match the resolved rest's
175
+ declared patterns against the pending changes, and commit
176
+ (or squash) the one resulting transition. Pass
177
+ --cost=<n> (optionally --model=<name>) to record the
178
+ just-finished invocation's token cost and model on the
179
+ turn commit (summed into it.processCost/processCostByModel)
180
+ review <commitish>
181
+ Start a NEW review process at the workflow's declared
182
+ review-entry state (reviewEntry: true), reviewing
183
+ <commitish>..HEAD — e.g. a colleague's PR branch. Requires
184
+ a clean tree resting at the workflow's initial state
185
+ fix Start a NEW process at the workflow's declared fix-entry
186
+ state (fixEntry: true) that goes straight into repairing the
187
+ current failing tests. Requires a clean tree resting at the
188
+ workflow's initial state
189
+ abandon End the process currently underway without completing it:
190
+ close any open review checkout window, then rewind HEAD to
191
+ the commit the process started from, keeping everything it
192
+ produced as uncommitted changes. A no-op when no process is
193
+ underway
194
+ restore Hard-reset HEAD back to the pre-squash tip retained by the
195
+ last squash/abandon (refs/worktree/gtd/history), undoing a
196
+ squash or bringing back an abandoned process's turns.
197
+ Refuses on a dirty working tree, when there is no retained
198
+ history, or when HEAD has advanced past the squash with
199
+ commits that would be lost
200
+ next Print the resolved rest's rendered script/prompt/message
201
+ (no mutation)
202
+ status Print the resolved rest's state/actor and which declared
203
+ pattern (if any) each pending change matches (no mutation)
204
+ validate Format and validate the steering file the resolved rest
205
+ declares, with its mode's commands (its file:/mode:);
206
+ exits non-zero with the findings when it is invalid
207
+ lsp Start the LSP server for .gtd/ steering files (stdio)
208
+ visualize Serve an interactive diagram of the active workflow on a
209
+ local web server (--port <n>, --no-open; --json prints the
210
+ model and exits)
211
+ version Print version and exit
212
+ help Print this help and exit
213
+
214
+ Options:
215
+ --json Output structured JSON instead of plain text
216
+ --port=<n> (gtd visualize only) port to serve on (default: a free port)
217
+ --no-open (gtd visualize only) do not open the browser
218
+ --cost=<n> (gtd step only) record the invocation's token cost
219
+ --model=<name> (gtd step only, with --cost) tag that cost's model
220
+ --once (bare gtd or gtd loop only) run exactly one loop beat (one
221
+ human-gate capture, one script check+step, or one agent
222
+ prompt+step), then exit
223
+ --version, -v Print version and exit
224
+ --help, -h Print this help and exit
225
+ ```
226
+
227
+ `--version` (`-v`) / `gtd version` and `--help` (`-h`) / `gtd help`
228
+ short-circuit before any git or repository-state work — they run outside a repo
229
+ and in any repo state. Bare `gtd` (no subcommand) and `gtd loop` both launch the
230
+ loop driver immediately — neither is a usage error. Any other, truly unknown
231
+ subcommand is a usage error: it prints the help text and exits 1 without
232
+ touching the repository. Every other (recognized) command must be run from the
233
+ **repository root** — gtd derives the workflow, pending changes, and process
234
+ history relative to cwd, so it refuses with a clear error if invoked from a
235
+ subdirectory.
236
+
237
+ `--json`, `--cost=<n>`, and `--model=<name>` (the latter two only for
238
+ `gtd step`) are the only long options the compiled bundle recognizes. Any other
239
+ `--` option (including a typo like `--jsn`) is rejected with a usage error
240
+ rather than silently ignored, so a mistyped flag can never degrade a JSON caller
241
+ to plain-text mode. A bare `--cost`/`--model` with no value, a non-numeric or
242
+ negative `--cost`, an empty `--model`, `--model` without `--cost`, or either
243
+ flag on any command other than `gtd step` are all usage errors.
244
+
245
+ `--once` is a separate, bash-level flag handled entirely by the `bin/gtd` driver
246
+ itself, stripped before anything reaches the bundle.
247
+
248
+ ### `gtd status`'s `Next:`/`next`
249
+
250
+ Both plain and `--json` output include a headline preview of what would happen
251
+ next: the first declared `on` edge whose pattern matches the pending changes AS
252
+ A WHOLE (the same first-match-wins semantics `gtd step` itself uses), using its
253
+ `action` when the edge declares one, else its raw pattern, alongside its target
254
+ state. Plain output prints a `Next: <action-or-pattern> → <target>` line (or
255
+ `Next: (no match — nothing would happen)`); `--json`'s `next` key mirrors it as
256
+ `{ action?, pattern, target }`, or `null` on no match.
257
+
258
+ This reports the **declared** route only: a capped `retry` may redirect
259
+ elsewhere at real step time, which `Next:`/`next` does not apply — it previews
260
+ what the declared `on` patterns would match, not a guarantee of where a real
261
+ `gtd step` lands.
262
+
263
+ ### Error envelope
264
+
265
+ Every command, in `--json` mode, reports a failure as a machine-readable
266
+ envelope on **stdout**, and still exits 1:
267
+
268
+ ```json
269
+ { "state": "error", "prompt": "<message>" }
270
+ ```
271
+
272
+ A human-readable `gtd: <message>` line is still written to **stderr** regardless
273
+ of `--json` — the envelope adds a structured stdout channel, it does not replace
274
+ the plain-text one.
275
+
276
+ ## Driving the loop
178
277
 
179
278
  Bare `gtd` (or `gtd loop`) is a ready-to-run driver for the whole protocol —
180
279
  point it at a repo and it runs the loop until it's your turn. It drives the
@@ -182,58 +281,251 @@ autonomous states (agent turns, check runs) and stops at the first
182
281
  non-autonomous one: reaching a human gate it prints the gate and exits. You act
183
282
  by editing files (answer a plan question, tick a review box, fix code) and
184
283
  re-launching it — its opening move captures whatever you left, so you never run
185
- `gtd step human` by hand. Anything richer at that boundary — opening your
186
- editor, desktop notifications, terminal-multiplexer status — is the job of an
187
- outer wrapper around `gtd`, not of the loop itself. Pass `--once` to restrict a
188
- run to exactly one beat — one human-gate capture, one check, or one agent turn —
189
- instead of driving all the way to idle. Bare `gtd` prints one line per event —
190
- colored and emoji on a real terminal, plain ASCII under `NO_COLOR` or when piped
191
- — and redirects the noisier agent/check/step subprocess output to a
192
- per-repo/per-worktree log file (its path is the run's first output line, ready
193
- to `tail -f`). See [Driving the loop](docs/loop.md).
194
-
195
- Before wiring gtd into a repo, note the
196
- [repository requirements](docs/cli.md#repository-requirements) — most
197
- importantly: gitignore everything your scripts write.
198
-
199
- Editor integration: `gtd lsp` starts an LSP server over stdio for `.gtd/`
200
- steering files — a symbol per `review`-mode chunk that still has an unchecked
201
- hunk (an outline of the packages left to review) plus check/uncheck actions over
202
- those chunks, go-to-definition from a `review`-mode hunk line into the file it
203
- points at (at its `#line`), symbols over a `qa`-mode file's open questions,
204
- diagnostics for both (live as you edit), and a `gtd.openSteeringFile` command
205
- that jumps to the current state's steering file. Config-driven via each state's
206
- `file:`/`mode:` (see [CLI reference](docs/cli.md#gtd-lsp)) — falls back to
207
- basename dispatch (`REVIEW.md` → `review`) with no config in sight. `qa` and
208
- `review` are gtd's built-in steering-file MODES with a VALIDATOR gtd itself
209
- implements; a mode's `format:` and `validate:` are shell commands a workflow (or
210
- a project's `.gtdrc`) declares for itself, so you bring your own formatter and
211
- your own checkers (see
212
- [Configuration](docs/configuration.md#modes--pluggable-steering-file-modes)). A
213
- third built-in, `prose` — format-only, no validator, used by the simple flow's
214
- plan file — has no live editor support: `gtd lsp` publishes no symbols or
215
- diagnostics for it, though `gtd validate` and the `gtd step` gate still format
216
- and validate it like any other mode. Both halves are enforced by `gtd validate`
217
- and the `gtd step` gate.
284
+ `gtd step human` by hand.
285
+
286
+ Anything richer at that boundary — opening your editor, desktop notifications,
287
+ terminal-multiplexer status — is the job of an outer wrapper around `gtd`, not
288
+ of the loop itself. Pass `--once` to restrict a run to exactly one beat — one
289
+ human-gate capture, one check, or one agent turn — instead of driving all the
290
+ way to idle.
291
+
292
+ Bare `gtd` prints one line per event — colored and emoji on a real terminal,
293
+ plain ASCII under `NO_COLOR` or when piped — and redirects the noisier
294
+ agent/check/step subprocess output to a per-repo/per-worktree log file (its path
295
+ is the run's first output line, ready to `tail -f`).
218
296
 
219
297
  A workflow state can declare an optional `label:` — a human-readable display
220
- name surfaced in `gtd next --json`/`gtd status`. The reference `bin/gtd` driver
221
- uses it for its per-beat progress lines; an outer wrapper (a terminal
222
- multiplexer, a notifier) can use it the same way.
223
-
224
- ## Documentation
225
-
226
- - [STATES.md](STATES.md) — the full pattern-machine specification: the model,
227
- the pattern grammar, resolution, retry, the squash lifecycle, reusable
228
- sub-machines, and the bundled workflow template
229
- - [CLI reference](docs/cli.md) — every command, exit codes, JSON schemas,
230
- repository requirements
231
- - [Driving the loop](docs/loop.md) — the reference loop driver,
232
- `gtd`/`gtd loop`, custom agents
233
- - [Configuration](docs/configuration.md) — `gtd init`, the `.gtdrc` `workflow:`
234
- schema, lookup
235
- - [Upgrading](docs/upgrading.md) — breaking changes and migration
236
- - [Development](docs/development.md) — building, testing, releasing
298
+ name surfaced in `gtd next --json`/`gtd status`. The driver uses it for its
299
+ per-beat progress lines; an outer wrapper (a terminal multiplexer, a notifier)
300
+ can use it the same way.
301
+
302
+ ## Configuration
303
+
304
+ gtd reads an optional `.gtdrc` config file via
305
+ [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig). With no `workflow:`
306
+ configured anywhere in the cwd→home config chain, the bundled unified workflow
307
+ is used automatically, so a state command works out of the box with no config at
308
+ all. Supported filenames (searched in this order):
309
+
310
+ - `.gtdrc`
311
+ - `.gtdrc.json`
312
+ - `.gtdrc.yaml`
313
+ - `.gtdrc.yml`
314
+ - `gtd.config.json`
315
+ - `gtd.config.yaml`
316
+
317
+ ### Schema
318
+
319
+ `.gtdrc` has exactly three blessed top-level keys:
320
+
321
+ - **`workflow`** (object, optional) — the whole machine definition (its states,
322
+ plus its own `vars:` defaults and `modes:`). Absent = gtd's built-in default
323
+ is used. Declare it to fully REPLACE that default with your own machine (there
324
+ is no `extends`/merge).
325
+ - **`vars`** (object, optional) — a flat `name -> scalar` map, one layer of the
326
+ merged `it.vars` every template sees.
327
+ - **`modes`** (object, optional) — steering-file modes (`format:`/`validate:`
328
+ shell commands), layered over the active workflow's own `modes:` and gtd's
329
+ built-in validators, so a project can plug in its formatter or linter without
330
+ re-declaring that mode on the workflow itself.
331
+ - **`$schema`** (string, optional) — stripped before validation, so it never
332
+ counts as an unknown key. Point it at the published schema for editor-backed
333
+ autocompletion (this is what `gtd init` writes):
334
+
335
+ ```
336
+ https://cdn.jsdelivr.net/npm/@pmelab/gtd/schema.json
337
+ ```
338
+
339
+ That URL serves `schema.json` straight out of the published npm tarball, so it
340
+ always matches the latest release. Pin it to a major with
341
+ `@pmelab/gtd@8/schema.json`, or point at your own install
342
+ (`./node_modules/@pmelab/gtd/schema.json`) to work offline.
343
+
344
+ Any other top-level key is **rejected**. The engine blesses no VARIABLE NAMES
345
+ either — `testCommand` is workflow-authored data like any other `it.vars` entry,
346
+ not a special key gtd interprets.
347
+
348
+ ### The `workflow:` key
349
+
350
+ A declared `workflow:` key fully REPLACES gtd's built-in default. The built-in
351
+ default is itself a YAML asset (`src/workflows/unified.yaml`) compiled through
352
+ the exact same compiler your own `workflow:` value goes through — no privileged
353
+ code path. Its shape:
354
+
355
+ ```yaml
356
+ workflow:
357
+ vars: # optional — the workflow's own declared `it.vars` defaults
358
+ anyKey: anyScalarValue
359
+ modes: # optional — steering-file modes a state's `mode:` may name
360
+ <name>:
361
+ format: <shell command> # at least one of format/validate
362
+ validate: <shell command>
363
+ states:
364
+ <name>:
365
+ actor: <string> # forbidden on a commit state, required otherwise
366
+ script: <string> # exactly one of script/prompt/message/commit
367
+ prompt: <string>
368
+ message: <string>
369
+ commit: <string>
370
+ on: # a mapping, DECLARATION ORDER PRESERVED
371
+ "<pattern>": <targetState> # short form
372
+ "<pattern>": {
373
+ to: <targetState>,
374
+ describe: <sentence>,
375
+ action: <label>,
376
+ } # description/action
377
+ initial: true # exactly one state across the whole workflow
378
+ retry:
379
+ max: <number>
380
+ otherwise: <targetState>
381
+ model: <string> # optional, opaque harness hint — forbidden on a commit state
382
+ memory: <string> # optional, opaque memory-scope label — forbidden on a commit state
383
+ file: <string> # optional, an Eta template naming the state's steering file
384
+ mode: <modeName> # optional, requires "file" — a built-in (qa/review/prose) or a `modes:` entry
385
+ ```
386
+
387
+ Authoring or editing a workflow with a coding agent? `skills/authoring/SKILL.md`
388
+ is the agent-facing contract for producing a valid `workflow:` — the state
389
+ model, pattern grammar, load-time rules, and how to verify a change compiles.
390
+
391
+ ### Variables
392
+
393
+ Every template — `script`/`prompt`/`message`/`commit`, and
394
+ `model`/`memory`/`file` — sees `it.vars`: a flat `Record<string, string>`
395
+ assembled from three layers, **later wins**:
396
+
397
+ 1. **The workflow's own `vars:` key** (sibling to `states:`) — the workflow
398
+ author's declared defaults. The unified template declares
399
+ `vars: { testCommand: "npm test" }`, read by `checking`'s script as
400
+ `<%~ it.vars.testCommand %>`.
401
+ 2. **A top-level `.gtdrc` `vars:` key** (a sibling of `workflow:`, NOT nested
402
+ inside it) — per-repo tuning without redefining the whole workflow.
403
+ 3. **`GTD_<UPPERCASE-name>` environment variables** — highest precedence,
404
+ checked at every invocation, case-insensitively against each name already
405
+ declared by layer 1 or 2: `GTD_TESTCOMMAND` overrides `testCommand`. The
406
+ environment can only OVERRIDE a name a config layer already declared — a
407
+ `GTD_*` var matching no declared name is silently ignored.
408
+
409
+ Values in layers 1–2 must be YAML scalars (string/number/boolean), coerced to
410
+ strings at load time; an object or array value is a load error.
411
+
412
+ ```yaml
413
+ # .gtdrc — overriding the unified template's testCommand
414
+ vars:
415
+ testCommand: npm run test:ci
416
+ ```
417
+
418
+ ```bash
419
+ # highest precedence — beats both the workflow default and the .gtdrc value above
420
+ GTD_TESTCOMMAND="npm run test -- --bail" gtd next
421
+ ```
422
+
423
+ ### Lookup and precedence
424
+
425
+ gtd walks from the current working directory **up to your home directory** (or
426
+ to the filesystem root when cwd is outside home), collecting every `.gtdrc` it
427
+ finds along the way. All found levels are **deep-merged**, with the **innermost
428
+ (cwd) config winning** on conflicts — so a shared `.gtdrc` in a worktree-parent
429
+ directory cascades to every checkout beneath it, while any individual checkout
430
+ can still override with its own `.gtdrc`.
431
+
432
+ ### Validation and errors
433
+
434
+ Config-shape problems (unknown keys, wrong types, unreadable file references)
435
+ are collected together; if the shape is clean, the assembled definition is
436
+ additionally run through the engine's own validation. A bad config throws
437
+ **one** error listing every finding, at load time — before anything touches the
438
+ repository — never partially, and never deferred to step time:
439
+
440
+ ```
441
+ workflow config:
442
+ - state "idle": must declare exactly one of script/prompt/message/commit (found 2)
443
+ - state "idle": "on" target "nowhere" is not a defined state
444
+ ```
445
+
446
+ Those findings include the **semantic graph checks**: every `on` target and
447
+ `retry.otherwise` must name a defined state, and every state must be
448
+ **reachable** from the initial state. All load failures exit **1** and write to
449
+ **stderr**, never stdout.
450
+
451
+ Many of these problems never reach gtd at all if your editor validates against
452
+ the [published schema](#schema), which fully types the `workflow:` key. The
453
+ rules JSON Schema cannot express — exactly one content kind, exactly one
454
+ `initial: true`, targets naming defined states, reachability — remain the
455
+ compiler's job at load time.
456
+
457
+ ## Repository requirements
458
+
459
+ - **Single writer, linear branch.** A process's history is walked via
460
+ **first-parent** commits only.
461
+ - **Test/build artifacts must be gitignored.** This is **load-bearing**, not a
462
+ style preference: every step decision detects "clean" via
463
+ `git diff --name-status HEAD` (tracked changes) unioned with
464
+ `git ls-files --others --exclude-standard` (untracked files), which silently
465
+ omits anything matched by `.gitignore`. If a `script` state's command (or the
466
+ build it triggers) writes output — a `dist/`, a coverage report, a log file —
467
+ into the working tree, the tree never goes clean after a green run, and the
468
+ check's `"C"` pattern never fires. Gitignore every path your scripts write
469
+ before wiring gtd into a repo.
470
+ - **Repository root invocation.** Every state subcommand must run from the git
471
+ repository root. `--help`/`--version` (and the `help`/`version` subcommands),
472
+ `lsp`, and `visualize` skip this guard entirely (`visualize` still reads the
473
+ `.gtdrc` workflow, but needs no git state).
474
+ - **Linked worktrees are independent.** N `git worktree` worktrees of one
475
+ repository (sharing a single `.git`) each run their own gtd process: state is
476
+ derived from that worktree's own HEAD, and the review checkout window's refs
477
+ live in git's per-worktree `refs/worktree/gtd/*` namespace, so a review
478
+ resting in one worktree neither blocks nor rewrites any other.
479
+
480
+ ## Editor integration
481
+
482
+ `gtd lsp` starts an LSP server over stdio for `.gtd/` steering files — a symbol
483
+ per `review`-mode chunk that still has an unchecked hunk (an outline of the
484
+ packages left to review) plus check/uncheck actions over those chunks,
485
+ go-to-definition from a `review`-mode hunk line into the file it points at (at
486
+ its `#line`), symbols over a `qa`-mode file's open questions, diagnostics for
487
+ both (live as you edit), and a `gtd.openSteeringFile` command that jumps to the
488
+ current state's steering file.
489
+
490
+ It is config-driven via each state's `file:`/`mode:`, and falls back to basename
491
+ dispatch (`REVIEW.md` → `review`) with no config in sight. `qa` and `review` are
492
+ gtd's built-in steering-file MODES with a VALIDATOR gtd itself implements; a
493
+ mode's `format:` and `validate:` are shell commands a workflow (or a project's
494
+ `.gtdrc`) declares for itself, so you bring your own formatter and your own
495
+ checkers. A third built-in, `prose` — format-only, no validator, used by the
496
+ simple flow's plan file — has no live editor support: `gtd lsp` publishes no
497
+ symbols or diagnostics for it, though `gtd validate` and the `gtd step` gate
498
+ still format and validate it like any other mode.
499
+
500
+ ## Development
501
+
502
+ ```bash
503
+ npm install
504
+ npm run dev # run from source, no build (node dev/run.mjs)
505
+ npm run build # tsdown → dist/gtd.bundle.mjs
506
+ npm test # format:check, typecheck, lint, unit + e2e tests, fallow
507
+ npm run test:unit # vitest unit tests (the pure resolver) — --project unit
508
+ npm run test:e2e # gherkin e2e via vitest + quickpickle — --project e2e
509
+ npm run test:mutation # StrykerJS mutation testing (manual only, ~10 min)
510
+ npm run typecheck
511
+ npm run lint
512
+ ```
513
+
514
+ A pre-commit hook is installed automatically via the `prepare` script when you
515
+ run `npm install` on a fresh clone — it runs
516
+ [lint-staged](https://github.com/lint-staged/lint-staged) with
517
+ [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html), mirroring the
518
+ `format:check` step enforced in CI.
519
+
520
+ The decision core is pure and IO-free: the pattern machine's shape (states,
521
+ patterns, retry) is a plain-data `WorkflowDefinition` (`src/PatternMachine.ts`),
522
+ and the same module's `resolveState`/`step` are the pure resolver/interpreter
523
+ over it — so the whole engine is trivially unit-testable in isolation. All
524
+ git/filesystem/template IO is confined to the edge (`src/Edge.ts`).
525
+
526
+ Releases are automatic: push releasable Conventional Commits (`fix:`, `feat:`,
527
+ or breaking changes) to `main` and semantic-release computes the next version,
528
+ builds the bundle, tags it, and publishes.
237
529
 
238
530
  ## License
239
531
 
package/bin/gtd CHANGED
@@ -247,7 +247,7 @@ fi
247
247
  # otherwise ($# -eq 0, or exactly "loop" with no further args, --once already
248
248
  # stripped above): fall through into the loop body below.
249
249
 
250
- # Drives the v3 pattern-machine loop (see docs/loop.md): each iteration asks
250
+ # Drives the v3 pattern-machine loop: each iteration asks
251
251
  # `gtd next --json` who's up and what they should do, dispatching on `kind`:
252
252
  # - "message" (a human rest) -> the non-autonomous halt: print the gate and
253
253
  # exit 0. Acting on it (opening an editor, notifying, whatever) is an
@@ -264,8 +264,7 @@ fi
264
264
  # adapter invoked at a "prompt" rest; the default adapter appends `--model
265
265
  # "$GTD_LOOP_MODEL"` only when it's non-empty.
266
266
  #
267
- # `.memory` (optional, opaque — see skills/loop/SKILL.md "Agent memory scope")
268
- # is the agent-memory scope label. gtd never interprets it; the driver does:
267
+ # `.memory` (optional, opaque) is the agent-memory scope label. gtd never interprets it; the driver does:
269
268
  # consecutive "prompt" turns emitting the SAME label continue ONE agent
270
269
  # session (so the agent still remembers its previous turn), and a changed
271
270
  # label — or the first turn, or an unset label — starts fresh. That is what
@@ -425,7 +424,7 @@ while true; do
425
424
  continue
426
425
  fi
427
426
 
428
- # kind == "prompt": stall detection (skills/loop/SKILL.md) — the same
427
+ # kind == "prompt": stall detection — the same
429
428
  # agent-owned state and content repeating, WITH NO COMMIT authored since the
430
429
  # last time we saw this beat, means the last dispatch made no progress; stop
431
430
  # rather than spin on it. The HEAD check is what distinguishes a genuine