@pmelab/gtd 7.11.2 → 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,61 +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.
111
- - **`gtd edit [path]`** — open `<path>` (or, with no argument, the current
112
- resting state's steering file, or the repo dir) in `${VISUAL:-$EDITOR}`,
113
- blocking until it exits. Low-level plumbing — for "force an edit at the
114
- current human gate, then keep driving", pass `--edit` to the loop instead (see
115
- below).
116
-
117
- `gtd version` (or `gtd --version`/`-v`) prints the installed version and exits;
118
- `gtd help` (or `gtd --help`/`-h`) prints the command list. Both short-circuit
119
- before any repo work, so they run anywhere.
79
+ template), with an ordered set of change-patterns routing to the next state.
120
80
 
121
81
  The loop is one beat, repeated: run `gtd next --json` and dispatch on `kind` —
122
82
  `"message"` means it's a human's move (stop and hand off); `"script"` means the
123
83
  driver runs `content` itself, then steps its actor; `"prompt"` means feed
124
84
  `content` to your agent, then run `gtd step <actor>` once it's done. gtd itself
125
- never executes anything — the driver owns running scripts. See
126
- [STATES.md](STATES.md) for the model and [Driving the loop](docs/loop.md) for
127
- 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.
128
94
 
129
95
  The unified workflow has **entry points behind a green-baseline gate, into one
130
96
  shared tail**. Every entry first runs your test suite and only starts once it's
@@ -160,93 +126,406 @@ dropped — a build turn that addresses nothing is refused). Ticking every box
160
126
  with no comment is the sign-off, which collapses the whole cycle into one commit
161
127
  (a **squash finale** whose message an agent drafts). Stepping with a box still
162
128
  unticked and no comment is refused (finish reviewing first), as is deleting
