@pmelab/gtd 59.0.1 → 60.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/.claude-plugin/plugin.json +1 -1
- package/README.md +48 -32
- package/claude/hooks/doors.ts +8 -4
- package/dist/chunks/flows-DENt0uWV.mjs +707 -0
- package/dist/chunks/{steering-CCNvngSH.mjs → steering-DF_BMadH.mjs} +292 -289
- package/dist/chunks/testkit-BhTey1Do.mjs +30517 -0
- package/dist/chunks/{wire-BTUhRGXj.mjs → wire-DZ8R1RU9.mjs} +8 -1
- package/dist/flows.mjs +2 -676
- package/dist/gtd.bundle.mjs +11285 -19864
- package/dist/gtd.core.mjs +593 -0
- package/dist/steering.mjs +2 -2
- package/dist/testkit/gherkin.mjs +246 -37
- package/dist/testkit.mjs +3 -2
- package/dist/web/main.js +234 -232
- package/dist/wire.mjs +2 -2
- package/dist/workflow-kit.mjs +3 -3
- package/package.json +7 -7
- package/skills/authoring/SKILL.md +66 -60
- package/src/cli/Cli.test.ts +185 -184
- package/src/cli/Cli.ts +219 -224
- package/src/cli/History.ts +9 -4
- package/src/cli/Judges.ts +1 -1
- package/src/cli/Output.test.ts +35 -0
- package/src/cli/Output.ts +34 -3
- package/src/cli/Program.test.ts +78 -84
- package/src/cli/Program.ts +192 -128
- package/src/cli/ToolCommands.ts +2 -2
- package/src/edge/Edge.test.ts +72 -62
- package/src/edge/Edge.ts +6 -6
- package/src/flows/factory.test.ts +14 -0
- package/src/flows/factory.ts +22 -5
- package/src/flows/helpers.test.ts +35 -0
- package/src/flows/helpers.ts +19 -10
- package/src/flows/index.test.ts +66 -0
- package/src/flows/index.ts +109 -5
- package/src/flows/internal.ts +7 -0
- package/src/flows/runtime.test.ts +192 -1
- package/src/flows/runtime.ts +189 -55
- package/src/gherkin/git-control.feature +6 -6
- package/src/gherkin/index.test.ts +127 -0
- package/src/gherkin/index.ts +370 -51
- package/src/gherkin/messages.test.ts +38 -4
- package/src/gherkin/messages.ts +21 -4
- package/src/gherkin/more-steps.feature +170 -0
- package/src/gherkin/scenario-end.feature +101 -0
- package/src/gherkin/testkit.feature +83 -7
- package/src/install/Install.test.ts +7 -7
- package/src/install/Install.ts +8 -8
- package/src/install/Version.ts +9 -3
- package/src/install/index.ts +1 -1
- package/src/platform/CommandRunner.ts +13 -11
- package/src/platform/Commentary.ts +2 -2
- package/src/platform/Git.test.ts +4 -5
- package/src/platform/Git.ts +42 -38
- package/src/platform/Host.ts +1 -1
- package/src/platform/NodeServices.ts +11 -0
- package/src/platform/Workspace.test.ts +4 -5
- package/src/platform/Workspace.ts +3 -3
- package/src/platform/WorktreeState.test.ts +2 -3
- package/src/platform/WorktreeState.ts +1 -1
- package/src/platform/index.ts +2 -1
- package/src/replay/Replay.test.ts +13 -2
- package/src/replay/Replay.ts +19 -30
- package/src/replay/judgeDiffShape.test.ts +1 -1
- package/src/steering/Footnotes.test.ts +1 -1
- package/src/steering/SteeringFormats.test.ts +1 -1
- package/src/steering/freeform.test.ts +1 -1
- package/src/steering/index.test.ts +27 -1
- package/src/steering/index.ts +6 -104
- package/src/steering/internal.ts +11 -0
- package/src/steering/qa.test.ts +7 -2
- package/src/steering/reads.test.ts +42 -0
- package/src/steering/reads.ts +43 -0
- package/src/steering/registry.ts +93 -0
- package/src/steering/review.test.ts +2 -2
- package/src/step/planStart.test.ts +18 -16
- package/src/step/planStart.ts +12 -12
- package/src/testkit/TestRepo.test.ts +245 -7
- package/src/testkit/TestRepo.ts +271 -40
- package/src/testkit/imports.test.ts +58 -0
- package/src/testkit/imports.ts +102 -0
- package/src/testkit/index.test.ts +28 -0
- package/src/testkit/index.ts +14 -2
- package/src/twins/EmittedScriptRecognizer.ts +2 -6
- package/src/twins/EmittedScripts.test.ts +5 -3
- package/src/twins/GitTiers.ts +6 -7
- package/src/twins/InMemRepo.ts +1 -0
- package/src/twins/Layers.test.ts +1 -1
- package/src/twins/Layers.ts +10 -3
- package/src/twins/cliIo.ts +9 -4
- package/src/wire/Script.ts +11 -0
- package/src/wire/WireSchema.test.ts +3 -0
- package/src/wire/golden/1/script.json +4 -0
- package/src/wire/index.ts +1 -0
- package/src/workflow/SteeringFormats.test.ts +1 -1
- package/src/workflow/compile.ts +2 -2
- package/src/workflow/discovery.test.ts +27 -10
- package/src/workflow/discovery.ts +5 -6
- package/src/workflow/index.ts +1 -0
- package/src/workflow/load.test.ts +316 -119
- package/src/workflow/load.ts +478 -305
- package/src/workflow/pin.test.ts +159 -0
- package/src/workflow/pin.ts +72 -0
- package/src/workflow/vars.ts +3 -3
- package/src/workflow-kit/index.test.ts +25 -0
- package/src/workflow-kit/index.ts +37 -4
- package/src/workflow-kit/review.ts +2 -2
- package/dist/chunks/testkit-07Z_ENch.mjs +0 -32175
package/README.md
CHANGED
|
@@ -15,6 +15,8 @@ to any machine that checks it out.
|
|
|
15
15
|
|
|
16
16
|
## Install
|
|
17
17
|
|
|
18
|
+
gtd needs Node 22.19 or newer.
|
|
19
|
+
|
|
18
20
|
```bash
|
|
19
21
|
npm install -g @pmelab/gtd
|
|
20
22
|
```
|
|
@@ -23,6 +25,11 @@ That installs `latest`, which moves once a day to the newest release. Every
|
|
|
23
25
|
merge to `main` publishes to `next` first: `npm install -g @pmelab/gtd@next`
|
|
24
26
|
gets each one as it lands.
|
|
25
27
|
|
|
28
|
+
gtd bundles `gtd.config.ts` with [rolldown](https://rolldown.rs), whose native
|
|
29
|
+
binary npm installs for your platform. Where rolldown ships none, install its
|
|
30
|
+
WebAssembly build next to gtd:
|
|
31
|
+
`npm install -g --force @rolldown/binding-wasm32-wasi`.
|
|
32
|
+
|
|
26
33
|
Or run without installing (prefix every `gtd` below with `npx`) — see
|
|
27
34
|
[Configuration](https://github.com/pmelab/gtd/blob/main/docs/configuration.md)
|
|
28
35
|
for the settings most projects tune. A process setting's value is committed to
|
|
@@ -57,9 +64,9 @@ driver enforces it at the OS level. See
|
|
|
57
64
|
|
|
58
65
|
> **A repository's `gtd.config.ts` is code, and gtd runs it.** A custom workflow
|
|
59
66
|
> is a TypeScript module, and every gtd command that looks at workflow state —
|
|
60
|
-
> `gtd next`, `gtd lsp
|
|
61
|
-
>
|
|
62
|
-
>
|
|
67
|
+
> `gtd next`, `gtd lsp` and `gtd start` included, not just `gtd land` —
|
|
68
|
+
> evaluates it. Treat it like a Makefile or a `package.json` script: don't run
|
|
69
|
+
> gtd in a checkout you don't trust.
|
|
63
70
|
|
|
64
71
|
## Quick start
|
|
65
72
|
|
|
@@ -67,7 +74,7 @@ Put a `gtd.config.ts` at your repository's root (see [Install](#install)) and
|
|
|
67
74
|
commit it; gtd refuses to run without one. The repository need not be a
|
|
68
75
|
JavaScript project: gtd resolves the config's `@pmelab/gtd/*` imports itself, so
|
|
69
76
|
a Python, Rust or notes repository needs no `package.json` and no install. Then
|
|
70
|
-
run `gtd
|
|
77
|
+
run `gtd guide`: it writes nothing and prints a briefing (and where to get a
|
|
71
78
|
workflow, if you have none yet). Pipe that briefing into your coding agent and
|
|
72
79
|
answer its questions. It should build you a script that will autonomously run
|
|
73
80
|
the process for you. Ask your agent if you have any questions.
|
|
@@ -263,7 +270,7 @@ gtd next | claude -p --dangerously-skip-permissions
|
|
|
263
270
|
**The turn ends when `claude -p` returns** — a command the agent backgrounds
|
|
264
271
|
dies unread, and the process stalls on an empty turn. Claude Code lets the agent
|
|
265
272
|
background commands and caps foreground ones at 10 minutes by default, so a real
|
|
266
|
-
driver exports these first (`gtd
|
|
273
|
+
driver exports these first (`gtd guide`'s reference driver does):
|
|
267
274
|
|
|
268
275
|
```bash
|
|
269
276
|
export CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1
|
|
@@ -346,9 +353,9 @@ The requirements go to the top of `.gtd/TODO.md`, above whatever it already
|
|
|
346
353
|
holds. A long, multi-line requirements paste still starts a process; if Claude
|
|
347
354
|
Code never expanded the paste, gtd says it could not read it, and you add the
|
|
348
355
|
requirements to the top of `.gtd/TODO.md` and run `/gtd`. `/gtd <door> [args]`
|
|
349
|
-
takes one of the doors `gtd
|
|
350
|
-
`review [base]`, and `rollout <flag>` and `cleanup <flag>` where the
|
|
351
|
-
exports them); text whose word count does not fit a door's args (bare
|
|
356
|
+
takes one of the doors a bare `gtd start` lists (gtd-workflows' `default` brings
|
|
357
|
+
`fix`, `review [base]`, and `rollout <flag>` and `cleanup <flag>` where the
|
|
358
|
+
config exports them); text whose word count does not fit a door's args (bare
|
|
352
359
|
`/gtd rollout` included) starts a process from that text as requirements. At
|
|
353
360
|
every human rest Claude itself takes over: it walks you through the open
|
|
354
361
|
questions one at a time, answers your own questions about the plan or the diff,
|
|
@@ -381,7 +388,7 @@ But lets be honest, who reads documentation these days. Paste this into your
|
|
|
381
388
|
coding agent:
|
|
382
389
|
|
|
383
390
|
```
|
|
384
|
-
!gtd
|
|
391
|
+
!gtd guide
|
|
385
392
|
```
|
|
386
393
|
|
|
387
394
|
It prints a self-contained briefing that teaches the agent to set the project
|
|
@@ -390,8 +397,8 @@ you what you want before it starts driving. You get one prompt to paste, not a
|
|
|
390
397
|
state name to choose. The four commands: **`gtd-build`** drives beats until the
|
|
391
398
|
process rests; **`gtd-edit`** opens the steering file the process is waiting on
|
|
392
399
|
right now — falling back to `.gtd/TODO.md` when the resting state declares none;
|
|
393
|
-
**`gtd-door <name> [args...]`** starts a process through one of the doors
|
|
394
|
-
`gtd
|
|
400
|
+
**`gtd-door <name> [args...]`** starts a process through one of the doors a bare
|
|
401
|
+
`gtd start` lists (`gtd-door fix`, `gtd-door review [base]` with gtd-workflows'
|
|
395
402
|
`default`) and drives it. The `.gtd/TODO.md` fallback is also how you begin: on
|
|
396
403
|
a clean repository the edit command opens the empty `.gtd/TODO.md`, and whatever
|
|
397
404
|
you write there is the first sketch the whole process gets planned from. As a
|
|
@@ -447,9 +454,9 @@ The workflow itself is a plain async TypeScript function, and the
|
|
|
447
454
|
`gtd.config.ts` at the repository root names it. A workflow may be a factory —
|
|
448
455
|
`feature({ testCommand: "npm run ci" })` — whose options gtd validates when it
|
|
449
456
|
loads the config: a misspelled or mistyped one fails every command, naming the
|
|
450
|
-
workflow, the key and what was expected. `gtd
|
|
451
|
-
|
|
452
|
-
by name. See
|
|
457
|
+
workflow, the key and what was expected. `gtd start` lists the workflows your
|
|
458
|
+
config exports and the doors they bring, and `gtd start <name> [args...]` starts
|
|
459
|
+
one by name; a door named like a workflow wins. See
|
|
453
460
|
[Configuration](https://github.com/pmelab/gtd/blob/main/docs/configuration.md) —
|
|
454
461
|
and remember gtd evaluates that file on every command. A shared workflow package
|
|
455
462
|
bundling its own `@pmelab/gtd` is checked against the running gtd and refused,
|
|
@@ -484,14 +491,16 @@ doesn't lose it. `/gtd ship` pushes this process's own ref to origin alongside
|
|
|
484
491
|
the branch (never the others) and writes a `Gtd-History: <ref>` trailer on the
|
|
485
492
|
squashed commit. The push is forced, so it replaces origin's copy of that one
|
|
486
493
|
ref. If that push fails, the ship fails and nothing is squashed. Recover the
|
|
487
|
-
full trail with `gtd history fetch
|
|
494
|
+
full trail with `s=$(gtd history fetch --json=script) && sh -c "$s"`, then
|
|
495
|
+
`gtd history show <ref>`.
|
|
488
496
|
|
|
489
497
|
```sh
|
|
490
498
|
gtd history list # one line per kept process
|
|
491
499
|
gtd history show <ref> # replay its steps, judge verdicts and approvals
|
|
492
500
|
gtd history metrics [ref...] # how the kept processes went, per process and in total
|
|
493
501
|
gtd history judges [ref...] # how often each judge's verdicts were overturned
|
|
494
|
-
|
|
502
|
+
# pull every kept ref from origin
|
|
503
|
+
s=$(gtd history fetch --json=script) && sh -c "$s"
|
|
495
504
|
```
|
|
496
505
|
|
|
497
506
|
`gtd history metrics` measures gtd-workflows' `default` `feature` workflow from
|
|
@@ -537,12 +546,13 @@ contradicts it:
|
|
|
537
546
|
|
|
538
547
|
Any other verdict has no outcome. The report counts verdicts, scored verdicts
|
|
539
548
|
and overturns per judge and per `p` bucket (`0.8-0.9: 1/2` — one of two
|
|
540
|
-
overturned). `--
|
|
541
|
-
another threshold and prints the decisions that would change,
|
|
542
|
-
threshold each process recorded (a process that recorded none is
|
|
549
|
+
overturned). `--threshold <name>=<value>` (formerly `--var`) re-decides every
|
|
550
|
+
past verdict under another threshold and prints the decisions that would change,
|
|
551
|
+
against the threshold each process recorded (a process that recorded none is
|
|
552
|
+
left out):
|
|
543
553
|
|
|
544
554
|
```sh
|
|
545
|
-
gtd history judges --
|
|
555
|
+
gtd history judges --threshold qualityTriageMinP=0.9
|
|
546
556
|
# what-if qualityTriageMinP=0.9: 7 noise drops become notes (2 overturned)
|
|
547
557
|
```
|
|
548
558
|
|
|
@@ -600,25 +610,31 @@ approvals as `approvals` (`[]` when none), and `gtd history show` prints each as
|
|
|
600
610
|
gtd is one package, `@pmelab/gtd`, and every entrypoint shares its version and
|
|
601
611
|
[SemVer promise](https://github.com/pmelab/gtd/blob/main/COMPATIBILITY.md).
|
|
602
612
|
|
|
603
|
-
| Import | What it is
|
|
604
|
-
| ----------------------------- |
|
|
605
|
-
| `@pmelab/gtd/flows` | The flow API a workflow is written in: the steps (`agent`, `human`, `run`, …), `scope`, workflow factories, `defineConfig` and `FLOWS_PROTOCOL`.
|
|
606
|
-
| `@pmelab/gtd/wire` | The driver protocol: `WIRE_SCHEMA`, the exit codes and the types of every `--json` document.
|
|
607
|
-
| `@pmelab/gtd/steering` | The steering-file formats (`qa`, `review`, `findings`)
|
|
608
|
-
| `@pmelab/gtd/workflow-kit` | Policy-free building blocks to compose a workflow from: health checks, quality laps, scenario freezing, review tails.
|
|
609
|
-
| `@pmelab/gtd/testkit` | Runs any workflow against the real engine in an in-memory repository, under any test runner. See [Testing a workflow](https://github.com/pmelab/gtd/blob/main/docs/testing.md). |
|
|
610
|
-
| `@pmelab/gtd/testkit/gherkin` | The testkit as quickpickle steps for vitest. Needs `vitest` and `quickpickle`, optional peer dependencies.
|
|
613
|
+
| Import | What it is |
|
|
614
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
615
|
+
| `@pmelab/gtd/flows` | The flow API a workflow is written in: the steps (`agent`, `human`, `run`, …), `scope`, `workflow()`, workflow factories, `defineConfig` and `FLOWS_PROTOCOL`. |
|
|
616
|
+
| `@pmelab/gtd/wire` | The driver protocol: `WIRE_SCHEMA`, the exit codes and the types of every `--json` document. |
|
|
617
|
+
| `@pmelab/gtd/steering` | The steering-file formats (`qa`, `review`, `findings`), the review-note readers, and `sections`, `threads` and `openQuestions` as plain functions. |
|
|
618
|
+
| `@pmelab/gtd/workflow-kit` | Policy-free building blocks to compose a workflow from: health checks, quality laps, scenario freezing, review tails. See [Workflow kit](https://github.com/pmelab/gtd/blob/main/docs/workflow-kit.md). |
|
|
619
|
+
| `@pmelab/gtd/testkit` | Runs any workflow against the real engine in an in-memory repository, under any test runner, plus a flow-context harness for rendering prompts. See [Testing a workflow](https://github.com/pmelab/gtd/blob/main/docs/testing.md). |
|
|
620
|
+
| `@pmelab/gtd/testkit/gherkin` | The testkit as quickpickle steps for vitest. Needs `vitest` and `quickpickle`, optional peer dependencies. |
|
|
611
621
|
|
|
612
622
|
Types come from the TypeScript sources the package ships. Configs never need an
|
|
613
623
|
install for any of these but the testkit's: gtd resolves a `gtd.config.ts`'s
|
|
614
624
|
`@pmelab/gtd/*` imports to its own copy.
|
|
615
625
|
|
|
616
|
-
The `gtd` bin's commands — `next`, `land`, `
|
|
617
|
-
`
|
|
626
|
+
The `gtd` bin's commands — `next`, `land`, `start`, `abandon`, `restore`,
|
|
627
|
+
`validate`, `check`, `uncheck`, `guide`, `bundle`, `summary`, `base`, `version`,
|
|
618
628
|
`help`, `history list`, `history show`, `history metrics`, `history judges`,
|
|
619
|
-
`history fetch`, `strays`,
|
|
629
|
+
`history fetch`, `strays`, the tools `ui`, `lsp`, `judge` (`judge answer`,
|
|
620
630
|
`judge run`) — are listed in the
|
|
621
|
-
[CLI reference](https://github.com/pmelab/gtd/blob/main/docs/cli.md).
|
|
631
|
+
[CLI reference](https://github.com/pmelab/gtd/blob/main/docs/cli.md). Every
|
|
632
|
+
command that prints a script takes `--json=script`, and `--` ends the options.
|
|
633
|
+
|
|
634
|
+
`gtd bundle` prints a pin: gtd's engine and the current workflow, npm packages
|
|
635
|
+
included, as one gzipped ES module after a plain-text
|
|
636
|
+
`gtdpin <format> gtd <version>` line. A workflow using a package with a native
|
|
637
|
+
addon cannot be pinned.
|
|
622
638
|
|
|
623
639
|
## License
|
|
624
640
|
|
package/claude/hooks/doors.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Doors are the workflow's named shortcuts into a process (`gtd
|
|
1
|
+
// Doors are the workflow's named shortcuts into a process (`gtd start` lists them). gtd
|
|
2
2
|
// prints the script that starts one; running it is the driver's job, as with
|
|
3
3
|
// every git write gtd plans. The mod hardcodes no door: it asks gtd.
|
|
4
4
|
|
|
@@ -12,19 +12,23 @@ export type Door = {
|
|
|
12
12
|
|
|
13
13
|
const fail = (text: string): Shipped => ({ ok: false, text })
|
|
14
14
|
|
|
15
|
+
type Startable = { kind: "workflow"; name: string } | ({ kind: "door" } & Door)
|
|
16
|
+
|
|
15
17
|
// Every door the repository offers; none when gtd cannot say.
|
|
16
18
|
export async function doors(io: ShipIo): Promise<Door[]> {
|
|
17
|
-
const listed = await io.run(["gtd", "
|
|
19
|
+
const listed = await io.run(["gtd", "start", "--json"])
|
|
18
20
|
if (listed.code !== 0) return []
|
|
19
21
|
try {
|
|
20
|
-
return JSON.parse(listed.out) as
|
|
22
|
+
return (JSON.parse(listed.out) as Startable[]).flatMap((s) =>
|
|
23
|
+
s.kind === "door" ? [{ name: s.name, workflow: s.workflow, args: s.args }] : [],
|
|
24
|
+
)
|
|
21
25
|
} catch {
|
|
22
26
|
return []
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
export async function enter(io: ShipIo, name: string, args: string[]): Promise<Shipped> {
|
|
27
|
-
const argv = ["gtd", "
|
|
31
|
+
const argv = ["gtd", "start", name, ...args]
|
|
28
32
|
const planned = await io.run(argv)
|
|
29
33
|
if (planned.code !== 0)
|
|
30
34
|
return fail(planned.err.trim() || `${argv.join(" ")} exited ${planned.code}`)
|