@pmelab/gtd 9.1.1 → 9.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.
Files changed (3) hide show
  1. package/README.md +169 -107
  2. package/dist/gtd.bundle.mjs +166 -85
  3. package/package.json +7 -4
package/README.md CHANGED
@@ -21,9 +21,10 @@ No chat scrollback. No lost sessions. No infinite fix loops. Just git.
21
21
  - **Shareable.** Push the branch, and the workflow travels with it — the state
22
22
  lives in the commits, so another machine (or another person) picks up exactly
23
23
  where you left off.
24
- - **Files, not chat.** Plans live in `.gtd/TODO.md`. Request changes by editing
25
- it, approve by leaving the tree clean — all in your own editor. There is no
26
- chat UI to lose.
24
+ - **Files, not chat.** Plans live in `.gtd/` steering files (`REQUIREMENTS.md`,
25
+ `ARCHITECTURE.md`, the package files under `.gtd/packages/`). Request changes
26
+ by editing them, approve by leaving the tree clean — all in your own editor.
27
+ There is no chat UI to lose.
27
28
  - **Harness agnostic.** gtd emits prompts to stdout (or JSON). Claude Code, a
28
29
  bash loop, a CI job, or you reading it out loud — the workflow doesn't care
29
30
  who executes it.
@@ -61,17 +62,23 @@ gtd init
61
62
  This writes a minimal `.gtdrc.json` seeding the one variable most projects
62
63
  change — the test command (`vars.testCommand`, defaulting to `npm test`) — plus
63
64
  a top-level `modes:` block suggesting **Prettier** as the steering-file
