@pmelab/gtd 6.4.0 → 6.5.1
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/dist/gtd.bundle.mjs +45 -37
- package/docs/configuration.md +4 -4
- package/docs/design/state-file-association.md +4 -4
- package/docs/design/steering-file-loops.md +25 -18
- package/docs/design/steering-file-validation-command.md +2 -3
- package/docs/examples/advanced-workflow.md +30 -13
- package/package.json +1 -1
package/dist/gtd.bundle.mjs
CHANGED
|
@@ -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#\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";
|
|
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 near the top, one `### <question>` sub-heading each, its body\n your suggested answer in plain prose (always suggest one — the human\n accepts it by leaving it untouched, or overrides it by editing it). Omit\n the section entirely once there are none.\n\n If `.gtd/TODO.md` already carries a `## Open Questions` section from a\n previous lap, the human has now responded to that whole batch: fold every\n one of those questions into the plan — the human's edit where they gave\n one, your own suggestion where they left it untouched (an untouched\n suggestion IS acceptance) — and MOVE each resolved `### <question>` block\n down into a `## Answered Questions` section at the bottom. Raise any\n genuinely new questions under `## Open Questions` at the top.\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 answer.\n\n To answer a question, edit its body in place, then run\n `gtd step human`; leave a suggestion untouched to accept it as-is. On the\n next lap the agent folds every answered question into the plan and moves\n it down to `## Answered Questions`.\n\n To accept all suggested answers 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, its body your suggested answer in plain prose). Omit the\n section once there are none. On a return lap, fold the whole answered\n batch into the plan and move each resolved `### <question>` block down\n into a `## Answered Questions` section at the bottom, exactly as grilling\n does.\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 body in place, then run `gtd step human`;\n leave a suggestion untouched to accept it as-is.\n\n To accept all suggested answers 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 # 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.\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. `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";
|
|
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): answer a question by\n# editing its body in place, or leave a suggestion untouched to accept it;\n# a clean step accepts every remaining suggestion -> building; any edit\n# loops back to grilling (which folds the whole answered batch into the\n# plan and moves it down to `## Answered Questions`).\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 near the top, one `### <question>`\n sub-heading each, its body your suggested answer in plain prose (always\n suggest one — the human accepts it by leaving it untouched, or overrides\n it by editing it). Omit the section entirely once there are no open\n questions.\n\n If `<%= it.vars.todoFile %>` already carries a `## Open Questions`\n section from a previous lap, the human has now responded to that whole\n batch: fold every one of those questions into the plan — using the\n human's edit where they gave one, your own suggested answer where they\n left it untouched (an untouched suggestion IS acceptance) — and MOVE each\n resolved `### <question>` block down into a `## Answered Questions`\n section at the very bottom, keeping it as a record. Raise any genuinely\n new questions this lap under `## Open Questions` at the top.\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 answer. Answer a question by editing its body in place; leave a\n suggestion untouched to accept it as-is. On the next lap the agent folds\n every answered question into the plan and moves it down to\n `## Answered Questions`.\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 answer 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
|
/**
|
|
@@ -203373,33 +203373,42 @@ function getWellformedEdit(textEdit) {
|
|
|
203373
203373
|
//#endregion
|
|
203374
203374
|
//#region src/OpenQuestions.ts
|
|
203375
203375
|
const OPEN_QUESTIONS_HEADING = "## Open Questions";
|
|
203376
|
-
const
|
|
203377
|
-
/**
|
|
203378
|
-
|
|
203379
|
-
|
|
203380
|
-
|
|
203376
|
+
const ANSWERED_QUESTIONS_HEADING = "## Answered Questions";
|
|
203377
|
+
/**
|
|
203378
|
+
* Parses an ATX heading (`#`..`######` followed by a space and text, OR a bare
|
|
203379
|
+
* `###` run with no text), or `undefined` when the (trimmed) line isn't a
|
|
203380
|
+
* heading. A bare `### ` is a level-3 heading with empty `text` on purpose — an
|
|
203381
|
+
* open-question heading with no question text is the one structural error this
|
|
203382
|
+
* format reports, so it must be recognised rather than skipped as prose.
|
|
203383
|
+
*/
|
|
203384
|
+
const parseHeading = (line) => {
|
|
203385
|
+
const match = /^(#{1,6})(?:\s+(.*))?$/.exec(line.trim());
|
|
203386
|
+
return match ? {
|
|
203387
|
+
level: match[1].length,
|
|
203388
|
+
text: (match[2] ?? "").trim()
|
|
203389
|
+
} : void 0;
|
|
203381
203390
|
};
|
|
203382
203391
|
/**
|
|
203383
|
-
* Splits the lines after `##
|
|
203384
|
-
* Stops at the next level-1/2 heading (the end of the section) or EOF;
|
|
203385
|
-
* heading deeper than level 3, or plain prose, is skipped as filler between
|
|
203392
|
+
* Splits the lines after a `## ... Questions` heading into consecutive `###`
|
|
203393
|
+
* blocks. Stops at the next level-1/2 heading (the end of the section) or EOF;
|
|
203394
|
+
* a heading deeper than level 3, or plain prose, is skipped as filler between
|
|
203386
203395
|
* blocks.
|
|
203387
203396
|
*/
|
|
203388
203397
|
const splitQuestionBlocks = (lines, start) => {
|
|
203389
203398
|
const blocks = [];
|
|
203390
203399
|
let i = start;
|
|
203391
203400
|
while (i < lines.length) {
|
|
203392
|
-
const
|
|
203393
|
-
if (
|
|
203394
|
-
if (level !== 3) {
|
|
203401
|
+
const heading = parseHeading(lines[i]);
|
|
203402
|
+
if (heading !== void 0 && heading.level <= 2) break;
|
|
203403
|
+
if (heading?.level !== 3) {
|
|
203395
203404
|
i += 1;
|
|
203396
203405
|
continue;
|
|
203397
203406
|
}
|
|
203398
|
-
const question =
|
|
203407
|
+
const question = heading.text;
|
|
203399
203408
|
const headingLine = i;
|
|
203400
203409
|
i += 1;
|
|
203401
203410
|
const body = [];
|
|
203402
|
-
while (i < lines.length &&
|
|
203411
|
+
while (i < lines.length && parseHeading(lines[i]) === void 0) {
|
|
203403
203412
|
body.push(lines[i]);
|
|
203404
203413
|
i += 1;
|
|
203405
203414
|
}
|
|
@@ -203412,16 +203421,13 @@ const splitQuestionBlocks = (lines, start) => {
|
|
|
203412
203421
|
return blocks;
|
|
203413
203422
|
};
|
|
203414
203423
|
/** Parses one question block into a well-formed `OpenQuestion`, or an error message. */
|
|
203415
|
-
const parseQuestionBlock = (block) => {
|
|
203416
|
-
if (block.question.length === 0) return { error: "An '### '
|
|
203417
|
-
const firstNonBlank = block.body.map((line) => line.trim()).find((line) => line.length > 0);
|
|
203418
|
-
const responseMatch = firstNonBlank ? RESPONSE_RE.exec(firstNonBlank) : void 0;
|
|
203419
|
-
const text = responseMatch?.[2]?.trim() ?? "";
|
|
203420
|
-
if (!responseMatch || text.length === 0) return { error: `Open question "${block.question}" is missing a "Suggested default: ..." or "Answer: ..." line` };
|
|
203424
|
+
const parseQuestionBlock = (block, status) => {
|
|
203425
|
+
if (block.question.length === 0) return { error: "An '### ' question heading under '## Open Questions' or '## Answered Questions' has no question text" };
|
|
203426
|
+
const firstNonBlank = block.body.map((line) => line.trim()).find((line) => line.length > 0) ?? "";
|
|
203421
203427
|
return {
|
|
203422
203428
|
question: block.question,
|
|
203423
|
-
status
|
|
203424
|
-
text,
|
|
203429
|
+
status,
|
|
203430
|
+
text: firstNonBlank,
|
|
203425
203431
|
headingLine: block.headingLine
|
|
203426
203432
|
};
|
|
203427
203433
|
};
|
|
@@ -203429,25 +203435,27 @@ const parseQuestionBlock = (block) => {
|
|
|
203429
203435
|
* Parses the open-questions structure out of `content` (the raw text of
|
|
203430
203436
|
* `.gtd/TODO.md` or `.gtd/ARCHITECTURE.md`). Total and side-effect-free:
|
|
203431
203437
|
* always returns a result, never throws. `errors` is non-empty exactly when
|
|
203432
|
-
* the document violates the required structure (a `###` question under
|
|
203433
|
-
*
|
|
203434
|
-
*
|
|
203435
|
-
*
|
|
203438
|
+
* the document violates the required structure (a `###` question under either
|
|
203439
|
+
* questions section with no question text) — the caller decides what to do with
|
|
203440
|
+
* that (`gtd validate` exits non-zero with them; the LSP publishes them as
|
|
203441
|
+
* diagnostics). Questions are returned in document order (by heading line)
|
|
203442
|
+
* regardless of which section comes first.
|
|
203436
203443
|
*/
|
|
203437
203444
|
const parseOpenQuestions = (content) => {
|
|
203438
203445
|
const lines = content.split(/\r?\n/);
|
|
203439
|
-
const headingIndex = lines.findIndex((line) => line.trim() === OPEN_QUESTIONS_HEADING);
|
|
203440
|
-
if (headingIndex === -1) return {
|
|
203441
|
-
questions: [],
|
|
203442
|
-
errors: []
|
|
203443
|
-
};
|
|
203444
203446
|
const questions = [];
|
|
203445
203447
|
const errors = [];
|
|
203446
|
-
|
|
203447
|
-
|
|
203448
|
-
|
|
203449
|
-
|
|
203448
|
+
const sections = [[OPEN_QUESTIONS_HEADING, "open"], [ANSWERED_QUESTIONS_HEADING, "answered"]];
|
|
203449
|
+
for (const [heading, status] of sections) {
|
|
203450
|
+
const headingIndex = lines.findIndex((line) => line.trim() === heading);
|
|
203451
|
+
if (headingIndex === -1) continue;
|
|
203452
|
+
for (const block of splitQuestionBlocks(lines, headingIndex + 1)) {
|
|
203453
|
+
const result = parseQuestionBlock(block, status);
|
|
203454
|
+
if ("error" in result) errors.push(result.error);
|
|
203455
|
+
else questions.push(result);
|
|
203456
|
+
}
|
|
203450
203457
|
}
|
|
203458
|
+
questions.sort((a, b) => a.headingLine - b.headingLine);
|
|
203451
203459
|
return {
|
|
203452
203460
|
questions,
|
|
203453
203461
|
errors
|
|
@@ -203638,7 +203646,7 @@ const spanRange = (lines, startLine, endLine) => ({
|
|
|
203638
203646
|
character: (lines[endLine] ?? "").length
|
|
203639
203647
|
}
|
|
203640
203648
|
});
|
|
203641
|
-
const statusMarker = (status) => status === "answered" ? "[answered]" : "[
|
|
203649
|
+
const statusMarker = (status) => status === "answered" ? "[answered]" : "[open]";
|
|
203642
203650
|
/** Document symbols for `.gtd/TODO.md`'s open questions. */
|
|
203643
203651
|
const questionSymbols = (content) => {
|
|
203644
203652
|
const { questions } = parseOpenQuestions(content);
|
package/docs/configuration.md
CHANGED
|
@@ -271,10 +271,10 @@ workflow:
|
|
|
271
271
|
**steering-file mode**. Two names are BUILT IN, each carrying a VALIDATOR gtd
|
|
272
272
|
implements itself:
|
|
273
273
|
|
|
274
|
-
| `mode` | Format
|
|
275
|
-
| -------- |
|
|
276
|
-
| `qa` | The open-questions format (`## Open Questions
|
|
277
|
-
| `review` | The checkbox review format (`# Review: <hash>` header, `<!-- base: <hash> -->` comment, `##` chunks, `- [ ]` pointers).
|
|
274
|
+
| `mode` | Format |
|
|
275
|
+
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
276
|
+
| `qa` | The open-questions format (`## Open Questions` near the top and `## Answered Questions` at the bottom, one `###` sub-heading per question with a free-form body; status is positional, no marker line). |
|
|
277
|
+
| `review` | The checkbox review format (`# Review: <hash>` header, `<!-- base: <hash> -->` comment, `##` chunks, `- [ ]` pointers). |
|
|
278
278
|
|
|
279
279
|
Any other name must be declared in a `modes:` map (next section) — as must a
|
|
280
280
|
`format:` command for these two, since gtd ships no formatter. A `mode:` naming
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
## 1. The two new state properties
|
|
19
19
|
|
|
20
|
-
| Property | Meaning
|
|
21
|
-
| -------- |
|
|
22
|
-
| `file:` | Optional. THE steering file this state is about — the file a human/editor should look at while the machine rests here. An **Eta template** rendered with the standard `TemplateContext` (in practice `<%= it.vars.… %>`; the full context is available). Forbidden on commit states (never at rest), must render non-empty.
|
|
23
|
-
| `mode:` | Optional, requires `file:`. The file's FORMAT, from a closed, documented vocabulary: `qa` (the open-questions format — `## Open Questions
|
|
20
|
+
| Property | Meaning |
|
|
21
|
+
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
22
|
+
| `file:` | Optional. THE steering file this state is about — the file a human/editor should look at while the machine rests here. An **Eta template** rendered with the standard `TemplateContext` (in practice `<%= it.vars.… %>`; the full context is available). Forbidden on commit states (never at rest), must render non-empty. |
|
|
23
|
+
| `mode:` | Optional, requires `file:`. The file's FORMAT, from a closed, documented vocabulary: `qa` (the open-questions format — `## Open Questions` / `## Answered Questions` sections, `###` question with a free-form body, status positional) or `review` (the checkbox review format — `# Review:` header, `##` chunks, `- [ ]` pointers). Unknown values are a load error (typos must not silently disable editor support). The ENGINE never branches on it — like `model`, it is emitted data; only the LSP interprets it. |
|
|
24
24
|
|
|
25
25
|
Multiple states may (and in the default, do) share one file+mode — the mode
|
|
26
26
|
describes the file, the association is per state.
|
|
@@ -29,13 +29,20 @@ bounce):
|
|
|
29
29
|
|
|
30
30
|
**`.gtd/TODO.md` open questions** (`OpenQuestions.ts`):
|
|
31
31
|
|
|
32
|
-
- Free-form prose, plus an OPTIONAL `## Open Questions` section (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
- Free-form prose, plus an OPTIONAL `## Open Questions` section (near the top)
|
|
33
|
+
and an OPTIONAL `## Answered Questions` section (at the bottom) — either
|
|
34
|
+
absent = zero questions of that status, valid.
|
|
35
|
+
- Every `###` sub-heading directly under one of those sections is one question;
|
|
36
|
+
its STATUS is POSITIONAL (under `## Open Questions` → open, under
|
|
37
|
+
`## Answered Questions` → answered). The body is free-form (the agent's
|
|
38
|
+
suggested answer for an open one, the settled resolution for an answered one)
|
|
39
|
+
— there is no `Suggested default:`/`Answer:` marker line. The only structural
|
|
40
|
+
error is a `###` heading with no question text.
|
|
41
|
+
- A question is answered/accepted by MOVING its `###` block down into
|
|
42
|
+
`## Answered Questions` (the agent does this on the next `grilling` lap; a
|
|
43
|
+
human leaving a suggestion untouched IS acceptance). Nothing enforces the move
|
|
44
|
+
or the section order — that is the producing agent's prompt contract.
|
|
45
|
+
- Each section ends at the next level-1/2 heading or EOF.
|
|
39
46
|
|
|
40
47
|
**`.gtd/REVIEW.md`** (`ReviewDoc.ts`):
|
|
41
48
|
|
|
@@ -72,10 +79,11 @@ Current 7 states, plus the two loops. `smart` on `grilling` and `reviewing`.
|
|
|
72
79
|
- `todo-validating` (deterministic script): parse-check TODO.md against §1's
|
|
73
80
|
rules. Malformed → write findings to `.gtd/FORMAT.md` (one line each) → back
|
|
74
81
|
to `grilling`. Valid → `rm -f .gtd/FORMAT.md` → `grilling-answer`.
|
|
75
|
-
- `grilling-answer` (human): answer by
|
|
76
|
-
|
|
77
|
-
`building`); any edit loops back to `grilling` (the
|
|
78
|
-
|
|
82
|
+
- `grilling-answer` (human): answer by editing a question's body in place, or
|
|
83
|
+
leave a suggestion untouched to accept it; accept all remaining suggestions
|
|
84
|
+
with a clean step (`C` → `building`); any edit loops back to `grilling` (the
|
|
85
|
+
agent folds the whole answered batch into the plan, moving each resolved block
|
|
86
|
+
down to `## Answered Questions`, possibly asks follow-ups, and re-validates).
|
|
79
87
|
|
|
80
88
|
**Loop 2 — REVIEW.md checkboxes (maps the LSP's review chunks/check actions):**
|
|
81
89
|
|
|
@@ -110,12 +118,11 @@ REVIEW.md by the approval, TODO.md by `building`.
|
|
|
110
118
|
|
|
111
119
|
Same discipline as `checking`/the old `picking`: mechanics-only bash, verdict =
|
|
112
120
|
file op, semantics = the `on` map. Grep/awk ports of the parser rules
|
|
113
|
-
(pragmatic, not a full markdown parser): e.g. a question
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
actionable input.
|
|
121
|
+
(pragmatic, not a full markdown parser): e.g. a `###` question heading with no
|
|
122
|
+
question text is a finding; a pointer line failing the
|
|
123
|
+
`- [(x| )] ./path(#N)?( — note)?` shape is a finding; `- [ ]` presence is the
|
|
124
|
+
review-deciding branch condition. Findings go into `.gtd/FORMAT.md` verbatim
|
|
125
|
+
(file + line + rule), so the fixing agent gets actionable input.
|
|
119
126
|
|
|
120
127
|
## 4. Change chart
|
|
121
128
|
|
|
@@ -143,7 +150,7 @@ what is workflow-agnostic — the FILE FORMATS, not any particular state machine
|
|
|
143
150
|
- **New `src/Lsp.ts`** (recover from history, then STRIP the v2-model
|
|
144
151
|
dependencies — Events/Machine/ReviewWindow/STATE_FILE are gone): keyed on FILE
|
|
145
152
|
NAME, not state. For `.gtd/TODO.md`: document symbols for open questions
|
|
146
|
-
([
|
|
153
|
+
([open]/[answered]). For `.gtd/REVIEW.md`: chunk/hunk symbols and the
|
|
147
154
|
check/uncheck code actions (hunk and whole-chunk). BOTH files: publish the
|
|
148
155
|
parsers' `errors` as diagnostics — the same findings the workflow's
|
|
149
156
|
`.gtd/FORMAT.md` validators produce, live in the editor. The v2
|
|
@@ -332,9 +332,8 @@ to the driver protocol — `dispatch on kind` + the new validate gate).
|
|
|
332
332
|
`a commit "gtd(<actor>): <state>" that adds …`:
|
|
333
333
|
- `grilling` + a valid `.gtd/TODO.md` → `gtd validate` succeeds, stdout
|
|
334
334
|
"valid".
|
|
335
|
-
- `grilling` + a malformed `.gtd/TODO.md` (
|
|
336
|
-
|
|
337
|
-
the finding.
|
|
335
|
+
- `grilling` + a malformed `.gtd/TODO.md` (a bare `###` question heading with
|
|
336
|
+
no question text) → `gtd validate` fails, stderr carries the finding.
|
|
338
337
|
- `reviewing` + a malformed `.gtd/REVIEW.md` (missing `# Review:` header) →
|
|
339
338
|
fails with the finding; a valid one → succeeds.
|
|
340
339
|
- a state with a `file:` but no `mode:` (e.g. `fixing`) → succeeds with
|
|
@@ -129,9 +129,18 @@ workflow:
|
|
|
129
129
|
the next phase (`.gtd/ARCHITECTURE.md`).
|
|
130
130
|
|
|
131
131
|
For every remaining open question, add it under a `## Open Questions`
|
|
132
|
-
heading, one `### <question>` sub-heading each,
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
heading near the top, one `### <question>` sub-heading each, its body
|
|
133
|
+
your suggested answer in plain prose (always suggest one — the human
|
|
134
|
+
accepts it by leaving it untouched, or overrides it by editing it). Omit
|
|
135
|
+
the section entirely once there are none.
|
|
136
|
+
|
|
137
|
+
If `.gtd/TODO.md` already carries a `## Open Questions` section from a
|
|
138
|
+
previous lap, the human has now responded to that whole batch: fold every
|
|
139
|
+
one of those questions into the plan — the human's edit where they gave
|
|
140
|
+
one, your own suggestion where they left it untouched (an untouched
|
|
141
|
+
suggestion IS acceptance) — and MOVE each resolved `### <question>` block
|
|
142
|
+
down into a `## Answered Questions` section at the bottom. Raise any
|
|
143
|
+
genuinely new questions under `## Open Questions` at the top.
|
|
135
144
|
|
|
136
145
|
Leave `.gtd/TODO.md` uncommitted and finish your turn — do not commit,
|
|
137
146
|
and do not run `gtd step agent` yourself; the harness does that.
|
|
@@ -145,13 +154,14 @@ workflow:
|
|
|
145
154
|
message: |
|
|
146
155
|
`<%= it.vars.todoFile %>` holds the plan under development, with any
|
|
147
156
|
open questions under `## Open Questions` — each carrying a suggested
|
|
148
|
-
|
|
157
|
+
answer.
|
|
149
158
|
|
|
150
|
-
To answer a question, edit its
|
|
151
|
-
`
|
|
152
|
-
|
|
159
|
+
To answer a question, edit its body in place, then run
|
|
160
|
+
`gtd step human`; leave a suggestion untouched to accept it as-is. On the
|
|
161
|
+
next lap the agent folds every answered question into the plan and moves
|
|
162
|
+
it down to `## Answered Questions`.
|
|
153
163
|
|
|
154
|
-
To accept all suggested
|
|
164
|
+
To accept all suggested answers as-is and move on to technical
|
|
155
165
|
architecting, run `gtd step human` with no edits.
|
|
156
166
|
on:
|
|
157
167
|
"C": architecting
|
|
@@ -177,8 +187,11 @@ workflow:
|
|
|
177
187
|
|
|
178
188
|
For every remaining open question, add it under a `## Open Questions`
|
|
179
189
|
heading the same way as the grilling phase (one `### <question>`
|
|
180
|
-
sub-heading,
|
|
181
|
-
once there are none.
|
|
190
|
+
sub-heading, its body your suggested answer in plain prose). Omit the
|
|
191
|
+
section once there are none. On a return lap, fold the whole answered
|
|
192
|
+
batch into the plan and move each resolved `### <question>` block down
|
|
193
|
+
into a `## Answered Questions` section at the bottom, exactly as grilling
|
|
194
|
+
does.
|
|
182
195
|
|
|
183
196
|
Once `<%= it.vars.architectureFile %>` is written, delete
|
|
184
197
|
`<%= it.vars.todoFile %>` — its content has been folded in and it must
|
|
@@ -196,10 +209,10 @@ workflow:
|
|
|
196
209
|
`<%= it.vars.architectureFile %>` holds the technical plan under
|
|
197
210
|
development, with any open questions under `## Open Questions`.
|
|
198
211
|
|
|
199
|
-
To answer a question, edit its
|
|
200
|
-
|
|
212
|
+
To answer a question, edit its body in place, then run `gtd step human`;
|
|
213
|
+
leave a suggestion untouched to accept it as-is.
|
|
201
214
|
|
|
202
|
-
To accept all suggested
|
|
215
|
+
To accept all suggested answers as-is and move on to decomposing the
|
|
203
216
|
work, run `gtd step human` with no edits.
|
|
204
217
|
on:
|
|
205
218
|
"C": decompose
|
|
@@ -380,6 +393,10 @@ workflow:
|
|
|
380
393
|
actor: human
|
|
381
394
|
file: <%= it.vars.reviewFile %>
|
|
382
395
|
mode: review
|
|
396
|
+
# Opens the review checkout window: HEAD/index are rewound to the cycle
|
|
397
|
+
# start so the whole diff shows as uncommitted changes in the editor
|
|
398
|
+
# (see STATES.md §11). Closes automatically once the cycle rests elsewhere.
|
|
399
|
+
reviewWindow: true
|
|
383
400
|
message: |
|
|
384
401
|
`<%= it.vars.reviewFile %>` holds the review record for the completed
|
|
385
402
|
cycle.
|