@pmelab/gtd 5.1.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1058,15 +1058,15 @@ const hash = (self) => {
1058
1058
  if (structuralRegionState.enabled === true) return 0;
1059
1059
  switch (typeof self) {
1060
1060
  case "number": return number$1(self);
1061
- case "bigint": return string$2(self.toString(10));
1062
- case "boolean": return string$2(String(self));
1063
- case "symbol": return string$2(String(self));
1064
- case "string": return string$2(self);
1065
- case "undefined": return string$2("undefined");
1061
+ case "bigint": return string(self.toString(10));
1062
+ case "boolean": return string(String(self));
1063
+ case "symbol": return string(String(self));
1064
+ case "string": return string(self);
1065
+ case "undefined": return string("undefined");
1066
1066
  case "function":
1067
- case "object": if (self === null) return string$2("null");
1067
+ case "object": if (self === null) return string("null");
1068
1068
  else if (self instanceof Date) {
1069
- if (Number.isNaN(self.getTime())) return string$2("Invalid Date");
1069
+ if (Number.isNaN(self.getTime())) return string("Invalid Date");
1070
1070
  return hash(self.toISOString());
1071
1071
  } else if (self instanceof URL) return hash(self.href);
1072
1072
  else if (isHash(self)) return self[symbol$1]();
@@ -1112,7 +1112,7 @@ const number$1 = (n) => {
1112
1112
  * @since 2.0.0
1113
1113
  * @category hashing
1114
1114
  */
1115
- const string$2 = (str) => {
1115
+ const string = (str) => {
1116
1116
  let h = 5381, i = str.length;
1117
1117
  while (i) h = h * 33 ^ str.charCodeAt(--i);
1118
1118
  return optimize(h);
@@ -1123,7 +1123,7 @@ const string$2 = (str) => {
1123
1123
  */
1124
1124
  const structureKeys = (o, keys) => {
1125
1125
  let h = 12289;
1126
- for (let i = 0; i < keys.length; i++) h ^= pipe(string$2(keys[i]), combine$7(hash(o[keys[i]])));
1126
+ for (let i = 0; i < keys.length; i++) h ^= pipe(string(keys[i]), combine$7(hash(o[keys[i]])));
1127
1127
  return optimize(h);
1128
1128
  };
1129
1129
  /**
@@ -6665,7 +6665,7 @@ const OP_NONE = "None";
6665
6665
  const OP_RUNTIME = "Runtime";
6666
6666
  /** @internal */
6667
6667
  const OP_COMPOSITE = "Composite";
6668
- const emptyHash = /*#__PURE__*/ string$2(`${FiberIdSymbolKey}-${OP_NONE}`);
6668
+ const emptyHash = /*#__PURE__*/ string(`${FiberIdSymbolKey}-${OP_NONE}`);
6669
6669
  /** @internal */
6670
6670
  var None$2 = class {
6671
6671
  [FiberIdTypeId] = FiberIdTypeId;
@@ -6702,7 +6702,7 @@ var Runtime = class {
6702
6702
  this.startTimeMillis = startTimeMillis;
6703
6703
  }
6704
6704
  [symbol$1]() {
6705
- return cached(this, string$2(`${FiberIdSymbolKey}-${this._tag}-${this.id}-${this.startTimeMillis}`));
6705
+ return cached(this, string(`${FiberIdSymbolKey}-${this._tag}-${this.id}-${this.startTimeMillis}`));
6706
6706
  }
6707
6707
  [symbol](that) {
6708
6708
  return isFiberId$1(that) && that._tag === OP_RUNTIME && this.id === that.id && this.startTimeMillis === that.startTimeMillis;
@@ -6734,7 +6734,7 @@ var Composite$1 = class {
6734
6734
  }
6735
6735
  _hash;
6736
6736
  [symbol$1]() {
6737
- return pipe(string$2(`${FiberIdSymbolKey}-${this._tag}`), combine$7(hash(this.left)), combine$7(hash(this.right)), cached(this));
6737
+ return pipe(string(`${FiberIdSymbolKey}-${this._tag}`), combine$7(hash(this.left)), combine$7(hash(this.right)), cached(this));
6738
6738
  }
6739
6739
  [symbol](that) {
6740
6740
  return isFiberId$1(that) && that._tag === OP_COMPOSITE && equals$2(this.left, that.left) && equals$2(this.right, that.right);
@@ -7047,7 +7047,7 @@ const makeCons = (head, tail) => {
7047
7047
  cons.tail = tail;
7048
7048
  return cons;
7049
7049
  };
7050
- const NilHash = /*#__PURE__*/ string$2("Nil");
7050
+ const NilHash = /*#__PURE__*/ string("Nil");
7051
7051
  const _Nil = /*#__PURE__*/ Object.create({
7052
7052
  [TypeId$18]: TypeId$18,
7053
7053
  _tag: "Nil",
@@ -7957,7 +7957,7 @@ var EffectPrimitiveFailure = class {
7957
7957
  return exitIsExit(that) && that._op === "Failure" && equals$2(this.effect_instruction_i0, that.effect_instruction_i0);
7958
7958
  }
7959
7959
  [symbol$1]() {
7960
- return pipe(string$2(this._tag), combine$7(hash(this.effect_instruction_i0)), cached(this));
7960
+ return pipe(string(this._tag), combine$7(hash(this.effect_instruction_i0)), cached(this));
7961
7961
  }
7962
7962
  get cause() {
7963
7963
  return this.effect_instruction_i0;
@@ -7998,7 +7998,7 @@ var EffectPrimitiveSuccess = class {
7998
7998
  return exitIsExit(that) && that._op === "Success" && equals$2(this.effect_instruction_i0, that.effect_instruction_i0);
7999
7999
  }
8000
8000
  [symbol$1]() {
8001
- return pipe(string$2(this._tag), combine$7(hash(this.effect_instruction_i0)), cached(this));
8001
+ return pipe(string(this._tag), combine$7(hash(this.effect_instruction_i0)), cached(this));
8002
8002
  }
8003
8003
  get value() {
8004
8004
  return this.effect_instruction_i0;
@@ -10127,7 +10127,7 @@ const OP_DONE$3 = "Done";
10127
10127
  const OP_RUNNING = "Running";
10128
10128
  /** @internal */
10129
10129
  const OP_SUSPENDED = "Suspended";
10130
- const DoneHash = /*#__PURE__*/ string$2(`${FiberStatusSymbolKey}-${OP_DONE$3}`);
10130
+ const DoneHash = /*#__PURE__*/ string(`${FiberStatusSymbolKey}-${OP_DONE$3}`);
10131
10131
  /** @internal */
10132
10132
  var Done$1 = class {
10133
10133
  [FiberStatusTypeId] = FiberStatusTypeId;
@@ -10551,7 +10551,7 @@ const makeExit = (options) => {
10551
10551
  return isMicroExit(that) && that._tag === options.op && equals$2(this[args], that[args]);
10552
10552
  },
10553
10553
  [symbol$1]() {
10554
- return cached(this, combine$7(string$2(options.op))(hash(this[args])));
10554
+ return cached(this, combine$7(string(options.op))(hash(this[args])));
10555
10555
  }
10556
10556
  };
10557
10557
  return function(value) {
@@ -11203,7 +11203,7 @@ var MetricLabelImpl = class {
11203
11203
  constructor(key, value) {
11204
11204
  this.key = key;
11205
11205
  this.value = value;
11206
- this._hash = string$2(MetricLabelSymbolKey + this.key + this.value);
11206
+ this._hash = string(MetricLabelSymbolKey + this.key + this.value);
11207
11207
  }
11208
11208
  [symbol$1]() {
11209
11209
  return this._hash;
@@ -11734,7 +11734,7 @@ var MetricBoundariesImpl = class {
11734
11734
  [MetricBoundariesTypeId] = MetricBoundariesTypeId;
11735
11735
  constructor(values) {
11736
11736
  this.values = values;
11737
- this._hash = pipe(string$2(MetricBoundariesSymbolKey), combine$7(array(this.values)));
11737
+ this._hash = pipe(string(MetricBoundariesSymbolKey), combine$7(array(this.values)));
11738
11738
  }
11739
11739
  _hash;
11740
11740
  [symbol$1]() {
@@ -11786,7 +11786,7 @@ var CounterKeyType = class {
11786
11786
  constructor(incremental, bigint) {
11787
11787
  this.incremental = incremental;
11788
11788
  this.bigint = bigint;
11789
- this._hash = string$2(CounterKeyTypeSymbolKey);
11789
+ this._hash = string(CounterKeyTypeSymbolKey);
11790
11790
  }
11791
11791
  _hash;
11792
11792
  [symbol$1]() {
@@ -11806,7 +11806,7 @@ var HistogramKeyType = class {
11806
11806
  [HistogramKeyTypeTypeId] = HistogramKeyTypeTypeId;
11807
11807
  constructor(boundaries) {
11808
11808
  this.boundaries = boundaries;
11809
- this._hash = pipe(string$2(HistogramKeyTypeSymbolKey), combine$7(hash(this.boundaries)));
11809
+ this._hash = pipe(string(HistogramKeyTypeSymbolKey), combine$7(hash(this.boundaries)));
11810
11810
  }
11811
11811
  _hash;
11812
11812
  [symbol$1]() {
@@ -11853,7 +11853,7 @@ var MetricKeyImpl = class {
11853
11853
  this.keyType = keyType;
11854
11854
  this.description = description;
11855
11855
  this.tags = tags;
11856
- this._hash = pipe(string$2(this.name + this.description), combine$7(hash(this.keyType)), combine$7(array(this.tags)));
11856
+ this._hash = pipe(string(this.name + this.description), combine$7(hash(this.keyType)), combine$7(array(this.tags)));
11857
11857
  }
11858
11858
  _hash;
11859
11859
  [symbol$1]() {
@@ -12058,7 +12058,7 @@ var FrequencyState = class {
12058
12058
  }
12059
12059
  _hash;
12060
12060
  [symbol$1]() {
12061
- return pipe(string$2(FrequencyStateSymbolKey), combine$7(array(fromIterable$6(this.occurrences.entries()))), cached(this));
12061
+ return pipe(string(FrequencyStateSymbolKey), combine$7(array(fromIterable$6(this.occurrences.entries()))), cached(this));
12062
12062
  }
12063
12063
  [symbol](that) {
12064
12064
  return isFrequencyState(that) && arrayEquals(fromIterable$6(this.occurrences.entries()), fromIterable$6(that.occurrences.entries()));
@@ -15357,7 +15357,7 @@ const ProtoTimeZoneNamed = {
15357
15357
  ...ProtoTimeZone,
15358
15358
  _tag: "Named",
15359
15359
  [symbol$1]() {
15360
- return cached(this, string$2(`Named:${this.id}`));
15360
+ return cached(this, string(`Named:${this.id}`));
15361
15361
  },
15362
15362
  [symbol](that) {
15363
15363
  return isTimeZone(that) && that._tag === "Named" && this.id === that.id;
@@ -15377,7 +15377,7 @@ const ProtoTimeZoneOffset = {
15377
15377
  ...ProtoTimeZone,
15378
15378
  _tag: "Offset",
15379
15379
  [symbol$1]() {
15380
- return cached(this, string$2(`Offset:${this.offset}`));
15380
+ return cached(this, string(`Offset:${this.offset}`));
15381
15381
  },
15382
15382
  [symbol](that) {
15383
15383
  return isTimeZone(that) && that._tag === "Offset" && this.offset === that.offset;
@@ -29906,8 +29906,6 @@ const collectUint8Array = /*#__PURE__*/ foldLeftChunks(/*#__PURE__*/ new Uint8Ar
29906
29906
  /** @internal */
29907
29907
  const CommandTypeId = /*#__PURE__*/ Symbol.for("@effect/platform/Command");
29908
29908
  /** @internal */
29909
- const isCommand = (u) => typeof u === "object" && u != null && CommandTypeId in u;
29910
- /** @internal */
29911
29909
  const flatten$1 = (self) => Array.from(flattenLoop(self));
29912
29910
  /** @internal */
29913
29911
  const flattenLoop = (self) => {
@@ -30012,8 +30010,6 @@ const stdout$1 = /*#__PURE__*/ dual(2, (self, output) => {
30012
30010
  }
30013
30011
  });
30014
30012
  /** @internal */
30015
- const string$1 = /*#__PURE__*/ dual((args) => isCommand(args[0]), (command, encoding) => flatMap$4(CommandExecutor$1, (executor) => executor.string(command, encoding)));
30016
- /** @internal */
30017
30013
  const workingDirectory$1 = /*#__PURE__*/ dual(2, (self, cwd) => {
30018
30014
  switch (self._tag) {
30019
30015
  case "StandardCommand": return makeStandard({
@@ -30045,16 +30041,6 @@ const flatten = flatten$1;
30045
30041
  */
30046
30042
  const make$1 = make$2;
30047
30043
  /**
30048
- * Runs the command returning the entire output as a string with the
30049
- * specified encoding.
30050
- *
30051
- * If an encoding is not specified, the encoding will default to `utf-8`.
30052
- *
30053
- * @since 1.0.0
30054
- * @category execution
30055
- */
30056
- const string = string$1;
30057
- /**
30058
30044
  * Specify the standard error stream for a command.
30059
30045
  *
30060
30046
  * @since 1.0.0
@@ -190046,27 +190032,6 @@ const compileWorkflowConfig = (raw, configDir, rcModes) => {
190046
190032
  };
190047
190033
  };
190048
190034
  //#endregion
190049
- //#region src/workflows/default.ts
190050
- /**
190051
- * The bundled default workflow, compiled through the exact same
190052
- * `compileWorkflowConfig` a user's `.gtdrc` `workflow:` key goes through — no
190053
- * privileged code path (see default.yaml's header comment for why every
190054
- * content string there is inline rather than a `./`-relative file
190055
- * reference). `default.yaml` is imported as raw text (tsdown's `.yaml` text
190056
- * loader / the vitest `rawMd` transform — see tsdown.config.ts /
190057
- * tests/vitest.rawMd.ts), so this module never touches the filesystem: it
190058
- * works identically in the dev checkout, under `vitest`, and inside the
190059
- * single-file `dist/gtd.bundle.mjs` build.
190060
- *
190061
- * `configDir` is passed as `"."` and never actually consulted: none of
190062
- * default.yaml's content values start with `./`/`../`, so
190063
- * `compileWorkflowConfig` never resolves a file reference against it.
190064
- */
190065
- const compiled = compileWorkflowConfig((0, import_dist$1.parse)("# The bundled default gtd workflow (v3 \"pattern machine\" — see\n# docs/design/pattern-machine-plan.md, and\n# docs/design/steering-file-validation-command.md for the `gtd validate`\n# self-validation model that replaced the old in-machine validation loops).\n# Compiled through the exact same `compileWorkflowConfig` a user's `.gtdrc`\n# `workflow:` key goes through — no privileged code path\n# (src/workflows/default.ts does the compiling).\n#\n# Every content string below is INLINE (no `./`-relative file references):\n# the bundled default ships inside a single-file build\n# (`dist/gtd.bundle.mjs`), so its content must already be resolved at BUILD\n# time rather than read from disk at RUNTIME — the same reason\n# `src/prompts/*.md` are imported through tsdown's `.md`-as-text loader\n# instead of read via `fs` at runtime. `default.yaml` itself is imported the\n# same way (tsdown/vitest both treat `.yaml` as text — see\n# tsdown.config.ts / tests/vitest.rawMd.ts), so this file never needs a\n# sibling prompts/ directory to exist on disk once installed.\n#\n# States, in cycle order — 10 states, no squash:\n# idle (initial, human, message)\n# -> grilling (agent, prompt): reads .gtd/TODO.md's sketch (or a prior\n# lap's feedback), explores the codebase, and develops it into a concrete\n# implementation plan, stating any open question it can't settle itself\n# under a `## Open Questions` heading rather than guessing silently. Its\n# `file:`/`mode:` (TODO.md/`qa`) makes the plan's format checkable — it\n# self-validates before finishing (see \"Steering-file validation\" below).\n# grilling -> grilling-answer (human, message): tick off suggested\n# defaults by replacing them with `Answer:` lines; a clean step accepts\n# every remaining default -> building; any edit loops back to grilling.\n# grilling-answer -> building (agent, prompt): implements the plan in\n# .gtd/TODO.md directly (no task decomposition, no per-task queue) and\n# deletes .gtd/TODO.md once the work is complete and verified.\n# building -> checking (check, script): runs the test command inline;\n# A/M .gtd/FEEDBACK.md -> fixing (capped, redirects to escalate); D\n# .gtd/FEEDBACK.md (a green run that just cleaned up prior feedback) or C\n# (green, nothing to clean) -> reviewing.\n# fixing (agent, prompt) <-> checking\n# escalate (human, message): manual intervention, then back to checking\n# checking (green) -> reviewing (agent, prompt): writes .gtd/REVIEW.md in\n# the checkbox review format, grouping the cycle's full diff into\n# reviewable chunks; its `file:`/`mode:` (REVIEW.md/`review`) makes that\n# format checkable, so it self-validates before finishing. `reviewing`\n# ALSO declares `reviewEntry: true` — a second way in: `gtd review\n# <commitish>` (a clean tree resting at idle) writes an empty\n# `gtd(human): reviewing` entry commit carrying <commitish>'s hash as a\n# `Gtd-Review-Base:` trailer, starting a brand new process that reviews\n# <commitish>..HEAD (e.g. a colleague's PR branch) through this exact same\n# reviewing/await-review/feedback-lap machinery.\n# reviewing -> await-review (human, message): tick a pointer's `- [\n# ]` to `- [x]` to approve that item; deleting .gtd/REVIEW.md outright is\n# the power-user approve-everything shortcut; anything else pending\n# (code edits with REVIEW.md untouched) is feedback straight to grilling.\n# await-review -> review-deciding (check, script), entered by any `M\n# .gtd/REVIEW.md` step: if no unticked `- [ ]` pointer remains, the cycle\n# is approved (rm .gtd/REVIEW.md -> idle); otherwise the still-unticked\n# pointers (with their notes) are extracted into a fresh .gtd/TODO.md and\n# .gtd/REVIEW.md is removed (-> grilling, feedback lap).\n#\n# The cycle ends at human approval, resting back at idle — there is no\n# squash state. The cycle's commits stay in history; whether/how to squash\n# them (amend, interactive rebase, a PR's squash-merge) is entirely the\n# human's business once they're done reviewing — gtd makes no assumption.\n# That squash-flavored finale (a `squashing` prompt state + a `done` commit\n# state) still exists as an ENGINE capability (see STATES.md §8) and is kept\n# as part of the fuller machine at docs/examples/advanced-workflow.md.\n#\n# A `gtd(<actor>): idle` commit — entering the workflow's own initial state —\n# is therefore a PROCESS BOUNDARY (see `computeProcessRun` in src/Edge.ts):\n# the next cycle's `retry` counts, `startCommit`, and diffs never reach back\n# across an approved cycle's own idle-entering commit.\n#\n# HYGIENE INVARIANT (asserted in e2e — see default-workflow.feature): an\n# approved cycle leaves `.gtd/` empty. FEEDBACK.md is cleaned up by a green\n# `checking` run; REVIEW.md by the review-deciding approval branch; TODO.md by\n# `building`.\n#\n# Steering-file validation. `grilling` and `reviewing` each declare a\n# `file:`/`mode:` pair (TODO.md as `qa`, REVIEW.md as `review`), so their\n# output has a checkable format. src/OpenQuestions.ts and src/ReviewDoc.ts are\n# those two formats' EXECUTABLE SPECS (their unit tests are the format spec\n# tests), and `gtd validate` FORMATS the resolved state's rendered `file:` in\n# place then runs the SAME parser over it, exiting non-zero with findings when\n# it violates the format. There is no in-machine validation state and no bash\n# port to keep in sync — the producing agent self-validates before finishing\n# (plain `gtd next` appends the \"run `gtd validate` and fix all violations\"\n# instruction; under `--json` the driving loop runs it after the turn and\n# re-prompts on findings — see skills/loop/SKILL.md), AND `gtd step` runs the\n# same format-and-validate gate on capture, refusing a turn whose steering file\n# is invalid. So the check runs after a human edits too — at the human gates\n# `grilling-answer` (TODO.md) and `await-review` (REVIEW.md) — and a human gate\n# is only ever handed a tidy, well-formed file. The same parsers back the LSP's\n# live diagnostics (src/Lsp.ts).\n#\n# `grilling` and `reviewing` both declare `model: smart` — an opaque harness\n# hint (see the comment at `grilling` below) for their heavier one-shot\n# planning/reviewing turns. Every other state is unset (harness default).\n#\n# The four agent states each declare a `memory:` scope label (`plan`,\n# `build`, `fix`, `review` — see the comment at `grilling` below) — another\n# opaque hint a memory-aware driver reads to decide when an agent turn keeps\n# the previous turn's memory and when it starts fresh: a loop that re-enters\n# one state (grilling around its answer loop, fixing around checking) keeps\n# the same label and retains memory across its laps; crossing to the next\n# phase's differently-labelled state clears it. gtd never interprets the\n# label (see STATES.md §1 and skills/loop/SKILL.md's driver contract).\n#\n# `vars.testCommand` is this workflow's own declared default for `checking`'s\n# script (see it.vars in PatternTemplates.ts) — override it per-repo with a\n# top-level `.gtdrc` `vars: { testCommand: ... }` key, or per-invocation with\n# a `GTD_VAR_testCommand` environment variable (highest precedence).\n#\n# `vars.todoFile`/`reviewFile`/`feedbackFile` are this workflow's ONE source\n# of truth for the three steering-file paths every prompt/script below reads\n# or writes — each appears in templates as `<%~ it.vars.todoFile %>` etc\n# (see docs/design/state-file-association.md §2). Every state that rests on\n# one of these files also declares a `file:`/`mode:` pair (see STATES.md's\n# property table) so `gtd status`/`gtd next --json` and the LSP (`gtd lsp`)\n# know which file a human/editor should look at, and in what format\n# (`qa` for TODO.md's open-questions format, `review` for REVIEW.md's\n# checkbox format) — `fixing`/`escalate` declare `file:` alone (FEEDBACK.md\n# is plain text, no LSP format). KNOWN LIMITATION: `on` pattern keys below are\n# NOT Eta templates — they keep the LITERAL `.gtd/...` paths matching these\n# vars' DEFAULT values. Repointing `todoFile`/`reviewFile`/`feedbackFile` via\n# `.gtdrc`'s top-level `vars:` or a `GTD_VAR_` override changes what `file:`\n# renders to (and what a template reads/writes) WITHOUT changing what the\n# `on` patterns match against — desyncing the machine. See\n# docs/configuration.md's `file:`/`mode:` section for the full caveat.\n#\n# A fuller machine — two-phase Q&A planning, an architecture phase, task\n# decomposition, a deterministic per-task builder loop, agent-prepared\n# review, and the squash finale (`squashing` + `done`) — is preserved as a\n# copy-paste `.gtdrc` example at docs/examples/advanced-workflow.md.\n\nvars:\n testCommand: npm test\n todoFile: .gtd/TODO.md\n reviewFile: .gtd/REVIEW.md\n feedbackFile: .gtd/FEEDBACK.md\n\nstates:\n idle:\n actor: human\n initial: true\n # Every human-gate `message:` below closes with the SAME rendered block —\n # a \"What each change does next\" list built from `it.edges`, the resting\n # state's own `on` edges (see PatternTemplates.TemplateContext.edges). Each\n # edge's human-readable route lives in its `describe:` (the single source\n # of truth), so the list can never drift from the routing it documents.\n # The block skips edges without a `describe`, and each `<%~ ... \"\\n\" %>`\n # keeps the bullet's own newline (Eta's autoTrim strips the template's own\n # line breaks around `<% %>` tags, not text inside an interpolation).\n message: |\n No active gtd cycle.\n\n To start one, write `.gtd/TODO.md` with a short sketch of what you want\n built — a few sentences is enough.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: grilling\n describe: >-\n Save your sketch to `.gtd/TODO.md` (any working-tree change) to start\n the cycle — the agent reads it, explores the codebase, and develops it\n into a concrete implementation plan (**grilling**).\n\n grilling:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # `model` is an opaque harness hint — gtd never interprets this string, it\n # only passes it through to `gtd next --json`/`gtd status --json` so the\n # driving loop can map it onto whatever models its agent harness\n # provides. \"smart\" here just names the harness-chosen tier for the\n # heavier planning turn; states without a `model` use the harness's\n # default.\n model: smart\n # `memory` is an opaque memory-scope label — gtd never interprets it, it\n # only passes it through to `gtd next --json`/`gtd status --json` so a\n # memory-aware driving loop can decide when an agent turn continues from\n # the previous turn's memory and when it starts fresh: consecutive agent\n # turns that emit the SAME label share memory, a change (or the first\n # turn) is where the driver starts fresh. `grilling` re-enters itself\n # around the grilling-answer loop, so labelling every lap\n # `plan` keeps the planner's accumulated exploration across the loop; the\n # next phase (`building`) carries a different label, clearing it.\n memory: plan\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.todoFile %>`, which this prompt tells you to develop.\n\n `<%= it.vars.todoFile %>` holds a short sketch of what to build (or\n feedback from a prior review lap). Read it, explore the codebase, and\n develop it into a concrete implementation plan.\n\n For every question you cannot settle yourself, add it under a\n `## Open Questions` heading, one `### <question>` sub-heading each,\n whose body's FIRST non-blank line is exactly\n `Suggested default: <your answer>` — the human can accept it as-is or\n override it. Omit the section entirely once there are no open\n questions. If `<%= it.vars.todoFile %>` already carries\n `## Open Questions` entries from a previous lap, fold any\n `Answer: <text>` line into the plan; every remaining entry's body must\n still start with either `Suggested default: ...` or `Answer: ...` —\n never anything else.\n\n Leave `<%= it.vars.todoFile %>` uncommitted and finish your turn — do\n not commit, and do not run `gtd step agent` yourself; the harness does\n that.\n on:\n \"* **\": grilling-answer\n\n grilling-answer:\n actor: human\n file: <%= it.vars.todoFile %>\n mode: qa\n message: |\n `<%= it.vars.todoFile %>` holds the plan under development, with any\n open questions under `## Open Questions` — each carrying a suggested\n default. Answer a question by editing its entry in place: replace its\n `Suggested default: ...` line with `Answer: ...`, or add further detail.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"C\":\n to: building\n describe: >-\n Change nothing to accept every suggested default as-is and move on to\n implementation (**building**).\n \"* **\":\n to: grilling\n describe: >-\n Edit the plan — answer a question, add detail, or raise a new one — to\n send it back for another round of grilling (**grilling**).\n\n building:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # A distinct memory scope from `plan`: implementation starts fresh, with\n # the plan already settled in `.gtd/TODO.md` (which this prompt reads\n # below) rather than carried in the planner's working memory.\n memory: build\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create or edit anything under `.gtd/` except deleting\n `<%= it.vars.todoFile %>`, which this prompt tells you to delete once\n its work is complete.\n\n The plan to implement is: <%~ it.read(it.vars.todoFile) %>\n\n Read that plan and implement it in full. Use TDD discipline: one test,\n then the implementation that passes it, then the next — never write\n all the tests first.\n\n Delete `<%= it.vars.todoFile %>` once the work it describes is complete\n and verified. Leave everything else uncommitted and finish your turn.\n on:\n \"* **\": checking\n\n checking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: run the test suite and record a\n # red run's output as .gtd/FEEDBACK.md. What that output MEANS (another\n # fix round vs escalation) is decided by the workflow's own `on`/`retry`\n # rules at capture time — never here.\n #\n # `it.vars.testCommand` defaults to \"npm test\" (this workflow's own\n # `vars:` above) — override it with a top-level `.gtdrc`\n # `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`\n # environment variable (highest precedence).\n #\n # A green run also removes any `<%= it.vars.feedbackFile %>` left over\n # from an earlier red run — there is no squash to discard it for us\n # anymore, so the script cleans it up itself before moving on to\n # review.\n set +e\n mkdir -p .gtd\n <%~ it.vars.testCommand %> > .gtd/.check-output 2>&1\n code=$?\n if [ \"$code\" -ne 0 ]; then\n if [ -s .gtd/.check-output ]; then\n mv .gtd/.check-output <%~ it.vars.feedbackFile %>\n else\n rm -f .gtd/.check-output\n printf 'npm test failed with exit code %s and produced no output.' \"$code\" > <%~ it.vars.feedbackFile %>\n fi\n else\n rm -f .gtd/.check-output\n rm -f <%~ it.vars.feedbackFile %>\n fi\n on:\n \"A .gtd/FEEDBACK.md\": fixing\n \"M .gtd/FEEDBACK.md\": fixing\n \"D .gtd/FEEDBACK.md\": reviewing\n \"C\": reviewing\n\n fixing:\n actor: agent\n file: <%= it.vars.feedbackFile %>\n # Its own memory scope: the fix loop re-enters `fixing` around `checking`\n # (up to the retry cap), so labelling every attempt `fix` lets the agent\n # remember what it already tried across the loop; a green check moves on\n # to the differently-labelled `reviewing`, clearing it.\n memory: fix\n retry:\n max: 3\n otherwise: escalate\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.feedbackFile %>`, which this prompt tells you to address.\n\n Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix\n the code so the suite passes. Keep the change focused — do not\n refactor unrelated code. If the feedback is wrong, empty or delete\n `<%= it.vars.feedbackFile %>` instead of \"fixing\" a non-issue; the\n machine picks the dispute up either way.\n\n Leave everything uncommitted and finish your turn — do not commit.\n on:\n \"* **\": checking\n\n escalate:\n actor: human\n file: <%= it.vars.feedbackFile %>\n message: |\n The agent could not get the check to pass after repeated attempts.\n `<%= it.vars.feedbackFile %>` holds the last failing output.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: checking\n describe: >-\n Fix the failure yourself — edit the code and/or `.gtd/FEEDBACK.md` —\n to re-run the check (**checking**).\n\n reviewing:\n actor: agent\n file: <%= it.vars.reviewFile %>\n mode: review\n model: smart\n # A distinct memory scope again: the reviewer looks at the cycle's full\n # diff (inlined into its prompt) with a fresh perspective, not the\n # builder's or fixer's working memory.\n memory: review\n # `gtd review <commitish>` (a plain non-gtd branch, e.g. a colleague's PR)\n # enters here directly, recording the resolved base as a `Gtd-Review-Base:`\n # trailer on its empty entry commit — everything below then reuses the\n # existing reviewing/await-review/feedback-lap machinery unmodified over\n # <commitish>..HEAD (see STATES.md §11).\n reviewEntry: true\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.reviewFile %>`, which this prompt tells you to write.\n\n Write `<%= it.vars.reviewFile %>` to help a human review the cycle's\n full diff (inlined below) in this EXACT format:\n\n - First non-blank line: `# Review: <%= it.currentCommit.slice(0, 7) %>`\n - Somewhere in the document: `<!-- base: <%= it.startCommit %> -->`\n - At least one `## <Chunk Title>` heading, grouping hunks semantically\n (same feature/refactor/fix, even across files) — a short explanation\n of what changed and why, then one\n `- [ ] ./path/to/file.ts#42 — note` file pointer per hunk (checkboxes\n are for the human to tick, not you; every path is `./`-relative, with\n an optional `#line` and an optional ` — note`).\n\n Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"* **\": await-review\n\n await-review:\n actor: human\n file: <%= it.vars.reviewFile %>\n mode: review\n # While the cycle rests here for human review, gtd opens a \"review checkout\n # window\": HEAD and the index are temporarily rewound to this cycle's start\n # (the process boundary — no `reviewBase` state is declared, so the base\n # defaults to it) with the working tree untouched, so the whole cycle diff\n # surfaces as ordinary uncommitted changes in the editor's git integration.\n # The window closes automatically on the next invocation, once the cycle\n # rests anywhere else (see src/ReviewWindow.ts, STATES.md §11).\n reviewWindow: true\n message: |\n `<%= it.vars.reviewFile %>` holds the review record for the completed\n cycle — one `- [ ]` checkbox per reviewable item, grouped into chunks.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"D .gtd/REVIEW.md\":\n to: idle\n describe: >-\n Delete `.gtd/REVIEW.md` outright to approve the whole cycle at once\n and rest back at the start (**idle**).\n \"M .gtd/REVIEW.md\":\n to: review-deciding\n describe: >-\n Edit `.gtd/REVIEW.md` — tick a `- [ ]` box to `- [x]` to approve that\n item, or add notes — to hand it to a deterministic check\n (**review-deciding**) that closes the cycle out when every box is\n ticked, or extracts the still-unticked items into a fresh\n `.gtd/TODO.md` and loops back through **grilling** with that feedback.\n \"* **\":\n to: grilling\n describe: >-\n Change only code, leaving `.gtd/REVIEW.md` untouched, to send that as\n feedback straight back to **grilling**.\n\n review-deciding:\n actor: check\n file: <%= it.vars.reviewFile %>\n mode: review\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: if .gtd/REVIEW.md still has any\n # unticked \"- [ ]\" pointer, extract those pointers (with their notes)\n # into a fresh .gtd/TODO.md; either way, remove .gtd/REVIEW.md. What\n # the resulting diff MEANS (feedback lap vs. full approval) is decided\n # by this state's own `on` rules at capture time — never here. The\n # A/M .gtd/TODO.md row is declared BEFORE the D .gtd/REVIEW.md row (see\n # this workflow's `on` map below) so a feedback lap — which always also\n # deletes .gtd/REVIEW.md — is captured as feedback, not mistaken for an\n # approval.\n set +e\n mkdir -p .gtd\n if grep -qE '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %> 2>/dev/null; then\n {\n echo \"Feedback from review — address these before continuing:\"\n echo\n grep -E '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %>\n } > <%~ it.vars.todoFile %>\n fi\n rm -f <%~ it.vars.reviewFile %>\n on:\n \"A .gtd/TODO.md\": grilling\n \"M .gtd/TODO.md\": grilling\n \"D .gtd/REVIEW.md\": idle\n \"C\": await-review\n"), ".");
190066
- const defaultWorkflowDefinition = compiled.definition;
190067
- /** The default workflow's own declared `vars:` defaults — `{ testCommand: "npm test" }`, overridable via a top-level `.gtdrc` `vars:` key or a `GTD_VAR_testCommand` environment variable (see `src/Edge.ts`'s `resolveVars`). */
190068
- const defaultWorkflowVars = compiled.vars;
190069
- //#endregion
190070
190035
  //#region src/Cwd.ts
190071
190036
  var Cwd = class Cwd extends Tag("Cwd")() {
190072
190037
  static layer = (root) => succeed$2(Cwd, { root });
@@ -190104,10 +190069,11 @@ var Cwd = class Cwd extends Tag("Cwd")() {
190104
190069
  * Kept in its own module, separate from `./Config.js`, so `scripts/generate-
190105
190070
  * schema.ts` (run via `jiti`, a plain TS-via-Babel loader with no bundler-
190106
190071
  * style pluggable per-extension loaders) can import JUST the schema without
190107
- * pulling in `./Config.js`'s chain to `./workflows/default.js` — which
190108
- * imports `default.yaml` as raw text via tsdown's/vitest's `.yaml`-as-text
190109
- * loader, something `jiti` has no equivalent for and doesn't need here: the
190110
- * schema shape never depends on the bundled default workflow's content.
190072
+ * risking a transitive pull into the bundled workflow templates
190073
+ * (`./workflows/templates.js`, which imports `simple.yaml`/`advanced.yaml` as
190074
+ * raw text via tsdown's/vitest's `.yaml`-as-text loader — something `jiti` has
190075
+ * no equivalent for and doesn't need here): the schema shape never depends on
190076
+ * any workflow's content.
190111
190077
  */
190112
190078
  /** The `vars:` shape (top-level AND inside `workflow:`): a flat name -> scalar map (`compileVarsMap` coerces every scalar to a string). */
190113
190079
  const varsJsonSchema = {
@@ -190355,11 +190321,11 @@ const loadMerged = (root) => tryPromise({
190355
190321
  },
190356
190322
  catch: (e) => e instanceof Error ? e : new Error(String(e))
190357
190323
  });
190358
- const SCHEMA_STUB = `${JSON.stringify({ $schema: "https://raw.githubusercontent.com/pmelab/gtd/main/schema.json" }, null, 2)}\n`;
190359
190324
  /**
190360
190325
  * Reuses the same `walkUp` + `searchStrategy: "none"` cosmiconfig explorer as
190361
190326
  * `loadMerged` to detect whether ANY level of the cwd→root walk carries a gtd
190362
- * config. Returns `true` on the first non-empty `search(dir)` result.
190327
+ * config. Returns `true` on the first non-empty `search(dir)` result. Exported
190328
+ * so `gtd init` (src/program.ts) can refuse to overwrite an existing config.
190363
190329
  */
190364
190330
  const anyConfigPresent = (root) => tryPromise({
190365
190331
  try: async () => {
@@ -190412,29 +190378,25 @@ const compileRcVars = (raw) => {
190412
190378
  return vars;
190413
190379
  };
190414
190380
  /**
190415
- * Compile the decoded config's `workflow:` key (or the bundled default, when
190416
- * absent) plus its top-level `vars:`/`modes:` keys into `ConfigOperations`. `root` is
190417
- * used as the workflow compiler's `configDir` — the directory a custom
190418
- * workflow's `./`-relative content references resolve against. Throws (via
190419
- * `compileWorkflowConfig`/`compileRcVars`) on any invalid custom
190420
- * workflow/vars; the bundled default's workflow half never throws here (it
190421
- * is pre-compiled and validated once at module load, see
190422
- * `./workflows/default.ts`).
190381
+ * The error every config-reading command fails with when no `workflow:` key is
190382
+ * configured anywhere in the cwd→home chain. gtd ships no default workflow, so
190383
+ * there is nothing to fall back to — the user must scaffold one with
190384
+ * `gtd init`. Exported so the CLI layer and tests can assert on it verbatim.
190385
+ */
190386
+ const NO_WORKFLOW_MESSAGE = "gtd: no workflow configured — run `gtd init <simple|advanced>` to create .gtdrc.json";
190387
+ /**
190388
+ * Compile the decoded config's `workflow:` key plus its top-level
190389
+ * `vars:`/`modes:` keys into `ConfigOperations`. `root` is used as the
190390
+ * workflow compiler's `configDir` — the directory a custom workflow's
190391
+ * `./`-relative content references resolve against. Throws `NO_WORKFLOW_MESSAGE`
190392
+ * when no `workflow:` key is present (there is no bundled default to fall back
190393
+ * to — see `gtd init`), or (via `compileWorkflowConfig`/`compileRcVars`) on any
190394
+ * invalid workflow/vars.
190423
190395
  */
190424
190396
  const toOperations = (decoded, root) => {
190425
190397
  const rcVars = compileRcVars(decoded.vars);
190426
190398
  const rcModes = compileRcModes(decoded.modes);
190427
- if (decoded.workflow === void 0) {
190428
- const modes = mergeModes(defaultWorkflowDefinition.modes, rcModes);
190429
- return {
190430
- workflow: modes !== void 0 ? {
190431
- ...defaultWorkflowDefinition,
190432
- modes
190433
- } : defaultWorkflowDefinition,
190434
- workflowVars: defaultWorkflowVars,
190435
- rcVars
190436
- };
190437
- }
190399
+ if (decoded.workflow === void 0) throw new Error(NO_WORKFLOW_MESSAGE);
190438
190400
  const { definition, vars: workflowVars } = compileWorkflowConfig(decoded.workflow, root, rcModes);
190439
190401
  return {
190440
190402
  workflow: definition,
@@ -190445,43 +190407,17 @@ const toOperations = (decoded, root) => {
190445
190407
  const formatSchemaError = (e) => {
190446
190408
  return `Invalid gtd config: ${ArrayFormatter.formatErrorSync(e).map((i) => (i.path.length > 0 ? i.path.join(".") + ": " : "") + i.message).join("; ")}`;
190447
190409
  };
190448
- /**
190449
- * Auto-init as an explicit capability, separate from config LOADING: the stub
190450
- * write mutates the repository (a file write plus a commit or amend), so it
190451
- * must only ever run for a state command that has already passed the
190452
- * repo-root guard — never at layer-construction time, where it would fire for
190453
- * `--version`/`--help`, `format`, bare/unknown commands, and root-guard
190454
- * refusals alike (and from a subdirectory would drop the stub into the wrong
190455
- * directory). `makeProgram` calls `ensure` right after the repo-root guard;
190456
- * the in-memory test world provides `ConfigInit.Noop`.
190457
- */
190458
- var ConfigInit = class ConfigInit extends Tag("ConfigInit")() {
190459
- static Noop = succeed$2(ConfigInit, { ensure: _void });
190460
- static Live = effect$1(ConfigInit, gen(function* () {
190461
- const { root } = yield* Cwd;
190462
- const executor = yield* CommandExecutor;
190463
- const fs = yield* FileSystem;
190464
- return { ensure: gen(function* () {
190465
- if (yield* anyConfigPresent(root)) return;
190466
- const git = (...args) => executor.exitCode(make$1("git", ...args).pipe(workingDirectory(root)));
190467
- const writeStub = fs.writeFileString(join(root, ".gtdrc.json"), SCHEMA_STUB).pipe(mapError$1((e) => e instanceof Error ? e : new Error(String(e))));
190468
- const headSubject = yield* make$1("git", "log", "-1", "--pretty=%s").pipe(workingDirectory(root), string).pipe(map$4((s) => s.trim())).pipe(catchAll(() => succeed$3(void 0)));
190469
- yield* writeStub;
190470
- yield* git("add", ".gtdrc.json");
190471
- if (headSubject !== void 0 && parseStateSubject(headSubject) !== void 0) yield* git("commit", "--amend", "--no-edit");
190472
- else yield* git("commit", "-m", "chore: add .gtdrc.json");
190473
- }).pipe(provideService(CommandExecutor, executor), mapError$1((e) => e instanceof Error ? e : new Error(String(e)))) };
190474
- }));
190475
- };
190476
190410
  var ConfigService = class ConfigService extends Tag("ConfigService")() {
190477
190411
  static Live = effect$1(ConfigService, gen(function* () {
190478
190412
  const { root } = yield* Cwd;
190479
- const { $schema: _schema, ...cleaned } = yield* loadMerged(root);
190480
- const decoded = yield* decodeUnknown(ConfigSchema)(cleaned, { onExcessProperty: "error" }).pipe(mapError$1(formatSchemaError)).pipe(mapError$1((msg) => new Error(msg)));
190481
- return yield* try_({
190482
- try: () => toOperations(decoded, root),
190483
- catch: (e) => e instanceof Error ? e : new Error(String(e))
190484
- });
190413
+ return { load: gen(function* () {
190414
+ const { $schema: _schema, ...cleaned } = yield* loadMerged(root);
190415
+ const decoded = yield* decodeUnknown(ConfigSchema)(cleaned, { onExcessProperty: "error" }).pipe(mapError$1(formatSchemaError)).pipe(mapError$1((msg) => new Error(msg)));
190416
+ return yield* try_({
190417
+ try: () => toOperations(decoded, root),
190418
+ catch: (e) => e instanceof Error ? e : new Error(String(e))
190419
+ });
190420
+ }) };
190485
190421
  }));
190486
190422
  };
190487
190423
  //#endregion
@@ -191439,6 +191375,49 @@ var WorktreeReader = class WorktreeReader extends Tag("WorktreeReader")() {
191439
191375
  }));
191440
191376
  };
191441
191377
  //#endregion
191378
+ //#region src/workflows/advanced.yaml
191379
+ var advanced_default = "# The \"advanced\" gtd workflow template — written verbatim into `.gtdrc.json`\n# (nested under a `workflow:` key) by `gtd init advanced`. See\n# docs/examples/advanced-workflow.md for the full state-by-state walkthrough\n# and STATES.md §10 for how it relates to the \"simple\" template.\n#\n# This is the fuller machine: two-phase human-in-the-loop planning\n# (grilling ⇄ grilling-answer for the product plan, architecting ⇄\n# architecting-answer for the technical plan), task decomposition\n# (decompose → .gtd/tasks/), a deterministic per-task builder queue (picking →\n# building → checking/fixing), agent-prepared review (reviewing → await-review),\n# and a squash finale (squashing → done, a `commit:` state that collapses the\n# whole cycle into one commit whose message the agent authored in\n# .gtd/COMMIT_MSG.md).\n#\n# Every content string below is INLINE (no `./`-relative file references): the\n# bundled templates ship inside a single-file build (`dist/gtd.bundle.mjs`), so\n# their content must already be resolved at BUILD time rather than read from\n# disk at RUNTIME. `advanced.yaml` is imported as raw text (tsdown's `.yaml`\n# text loader / the vitest rawMd transform), so this module never touches the\n# filesystem.\n\nvars:\n testCommand: npm test\n todoFile: .gtd/TODO.md\n architectureFile: .gtd/ARCHITECTURE.md\n reviewFile: .gtd/REVIEW.md\n feedbackFile: .gtd/FEEDBACK.md\n\nstates:\n idle:\n actor: human\n initial: true\n message: |\n No active gtd cycle.\n\n To start one: write `.gtd/TODO.md` with a short sketch of what you want\n built — a few sentences is enough — then run `gtd step human`.\n on:\n \"* **\": grilling\n\n grilling:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # `model` is an opaque harness hint — gtd never interprets this string, it\n # only passes it through to `gtd next --json`/`gtd status --json` so the\n # driving loop can map it onto whatever models its agent harness\n # provides. \"smart\" here just names the harness-chosen tier for the\n # heavier planning/reviewing turns; states without a `model` use the\n # harness's default.\n model: smart\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state (plans, task specs, review records) — never create, edit, or\n delete anything under `.gtd/` except `<%= it.vars.todoFile %>`, which\n this prompt tells you to write.\n\n `<%= it.vars.todoFile %>` holds the plan under development. Read it,\n then develop it into a concrete, product-level plan in this one turn —\n explore the codebase before asking anything, so every open question is\n one the codebase genuinely cannot answer.\n\n Scope: product and user-facing decisions only. Leave implementation\n details (file/module structure, data models, tech-stack choices) for\n the next phase (`.gtd/ARCHITECTURE.md`).\n\n For every remaining open question, add it under a `## Open Questions`\n heading, one `### <question>` sub-heading each, with a\n `Suggested default: <answer>` line the human can accept as-is. Omit the\n section entirely once there are none.\n\n Leave `.gtd/TODO.md` uncommitted and finish your turn — do not commit,\n and do not run `gtd step agent` yourself; the harness does that.\n on:\n \"* **\": grilling-answer\n\n grilling-answer:\n actor: human\n file: <%= it.vars.todoFile %>\n mode: qa\n message: |\n `<%= it.vars.todoFile %>` holds the plan under development, with any\n open questions under `## Open Questions` — each carrying a suggested\n default.\n\n To answer a question, edit its entry in place (replace\n `Suggested default: ...` with `Answer: ...`, or annotate further), then\n run `gtd step human`.\n\n To accept all suggested defaults as-is and move on to technical\n architecting, run `gtd step human` with no edits.\n on:\n \"C\": architecting\n \"* **\": grilling\n\n architecting:\n actor: agent\n file: <%= it.vars.architectureFile %>\n mode: qa\n model: smart\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.architectureFile %>` and `<%= it.vars.todoFile %>`, which\n this prompt tells you to write and delete respectively.\n\n Read `<%= it.vars.todoFile %>` (the converged product plan) and\n develop `<%= it.vars.architectureFile %>` from it in this one turn:\n file/module structure, data models, library/tech-stack choices,\n error-handling strategy — the *how*, building on the *what* already\n settled. Do not re-open product-level decisions from\n `<%= it.vars.todoFile %>`; treat them as settled.\n\n For every remaining open question, add it under a `## Open Questions`\n heading the same way as the grilling phase (one `### <question>`\n sub-heading, a `Suggested default: <answer>` line). Omit the section\n once there are none.\n\n Once `<%= it.vars.architectureFile %>` is written, delete\n `<%= it.vars.todoFile %>` — its content has been folded in and it must\n not linger.\n\n Leave everything uncommitted and finish your turn.\n on:\n \"* **\": architecting-answer\n\n architecting-answer:\n actor: human\n file: <%= it.vars.architectureFile %>\n mode: qa\n message: |\n `<%= it.vars.architectureFile %>` holds the technical plan under\n development, with any open questions under `## Open Questions`.\n\n To answer a question, edit its entry in place, then run\n `gtd step human`.\n\n To accept all suggested defaults as-is and move on to decomposing the\n work, run `gtd step human` with no edits.\n on:\n \"C\": decompose\n \"* **\": architecting\n\n decompose:\n actor: agent\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except the\n task-spec files this prompt tells you to write (under `.gtd/tasks/`),\n and `.gtd/ARCHITECTURE.md`, which it tells you to delete.\n\n Read `.gtd/ARCHITECTURE.md` (the converged technical plan) and\n decompose it into an ordered set of self-contained task files under\n `.gtd/tasks/` (e.g. `.gtd/tasks/01-short-name.md`,\n `.gtd/tasks/02-short-name.md`, ...). Order them so the test suite can\n pass again after each one lands; each file is self-contained\n (description, acceptance criteria as `- [ ]` checkboxes, relevant\n paths) since a building turn receives only that one file as context.\n\n No task file may reference any other `.gtd/` file, or a requirement to\n preserve/update workflow state — `.gtd/` is machine-managed and gets\n cleaned up as the cycle proceeds.\n\n Once the task files are written, delete `.gtd/ARCHITECTURE.md`. Leave\n everything uncommitted and finish your turn.\n on:\n \"* .gtd/tasks/**\": picking\n\n picking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn (the queue arbiter) — the loop driver executes this\n # verbatim, then steps the check actor. Mechanics only: take the\n # first task file (by name) under .gtd/tasks/ into .gtd/NEXT.md, or\n # remove .gtd/NEXT.md when the queue is empty. What NEXT.md's\n # presence/absence MEANS (another task to build vs. the queue closing\n # out to review) is decided by this state's own `on` rules at capture\n # time — never here.\n set +e\n next=$(ls .gtd/tasks/*.md 2>/dev/null | head -n 1)\n if [ -n \"$next\" ]; then\n printf '%s' \"$next\" > .gtd/NEXT.md\n else\n rm -f .gtd/NEXT.md\n fi\n on:\n \"D .gtd/NEXT.md\": reviewing\n \"* .gtd/NEXT.md\": building\n \"C\": reviewing\n\n building:\n actor: agent\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create or edit anything under `.gtd/` except deleting the\n one task file this prompt tells you to delete; never touch\n `.gtd/NEXT.md` yourself — the `picking` state owns it.\n\n The task file to implement is: <%~ it.read(\".gtd/NEXT.md\") %>\n\n Read that file and implement EXACTLY the one task it describes — no\n more, no less; leave every other task file under `.gtd/tasks/`\n untouched. Use TDD discipline: one test, then the implementation that\n passes it, then the next — never write all the tests first.\n\n Delete the task file once its work is complete and verified. Leave\n everything else uncommitted and finish your turn.\n on:\n \"* **\": checking\n\n checking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then steps\n # the check actor. Mechanics only: run the test suite and record a\n # red run's output as .gtd/FEEDBACK.md. What that output MEANS (another\n # fix round vs escalation) is decided by the workflow's own `on`/`retry`\n # rules at capture time — never here.\n #\n # `it.vars.testCommand` defaults to \"npm test\" (this workflow's own\n # `vars:` above) — override it with a top-level `.gtdrc`\n # `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`\n # environment variable (highest precedence).\n set +e\n mkdir -p .gtd\n <%~ it.vars.testCommand %> > .gtd/.check-output 2>&1\n code=$?\n if [ \"$code\" -ne 0 ]; then\n if [ -s .gtd/.check-output ]; then\n mv .gtd/.check-output .gtd/FEEDBACK.md\n else\n rm -f .gtd/.check-output\n printf 'npm test failed with exit code %s and produced no output.' \"$code\" > .gtd/FEEDBACK.md\n fi\n else\n rm -f .gtd/.check-output\n fi\n on:\n \"A .gtd/FEEDBACK.md\": fixing\n \"M .gtd/FEEDBACK.md\": fixing\n \"C\": picking\n\n fixing:\n actor: agent\n file: <%= it.vars.feedbackFile %>\n retry:\n max: 3\n otherwise: escalate\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.feedbackFile %>`, which this prompt tells you to address.\n\n Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix\n the code so the suite passes. Keep the change focused — do not\n refactor unrelated code. If the feedback is wrong, empty or delete\n `<%= it.vars.feedbackFile %>` instead of \"fixing\" a non-issue; the\n machine picks the dispute up either way.\n\n Leave everything uncommitted and finish your turn — do not commit.\n on:\n \"* **\": checking\n\n escalate:\n actor: human\n file: <%= it.vars.feedbackFile %>\n message: |\n The agent could not get the check to pass after repeated attempts.\n `<%= it.vars.feedbackFile %>` holds the last failing output.\n\n Investigate and fix it yourself (editing code and/or\n `<%= it.vars.feedbackFile %>`), then run `gtd step human` to try the\n check again.\n on:\n \"* **\": checking\n\n reviewing:\n actor: agent\n file: <%= it.vars.reviewFile %>\n mode: review\n model: smart\n # A direct entry point: `gtd review <commitish>` starts a fresh review\n # process here over `<commitish>..HEAD` (e.g. a colleague's PR branch).\n reviewEntry: true\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.reviewFile %>`, which this prompt tells you to write.\n\n Write `<%= it.vars.reviewFile %>` to help a human review the cycle's\n full diff (inlined below): group hunks semantically (same\n feature/refactor/fix, even across files), and for each group write a\n short heading, an explanation of what changed and why, and\n `- [ ] ./path/to/file.ts#42` style file pointers (checkboxes are for\n the human to tick, not you).\n\n Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"* .gtd/REVIEW.md\": await-review\n\n await-review:\n actor: human\n file: <%= it.vars.reviewFile %>\n mode: review\n message: |\n `<%= it.vars.reviewFile %>` holds the review record for the completed\n cycle.\n\n To approve: delete `<%= it.vars.reviewFile %>` and run\n `gtd step human`.\n\n To request changes: edit `<%= it.vars.reviewFile %>` (or the code)\n with what's wrong — including just ticking its checkboxes — then run\n `gtd step human`; this sends the cycle back through grilling with your\n feedback as the new input.\n on:\n \"D .gtd/REVIEW.md\": squashing\n \"* **\": grilling\n\n squashing:\n actor: agent\n prompt: |\n You are an autonomous coding agent. The cycle is approved and done.\n `.gtd/` holds this workflow's own state — never create, edit, or delete\n anything under `.gtd/` except `.gtd/COMMIT_MSG.md`, which this prompt\n tells you to write.\n\n Write `.gtd/COMMIT_MSG.md` with ONE conventional-commits message for\n the entire cycle (subject line `type(scope): subject`, imperative mood,\n <= 72 characters; a body explaining the why, trade-offs, and key\n decisions). Plain text, no markdown wrapper.\n\n Leave `.gtd/COMMIT_MSG.md` uncommitted and finish your turn — entering\n this file squashes the whole cycle into one commit using its content as\n the message.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"A .gtd/COMMIT_MSG.md\": done\n \"M .gtd/COMMIT_MSG.md\": done\n\n done:\n commit: |\n <%~ it.read(\".gtd/COMMIT_MSG.md\") %>\n\n Token cost: <%= it.processCost %>\n <% it.processCostByModel.forEach(function(m){ %>\n - <%= m.model %>: <%= m.cost %>\n <% }) %>\n";
191380
+ //#endregion
191381
+ //#region src/workflows/simple.yaml
191382
+ var simple_default = "# The \"simple\" gtd workflow template — written verbatim into `.gtdrc.json`\n# (nested under a `workflow:` key) by `gtd init simple`. gtd ships no default\n# workflow: a repo picks one of the bundled templates with `gtd init`, and a\n# state command run with no workflow configured fails (see src/Config.ts).\n# See STATES.md §10 for the walkthrough and docs/examples/advanced-workflow.md\n# for the fuller `advanced` template.\n#\n# Compiled through the exact same `compileWorkflowConfig` a user's `.gtdrc`\n# `workflow:` key goes through — no privileged code path\n# (src/workflows/templates.ts does the compiling).\n#\n# Every content string below is INLINE (no `./`-relative file references):\n# the bundled templates ship inside a single-file build\n# (`dist/gtd.bundle.mjs`), so their content must already be resolved at BUILD\n# time rather than read from disk at RUNTIME — the same reason\n# `src/prompts/*.md` are imported through tsdown's `.md`-as-text loader\n# instead of read via `fs` at runtime. `simple.yaml` itself is imported the\n# same way (tsdown/vitest both treat `.yaml` as text — see\n# tsdown.config.ts / tests/vitest.rawMd.ts), so this file never needs a\n# sibling prompts/ directory to exist on disk once installed.\n#\n# States, in cycle order — 10 states, no squash:\n# idle (initial, human, message)\n# -> grilling (agent, prompt): reads .gtd/TODO.md's sketch (or a prior\n# lap's feedback), explores the codebase, and develops it into a concrete\n# implementation plan, stating any open question it can't settle itself\n# under a `## Open Questions` heading rather than guessing silently. Its\n# `file:`/`mode:` (TODO.md/`qa`) makes the plan's format checkable — it\n# self-validates before finishing (see \"Steering-file validation\" below).\n# grilling -> grilling-answer (human, message): tick off suggested\n# defaults by replacing them with `Answer:` lines; a clean step accepts\n# every remaining default -> building; any edit loops back to grilling.\n# grilling-answer -> building (agent, prompt): implements the plan in\n# .gtd/TODO.md directly (no task decomposition, no per-task queue) and\n# deletes .gtd/TODO.md once the work is complete and verified.\n# building -> checking (check, script): runs the test command inline;\n# A/M .gtd/FEEDBACK.md -> fixing (capped, redirects to escalate); D\n# .gtd/FEEDBACK.md (a green run that just cleaned up prior feedback) or C\n# (green, nothing to clean) -> reviewing.\n# fixing (agent, prompt) <-> checking\n# escalate (human, message): manual intervention, then back to checking\n# checking (green) -> reviewing (agent, prompt): writes .gtd/REVIEW.md in\n# the checkbox review format, grouping the cycle's full diff into\n# reviewable chunks; its `file:`/`mode:` (REVIEW.md/`review`) makes that\n# format checkable, so it self-validates before finishing. `reviewing`\n# ALSO declares `reviewEntry: true` — a second way in: `gtd review\n# <commitish>` (a clean tree resting at idle) writes an empty\n# `gtd(human): reviewing` entry commit carrying <commitish>'s hash as a\n# `Gtd-Review-Base:` trailer, starting a brand new process that reviews\n# <commitish>..HEAD (e.g. a colleague's PR branch) through this exact same\n# reviewing/await-review/feedback-lap machinery.\n# reviewing -> await-review (human, message): tick a pointer's `- [\n# ]` to `- [x]` to approve that item; deleting .gtd/REVIEW.md outright is\n# the power-user approve-everything shortcut; anything else pending\n# (code edits with REVIEW.md untouched) is feedback straight to grilling.\n# await-review -> review-deciding (check, script), entered by any `M\n# .gtd/REVIEW.md` step: if no unticked `- [ ]` pointer remains, the cycle\n# is approved (rm .gtd/REVIEW.md -> idle); otherwise the still-unticked\n# pointers (with their notes) are extracted into a fresh .gtd/TODO.md and\n# .gtd/REVIEW.md is removed (-> grilling, feedback lap).\n#\n# The cycle ends at human approval, resting back at idle — there is no\n# squash state. The cycle's commits stay in history; whether/how to squash\n# them (amend, interactive rebase, a PR's squash-merge) is entirely the\n# human's business once they're done reviewing — gtd makes no assumption.\n# That squash-flavored finale (a `squashing` prompt state + a `done` commit\n# state) still exists as an ENGINE capability (see STATES.md §8) and is kept\n# as part of the fuller machine at docs/examples/advanced-workflow.md.\n#\n# A `gtd(<actor>): idle` commit — entering the workflow's own initial state —\n# is therefore a PROCESS BOUNDARY (see `computeProcessRun` in src/Edge.ts):\n# the next cycle's `retry` counts, `startCommit`, and diffs never reach back\n# across an approved cycle's own idle-entering commit.\n#\n# HYGIENE INVARIANT (asserted in e2e — see default-workflow.feature): an\n# approved cycle leaves `.gtd/` empty. FEEDBACK.md is cleaned up by a green\n# `checking` run; REVIEW.md by the review-deciding approval branch; TODO.md by\n# `building`.\n#\n# Steering-file validation. `grilling` and `reviewing` each declare a\n# `file:`/`mode:` pair (TODO.md as `qa`, REVIEW.md as `review`), so their\n# output has a checkable format. src/OpenQuestions.ts and src/ReviewDoc.ts are\n# those two formats' EXECUTABLE SPECS (their unit tests are the format spec\n# tests), and `gtd validate` FORMATS the resolved state's rendered `file:` in\n# place then runs the SAME parser over it, exiting non-zero with findings when\n# it violates the format. There is no in-machine validation state and no bash\n# port to keep in sync — the producing agent self-validates before finishing\n# (plain `gtd next` appends the \"run `gtd validate` and fix all violations\"\n# instruction; under `--json` the driving loop runs it after the turn and\n# re-prompts on findings — see skills/loop/SKILL.md), AND `gtd step` runs the\n# same format-and-validate gate on capture, refusing a turn whose steering file\n# is invalid. So the check runs after a human edits too — at the human gates\n# `grilling-answer` (TODO.md) and `await-review` (REVIEW.md) — and a human gate\n# is only ever handed a tidy, well-formed file. The same parsers back the LSP's\n# live diagnostics (src/Lsp.ts).\n#\n# `grilling` and `reviewing` both declare `model: smart` — an opaque harness\n# hint (see the comment at `grilling` below) for their heavier one-shot\n# planning/reviewing turns. Every other state is unset (harness default).\n#\n# The four agent states each declare a `memory:` scope label (`plan`,\n# `build`, `fix`, `review` — see the comment at `grilling` below) — another\n# opaque hint a memory-aware driver reads to decide when an agent turn keeps\n# the previous turn's memory and when it starts fresh: a loop that re-enters\n# one state (grilling around its answer loop, fixing around checking) keeps\n# the same label and retains memory across its laps; crossing to the next\n# phase's differently-labelled state clears it. gtd never interprets the\n# label (see STATES.md §1 and skills/loop/SKILL.md's driver contract).\n#\n# `vars.testCommand` is this workflow's own declared default for `checking`'s\n# script (see it.vars in PatternTemplates.ts) — override it per-repo with a\n# top-level `.gtdrc` `vars: { testCommand: ... }` key, or per-invocation with\n# a `GTD_VAR_testCommand` environment variable (highest precedence).\n#\n# `vars.todoFile`/`reviewFile`/`feedbackFile` are this workflow's ONE source\n# of truth for the three steering-file paths every prompt/script below reads\n# or writes — each appears in templates as `<%~ it.vars.todoFile %>` etc\n# (see docs/design/state-file-association.md §2). Every state that rests on\n# one of these files also declares a `file:`/`mode:` pair (see STATES.md's\n# property table) so `gtd status`/`gtd next --json` and the LSP (`gtd lsp`)\n# know which file a human/editor should look at, and in what format\n# (`qa` for TODO.md's open-questions format, `review` for REVIEW.md's\n# checkbox format) — `fixing`/`escalate` declare `file:` alone (FEEDBACK.md\n# is plain text, no LSP format). KNOWN LIMITATION: `on` pattern keys below are\n# NOT Eta templates — they keep the LITERAL `.gtd/...` paths matching these\n# vars' DEFAULT values. Repointing `todoFile`/`reviewFile`/`feedbackFile` via\n# `.gtdrc`'s top-level `vars:` or a `GTD_VAR_` override changes what `file:`\n# renders to (and what a template reads/writes) WITHOUT changing what the\n# `on` patterns match against — desyncing the machine. See\n# docs/configuration.md's `file:`/`mode:` section for the full caveat.\n#\n# A fuller machine — two-phase Q&A planning, an architecture phase, task\n# decomposition, a deterministic per-task builder loop, agent-prepared\n# review, and the squash finale (`squashing` + `done`) — is preserved as a\n# copy-paste `.gtdrc` example at docs/examples/advanced-workflow.md.\n\nvars:\n testCommand: npm test\n todoFile: .gtd/TODO.md\n reviewFile: .gtd/REVIEW.md\n feedbackFile: .gtd/FEEDBACK.md\n\nstates:\n idle:\n actor: human\n initial: true\n # Every human-gate `message:` below closes with the SAME rendered block —\n # a \"What each change does next\" list built from `it.edges`, the resting\n # state's own `on` edges (see PatternTemplates.TemplateContext.edges). Each\n # edge's human-readable route lives in its `describe:` (the single source\n # of truth), so the list can never drift from the routing it documents.\n # The block skips edges without a `describe`, and each `<%~ ... \"\\n\" %>`\n # keeps the bullet's own newline (Eta's autoTrim strips the template's own\n # line breaks around `<% %>` tags, not text inside an interpolation).\n message: |\n No active gtd cycle.\n\n To start one, write `.gtd/TODO.md` with a short sketch of what you want\n built — a few sentences is enough.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: grilling\n describe: >-\n Save your sketch to `.gtd/TODO.md` (any working-tree change) to start\n the cycle — the agent reads it, explores the codebase, and develops it\n into a concrete implementation plan (**grilling**).\n\n grilling:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # `model` is an opaque harness hint — gtd never interprets this string, it\n # only passes it through to `gtd next --json`/`gtd status --json` so the\n # driving loop can map it onto whatever models its agent harness\n # provides. \"smart\" here just names the harness-chosen tier for the\n # heavier planning turn; states without a `model` use the harness's\n # default.\n model: smart\n # `memory` is an opaque memory-scope label — gtd never interprets it, it\n # only passes it through to `gtd next --json`/`gtd status --json` so a\n # memory-aware driving loop can decide when an agent turn continues from\n # the previous turn's memory and when it starts fresh: consecutive agent\n # turns that emit the SAME label share memory, a change (or the first\n # turn) is where the driver starts fresh. `grilling` re-enters itself\n # around the grilling-answer loop, so labelling every lap\n # `plan` keeps the planner's accumulated exploration across the loop; the\n # next phase (`building`) carries a different label, clearing it.\n memory: plan\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.todoFile %>`, which this prompt tells you to develop.\n\n `<%= it.vars.todoFile %>` holds a short sketch of what to build (or\n feedback from a prior review lap). Read it, explore the codebase, and\n develop it into a concrete implementation plan.\n\n For every question you cannot settle yourself, add it under a\n `## Open Questions` heading, one `### <question>` sub-heading each,\n whose body's FIRST non-blank line is exactly\n `Suggested default: <your answer>` — the human can accept it as-is or\n override it. Omit the section entirely once there are no open\n questions. If `<%= it.vars.todoFile %>` already carries\n `## Open Questions` entries from a previous lap, fold any\n `Answer: <text>` line into the plan; every remaining entry's body must\n still start with either `Suggested default: ...` or `Answer: ...` —\n never anything else.\n\n Leave `<%= it.vars.todoFile %>` uncommitted and finish your turn — do\n not commit, and do not run `gtd step agent` yourself; the harness does\n that.\n on:\n \"* **\": grilling-answer\n\n grilling-answer:\n actor: human\n file: <%= it.vars.todoFile %>\n mode: qa\n message: |\n `<%= it.vars.todoFile %>` holds the plan under development, with any\n open questions under `## Open Questions` — each carrying a suggested\n default. Answer a question by editing its entry in place: replace its\n `Suggested default: ...` line with `Answer: ...`, or add further detail.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"C\":\n to: building\n describe: >-\n Change nothing to accept every suggested default as-is and move on to\n implementation (**building**).\n \"* **\":\n to: grilling\n describe: >-\n Edit the plan — answer a question, add detail, or raise a new one — to\n send it back for another round of grilling (**grilling**).\n\n building:\n actor: agent\n file: <%= it.vars.todoFile %>\n mode: qa\n # A distinct memory scope from `plan`: implementation starts fresh, with\n # the plan already settled in `.gtd/TODO.md` (which this prompt reads\n # below) rather than carried in the planner's working memory.\n memory: build\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create or edit anything under `.gtd/` except deleting\n `<%= it.vars.todoFile %>`, which this prompt tells you to delete once\n its work is complete.\n\n The plan to implement is: <%~ it.read(it.vars.todoFile) %>\n\n Read that plan and implement it in full. Use TDD discipline: one test,\n then the implementation that passes it, then the next — never write\n all the tests first.\n\n Delete `<%= it.vars.todoFile %>` once the work it describes is complete\n and verified. Leave everything else uncommitted and finish your turn.\n on:\n \"* **\": checking\n\n checking:\n actor: check\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: run the test suite and record a\n # red run's output as .gtd/FEEDBACK.md. What that output MEANS (another\n # fix round vs escalation) is decided by the workflow's own `on`/`retry`\n # rules at capture time — never here.\n #\n # `it.vars.testCommand` defaults to \"npm test\" (this workflow's own\n # `vars:` above) — override it with a top-level `.gtdrc`\n # `vars: { testCommand: ... }` key, or a `GTD_VAR_testCommand`\n # environment variable (highest precedence).\n #\n # A green run also removes any `<%= it.vars.feedbackFile %>` left over\n # from an earlier red run — there is no squash to discard it for us\n # anymore, so the script cleans it up itself before moving on to\n # review.\n set +e\n mkdir -p .gtd\n <%~ it.vars.testCommand %> > .gtd/.check-output 2>&1\n code=$?\n if [ \"$code\" -ne 0 ]; then\n if [ -s .gtd/.check-output ]; then\n mv .gtd/.check-output <%~ it.vars.feedbackFile %>\n else\n rm -f .gtd/.check-output\n printf 'npm test failed with exit code %s and produced no output.' \"$code\" > <%~ it.vars.feedbackFile %>\n fi\n else\n rm -f .gtd/.check-output\n rm -f <%~ it.vars.feedbackFile %>\n fi\n on:\n \"A .gtd/FEEDBACK.md\": fixing\n \"M .gtd/FEEDBACK.md\": fixing\n \"D .gtd/FEEDBACK.md\": reviewing\n \"C\": reviewing\n\n fixing:\n actor: agent\n file: <%= it.vars.feedbackFile %>\n # Its own memory scope: the fix loop re-enters `fixing` around `checking`\n # (up to the retry cap), so labelling every attempt `fix` lets the agent\n # remember what it already tried across the loop; a green check moves on\n # to the differently-labelled `reviewing`, clearing it.\n memory: fix\n retry:\n max: 3\n otherwise: escalate\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.feedbackFile %>`, which this prompt tells you to address.\n\n Read `<%= it.vars.feedbackFile %>` (the failing test output) and fix\n the code so the suite passes. Keep the change focused — do not\n refactor unrelated code. If the feedback is wrong, empty or delete\n `<%= it.vars.feedbackFile %>` instead of \"fixing\" a non-issue; the\n machine picks the dispute up either way.\n\n Leave everything uncommitted and finish your turn — do not commit.\n on:\n \"* **\": checking\n\n escalate:\n actor: human\n file: <%= it.vars.feedbackFile %>\n message: |\n The agent could not get the check to pass after repeated attempts.\n `<%= it.vars.feedbackFile %>` holds the last failing output.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"* **\":\n to: checking\n describe: >-\n Fix the failure yourself — edit the code and/or `.gtd/FEEDBACK.md` —\n to re-run the check (**checking**).\n\n reviewing:\n actor: agent\n file: <%= it.vars.reviewFile %>\n mode: review\n model: smart\n # A distinct memory scope again: the reviewer looks at the cycle's full\n # diff (inlined into its prompt) with a fresh perspective, not the\n # builder's or fixer's working memory.\n memory: review\n # `gtd review <commitish>` (a plain non-gtd branch, e.g. a colleague's PR)\n # enters here directly, recording the resolved base as a `Gtd-Review-Base:`\n # trailer on its empty entry commit — everything below then reuses the\n # existing reviewing/await-review/feedback-lap machinery unmodified over\n # <commitish>..HEAD (see STATES.md §11).\n reviewEntry: true\n prompt: |\n You are an autonomous coding agent. `.gtd/` holds this workflow's own\n state — never create, edit, or delete anything under `.gtd/` except\n `<%= it.vars.reviewFile %>`, which this prompt tells you to write.\n\n Write `<%= it.vars.reviewFile %>` to help a human review the cycle's\n full diff (inlined below) in this EXACT format:\n\n - First non-blank line: `# Review: <%= it.currentCommit.slice(0, 7) %>`\n - Somewhere in the document: `<!-- base: <%= it.startCommit %> -->`\n - At least one `## <Chunk Title>` heading, grouping hunks semantically\n (same feature/refactor/fix, even across files) — a short explanation\n of what changed and why, then one\n `- [ ] ./path/to/file.ts#42 — note` file pointer per hunk (checkboxes\n are for the human to tick, not you; every path is `./`-relative, with\n an optional `#line` and an optional ` — note`).\n\n Leave `<%= it.vars.reviewFile %>` uncommitted and finish your turn.\n <% if (it.processDiff.trim()) { %>\n\n ## Full cycle diff\n\n ```diff\n <%~ it.processDiff %>\n ```\n <% } %>\n on:\n \"* **\": await-review\n\n await-review:\n actor: human\n file: <%= it.vars.reviewFile %>\n mode: review\n # While the cycle rests here for human review, gtd opens a \"review checkout\n # window\": HEAD and the index are temporarily rewound to this cycle's start\n # (the process boundary — no `reviewBase` state is declared, so the base\n # defaults to it) with the working tree untouched, so the whole cycle diff\n # surfaces as ordinary uncommitted changes in the editor's git integration.\n # The window closes automatically on the next invocation, once the cycle\n # rests anywhere else (see src/ReviewWindow.ts, STATES.md §11).\n reviewWindow: true\n message: |\n `<%= it.vars.reviewFile %>` holds the review record for the completed\n cycle — one `- [ ]` checkbox per reviewable item, grouped into chunks.\n\n What each change does next (then run `gtd step human`):\n <% it.edges.forEach(function (e) { if (e.describe) { %>\n <%~ \"- \" + e.describe + \"\\n\" %>\n <% } }) %>\n on:\n \"D .gtd/REVIEW.md\":\n to: idle\n describe: >-\n Delete `.gtd/REVIEW.md` outright to approve the whole cycle at once\n and rest back at the start (**idle**).\n \"M .gtd/REVIEW.md\":\n to: review-deciding\n describe: >-\n Edit `.gtd/REVIEW.md` — tick a `- [ ]` box to `- [x]` to approve that\n item, or add notes — to hand it to a deterministic check\n (**review-deciding**) that closes the cycle out when every box is\n ticked, or extracts the still-unticked items into a fresh\n `.gtd/TODO.md` and loops back through **grilling** with that feedback.\n \"* **\":\n to: grilling\n describe: >-\n Change only code, leaving `.gtd/REVIEW.md` untouched, to send that as\n feedback straight back to **grilling**.\n\n review-deciding:\n actor: check\n file: <%= it.vars.reviewFile %>\n mode: review\n script: |\n #!/usr/bin/env bash\n # gtd check turn — the loop driver executes this verbatim, then\n # steps the check actor. Mechanics only: if .gtd/REVIEW.md still has any\n # unticked \"- [ ]\" pointer, extract those pointers (with their notes)\n # into a fresh .gtd/TODO.md; either way, remove .gtd/REVIEW.md. What\n # the resulting diff MEANS (feedback lap vs. full approval) is decided\n # by this state's own `on` rules at capture time — never here. The\n # A/M .gtd/TODO.md row is declared BEFORE the D .gtd/REVIEW.md row (see\n # this workflow's `on` map below) so a feedback lap — which always also\n # deletes .gtd/REVIEW.md — is captured as feedback, not mistaken for an\n # approval.\n set +e\n mkdir -p .gtd\n if grep -qE '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %> 2>/dev/null; then\n {\n echo \"Feedback from review — address these before continuing:\"\n echo\n grep -E '^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\]' <%~ it.vars.reviewFile %>\n } > <%~ it.vars.todoFile %>\n fi\n rm -f <%~ it.vars.reviewFile %>\n on:\n \"A .gtd/TODO.md\": grilling\n \"M .gtd/TODO.md\": grilling\n \"D .gtd/REVIEW.md\": idle\n \"C\": await-review\n";
191383
+ //#endregion
191384
+ //#region src/workflows/templates.ts
191385
+ /**
191386
+ * The `$schema` URL editors resolve for `.gtdrc.json` completion/validation —
191387
+ * written as the first key of every `gtd init` config (see `renderInitConfig`).
191388
+ */
191389
+ const SCHEMA_URL = "https://raw.githubusercontent.com/pmelab/gtd/main/schema.json";
191390
+ /**
191391
+ * The bundled workflow templates `gtd init <name>` can scaffold, keyed by the
191392
+ * name the user passes. Each value is the raw YAML text of the template file,
191393
+ * imported as a string (tsdown's `.yaml` text loader / the vitest `rawMd`
191394
+ * transform — see tsdown.config.ts / tests/vitest.rawMd.ts), so this module
191395
+ * never touches the filesystem: it works identically in the dev checkout,
191396
+ * under `vitest`, and inside the single-file `dist/gtd.bundle.mjs` build.
191397
+ */
191398
+ const WORKFLOW_TEMPLATES = {
191399
+ simple: simple_default,
191400
+ advanced: advanced_default
191401
+ };
191402
+ /** The template names as a plain array, for usage messages and validation. */
191403
+ const WORKFLOW_TEMPLATE_NAMES = Object.keys(WORKFLOW_TEMPLATES);
191404
+ const isWorkflowTemplateName = (name) => Object.prototype.hasOwnProperty.call(WORKFLOW_TEMPLATES, name);
191405
+ /**
191406
+ * Render the `.gtdrc.json` `gtd init <name>` writes: a `$schema` link (so
191407
+ * editors pick up completion/validation) plus the template's whole workflow
191408
+ * object nested under a `workflow:` key — exactly the shape a hand-authored
191409
+ * `.gtdrc` `workflow:` value takes (`{ vars, states }`). The template's
191410
+ * multi-line prompts/scripts become `\n`-escaped JSON strings; the config
191411
+ * loader parses them back identically to the YAML source.
191412
+ */
191413
+ const renderInitConfig = (name) => {
191414
+ const workflow = (0, import_dist$1.parse)(WORKFLOW_TEMPLATES[name]);
191415
+ return JSON.stringify({
191416
+ $schema: SCHEMA_URL,
191417
+ workflow
191418
+ }, null, 2) + "\n";
191419
+ };
191420
+ //#endregion
191442
191421
  //#region node_modules/eta/dist/index.mjs
191443
191422
  var EtaError = class extends Error {
191444
191423
  constructor(message) {
@@ -192023,7 +192002,7 @@ const normalizeStatus = (raw) => raw === "A" ? "A" : raw === "D" ? "D" : "M";
192023
192002
  /** Resolve HEAD's subject against the active workflow definition (the bundled default, or a compiled `.gtdrc` `workflow:` key). */
192024
192003
  const resolveRest = () => gen(function* () {
192025
192004
  const git = yield* GitService;
192026
- const def = (yield* ConfigService).workflow;
192005
+ const def = (yield* (yield* ConfigService).load).workflow;
192027
192006
  const state = resolveState(def, (yield* git.hasCommits()) ? yield* git.lastCommitSubject() : "");
192028
192007
  const stateDef = def.states[state];
192029
192008
  if (stateDef.actor === void 0) return yield* fail$2(/* @__PURE__ */ new Error(`gtd: resolved at commit state "${state}" — a process never rests there`));
@@ -192360,7 +192339,7 @@ const closeReviewWindow = gen(function* () {
192360
192339
  */
192361
192340
  const openReviewWindow = gen(function* () {
192362
192341
  const git = yield* GitService;
192363
- const def = (yield* ConfigService).workflow;
192342
+ const def = (yield* (yield* ConfigService).load).workflow;
192364
192343
  if (!(yield* git.hasCommits())) return { opened: false };
192365
192344
  if (!isReviewWindowState(def, resolveState(def, yield* git.lastCommitSubject()))) return { opened: false };
192366
192345
  const run = yield* computeProcessRun(git, def);
@@ -203901,7 +203880,7 @@ const worktreeLayerForRoot = (root) => WorktreeReader.Live.pipe(provide(Cwd.laye
203901
203880
  */
203902
203881
  const loadModeMap = async (root, onWarn) => {
203903
203882
  try {
203904
- const config = await runPromise(ConfigService.pipe(provide$1(configLayerForRoot(root))));
203883
+ const config = await runPromise(ConfigService.pipe(flatMap$4((c) => c.load), provide$1(configLayerForRoot(root))));
203905
203884
  const vars = resolveVars(config.workflowVars, config.rcVars, process.env);
203906
203885
  const { map, warnings } = buildFileModeMap(config.workflow, vars, root);
203907
203886
  for (const warning of warnings) onWarn(warning);
@@ -203920,7 +203899,7 @@ const loadModeMap = async (root, onWarn) => {
203920
203899
  */
203921
203900
  const resolveSteeringFile = (root) => gen(function* () {
203922
203901
  const git = yield* GitService;
203923
- const config = yield* ConfigService;
203902
+ const config = yield* (yield* ConfigService).load;
203924
203903
  const worktree = yield* WorktreeReader;
203925
203904
  const envVars = yield* EnvVars;
203926
203905
  const rest = yield* resolveRest();
@@ -204194,6 +204173,10 @@ const GTD_VERSION = createRequire(import.meta.url)("../package.json").version;
204194
204173
  const HELP_TEXT = `Usage: gtd [command] [options]
204195
204174
 
204196
204175
  Commands:
204176
+ init <workflow> Scaffold a .gtdrc.json for this repo with the chosen
204177
+ bundled workflow inline (one of: simple, advanced). Run
204178
+ once per repo; refuses if a gtd config already exists.
204179
+ Leaves the file uncommitted for you to review and commit
204197
204180
  step <actor> Authenticate as <actor>, match the resolved rest's
204198
204181
  declared patterns against the pending changes, and commit
204199
204182
  (or squash) the one resulting transition. Pass
@@ -204215,6 +204198,8 @@ Commands:
204215
204198
  mermaid Print the active workflow's shape as Mermaid
204216
204199
  stateDiagram-v2 source (no mutation)
204217
204200
  lsp Start the LSP server for .gtd/ steering files (stdio)
204201
+ version Print version and exit
204202
+ help Print this help and exit
204218
204203
 
204219
204204
  Options:
204220
204205
  --json Output structured JSON instead of plain text
@@ -204296,16 +204281,47 @@ const rejectExtraArgs = (command, argv) => {
204296
204281
  /**
204297
204282
  * `gtd lsp`: start the LSP server for `.gtd/` steering files over stdio.
204298
204283
  * Rejects `--json` (not a state command) and extra positional arguments
204299
- * (takes none). Dispatched BEFORE the known-subcommand guard, the repo-root
204300
- * guard, and auto-init — since the server needs no
204301
- * git/config/workflow dependency at all (it's keyed on file name, not
204302
- * workflow state; see `src/Lsp.ts`'s module doc).
204284
+ * (takes none). Dispatched BEFORE the known-subcommand guard and the repo-root
204285
+ * guard — since the server needs no git/config/workflow dependency at all
204286
+ * (it's keyed on file name, not workflow state; see `src/Lsp.ts`'s module doc).
204303
204287
  */
204304
204288
  const runLspCommand = (argv, json) => gen(function* () {
204305
204289
  if (json) return yield* fail$2(/* @__PURE__ */ new Error("gtd lsp does not accept --json"));
204306
204290
  yield* rejectExtraArgs("lsp", argv);
204307
204291
  yield* startLspServer();
204308
204292
  });
204293
+ /** The `choose one of: ...` suffix shared by every `gtd init` usage error. */
204294
+ const initWorkflowChoices = () => `choose one of: ${WORKFLOW_TEMPLATE_NAMES.join(", ")}`;
204295
+ /**
204296
+ * `gtd init <workflow>`: scaffold a `.gtdrc.json` carrying one of the bundled
204297
+ * workflow templates inline (`simple`/`advanced`). Dispatched like `lsp` —
204298
+ * BEFORE the closeReviewWindow/dispatch/openReviewWindow block — because it is
204299
+ * the ONE command that must run with no workflow configured yet: it needs no
204300
+ * `ConfigService` (which would throw the "no workflow" error pre-init) and no
204301
+ * review window. It still runs the repo-root guard (it writes `.gtdrc.json` at
204302
+ * the root) and refuses to clobber an existing config. The file is left
204303
+ * UNCOMMITTED, so the message warns to commit it before the first `gtd step`
204304
+ * (an uncommitted config is a pending change the initial state's `* **` edge
204305
+ * would otherwise capture).
204306
+ */
204307
+ const runInitCommand = (argv, json, write) => gen(function* () {
204308
+ const args = commandArgs(argv);
204309
+ if (args.length === 0) return yield* fail$2(/* @__PURE__ */ new Error(`gtd init: missing workflow — ${initWorkflowChoices()}`));
204310
+ if (args.length > 1) return yield* fail$2(/* @__PURE__ */ new Error(`gtd init: too many arguments — expected one workflow, got: ${args.join(", ")}`));
204311
+ const name = args[0];
204312
+ if (!isWorkflowTemplateName(name)) return yield* fail$2(/* @__PURE__ */ new Error(`gtd init: unknown workflow '${name}' — ${initWorkflowChoices()}`));
204313
+ const git = yield* GitService;
204314
+ const fs = yield* FileSystem;
204315
+ yield* assertRunningFromRepoRoot(git, fs);
204316
+ const { root } = yield* Cwd;
204317
+ if (yield* anyConfigPresent(root)) return yield* fail$2(/* @__PURE__ */ new Error("gtd init: a gtd config already exists — remove it before re-initializing"));
204318
+ yield* fs.writeFileString(join(root, ".gtdrc.json"), renderInitConfig(name)).pipe(mapError$1((e) => e instanceof Error ? e : new Error(String(e))));
204319
+ if (json) write(JSON.stringify({
204320
+ written: ".gtdrc.json",
204321
+ workflow: name
204322
+ }) + "\n");
204323
+ else write(`Wrote .gtdrc.json with the "${name}" workflow.\n\nReview and commit it before starting: an uncommitted .gtdrc.json counts as a\npending change, so the initial state would capture it on the first step. Once\ncommitted, run \`gtd step human\` to begin.\n`);
204324
+ });
204309
204325
  /**
204310
204326
  * Resolve HEAD's rest, the current process run, and the template context for
204311
204327
  * rendering that rest's OWN state/actor — the common prefix shared by `gtd
@@ -204315,7 +204331,7 @@ const runLspCommand = (argv, json) => gen(function* () {
204315
204331
  * instead of sharing this helper).
204316
204332
  */
204317
204333
  const resolveRestContext = (git) => gen(function* () {
204318
- const config = yield* ConfigService;
204334
+ const config = yield* (yield* ConfigService).load;
204319
204335
  const worktree = yield* WorktreeReader;
204320
204336
  const envVars = yield* EnvVars;
204321
204337
  const rest = yield* resolveRest();
@@ -204338,7 +204354,7 @@ const formatStepRefusal = (invoker, refusal) => refusal.reason === "out-of-turn"
204338
204354
  */
204339
204355
  const stepAsActor = (invoker, cost, model) => gen(function* () {
204340
204356
  const git = yield* GitService;
204341
- const config = yield* ConfigService;
204357
+ const config = yield* (yield* ConfigService).load;
204342
204358
  const worktree = yield* WorktreeReader;
204343
204359
  const envVars = yield* EnvVars;
204344
204360
  const rest = yield* resolveRest();
@@ -204639,7 +204655,7 @@ const runStatusCommand = (argv, json, write) => gen(function* () {
204639
204655
  const runMermaidCommand = (argv, json, write) => gen(function* () {
204640
204656
  if (json) return yield* fail$2(/* @__PURE__ */ new Error("gtd mermaid does not accept --json"));
204641
204657
  yield* rejectExtraArgs("mermaid", argv);
204642
- write(renderMermaid((yield* ConfigService).workflow));
204658
+ write(renderMermaid((yield* (yield* ConfigService).load).workflow));
204643
204659
  });
204644
204660
  const KNOWN_SUBCOMMANDS = [
204645
204661
  "step",
@@ -204650,17 +204666,19 @@ const KNOWN_SUBCOMMANDS = [
204650
204666
  "mermaid"
204651
204667
  ];
204652
204668
  /**
204653
- * `--version`/`-v` or `--help`/`-h`: short-circuits before any git or state
204654
- * work, so it works outside a repo too. Exported so main.ts can run the same
204655
- * check synchronously BEFORE the Effect runtime builds any layer — layer
204656
- * construction must never observe a version/help invocation.
204669
+ * `--version`/`-v`/`version` or `--help`/`-h`/`help`: short-circuits before any
204670
+ * git or state work, so it works outside a repo too. The bare `version`/`help`
204671
+ * subcommands are equivalent to their flag forms. Exported so main.ts can run
204672
+ * the same check synchronously BEFORE the Effect runtime builds any layer —
204673
+ * layer construction must never observe a version/help invocation.
204657
204674
  */
204658
204675
  const runVersionOrHelp = (argv, write) => {
204659
- if (argv.includes("--version") || argv.includes("-v")) {
204676
+ const positional = argv.slice(2).find((a) => !a.startsWith("--"));
204677
+ if (argv.includes("--version") || argv.includes("-v") || positional === "version") {
204660
204678
  write(GTD_VERSION + "\n");
204661
204679
  return true;
204662
204680
  }
204663
- if (argv.includes("--help") || argv.includes("-h")) {
204681
+ if (argv.includes("--help") || argv.includes("-h") || positional === "help") {
204664
204682
  write(HELP_TEXT);
204665
204683
  return true;
204666
204684
  }
@@ -204705,15 +204723,17 @@ const dispatchKnownSubcommand = (sub, argv, json, write, cost, model) => {
204705
204723
  * Factory that returns the gtd driver Effect with the given I/O options.
204706
204724
  *
204707
204725
  * The returned Effect requires `GitService | FileSystem.FileSystem |
204708
- * ConfigService | ConfigInit | Cwd | WorktreeReader`. Production code calls
204726
+ * ConfigService | Cwd | WorktreeReader | EnvVars`. Production code calls
204709
204727
  * this with no arguments; the test world supplies an in-memory layer set and
204710
204728
  * captures stdout via the `write` callback.
204711
204729
  *
204712
- * v3 command surface: `step <actor>` / `next` / `run` / `status` /
204713
- * `validate` / `mermaid` (see `src/Edge.ts` and
204714
- * `docs/design/pattern-machine-plan.md` §3), plus `lsp`. Bare `gtd` or an
204715
- * unknown subcommand is a usage error. Shared setup (argv parsing, the repo-root guard) lives here;
204716
- * each subcommand's own logic is a named `run*Command` function above.
204730
+ * v3 command surface: `step <actor>` / `next` / `status` / `validate` /
204731
+ * `mermaid` (see `src/Edge.ts` and `docs/design/pattern-machine-plan.md` §3),
204732
+ * plus `lsp` and `init <workflow>` — both dispatched before the config-reading
204733
+ * path since they must work with no workflow configured yet. Bare `gtd` or an
204734
+ * unknown subcommand is a usage error. Shared setup (argv parsing, the
204735
+ * repo-root guard) lives here; each subcommand's own logic is a named
204736
+ * `run*Command` function above.
204717
204737
  */
204718
204738
  function makeProgram(opts = {}) {
204719
204739
  const argv = opts.argv ?? process.argv;
@@ -204726,12 +204746,12 @@ function makeProgram(opts = {}) {
204726
204746
  if (unknownOption !== void 0) return yield* fail$2(/* @__PURE__ */ new Error(`gtd: unknown option '${unknownOption}' — see \`gtd --help\``));
204727
204747
  const { cost, model } = yield* parseStepFlags(argv, positional);
204728
204748
  if (positional === "lsp") return yield* runLspCommand(argv, json);
204749
+ if (positional === "init") return yield* runInitCommand(argv, json, write);
204729
204750
  const sub = yield* requireKnownSubcommand(positional, json, write);
204730
204751
  const git = yield* GitService;
204731
204752
  const fs = yield* FileSystem;
204732
204753
  yield* assertRunningFromRepoRoot(git, fs);
204733
204754
  yield* closeReviewWindow;
204734
- yield* (yield* ConfigInit).ensure;
204735
204755
  const outcome = yield* either(dispatchKnownSubcommand(sub, argv, json, write, cost, model));
204736
204756
  const rearm = yield* either(openReviewWindow);
204737
204757
  if (isLeft(outcome)) return yield* fail$2(outcome.left);
@@ -204744,7 +204764,7 @@ function makeProgram(opts = {}) {
204744
204764
  //#endregion
204745
204765
  //#region src/main.ts
204746
204766
  if (runVersionOrHelp(process.argv, (chunk) => process.stdout.write(chunk))) process.exit(0);
204747
- makeProgram().pipe(provide$1(GitService.Live), provide$1(ConfigService.Live), provide$1(ConfigInit.Live), provide$1(WorktreeReader.Live), provide$1(EnvVars.Live), provide$1(Cwd.Live), provide$1(layer), catchAll((error) => sync$1(() => {
204767
+ makeProgram().pipe(provide$1(GitService.Live), provide$1(ConfigService.Live), provide$1(WorktreeReader.Live), provide$1(EnvVars.Live), provide$1(Cwd.Live), provide$1(layer), catchAll((error) => sync$1(() => {
204748
204768
  if (process.argv.includes("--json") && !isEnveloped(error)) process.stdout.write(JSON.stringify({
204749
204769
  state: "error",
204750
204770
  prompt: error.message