@pmelab/gtd 9.2.0 → 9.4.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 +116 -56
- package/dist/gtd.bundle.mjs +287 -94
- package/package.json +1 -1
- package/schema.json +9 -1
package/README.md
CHANGED
|
@@ -121,10 +121,14 @@ reads intent first, glob second.
|
|
|
121
121
|
to the tree — a hand-edit to real code, a scratch note in some file, anything at
|
|
122
122
|
all — as a sketch to be finished, never as work to be preserved: there is no
|
|
123
123
|
fork on which steering file you happen to create, and `idle` has exactly one
|
|
124
|
-
outgoing edge, into `unwind`. `
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
outgoing edge, into `unwind`. `.gtd/TODO.md` (the `todoFile` var) is a good
|
|
125
|
+
default place to start sketching when you'd rather write a note than touch code
|
|
126
|
+
— despite living beside the workflow's own state files, that sketch is your
|
|
127
|
+
input for `design.triage` to fold in, never gtd bookkeeping to preserve or
|
|
128
|
+
ignore. `unwind` reverts that whole diff back out of your working tree
|
|
129
|
+
(`git revert --no-commit` against the commit it just landed in) before planning
|
|
130
|
+
ever starts — your tree is back to exactly what it was, and your intent doesn't
|
|
131
|
+
disappear, it survives in history for `design.triage` to read.
|
|
128
132
|
|
|
129
133
|
From there, `start-gate.check` runs your test suite on the tree as it now stands
|
|
130
134
|
— which, thanks to the unwind, is simply your repo's own baseline. The rule is
|
|
@@ -181,30 +185,37 @@ alone is not a pending change, and only actually removing it from disk counts as
|
|
|
181
185
|
a deletion). The next landing's own script closes the window before it commits.
|
|
182
186
|
Tick a box as you review each hunk (ticking just records "I read this"), and
|
|
183
187
|
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.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
review
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
188
|
+
`// TODO`-style comment in the code, or a direct code edit. A comment sends a
|
|
189
|
+
FULL development lap, not a quick fix-and-re-review: an agent first judges
|
|
190
|
+
whether your comment is actually actionable (a genuinely approving remark with
|
|
191
|
+
no code edit short-circuits straight to sign-off instead), and an actionable
|
|
192
|
+
round is re-planned from scratch through triage, architecture, and the package
|
|
193
|
+
queue again — a hand-edit you made during review is treated as a **sketch**, the
|
|
194
|
+
same as any other change that starts a process, not a fix the agent builds on:
|
|
195
|
+
it is reverted out of the tree first, and your intent survives only in your own
|
|
196
|
+
review-round commit for triage to read. There is no baseline check on the way
|
|
197
|
+
back into planning. Only the turn that drafts the final squash message resumes
|
|
198
|
+
the session that built the feature in the first place (the review tail is nested
|
|
199
|
+
inside that build identity rather than sitting beside it) — an actionable round
|
|
200
|
+
leaves that identity entirely, so it starts a fresh session like any other
|
|
201
|
+
process. Ticking every box with no comment is the sign-off, which collapses the
|
|
202
|
+
whole process into one commit (a **squash finale** whose message an agent
|
|
203
|
+
drafts). Landing with a box still unticked and no comment is refused (finish
|
|
204
|
+
reviewing first), as is deleting `.gtd/REVIEW.md`. Both refusals hold wherever
|
|
205
|
+
the review doc lives: repointing `reviewFile` out of `.gtd/` (say to `REVIEW.md`
|
|
206
|
+
at the repo root) changes nothing about them — your own edit to the review doc
|
|
207
|
+
is never mistaken for a code comment, and the doc's pre-turn copy is read at the
|
|
208
|
+
review window's saved head rather than at the rewound `HEAD`.
|
|
201
209
|
|
|
202
210
|
A second entry, the same review tail's own direct entry point —
|
|
203
211
|
`gtd --entry review-gate.check --var reviewBase=<commitish>` starts a brand new
|
|
204
|
-
process reviewing `<commitish>..HEAD` with no build of its own
|
|
205
|
-
colleague's PR branch (`review-gate.check`'s `reviewBase:` is a
|
|
206
|
-
to the `reviewBase` var, so supplying it via `--var` fixes the
|
|
207
|
-
diff base to that commitish)
|
|
212
|
+
process reviewing `<commitish>..HEAD` with no build of its own on a clean
|
|
213
|
+
sign-off, e.g. a colleague's PR branch (`review-gate.check`'s `reviewBase:` is a
|
|
214
|
+
template bound to the `reviewBase` var, so supplying it via `--var` fixes the
|
|
215
|
+
whole process's diff base to that commitish) — though an actionable round on
|
|
216
|
+
this entry runs the same full triage → gates → architecture → package-queue lap
|
|
217
|
+
as any other, same as `re-unwind` re-plans a build process's own review
|
|
218
|
+
feedback. A clean sign-off's squash keeps and describes only the fixes made
|
|
208
219
|
_during_ the review (not the reviewed changeset); a clean sign-off with no fixes
|
|
209
220
|
becomes an empty `chore: human review` commit. A third entry,
|
|
210
221
|
`gtd --entry fix-precheck`, starts from a clean `idle` and goes straight into
|
|
@@ -227,13 +238,27 @@ to target a state.
|
|
|
227
238
|
Every agent state routes its model through two `vars` tiers — `plannerModel`
|
|
228
239
|
(heavier planning and review) and `coderModel` (the coding turns) — so you can
|
|
229
240
|
repoint the models globally in one place (a `vars:` edit or a `GTD_PLANNERMODEL`
|
|
230
|
-
override) instead of per state. Steering-file path vars (`
|
|
231
|
-
`reviewFile`, …) work the same way, and propagate to the `on`
|
|
232
|
-
route on them too — a repointed path var actually reroutes the
|
|
233
|
-
the templates that read/write the file.
|
|
234
|
-
`.gtd`
|
|
241
|
+
override) instead of per state. Steering-file path vars (`todoFile`,
|
|
242
|
+
`feedbackFile`, `reviewFile`, …) work the same way, and propagate to the `on`
|
|
243
|
+
patterns that route on them too — a repointed path var actually reroutes the
|
|
244
|
+
machine, not just the templates that read/write the file. `todoFile` (default
|
|
245
|
+
`.gtd/TODO.md`, `idle`'s own `file:` hint) is the one exception: it's the only
|
|
246
|
+
per-file var gtd never writes and never reads, since it names your own sketch
|
|
247
|
+
pad, not a file any state produces. A separate `stateDir` var (default `.gtd`)
|
|
248
|
+
names only where the check scripts keep their own scratch/bookkeeping,
|
|
235
249
|
independent of the per-file vars — relocate one steering file without touching
|
|
236
|
-
it.
|
|
250
|
+
it. The workflow declares its plumbing directory once, at the top level of the
|
|
251
|
+
`workflow:` value (`stateDir: <%= it.vars.stateDir %>` in the bundled template),
|
|
252
|
+
rendered from that same `stateDir` var — this is what the engine itself reads to
|
|
253
|
+
tell gtd's own bookkeeping apart from your code (e.g. the review window's revert
|
|
254
|
+
pathspec, the step guards' code-vs-plumbing check), not just a value the
|
|
255
|
+
templates happen to share. The rendered value is constrained: it must name a
|
|
256
|
+
directory inside the repository — not the repo root, not an absolute path, and
|
|
257
|
+
not a path that escapes the repository via `..` — and it must be spelled
|
|
258
|
+
canonically: no `.` and no empty path segments (`a/./state` or `a//state` are
|
|
259
|
+
rejected, not rewritten), though a leading `./` and a trailing `/` are accepted
|
|
260
|
+
— or the next `gtd next`/`gtd status`/`gtd land` fails loudly with that message,
|
|
261
|
+
rather than silently excluding the whole tree from the review window's revert.
|
|
237
262
|
|
|
238
263
|
To inspect or change the machine itself, see [Configuration](#configuration) —
|
|
239
264
|
the workflow is just `.gtdrc` config.
|
|
@@ -453,11 +478,15 @@ started FROM. Entering a **descendant** scope (e.g. dipping from `build` into
|
|
|
453
478
|
a nested child machine, then back to the parent, still resumes the SAME parent
|
|
454
479
|
conversation; entering a **sibling or unrelated** scope does start a fresh one.
|
|
455
480
|
The bundled template's `build.review` (the human review tail) is a worked
|
|
456
|
-
example: it is nested INSIDE `build` (the builder's own machine)
|
|
457
|
-
|
|
458
|
-
`build.squashing`
|
|
459
|
-
|
|
460
|
-
|
|
481
|
+
example: it is nested INSIDE `build` (the builder's own machine) so that a
|
|
482
|
+
`gtd --entry fix-precheck` run — `build.fix` -> `build.health.check` ->
|
|
483
|
+
`build.review.*` -> `build.squashing` — stays inside one subtree, letting
|
|
484
|
+
`build.squashing` resume the SAME session that made the fixes instead of a
|
|
485
|
+
root-level sibling forcing it to re-derive the range from scratch on every pass
|
|
486
|
+
through the tail. (An actionable review round breaks the run on purpose instead
|
|
487
|
+
— it leaves `build` entirely through a root-level `re-unwind` state and a full
|
|
488
|
+
re-plan, since a hand-edit made during review is a sketch to reconsider, not a
|
|
489
|
+
fix to build on.) Two instances of the same reusable machine (e.g.
|
|
461
490
|
`build.health` and `packages.item.health`, both instantiating `healthGate`) get
|
|
462
491
|
different scopes and so never share a key, even though they're the "same shaped"
|
|
463
492
|
machine. One consequence is a structural guarantee: **a reviewer's turn never
|
|
@@ -823,18 +852,19 @@ its own retry/resume logic beyond "if the script failed, ask gtd again."
|
|
|
823
852
|
A mode's `format:` command may reformat a steering file — whitespace, wrapping,
|
|
824
853
|
reordering — but must NEVER change what a land-capture guard would decide. gtd's
|
|
825
854
|
guards (the review sign-off check, the feedback-progress check, the
|
|
826
|
-
answer-completeness check — `src/StepGuards.ts`)
|
|
827
|
-
bytes are on disk at the moment `gtd land` runs,
|
|
828
|
-
emitted script's own `format:` line has run (the
|
|
829
|
-
`validate:` then the commit — see
|
|
830
|
-
`renderSteeringCommands` — but gtd's decision and the
|
|
831
|
-
are different processes at different times, so there's
|
|
832
|
-
between "gtd decided" and "the script formatted"). That's
|
|
833
|
-
every built-in guard judges content, not incidental formatting
|
|
834
|
-
normalizes `[ ]`/`[x]` checkboxes before comparing). If you plug in
|
|
835
|
-
`format:` command, the same rule binds it: a formatter that also
|
|
836
|
-
— ticking a box, stripping a paragraph — makes the guard's
|
|
837
|
-
file's actual content disagree, and gtd will not catch that for
|
|
855
|
+
answer-completeness check, the require-revert check — `src/StepGuards.ts`)
|
|
856
|
+
decide ONCE, against whichever bytes are on disk at the moment `gtd land` runs,
|
|
857
|
+
which may be before OR after an emitted script's own `format:` line has run (the
|
|
858
|
+
script runs `format:` then `validate:` then the commit — see
|
|
859
|
+
`src/SteeringMode.ts`'s `renderSteeringCommands` — but gtd's decision and the
|
|
860
|
+
driver's script execution are different processes at different times, so there's
|
|
861
|
+
no guaranteed ordering between "gtd decided" and "the script formatted"). That's
|
|
862
|
+
only safe because every built-in guard judges content, not incidental formatting
|
|
863
|
+
(e.g. it normalizes `[ ]`/`[x]` checkboxes before comparing). If you plug in
|
|
864
|
+
your own `format:` command, the same rule binds it: a formatter that also
|
|
865
|
+
changes meaning — ticking a box, stripping a paragraph — makes the guard's
|
|
866
|
+
decision and the file's actual content disagree, and gtd will not catch that for
|
|
867
|
+
you.
|
|
838
868
|
|
|
839
869
|
One case never runs your `format:` (or `validate:`) at all: a step whose diff
|
|
840
870
|
DELETES the state's own `file:`. Deleting it is a legitimate outcome — a review
|
|
@@ -921,6 +951,7 @@ workflow:
|
|
|
921
951
|
<name>:
|
|
922
952
|
format: <shell command> # both optional — {} is the format-only tier
|
|
923
953
|
validate: <shell command>
|
|
954
|
+
stateDir: <string> # optional, an Eta template naming where this workflow keeps its own plumbing (default ".gtd") — the definition-level declaration the engine reads, distinct from the `vars.stateDir` var the bundled template renders it from
|
|
924
955
|
entry:
|
|
925
956
|
default: <machine name> # which machine is the ROOT instance
|
|
926
957
|
machines:
|
|
@@ -953,6 +984,7 @@ workflow:
|
|
|
953
984
|
# reviewBase: <Eta template> # OR a template — rendered (only meaningful entering via --entry) to a commitish that fixes the WHOLE PROCESS's diff base
|
|
954
985
|
requireProgress: true # optional, requires "file" — refuse a turn whose only change deletes this state's own `file:`
|
|
955
986
|
answerGate: true # optional, requires "file" — refuse a turn until every open question in the (qa-mode) `file:` is answered
|
|
987
|
+
requireRevert: true # optional, requires "file" — refuse a turn until the human's review-round paths actually match the review base's parent
|
|
956
988
|
entry: true # optional — an EXTRA reachability root (`entries.manual`), enterable via `gtd --entry <this state's qualified name>` — NOT a precondition for `--entry` (any declared, non-commit state is a valid target)
|
|
957
989
|
<local>: { machine: <name>, with: { <param>: <value> } } # a REFERENCE — instantiates <name> as a child, qualified as `<local>.<childLocal>`
|
|
958
990
|
```
|
|
@@ -965,7 +997,11 @@ derives a driver's session id).
|
|
|
965
997
|
The top-level `entry:` key (naming the root machine, `entry.default`) and a
|
|
966
998
|
state's own `entry: true` flag are the same word at two different levels, by
|
|
967
999
|
design: one selects the workflow's root machine, the other opts one state in as
|
|
968
|
-
an extra manual entry point.
|
|
1000
|
+
an extra manual entry point. The top-level `stateDir:` key and the
|
|
1001
|
+
`vars.stateDir` var it renders from are the same call: the definition-level
|
|
1002
|
+
declaration is what the engine reads (e.g. to tell gtd's own plumbing apart from
|
|
1003
|
+
your code), while the var is the knob you actually override — repointing
|
|
1004
|
+
`vars.stateDir` moves both.
|
|
969
1005
|
|
|
970
1006
|
A workflow is authored as a TREE of reusable, parameterized machines — a
|
|
971
1007
|
gate/loop written once and instantiated several times with different `with:`
|
|
@@ -985,7 +1021,12 @@ Besides `it.vars` (below), a `script`/`prompt`/`message`/`commit` template sees:
|
|
|
985
1021
|
- **`it.startCommit`** — the process's diff base (the commit the current process
|
|
986
1022
|
started from, or the base a `--var reviewBase=<commitish>` entry resolved to).
|
|
987
1023
|
- **`it.reviewBase`** — the previous review round's boundary, falling back to
|
|
988
|
-
`it.startCommit` on a first review.
|
|
1024
|
+
`it.startCommit` on a first review. In the bundled template, an actionable
|
|
1025
|
+
round's NEXT review therefore covers the revert of the human's own lines
|
|
1026
|
+
(`re-unwind`) followed by the whole lap that re-derives and re-implements them
|
|
1027
|
+
— the net diff is the final implementation, the right thing to review, but no
|
|
1028
|
+
longer the tiny "just the fixes" delta a quick fix-and-re-review would have
|
|
1029
|
+
shown.
|
|
989
1030
|
- **`it.retainedBase`** — the process's trace/retry boundary, what a squash
|
|
990
1031
|
actually keeps (never moved by a review entry's fixed base).
|
|
991
1032
|
- **`it.currentCommit`** / **`it.previousCommit`** — HEAD's hash and its parent,
|
|
@@ -1080,11 +1121,23 @@ model, pattern grammar, load-time rules, and how to verify a change compiles.
|
|
|
1080
1121
|
> `design.gate.answer`, `design.technical-author` → `architecture.author`,
|
|
1081
1122
|
> `design.technical-answer` → `architecture.gate.answer`, `design.decompose` →
|
|
1082
1123
|
> `architecture.decompose` (architecture is now its own sibling machine with its
|
|
1083
|
-
> own memory scope, not nested under `design`). The `
|
|
1084
|
-
>
|
|
1085
|
-
>
|
|
1086
|
-
> no
|
|
1087
|
-
>
|
|
1124
|
+
> own memory scope, not nested under `design`). The `prose` mode is gone and
|
|
1125
|
+
> there is no more free-form _plan_ file — `todoFile` itself came back later
|
|
1126
|
+
> with a different job: `idle`'s own mode-less `file:` hint, gtd's sketch pad
|
|
1127
|
+
> that no state writes or reads. As with every rename above, an in-flight
|
|
1128
|
+
> process resting at one of the old names can no longer be resumed;
|
|
1129
|
+
> `gtd abandon` it (or finish it on the pre-upgrade workflow version) before
|
|
1130
|
+
> upgrading.
|
|
1131
|
+
|
|
1132
|
+
> **Upgrading a `workflow:` that still references `build.addressing`?** That
|
|
1133
|
+
> state is REMOVED, not renamed — the implementer's own follow-through on review
|
|
1134
|
+
> feedback is gone outright, since an actionable review round is now re-planned
|
|
1135
|
+
> from scratch through a new root-level `re-unwind` state (reverting the human's
|
|
1136
|
+
> hand-edit) instead of being built upon. A non-actionable round (an approving
|
|
1137
|
+
> remark with no code edit) short-circuits straight to `build.squashing` instead
|
|
1138
|
+
> of spending a lap on nothing. As with every rename above, an in-flight process
|
|
1139
|
+
> resting at `build.addressing` can no longer be resumed after upgrading;
|
|
1140
|
+
> `gtd abandon` it (or finish it on the pre-upgrade workflow version) first.
|
|
1088
1141
|
|
|
1089
1142
|
### Variables
|
|
1090
1143
|
|
|
@@ -1197,7 +1250,14 @@ separator), symbols over a `qa`-mode file's open questions plus "pick this
|
|
|
1197
1250
|
option"/"uncheck this option" code actions on each option — offered anywhere on
|
|
1198
1251
|
the option's list item, including any wrapped continuation lines, not just its
|
|
1199
1252
|
own `- [ ]` line — diagnostics for both (live as you edit), and a
|
|
1200
|
-
`gtd.openSteeringFile` command that jumps to the current state's steering file
|
|
1253
|
+
`gtd.openSteeringFile` command that jumps to the current state's steering file —
|
|
1254
|
+
including `idle`, whose `todoFile` hint gives the one keybinding an answer even
|
|
1255
|
+
before a process has started. The command only names that path — it never
|
|
1256
|
+
stat-checks or creates it — so on a repo that has never run gtd, `.gtd/` may not
|
|
1257
|
+
exist yet and editors differ on opening a file whose parent directory is missing
|
|
1258
|
+
(an empty buffer that creates it on save vs. refusing the path outright); this
|
|
1259
|
+
bites only the very first sketch in a fresh repo, since the workflow's own check
|
|
1260
|
+
scripts create the state directory on the first `gtd next`/`gtd land`.
|
|
1201
1261
|
|
|
1202
1262
|
It is config-driven via each state's `file:`/`mode:`, and falls back to basename
|
|
1203
1263
|
dispatch (`REVIEW.md` → `review`) with no config in sight. `qa` and `review` are
|