163
- `.gtd/REVIEW.md`. The same review tail also has a direct entry point —
164
- `gtd review <commitish>` starts a brand new process reviewing
165
- `<commitish>..HEAD` with no cycle of its own, e.g. a colleague's PR branch. Its
166
- squash keeps and describes only the fixes made _during_ the review (not the
167
- reviewed changeset); a clean sign-off with no fixes becomes an empty
168
- `chore: human review` commit. A fourth entry, `gtd fix`, starts from a clean
169
- `idle` and goes straight into repairing a red baseline — repair, review, and
170
- squash into one commit. If the suite is already green there is nothing to fix,
171
- and the log is left untouched — no commit is left behind. See
172
- [STATES.md](STATES.md#10-the-bundled-workflow-template) for the full shape. The
173
- workflow is just `.gtdrc` config — edit it or write your own (see
174
- [Configuration](docs/configuration.md)). Every agent state routes its model
175
- through two `vars` tiers — `plannerModel` (heavier planning and review) and
176
- `coderModel` (the coding turns) — so you can repoint the models globally in one
177
- place (a `vars:` edit or a `GTD_PLANNERMODEL` override) instead of per state.
178
- Steering-file path vars (`feedbackFile`, `reviewFile`, …) work the same way, and
179
- now propagate to the `on` patterns that route on them too — a repointed path var
180
- actually reroutes the machine, not just the templates that read/write the file.
181
- A separate `stateDir` var (default `.gtd`) names only where the check scripts
182
- keep their own scratch/bookkeeping, independent of the per-file vars — relocate
183
- 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
184
277
 
185
278
  Bare `gtd` (or `gtd loop`) is a ready-to-run driver for the whole protocol —
186
- point it at a repo and it runs the loop until it's your turn. It is the only
187
- command you run: at a human gate it now opens `${VISUAL:-$EDITOR}` on the gate's
188
- file for you automatically (answer a plan question, tick a review box, fix
189
- code), waits for you to save and exit, then captures your edit itself and keeps
190
- driving — or halts if you left nothing changed — so you never run
191
- `gtd step human` by hand. Pass `--no-edit` (or set `GTD_NO_EDIT`) to fall back
192
- to halting and printing the gate instead, if you'd rather edit and re-launch it
193
- yourself; pass `--edit`/`-e` to force the editor open at the gate right now,
194
- overriding an ambient `GTD_NO_EDIT`/`--no-edit`. Pass `--once` to restrict a run
195
- to exactly one beat — one human gate, one check, or one agent turn — instead of
196
- driving all the way to idle; it combines freely with `--edit`/`--no-edit`. Pass
197
- `--no-notify` (or set `GTD_NO_NOTIFY`) to suppress Herdr desktop notifications
198
- while keeping Herdr sidebar state reporting on. Bare `gtd` prints one line per
199
- event — colored and emoji on a real terminal, plain ASCII under `NO_COLOR` or
200
- when piped — and redirects the noisier agent/check/step subprocess output to a
201
- per-repo/per-worktree log file. `gtd log` opens that logfile in your editor. See
202
- [Driving the loop](docs/loop.md).
203
-
204
- Before wiring gtd into a repo, note the
205
- [repository requirements](docs/cli.md#repository-requirements) — most
206
- importantly: gitignore everything your scripts write.
207
-
208
- Editor integration: `gtd lsp` starts an LSP server over stdio for `.gtd/`
209
- steering files — a symbol per `review`-mode chunk that still has an unchecked
210
- hunk (an outline of the packages left to review) plus check/uncheck actions over
211
- those chunks, go-to-definition from a `review`-mode hunk line into the file it
212
- points at (at its `#line`), symbols over a `qa`-mode file's open questions,
213
- diagnostics for both (live as you edit), and a `gtd.openSteeringFile` command
214
- that jumps to the current state's steering file. Config-driven via each state's
215
- `file:`/`mode:` (see [CLI reference](docs/cli.md#gtd-lsp)) — falls back to
216
- basename dispatch (`REVIEW.md` → `review`) with no config in sight. `qa` and
217
- `review` are gtd's built-in steering-file MODES with a VALIDATOR gtd itself
218
- implements; a mode's `format:` and `validate:` are shell commands a workflow (or
219
- a project's `.gtdrc`) declares for itself, so you bring your own formatter and
220
- your own checkers (see
221
- [Configuration](docs/configuration.md#modes--pluggable-steering-file-modes)). A
222
- third built-in, `prose` — format-only, no validator, used by the simple flow's
223
- plan file — has no live editor support: `gtd lsp` publishes no symbols or
224
- diagnostics for it, though `gtd validate` and the `gtd step` gate still format
225
- and validate it like any other mode. Both halves are enforced by `gtd validate`
226
- and the `gtd step` gate.
227
-
228
- Herdr integration: a workflow state can declare an optional `label:` — a
229
- human-readable display name surfaced in `gtd next --json`/`gtd status`. The
230
- reference `bin/gtd` driver uses it to report its lifecycle
231
- (working/blocked/idle) to a [Herdr](https://herdr.dev) pane sidebar via the
232
- `herdr` CLI when running under Herdr (`HERDR_ENV=1`, a pane ID, and `herdr` on
233
- `$PATH`); outside Herdr this is a complete no-op. See
234
- [Driving the loop](docs/loop.md#herdr-integration-optional) for the full
235
- reporting contract.
236
-
237
- ## Documentation
238
-
239
- - [STATES.md](STATES.md) — the full pattern-machine specification: the model,
240
- the pattern grammar, resolution, retry, the squash lifecycle, reusable
241
- sub-machines, and the bundled workflow template
242
- - [CLI reference](docs/cli.md) — every command, exit codes, JSON schemas,
243
- repository requirements
244
- - [Driving the loop](docs/loop.md) — the reference loop driver,
245
- `gtd`/`gtd loop`, custom agents
246
- - [Configuration](docs/configuration.md) — `gtd init`, the `.gtdrc` `workflow:`
247
- schema, lookup
248
- - [Upgrading](docs/upgrading.md) — breaking changes and migration
249
- - [Development](docs/development.md) — building, testing, releasing
279
+ point it at a repo and it runs the loop until it's your turn. It drives the
280
+ autonomous states (agent turns, check runs) and stops at the first
281
+ non-autonomous one: reaching a human gate it prints the gate and exits. You act
282
+ by editing files (answer a plan question, tick a review box, fix code) and
283
+ re-launching it — its opening move captures whatever you left, so you never run
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`).
296
+
297
+ A workflow state can declare an optional `label:` — a human-readable display
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.
250
529
 
251
530
  ## License
252
531