@pmelab/gtd 1.6.1 → 1.7.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 +23 -56
- package/dist/gtd.bundle.mjs +14 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ merge-base with the default branch (whole-history fallback when there is no
|
|
|
17
17
|
default branch, when HEAD equals the merge-base, or when there is no merge-base
|
|
18
18
|
— i.e. budgets engage on the default branch too) plus the working tree, turns
|
|
19
19
|
them into a `COMMIT[]` + single terminal `RESOLVE` event stream, and folds them
|
|
20
|
-
through the machine. The fold lands on exactly **one** of
|
|
20
|
+
through the machine. The fold lands on exactly **one** of 18 states, which
|
|
21
21
|
selects the prompt. A single run resolves to a single state.
|
|
22
22
|
|
|
23
23
|
`resolve()` returns that state plus an optional **`EdgeAction`** (a commit,
|
|
@@ -239,7 +239,9 @@ flowchart TD
|
|
|
239
239
|
P5 -->|no| P6{"TODO.md?"}
|
|
240
240
|
P6 -->|"open markers"| GrillStop["Grilling — gtd: grilling, STOP for answers"]:::gate
|
|
241
241
|
P6 -->|"dirty, no markers"| GrillIter["Grilling — gtd: grilling, agent iterates"]:::agent
|
|
242
|
-
P6 -->|"clean, no markers"|
|
|
242
|
+
P6 -->|"clean, no markers"| GrilledReview["Grilled review — gtd: grilled, human review"]:::gate
|
|
243
|
+
GrilledReview -->|"re-run gtd clean"| Grilled["Grilled — gtd: grilled, decompose"]:::agent
|
|
244
|
+
GrilledReview -->|"edits present"| GrillIter
|
|
243
245
|
P6 -->|absent| P7{"clean + boundary/package-done HEAD,<br/>reviewable diff?"}
|
|
244
246
|
P7 -->|yes| CleanState["Clean — write REVIEW.md"]:::agent
|
|
245
247
|
P7 -->|no| Idle
|
|
@@ -290,7 +292,7 @@ back into the working tree uncommitted, and re-derives state from scratch. If
|
|
|
290
292
|
the transport commit is the repository's root commit (no parent), `gtd` fails
|
|
291
293
|
immediately with a clear error instead of looping.
|
|
292
294
|
|
|
293
|
-
## The
|
|
295
|
+
## The 18 states
|
|
294
296
|
|
|
295
297
|
Each state has a **condition** (when it wins), a deterministic **action**, the
|
|
296
298
|
**commit(s)** it produces, and where it **advances**. States marked
|
|
@@ -313,8 +315,9 @@ action and re-resolves silently.
|
|
|
313
315
|
| **Accept Review** | edge-only, auto | REVIEW.md committed + pending **non-checkbox** edits (human annotated REVIEW.md with comments / edited code) | seed TODO.md from the changeset, `git checkout` to discard the code edits, rm REVIEW.md; **all uncommitted** | Grilling |
|
|
314
316
|
| **Await Review** | edge-only, auto | REVIEW.md present and **uncommitted** (freshly written by Clean) | commit REVIEW.md `gtd: awaiting review` | Done (auto, same run) |
|
|
315
317
|
| **New Feature** | edge-only, auto | boundary HEAD + pending changes (code and/or a new uncommitted TODO.md), **or** HEAD `gtd: new task` + clean tree (lost-seed regen) | commit the raw input verbatim `gtd: new task` (unless already there), `git revert --no-commit` it back to a clean baseline, seed TODO.md from that diff — revert + seed left **uncommitted** | Grilling |
|
|
316
|
-
| **Grilling** | agent (iterate) / STOP (answers) | TODO.md present, not New Feature | commit pending edits `gtd: grilling`. Open-question markers present → STOP for the human to answer inline; no markers but dirty → grilling agent iterates | converge (no markers, clean tree) → Grilled
|
|
317
|
-
| **Grilled**
|
|
318
|
+
| **Grilling** | agent (iterate) / STOP (answers) | TODO.md present, not New Feature | commit pending edits `gtd: grilling`. Open-question markers present → STOP for the human to answer inline; no markers but dirty → grilling agent iterates | converge (no markers, clean tree) → Grilled review |
|
|
319
|
+
| **Grilled review** | STOP | TODO.md present, no markers, clean tree, HEAD `gtd: grilled` (converged — not yet decomposed) | none | edits → Grilling; clean re-run → Grilled |
|
|
320
|
+
| **Grilled** | agent, auto | TODO.md present, no markers, clean tree, HEAD `gtd: grilled` (returning from Grilled review with no new edits) | commit pending `gtd: grilled` | decompose into `.gtd/` → Planning |
|
|
318
321
|
| **Clean** | agent | no steering files, clean tree, boundary or `gtd: package done` HEAD, and the review base yields a **non-empty** diff | compute the review base (four rules — see below); agent writes REVIEW.md **uncommitted** with `# Review: <short-hash>` heading, `<!-- base: <full-hash> -->` marker, and per-hunk `- [ ]` checkboxes (ticking them signals approval → Done) | Await Review |
|
|
319
322
|
| **Idle** | STOP | no steering files, clean tree, and nothing to review (HEAD `gtd: done` with `squash` disabled or after Squashing, or no reviewable diff) | none | — |
|
|
320
323
|
|
|
@@ -422,9 +425,11 @@ loop before the next one starts.
|
|
|
422
425
|
your answer, and run `gtd` again. The agent integrates answers, moves them to
|
|
423
426
|
`## Resolved`, and raises fresh questions — repeat until none remain (it
|
|
424
427
|
writes `no open questions — run gtd to plan` with no markers).
|
|
425
|
-
4. **Converge.** A clean tree with no markers resolves to **Grilled**
|
|
426
|
-
(`gtd: grilled`)
|
|
427
|
-
|
|
428
|
+
4. **Converge.** A clean tree with no markers resolves to **Grilled review**
|
|
429
|
+
(`gtd: grilled`) — a human STOP. Review the plan; edit and re-run `gtd` to
|
|
430
|
+
re-enter Grilling, or re-run `gtd` with no changes to advance. A clean re-run
|
|
431
|
+
triggers **Grilled** (auto-advance), which then **Planning** decomposes
|
|
432
|
+
`TODO.md` into ordered `.gtd/` work packages (`gtd: planning`).
|
|
428
433
|
5. **Build.** Run `gtd` — **Building** first deletes `TODO.md` (when HEAD is
|
|
429
434
|
`gtd: planning` and it is still present, committed under the same
|
|
430
435
|
`gtd: planning` prefix — fires once). It then names the single next package
|
|
@@ -442,9 +447,9 @@ loop before the next one starts.
|
|
|
442
447
|
(`gtd: done`) → **Squashing** → **Idle**. The Squashing agent authors a
|
|
443
448
|
conventional-commits message from the full process diff and squashes all
|
|
444
449
|
intermediate `gtd: *` commits into one with `git reset --soft <base>` +
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
450
|
+
`git commit`, then **gtd STOPs**. The base is the parent of the current
|
|
451
|
+
cycle's start marker **nearest to HEAD** (the last `gtd: new task`; for
|
|
452
|
+
legacy cycles the last contiguous `gtd: grilling` run), and on a feature
|
|
448
453
|
branch it never reaches below the merge-base with the default branch — stray
|
|
449
454
|
markers left behind by older squashes can never drag the squash into
|
|
450
455
|
previously shipped features. Post-squash review does not fire automatically —
|
|
@@ -453,20 +458,13 @@ loop before the next one starts.
|
|
|
453
458
|
has no unrelated code dirty — a lone untracked `SQUASH_MSG.md` is tolerated
|
|
454
459
|
and deleted before the squash commit. If unrelated code is dirty at
|
|
455
460
|
`gtd: done`, gtd routes to **New Feature** instead. Set `squash: false` in
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
> > > > > > > straight to Idle. Checking off REVIEW.md checkboxes (`- [ ]` →
|
|
464
|
-
> > > > > > > `- [x]`) also counts as approval and routes to **Done** — they
|
|
465
|
-
> > > > > > > are navigation aids, not feedback. Only **non-checkbox** edits
|
|
466
|
-
> > > > > > > (code changes, inline comments, textual annotations in
|
|
467
|
-
> > > > > > > REVIEW.md) trigger **Accept Review**, which seeds a fresh
|
|
468
|
-
> > > > > > > `TODO.md` from your feedback, discards your code edits, removes
|
|
469
|
-
> > > > > > > `REVIEW.md`, and re-enters Grilling — the loop starts over.
|
|
461
|
+
`.gtdrc` to skip squashing and go straight to Idle. Checking off REVIEW.md
|
|
462
|
+
checkboxes (`- [ ]` → `- [x]`) also counts as approval and routes to **Done**
|
|
463
|
+
— they are navigation aids, not feedback. Only **non-checkbox** edits (code
|
|
464
|
+
changes, inline comments, textual annotations in REVIEW.md) trigger **Accept
|
|
465
|
+
Review**, which seeds a fresh `TODO.md` from your feedback, discards your
|
|
466
|
+
code edits, removes `REVIEW.md`, and re-enters Grilling — the loop starts
|
|
467
|
+
over.
|
|
470
468
|
|
|
471
469
|
## Configuration
|
|
472
470
|
|
|
@@ -814,37 +812,6 @@ Run `npm run test:mutation` after making changes to the mutated files to check
|
|
|
814
812
|
whether surviving mutants increased. The HTML report lands in
|
|
815
813
|
`reports/mutation/mutation.html` (git-ignored).
|
|
816
814
|
|
|
817
|
-
### Mutation testing
|
|
818
|
-
|
|
819
|
-
Run mutation testing on-demand with `npm run test:mutation` (StrykerJS, ~2 min).
|
|
820
|
-
The single `stryker.config.json` mutates six core files:
|
|
821
|
-
|
|
822
|
-
```
|
|
823
|
-
src/Machine.ts src/Prompt.ts src/Config.ts
|
|
824
|
-
src/Format.ts src/State.ts src/Events.ts
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
`src/Git.ts` is excluded: the Cucumber harness stubs git at the Effect boundary,
|
|
828
|
-
so Git.ts mutants have zero in-memory coverage. Measuring its post-refactor
|
|
829
|
-
Live-tier kill rate is a follow-up before re-including it.
|
|
830
|
-
|
|
831
|
-
**`process.chdir()` gotcha (resolved).** `@stryker-mutator/vitest-runner`
|
|
832
|
-
hardcodes `pool: 'threads'` internally, and `process.chdir()` is unsupported in
|
|
833
|
-
worker threads. Before the cwd refactor (package 01), four test files
|
|
834
|
-
(`Events.test.ts`, `Git.test.ts`, `Config.test.ts`, `TestRunner.test.ts`) had to
|
|
835
|
-
be excluded from all Stryker runs. The refactor eliminated those calls, letting
|
|
836
|
-
all four files rejoin the run.
|
|
837
|
-
|
|
838
|
-
Two additional notes: `vitest.related` is disabled for feature-file runs because
|
|
839
|
-
feature files don't import source files directly (Stryker's coverage-based
|
|
840
|
-
filtering would assign zero tests to every mutant). Compile-error mutants are
|
|
841
|
-
counted as kills by the TypeScript checker — they represent real signal, not a
|
|
842
|
-
configuration problem.
|
|
843
|
-
|
|
844
|
-
Run `npm run test:mutation` after making changes to the mutated files to check
|
|
845
|
-
whether surviving mutants increased. The HTML report lands in
|
|
846
|
-
`reports/mutation/mutation.html` (git-ignored).
|
|
847
|
-
|
|
848
815
|
## Releasing
|
|
849
816
|
|
|
850
817
|
Releases are automatic. Push releasable Conventional Commits (`fix:`, `feat:`,
|
package/dist/gtd.bundle.mjs
CHANGED
|
@@ -368486,6 +368486,9 @@ var squashing_default = '<%~ include("@header") %>\n\n<%~ include("@context", {
|
|
|
368486
368486
|
// src/prompts/escalate.md
|
|
368487
368487
|
var escalate_default = '<%~ include("@header") %>\n\n<%~ include("@context", { context: it.context, fenceFor: it.fenceFor }) %>\nThe agent was not able to fix all errors on its own. The last error report is\nstored in `ERRORS.md` for a human to investigate.\n\nNext steps for the human developer:\n\n1. Investigate and fix errors reported in `ERRORS.md`\n2. Delete `ERRORS.md`\n3. Continue the process when you are ready\n\n<%~ include(it.tail) %>\n';
|
|
368488
368488
|
|
|
368489
|
+
// src/prompts/grilled-review.md
|
|
368490
|
+
var grilled_review_default = '<%~ include("@header") %>\n\n<%~ include("@context", { context: it.context, fenceFor: it.fenceFor }) %> The\nplan in `TODO.md` has converged \u2014 no open questions remain \u2014 and has been\ncommitted as `gtd: grilled`.\n\n### Human review gate\n\nThis is a human review point. Tell the user to open `TODO.md` and review the\nfinalized plan:\n\n- To **proceed**, continue with a clean working tree \u2014 the plan will be\n decomposed into `.gtd/` work packages.\n- To **revise**, edit `TODO.md` (or sketch code) and continue \u2014 the changes\n re-enter the grilling loop for another convergence round.\n\n<%~ include(it.tail) %>\n';
|
|
368491
|
+
|
|
368489
368492
|
// src/prompts/idle.md
|
|
368490
368493
|
var idle_default = '<%~ include("@header") %>\n\n<%~ include("@context", { context: it.context, fenceFor: it.fenceFor }) %>\nReport that the repository is idle \u2014 nothing to do.\n\n<%~ include(it.tail) %>\n';
|
|
368491
368494
|
|
|
@@ -368533,11 +368536,13 @@ eta.loadTemplate("@agentic-review", agentic_review_default);
|
|
|
368533
368536
|
eta.loadTemplate("@clean", clean_default);
|
|
368534
368537
|
eta.loadTemplate("@squashing", squashing_default);
|
|
368535
368538
|
eta.loadTemplate("@escalate", escalate_default);
|
|
368539
|
+
eta.loadTemplate("@grilled-review", grilled_review_default);
|
|
368536
368540
|
eta.loadTemplate("@idle", idle_default);
|
|
368537
368541
|
eta.readFile = null;
|
|
368538
368542
|
eta.resolvePath = null;
|
|
368539
368543
|
var STATE_TEMPLATE = {
|
|
368540
368544
|
grilled: "@decompose",
|
|
368545
|
+
"grilled-review": "@grilled-review",
|
|
368541
368546
|
planning: "@decompose",
|
|
368542
368547
|
building: "@building",
|
|
368543
368548
|
fixing: "@fixing",
|
|
@@ -388987,9 +388992,16 @@ var resolveGrilling = (p4, counters, head7) => {
|
|
|
388987
388992
|
context: buildContext(p4, counters, "iterate")
|
|
388988
388993
|
};
|
|
388989
388994
|
}
|
|
388995
|
+
if (head7 === "gtd: grilled") {
|
|
388996
|
+
return {
|
|
388997
|
+
state: "grilled",
|
|
388998
|
+
autoAdvance: true,
|
|
388999
|
+
context: buildContext(p4, counters)
|
|
389000
|
+
};
|
|
389001
|
+
}
|
|
388990
389002
|
return {
|
|
388991
|
-
state: "grilled",
|
|
388992
|
-
autoAdvance:
|
|
389003
|
+
state: "grilled-review",
|
|
389004
|
+
autoAdvance: false,
|
|
388993
389005
|
edgeAction: { kind: "commitPending", prefix: "gtd: grilled" },
|
|
388994
389006
|
context: buildContext(p4, counters)
|
|
388995
389007
|
};
|