@pmelab/gtd 6.1.1 → 6.3.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
@@ -54,10 +54,12 @@ Then scaffold a workflow for the repo — run once:
54
54
  gtd init simple # or: gtd init advanced
55
55
  ```
56
56
 
57
- This writes a `.gtdrc.json` with the chosen workflow inline (review and commit
58
- it). gtd ships **no** default workflow: a state command run before `gtd init`
59
- fails, pointing you back here. See
60
- [Configuration](docs/configuration.md#gtd-init) for the two templates.
57
+ This writes a `.gtdrc.json` for the chosen workflow, with each agent state's
58
+ prompt saved as an editable Markdown file under `gtd-prompts/` and referenced
59
+ from the config (review and commit both). Edit a prompt by editing its
60
+ `gtd-prompts/*.md` file — no config edit needed. gtd ships **no** default
61
+ workflow: a state command run before `gtd init` fails, pointing you back here.
62
+ See [Configuration](docs/configuration.md#gtd-init) for the two templates.
61
63
 
62
64
  ## How it works
63
65
 
@@ -104,7 +106,11 @@ machine — two-phase Q&A planning, an architecture phase, task decomposition, a
104
106
  per-task build loop, and a squash finale — walked through at
105
107
  [docs/examples/advanced-workflow.md](docs/examples/advanced-workflow.md). Either
106
108
  way the workflow is just `.gtdrc` config — edit it or write your own (see
107
- [Configuration](docs/configuration.md)).
109
+ [Configuration](docs/configuration.md)). Both templates route every agent
110
+ state's model through two `vars` tiers — `plannerModel` (heavier planning and
111
+ review) and `coderModel` (the coding turns) — so you can repoint the models
112
+ globally in one place (a `vars:` edit or a `GTD_VAR_plannerModel` override)
113
+ instead of per state.
108
114
 
109
115
  `gtd-loop`, installed alongside `gtd`, is a ready-to-run driver for the whole
110
116
  protocol — point it at a repo and it runs the loop until it's your turn. See
@@ -191367,10 +191367,10 @@ var WorktreeReader = class WorktreeReader extends Tag("WorktreeReader")() {
191367
191367
  };
191368
191368
  //#endregion
191369
191369
  //#region src/workflows/advanced.yaml
191370
- var advanced_default = "# The \"advanced\" gtd workflow template — written verbatim into `.gtdrc.json`\n# (nested under a `workflow:` key) by `gtd init advanced`. See\n# docs/examples/advanced-workflow.md for the full state-by-state walkthrough\n# and STATES.md §10 for how it relates to the \"simple\" template.\n#\n# This is the fuller machine: two-phase human-in-the-loop planning\n# (grilling ⇄ grilling-answer for the product plan, architecting ⇄\n# architecting-answer for the technical plan), task decomposition\n# (decompose → .gtd/tasks/), a deterministic per-task builder queue (picking →\n# building → checking/fixing), agent-prepared review (reviewing → await-review),\n# and a squash finale (squashing → done, a `commit:` state that collapses the\n# whole cycle into one commit whose message the agent authored in\n# .gtd/COMMIT_MSG.md).\n#\n# Every content string below is INLINE (no `./`-relative file references): the\n# bundled templates ship inside a single-file build (`dist/gtd.bundle.mjs`), so\n# their content must already be resolved at BUILD time rather than read from\n# disk at RUNTIME. `advanced.yaml` is imported as raw text (tsdown's `.yaml`\n# text loader / the vitest rawMd transform), so this module never touches the\n# filesystem.\n\nvars:\n testCommand: npm test\n todoFile: .gtd/TODO.md\n architectureFile: .gtd/ARCHITECTURE.md\n reviewFile: .gtd/REVIEW.md\n feedbackFile: .gtd/FEEDBACK.md\n\nstates:\n idle:\n actor: human\n initial: true\n message: |\n No active gtd cycle.\n\n To start one: write `.gtd/TODO.md` with a short sketch of what you want\n built — a few sentences is enough — then run `gtd step human`.\n on:\n \"* **\": grilling\n\n grilling:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # `model` is an opaque harness hint — gtd never interprets this string, it\n # only passes it through to `gtd next --json`/`gtd status --json` so the\n # driving loop can map it onto whatever models its agent harness\n # provides. \"smart\" here just names the harness-chosen tier for the\n # heavier planning/reviewing turns; states without a `model` use the\n # harness's default.\n model: smart\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state (plans, task specs, review records) — never create, edit, or\n delete anything under `.gtd/` except `<%= it.vars.todoFile %>`, which\n this prompt tells you to write.\n\n `<%= it.vars.todoFile %>` holds the plan under development. Read it,\n then develop it into a concrete, product-level plan in this one turn —\n explore the codebase before asking anything, so every open question is\n one the codebase genuinely cannot answer.\n\n Scope: product and user-facing decisions only. Leave implementation\n details (file/module structure, data models, tech-stack choices) for\n the next phase (`.gtd/ARCHITECTURE.md`).\n\n For every remaining open question, add it under a `## Open Questions`\n heading, one `### <question>` sub-heading each, with a\n `Suggested default: <answer>` line the human can accept as-is. Omit the\n section entirely once there are none.\n\n Leave `.gtd/TODO.md` uncommitted and finish your turn — do not commit,\n and do not run `gtd step agent` yourself; the harness does that.\n on:\n \"* **\": grilling-answer\n\n grilling-answer:\n actor: human\n file: <%= it.vars.todoFile %>\n mode: qa\n message: |\n `<%= it.vars.todoFile %>` holds the plan under development, with any\n open questions under `## Open Questions` — each carrying a suggested\n default.\n\n To answer a question, edit its entry in place (replace\n `Suggested default: ...` with `Answer: ...`, or annotate further), then\n run `gtd step human`.\n\n To accept all suggested defaults as-is and move on to technical\n architecting, run `gtd step human` with no edits.\n on:\n \"C\": architecting\n \"* **\": grilling\n\n architecting:\n actor: agent\n file: <%= it.vars.architectureFile %>\n mode: qa\n model: smart\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.architectureFile %>` and `<%= it.vars.todoFile %>`, which\n this prompt tells you to write and delete respectively.\n\n Read `<%= it.vars.todoFile %>` (the converged product plan) and\n develop `<%= it.vars.architectureFile %>` from it in this one turn:\n file/module structure, data models, library/tech-stack choices,\n error-handling strategy — the *how*, building on the *what* already\n settled. Do not re-open product-level decisions from\n `<%= it.vars.todoFile %>`; treat them as settled.\n\n For every remaining open question, add it under a `## Open Questions`\n heading the same way as the grilling phase (one `### <question>`\n sub-heading, a `Suggested default: <answer>` line). Omit the section\n once there are none.\n\n Once `<%= it.vars.architectureFile %>` is written, delete\n `<%= it.vars.todoFile %>` — its content has been folded in and it must\n not linger.\n\n Leave everything uncommitted and finish your turn.\n on:\n \"* **\": architecting-answer\n\n architecting-answer:\n actor: human\n file: <%= it.vars.architectureFile %>\n mode: qa\n message: |\n `<%= it.vars.architectureFile %>` holds the technical plan under\n development, with any open questions under `## Open Questions`.\n\n To answer a question, edit its entry in place, then run\n `gtd step human`.\n\n To accept all suggested defaults as-is and move on to decomposing the\n work, run `gtd step human` with no edits.\n on:\n \"C\": decompose\n \"* **\": architecting\n\n decompose:\n actor: agent\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except the\n task-spec files this prompt tells you to write (under `.gtd/tasks/`),\n and `.gtd/ARCHITECTURE.md`, which it tells you to delete.\n\n Read `.gtd/ARCHITECTURE.md` (the converged technical plan) and\n decompose it into an ordered set of self-contained task files under\n `.gtd/tasks/` (e.g. `.gtd/tasks/01-short-name.md`,\n `.gtd/tasks/02-short-name.md`, ...). Order them so the test suite can\n pass again after each one lands; each file is self-contained\n (description, acceptance criteria as `- [ ]` checkboxes, relevant\n paths) since a building turn receives only that one file as context.\n\n No task file may reference any other `.gtd/` file, or a requirement to\n preserve/update workflow state — `.gtd/` is machine-managed and gets\n cleaned up as the cycle proceeds.\n\n Once the task files are written, delete `.gtd/ARCHITECTURE.md`. Leave\n everything uncommitted and finish your turn.\n on:\n \"* .gtd/tasks/**\": picking\n\n picking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn (the queue arbiter) — the loop driver executes this\n # verbatim, then steps the check actor. Mechanics only: take the\n # first task file (by name) under .gtd/tasks/ into .gtd/NEXT.md, or\n # remove .gtd/NEXT.md when the queue is empty. What NEXT.md's\n # presence/absence MEANS (another task to build vs. the queue closing\n # out to review) is decided by this state's own `on` rules at capture\n # time — never here.\n set +e\n next=$(ls .gtd/tasks/*.md 2>/dev/null | head -n 1)\n if [ -n \"$next\" ]; then\n printf '%s' \"$next\" > .gtd/NEXT.md\n else\n rm -f .gtd/NEXT.md\n fi\n on:\n \"D .gtd/NEXT.md\": reviewing\n \"* .gtd/NEXT.md\": building\n \"C\": reviewing\n\n building:\n actor: agent\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create or edit anything under `.gtd/` except deleting the\n one task file this prompt tells you to delete; never touch\n `.gtd/NEXT.md` yourself — the `picking` state owns it.\n\n The task file to implement is: <%~ it.read(\".gtd/NEXT.md\") %>\n\n Read that file and implement EXACTLY the one task it describes — no\n more, no less; leave every other task file under `.gtd/tasks/`\n untouched. Use TDD discipline: one test, then the implementation that\n passes it, then the next — never write all the tests first.\n\n Delete the task file once its work is complete and verified. Leave\n everything else uncommitted and finish your turn.\n on:\n \"* **\": checking\n\n checking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then steps\n # the check actor. Mechanics only: run the test suite and record a\n # red run's output as .gtd/FEEDBACK.md. What that output MEANS (another\n # fix round vs escalation) is decided by the workflow's own `on`/`retry`\n # rules at capture time — never here.\n #\n # `it.vars.testCommand` defaults to \"npm test\" (this workflow's own\n # `vars:` above) — override it with a top-level `.gtdrc`\n # `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`\n # environment variable (highest precedence).\n set +e\n mkdir -p .gtd\n <%~ it.vars.testCommand %> > .gtd/.check-output 2>&1\n code=$?\n if [ \"$code\" -ne 0 ]; then\n if [ -s .gtd/.check-output ]; then\n mv .gtd/.check-output .gtd/FEEDBACK.md\n else\n rm -f .gtd/.check-output\n printf 'npm test failed with exit code %s and produced no output.' \"$code\" > .gtd/FEEDBACK.md\n fi\n else\n rm -f .gtd/.check-output\n fi\n on:\n \"A .gtd/FEEDBACK.md\": fixing\n \"M .gtd/FEEDBACK.md\": fixing\n \"C\": picking\n\n fixing:\n actor: agent\n file: <%= it.vars.feedbackFile %>\n retry:\n max: 3\n otherwise: escalate\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.feedbackFile %>`, which this prompt tells you to address.\n\n Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix\n the code so the suite passes. Keep the change focused — do not\n refactor unrelated code. If the feedback is wrong, empty or delete\n `<%= it.vars.feedbackFile %>` instead of \"fixing\" a non-issue; the\n machine picks the dispute up either way.\n\n Leave everything uncommitted and finish your turn — do not commit.\n on:\n \"* **\": checking\n\n escalate:\n actor: human\n file: <%= it.vars.feedbackFile %>\n message: |\n The agent could not get the check to pass after repeated attempts.\n `<%= it.vars.feedbackFile %>` holds the last failing output.\n\n Investigate and fix it yourself (editing code and/or\n `<%= it.vars.feedbackFile %>`), then run `gtd step human` to try the\n check again.\n on:\n \"* **\": checking\n\n reviewing:\n actor: agent\n file: <%= it.vars.reviewFile %>\n mode: review\n model: smart\n # A direct entry point: `gtd review <commitish>` starts a fresh review\n # process here over `<commitish>..HEAD` (e.g. a colleague's PR branch).\n reviewEntry: true\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.reviewFile %>`, which this prompt tells you to write.\n\n Write `<%= it.vars.reviewFile %>` to help a human review the cycle's\n full diff (inlined below): group hunks semantically (same\n feature/refactor/fix, even across files), and for each group write a\n short heading, an explanation of what changed and why, and\n `- [ ] ./path/to/file.ts#42` style file pointers (checkboxes are for\n the human to tick, not you).\n\n Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"* .gtd/REVIEW.md\": await-review\n\n await-review:\n actor: human\n file: <%= it.vars.reviewFile %>\n mode: review\n message: |\n `<%= it.vars.reviewFile %>` holds the review record for the completed\n cycle.\n\n To approve: delete `<%= it.vars.reviewFile %>` and run\n `gtd step human`.\n\n To request changes: edit `<%= it.vars.reviewFile %>` (or the code)\n with what's wrong — including just ticking its checkboxes — then run\n `gtd step human`; this sends the cycle back through grilling with your\n feedback as the new input.\n on:\n \"D .gtd/REVIEW.md\": squashing\n \"* **\": grilling\n\n squashing:\n actor: agent\n prompt: |\n You are an autonomous coding agent. The cycle is approved and done.\n `.gtd/` holds this workflow's own state — never create, edit, or delete\n anything under `.gtd/` except `.gtd/COMMIT_MSG.md`, which this prompt\n tells you to write.\n\n Write `.gtd/COMMIT_MSG.md` with ONE conventional-commits message for\n the entire cycle (subject line `type(scope): subject`, imperative mood,\n <= 72 characters; a body explaining the why, trade-offs, and key\n decisions). Plain text, no markdown wrapper.\n\n Leave `.gtd/COMMIT_MSG.md` uncommitted and finish your turn — entering\n this file squashes the whole cycle into one commit using its content as\n the message.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"A .gtd/COMMIT_MSG.md\": done\n \"M .gtd/COMMIT_MSG.md\": done\n\n done:\n commit: |\n <%~ it.read(\".gtd/COMMIT_MSG.md\") %>\n\n Token cost: <%= it.processCost %>\n <% it.processCostByModel.forEach(function(m){ %>\n - <%= m.model %>: <%= m.cost %>\n <% }) %>\n";
191370
+ var advanced_default = "# The \"advanced\" gtd workflow template — written verbatim into `.gtdrc.json`\n# (nested under a `workflow:` key) by `gtd init advanced`. See\n# docs/examples/advanced-workflow.md for the full state-by-state walkthrough\n# and STATES.md §10 for how it relates to the \"simple\" template.\n#\n# This is the fuller machine: two-phase human-in-the-loop planning\n# (grilling ⇄ grilling-answer for the product plan, architecting ⇄\n# architecting-answer for the technical plan), task decomposition\n# (decompose → .gtd/tasks/), a deterministic per-task builder queue (picking →\n# building → checking/fixing), agent-prepared review (reviewing → await-review),\n# and a squash finale (squashing → done, a `commit:` state that collapses the\n# whole cycle into one commit whose message the agent authored in\n# .gtd/COMMIT_MSG.md).\n#\n# Every content string below is INLINE (no `./`-relative file references): the\n# bundled templates ship inside a single-file build (`dist/gtd.bundle.mjs`), so\n# their content must already be resolved at BUILD time rather than read from\n# disk at RUNTIME. `advanced.yaml` is imported as raw text (tsdown's `.yaml`\n# text loader / the vitest rawMd transform), so this module never touches the\n# filesystem.\n#\n# `gtd init advanced` DERIVES the scaffolded `.gtdrc.json` from this inline\n# source (src/workflows/templates.ts `renderInitScaffold`): each agent state's\n# `prompt:` below is written out as an editable `gtd-prompts/<state>.md` file\n# and the config value is rewritten to a `./gtd-prompts/<state>.md` reference\n# `compileWorkflowConfig` inlines back at load time. Human `message:`/check\n# `script:` bodies and the `done` `commit:` template stay inline in the config.\n# This YAML stays fully inline regardless — the split happens only at scaffold\n# time, on real disk.\n\nvars:\n testCommand: npm test\n todoFile: .gtd/TODO.md\n architectureFile: .gtd/ARCHITECTURE.md\n reviewFile: .gtd/REVIEW.md\n feedbackFile: .gtd/FEEDBACK.md\n # The two model tiers every agent state draws from (see the model comment at\n # `grilling` below). Both are opaque harness hints — repoint them here (or\n # via a top-level `.gtdrc` `vars:` key / a `GTD_VAR_plannerModel` env var) to\n # change every state on that tier at once.\n plannerModel: smart\n coderModel: base\n\nstates:\n idle:\n actor: human\n initial: true\n message: |\n No active gtd cycle.\n\n To start one: write `.gtd/TODO.md` with a short sketch of what you want\n built — a few sentences is enough — then run `gtd step human`.\n on:\n \"* **\": grilling\n\n grilling:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # `model` is an opaque harness hint — gtd never interprets this string, it\n # only passes it through to `gtd next --json`/`gtd status --json` so the\n # driving loop can map it onto whatever models its agent harness provides.\n # Every agent state draws its tier from a `vars` model entry (see `vars:`\n # above) so the tiers repoint in one place: `plannerModel` (default\n # \"smart\") names the heavier tier for the one-shot planning/architecting/\n # reviewing turns, `coderModel` (default \"base\") the tier for the\n # decompose/build/fix/squash turns.\n model: <%= it.vars.plannerModel %>\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state (plans, task specs, review records) — never create, edit, or\n delete anything under `.gtd/` except `<%= it.vars.todoFile %>`, which\n this prompt tells you to write.\n\n `<%= it.vars.todoFile %>` holds the plan under development. Read it,\n then develop it into a concrete, product-level plan in this one turn —\n explore the codebase before asking anything, so every open question is\n one the codebase genuinely cannot answer.\n\n Scope: product and user-facing decisions only. Leave implementation\n details (file/module structure, data models, tech-stack choices) for\n the next phase (`.gtd/ARCHITECTURE.md`).\n\n For every remaining open question, add it under a `## Open Questions`\n heading, one `### <question>` sub-heading each, with a\n `Suggested default: <answer>` line the human can accept as-is. Omit the\n section entirely once there are none.\n\n Leave `.gtd/TODO.md` uncommitted and finish your turn — do not commit,\n and do not run `gtd step agent` yourself; the harness does that.\n on:\n \"* **\": grilling-answer\n\n grilling-answer:\n actor: human\n file: <%= it.vars.todoFile %>\n mode: qa\n message: |\n `<%= it.vars.todoFile %>` holds the plan under development, with any\n open questions under `## Open Questions` — each carrying a suggested\n default.\n\n To answer a question, edit its entry in place (replace\n `Suggested default: ...` with `Answer: ...`, or annotate further), then\n run `gtd step human`.\n\n To accept all suggested defaults as-is and move on to technical\n architecting, run `gtd step human` with no edits.\n on:\n \"C\": architecting\n \"* **\": grilling\n\n architecting:\n actor: agent\n file: <%= it.vars.architectureFile %>\n mode: qa\n model: <%= it.vars.plannerModel %>\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.architectureFile %>` and `<%= it.vars.todoFile %>`, which\n this prompt tells you to write and delete respectively.\n\n Read `<%= it.vars.todoFile %>` (the converged product plan) and\n develop `<%= it.vars.architectureFile %>` from it in this one turn:\n file/module structure, data models, library/tech-stack choices,\n error-handling strategy — the *how*, building on the *what* already\n settled. Do not re-open product-level decisions from\n `<%= it.vars.todoFile %>`; treat them as settled.\n\n For every remaining open question, add it under a `## Open Questions`\n heading the same way as the grilling phase (one `### <question>`\n sub-heading, a `Suggested default: <answer>` line). Omit the section\n once there are none.\n\n Once `<%= it.vars.architectureFile %>` is written, delete\n `<%= it.vars.todoFile %>` — its content has been folded in and it must\n not linger.\n\n Leave everything uncommitted and finish your turn.\n on:\n \"* **\": architecting-answer\n\n architecting-answer:\n actor: human\n file: <%= it.vars.architectureFile %>\n mode: qa\n message: |\n `<%= it.vars.architectureFile %>` holds the technical plan under\n development, with any open questions under `## Open Questions`.\n\n To answer a question, edit its entry in place, then run\n `gtd step human`.\n\n To accept all suggested defaults as-is and move on to decomposing the\n work, run `gtd step human` with no edits.\n on:\n \"C\": decompose\n \"* **\": architecting\n\n decompose:\n actor: agent\n model: <%= it.vars.coderModel %>\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except the\n task-spec files this prompt tells you to write (under `.gtd/tasks/`),\n and `.gtd/ARCHITECTURE.md`, which it tells you to delete.\n\n Read `.gtd/ARCHITECTURE.md` (the converged technical plan) and\n decompose it into an ordered set of self-contained task files under\n `.gtd/tasks/` (e.g. `.gtd/tasks/01-short-name.md`,\n `.gtd/tasks/02-short-name.md`, ...). Order them so the test suite can\n pass again after each one lands; each file is self-contained\n (description, acceptance criteria as `- [ ]` checkboxes, relevant\n paths) since a building turn receives only that one file as context.\n\n No task file may reference any other `.gtd/` file, or a requirement to\n preserve/update workflow state — `.gtd/` is machine-managed and gets\n cleaned up as the cycle proceeds.\n\n Once the task files are written, delete `.gtd/ARCHITECTURE.md`. Leave\n everything uncommitted and finish your turn.\n on:\n \"* .gtd/tasks/**\": picking\n\n picking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn (the queue arbiter) — the loop driver executes this\n # verbatim, then steps the check actor. Mechanics only: take the\n # first task file (by name) under .gtd/tasks/ into .gtd/NEXT.md, or\n # remove .gtd/NEXT.md when the queue is empty. What NEXT.md's\n # presence/absence MEANS (another task to build vs. the queue closing\n # out to review) is decided by this state's own `on` rules at capture\n # time — never here.\n set +e\n next=$(ls .gtd/tasks/*.md 2>/dev/null | head -n 1)\n if [ -n \"$next\" ]; then\n printf '%s' \"$next\" > .gtd/NEXT.md\n else\n rm -f .gtd/NEXT.md\n fi\n on:\n \"D .gtd/NEXT.md\": reviewing\n \"* .gtd/NEXT.md\": building\n \"C\": reviewing\n\n building:\n actor: agent\n model: <%= it.vars.coderModel %>\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create or edit anything under `.gtd/` except deleting the\n one task file this prompt tells you to delete; never touch\n `.gtd/NEXT.md` yourself — the `picking` state owns it.\n\n The task file to implement is: <%~ it.read(\".gtd/NEXT.md\") %>\n\n Read that file and implement EXACTLY the one task it describes — no\n more, no less; leave every other task file under `.gtd/tasks/`\n untouched. Use TDD discipline: one test, then the implementation that\n passes it, then the next — never write all the tests first.\n\n Delete the task file once its work is complete and verified. Leave\n everything else uncommitted and finish your turn.\n on:\n \"* **\": checking\n\n checking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then steps\n # the check actor. Mechanics only: run the test suite and record a\n # red run's output as .gtd/FEEDBACK.md. What that output MEANS (another\n # fix round vs escalation) is decided by the workflow's own `on`/`retry`\n # rules at capture time — never here.\n #\n # `it.vars.testCommand` defaults to \"npm test\" (this workflow's own\n # `vars:` above) — override it with a top-level `.gtdrc`\n # `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`\n # environment variable (highest precedence).\n set +e\n mkdir -p .gtd\n <%~ it.vars.testCommand %> > .gtd/.check-output 2>&1\n code=$?\n if [ \"$code\" -ne 0 ]; then\n if [ -s .gtd/.check-output ]; then\n mv .gtd/.check-output .gtd/FEEDBACK.md\n else\n rm -f .gtd/.check-output\n printf 'npm test failed with exit code %s and produced no output.' \"$code\" > .gtd/FEEDBACK.md\n fi\n else\n rm -f .gtd/.check-output\n fi\n on:\n \"A .gtd/FEEDBACK.md\": fixing\n \"M .gtd/FEEDBACK.md\": fixing\n \"C\": picking\n\n fixing:\n actor: agent\n file: <%= it.vars.feedbackFile %>\n model: <%= it.vars.coderModel %>\n retry:\n max: 3\n otherwise: escalate\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.feedbackFile %>`, which this prompt tells you to address.\n\n Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix\n the code so the suite passes. Keep the change focused — do not\n refactor unrelated code. If the feedback is wrong, empty or delete\n `<%= it.vars.feedbackFile %>` instead of \"fixing\" a non-issue; the\n machine picks the dispute up either way.\n\n Leave everything uncommitted and finish your turn — do not commit.\n on:\n \"* **\": checking\n\n escalate:\n actor: human\n file: <%= it.vars.feedbackFile %>\n message: |\n The agent could not get the check to pass after repeated attempts.\n `<%= it.vars.feedbackFile %>` holds the last failing output.\n\n Investigate and fix it yourself (editing code and/or\n `<%= it.vars.feedbackFile %>`), then run `gtd step human` to try the\n check again.\n on:\n \"* **\": checking\n\n reviewing:\n actor: agent\n file: <%= it.vars.reviewFile %>\n mode: review\n model: <%= it.vars.plannerModel %>\n # A direct entry point: `gtd review <commitish>` starts a fresh review\n # process here over `<commitish>..HEAD` (e.g. a colleague's PR branch).\n reviewEntry: true\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.reviewFile %>`, which this prompt tells you to write.\n\n Write `<%= it.vars.reviewFile %>` to help a human review the cycle's\n full diff (inlined below): group hunks semantically (same\n feature/refactor/fix, even across files), and for each group write a\n short heading, an explanation of what changed and why, and\n `- [ ] ./path/to/file.ts#42` style file pointers (checkboxes are for\n the human to tick, not you).\n\n Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"* .gtd/REVIEW.md\": await-review\n\n await-review:\n actor: human\n file: <%= it.vars.reviewFile %>\n mode: review\n message: |\n `<%= it.vars.reviewFile %>` holds the review record for the completed\n cycle.\n\n To approve: delete `<%= it.vars.reviewFile %>` and run\n `gtd step human`.\n\n To request changes: edit `<%= it.vars.reviewFile %>` (or the code)\n with what's wrong — including just ticking its checkboxes — then run\n `gtd step human`; this sends the cycle back through grilling with your\n feedback as the new input.\n on:\n \"D .gtd/REVIEW.md\": squashing\n \"* **\": grilling\n\n squashing:\n actor: agent\n model: <%= it.vars.coderModel %>\n prompt: |\n You are an autonomous coding agent. The cycle is approved and done.\n `.gtd/` holds this workflow's own state — never create, edit, or delete\n anything under `.gtd/` except `.gtd/COMMIT_MSG.md`, which this prompt\n tells you to write.\n\n Write `.gtd/COMMIT_MSG.md` with ONE conventional-commits message for\n the entire cycle (subject line `type(scope): subject`, imperative mood,\n <= 72 characters; a body explaining the why, trade-offs, and key\n decisions). Plain text, no markdown wrapper.\n\n Leave `.gtd/COMMIT_MSG.md` uncommitted and finish your turn — entering\n this file squashes the whole cycle into one commit using its content as\n the message.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"A .gtd/COMMIT_MSG.md\": done\n \"M .gtd/COMMIT_MSG.md\": done\n\n done:\n commit: |\n <%~ it.read(\".gtd/COMMIT_MSG.md\") %>\n\n Token cost: <%= it.processCost %>\n <% it.processCostByModel.forEach(function(m){ %>\n - <%= m.model %>: <%= m.cost %>\n <% }) %>\n";
191371
191371
  //#endregion
191372
191372
  //#region src/workflows/simple.yaml
191373
- var simple_default = "# The \"simple\" gtd workflow template — written verbatim into `.gtdrc.json`\n# (nested under a `workflow:` key) by `gtd init simple`. gtd ships no default\n# workflow: a repo picks one of the bundled templates with `gtd init`, and a\n# state command run with no workflow configured fails (see src/Config.ts).\n# See STATES.md §10 for the walkthrough and docs/examples/advanced-workflow.md\n# for the fuller `advanced` template.\n#\n# Compiled through the exact same `compileWorkflowConfig` a user's `.gtdrc`\n# `workflow:` key goes through — no privileged code path\n# (src/workflows/templates.ts does the compiling).\n#\n# Every content string below is INLINE (no `./`-relative file references):\n# the bundled templates ship inside a single-file build\n# (`dist/gtd.bundle.mjs`), so their content must already be resolved at BUILD\n# time rather than read from disk at RUNTIME — the same reason\n# `src/prompts/*.md` are imported through tsdown's `.md`-as-text loader\n# instead of read via `fs` at runtime. `simple.yaml` itself is imported the\n# same way (tsdown/vitest both treat `.yaml` as text — see\n# tsdown.config.ts / tests/vitest.rawMd.ts), so this file never needs a\n# sibling prompts/ directory to exist on disk once installed.\n#\n# States, in cycle order — 10 states, no squash:\n# idle (initial, human, message)\n# -> grilling (agent, prompt): reads .gtd/TODO.md's sketch (or a prior\n# lap's feedback), explores the codebase, and develops it into a concrete\n# implementation plan, stating any open question it can't settle itself\n# under a `## Open Questions` heading rather than guessing silently. Its\n# `file:`/`mode:` (TODO.md/`qa`) makes the plan's format checkable — it\n# self-validates before finishing (see \"Steering-file validation\" below).\n# grilling -> grilling-answer (human, message): tick off suggested\n# defaults by replacing them with `Answer:` lines; a clean step accepts\n# every remaining default -> building; any edit loops back to grilling.\n# grilling-answer -> building (agent, prompt): implements the plan in\n# .gtd/TODO.md directly (no task decomposition, no per-task queue) and\n# deletes .gtd/TODO.md once the work is complete and verified.\n# building -> checking (check, script): runs the test command inline;\n# A/M .gtd/FEEDBACK.md -> fixing (capped, redirects to escalate); D\n# .gtd/FEEDBACK.md (a green run that just cleaned up prior feedback) or C\n# (green, nothing to clean) -> reviewing.\n# fixing (agent, prompt) <-> checking\n# escalate (human, message): manual intervention, then back to checking\n# checking (green) -> reviewing (agent, prompt): writes .gtd/REVIEW.md in\n# the checkbox review format, grouping the cycle's full diff into\n# reviewable chunks; its `file:`/`mode:` (REVIEW.md/`review`) makes that\n# format checkable, so it self-validates before finishing. `reviewing`\n# ALSO declares `reviewEntry: true` — a second way in: `gtd review\n# <commitish>` (a clean tree resting at idle) writes an empty\n# `gtd(human): reviewing` entry commit carrying <commitish>'s hash as a\n# `Gtd-Review-Base:` trailer, starting a brand new process that reviews\n# <commitish>..HEAD (e.g. a colleague's PR branch) through this exact same\n# reviewing/await-review/feedback-lap machinery.\n# reviewing -> await-review (human, message): tick a pointer's `- [\n# ]` to `- [x]` to approve that item; deleting .gtd/REVIEW.md outright is\n# the power-user approve-everything shortcut; anything else pending\n# (code edits with REVIEW.md untouched) is feedback straight to grilling.\n# await-review -> review-deciding (check, script), entered by any `M\n# .gtd/REVIEW.md` step: if no unticked `- [ ]` pointer remains, the cycle\n# is approved (rm .gtd/REVIEW.md -> idle); otherwise the still-unticked\n# pointers (with their notes) are extracted into a fresh .gtd/TODO.md and\n# .gtd/REVIEW.md is removed (-> grilling, feedback lap).\n#\n# The cycle ends at human approval, resting back at idle — there is no\n# squash state. The cycle's commits stay in history; whether/how to squash\n# them (amend, interactive rebase, a PR's squash-merge) is entirely the\n# human's business once they're done reviewing — gtd makes no assumption.\n# That squash-flavored finale (a `squashing` prompt state + a `done` commit\n# state) still exists as an ENGINE capability (see STATES.md §8) and is kept\n# as part of the fuller machine at docs/examples/advanced-workflow.md.\n#\n# A `gtd(<actor>): idle` commit — entering the workflow's own initial state —\n# is therefore a PROCESS BOUNDARY (see `computeProcessRun` in src/Edge.ts):\n# the next cycle's `retry` counts, `startCommit`, and diffs never reach back\n# across an approved cycle's own idle-entering commit.\n#\n# HYGIENE INVARIANT (asserted in e2e — see default-workflow.feature): an\n# approved cycle leaves `.gtd/` empty. FEEDBACK.md is cleaned up by a green\n# `checking` run; REVIEW.md by the review-deciding approval branch; TODO.md by\n# `building`.\n#\n# Steering-file validation. `grilling` and `reviewing` each declare a\n# `file:`/`mode:` pair (TODO.md as `qa`, REVIEW.md as `review`), so their\n# output has a checkable format. src/OpenQuestions.ts and src/ReviewDoc.ts are\n# those two formats' EXECUTABLE SPECS (their unit tests are the format spec\n# tests), and `gtd validate` FORMATS the resolved state's rendered `file:` in\n# place then runs the SAME parser over it, exiting non-zero with findings when\n# it violates the format. There is no in-machine validation state and no bash\n# port to keep in sync — the producing agent self-validates before finishing\n# (plain `gtd next` appends the \"run `gtd validate` and fix all violations\"\n# instruction; under `--json` the driving loop runs it after the turn and\n# re-prompts on findings — see skills/loop/SKILL.md), AND `gtd step` runs the\n# same format-and-validate gate on capture, refusing a turn whose steering file\n# is invalid. So the check runs after a human edits too — at the human gates\n# `grilling-answer` (TODO.md) and `await-review` (REVIEW.md) — and a human gate\n# is only ever handed a tidy, well-formed file. The same parsers back the LSP's\n# live diagnostics (src/Lsp.ts).\n#\n# `grilling` and `reviewing` both declare `model: smart` — an opaque harness\n# hint (see the comment at `grilling` below) for their heavier one-shot\n# planning/reviewing turns. Every other state is unset (harness default).\n#\n# The four agent states each declare a `memory:` scope label (`plan`,\n# `build`, `fix`, `review` — see the comment at `grilling` below) — another\n# opaque hint a memory-aware driver reads to decide when an agent turn keeps\n# the previous turn's memory and when it starts fresh: a loop that re-enters\n# one state (grilling around its answer loop, fixing around checking) keeps\n# the same label and retains memory across its laps; crossing to the next\n# phase's differently-labelled state clears it. gtd never interprets the\n# label (see STATES.md §1 and skills/loop/SKILL.md's driver contract).\n#\n# `vars.testCommand` is this workflow's own declared default for `checking`'s\n# script (see it.vars in PatternTemplates.ts) — override it per-repo with a\n# top-level `.gtdrc` `vars: { testCommand: ... }` key, or per-invocation with\n# a `GTD_VAR_testCommand` environment variable (highest precedence).\n#\n# `vars.todoFile`/`reviewFile`/`feedbackFile` are this workflow's ONE source\n# of truth for the three steering-file paths every prompt/script below reads\n# or writes — each appears in templates as `<%~ it.vars.todoFile %>` etc\n# (see docs/design/state-file-association.md §2). Every state that rests on\n# one of these files also declares a `file:`/`mode:` pair (see STATES.md's\n# property table) so `gtd status`/`gtd next --json` and the LSP (`gtd lsp`)\n# know which file a human/editor should look at, and in what format\n# (`qa` for TODO.md's open-questions format, `review` for REVIEW.md's\n# checkbox format) — `fixing`/`escalate` declare `file:` alone (FEEDBACK.md\n# is plain text, no LSP format). KNOWN LIMITATION: `on` pattern keys below are\n# NOT Eta templates — they keep the LITERAL `.gtd/...` paths matching these\n# vars' DEFAULT values. Repointing `todoFile`/`reviewFile`/`feedbackFile` via\n# `.gtdrc`'s top-level `vars:` or a `GTD_VAR_` override changes what `file:`\n# renders to (and what a template reads/writes) WITHOUT changing what the\n# `on` patterns match against — desyncing the machine. See\n# docs/configuration.md's `file:`/`mode:` section for the full caveat.\n#\n# A fuller machine — two-phase Q&A planning, an architecture phase, task\n# decomposition, a deterministic per-task builder loop, agent-prepared\n# review, and the squash finale (`squashing` + `done`) — is preserved as a\n# copy-paste `.gtdrc` example at docs/examples/advanced-workflow.md.\n\nvars:\n testCommand: npm test\n todoFile: .gtd/TODO.md\n reviewFile: .gtd/REVIEW.md\n feedbackFile: .gtd/FEEDBACK.md\n\nstates:\n idle:\n actor: human\n initial: true\n # Every human-gate `message:` below closes with the SAME rendered block —\n # a \"What each change does next\" list built from `it.edges`, the resting\n # state's own `on` edges (see PatternTemplates.TemplateContext.edges). Each\n # edge's human-readable route lives in its `describe:` (the single source\n # of truth), so the list can never drift from the routing it documents.\n # The block skips edges without a `describe`, and each `<%~ ... \"\\n\" %>`\n # keeps the bullet's own newline (Eta's autoTrim strips the template's own\n # line breaks around `<% %>` tags, not text inside an interpolation).\n message: |\n No active gtd cycle.\n\n To start one, write `.gtd/TODO.md` with a short sketch of what you want\n built — a few sentences is enough.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: grilling\n describe: >-\n Save your sketch to `.gtd/TODO.md` (any working-tree change) to start\n the cycle — the agent reads it, explores the codebase, and develops it\n into a concrete implementation plan (**grilling**).\n\n grilling:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # `model` is an opaque harness hint — gtd never interprets this string, it\n # only passes it through to `gtd next --json`/`gtd status --json` so the\n # driving loop can map it onto whatever models its agent harness\n # provides. \"smart\" here just names the harness-chosen tier for the\n # heavier planning turn; states without a `model` use the harness's\n # default.\n model: smart\n # `memory` is an opaque memory-scope label — gtd never interprets it, it\n # only passes it through to `gtd next --json`/`gtd status --json` so a\n # memory-aware driving loop can decide when an agent turn continues from\n # the previous turn's memory and when it starts fresh: consecutive agent\n # turns that emit the SAME label share memory, a change (or the first\n # turn) is where the driver starts fresh. `grilling` re-enters itself\n # around the grilling-answer loop, so labelling every lap\n # `plan` keeps the planner's accumulated exploration across the loop; the\n # next phase (`building`) carries a different label, clearing it.\n memory: plan\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.todoFile %>`, which this prompt tells you to develop.\n\n `<%= it.vars.todoFile %>` holds a short sketch of what to build (or\n feedback from a prior review lap). Read it, explore the codebase, and\n develop it into a concrete implementation plan.\n\n For every question you cannot settle yourself, add it under a\n `## Open Questions` heading, one `### <question>` sub-heading each,\n whose body's FIRST non-blank line is exactly\n `Suggested default: <your answer>` — the human can accept it as-is or\n override it. Omit the section entirely once there are no open\n questions. If `<%= it.vars.todoFile %>` already carries\n `## Open Questions` entries from a previous lap, fold any\n `Answer: <text>` line into the plan; every remaining entry's body must\n still start with either `Suggested default: ...` or `Answer: ...` —\n never anything else.\n\n Leave `<%= it.vars.todoFile %>` uncommitted and finish your turn — do\n not commit, and do not run `gtd step agent` yourself; the harness does\n that.\n on:\n \"* **\": grilling-answer\n\n grilling-answer:\n actor: human\n file: <%= it.vars.todoFile %>\n mode: qa\n message: |\n `<%= it.vars.todoFile %>` holds the plan under development, with any\n open questions under `## Open Questions` — each carrying a suggested\n default. Answer a question by editing its entry in place: replace its\n `Suggested default: ...` line with `Answer: ...`, or add further detail.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"C\":\n to: building\n describe: >-\n Change nothing to accept every suggested default as-is and move on to\n implementation (**building**).\n \"* **\":\n to: grilling\n describe: >-\n Edit the plan — answer a question, add detail, or raise a new one — to\n send it back for another round of grilling (**grilling**).\n\n building:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # A distinct memory scope from `plan`: implementation starts fresh, with\n # the plan already settled in `.gtd/TODO.md` (which this prompt reads\n # below) rather than carried in the planner's working memory.\n memory: build\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create or edit anything under `.gtd/` except deleting\n `<%= it.vars.todoFile %>`, which this prompt tells you to delete once\n its work is complete.\n\n The plan to implement is: <%~ it.read(it.vars.todoFile) %>\n\n Read that plan and implement it in full. Use TDD discipline: one test,\n then the implementation that passes it, then the next — never write\n all the tests first.\n\n Delete `<%= it.vars.todoFile %>` once the work it describes is complete\n and verified. Leave everything else uncommitted and finish your turn.\n on:\n \"* **\": checking\n\n checking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: run the test suite and record a\n # red run's output as .gtd/FEEDBACK.md. What that output MEANS (another\n # fix round vs escalation) is decided by the workflow's own `on`/`retry`\n # rules at capture time — never here.\n #\n # `it.vars.testCommand` defaults to \"npm test\" (this workflow's own\n # `vars:` above) — override it with a top-level `.gtdrc`\n # `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`\n # environment variable (highest precedence).\n #\n # A green run also removes any `<%= it.vars.feedbackFile %>` left over\n # from an earlier red run — there is no squash to discard it for us\n # anymore, so the script cleans it up itself before moving on to\n # review.\n set +e\n mkdir -p .gtd\n <%~ it.vars.testCommand %> > .gtd/.check-output 2>&1\n code=$?\n if [ \"$code\" -ne 0 ]; then\n if [ -s .gtd/.check-output ]; then\n mv .gtd/.check-output <%~ it.vars.feedbackFile %>\n else\n rm -f .gtd/.check-output\n printf 'npm test failed with exit code %s and produced no output.' \"$code\" > <%~ it.vars.feedbackFile %>\n fi\n else\n rm -f .gtd/.check-output\n rm -f <%~ it.vars.feedbackFile %>\n fi\n on:\n \"A .gtd/FEEDBACK.md\": fixing\n \"M .gtd/FEEDBACK.md\": fixing\n \"D .gtd/FEEDBACK.md\": reviewing\n \"C\": reviewing\n\n fixing:\n actor: agent\n file: <%= it.vars.feedbackFile %>\n # Its own memory scope: the fix loop re-enters `fixing` around `checking`\n # (up to the retry cap), so labelling every attempt `fix` lets the agent\n # remember what it already tried across the loop; a green check moves on\n # to the differently-labelled `reviewing`, clearing it.\n memory: fix\n retry:\n max: 3\n otherwise: escalate\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.feedbackFile %>`, which this prompt tells you to address.\n\n Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix\n the code so the suite passes. Keep the change focused — do not\n refactor unrelated code. If the feedback is wrong, empty or delete\n `<%= it.vars.feedbackFile %>` instead of \"fixing\" a non-issue; the\n machine picks the dispute up either way.\n\n Leave everything uncommitted and finish your turn — do not commit.\n on:\n \"* **\": checking\n\n escalate:\n actor: human\n file: <%= it.vars.feedbackFile %>\n message: |\n The agent could not get the check to pass after repeated attempts.\n `<%= it.vars.feedbackFile %>` holds the last failing output.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: checking\n describe: >-\n Fix the failure yourself — edit the code and/or `.gtd/FEEDBACK.md` —\n to re-run the check (**checking**).\n\n reviewing:\n actor: agent\n file: <%= it.vars.reviewFile %>\n mode: review\n model: smart\n # A distinct memory scope again: the reviewer looks at the cycle's full\n # diff (inlined into its prompt) with a fresh perspective, not the\n # builder's or fixer's working memory.\n memory: review\n # `gtd review <commitish>` (a plain non-gtd branch, e.g. a colleague's PR)\n # enters here directly, recording the resolved base as a `Gtd-Review-Base:`\n # trailer on its empty entry commit — everything below then reuses the\n # existing reviewing/await-review/feedback-lap machinery unmodified over\n # <commitish>..HEAD (see STATES.md §11).\n reviewEntry: true\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.reviewFile %>`, which this prompt tells you to write.\n\n Write `<%= it.vars.reviewFile %>` to help a human review the cycle's\n full diff (inlined below) in this EXACT format:\n\n - First non-blank line: `# Review: <%= it.currentCommit.slice(0, 7) %>`\n - Somewhere in the document: `<!-- base: <%= it.startCommit %> -->`\n - At least one `## <Chunk Title>` heading, grouping hunks semantically\n (same feature/refactor/fix, even across files) — a short explanation\n of what changed and why, then one\n `- [ ] ./path/to/file.ts#42 — note` file pointer per hunk (checkboxes\n are for the human to tick, not you; every path is `./`-relative, with\n an optional `#line` and an optional ` — note`).\n\n Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"* **\": await-review\n\n await-review:\n actor: human\n file: <%= it.vars.reviewFile %>\n mode: review\n # While the cycle rests here for human review, gtd opens a \"review checkout\n # window\": HEAD and the index are temporarily rewound to this cycle's start\n # (the process boundary — no `reviewBase` state is declared, so the base\n # defaults to it) with the working tree untouched, so the whole cycle diff\n # surfaces as ordinary uncommitted changes in the editor's git integration.\n # The window closes automatically on the next invocation, once the cycle\n # rests anywhere else (see src/ReviewWindow.ts, STATES.md §11).\n reviewWindow: true\n message: |\n `<%= it.vars.reviewFile %>` holds the review record for the completed\n cycle — one `- [ ]` checkbox per reviewable item, grouped into chunks.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"D .gtd/REVIEW.md\":\n to: idle\n describe: >-\n Delete `.gtd/REVIEW.md` outright to approve the whole cycle at once\n and rest back at the start (**idle**).\n \"M .gtd/REVIEW.md\":\n to: review-deciding\n describe: >-\n Edit `.gtd/REVIEW.md` — tick a `- [ ]` box to `- [x]` to approve that\n item, or add notes — to hand it to a deterministic check\n (**review-deciding**) that closes the cycle out when every box is\n ticked, or extracts the still-unticked items into a fresh\n `.gtd/TODO.md` and loops back through **grilling** with that feedback.\n \"* **\":\n to: grilling\n describe: >-\n Change only code, leaving `.gtd/REVIEW.md` untouched, to send that as\n feedback straight back to **grilling**.\n\n review-deciding:\n actor: check\n file: <%= it.vars.reviewFile %>\n mode: review\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: if .gtd/REVIEW.md still has any\n # unticked \"- [ ]\" pointer, extract those pointers (with their notes)\n # into a fresh .gtd/TODO.md; either way, remove .gtd/REVIEW.md. What\n # the resulting diff MEANS (feedback lap vs. full approval) is decided\n # by this state's own `on` rules at capture time — never here. The\n # A/M .gtd/TODO.md row is declared BEFORE the D .gtd/REVIEW.md row (see\n # this workflow's `on` map below) so a feedback lap — which always also\n # deletes .gtd/REVIEW.md — is captured as feedback, not mistaken for an\n # approval.\n set +e\n mkdir -p .gtd\n if grep -qE '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %> 2>/dev/null; then\n {\n echo \"Feedback from review — address these before continuing:\"\n echo\n grep -E '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %>\n } > <%~ it.vars.todoFile %>\n fi\n rm -f <%~ it.vars.reviewFile %>\n on:\n \"A .gtd/TODO.md\": grilling\n \"M .gtd/TODO.md\": grilling\n \"D .gtd/REVIEW.md\": idle\n \"C\": await-review\n";
191373
+ var simple_default = "# The \"simple\" gtd workflow template — written verbatim into `.gtdrc.json`\n# (nested under a `workflow:` key) by `gtd init simple`. gtd ships no default\n# workflow: a repo picks one of the bundled templates with `gtd init`, and a\n# state command run with no workflow configured fails (see src/Config.ts).\n# See STATES.md §10 for the walkthrough and docs/examples/advanced-workflow.md\n# for the fuller `advanced` template.\n#\n# Compiled through the exact same `compileWorkflowConfig` a user's `.gtdrc`\n# `workflow:` key goes through — no privileged code path\n# (src/workflows/templates.ts does the compiling).\n#\n# Every content string below is INLINE (no `./`-relative file references):\n# the bundled templates ship inside a single-file build\n# (`dist/gtd.bundle.mjs`), so their content must already be resolved at BUILD\n# time rather than read from disk at RUNTIME. `simple.yaml` itself is imported\n# as raw text (tsdown/vitest both treat `.yaml` as text — see\n# tsdown.config.ts / tests/vitest.rawMd.ts), so this file never needs a\n# sibling prompts/ directory to exist on disk once installed.\n#\n# `gtd init simple` DERIVES the scaffolded `.gtdrc.json` from this inline\n# source (src/workflows/templates.ts `renderInitScaffold`): each agent state's\n# `prompt:` below is written out as an editable `gtd-prompts/<state>.md` file\n# and the config value is rewritten to a `./gtd-prompts/<state>.md` reference\n# `compileWorkflowConfig` inlines back at load time. Human `message:`/check\n# `script:` bodies stay inline in the config. This YAML stays fully inline\n# regardless — the split happens only at scaffold time, on real disk.\n#\n# States, in cycle order — 10 states, no squash:\n# idle (initial, human, message)\n# -> grilling (agent, prompt): reads .gtd/TODO.md's sketch (or a prior\n# lap's feedback), explores the codebase, and develops it into a concrete\n# implementation plan, stating any open question it can't settle itself\n# under a `## Open Questions` heading rather than guessing silently. Its\n# `file:`/`mode:` (TODO.md/`qa`) makes the plan's format checkable — it\n# self-validates before finishing (see \"Steering-file validation\" below).\n# grilling -> grilling-answer (human, message): tick off suggested\n# defaults by replacing them with `Answer:` lines; a clean step accepts\n# every remaining default -> building; any edit loops back to grilling.\n# grilling-answer -> building (agent, prompt): implements the plan in\n# .gtd/TODO.md directly (no task decomposition, no per-task queue) and\n# deletes .gtd/TODO.md once the work is complete and verified.\n# building -> checking (check, script): runs the test command inline;\n# A/M .gtd/FEEDBACK.md -> fixing (capped, redirects to escalate); D\n# .gtd/FEEDBACK.md (a green run that just cleaned up prior feedback) or C\n# (green, nothing to clean) -> reviewing.\n# fixing (agent, prompt) <-> checking\n# escalate (human, message): manual intervention, then back to checking\n# checking (green) -> reviewing (agent, prompt): writes .gtd/REVIEW.md in\n# the checkbox review format, grouping the cycle's full diff into\n# reviewable chunks; its `file:`/`mode:` (REVIEW.md/`review`) makes that\n# format checkable, so it self-validates before finishing. `reviewing`\n# ALSO declares `reviewEntry: true` — a second way in: `gtd review\n# <commitish>` (a clean tree resting at idle) writes an empty\n# `gtd(human): reviewing` entry commit carrying <commitish>'s hash as a\n# `Gtd-Review-Base:` trailer, starting a brand new process that reviews\n# <commitish>..HEAD (e.g. a colleague's PR branch) through this exact same\n# reviewing/await-review/feedback-lap machinery.\n# reviewing -> await-review (human, message): tick a pointer's `- [\n# ]` to `- [x]` to approve that item; deleting .gtd/REVIEW.md outright is\n# the power-user approve-everything shortcut; anything else pending\n# (code edits with REVIEW.md untouched) is feedback straight to grilling.\n# await-review -> review-deciding (check, script), entered by any `M\n# .gtd/REVIEW.md` step: if no unticked `- [ ]` pointer remains, the cycle\n# is approved (rm .gtd/REVIEW.md -> idle); otherwise the still-unticked\n# pointers (with their notes) are extracted into a fresh .gtd/TODO.md and\n# .gtd/REVIEW.md is removed (-> grilling, feedback lap).\n#\n# The cycle ends at human approval, resting back at idle — there is no\n# squash state. The cycle's commits stay in history; whether/how to squash\n# them (amend, interactive rebase, a PR's squash-merge) is entirely the\n# human's business once they're done reviewing — gtd makes no assumption.\n# That squash-flavored finale (a `squashing` prompt state + a `done` commit\n# state) still exists as an ENGINE capability (see STATES.md §8) and is kept\n# as part of the fuller machine at docs/examples/advanced-workflow.md.\n#\n# A `gtd(<actor>): idle` commit — entering the workflow's own initial state —\n# is therefore a PROCESS BOUNDARY (see `computeProcessRun` in src/Edge.ts):\n# the next cycle's `retry` counts, `startCommit`, and diffs never reach back\n# across an approved cycle's own idle-entering commit.\n#\n# HYGIENE INVARIANT (asserted in e2e — see default-workflow.feature): an\n# approved cycle leaves `.gtd/` empty. FEEDBACK.md is cleaned up by a green\n# `checking` run; REVIEW.md by the review-deciding approval branch; TODO.md by\n# `building`.\n#\n# Steering-file validation. `grilling` and `reviewing` each declare a\n# `file:`/`mode:` pair (TODO.md as `qa`, REVIEW.md as `review`), so their\n# output has a checkable format. src/OpenQuestions.ts and src/ReviewDoc.ts are\n# those two formats' EXECUTABLE SPECS (their unit tests are the format spec\n# tests), and `gtd validate` FORMATS the resolved state's rendered `file:` in\n# place then runs the SAME parser over it, exiting non-zero with findings when\n# it violates the format. There is no in-machine validation state and no bash\n# port to keep in sync — the producing agent self-validates before finishing\n# (plain `gtd next` appends the \"run `gtd validate` and fix all violations\"\n# instruction; under `--json` the driving loop runs it after the turn and\n# re-prompts on findings — see skills/loop/SKILL.md), AND `gtd step` runs the\n# same format-and-validate gate on capture, refusing a turn whose steering file\n# is invalid. So the check runs after a human edits too — at the human gates\n# `grilling-answer` (TODO.md) and `await-review` (REVIEW.md) — and a human gate\n# is only ever handed a tidy, well-formed file. The same parsers back the LSP's\n# live diagnostics (src/Lsp.ts).\n#\n# Every agent state draws its `model` from a `vars` tier entry (see `vars:`\n# below and the comment at `grilling`) rather than a hardcoded string, so both\n# tiers repoint in one place: `plannerModel` (default \"smart\") for the heavier\n# one-shot planning/reviewing turns (`grilling`, `reviewing`), `coderModel`\n# (default \"base\") for the coding turns (`building`, `fixing`). Both are opaque\n# hints the driving loop maps onto its harness.\n#\n# The four agent states each declare a `memory:` scope label (`plan`,\n# `build`, `fix`, `review` — see the comment at `grilling` below) — another\n# opaque hint a memory-aware driver reads to decide when an agent turn keeps\n# the previous turn's memory and when it starts fresh: a loop that re-enters\n# one state (grilling around its answer loop, fixing around checking) keeps\n# the same label and retains memory across its laps; crossing to the next\n# phase's differently-labelled state clears it. gtd never interprets the\n# label (see STATES.md §1 and skills/loop/SKILL.md's driver contract).\n#\n# `vars.testCommand` is this workflow's own declared default for `checking`'s\n# script (see it.vars in PatternTemplates.ts) — override it per-repo with a\n# top-level `.gtdrc` `vars: { testCommand: ... }` key, or per-invocation with\n# a `GTD_VAR_testCommand` environment variable (highest precedence).\n#\n# `vars.todoFile`/`reviewFile`/`feedbackFile` are this workflow's ONE source\n# of truth for the three steering-file paths every prompt/script below reads\n# or writes — each appears in templates as `<%~ it.vars.todoFile %>` etc\n# (see docs/design/state-file-association.md §2). Every state that rests on\n# one of these files also declares a `file:`/`mode:` pair (see STATES.md's\n# property table) so `gtd status`/`gtd next --json` and the LSP (`gtd lsp`)\n# know which file a human/editor should look at, and in what format\n# (`qa` for TODO.md's open-questions format, `review` for REVIEW.md's\n# checkbox format) — `fixing`/`escalate` declare `file:` alone (FEEDBACK.md\n# is plain text, no LSP format). KNOWN LIMITATION: `on` pattern keys below are\n# NOT Eta templates — they keep the LITERAL `.gtd/...` paths matching these\n# vars' DEFAULT values. Repointing `todoFile`/`reviewFile`/`feedbackFile` via\n# `.gtdrc`'s top-level `vars:` or a `GTD_VAR_` override changes what `file:`\n# renders to (and what a template reads/writes) WITHOUT changing what the\n# `on` patterns match against — desyncing the machine. See\n# docs/configuration.md's `file:`/`mode:` section for the full caveat.\n#\n# A fuller machine — two-phase Q&A planning, an architecture phase, task\n# decomposition, a deterministic per-task builder loop, agent-prepared\n# review, and the squash finale (`squashing` + `done`) — is preserved as a\n# copy-paste `.gtdrc` example at docs/examples/advanced-workflow.md.\n\nvars:\n testCommand: npm test\n todoFile: .gtd/TODO.md\n reviewFile: .gtd/REVIEW.md\n feedbackFile: .gtd/FEEDBACK.md\n # The two model tiers every agent state draws from (see the model comment at\n # `grilling` below). Both are opaque harness hints — repoint them here (or\n # via a top-level `.gtdrc` `vars:` key / a `GTD_VAR_plannerModel` env var) to\n # change every state on that tier at once.\n plannerModel: smart\n coderModel: base\n\nstates:\n idle:\n actor: human\n initial: true\n # Every human-gate `message:` below closes with the SAME rendered block —\n # a \"What each change does next\" list built from `it.edges`, the resting\n # state's own `on` edges (see PatternTemplates.TemplateContext.edges). Each\n # edge's human-readable route lives in its `describe:` (the single source\n # of truth), so the list can never drift from the routing it documents.\n # The block skips edges without a `describe`, and each `<%~ ... \"\\n\" %>`\n # keeps the bullet's own newline (Eta's autoTrim strips the template's own\n # line breaks around `<% %>` tags, not text inside an interpolation).\n message: |\n No active gtd cycle.\n\n To start one, write `.gtd/TODO.md` with a short sketch of what you want\n built — a few sentences is enough.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: grilling\n describe: >-\n Save your sketch to `.gtd/TODO.md` (any working-tree change) to start\n the cycle — the agent reads it, explores the codebase, and develops it\n into a concrete implementation plan (**grilling**).\n\n grilling:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # `model` is an opaque harness hint — gtd never interprets this string, it\n # only passes it through to `gtd next --json`/`gtd status --json` so the\n # driving loop can map it onto whatever models its agent harness provides.\n # Every agent state draws its tier from a `vars` model entry (see `vars:`\n # above) so the tiers repoint in one place: `plannerModel` (default\n # \"smart\") names the heavier tier for the one-shot planning/reviewing\n # turns, `coderModel` (default \"base\") the tier for the coding turns.\n model: <%= it.vars.plannerModel %>\n # `memory` is an opaque memory-scope label — gtd never interprets it, it\n # only passes it through to `gtd next --json`/`gtd status --json` so a\n # memory-aware driving loop can decide when an agent turn continues from\n # the previous turn's memory and when it starts fresh: consecutive agent\n # turns that emit the SAME label share memory, a change (or the first\n # turn) is where the driver starts fresh. `grilling` re-enters itself\n # around the grilling-answer loop, so labelling every lap\n # `plan` keeps the planner's accumulated exploration across the loop; the\n # next phase (`building`) carries a different label, clearing it.\n memory: plan\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.todoFile %>`, which this prompt tells you to develop.\n\n `<%= it.vars.todoFile %>` holds a short sketch of what to build (or\n feedback from a prior review lap). Read it, explore the codebase, and\n develop it into a concrete implementation plan.\n\n For every question you cannot settle yourself, add it under a\n `## Open Questions` heading, one `### <question>` sub-heading each,\n whose body's FIRST non-blank line is exactly\n `Suggested default: <your answer>` — the human can accept it as-is or\n override it. Omit the section entirely once there are no open\n questions. If `<%= it.vars.todoFile %>` already carries\n `## Open Questions` entries from a previous lap, fold any\n `Answer: <text>` line into the plan; every remaining entry's body must\n still start with either `Suggested default: ...` or `Answer: ...` —\n never anything else.\n\n Leave `<%= it.vars.todoFile %>` uncommitted and finish your turn — do\n not commit, and do not run `gtd step agent` yourself; the harness does\n that.\n on:\n \"* **\": grilling-answer\n\n grilling-answer:\n actor: human\n file: <%= it.vars.todoFile %>\n mode: qa\n message: |\n `<%= it.vars.todoFile %>` holds the plan under development, with any\n open questions under `## Open Questions` — each carrying a suggested\n default. Answer a question by editing its entry in place: replace its\n `Suggested default: ...` line with `Answer: ...`, or add further detail.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"C\":\n to: building\n describe: >-\n Change nothing to accept every suggested default as-is and move on to\n implementation (**building**).\n \"* **\":\n to: grilling\n describe: >-\n Edit the plan — answer a question, add detail, or raise a new one — to\n send it back for another round of grilling (**grilling**).\n\n building:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n model: <%= it.vars.coderModel %>\n # A distinct memory scope from `plan`: implementation starts fresh, with\n # the plan already settled in `.gtd/TODO.md` (which this prompt reads\n # below) rather than carried in the planner's working memory.\n memory: build\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create or edit anything under `.gtd/` except deleting\n `<%= it.vars.todoFile %>`, which this prompt tells you to delete once\n its work is complete.\n\n The plan to implement is: <%~ it.read(it.vars.todoFile) %>\n\n Read that plan and implement it in full. Use TDD discipline: one test,\n then the implementation that passes it, then the next — never write\n all the tests first.\n\n Delete `<%= it.vars.todoFile %>` once the work it describes is complete\n and verified. Leave everything else uncommitted and finish your turn.\n on:\n \"* **\": checking\n\n checking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: run the test suite and record a\n # red run's output as .gtd/FEEDBACK.md. What that output MEANS (another\n # fix round vs escalation) is decided by the workflow's own `on`/`retry`\n # rules at capture time — never here.\n #\n # `it.vars.testCommand` defaults to \"npm test\" (this workflow's own\n # `vars:` above) — override it with a top-level `.gtdrc`\n # `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`\n # environment variable (highest precedence).\n #\n # A green run also removes any `<%= it.vars.feedbackFile %>` left over\n # from an earlier red run — there is no squash to discard it for us\n # anymore, so the script cleans it up itself before moving on to\n # review.\n set +e\n mkdir -p .gtd\n <%~ it.vars.testCommand %> > .gtd/.check-output 2>&1\n code=$?\n if [ \"$code\" -ne 0 ]; then\n if [ -s .gtd/.check-output ]; then\n mv .gtd/.check-output <%~ it.vars.feedbackFile %>\n else\n rm -f .gtd/.check-output\n printf 'npm test failed with exit code %s and produced no output.' \"$code\" > <%~ it.vars.feedbackFile %>\n fi\n else\n rm -f .gtd/.check-output\n rm -f <%~ it.vars.feedbackFile %>\n fi\n on:\n \"A .gtd/FEEDBACK.md\": fixing\n \"M .gtd/FEEDBACK.md\": fixing\n \"D .gtd/FEEDBACK.md\": reviewing\n \"C\": reviewing\n\n fixing:\n actor: agent\n file: <%= it.vars.feedbackFile %>\n model: <%= it.vars.coderModel %>\n # Its own memory scope: the fix loop re-enters `fixing` around `checking`\n # (up to the retry cap), so labelling every attempt `fix` lets the agent\n # remember what it already tried across the loop; a green check moves on\n # to the differently-labelled `reviewing`, clearing it.\n memory: fix\n retry:\n max: 3\n otherwise: escalate\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.feedbackFile %>`, which this prompt tells you to address.\n\n Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix\n the code so the suite passes. Keep the change focused — do not\n refactor unrelated code. If the feedback is wrong, empty or delete\n `<%= it.vars.feedbackFile %>` instead of \"fixing\" a non-issue; the\n machine picks the dispute up either way.\n\n Leave everything uncommitted and finish your turn — do not commit.\n on:\n \"* **\": checking\n\n escalate:\n actor: human\n file: <%= it.vars.feedbackFile %>\n message: |\n The agent could not get the check to pass after repeated attempts.\n `<%= it.vars.feedbackFile %>` holds the last failing output.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: checking\n describe: >-\n Fix the failure yourself — edit the code and/or `.gtd/FEEDBACK.md` —\n to re-run the check (**checking**).\n\n reviewing:\n actor: agent\n file: <%= it.vars.reviewFile %>\n mode: review\n model: <%= it.vars.plannerModel %>\n # A distinct memory scope again: the reviewer looks at the cycle's full\n # diff (inlined into its prompt) with a fresh perspective, not the\n # builder's or fixer's working memory.\n memory: review\n # `gtd review <commitish>` (a plain non-gtd branch, e.g. a colleague's PR)\n # enters here directly, recording the resolved base as a `Gtd-Review-Base:`\n # trailer on its empty entry commit — everything below then reuses the\n # existing reviewing/await-review/feedback-lap machinery unmodified over\n # <commitish>..HEAD (see STATES.md §11).\n reviewEntry: true\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.reviewFile %>`, which this prompt tells you to write.\n\n Write `<%= it.vars.reviewFile %>` to help a human review the cycle's\n full diff (inlined below) in this EXACT format:\n\n - First non-blank line: `# Review: <%= it.currentCommit.slice(0, 7) %>`\n - Somewhere in the document: `<!-- base: <%= it.startCommit %> -->`\n - At least one `## <Chunk Title>` heading, grouping hunks semantically\n (same feature/refactor/fix, even across files) — a short explanation\n of what changed and why, then one\n `- [ ] ./path/to/file.ts#42 — note` file pointer per hunk (checkboxes\n are for the human to tick, not you; every path is `./`-relative, with\n an optional `#line` and an optional ` — note`).\n\n Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"* **\": await-review\n\n await-review:\n actor: human\n file: <%= it.vars.reviewFile %>\n mode: review\n # While the cycle rests here for human review, gtd opens a \"review checkout\n # window\": HEAD and the index are temporarily rewound to this cycle's start\n # (the process boundary — no `reviewBase` state is declared, so the base\n # defaults to it) with the working tree untouched, so the whole cycle diff\n # surfaces as ordinary uncommitted changes in the editor's git integration.\n # The window closes automatically on the next invocation, once the cycle\n # rests anywhere else (see src/ReviewWindow.ts, STATES.md §11).\n reviewWindow: true\n message: |\n `<%= it.vars.reviewFile %>` holds the review record for the completed\n cycle — one `- [ ]` checkbox per reviewable item, grouped into chunks.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"D .gtd/REVIEW.md\":\n to: idle\n describe: >-\n Delete `.gtd/REVIEW.md` outright to approve the whole cycle at once\n and rest back at the start (**idle**).\n \"M .gtd/REVIEW.md\":\n to: review-deciding\n describe: >-\n Edit `.gtd/REVIEW.md` — tick a `- [ ]` box to `- [x]` to approve that\n item, or add notes — to hand it to a deterministic check\n (**review-deciding**) that closes the cycle out when every box is\n ticked, or extracts the still-unticked items into a fresh\n `.gtd/TODO.md` and loops back through **grilling** with that feedback.\n \"* **\":\n to: grilling\n describe: >-\n Change only code, leaving `.gtd/REVIEW.md` untouched, to send that as\n feedback straight back to **grilling**.\n\n review-deciding:\n actor: check\n file: <%= it.vars.reviewFile %>\n mode: review\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: if .gtd/REVIEW.md still has any\n # unticked \"- [ ]\" pointer, extract those pointers (with their notes)\n # into a fresh .gtd/TODO.md; either way, remove .gtd/REVIEW.md. What\n # the resulting diff MEANS (feedback lap vs. full approval) is decided\n # by this state's own `on` rules at capture time — never here. The\n # A/M .gtd/TODO.md row is declared BEFORE the D .gtd/REVIEW.md row (see\n # this workflow's `on` map below) so a feedback lap — which always also\n # deletes .gtd/REVIEW.md — is captured as feedback, not mistaken for an\n # approval.\n set +e\n mkdir -p .gtd\n if grep -qE '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %> 2>/dev/null; then\n {\n echo \"Feedback from review — address these before continuing:\"\n echo\n grep -E '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %>\n } > <%~ it.vars.todoFile %>\n fi\n rm -f <%~ it.vars.reviewFile %>\n on:\n \"A .gtd/TODO.md\": grilling\n \"M .gtd/TODO.md\": grilling\n \"D .gtd/REVIEW.md\": idle\n \"C\": await-review\n";
191374
191374
  //#endregion
191375
191375
  //#region src/workflows/templates.ts
191376
191376
  /**
@@ -191379,6 +191379,15 @@ var simple_default = "# The \"simple\" gtd workflow template — written verbati
191379
191379
  */
