@pmelab/gtd 59.0.0 → 60.0.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 +42 -38
- 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-CMBAAyRK.mjs → testkit-BvecVjQ0.mjs} +937 -772
- package/dist/chunks/{wire-C12dahrH.mjs → wire-DZ8R1RU9.mjs} +9 -2
- package/dist/flows.mjs +2 -676
- package/dist/gtd.bundle.mjs +1101 -1025
- package/dist/steering.mjs +2 -2
- package/dist/testkit/gherkin.mjs +371 -82
- 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 +1 -1
- package/skills/authoring/SKILL.md +68 -61
- package/src/cli/Cli.test.ts +311 -229
- package/src/cli/Cli.ts +486 -585
- package/src/cli/Help.test.ts +47 -0
- package/src/cli/Help.ts +70 -0
- 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 +31 -1
- package/src/cli/Program.test.ts +131 -82
- package/src/cli/Program.ts +197 -111
- package/src/edge/Edge.test.ts +64 -56
- package/src/edge/Edge.ts +4 -4
- package/src/emit/Emit.test.ts +1 -1
- package/src/emit/Emit.ts +1 -1
- package/src/flows/factory.test.ts +14 -0
- package/src/flows/factory.ts +25 -6
- 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 +188 -54
- package/src/gherkin/git-control.feature +6 -6
- package/src/gherkin/index.test.ts +127 -0
- package/src/gherkin/index.ts +481 -98
- package/src/gherkin/messages.test.ts +124 -0
- package/src/gherkin/messages.ts +101 -0
- 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/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 +9 -9
- package/src/testkit/TestRepo.test.ts +289 -6
- package/src/testkit/TestRepo.ts +317 -41
- 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 +7 -14
- package/src/twins/EmittedScripts.test.ts +4 -2
- package/src/twins/InMemRepo.ts +1 -0
- package/src/wire/Land.ts +1 -1
- 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 +3 -3
- package/src/workflow/load.test.ts +256 -116
- package/src/workflow/load.ts +175 -152
- package/src/workflow/skills.test.ts +5 -5
- package/src/workflow/skills.ts +1 -1
- 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/README.md
CHANGED
|
@@ -57,9 +57,9 @@ driver enforces it at the OS level. See
|
|
|
57
57
|
|
|
58
58
|
> **A repository's `gtd.config.ts` is code, and gtd runs it.** A custom workflow
|
|
59
59
|
> is a TypeScript module, and every gtd command that looks at workflow state —
|
|
60
|
-
> `gtd next`, `gtd lsp
|
|
61
|
-
>
|
|
62
|
-
>
|
|
60
|
+
> `gtd next`, `gtd lsp` and `gtd start` included, not just `gtd land` —
|
|
61
|
+
> evaluates it. Treat it like a Makefile or a `package.json` script: don't run
|
|
62
|
+
> gtd in a checkout you don't trust.
|
|
63
63
|
|
|
64
64
|
## Quick start
|
|
65
65
|
|
|
@@ -67,7 +67,7 @@ Put a `gtd.config.ts` at your repository's root (see [Install](#install)) and
|
|
|
67
67
|
commit it; gtd refuses to run without one. The repository need not be a
|
|
68
68
|
JavaScript project: gtd resolves the config's `@pmelab/gtd/*` imports itself, so
|
|
69
69
|
a Python, Rust or notes repository needs no `package.json` and no install. Then
|
|
70
|
-
run `gtd
|
|
70
|
+
run `gtd guide`: it writes nothing and prints a briefing (and where to get a
|
|
71
71
|
workflow, if you have none yet). Pipe that briefing into your coding agent and
|
|
72
72
|
answer its questions. It should build you a script that will autonomously run
|
|
73
73
|
the process for you. Ask your agent if you have any questions.
|
|
@@ -155,14 +155,14 @@ gtd land
|
|
|
155
155
|
|
|
156
156
|
```
|
|
157
157
|
commit everything with this message: gtd(human): idle → unwind
|
|
158
|
-
(
|
|
158
|
+
(to land it: s=$(gtd land --json=script) && sh -c "$s")
|
|
159
159
|
```
|
|
160
160
|
|
|
161
161
|
You could run that commit by hand. Take the script instead — it spells out the
|
|
162
162
|
exact message and reports what landed:
|
|
163
163
|
|
|
164
164
|
```bash
|
|
165
|
-
gtd land --json=script
|
|
165
|
+
s=$(gtd land --json=script) && sh -c "$s"
|
|
166
166
|
```
|
|
167
167
|
|
|
168
168
|
```
|
|
@@ -205,7 +205,7 @@ before:
|
|
|
205
205
|
|
|
206
206
|
```bash
|
|
207
207
|
sh -c "$(gtd next --json=content)"
|
|
208
|
-
gtd land --json=script
|
|
208
|
+
s=$(gtd land --json=script) && sh -c "$s"
|
|
209
209
|
```
|
|
210
210
|
|
|
211
211
|
`--json=<field>` is how a script reads one value out of a beat. Bare `--json`
|
|
@@ -263,7 +263,7 @@ gtd next | claude -p --dangerously-skip-permissions
|
|
|
263
263
|
**The turn ends when `claude -p` returns** — a command the agent backgrounds
|
|
264
264
|
dies unread, and the process stalls on an empty turn. Claude Code lets the agent
|
|
265
265
|
background commands and caps foreground ones at 10 minutes by default, so a real
|
|
266
|
-
driver exports these first (`gtd
|
|
266
|
+
driver exports these first (`gtd guide`'s reference driver does):
|
|
267
267
|
|
|
268
268
|
```bash
|
|
269
269
|
export CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1
|
|
@@ -278,7 +278,7 @@ The prompt tells the agent to asses your request and write
|
|
|
278
278
|
`.gtd/REQUIREMENTS.md`, and that file is the turn. Land it like any other beat:
|
|
279
279
|
|
|
280
280
|
```bash
|
|
281
|
-
gtd land --json=script
|
|
281
|
+
s=$(gtd land --json=script) && sh -c "$s"
|
|
282
282
|
```
|
|
283
283
|
|
|
284
284
|
`gtd next --json=validate` is there if you want to check the agent's work first:
|
|
@@ -303,7 +303,7 @@ while :; do
|
|
|
303
303
|
# Nothing left to do, abort.
|
|
304
304
|
stalled) gtd next >&2; exit 1 ;;
|
|
305
305
|
esac
|
|
306
|
-
gtd land --json=script
|
|
306
|
+
s=$(gtd land --json=script) && sh -c "$s"
|
|
307
307
|
done
|
|
308
308
|
```
|
|
309
309
|
|
|
@@ -346,9 +346,9 @@ The requirements go to the top of `.gtd/TODO.md`, above whatever it already
|
|
|
346
346
|
holds. A long, multi-line requirements paste still starts a process; if Claude
|
|
347
347
|
Code never expanded the paste, gtd says it could not read it, and you add the
|
|
348
348
|
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
|
|
349
|
+
takes one of the doors a bare `gtd start` lists (gtd-workflows' `default` brings
|
|
350
|
+
`fix`, `review [base]`, and `rollout <flag>` and `cleanup <flag>` where the
|
|
351
|
+
config exports them); text whose word count does not fit a door's args (bare
|
|
352
352
|
`/gtd rollout` included) starts a process from that text as requirements. At
|
|
353
353
|
every human rest Claude itself takes over: it walks you through the open
|
|
354
354
|
questions one at a time, answers your own questions about the plan or the diff,
|
|
@@ -381,7 +381,7 @@ But lets be honest, who reads documentation these days. Paste this into your
|
|
|
381
381
|
coding agent:
|
|
382
382
|
|
|
383
383
|
```
|
|
384
|
-
!gtd
|
|
384
|
+
!gtd guide
|
|
385
385
|
```
|
|
386
386
|
|
|
387
387
|
It prints a self-contained briefing that teaches the agent to set the project
|
|
@@ -390,8 +390,8 @@ you what you want before it starts driving. You get one prompt to paste, not a
|
|
|
390
390
|
state name to choose. The four commands: **`gtd-build`** drives beats until the
|
|
391
391
|
process rests; **`gtd-edit`** opens the steering file the process is waiting on
|
|
392
392
|
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
|
|
393
|
+
**`gtd-door <name> [args...]`** starts a process through one of the doors a bare
|
|
394
|
+
`gtd start` lists (`gtd-door fix`, `gtd-door review [base]` with gtd-workflows'
|
|
395
395
|
`default`) and drives it. The `.gtd/TODO.md` fallback is also how you begin: on
|
|
396
396
|
a clean repository the edit command opens the empty `.gtd/TODO.md`, and whatever
|
|
397
397
|
you write there is the first sketch the whole process gets planned from. As a
|
|
@@ -447,9 +447,9 @@ The workflow itself is a plain async TypeScript function, and the
|
|
|
447
447
|
`gtd.config.ts` at the repository root names it. A workflow may be a factory —
|
|
448
448
|
`feature({ testCommand: "npm run ci" })` — whose options gtd validates when it
|
|
449
449
|
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
|
|
450
|
+
workflow, the key and what was expected. `gtd start` lists the workflows your
|
|
451
|
+
config exports and the doors they bring, and `gtd start <name> [args...]` starts
|
|
452
|
+
one by name; a door named like a workflow wins. See
|
|
453
453
|
[Configuration](https://github.com/pmelab/gtd/blob/main/docs/configuration.md) —
|
|
454
454
|
and remember gtd evaluates that file on every command. A shared workflow package
|
|
455
455
|
bundling its own `@pmelab/gtd` is checked against the running gtd and refused,
|
|
@@ -484,14 +484,16 @@ doesn't lose it. `/gtd ship` pushes this process's own ref to origin alongside
|
|
|
484
484
|
the branch (never the others) and writes a `Gtd-History: <ref>` trailer on the
|
|
485
485
|
squashed commit. The push is forced, so it replaces origin's copy of that one
|
|
486
486
|
ref. If that push fails, the ship fails and nothing is squashed. Recover the
|
|
487
|
-
full trail with `gtd history fetch
|
|
487
|
+
full trail with `s=$(gtd history fetch --json=script) && sh -c "$s"`, then
|
|
488
|
+
`gtd history show <ref>`.
|
|
488
489
|
|
|
489
490
|
```sh
|
|
490
491
|
gtd history list # one line per kept process
|
|
491
492
|
gtd history show <ref> # replay its steps, judge verdicts and approvals
|
|
492
493
|
gtd history metrics [ref...] # how the kept processes went, per process and in total
|
|
493
494
|
gtd history judges [ref...] # how often each judge's verdicts were overturned
|
|
494
|
-
|
|
495
|
+
# pull every kept ref from origin
|
|
496
|
+
s=$(gtd history fetch --json=script) && sh -c "$s"
|
|
495
497
|
```
|
|
496
498
|
|
|
497
499
|
`gtd history metrics` measures gtd-workflows' `default` `feature` workflow from
|
|
@@ -537,12 +539,13 @@ contradicts it:
|
|
|
537
539
|
|
|
538
540
|
Any other verdict has no outcome. The report counts verdicts, scored verdicts
|
|
539
541
|
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
|
|
542
|
+
overturned). `--threshold <name>=<value>` (formerly `--var`) re-decides every
|
|
543
|
+
past verdict under another threshold and prints the decisions that would change,
|
|
544
|
+
against the threshold each process recorded (a process that recorded none is
|
|
545
|
+
left out):
|
|
543
546
|
|
|
544
547
|
```sh
|
|
545
|
-
gtd history judges --
|
|
548
|
+
gtd history judges --threshold qualityTriageMinP=0.9
|
|
546
549
|
# what-if qualityTriageMinP=0.9: 7 noise drops become notes (2 overturned)
|
|
547
550
|
```
|
|
548
551
|
|
|
@@ -600,25 +603,26 @@ approvals as `approvals` (`[]` when none), and `gtd history show` prints each as
|
|
|
600
603
|
gtd is one package, `@pmelab/gtd`, and every entrypoint shares its version and
|
|
601
604
|
[SemVer promise](https://github.com/pmelab/gtd/blob/main/COMPATIBILITY.md).
|
|
602
605
|
|
|
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.
|
|
606
|
+
| Import | What it is |
|
|
607
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
608
|
+
| `@pmelab/gtd/flows` | The flow API a workflow is written in: the steps (`agent`, `human`, `run`, …), `scope`, `workflow()`, workflow factories, `defineConfig` and `FLOWS_PROTOCOL`. |
|
|
609
|
+
| `@pmelab/gtd/wire` | The driver protocol: `WIRE_SCHEMA`, the exit codes and the types of every `--json` document. |
|
|
610
|
+
| `@pmelab/gtd/steering` | The steering-file formats (`qa`, `review`, `findings`), the review-note readers, and `sections`, `threads` and `openQuestions` as plain functions. |
|
|
611
|
+
| `@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). |
|
|
612
|
+
| `@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). |
|
|
613
|
+
| `@pmelab/gtd/testkit/gherkin` | The testkit as quickpickle steps for vitest. Needs `vitest` and `quickpickle`, optional peer dependencies. |
|
|
611
614
|
|
|
612
615
|
Types come from the TypeScript sources the package ships. Configs never need an
|
|
613
616
|
install for any of these but the testkit's: gtd resolves a `gtd.config.ts`'s
|
|
614
617
|
`@pmelab/gtd/*` imports to its own copy.
|
|
615
618
|
|
|
616
|
-
The `gtd` bin's commands — `next`, `land`, `
|
|
617
|
-
`check`, `uncheck`, `
|
|
618
|
-
`
|
|
619
|
-
`history fetch`, `strays`,
|
|
619
|
+
The `gtd` bin's commands — `next`, `land`, `start`, `abandon`, `restore`,
|
|
620
|
+
`validate`, `check`, `uncheck`, `guide`, `summary`, `base`, `version`, `help`,
|
|
621
|
+
`history list`, `history show`, `history metrics`, `history judges`,
|
|
622
|
+
`history fetch`, `strays`, the tools `ui`, `lsp`, `judge` (`judge answer`,
|
|
620
623
|
`judge run`) — are listed in the
|
|
621
|
-
[CLI reference](https://github.com/pmelab/gtd/blob/main/docs/cli.md).
|
|
624
|
+
[CLI reference](https://github.com/pmelab/gtd/blob/main/docs/cli.md). Every
|
|
625
|
+
command that prints a script takes `--json=script`, and `--` ends the options.
|
|
622
626
|
|
|
623
627
|
## License
|
|
624
628
|
|
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}`)
|