@pmelab/gtd 24.0.0 → 24.2.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.
Files changed (203) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +42 -13
  3. package/claude/hooks/access.ts +26 -1
  4. package/claude/hooks/assist.ts +135 -0
  5. package/claude/hooks/drive.ts +15 -7
  6. package/claude/hooks/judge.ts +27 -0
  7. package/claude/hooks/register.tsx +294 -135
  8. package/claude/hooks/tools.ts +121 -0
  9. package/claude/hooks/wording.ts +2 -35
  10. package/claude/types/index.d.ts +9 -0
  11. package/dist/chunks/Schema-Dh-mkwkq.mjs +25353 -0
  12. package/dist/chunks/reserved-ejn-LVYO.mjs +1388 -0
  13. package/dist/chunks/rolldown-runtime-8H4AJuhK.mjs +14 -0
  14. package/dist/chunks/steering-D-PvRC5W.mjs +16296 -0
  15. package/dist/chunks/wire-DA7q2ikx.mjs +473 -0
  16. package/dist/flows.mjs +525 -0
  17. package/dist/gtd.bundle.mjs +43339 -55575
  18. package/dist/steering.mjs +2 -0
  19. package/dist/testkit.mjs +13006 -0
  20. package/dist/wire.mjs +2 -0
  21. package/dist/workflow-kit.mjs +352 -0
  22. package/dist/workflows/feature.mjs +315 -0
  23. package/dist/workflows/fix.mjs +40 -0
  24. package/dist/workflows/review.mjs +25 -0
  25. package/dist/workflows.mjs +8 -6
  26. package/package.json +69 -8
  27. package/src/cli/Cli.test.ts +1329 -0
  28. package/src/cli/Cli.ts +1348 -0
  29. package/src/cli/Program.test.ts +2262 -0
  30. package/src/cli/Program.ts +1331 -0
  31. package/src/cli/ToolCommands.ts +43 -0
  32. package/src/cli/index.ts +14 -0
  33. package/src/edge/Edge.test.ts +1016 -0
  34. package/src/edge/Edge.ts +1225 -0
  35. package/src/edge/index.ts +16 -0
  36. package/src/emit/Emit.test.ts +425 -0
  37. package/src/emit/Emit.ts +139 -0
  38. package/src/emit/GitScript.test.ts +260 -0
  39. package/src/emit/GitScript.ts +131 -0
  40. package/src/emit/ModeContradiction.test.ts +120 -0
  41. package/src/emit/ModeContradiction.ts +66 -0
  42. package/src/emit/OutcomeScript.test.ts +238 -0
  43. package/src/emit/OutcomeScript.ts +73 -0
  44. package/src/emit/SteeringMode.test.ts +274 -0
  45. package/src/emit/SteeringMode.ts +256 -0
  46. package/src/emit/index.ts +40 -0
  47. package/src/install/ConfigScaffold.ts +19 -0
  48. package/src/install/Install.test.ts +426 -0
  49. package/src/install/Install.ts +634 -0
  50. package/src/install/Version.ts +27 -0
  51. package/src/install/index.ts +3 -0
  52. package/src/platform/CommandRunner.ts +74 -0
  53. package/src/platform/Commentary.test.ts +126 -0
  54. package/src/platform/Commentary.ts +92 -0
  55. package/src/platform/Git.test.ts +50 -0
  56. package/src/platform/Git.ts +552 -0
  57. package/src/platform/Host.ts +42 -0
  58. package/src/platform/RetainedHistory.test.ts +65 -0
  59. package/src/platform/RetainedHistory.ts +34 -0
  60. package/src/platform/Workspace.test.ts +669 -0
  61. package/src/platform/Workspace.ts +631 -0
  62. package/src/platform/WorktreeState.test.ts +162 -0
  63. package/src/platform/WorktreeState.ts +50 -0
  64. package/src/platform/index.ts +22 -0
  65. package/src/replay/Access.test.ts +53 -0
  66. package/src/replay/Access.ts +46 -0
  67. package/src/replay/Format.test.ts +20 -0
  68. package/src/replay/Format.ts +14 -0
  69. package/src/replay/Replay.test.ts +887 -0
  70. package/src/replay/Replay.ts +669 -0
  71. package/src/replay/Trailers.test.ts +117 -0
  72. package/src/replay/Trailers.ts +213 -0
  73. package/src/replay/Tree.test.ts +25 -0
  74. package/src/replay/Tree.ts +45 -0
  75. package/src/replay/index.ts +11 -0
  76. package/src/steering/Blocks.fixture.ts +6 -0
  77. package/src/steering/Blocks.test.ts +167 -0
  78. package/src/steering/Blocks.ts +321 -0
  79. package/src/steering/CodeThreads.test.ts +127 -0
  80. package/src/steering/CodeThreads.ts +197 -0
  81. package/src/steering/Edits.test.ts +19 -0
  82. package/src/steering/Edits.ts +20 -0
  83. package/src/steering/Eol.test.ts +16 -0
  84. package/src/steering/Eol.ts +2 -0
  85. package/src/steering/FORMATS.md +58 -0
  86. package/src/steering/Footnotes.test.ts +977 -0
  87. package/src/steering/Footnotes.ts +661 -0
  88. package/src/steering/Inline.fixture.ts +7 -0
  89. package/src/steering/Inline.test.ts +227 -0
  90. package/src/steering/Inline.ts +195 -0
  91. package/src/steering/MarkdownTree.test.ts +247 -0
  92. package/src/steering/MarkdownTree.ts +260 -0
  93. package/src/steering/Outline.ts +19 -0
  94. package/src/steering/SteeringFormat.test.ts +91 -0
  95. package/src/steering/SteeringFormat.ts +267 -0
  96. package/src/steering/SteeringFormats.test.ts +163 -0
  97. package/src/steering/Threads.ts +163 -0
  98. package/src/steering/contract.test.ts +264 -0
  99. package/src/steering/fixtures/code-threads/cache.stripped.ts.txt +6 -0
  100. package/src/steering/fixtures/code-threads/cache.ts.md +15 -0
  101. package/src/steering/fixtures/free-form/notes.md +12 -0
  102. package/src/steering/fixtures/free-form/notes.read.json +42 -0
  103. package/src/steering/fixtures/qa/answered.md +23 -0
  104. package/src/steering/fixtures/qa/answered.read.json +119 -0
  105. package/src/steering/fixtures/qa/requirements.md +160 -0
  106. package/src/steering/fixtures/qa/requirements.read.json +475 -0
  107. package/src/steering/fixtures/review/review.md +76 -0
  108. package/src/steering/fixtures/review/review.read.json +237 -0
  109. package/src/steering/fixtures/review/ticked.md +23 -0
  110. package/src/steering/fixtures/review/ticked.read.json +99 -0
  111. package/src/steering/fixtures/review-notes/baseline.md +14 -0
  112. package/src/steering/fixtures/review-notes/noted.md +19 -0
  113. package/src/steering/freeform.test.ts +311 -0
  114. package/src/steering/freeform.ts +148 -0
  115. package/src/steering/index.test.ts +62 -0
  116. package/src/steering/index.ts +140 -0
  117. package/src/steering/qa.test.ts +2160 -0
  118. package/src/steering/qa.ts +1104 -0
  119. package/src/steering/review.test.ts +1829 -0
  120. package/src/steering/review.ts +1180 -0
  121. package/src/step/LandStep.ts +31 -0
  122. package/src/step/RepoSnapshot.ts +29 -0
  123. package/src/step/accessRefusal.test.ts +58 -0
  124. package/src/step/accessRefusal.ts +26 -0
  125. package/src/step/index.ts +5 -0
  126. package/src/step/planStart.test.ts +202 -0
  127. package/src/step/planStart.ts +167 -0
  128. package/src/step/planStep.test.ts +104 -0
  129. package/src/step/planStep.ts +89 -0
  130. package/src/step/snapshot.fixture.ts +28 -0
  131. package/src/testkit/EmittedScriptRecognizer.test.ts +639 -0
  132. package/src/testkit/EmittedScriptRecognizer.ts +642 -0
  133. package/src/testkit/FakeGitOperations.ts +95 -0
  134. package/src/testkit/GitTiers.test.ts +11 -0
  135. package/src/testkit/GitTiers.ts +1052 -0
  136. package/src/testkit/InMemRepo.ts +467 -0
  137. package/src/testkit/Layers.test.ts +58 -0
  138. package/src/testkit/Layers.ts +241 -0
  139. package/src/testkit/StrictGitOperations.ts +31 -0
  140. package/src/testkit/TestRepo.test.ts +119 -0
  141. package/src/testkit/TestRepo.ts +274 -0
  142. package/src/testkit/cliIo.ts +36 -0
  143. package/src/testkit/index.ts +9 -0
  144. package/src/testkit/steps.ts +177 -0
  145. package/src/testkit/testkit.feature +65 -0
  146. package/src/wire/BeatDocument.test.ts +419 -0
  147. package/src/wire/BeatDocument.ts +114 -0
  148. package/src/wire/BeatPlain.test.ts +113 -0
  149. package/src/wire/BeatPlain.ts +127 -0
  150. package/src/wire/BeatStatus.test.ts +59 -0
  151. package/src/wire/BeatStatus.ts +81 -0
  152. package/src/wire/Demand.test.ts +142 -0
  153. package/src/wire/Demand.ts +108 -0
  154. package/src/wire/ExitCodes.test.ts +21 -0
  155. package/src/wire/ExitCodes.ts +16 -0
  156. package/src/wire/Glob.ts +29 -0
  157. package/src/wire/Judge.ts +22 -0
  158. package/src/wire/Land.test.ts +120 -0
  159. package/src/wire/Land.ts +75 -0
  160. package/src/wire/Select.test.ts +148 -0
  161. package/src/wire/Select.ts +78 -0
  162. package/src/wire/Sessions.test.ts +59 -0
  163. package/src/wire/Sessions.ts +39 -0
  164. package/src/wire/WireSchema.test.ts +162 -0
  165. package/src/wire/constants.ts +22 -0
  166. package/src/wire/golden/1/beat-capture.json +34 -0
  167. package/src/wire/golden/1/beat-message.json +34 -0
  168. package/src/wire/golden/1/beat-prompt.json +44 -0
  169. package/src/wire/golden/1/beat-script.json +34 -0
  170. package/src/wire/golden/1/beat-stalled.json +34 -0
  171. package/src/wire/golden/1/judge.json +14 -0
  172. package/src/wire/golden/1/land-noop.json +10 -0
  173. package/src/wire/golden/1/land.json +10 -0
  174. package/src/wire/index.ts +12 -0
  175. package/src/wire/types.ts +46 -0
  176. package/src/workflow/Diagnostic.test.ts +93 -0
  177. package/src/workflow/Diagnostic.ts +54 -0
  178. package/src/workflow/SteeringFormats.test.ts +27 -0
  179. package/src/workflow/SteeringFormats.ts +6 -0
  180. package/src/workflow/Workflow.ts +77 -0
  181. package/src/workflow/compile.test.ts +53 -0
  182. package/src/workflow/compile.ts +56 -0
  183. package/src/workflow/discovery.ts +122 -0
  184. package/src/workflow/fingerprint.test.ts +52 -0
  185. package/src/workflow/fingerprint.ts +53 -0
  186. package/src/workflow/index.ts +33 -0
  187. package/src/workflow/load.test.ts +1017 -0
  188. package/src/workflow/load.ts +836 -0
  189. package/src/workflow/skills.test.ts +109 -0
  190. package/src/workflow/skills.ts +90 -0
  191. package/src/workflow/vars.ts +33 -0
  192. package/src/workflows/feature/feature.test.ts +27 -33
  193. package/src/workflows/feature/index.ts +10 -0
  194. package/src/workflows/fix/fix.feature +80 -0
  195. package/src/workflows/fix/fix.test.ts +58 -78
  196. package/src/workflows/fix/index.ts +6 -0
  197. package/src/workflows/index.ts +2 -10
  198. package/src/workflows/review/index.ts +6 -0
  199. package/src/workflows/review/review.test.ts +85 -29
  200. package/src/workflows/review/review.ts +3 -1
  201. package/src/workflows/shared/config.fixture.ts +12 -0
  202. package/src/workflows/shared/reserved.ts +11 -0
  203. package/src/workflows/shared/workflows.steps.ts +7 -0