191380
191380
  const SCHEMA_URL = "https://raw.githubusercontent.com/pmelab/gtd/main/schema.json";
191381
191381
  /**
191382
+ * The repo-root-relative directory `gtd init` writes each agent state's prompt
191383
+ * into as a standalone, editable Markdown file (see `renderInitScaffold`). The
191384
+ * scaffolded `.gtdrc.json` references these via `./gtd-prompts/<state>.md`
191385
+ * content-value file references, which `compileWorkflowConfig` inlines at load
191386
+ * time (`resolveContent` in `src/PatternConfig.ts`) — so editing a prompt file
191387
+ * changes the workflow with no config edit.
191388
+ */
191389
+ const PROMPTS_DIR = "gtd-prompts";
191390
+ /**
191382
191391
  * The bundled workflow templates `gtd init <name>` can scaffold, keyed by the
191383
191392
  * name the user passes. Each value is the raw YAML text of the template file,
191384
191393
  * imported as a string (tsdown's `.yaml` text loader / the vitest `rawMd`
@@ -191394,19 +191403,36 @@ const WORKFLOW_TEMPLATES = {
191394
191403
  const WORKFLOW_TEMPLATE_NAMES = Object.keys(WORKFLOW_TEMPLATES);
191395
191404
  const isWorkflowTemplateName = (name) => Object.prototype.hasOwnProperty.call(WORKFLOW_TEMPLATES, name);
191396
191405
  /**
191397
- * Render the `.gtdrc.json` `gtd init <name>` writes: a `$schema` link (so
191398
- * editors pick up completion/validation) plus the template's whole workflow
191399
- * object nested under a `workflow:` key — exactly the shape a hand-authored
191400
- * `.gtdrc` `workflow:` value takes (`{ vars, states }`). The template's
191401
- * multi-line prompts/scripts become `\n`-escaped JSON strings; the config
191402
- * loader parses them back identically to the YAML source.
191403
- */
191404
- const renderInitConfig = (name) => {
191406
+ * Render everything `gtd init <name>` writes. Like `renderInitConfig`, but each
191407
+ * agent state's inline `prompt:` is EXTRACTED into a standalone
191408
+ * `gtd-prompts/<state>.md` file and the config value is rewritten to a
191409
+ * `./gtd-prompts/<state>.md` file reference — `compileWorkflowConfig` inlines
191410
+ * it back at load time (`resolveContent`), so the workflow behaves identically
191411
+ * to the fully-inline `renderInitConfig` form while the prompts stay editable
191412
+ * as ordinary Markdown. Only `prompt:` content is externalized: human
191413
+ * `message:` blocks and check `script:` bodies remain inline in the config
191414
+ * (they are workflow mechanics, not prompts). The bundled YAML template itself
191415
+ * stays fully inline (it ships inside the single-file bundle); this function is
191416
+ * the only place the split happens, at scaffold time.
191417
+ */
191418
+ const renderInitScaffold = (name) => {
191405
191419
  const workflow = (0, import_dist$1.parse)(WORKFLOW_TEMPLATES[name]);
191406
- return JSON.stringify({
191407
- $schema: SCHEMA_URL,
191408
- workflow
191409
- }, null, 2) + "\n";
191420
+ const prompts = [];
191421
+ for (const [stateName, state] of Object.entries(workflow.states ?? {})) if (typeof state.prompt === "string") {
191422
+ const path = `${PROMPTS_DIR}/${stateName}.md`;
191423
+ prompts.push({
191424
+ path,
191425
+ content: state.prompt
191426
+ });
191427
+ state.prompt = `./${path}`;
191428
+ }
191429
+ return {
191430
+ config: JSON.stringify({
191431
+ $schema: SCHEMA_URL,
191432
+ workflow
191433
+ }, null, 2) + "\n",
191434
+ prompts
191435
+ };
191410
191436
  };
191411
191437
  //#endregion
191412
191438
  //#region node_modules/eta/dist/index.mjs
@@ -204165,9 +204191,11 @@ const HELP_TEXT = `Usage: gtd [command] [options]
204165
204191
 
204166
204192
  Commands:
204167
204193
  init <workflow> Scaffold a .gtdrc.json for this repo with the chosen
204168
- bundled workflow inline (one of: simple, advanced). Run
204169
- once per repo; refuses if a gtd config already exists.
204170
- Leaves the file uncommitted for you to review and commit
204194
+ bundled workflow (one of: simple, advanced); its agent
204195
+ prompts are written as editable Markdown under gtd-prompts/
204196
+ and referenced from the config. Run once per repo; refuses
204197
+ if a gtd config already exists. Leaves the files uncommitted
204198
+ for you to review and commit
204171
204199
  step <actor> Authenticate as <actor>, match the resolved rest's
204172
204200
  declared patterns against the pending changes, and commit
204173
204201
  (or squash) the one resulting transition. Pass
@@ -204290,9 +204318,12 @@ const initWorkflowChoices = () => `choose one of: ${WORKFLOW_TEMPLATE_NAMES.join
204290
204318
  * the ONE command that must run with no workflow configured yet: it needs no
204291
204319
  * `ConfigService` (which would throw the "no workflow" error pre-init) and no
204292
204320
  * review window. It still runs the repo-root guard (it writes `.gtdrc.json` at
204293
- * the root) and refuses to clobber an existing config. The file is left
204294
- * UNCOMMITTED, so the message warns to commit it before the first `gtd step`
204295
- * (an uncommitted config is a pending change the initial state's `* **` edge
204321
+ * the root) and refuses to clobber an existing config. It also writes each
204322
+ * agent state's prompt as a standalone `gtd-prompts/<state>.md` file the config
204323
+ * references via `./` (see `renderInitScaffold`), so prompts are editable
204324
+ * Markdown rather than JSON-escaped strings. Everything is left UNCOMMITTED, so
204325
+ * the message warns to commit it all before the first `gtd step` (an
204326
+ * uncommitted config/prompt is a pending change the initial state's `* **` edge
204296
204327
  * would otherwise capture).
204297
204328
  */
204298
204329
  const runInitCommand = (argv, json, write) => gen(function* () {
@@ -204306,12 +204337,23 @@ const runInitCommand = (argv, json, write) => gen(function* () {
204306
204337
  yield* assertRunningFromRepoRoot(git, fs);
204307
204338
  const { root } = yield* Cwd;
204308
204339
  if (yield* configPresentAt(root)) return yield* fail$2(/* @__PURE__ */ new Error("gtd init: a gtd config already exists — remove it before re-initializing"));
204309
- yield* fs.writeFileString(join(root, ".gtdrc.json"), renderInitConfig(name)).pipe(mapError$1((e) => e instanceof Error ? e : new Error(String(e))));
204340
+ const toError = (e) => e instanceof Error ? e : new Error(String(e));
204341
+ const scaffold = renderInitScaffold(name);
204342
+ yield* fs.writeFileString(join(root, ".gtdrc.json"), scaffold.config).pipe(mapError$1(toError));
204343
+ for (const prompt of scaffold.prompts) {
204344
+ const full = join(root, prompt.path);
204345
+ yield* fs.makeDirectory(dirname(full), { recursive: true }).pipe(mapError$1(toError));
204346
+ yield* fs.writeFileString(full, prompt.content).pipe(mapError$1(toError));
204347
+ }
204310
204348
  if (json) write(JSON.stringify({
204311
204349
  written: ".gtdrc.json",
204312
- workflow: name
204350
+ workflow: name,
204351
+ prompts: scaffold.prompts.map((p) => p.path)
204313
204352
  }) + "\n");
204314
- else write(`Wrote .gtdrc.json with the "${name}" workflow.\n\nReview and commit it before starting: an uncommitted .gtdrc.json counts as a\npending change, so the initial state would capture it on the first step. Once\ncommitted, run \`gtd step human\` to begin.\n`);
204353
+ else {
204354
+ const promptCount = scaffold.prompts.length;
204355
+ write(`Wrote .gtdrc.json with the "${name}" workflow, and its ${promptCount} agent prompt${promptCount === 1 ? "" : "s"} as editable Markdown under ${PROMPTS_DIR}/ (referenced from the config).\n\nReview and commit them before starting: an uncommitted .gtdrc.json (or prompt\nfile) counts as a pending change, so the initial state would capture it on the\nfirst step. Once committed, run \`gtd step human\` to begin.\n`);
204356
+ }
204315
204357
  });
204316
204358
  /**
204317
204359
  * Resolve HEAD's rest, the current process run, and the template context for
package/docs/cli.md CHANGED
@@ -5,9 +5,11 @@ Usage: gtd [command] [options]
5
5
 
6
6
  Commands:
7
7
  init <workflow> Scaffold a .gtdrc.json for this repo with the chosen
8
- bundled workflow inline (one of: simple, advanced). Run
9
- once per repo; refuses if a gtd config already exists.
10
- Leaves the file uncommitted for you to review and commit
8
+ bundled workflow (one of: simple, advanced); its agent
9
+ prompts are written as editable Markdown under gtd-prompts/
10
+ and referenced from the config. Run once per repo; refuses
11
+ if a gtd config already exists. Leaves the files uncommitted
12
+ for you to review and commit
11
13
  step <actor> Authenticate as <actor>, match the resolved rest's
12
14
  declared patterns against the pending changes, and commit
13
15
  (or squash) the one resulting transition. Pass
@@ -3,9 +3,10 @@
3
3
  gtd reads a required `.gtdrc` config file via
4
4
  [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig). gtd ships **no**
5
5
  default workflow: scaffold one for the repo with [`gtd init`](#gtd-init) (once),
6
- which writes a `.gtdrc.json` carrying a bundled workflow template inline. A
7
- state command run with no `workflow:` configured fails, pointing you at
8
- `gtd init`. Supported filenames (searched in this order):
6
+ which writes a `.gtdrc.json` for a bundled workflow template (with its agent
7
+ prompts as editable Markdown under `gtd-prompts/`). A state command run with no
8
+ `workflow:` configured fails, pointing you at `gtd init`. Supported filenames
9
+ (searched in this order):
9
10
 
10
11
  - `.gtdrc`
11
12
  - `.gtdrc.json`
@@ -45,6 +46,12 @@ interprets.
45
46
 
46
47
  ## The `workflow:` key
47
48
 
49
+ > Authoring or editing a workflow with a coding agent?
50
+ > `skills/authoring/SKILL.md` is the agent-facing contract for producing a valid
51
+ > `workflow:` — the state model, pattern grammar, load-time rules, and how to
52
+ > verify a change compiles. This section is the exhaustive schema reference
53
+ > behind it.
54
+
48
55
  The `workflow:` key is the **only** definition source — there is no `extends`,
49
56
  no merge-over-a-built-in. The bundled templates `gtd init` scaffolds are
50
57
  themselves YAML assets (`src/workflows/simple.yaml`,
@@ -540,7 +547,12 @@ layers, **later wins**:
540
547
  workflow author's declared defaults. The `simple` template declares
541
548
  `vars: { testCommand: "npm test" }`, read by `checking`'s script as
542
549
  `<%~ it.vars.testCommand %>` (see
543
- [STATES.md §10](../STATES.md#10-the-bundled-workflow-templates)).
550
+ [STATES.md §10](../STATES.md#10-the-bundled-workflow-templates)). Both
551
+ bundled templates also declare two model-tier vars — `plannerModel` (default
552
+ `smart`) and `coderModel` (default `base`) — that every agent state's
553
+ `model:` resolves through (`model: <%= it.vars.plannerModel %>`), so
554
+ repointing one var here (or via layer 2/3 below) changes every state on that
555
+ tier at once.
544
556
  2. **A top-level `.gtdrc` `vars:` key** (a sibling of `workflow:`, NOT nested
545
557
  inside it) — per-repo tuning without redefining the whole workflow. Subject
546
558
  to the same cwd→home deep merge as everything else in `.gtdrc` (innermost
@@ -654,8 +666,15 @@ gtd init simple # or: gtd init advanced
654
666
  ```
655
667
 
656
668
  `gtd init <workflow>` writes a `.gtdrc.json` at the repository root with the
657
- chosen bundled template's whole workflow inline under a `workflow:` key, plus a
658
- `$schema` link (so editors pick up completion/validation). The two templates:
669
+ chosen bundled template's workflow under a `workflow:` key, plus a `$schema`
670
+ link (so editors pick up completion/validation). Each **agent state's prompt**
671
+ is written as a standalone Markdown file under `gtd-prompts/<state>.md` and the
672
+ config references it via a `./gtd-prompts/<state>.md`
673
+ [file reference](#content-values-inline-or-a-file-reference) — gtd inlines it at
674
+ load time, so a prompt is editable Markdown and editing it changes the workflow
675
+ with no config edit. Human `message:` blocks and check `script:` bodies stay
676
+ inline in the config (they are workflow mechanics, not prompts). The two
677
+ templates:
659
678
 
660
679
  - **`simple`** — the 10-state machine walked through in
661
680
  [STATES.md §10](../STATES.md#10-the-bundled-workflow-templates): idle →
@@ -666,13 +685,14 @@ chosen bundled template's whole workflow inline under a `workflow:` key, plus a
666
685
  walked through at
667
686
  [docs/examples/advanced-workflow.md](examples/advanced-workflow.md).
668
687
 
669
- The file is written **uncommitted** — review it, then commit it before your
670
- first `gtd step` (an uncommitted `.gtdrc.json` is a pending change the initial
671
- state's `* **` edge would otherwise capture). `gtd init` refuses if the repo
672
- root already has its OWN gtd config (remove it first to re-init; a
673
- global/ancestor config such as `~/.gtdrc` does not count), requires the
674
- repository root, and is one of the two commands (with `gtd lsp`) that run with
675
- no workflow configured. A state command run before `gtd init` fails with:
688
+ The files are written **uncommitted** — review them, then commit `.gtdrc.json`
689
+ and `gtd-prompts/` before your first `gtd step` (an uncommitted file is a
690
+ pending change the initial state's `* **` edge would otherwise capture).
691
+ `gtd init` refuses if the repo root already has its OWN gtd config (remove it
692
+ first to re-init; a global/ancestor config such as `~/.gtdrc` does not count),
693
+ requires the repository root, and is one of the two commands (with `gtd lsp`)
694
+ that run with no workflow configured. A state command run before `gtd init`
695
+ fails with:
676
696
 
677
697
  ```
678
698
  gtd: no workflow configured — run `gtd init <simple|advanced>` to create .gtdrc.json
@@ -62,15 +62,15 @@ slots into.
62
62
  | `grilling-answer` | human | message | `C` → `architecting`; `* **` → `grilling` | — | — | `vars.todoFile` | `qa` |
63
63
  | `architecting` | agent | prompt | `* **` → `architecting-answer` | — | `smart` | `vars.architectureFile` | `qa` |
64
64
  | `architecting-answer` | human | message | `C` → `decompose`; `* **` → `architecting` | — | — | `vars.architectureFile` | `qa` |
65
- | `decompose` | agent | prompt | `* .gtd/tasks/**` → `picking` | — | — | — | — |
65
+ | `decompose` | agent | prompt | `* .gtd/tasks/**` → `picking` | — | `base` | — | — |
66
66
  | `picking` | check | script | `D .gtd/NEXT.md` → `reviewing`; `* .gtd/NEXT.md` → `building`; `C` → `reviewing` | — | — | — | — |
67
- | `building` | agent | prompt | `* **` → `checking` | — | — | — | — |
67
+ | `building` | agent | prompt | `* **` → `checking` | — | `base` | — | — |
68
68
  | `checking` | check | script | `A .gtd/FEEDBACK.md` → `fixing`; `M .gtd/FEEDBACK.md` → `fixing`; `C` → `picking` | — | — | — | — |
69
- | `fixing` | agent | prompt | `* **` → `checking` | max 3 → `escalate` | — | `vars.feedbackFile` | — |
69
+ | `fixing` | agent | prompt | `* **` → `checking` | max 3 → `escalate` | `base` | `vars.feedbackFile` | — |
70
70
  | `escalate` | human | message | `* **` → `checking` | — | — | `vars.feedbackFile` | — |
71
71
  | `reviewing` | agent | prompt | `* .gtd/REVIEW.md` → `await-review` | — | `smart` | `vars.reviewFile` | `review` |
72
72
  | `await-review` | human | message | `D .gtd/REVIEW.md` → `squashing`; `* **` → `grilling` | — | — | `vars.reviewFile` | `review` |
73
- | `squashing` | agent | prompt | `A .gtd/COMMIT_MSG.md` → `done`; `M .gtd/COMMIT_MSG.md` → `done` | — | — | — | — |
73
+ | `squashing` | agent | prompt | `A .gtd/COMMIT_MSG.md` → `done`; `M .gtd/COMMIT_MSG.md` → `done` | — | `base` | — | — |
74
74
  | `done` | — | commit | (final — squashes the whole cycle, message read from `.gtd/COMMIT_MSG.md`) | — | — |
75
75
 
76
76
  ## The `.gtdrc` recipe
@@ -83,6 +83,11 @@ workflow:
83
83
  architectureFile: .gtd/ARCHITECTURE.md
84
84
  reviewFile: .gtd/REVIEW.md
85
85
  feedbackFile: .gtd/FEEDBACK.md
86
+ # The two model tiers every agent state draws from — opaque harness hints,
87
+ # repointed here (or via a top-level .gtdrc `vars:` / `GTD_VAR_` override)
88
+ # to change every state on that tier at once.
89
+ plannerModel: smart
90
+ coderModel: base
86
91
 
87
92
  states:
88
93
  idle:
@@ -102,11 +107,12 @@ workflow:
102
107
  mode: qa
103
108
  # `model` is an opaque harness hint — gtd never interprets this string, it
104
109
  # only passes it through to `gtd next --json`/`gtd status --json` so the
105
- # driving loop can map it onto whatever models its agent harness
106
- # provides. "smart" here just names the harness-chosen tier for the
107
- # heavier planning/reviewing turns; states without a `model` use the
108
- # harness's default.
109
- model: smart
110
+ # driving loop can map it onto whatever models its agent harness provides.
111
+ # Every agent state draws its tier from a `vars` model entry (see `vars:`
112
+ # above): `plannerModel` (default "smart") for the one-shot planning/
113
+ # architecting/reviewing turns, `coderModel` (default "base") for the
114
+ # decompose/build/fix/squash turns.
115
+ model: <%= it.vars.plannerModel %>
110
116
  prompt: |
111
117
  You are an autonomous coding agent. `.gtd/` holds this workflow's own
112
118
  state (plans, task specs, review records) — never create, edit, or
@@ -155,7 +161,7 @@ workflow:
155
161
  actor: agent
156
162
  file: <%= it.vars.architectureFile %>
157
163
  mode: qa
158
- model: smart
164
+ model: <%= it.vars.plannerModel %>
159
165
  prompt: |
160
166
  You are an autonomous coding agent. `.gtd/` holds this workflow's own
161
167
  state — never create, edit, or delete anything under `.gtd/` except
@@ -201,6 +207,7 @@ workflow:
201
207
 
202
208
  decompose:
203
209
  actor: agent
210
+ model: <%= it.vars.coderModel %>
204
211
  prompt: |
205
212
  You are an autonomous coding agent. `.gtd/` holds this workflow's own
206
213
  state — never create, edit, or delete anything under `.gtd/` except the
@@ -249,6 +256,7 @@ workflow:
249
256
 
250
257
  building:
251
258
  actor: agent
259
+ model: <%= it.vars.coderModel %>
252
260
  prompt: |
253
261
  You are an autonomous coding agent. `.gtd/` holds this workflow's own
254
262
  state — never create or edit anything under `.gtd/` except deleting the
@@ -303,6 +311,7 @@ workflow:
303
311
  fixing:
304
312
  actor: agent
305
313
  file: <%= it.vars.feedbackFile %>
314
+ model: <%= it.vars.coderModel %>
306
315
  retry:
307
316
  max: 3
308
317
  otherwise: escalate
@@ -338,7 +347,7 @@ workflow:
338
347
  actor: agent
339
348
  file: <%= it.vars.reviewFile %>
340
349
  mode: review
341
- model: smart
350
+ model: <%= it.vars.plannerModel %>
342
351
  # A second way in: `gtd review <commitish>` (clean tree, resting at the
343
352
  # initial state) enters here directly over <commitish>..HEAD — see
344
353
  # STATES.md §11.
@@ -388,6 +397,7 @@ workflow:
388
397
 
389
398
  squashing:
390
399
  actor: agent
400
+ model: <%= it.vars.coderModel %>
391
401
  prompt: |
392
402
  You are an autonomous coding agent. The cycle is approved and done.
393
403
  `.gtd/` holds this workflow's own state — never create, edit, or delete
package/docs/upgrading.md CHANGED
@@ -129,7 +129,8 @@ upgrading each repo must scaffold one **once**:
129
129
  gtd init simple # or: gtd init advanced
130
130
  ```
131
131
 
132
- `gtd init simple` writes a `.gtdrc.json` with the `simple` template inline: a
132
+ `gtd init simple` writes a `.gtdrc.json` for the `simple` template (its agent
133
+ prompts extracted to editable `gtd-prompts/*.md` files the config references): a
133
134
  single-shot `grilling` plan, direct `building`, a `checking`/`fixing` loop, and
134
135
  a direct-diff `await-review` that rests the cycle back at `idle` on approval —
135
136
  no squash; every turn commit stays in history for you to squash however you
@@ -139,10 +140,10 @@ like, or not at all (see
139
140
  ⇄ architecting-answer / decompose / picking / reviewing machine — including a
140
141
  squash finale — walked through at
141
142
  [docs/examples/advanced-workflow.md](examples/advanced-workflow.md). Review and
142
- commit the generated `.gtdrc.json`, then continue from a settled `idle`
143
- boundary. **Note:** a repo relying on earlier gtd's auto-created `.gtdrc.json`
144
- `$schema` stub (which carried no `workflow:`) will now fail until you `gtd init`
145
- — the stub alone is no longer enough.
143
+ commit the generated `.gtdrc.json` (and its `gtd-prompts/` directory), then
144
+ continue from a settled `idle` boundary. **Note:** a repo relying on earlier
145
+ gtd's auto-created `.gtdrc.json` `$schema` stub (which carried no `workflow:`)
146
+ will now fail until you `gtd init` — the stub alone is no longer enough.
146
147
 
147
148
  A repo that customized v2's `workflow:` key (actors, gates, guard vocabulary,
148
149
  ladders) needs to rewrite it from scratch in the v3 schema — see
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmelab/gtd",
3
- "version": "6.1.1",
3
+ "version": "6.3.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": {