64
- formatter (`npx prettier --write` for the built-in `qa`/`review`/`prose` modes —
65
- format only, so gtd still validates the `qa`/`review` ones; `prose`, used by the
66
- simple flow's plan file, has no validator to begin with); edit or drop either
67
- freely (point `testCommand` at your suite, swap Prettier for dprint or a script,
68
- delete a key). It writes **no** `workflow:` key — the machine is built in — so
69
- review and commit the file before your first `gtd land`. `gtd init` takes no
70
- argument and refuses to clobber an existing config; it may also run in a plain
71
- parent directory (not a git repo) to seed a shared config a nested repo picks
72
- up. To customize the machine itself, add a `workflow:` key (there is no default
65
+ formatter (`npx prettier --write` for the built-in `qa`/`review` modes — format
66
+ only, so gtd still validates them); edit or drop either freely (point
67
+ `testCommand` at your suite, swap Prettier for dprint or a script, delete a
68
+ key). It writes **no** `workflow:` key — the machine is built in — so review and
69
+ commit the file before your first `gtd land`. `gtd init` takes no argument and
70
+ refuses to clobber an existing config; it may also run in a plain parent
71
+ directory (not a git repo) to seed a shared config a nested repo picks up. To
72
+ customize the machine itself, add a `workflow:` key (there is no default
73
73
  fallback to merge over — a `workflow:` is the whole definition).
74
74
 
75
+ gtd requires a repository with **at least one commit** before any state command
76
+ (`land`, `--entry`, `next`, `status`, `abandon`, `restore`, `validate`) will run
77
+ — there is no workflow state to derive from an empty history. Committing the
78
+ `.gtdrc.json` above (or anything else) satisfies this by construction;
79
+ `gtd init`, `gtd install`, `gtd lsp`, `gtd visualize`, and `gtd check` are
80
+ unaffected since none of them derive workflow state.
81
+
75
82
  ## How it works
76
83
 
77
84
  gtd is a small **pattern machine**: named states, each awaiting one actor and
@@ -110,70 +117,96 @@ together: the `action` leads when the edge declares one, with the raw pattern
110
117
  (and `describe`) still shown alongside it, so a human choosing between routes
111
118
  reads intent first, glob second.
112
119
 
113
- The unified workflow has **entry points behind a green-baseline gate, into one
114
- shared tail**. Every entry first runs your test suite and only starts once it's
115
- green — you never build (or review) on top of a red baseline; a red run halts
116
- and tells you to repair it first (that's what `gtd --entry fix-precheck` is
117
- for). The two steering-file entries are chosen by which file you create:
118
-
119
- - Create **`.gtd/TODO.md`** with a short sketch to start the **simple** flow: an
120
- agent develops your sketch into a concrete plan — deciding open points itself
121
- rather than asking questions — and hands it back for you to accept as-is or
122
- edit. Editing sends it round again; accepting builds the plan in one turn and
123
- runs your tests (looping on failures) — the check run also mechanically sweeps
124
- `.gtd/TODO.md` and other spent steering files, so a plan that's left in place
125
- by mistake never leaks into the review diff or the final squash.
126
- - Create **`.gtd/REQUIREMENTS.md`** to start the **advanced** flow: one design
127
- conversation across product then technical Q&A (`.gtd/REQUIREMENTS.md` →
128
- `.gtd/ARCHITECTURE.md`) and decomposition — each open question offers a couple
129
- of candidate answers plus a `- [ ] _your answer_` slot, and you tick exactly
130
- one per question (the gate won't let a phase advance while any question is
131
- unanswered) — then decomposition into work **packages** (each a set of
132
- independent tasks a single build turn fans out to parallel subagents), a
133
- per-package test loop, and a per-package **agentic review** that verifies the
134
- package against its spec. All three phases share one machine identity, so the
135
- agent never re-explores the codebase from scratch between them, and the
136
- human's answers carry forward into decomposition.
137
-
138
- Both flows converge on the same tail: an agent hands you a `.gtd/REVIEW.md`
139
- checkbox review of the diff — the prompt never inlines the diff itself; it names
140
- the commit the changes are based at and the agent runs `git diff` to read the
141
- range before writing the review. While the process rests at that gate, the
142
- landing script opens a **review checkout window**: HEAD is rewound to the review
143
- base with the working tree untouched, so the whole reviewable change shows up as
144
- ordinary uncommitted changes in your editor's normal git integration (and files
145
- added during the process show up as ordinary untracked files, so discarding one
146
- deletes it — an untracked file you leave alone is not a pending change, and only
147
- actually removing it from disk counts as a deletion). The next landing's own
148
- script closes the window before it commits. Tick a box as you review each hunk
149
- (ticking just records "I read this"), and leave a **comment** to request
150
- changes: a note on a line, an inline `// TODO`-style comment in the code, or a
151
- direct code edit. Any comment sends a build + re-review round — an agent first
152
- turns your comments into an explicit instruction list, then a build turn
153
- implements it (a re-review then covers only the follow-through, and a hand-edit
154
- is treated as your own fix the agent completes without reverting your lines; a
155
- comment can't be silently dropped — a build turn that addresses nothing is
156
- refused). For the simple flow, the build turn that follows through on feedback
157
- and the turn that drafts the final squash message both resume the same session
158
- that built the feature in the first place, since the review tail is nested
159
- inside that build identity rather than sitting beside it. Ticking every box with
160
- no comment is the sign-off, which collapses the whole process into one commit (a
161
- **squash finale** whose message an agent drafts). Landing with a box still
162
- unticked and no comment is refused (finish reviewing first), as is deleting
163
- `.gtd/REVIEW.md`. Both refusals hold wherever the review doc lives: repointing
164
- `reviewFile` out of `.gtd/` (say to `REVIEW.md` at the repo root) changes
165
- nothing about them — your own edit to the review doc is never mistaken for a
166
- code comment, and the doc's pre-turn copy is read at the review window's saved
167
- head rather than at the rewound `HEAD`.
168
-
169
- The same review tail also has a direct entry point —
120
+ **Your input is a spec, not the work.** The unified workflow treats ANY change
121
+ to the tree — a hand-edit to real code, a scratch note in some file, anything at
122
+ all — as a sketch to be finished, never as work to be preserved: there is no
123
+ fork on which steering file you happen to create, and `idle` has exactly one
124
+ outgoing edge, into `unwind`. `unwind` reverts that whole diff back out of your
125
+ working tree (`git revert --no-commit` against the commit it just landed in)
126
+ before planning ever starts — your tree is back to exactly what it was, and your
127
+ intent doesn't disappear, it survives in history for `design.triage` to read.
128
+
129
+ From there, `start-gate.check` runs your test suite on the tree as it now stands
130
+ — which, thanks to the unwind, is simply your repo's own baseline. The rule is
131
+ the plain one: the baseline must be green. A red run halts the process and tells
132
+ you to repair it first (that's what `gtd --entry fix-precheck` is for);
133
+ `review-gate` follows the same rule.
134
+
135
+ Once past the gate, `design.triage` reads the diff that started the process
136
+ itself — the prompt never inlines it; it finds the entry commit (the one
137
+ `unwind` reverted) and runs `git show` against it — and groups that diff into an
138
+ ORDERED list of **concerns**, each one able to leave the test suite green on its
139
+ own, classifying each as **product** (a user-facing/requirements decision) or
140
+ **technical** (an implementation decision). It raises open questions for the
141
+ product concerns only, in `.gtd/REQUIREMENTS.md`, folding EVERYTHING the entry
142
+ commit added into those concerns — a scratch sketch and a hand-edited code
143
+ change alike, since the unwind already reverted both; nothing is left to delete.
144
+ A shared check+answer gate then probes `.gtd/REQUIREMENTS.md` for unanswered
145
+ questions: each open question offers a couple of candidate answers plus a
146
+ `- [ ] _your answer_` slot, and you tick exactly one per question (the gate
147
+ won't let the phase advance while any question is unanswered) — but a phase
148
+ whose document has no open questions skips that human stop entirely and falls
149
+ straight through.
150
+
151
+ Once the product questions are settled, `architecture.author` picks up as a
152
+ **cold reader** — a separate machine with its own memory scope, so it does not
153
+ resume the triage conversation but reads `.gtd/REQUIREMENTS.md` in full — and
154
+ develops the _how_ for each settled concern, raising only technical open
155
+ questions in `.gtd/ARCHITECTURE.md` (routed through that same shared
156
+ check+answer gate shape, again skipping the human stop when nothing is open),
157
+ deleting `.gtd/REQUIREMENTS.md` once its content is folded in. Once those are
158
+ settled, `architecture.decompose` is a purely mechanical write-out — **one
159
+ package file per concern**, in the settled order, with no merge/split judgement
160
+ of its own (that already happened in triage's grouping) — handing off to the
161
+ per-package build queue: each package (a set of independent tasks a single build
162
+ turn fans out to parallel subagents) runs its own test loop and a per-package
163
+ **agentic review** that verifies it against its own spec. A package whose work
164
+ already landed (an earlier package's fix turn pulled it in) is not a dead end:
165
+ the build turn records per-criterion evidence in `.gtd/SATISFIED.md` instead of
166
+ implementing anything, and the package still goes through the checks and the
167
+ spec review before closing out. If a queue item ever _does_ dead-end (a build
168
+ turn that authors nothing stalls), the supported recovery is to write that same
169
+ file yourself and `gtd land` — no hand-authored state commit.
170
+
171
+ The process converges on that same shared tail: an agent hands you a
172
+ `.gtd/REVIEW.md` checkbox review of the diff — the prompt never inlines the diff
173
+ itself; it names the commit the changes are based at and the agent runs
174
+ `git diff` to read the range before writing the review. While the process rests
175
+ at that gate, the landing script opens a **review checkout window**: HEAD is
176
+ rewound to the review base with the working tree untouched, so the whole
177
+ reviewable change shows up as ordinary uncommitted changes in your editor's
178
+ normal git integration (and files added during the process show up as ordinary
179
+ untracked files, so discarding one deletes it — an untracked file you leave
180
+ alone is not a pending change, and only actually removing it from disk counts as
181
+ a deletion). The next landing's own script closes the window before it commits.
182
+ Tick a box as you review each hunk (ticking just records "I read this"), and
183
+ leave a **comment** to request changes: a note on a line, an inline
184
+ `// TODO`-style comment in the code, or a direct code edit. Any comment sends a
185
+ build + re-review round — an agent first turns your comments into an explicit
186
+ instruction list, then a build turn implements it (a re-review then covers only
187
+ the follow-through, and a hand-edit is treated as your own fix the agent
188
+ completes without reverting your lines; a comment can't be silently dropped — a
189
+ build turn that addresses nothing is refused). The build turn that follows
190
+ through on feedback and the turn that drafts the final squash message both
191
+ resume the same session that built the feature in the first place, since the
192
+ review tail is nested inside that build identity rather than sitting beside it.
193
+ Ticking every box with no comment is the sign-off, which collapses the whole
194
+ process into one commit (a **squash finale** whose message an agent drafts).
195
+ Landing with a box still unticked and no comment is refused (finish reviewing
196
+ first), as is deleting `.gtd/REVIEW.md`. Both refusals hold wherever the review
197
+ doc lives: repointing `reviewFile` out of `.gtd/` (say to `REVIEW.md` at the
198
+ repo root) changes nothing about them — your own edit to the review doc is never
199
+ mistaken for a code comment, and the doc's pre-turn copy is read at the review
200
+ window's saved head rather than at the rewound `HEAD`.
201
+
202
+ A second entry, the same review tail's own direct entry point —
170
203
  `gtd --entry review-gate.check --var reviewBase=<commitish>` starts a brand new
171
204
  process reviewing `<commitish>..HEAD` with no build of its own, e.g. a
172
205
  colleague's PR branch (`review-gate.check`'s `reviewBase:` is a template bound
173
206
  to the `reviewBase` var, so supplying it via `--var` fixes the whole process's
174
207
  diff base to that commitish). Its squash keeps and describes only the fixes made
175
208
  _during_ the review (not the reviewed changeset); a clean sign-off with no fixes
176
- becomes an empty `chore: human review` commit. A fourth entry,
209
+ becomes an empty `chore: human review` commit. A third entry,
177
210
  `gtd --entry fix-precheck`, starts from a clean `idle` and goes straight into
178
211
  repairing a red baseline — repair, review, and squash into one commit. If the
179
212
  suite is already green there is nothing to fix, and the log is left untouched —
@@ -185,10 +218,11 @@ no commit is left behind.
185
218
  _extra_ reachability root (and drives a badge in `gtd visualize`) for a state
186
219
  that would otherwise be unreachable from the ordinary `idle` rest —
187
220
  `review-gate.check` and `fix-precheck` need it for exactly that reason, while
188
- `plan-gate.check`/`spec-gate.check` carry it too (the bundled template dedups
189
- the three `entryGate` instances into one shared machine, so flagging the shared
190
- state flags all three) even though `idle` already reaches them the ordinary way.
191
- `entry: true` is not a precondition for `--entry` to target a state.
221
+ `start-gate.check` carries it too (the bundled template dedups its two
222
+ `entryGate` instances — `start-gate` and `review-gate` — into one shared
223
+ machine, so flagging the shared state flags both) even though `idle` already
224
+ reaches it the ordinary way. `entry: true` is not a precondition for `--entry`
225
+ to target a state.
192
226
 
193
227
  Every agent state routes its model through two `vars` tiers — `plannerModel`
194
228
  (heavier planning and review) and `coderModel` (the coding turns) — so you can
@@ -274,7 +308,9 @@ Commands:
274
308
  non-zero when there are any. Resolves no workflow state and
275
309
  reads no config — standalone, runnable from any directory
276
310
  with <mode>/<file> given explicitly. This is what a
277
- workflow's emitted validation script invokes as a leaf step
311
+ workflow's emitted validation script invokes as a leaf step.
312
+ --open-questions runs the qa unanswered-questions predicate
313
+ instead (see --help)
278
314
  install Print a complete, self-contained briefing that teaches an
279
315
  agent (or a human) to build a gtd driver in any shell or
280
316
  runtime — the self-serve version of README's 'Writing
@@ -297,6 +333,10 @@ Options:
297
333
  (with --entry; repeatable) supply a fixed it.vars
298
334
  override for the new process; the name must already be
299
335
  declared by the workflow's own vars: or the .gtdrc vars:
336
+ --open-questions (gtd check only) ignore <mode>'s structural findings and
337
+ instead run the qa open-questions predicate over <file>,
338
+ printing each unanswered question one per line and exiting
339
+ non-zero when any remain
300
340
  --version, -v Print version and exit
301
341
  --help, -h Print this help and exit
302
342
  ```
@@ -377,17 +417,17 @@ exits. You act by editing files (answer a plan question, tick a review box, fix
377
417
  code) and re-running it — your pending edit arrives as the loop's first beat
378
418
  (`kind: "capture"`, landed immediately), so you never run `gtd land` by hand.
379
419
 
380
- Some gates accept by INACTION instead: the bundled template's `plan.await-plan`
381
- routes its `"C"` (clean-tree) pattern onward, so changing nothing there means
382
- "accept the plan". That reaches the driver as `kind: "message"`, which no
383
- inspection can tell apart from a gate you have not read yet — so the driver
384
- treats its OPENING beat as yours either way and lands it: you re-ran it while
385
- resting there, and that invocation IS the decision. Every later beat halts as
386
- usual, because a gate the driver produced mid-run is one you have not seen.
387
- Landing an opening beat at a gate with no `"C"` pattern is harmless — a benign
388
- no-op (see `gtd land`'s exit codes below) — and the gate then prints on the next
389
- beat. A mid-process restart simply resumes driving from whatever beat is
390
- actually next.
420
+ Some gates could accept by INACTION instead: a workflow may declare a `"C"`
421
+ (clean-tree) pattern on a human-actor state that routes onward, so changing
422
+ nothing there means "accept as-is" rather than nothing happening. That reaches
423
+ the driver as `kind: "message"` either way, which no inspection can tell apart
424
+ from a gate you have not read yet — so the driver treats its OPENING beat as
425
+ yours regardless and lands it: you re-ran it while resting there, and that
426
+ invocation IS the decision. Every later beat halts as usual, because a gate the
427
+ driver produced mid-run is one you have not seen. Landing an opening beat at a
428
+ gate with no `"C"` pattern is harmless — a benign no-op (see `gtd land`'s exit
429
+ codes below) — and the gate then prints on the next beat. A mid-process restart
430
+ simply resumes driving from whatever beat is actually next.
391
431
 
392
432
  Anything richer at that boundary — opening your editor, desktop notifications,
393
433
  terminal-multiplexer status — is the job of an outer wrapper around the driver,
@@ -752,17 +792,14 @@ emitted script opens by asserting its own precondition
752
792
  and the same shape for a review window's saved ref — see `src/Emit.ts`'s
753
793
  `headAssertion`/`reviewWindowAssertion`), so a script generated against a
754
794
  repository state that has since moved refuses loudly instead of corrupting
755
- anything. In a repository with no commits yet, `<expected>` is the empty string
756
- — the deciding read's own convention for "no commits yet" — so the first
757
- workflow commit is allowed to land instead of being blocked by an unborn `HEAD`.
758
- **Emitted scripts are re-runnable**: this is the single most important property
759
- for a driver's recovery logic. Re-running a script that already fully applied is
760
- a no-op (its git writes are `--allow-empty` commits, idempotent ref updates, and
761
- tolerant staged-restore calls), and re-running one that only partially applied
762
- resumes correctly, because the precondition either still holds (nothing landed
763
- yet — safe to retry verbatim) or gtd's next invocation reads the new real state
764
- and emits a fresh script for what remains. A driver never needs its own
765
- retry/resume logic beyond "if the script failed, ask gtd again."
795
+ anything. **Emitted scripts are re-runnable**: this is the single most important
796
+ property for a driver's recovery logic. Re-running a script that already fully
797
+ applied is a no-op (its git writes are `--allow-empty` commits, idempotent ref
798
+ updates, and tolerant staged-restore calls), and re-running one that only
799
+ partially applied resumes correctly, because the precondition either still holds
800
+ (nothing landed yet — safe to retry verbatim) or gtd's next invocation reads the
801
+ new real state and emits a fresh script for what remains. A driver never needs
802
+ its own retry/resume logic beyond "if the script failed, ask gtd again."
766
803
 
767
804
  ### Prerequisites
768
805
 
@@ -1031,6 +1068,24 @@ model, pattern grammar, load-time rules, and how to verify a change compiles.
1031
1068
  > discard it and start over (or finish the process on the pre-upgrade workflow
1032
1069
  > version first).
1033
1070
 
1071
+ > **Upgrading a `workflow:` from the old two-flow (`.gtd/TODO.md` vs.
1072
+ > `.gtd/REQUIREMENTS.md`) shape?** The bundled template collapsed that fork into
1073
+ > one flow: `idle` now has a single outgoing edge — any change at all starts the
1074
+ > process, never a fork on which steering file you create — and
1075
+ > `plan-gate.check`/`spec-gate.check` merged into one shared `start-gate.check`.
1076
+ > The old plan-iteration machine's `plan.planning`/`plan.await-plan` states and
1077
+ > its monolithic `build.building` state are gone outright; every concern now
1078
+ > goes through the same per-package build queue instead. Renamed:
1079
+ > `design.product-author` → `design.triage`, `design.product-answer` →
1080
+ > `design.gate.answer`, `design.technical-author` → `architecture.author`,
1081
+ > `design.technical-answer` → `architecture.gate.answer`, `design.decompose` →
1082
+ > `architecture.decompose` (architecture is now its own sibling machine with its
1083
+ > own memory scope, not nested under `design`). The `todoFile` var and the
1084
+ > `prose` mode are both gone — there is no more free-form plan file. As with
1085
+ > every rename above, an in-flight process resting at one of the old names can
1086
+ > no longer be resumed; `gtd abandon` it (or finish it on the pre-upgrade
1087
+ > workflow version) before upgrading.
1088
+
1034
1089
  ### Variables
1035
1090
 
1036
1091
  Every template — `script`/`prompt`/`message`/`commit`, a machine's own `model:`,
@@ -1136,7 +1191,9 @@ the compiler's job at load time.
1136
1191
  per `review`-mode chunk that still has an unchecked hunk (an outline of the
1137
1192
  packages left to review) plus check/uncheck actions over those chunks,
1138
1193
  go-to-definition from a `review`-mode hunk line into the file it points at (at
1139
- its `#line`), symbols over a `qa`-mode file's open questions plus "pick this
1194
+ its `#line` — a hunk's path is a single whitespace-delimited `./`-relative
1195
+ token, so a hyphen in a filename stays part of the path, never a note
1196
+ separator), symbols over a `qa`-mode file's open questions plus "pick this
1140
1197
  option"/"uncheck this option" code actions on each option — offered anywhere on
1141
1198
  the option's list item, including any wrapped continuation lines, not just its
1142
1199
  own `- [ ]` line — diagnostics for both (live as you edit), and a
@@ -1152,10 +1209,10 @@ itself, so you bring your own formatter and your own checkers. Overriding one of
1152
1209
  actions — those come from the FORMAT (the name), independent of who validates —
1153
1210
  but `gtd lsp` never runs a shell command per keystroke, so live diagnostics
1154
1211
  become one `Information` notice pointing at `gtd validate` instead of the
1155
- built-in findings. Any OTHER mode name — `prose` (used by the simple flow's plan
1156
- file), or a project's own declared name — has no built-in format, so it gets no
1157
- live editor support at all: `gtd validate`'s emitted script and the `gtd land`
1158
- gate still format and validate it like any other mode.
1212
+ built-in findings. Any OTHER mode name — a project's own declared name (e.g.
1213
+ `prose`, for a free-form note) — has no built-in format, so it gets no live
1214
+ editor support at all: `gtd validate`'s emitted script and the `gtd land` gate
1215
+ still format and validate it like any other mode.
1159
1216
 
1160
1217
  ## Development
1161
1218
 
@@ -1163,16 +1220,21 @@ gate still format and validate it like any other mode.
1163
1220
  npm install
1164
1221
  npm run dev # run from source, no build (node dev/run.mjs)
1165
1222
  npm run build # tsdown → dist/gtd.bundle.mjs
1166
- npm test # format:check, typecheck, lint, unit + e2e tests, fallow
1167
- npm run test:unit # vitest unit tests (the pure resolver) — --project unit
1168
- npm run test:e2e # gherkin e2e, both tiers — test:e2e:inmem + test:e2e:live
1169
- npm run test:e2e:inmem # @inmem scenarios, in-process, no build — --project e2e-inmem
1170
- npm run test:e2e:live # @live scenarios against the built bundle — --project e2e-live
1223
+ npm test # the whole gate, via turbo — cached and parallel
1224
+ npx turbo run test:unit # one task, cached (add --force to bypass)
1225
+ npx turbo run test:e2e:live # builds first (turbo dependsOn), then @live
1226
+ npm run test:changed # local pre-flight: only unit/@inmem tests git says changed
1171
1227
  npm run test:mutation # StrykerJS mutation testing (manual only, ~10 min)
1172
1228
  npm run typecheck
1173
1229
  npm run lint
1174
1230
  ```
1175
1231
 
1232
+ `npm test` is a turbo task graph (`turbo.json`): each check declares its own
1233
+ `inputs`, so an unchanged check is skipped, and a check that does run is run in
1234
+ parallel with the others. Caveat from the `test:e2e:live` task's `build`
1235
+ dependency: a bare `npm run test:e2e:live` skips the build, so use
1236
+ `npx turbo run test:e2e:live` to test against a fresh bundle.
1237
+
1176
1238
  A pre-commit hook is installed automatically via the `prepare` script when you
1177
1239
  run `npm install` on a fresh clone — it runs
1178
1240
  [lint-staged](https://github.com/lint-staged/lint-staged) with