@pmelab/gtd 10.0.0 → 10.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/README.md CHANGED
@@ -256,14 +256,19 @@ coding agent:
256
256
  ```
257
257
 
258
258
  It prints a self-contained briefing that teaches the agent to set the project
259
- up, build two commands for itself in whatever shell or runtime it runs, and ask
259
+ up, build four commands for itself in whatever shell or runtime it runs, and ask
260
260
  you what you want before it starts driving. You get one prompt to paste, not a
261
- state name to choose. The two commands: a **loop command** that drives beats
262
- until the process rests, and an **edit command** that opens the steering file
263
- the process is waiting on right now — falling back to `.gtd/TODO.md` when the
264
- resting state declares none. That fallback is also how you begin: on a clean
265
- repository the edit command opens the empty `.gtd/TODO.md`, and whatever you
266
- write there is the first sketch the whole process gets planned from.
261
+ state name to choose. The four commands: **`gtd-build`** drives beats until the
262
+ process rests; **`gtd-edit`** opens the steering file the process is waiting on
263
+ right now — falling back to `.gtd/TODO.md` when the resting state declares none;
264
+ **`gtd-review <commitish>`** starts a review round over that commitish and
265
+ drives it; **`gtd-fix`** enters the fix process and drives it. The
266
+ `.gtd/TODO.md` fallback is also how you begin: on a clean repository the edit
267
+ command opens the empty `.gtd/TODO.md`, and whatever you write there is the
268
+ first sketch the whole process gets planned from. As a final step, if it finds
269
+ an LSP-capable editor, the briefing also offers to wire up live diagnostics and
270
+ review actions in it — asking first and naming the exact file, and merging
271
+ rather than overwriting your editor's config.
267
272
 
268
273
  ### The workflow it ships with
269
274
 
@@ -205905,6 +205905,24 @@ f="$(gtd next --json=file)"
205905
205905
  f="\${f:-.gtd/TODO.md}"
205906
205906
  mkdir -p "$(dirname "$f")"
205907
205907
  exec "\${EDITOR:-vi}" "$f"`;
205908
+ const REVIEW_COMMAND = `#!/usr/bin/env sh
205909
+ set -eu
205910
+ GTD_BUILD=~/.local/bin/gtd-build
205911
+ if [ -z "\${1:-}" ]; then
205912
+ echo "usage: gtd-review <commitish>" >&2
205913
+ exit 2
205914
+ fi
205915
+ cd "$(git rev-parse --show-toplevel)"
205916
+ script="$(gtd --entry review-gate.check --var reviewBase="$1")"
205917
+ sh -c "$script"
205918
+ exec "$GTD_BUILD"`;
205919
+ const FIX_COMMAND = `#!/usr/bin/env sh
205920
+ set -eu
205921
+ GTD_BUILD=~/.local/bin/gtd-build
205922
+ cd "$(git rev-parse --show-toplevel)"
205923
+ script="$(gtd --entry fix-precheck)"
205924
+ sh -c "$script"
205925
+ exec "$GTD_BUILD"`;
205908
205926
  const HEADER = () => `gtd ${GTD_VERSION$1} — driver protocol\n\ngtd decides and prints; the driver executes. gtd never runs git, never runs\nyour agent, never runs a check script, and never runs a steering mode's own\nformat:/validate: command either — that pair is text in the script gtd next\n--json's validate field (or gtd validate) prints, for the driver to run\nitself ahead of gtd land.\n`;
205909
205927
  const BEAT_PROTOCOL = `
205910
205928
  ## The beat protocol
@@ -206082,14 +206100,14 @@ since moved refuses loudly instead of corrupting anything. Scripts are
206082
206100
  re-runnable and assert their own HEAD precondition — a driver needs no retry
206083
206101
  logic beyond "ask gtd again".
206084
206102
  `;
206085
- const referenceImplementation = () => `
206086
- ## Building the user's driver: interview first, then adapt
206103
+ const commandSuite = () => `
206104
+ ## Building the user's command suite: interview first, then adapt
206087
206105
 