@@ -0,0 +1,256 @@
1
+ import { join } from "node:path"
2
+ import { Effect } from "effect"
3
+ import { Host } from "../platform/index.js"
4
+ import {
5
+ isSeededValidateCommand,
6
+ knownModes,
7
+ type StateMode,
8
+ type WorkflowDefinition,
9
+ } from "../workflow/index.js"
10
+ import { steeringFormatFor, type SteeringFinding, type SteeringFormat } from "../steering/index.js"
11
+ import { buildModeContradictionCheck, modeContradictionSkipNotice } from "./ModeContradiction.js"
12
+ import {
13
+ binaryGuard,
14
+ emitScripts,
15
+ extractLeadingBinary,
16
+ fileExistsGuard,
17
+ withFileVar,
18
+ type EmitStep,
19
+ } from "./Emit.js"
20
+
21
+ /** How a resolved mode validates: a shell command, or a built-in format's own in-process parser. */
22
+ export type ResolvedValidator =
23
+ | { readonly kind: "command"; readonly command: string }
24
+ | { readonly kind: "builtin"; readonly format: SteeringFormat }
25
+
26
+ /**
27
+ * What a resolved mode can DO, for a consumer (the LSP, the sign-off/answer
28
+ * gates) that only cares about capability, not resolution mechanics:
29
+ * `liveValidate` is the built-in format's own `validate` function, present
30
+ * when the validator is either the built-in kind OR a command that is gtd's
31
+ * own SEEDED string for this mode (`isSeededValidateCommand` — the compiler
32
+ * seeding `qa`/`review`'s own `gtd check` command behind the scenes changes
33
+ * nothing about how the file is actually validated). `externalValidate` is
34
+ * `true` for a genuine user override of a built-in mode's `validate:`, or any
35
+ * command-validated non-built-in mode — the LSP shows a notice for that
36
+ * instead of live diagnostics.
37
+ */
38
+ export interface SteeringCapabilities {
39
+ readonly format?: SteeringFormat
40
+ readonly liveValidate?: (content: string) => readonly SteeringFinding[]
41
+ readonly externalValidate?: boolean
42
+ }
43
+
44
+ /** A `mode:` name successfully resolved against a definition (or the built-in registry alone). */
45
+ export interface ResolvedMode {
46
+ readonly kind: "resolved"
47
+ readonly mode: StateMode
48
+ /** The built-in `SteeringFormat` registered under this mode's NAME (`src/workflow/SteeringFormats.ts`), independent of who ends up validating — present even when a declared `validate:` command overrides the format's own parser. Absent when the name is not in the built-in registry at all. */
49
+ readonly format?: SteeringFormat
50
+ /** The `format:` shell command, when some `modes:` layer declared one. Absent = this mode formats nothing. */
51
+ readonly formatCommand?: string
52
+ /** How to validate, or absent when neither a command nor a built-in parser applies (a declared mode with only a `format:`). */
53
+ readonly validate?: ResolvedValidator
54
+ readonly capabilities: SteeringCapabilities
55
+ }
56
+
57
+ /** A `mode:` name that resolved to nothing — the message names what IS known. */
58
+ export interface UnknownMode {
59
+ readonly kind: "unknown"
60
+ readonly message: string
61
+ }
62
+
63
+ /** A state's `mode:` resolved against the active definition, or the reason it couldn't be. */
64
+ export type ModeResolution = ResolvedMode | UnknownMode
65
+
66
+ /**
67
+ * `format` alone (no live/external verdict) when there's no validator at
68
+ * all; a live in-process validator for a `"builtin"` validate OR a command
69
+ * that is exactly the format's own seeded string; `externalValidate` for any
70
+ * other command. Each arm returns directly — a flat sequence, not nested
71
+ * ternaries — so the four outcomes stay each their own case to read, not a
72
+ * boolean expression to re-derive.
73
+ */
74
+ const capabilitiesFor = (
75
+ mode: StateMode,
76
+ format: SteeringFormat | undefined,
77
+ validate: ResolvedValidator | undefined,
78
+ ): SteeringCapabilities => {
79
+ if (format === undefined) {
80
+ return validate?.kind === "command" ? { externalValidate: true } : {}
81
+ }
82
+ if (validate?.kind === "builtin") return { format, liveValidate: format.validate }
83
+ if (validate === undefined) return { format }
84
+ if (isSeededValidateCommand(mode, validate.command)) {
85
+ return { format, liveValidate: format.validate }
86
+ }
87
+ return { format, externalValidate: true }
88
+ }
89
+
90
+ /**
91
+ * Resolve a `mode:` name against `def.modes` plus the built-in registry
92
+ * (`src/workflow/SteeringFormats.ts`) — half by half: a declared `format:`/`validate:`
93
+ * wins, and an undeclared `validate:` falls back to the built-in format's own
94
+ * parser when the name is registered. `format` is set from the registry
95
+ * ALONE, independent of which half of `validate` wins — a declared validator
96
+ * overrides validation, not the format identity.
97
+ *
98
+ * `def: undefined` is the LSP's built-in-only fallback — resolving `mode`
99
+ * against the registry alone, with no workflow definition in hand (e.g. the
100
+ * basename dispatch for a `REVIEW.md` no config maps).
101
+ *
102
+ * The `"unknown"` arm carries the whole refusal message, naming what IS known
103
+ * when `def` is given — this is the one place that message is built, so it
104
+ * can never drift from what actually resolved.
105
+ */
106
+ export const resolveMode = (
107
+ def: Pick<WorkflowDefinition, "modes"> | undefined,
108
+ state: string,
109
+ mode: StateMode,
110
+ ): ModeResolution => {
111
+ const declared = def?.modes?.[mode]
112
+ const format = steeringFormatFor(mode)
113
+ if (declared === undefined && format === undefined) {
114
+ return {
115
+ kind: "unknown",
116
+ message:
117
+ def !== undefined
118
+ ? `state "${state}": mode "${mode}" is not defined by the active workflow (known modes: ${knownModes(def).join(", ")})`
119
+ : `mode "${mode}" is not a built-in steering format`,
120
+ }
121
+ }
122
+ const validate: ResolvedValidator | undefined =
123
+ declared?.validate !== undefined
124
+ ? { kind: "command", command: declared.validate }
125
+ : format !== undefined
126
+ ? { kind: "builtin", format }
127
+ : undefined
128
+ return {
129
+ kind: "resolved",
130
+ mode,
131
+ ...(format !== undefined ? { format } : {}),
132
+ ...(declared?.format !== undefined ? { formatCommand: declared.format } : {}),
133
+ ...(validate !== undefined ? { validate } : {}),
134
+ capabilities: capabilitiesFor(mode, format, validate),
135
+ }
136
+ }
137
+
138
+ /** `gtd next`'s fix-retry instruction, printed ahead of the failing command's captured output. */
139
+ const fixPromptInstruction = (file: string): string =>
140
+ `Your last turn does not pass its own validation script. Fix these format violations in ${file}, then finish:`
141
+
142
+ /**
143
+ * Pushes a `binaryGuard` step ahead of `command` when its own leading word
144
+ * is unambiguous — BEFORE, not wrapped around: a guard that fails must stop
145
+ * the script on its own `exit 127`, without touching `failurePromptWrapper`'s
146
+ * captured-output path. Each command guards on its OWN leading word — a
147
+ * guard naming the wrong binary is worse than none.
148
+ */
149
+ const pushGuardedCommand = (
150
+ steps: EmitStep[],
151
+ mode: StateMode,
152
+ key: "format" | "validate",
153
+ command: string,
154
+ file: string,
155
+ onFailure: string | undefined,
156
+ ): void => {
157
+ const binary = extractLeadingBinary(command)
158
+ if (binary !== undefined) {
159
+ steps.push({ kind: "command", command: binaryGuard(binary, mode, key) })
160
+ }
161
+ steps.push({
162
+ kind: "command",
163
+ command: withFileVar(command, file),
164
+ ...(onFailure !== undefined ? { onFailure } : {}),
165
+ })
166
+ }
167
+
168
+ /**
169
+ * `resolved`'s `format:`/`validate:` as `EmitStep[]` — format first,
170
+ * validate last, the last one wrapped with `onFailure` when the validator is
171
+ * a command (a built-in's own in-process parser has no shell step to wrap:
172
+ * `gtd check`'s seeded command carries that instead). Each command gets its
173
+ * own `binaryGuard` immediately ahead of it.
174
+ */
175
+ const modeCommandSteps = (resolved: ResolvedMode, file: string): readonly EmitStep[] => {
176
+ const steps: EmitStep[] = []
177
+ if (resolved.formatCommand !== undefined) {
178
+ pushGuardedCommand(steps, resolved.mode, "format", resolved.formatCommand, file, undefined)
179
+ }
180
+ if (resolved.validate?.kind === "command") {
181
+ pushGuardedCommand(
182
+ steps,
183
+ resolved.mode,
184
+ "validate",
185
+ resolved.validate.command,
186
+ file,
187
+ fixPromptInstruction(file),
188
+ )
189
+ }
190
+ return steps
191
+ }
192
+
193
+ /** `<Host.scratchDir>/gtd-mode-sample-<mode>-<pid>.md` — an absolute literal baked in at emit time, never a shell variable. `<pid>` avoids collisions between concurrent `gtd` processes. Never a `/tmp` literal or `mktemp` (`tests/tooling/no-tmp-assumption.test.ts` scans for both). */
194
+ const scratchSamplePath = (scratchDir: string, mode: StateMode): string =>
195
+ join(scratchDir, `gtd-mode-sample-${mode}-${process.pid}.md`)
196
+
197
+ /**
198
+ * The contradiction round-trip/skip-notice steps for `resolved`'s `mode:`.
199
+ * No `formatCommand` means nothing to round-trip: empty. Otherwise: a live
200
+ * built-in validator runs the round-trip against that format's own canonical
201
+ * sample; an external validator prints a one-line skip notice instead, since
202
+ * silence there would read as a clean bill of health; a format-only mode with
203
+ * neither has nothing to round-trip either.
204
+ */
205
+ const modeContradictionSteps = (
206
+ resolved: ResolvedMode,
207
+ ): Effect.Effect<readonly EmitStep[], Error, Host> =>
208
+ Effect.gen(function* () {
209
+ if (resolved.formatCommand === undefined) return []
210
+ const { capabilities } = resolved
211
+ if (capabilities.format !== undefined && capabilities.liveValidate !== undefined) {
212
+ const { scratchDir } = yield* Host
213
+ const samplePath = scratchSamplePath(scratchDir, resolved.mode)
214
+ const formatCommand = withFileVar(resolved.formatCommand, samplePath)
215
+ return [
216
+ {
217
+ kind: "command",
218
+ command: buildModeContradictionCheck({
219
+ mode: resolved.mode,
220
+ samplePath,
221
+ sample: capabilities.format.sample,
222
+ formatCommand,
223
+ }),
224
+ },
225
+ ]
226
+ }
227
+ if (capabilities.externalValidate === true) {
228
+ return [{ kind: "command", command: modeContradictionSkipNotice(resolved.mode) }]
229
+ }
230
+ return []
231
+ })
232
+
233
+ /** A resolved mode's full format-then-validate script text — a VALUE, never an execution. Carries the contradiction round-trip, the file-existence guard, and the format/validate commands, exactly as `gtd validate`/`gtd next --json`'s `validate` field emit them. */
234
+ export interface ValidateScript {
235
+ readonly script: string
236
+ }
237
+
238
+ /**
239
+ * Renders `resolved`'s complete validate script for `file`: the mode's
240
+ * format/validate contradiction check, a guard for a not-yet-written file,
241
+ * then the format/validate commands themselves (format first). gtd never
242
+ * runs this script itself — `resolveMode`+`validateScriptFor` only render
243
+ * text for a driver to execute (`gtd renders; the driver executes`).
244
+ */
245
+ export const validateScriptFor = (
246
+ resolved: ResolvedMode,
247
+ file: string,
248
+ ): Effect.Effect<ValidateScript, Error, Host> =>
249
+ Effect.gen(function* () {
250
+ const steps: EmitStep[] = [
251
+ ...(yield* modeContradictionSteps(resolved)),
252
+ { kind: "command", command: fileExistsGuard(file) },
253
+ ...modeCommandSteps(resolved, file),
254
+ ]
255
+ return { script: emitScripts(steps).required }
256
+ })
@@ -0,0 +1,40 @@
1
+ export {
2
+ type EmitStep,
3
+ fileExistsGuard,
4
+ commandForFile,
5
+ binaryGuard,
6
+ failurePromptWrapper,
7
+ emitScripts,
8
+ DID_NOT_RUN_COMMENT,
9
+ PRESENTATION_ONLY_COMMENT,
10
+ PRESENTATION_FAILURE_WARNING,
11
+ combinedScript,
12
+ } from "./Emit.js"
13
+ export {
14
+ shellQuote,
15
+ commitAll,
16
+ commitAsIs,
17
+ softResetTo,
18
+ mixedResetTo,
19
+ hardResetTo,
20
+ discardPending,
21
+ updateRef,
22
+ deleteRef,
23
+ type RunnableScript,
24
+ ScriptSurface,
25
+ } from "./GitScript.js"
26
+ export {
27
+ OUTCOME_MARKER,
28
+ transitionOutcome,
29
+ commitOutcome,
30
+ noteOutcome,
31
+ abandonedOutcome,
32
+ abandonNoopOutcome,
33
+ restoredOutcome,
34
+ } from "./OutcomeScript.js"
35
+ export {
36
+ contradictionMessage,
37
+ buildModeContradictionCheck,
38
+ modeContradictionSkipNotice,
39
+ } from "./ModeContradiction.js"
40
+ export { resolveMode, validateScriptFor } from "./SteeringMode.js"
@@ -0,0 +1,19 @@
1
+ // What `gtd install` writes as a repository's `gtd.config.ts`. The default
2
+ // export is also exported as `feature`, so a process shows that name.
3
+ export const CONFIG_SCAFFOLD = `// The workflows gtd runs here: gtd's shipped feature, review and fix.
4
+ // Every exported function is startable with \`gtd --workflow <name>\`; the
5
+ // default export is what a change in the tree starts. Each workflow brings
6
+ // its own doors: \`gtd door review [base]\` and \`gtd door fix\`.
7
+ export {
8
+ feature as default,
9
+ feature,
10
+ defaults,
11
+ envDefaults,
12
+ summary,
13
+ steering,
14
+ skills,
15
+ access,
16
+ } from "@pmelab/gtd/workflows/feature"
17
+ export { review } from "@pmelab/gtd/workflows/review"
18
+ export { fix } from "@pmelab/gtd/workflows/fix"
19
+ `