206088
- The obligations above are the contract; the sh block below is one WORKED
206089
- EXAMPLE of it. Do not copy it blindly, and do not guess the user's setup —
206090
- INVESTIGATE first, then INTERVIEW, then build a driver shaped by both. Hold
206091
- ONE conversation, not two: the setup steps below come first, because a repo
206092
- that is not set up yet cannot be driven, and the driver-shape questions
206106
+ The obligations above are the contract; the four command bodies below are one
206107
+ WORKED EXAMPLE of it. Do not copy them blindly, and do not guess the user's
206108
+ setup — INVESTIGATE first, then INTERVIEW, then build a suite shaped by both.
206109
+ Hold ONE conversation, not four: the setup steps below come first, because a
206110
+ repo that is not set up yet cannot be driven, and the suite-shape questions
206093
206111
  follow in the same numbered list.
206094
206112
 
206095
206113
  1. **Investigate the repository and ask the user what they want before
@@ -206108,29 +206126,59 @@ follow in the same numbered list.
206108
206126
  uncommitted config is a pending change, so starting a process without
206109
206127
  committing it first turns the config into the very first thing the
206110
206128
  process plans against. Commit it, THEN start driving.
206111
- 4. **Which agent should run the turns?** Whatever coding-agent CLI they
206112
- already use (default: \`claude\`). Map \`session.id\`/\`session.resume\`
206113
- onto THAT agent's continuation mechanism (obligation 5); an agent with
206114
- no session concept just ignores them — memory is an optimization, every
206115
- prompt is self-contained.
206116
- 5. **Under which permission model?** Fully autonomous turns (e.g.
206129
+ 4. **Which agent should run the turns?** Probe \`PATH\` for the known
206130
+ coding-agent CLIs — \`claude\`, \`codex\`, \`gemini\`, \`cursor-agent\`,
206131
+ \`aider\`, \`opencode\`, \`amp\` — show the user which are actually
206132
+ installed, and ask which one to drive with (default: \`claude\`). Accept
206133
+ a name that was not on the list; the probe is a convenience, not a
206134
+ restriction. The chosen CLI's own flags then replace the \`claude\` lines
206135
+ in the reference body below — its session flags (obligation 5) and its
206136
+ permission model (question 5).
206137
+ 5. **Under which permission model, and should the workflow's model hints be
206138
+ honored at all?** Fully autonomous turns (e.g.
206117
206139
  \`--dangerously-skip-permissions\`), a sandbox, or the agent's default
206118
- prompting — their risk tolerance, their call. Also whether the workflow's
206119
- own \`model\` hints should be honored (default: yes).
206120
- 6. **How do they want to invoke it?** A command on PATH (default:
206121
- \`~/.local/bin/gtd-loop\`), a project task-runner entry, a CI job step —
206122
- or no artifact at all: YOU drive the beats yourself, following the
206123
- obligations directly. Pick the runtime to match: bash, their language of
206124
- choice, anything that reads \`--json=<path>\` and spawns subprocesses.
206140
+ prompting — their risk tolerance, their call. Also ask whether the
206141
+ workflow's own \`model\` hints (resolved in question 6 below) should be
206142
+ honored (default: yes) — answering no means dropping \`--model\` entirely
206143
+ from every prompt line and writing no model exports, so every turn runs
206144
+ on the chosen CLI's own default tier.
206145
+ 6. **If model hints are honored, resolve them to real model identifiers.**
206146
+ The bundled workflow ships \`plannerModel: smart\` and \`coderModel: base\`.
206147
+ **Those are opaque hints, not model names** — gtd never interprets them,
206148
+ and passing \`--model smart\` to a real CLI fails on the first prompt
206149
+ beat. Derive the chosen CLI's own available models at install time — its
206150
+ \`--help\`, its docs, its own config — never a hardcoded table (a vendor
206151
+ renames a model and a baked-in list goes stale the day it ships). **When
206152
+ the heavier/cheaper mapping is not obvious, ask**: list the CLI's models
206153
+ and let the user pick one per tier — the heavier tier for
206154
+ \`plannerModel\` (triage, design, review), the cheaper tier for
206155
+ \`coderModel\` (build, fix). Write the resolved names as
206156
+ \`GTD_PLANNERMODEL\`/\`GTD_CODERMODEL\` exports at the top of \`gtd-build\`,
206157
+ wrapped in \`# gtd-install: model exports\` / \`# gtd-install: end\`
206158
+ markers — NOT into \`.gtdrc\`. They stay per machine and are never
206159
+ committed, so one person's model choice binds nobody else on the repo.
206160
+ Two consequences follow, both worth stating to the user: \`gtd-review\`
206161
+ and \`gtd-fix\` inherit these exports only because they \`exec\`
206162
+ \`gtd-build\` — anything that drives beats without going through
206163
+ \`gtd-build\` sees the raw \`smart\`/\`base\` hints and fails; and \`GTD_*\` is
206164
+ the highest-precedence config layer, so these exports silently win over
206165
+ a \`plannerModel\`/\`coderModel\` a teammate later commits to \`.gtdrc\`.
206125
206166
  7. **What should happen at the boundaries?** Where the log goes (obligation
206126
206167
  4), and whether halting at a human gate should do anything richer than
206127
206168
  print — desktop notification, terminal-multiplexer status, editor focus —
206128
206169
  which belongs in their wrapper, never in gtd.
206129
- 8. **Which editor should the edit command spawn?** Default \`$EDITOR\`, never
206130
- a hardcoded editor.
206131
- 9. **What should the edit command be named?** Suggest
206132
- \`~/.local/bin/gtd-edit\`, matching the loop command's own default
206133
- (\`~/.local/bin/gtd-loop\`) — the interview can override either name.
206170
+ 8. **How do they want to invoke it?** A command on PATH (default:
206171
+ \`~/.local/bin/gtd-build\`), a project task-runner entry, a CI job step —
206172
+ or no artifact at all: YOU drive the beats yourself, following the
206173
+ obligations directly. Pick the runtime to match: bash, their language of
206174
+ choice, anything that reads \`--json=<path>\` and spawns subprocesses.
206175
+ 9. **Where should the suite live, which editor should \`gtd-edit\` spawn, and
206176
+ does anything need renaming?** Suggest \`~/.local/bin\` for all four —
206177
+ \`gtd-build\`, \`gtd-edit\`, \`gtd-review\`, \`gtd-fix\` — and \`$EDITOR\` (never
206178
+ a hardcoded editor) for the one that opens files. The interview can
206179
+ rename any of the four; whatever name is chosen for \`gtd-build\` is the
206180
+ RESOLVED path baked into \`GTD_BUILD\` in the other two bodies below —
206181
+ never the literal string \`gtd-build\`.
206134
206182
 
206135
206183
  Then build it, and verify safely before the first real drive:
206136
206184
  \`gtd next --json=<path>\`/\`gtd next\` are both pure reads — read/parse them,
@@ -206138,20 +206186,20 @@ check your kind dispatch against the table above, call them as often as you
206138
206186
  like. Nothing happens until you run an emitted script.
206139
206187
 
206140
206188
  The reference rendering in sh (no \`jq\`, no JSON parser at all — each
206141
- \`--json=<path>\` call prints its one value directly; the \`claude\` lines are
206142
- what answers 1–2 replace):
206189
+ \`--json=<path>\` call prints its one value directly). Two of the four bodies
206190
+ below share one convention: \`GTD_BUILD\` is set once, at the top, to the
206191
+ suite's resolved \`gtd-build\` path.
206192
+
206193
+ ### \`gtd-build\` — the driver loop
206194
+
206195
+ The \`claude\` lines are what interview answers 4 and 6 replace. Default path:
206196
+ \`~/.local/bin/gtd-build\`.
206143
206197
 
206144
206198
  \`\`\`bash
206145
206199
  ${MINIMAL_DRIVER}
206146
206200
  \`\`\`
206147
- `;
206148
- const editCommand = () => `
206149
- ## Building the user's edit command
206150
206201
 
206151
- The loop command above drives beats; it never opens a file for the human. Add
206152
- a second artifact to the same interview (questions 8–9 above): an edit
206153
- command that opens the steering file the process is resting at right now,
206154
- suggested at \`~/.local/bin/gtd-edit\`.
206202
+ ### \`gtd-edit\` — open the steering file the process is resting at
206155
206203
 
206156
206204
  \`gtd next --json=file\` already reports the file for every state that
206157
206205
  declares one — the edit command needs no new engine surface, just a read and
@@ -206171,12 +206219,115 @@ the first sketch the whole process gets planned from. The same command does
206171
206219
  the same thing at every rest, whether or not a state declares a \`file:\`.
206172
206220
 
206173
206221
  The edit command stops when the editor exits — it never drives the loop. It
206174
- opens a file and returns; the human runs the loop command themselves when
206175
- they are ready.
206222
+ opens a file and returns; the human runs \`gtd-build\` themselves when they
206223
+ are ready. Default path: \`~/.local/bin/gtd-edit\`.
206176
206224
 
206177
206225
  \`\`\`bash
206178
206226
  ${EDIT_COMMAND}
206179
206227
  \`\`\`
206228
+
206229
+ ### \`gtd-review <commitish>\` — start a review round and drive it
206230
+
206231
+ Runs \`gtd --entry review-gate.check --var reviewBase=<commitish>\`, captured
206232
+ by command substitution — never a pipe: a pipeline reports only its LAST
206233
+ command's exit status, so \`gtd --entry ... | sh\` under \`set -e\` would sail
206234
+ past a refusal and \`exec\` a loop over a process that was never started. It
206235
+ runs the captured script, then \`exec\`s the suite's RESOLVED \`gtd-build\`
206236
+ path — never the literal string \`gtd-build\`. This is one invocation that
206237
+ carries the review all the way to its next human gate, not just a starter:
206238
+ \`gtd-review\` on a RED baseline hands off to \`gtd-build\`, which halts at the
206239
+ blocked gate and prints it, rather than starting the review. Refuses with
206240
+ \`usage: gtd-review <commitish>\` on stderr and exit \`2\` when the commitish is
206241
+ missing — nothing was even attempted. Default path: \`~/.local/bin/gtd-review\`.
206242
+
206243
+ \`\`\`bash
206244
+ ${REVIEW_COMMAND}
206245
+ \`\`\`
206246
+
206247
+ ### \`gtd-fix\` — enter the fix process and drive it
206248
+
206249
+ Runs \`gtd --entry fix-precheck\`, captured the same way, then \`exec\`s the
206250
+ suite's RESOLVED \`gtd-build\` path. \`gtd-fix\` on a GREEN suite is a no-op
206251
+ straight back to \`idle\` — the exec'd \`gtd-build\` exits immediately on it.
206252
+ Default path: \`~/.local/bin/gtd-fix\`.
206253
+
206254
+ \`\`\`bash
206255
+ ${FIX_COMMAND}
206256
+ \`\`\`
206257
+ ${REINSTALL}`;
206258
+ const REINSTALL = `
206259
+ ## Re-installing: detect and adapt, don't blindly overwrite
206260
+
206261
+ A second install on a machine that already has a suite is not a fresh
206262
+ install — read each of the four suite paths before writing anything
206263
+ (\`gtd-build\`, \`gtd-edit\`, \`gtd-review\`, \`gtd-fix\`), and branch per path:
206264
+
206265
+ - Absent — install it, as in a fresh install.
206266
+ - Present and content-equal to what this gtd version would emit — say so,
206267
+ change nothing, and skip that command's interview questions entirely.
206268
+ - Present and different — show the difference, name the likely cause (a gtd
206269
+ upgrade, or the user's own edit), and ask before overwriting. Never
206270
+ silently replace a file the user may have customised.
206271
+ - Unreadable, or present as a directory instead of a file — report it and
206272
+ ask about it, the same as a differing file. Never overwritten.
206273
+
206274
+ Drift is detected by comparing CONTENT, never by parsing a version out of
206275
+ the installed file — an installed command carries no version marker to
206276
+ parse.
206277
+
206278
+ \`gtd-build\` needs one exemption before that comparison: the region between
206279
+ \`# gtd-install: model exports\` and \`# gtd-install: end\` gets stripped from
206280
+ the installed file first. A \`gtd-build\` differing only inside those
206281
+ markers is unchanged, and re-asks nothing — the resolved model names are
206282
+ per machine, so without this exemption every single re-install would
206283
+ report drift on the one command everybody has.
206284
+
206285
+ This check scopes to exactly the four suite paths above. \`gtd-loop\` is
206286
+ outside it entirely — never read, never diffed, never touched by it in any
206287
+ way — an existing \`gtd-loop\` survives untouched beside the new
206288
+ \`gtd-build\`, and cleaning it up is the human's own call.
206289
+ `;
206290
+ const EDITOR_INTEGRATION = `
206291
+ ## Editor integration: offer it, don't bury it
206292
+
206293
+ \`gtd lsp\` runs a language server, started by \`gtd lsp\` itself, speaking LSP
206294
+ over \`stdio\`, applying to files under \`.gtd/\`. That is the whole integration
206295
+ contract, identical for every editor — this briefing names no specific editor
206296
+ and carries no per-editor config recipe.
206297
+
206298
+ Find the user's editor from their OWN shell configuration, never a guess:
206299
+ check \`$EDITOR\`/\`$VISUAL\` first, then look for an alias or export in their
206300
+ shell rc files (\`.zshrc\`, \`.bashrc\`, \`.config/fish/config.fish\`). Ask the
206301
+ user outright when that turns up nothing or turns up more than one. When the
206302
+ shell configuration names no editor and the user names none either, say
206303
+ nothing and move on — don't pitch editor integration to somebody with no
206304
+ editor to integrate.
206305
+
206306
+ Once an editor is identified, look ITS OWN LSP configuration format up
206307
+ yourself — there is no bundled recipe for it. If it is LSP-capable, offer to
206308
+ wire \`gtd lsp\` up with a brief explanation (three or four lines, not a copy
206309
+ of \`docs/setup.md\`): live diagnostics on \`.gtd/\` steering files, an outline
206310
+ of what is left to review, click-to-check review hunks, pick-an-option
206311
+ actions on open questions, and a \`gtd.openSteeringFile\` command that jumps
206312
+ to the current state's file. Two facts belong in that offer because both
206313
+ bite on a fresh repo: \`gtd lsp\` never creates \`.gtd/\`, so
206314
+ \`gtd.openSteeringFile\` may point at a path that does not exist yet before
206315
+ the first sketch; and \`gtd lsp\` needs no repository root — it is one of the
206316
+ commands that skips the root guard.
206317
+
206318
+ On yes, edit the editor's own config file yourself — never print a snippet
206319
+ and walk away. Integration works without the human touching anything. Three
206320
+ guards apply to that write, because it lands outside the repository in a
206321
+ file the user shares across every project:
206322
+
206323
+ - **Ask first, per editor, naming the exact file** about to change. Silence
206324
+ is not consent for a machine-wide config.
206325
+ - **Merge, never overwrite.** Read the existing config, add only the gtd
206326
+ language-server entry, and leave every other key byte-identical.
206327
+ - **Skip and report when the entry is already present** — a second install
206328
+ must not append a duplicate server registration. A malformed existing
206329
+ config (unparseable JSON, a TOML syntax error) is a stop-and-report, not a
206330
+ rewrite: name the file that could not be parsed and leave it untouched.
206180
206331
  `;
206181
206332
  const PREREQUISITES = `
206182
206333
  ## Prerequisites and portability
@@ -206193,7 +206344,7 @@ const PREREQUISITES = `
206193
206344
  Any runtime works: the contract is \`--json\`/\`--json=<path>\` in, subprocesses
206194
206345
  out.
206195
206346
  `;
206196
- const renderBriefing = () => HEADER() + BEAT_PROTOCOL + JSON_FIELD_REFERENCE + DRIVER_OBLIGATIONS + RECOVERY + referenceImplementation() + editCommand() + PREREQUISITES;
206347
+ const renderBriefing = () => HEADER() + BEAT_PROTOCOL + JSON_FIELD_REFERENCE + DRIVER_OBLIGATIONS + RECOVERY + commandSuite() + EDITOR_INTEGRATION + PREREQUISITES;
206197
206348
  //#endregion
206198
206349
  //#region src/Select.ts
206199
206350
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmelab/gtd",
3
- "version": "10.0.0",
3
+ "version": "10.1.0",
4
4
  "private": false,
5
5
  "description": "Git-aware CLI that emits the next prompt for an autonomous coding agent based on the current repository state",
6
6
  "bin": {