@trailstep/create-flows 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,176 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ https://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @trailstep/create-flows
2
+
3
+ `@trailstep/create-flows` is a public package of reusable, general-purpose TrailStep workflows.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @trailstep/create-flows @trailstep/authoring
9
+ pnpm add -D @trailstep/cli
10
+ ```
11
+
12
+ ## Workflows
13
+
14
+ - `takeItAway`: turns an existing conversation or feature request into reviewed planning and story-by-story delivery.
15
+ - `grillItAway`: starts with an interactive conversation and then runs the same implementation pipeline.
16
+
17
+ ## Usage
18
+
19
+ ```json
20
+ {
21
+ "conversation": "We need a workflow that exports widget reports..."
22
+ }
23
+ ```
24
+
25
+ ```bash
26
+ trailstep add @trailstep/create-flows#takeItAway
27
+ trailstep @trailstep/create-flows#takeItAway --input-file feature-request.json
28
+ trailstep @trailstep/create-flows#grillItAway
29
+ trailstep retry @trailstep/create-flows#takeItAway <runName>
30
+ ```
31
+
32
+ Generated run artifacts live under `.trailstep/runs`; inspect them, but do not edit them to recover workflow state.
@@ -0,0 +1,20 @@
1
+ import * as _trailstep_authoring from '@trailstep/authoring';
2
+
3
+ interface TakeItAwayOutput extends Record<string, unknown> {
4
+ readonly status: "implemented";
5
+ readonly featureDocPath: string;
6
+ readonly implementationDocPath: string;
7
+ readonly storyCount: number;
8
+ readonly completedStories: readonly string[];
9
+ readonly summary: string;
10
+ }
11
+
12
+ declare const grillItAway: _trailstep_authoring.DefinedWorkflow<Record<string, never>, TakeItAwayOutput>;
13
+
14
+ interface TakeItAwayInput extends Record<string, unknown> {
15
+ readonly conversation: string;
16
+ }
17
+
18
+ declare const takeItAway: _trailstep_authoring.DefinedWorkflow<TakeItAwayInput, TakeItAwayOutput>;
19
+
20
+ export { grillItAway, takeItAway };
package/dist/index.js ADDED
@@ -0,0 +1,823 @@
1
+ // src/grill-it-away/workflow.ts
2
+ import { defineWorkflow, shape as shape2 } from "@trailstep/authoring";
3
+
4
+ // src/feature-implementation/shared/output-schema.ts
5
+ import { jsonSchema } from "@trailstep/authoring";
6
+ var takeItAwayOutput = jsonSchema({
7
+ type: "object",
8
+ properties: {
9
+ status: { type: "string", const: "implemented" },
10
+ featureDocPath: { type: "string" },
11
+ implementationDocPath: { type: "string" },
12
+ storyCount: { type: "number" },
13
+ completedStories: { type: "array", items: { type: "string" } },
14
+ summary: { type: "string" }
15
+ },
16
+ required: [
17
+ "status",
18
+ "featureDocPath",
19
+ "implementationDocPath",
20
+ "storyCount",
21
+ "completedStories",
22
+ "summary"
23
+ ],
24
+ additionalProperties: false
25
+ });
26
+ function extractStoryTitle(storyContent, fallbackIndex) {
27
+ const heading = /^#{1,6}\s+(.+)$/m.exec(storyContent);
28
+ return heading?.[1]?.trim() || `Story ${fallbackIndex}`;
29
+ }
30
+
31
+ // src/grill-it-away/grill/step.ts
32
+ import { step as step8 } from "@trailstep/authoring";
33
+
34
+ // src/feature-implementation/create-feature-doc/step.ts
35
+ import { Document as Document2, state as state5, step as step7 } from "@trailstep/authoring";
36
+
37
+ // src/feature-implementation/create-or-improve-implementation-doc/step.ts
38
+ import { Document, state as state4, step as step6 } from "@trailstep/authoring";
39
+
40
+ // src/feature-implementation/review-implementation-doc/step.ts
41
+ import { fail as fail5, step as step5 } from "@trailstep/authoring";
42
+
43
+ // src/feature-implementation/shared/constants.ts
44
+ var STORY_BOUNDARY = "<!-- trailstep-story-boundary -->";
45
+ var STORY_CONTEXT_START = "<context>";
46
+ var STORY_CONTEXT_END = "</context>";
47
+ var REVIEW_PASS_THRESHOLD = 4;
48
+ var MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS = 5;
49
+ var MAX_STORY_REVIEW_ATTEMPTS = 3;
50
+
51
+ // src/feature-implementation/shared/review-schema.ts
52
+ import { jsonSchema as jsonSchema2 } from "@trailstep/authoring";
53
+ var RATING_SCHEMA = { type: "integer", minimum: 1, maximum: 5 };
54
+ var reviewOutput = jsonSchema2({
55
+ type: "object",
56
+ properties: {
57
+ score: RATING_SCHEMA,
58
+ summary: { type: "string" },
59
+ methodologyRatings: {
60
+ type: "object",
61
+ properties: {
62
+ tdd: RATING_SCHEMA,
63
+ verticalSlicing: RATING_SCHEMA,
64
+ tracerBullet: RATING_SCHEMA,
65
+ dependencies: RATING_SCHEMA,
66
+ architecture: RATING_SCHEMA
67
+ },
68
+ required: ["tdd", "verticalSlicing", "tracerBullet", "dependencies", "architecture"],
69
+ additionalProperties: false
70
+ },
71
+ requiredImprovements: { type: "array", items: { type: "string" } }
72
+ },
73
+ required: ["score", "summary", "methodologyRatings", "requiredImprovements"],
74
+ additionalProperties: false
75
+ });
76
+ function reviewPasses(review) {
77
+ return review.score >= REVIEW_PASS_THRESHOLD;
78
+ }
79
+
80
+ // src/feature-implementation/split-implementation-stories/step.ts
81
+ import { document, fail as fail4, state as state3, step as step4 } from "@trailstep/authoring";
82
+
83
+ // src/feature-implementation/implement-story/step.ts
84
+ import { fail as fail3, step as step3 } from "@trailstep/authoring";
85
+
86
+ // src/feature-implementation/review-story-implementation/step.ts
87
+ import { fail as fail2, step as step2 } from "@trailstep/authoring";
88
+
89
+ // src/feature-implementation/commit-reviewed-story/step.ts
90
+ import { done, fail, state as state2, step } from "@trailstep/authoring";
91
+
92
+ // src/feature-implementation/shared/story-state.ts
93
+ import { execFile } from "child_process";
94
+ import { promisify } from "util";
95
+ import { state } from "@trailstep/authoring";
96
+ var execFileAsync = promisify(execFile);
97
+ var STORY_STATE_KEYS = {
98
+ activeStory: "activeStory",
99
+ activeStoryStartCommit: "activeStoryStartCommit",
100
+ completedStories: "completedStories",
101
+ storyQueue: "storyQueue"
102
+ };
103
+ async function runGit(args, cwd) {
104
+ try {
105
+ const { stdout } = await execFileAsync("git", [...args], {
106
+ cwd,
107
+ maxBuffer: 1024 * 1024 * 10
108
+ });
109
+ return { ok: true, stdout: stdout.trimEnd() };
110
+ } catch (error) {
111
+ const message = error instanceof Error ? error.message : String(error);
112
+ return { ok: false, error: message };
113
+ }
114
+ }
115
+ async function recordActiveStoryStartCommit() {
116
+ const existing = await state.get(
117
+ STORY_STATE_KEYS.activeStoryStartCommit
118
+ );
119
+ if (existing?.commit || existing?.warning) {
120
+ return existing;
121
+ }
122
+ const cwd = state.cwd;
123
+ if (!cwd) {
124
+ const missingCwd = {
125
+ warning: "Workflow cwd is unavailable; the story reviewer cannot verify committed story changes from a durable git baseline."
126
+ };
127
+ await state.set(STORY_STATE_KEYS.activeStoryStartCommit, missingCwd);
128
+ return missingCwd;
129
+ }
130
+ const result = await runGit(["rev-parse", "HEAD"], cwd);
131
+ if (!result.ok || result.stdout.length === 0) {
132
+ const missingGitBaseline = {
133
+ warning: `Unable to record story start commit with \`git rev-parse HEAD\`: ${result.ok ? "no commit was returned" : result.error}`
134
+ };
135
+ await state.set(STORY_STATE_KEYS.activeStoryStartCommit, missingGitBaseline);
136
+ return missingGitBaseline;
137
+ }
138
+ const baseline = { commit: result.stdout };
139
+ await state.set(STORY_STATE_KEYS.activeStoryStartCommit, baseline);
140
+ return baseline;
141
+ }
142
+ async function resetActiveStoryStartCommit() {
143
+ await state.set(STORY_STATE_KEYS.activeStoryStartCommit, null);
144
+ }
145
+ async function loadStoryReviewGitContext() {
146
+ const baseline = await state.get(
147
+ STORY_STATE_KEYS.activeStoryStartCommit
148
+ );
149
+ const warnings = [];
150
+ if (baseline?.warning) {
151
+ warnings.push(baseline.warning);
152
+ }
153
+ const cwd = state.cwd;
154
+ if (!cwd) {
155
+ warnings.push(
156
+ "Workflow cwd is unavailable; reviewer must treat committed story-change context as missing."
157
+ );
158
+ return { storyStartCommit: baseline?.commit, warnings };
159
+ }
160
+ const status = await runGit(["status", "--short"], cwd);
161
+ if (!status.ok) {
162
+ warnings.push(`Unable to inspect \`git status --short\`: ${status.error}`);
163
+ }
164
+ const uncommittedDiff = await runGit(["diff"], cwd);
165
+ if (!uncommittedDiff.ok) {
166
+ warnings.push(
167
+ `Unable to inspect uncommitted changes with \`git diff\`: ${uncommittedDiff.error}`
168
+ );
169
+ }
170
+ const storyStartCommit = baseline?.commit;
171
+ let committedDiff;
172
+ if (!storyStartCommit) {
173
+ warnings.push(
174
+ "No durable story start commit is recorded; reviewer must not silently review only the current working tree diff."
175
+ );
176
+ } else {
177
+ const baselineReachable = await runGit(["cat-file", "-e", `${storyStartCommit}^{commit}`], cwd);
178
+ if (!baselineReachable.ok) {
179
+ warnings.push(
180
+ `Recorded story start commit \`${storyStartCommit}\` is invalid or unreachable: ${baselineReachable.error}`
181
+ );
182
+ } else {
183
+ const committed = await runGit(["diff", `${storyStartCommit}..HEAD`], cwd);
184
+ if (!committed.ok) {
185
+ warnings.push(
186
+ `Unable to inspect committed story changes with \`git diff ${storyStartCommit}..HEAD\`: ${committed.error}`
187
+ );
188
+ } else {
189
+ committedDiff = committed.stdout;
190
+ }
191
+ }
192
+ }
193
+ return {
194
+ storyStartCommit,
195
+ statusShort: status.ok ? status.stdout : void 0,
196
+ committedDiff,
197
+ uncommittedDiff: uncommittedDiff.ok ? uncommittedDiff.stdout : void 0,
198
+ warnings
199
+ };
200
+ }
201
+
202
+ // src/feature-implementation/commit-reviewed-story/run-git.ts
203
+ import { execFile as execFile2 } from "child_process";
204
+ import { promisify as promisify2 } from "util";
205
+ var execFileAsync2 = promisify2(execFile2);
206
+ async function runGit2(args, cwd) {
207
+ try {
208
+ const { stdout } = await execFileAsync2("git", [...args], {
209
+ cwd,
210
+ maxBuffer: 1024 * 1024 * 10
211
+ });
212
+ return { ok: true, stdout: stdout.trimEnd() };
213
+ } catch (error) {
214
+ const message = error instanceof Error ? error.message : String(error);
215
+ return { ok: false, error: message };
216
+ }
217
+ }
218
+
219
+ // src/feature-implementation/commit-reviewed-story/step.ts
220
+ var commitReviewedStoryStep = step({ id: "commit-reviewed-story" }).do(
221
+ async (input) => {
222
+ const activeStory = await state2.get(STORY_STATE_KEYS.activeStory) ?? input.currentStory;
223
+ if (storyAutoCommitEnabled()) {
224
+ const commitResult = await commitReviewedStoryChanges(
225
+ activeStory,
226
+ input.implementationSummary
227
+ );
228
+ if (!commitResult.ok) {
229
+ return fail({
230
+ code: commitResult.code,
231
+ message: commitResult.message,
232
+ details: commitResult.details
233
+ });
234
+ }
235
+ }
236
+ return completeReviewedStory(activeStory);
237
+ }
238
+ );
239
+ function storyAutoCommitEnabled() {
240
+ const mode = process.env.TRAILSTEP_STORY_COMMIT_MODE;
241
+ return ["1", "true", "enabled", "worktree"].includes(mode?.toLowerCase() ?? "");
242
+ }
243
+ async function commitReviewedStoryChanges(activeStory, implementationSummary) {
244
+ const cwd = state2.cwd;
245
+ if (!cwd) {
246
+ return {
247
+ ok: false,
248
+ code: "story_commit_missing_cwd",
249
+ message: "Cannot commit reviewed story because the TrailStep workflow cwd is unavailable.",
250
+ details: { storyPath: activeStory.path }
251
+ };
252
+ }
253
+ const insideWorkTree = await runGit2(["rev-parse", "--is-inside-work-tree"], cwd);
254
+ if (!insideWorkTree.ok || insideWorkTree.stdout !== "true") {
255
+ return {
256
+ ok: false,
257
+ code: "story_commit_not_git_worktree",
258
+ message: "Cannot commit reviewed story because the workflow is not running inside a git worktree.",
259
+ details: {
260
+ storyPath: activeStory.path,
261
+ gitError: insideWorkTree.ok ? void 0 : insideWorkTree.error
262
+ }
263
+ };
264
+ }
265
+ const add = await runGit2(["add", "-A"], cwd);
266
+ if (!add.ok) {
267
+ return {
268
+ ok: false,
269
+ code: "story_commit_stage_failed",
270
+ message: "Cannot commit reviewed story because `git add -A` failed.",
271
+ details: { storyPath: activeStory.path, gitError: add.error }
272
+ };
273
+ }
274
+ const staged = await runGit2(["diff", "--cached", "--name-only"], cwd);
275
+ if (!staged.ok) {
276
+ return {
277
+ ok: false,
278
+ code: "story_commit_status_failed",
279
+ message: "Cannot commit reviewed story because staged changes could not be inspected.",
280
+ details: { storyPath: activeStory.path, gitError: staged.error }
281
+ };
282
+ }
283
+ if (staged.stdout.trim().length === 0) {
284
+ const baseline = await state2.get(
285
+ STORY_STATE_KEYS.activeStoryStartCommit
286
+ );
287
+ const head = await runGit2(["rev-parse", "HEAD"], cwd);
288
+ if (baseline?.commit && head.ok && head.stdout !== baseline.commit) {
289
+ return { ok: true };
290
+ }
291
+ return {
292
+ ok: false,
293
+ code: "story_commit_empty",
294
+ message: "The story passed review, but there are no staged or already-committed changes since the story baseline to commit.",
295
+ details: {
296
+ storyPath: activeStory.path,
297
+ storyStartCommit: baseline?.commit,
298
+ head: head.ok ? head.stdout : void 0,
299
+ gitError: head.ok ? void 0 : head.error
300
+ }
301
+ };
302
+ }
303
+ const storyTitle = extractStoryTitle(activeStory.content, 1);
304
+ const commit = await runGit2(
305
+ [
306
+ "commit",
307
+ "-m",
308
+ truncateCommitSubject(`trailstep: ${storyTitle}`),
309
+ "-m",
310
+ commitBody(activeStory, implementationSummary, staged.stdout)
311
+ ],
312
+ cwd
313
+ );
314
+ if (!commit.ok) {
315
+ return {
316
+ ok: false,
317
+ code: "story_commit_failed",
318
+ message: "The story passed review, but TrailStep could not create the story commit.",
319
+ details: { storyPath: activeStory.path, gitError: commit.error }
320
+ };
321
+ }
322
+ return { ok: true };
323
+ }
324
+ async function completeReviewedStory(activeStory) {
325
+ const completed = await state2.get(STORY_STATE_KEYS.completedStories) ?? [];
326
+ const updatedCompleted = [
327
+ ...completed,
328
+ extractStoryTitle(activeStory.content, completed.length + 1)
329
+ ];
330
+ await state2.set(STORY_STATE_KEYS.completedStories, updatedCompleted);
331
+ const storyQueue = await state2.get(STORY_STATE_KEYS.storyQueue) ?? [];
332
+ const [nextStory, ...remaining] = storyQueue;
333
+ if (!nextStory) {
334
+ await state2.set(STORY_STATE_KEYS.activeStory, null);
335
+ await resetActiveStoryStartCommit();
336
+ const featureDoc = await state2.get("featureDoc");
337
+ const implementationDoc = await state2.get("implementationDoc");
338
+ const output = {
339
+ status: "implemented",
340
+ featureDocPath: featureDoc?.path ?? "",
341
+ implementationDocPath: implementationDoc?.path ?? "",
342
+ storyCount: updatedCompleted.length,
343
+ completedStories: updatedCompleted,
344
+ summary: `Implemented and reviewed ${updatedCompleted.length} ${updatedCompleted.length === 1 ? "story" : "stories"}.`
345
+ };
346
+ return done(output);
347
+ }
348
+ await state2.set(STORY_STATE_KEYS.storyQueue, remaining);
349
+ await state2.set(STORY_STATE_KEYS.activeStory, nextStory);
350
+ await resetActiveStoryStartCommit();
351
+ await recordActiveStoryStartCommit();
352
+ return implementStoryStep({ currentStory: nextStory, attempt: 1 });
353
+ }
354
+ function truncateCommitSubject(subject) {
355
+ return subject.length <= 72 ? subject : `${subject.slice(0, 69)}...`;
356
+ }
357
+ function commitBody(activeStory, implementationSummary, stagedFiles) {
358
+ return [
359
+ "Committed automatically by TrailStep after a passing story review.",
360
+ "",
361
+ `Story artifact: ${activeStory.path}`,
362
+ "",
363
+ "Implementer summary:",
364
+ implementationSummary?.trim() || "Not provided.",
365
+ "",
366
+ "Staged files:",
367
+ stagedFiles.split("\n").filter((file) => file.length > 0).map((file) => `- ${file}`).join("\n")
368
+ ].join("\n");
369
+ }
370
+
371
+ // src/feature-implementation/review-story-implementation/prompt.ts
372
+ import { loadFragments, promptSections, section } from "@trailstep/authoring";
373
+ var fragments = loadFragments(import.meta.dirname, {
374
+ methodology: "../shared/feature-methodology.md",
375
+ storyContract: "../shared/story-implementation-contract.md"
376
+ });
377
+ function reviewStoryImplementationPrompt({
378
+ input
379
+ }) {
380
+ const committedDiffCommand = input.gitContext.storyStartCommit ? `git diff ${input.gitContext.storyStartCommit}..HEAD` : "git diff <missing-story-start-commit>..HEAD";
381
+ return promptSections(
382
+ fragments.methodology,
383
+ fragments.storyContract,
384
+ section("Story", input.currentStory.content),
385
+ section("Implementer summary", input.implementationSummary ?? "Not provided."),
386
+ section(
387
+ "Story review git baseline",
388
+ [
389
+ `Recorded story start commit: ${input.gitContext.storyStartCommit ?? "MISSING"}`,
390
+ `Inspect committed story changes with: \`${committedDiffCommand}\``,
391
+ "Inspect uncommitted working tree changes with: `git diff`",
392
+ "Inspect status with: `git status --short`",
393
+ input.gitContext.warnings.length > 0 ? [
394
+ "",
395
+ "Warnings / blocked context:",
396
+ ...input.gitContext.warnings.map((warning) => `- ${warning}`)
397
+ ].join("\n") : ""
398
+ ].filter((line) => line.length > 0).join("\n")
399
+ ),
400
+ section(
401
+ "Committed story changes (`git diff <storyStartCommit>..HEAD`)",
402
+ input.gitContext.committedDiff ?? "Not available."
403
+ ),
404
+ section(
405
+ "Uncommitted working tree changes (`git diff`)",
406
+ input.gitContext.uncommittedDiff ?? "Not available."
407
+ ),
408
+ section(
409
+ "Working tree status (`git status --short`)",
410
+ input.gitContext.statusShort ?? "Not available."
411
+ ),
412
+ section(
413
+ "Task",
414
+ "Review only the active story slice represented by the recorded story start commit through HEAD, plus the current uncommitted working tree changes, against the story above and the implementer summary. Prefer the supplied diff/status sections; if you need to inspect locally, use read-only commands only (`git status --short`, the listed `git diff <storyStartCommit>..HEAD`, and `git diff`) \u2014 do not run tests, edit code, revert files, clean files, or try to isolate the diff by changing the repository. If unrelated dirty files, a missing/invalid baseline, or ambiguous context prevents a trustworthy review, say so in the structured review and require the implementer/workflow to fix the isolation; never remove changes yourself. Respond only with the structured review."
415
+ )
416
+ );
417
+ }
418
+
419
+ // src/feature-implementation/review-story-implementation/step.ts
420
+ var reviewStoryImplementationStep = step2({ id: "review-story-implementation" }).prompt(reviewStoryImplementationPrompt, {
421
+ agent: "reviewer",
422
+ output: reviewOutput
423
+ }).do(async (review, input) => {
424
+ if (!reviewPasses(review)) {
425
+ if (input.attempt >= MAX_STORY_REVIEW_ATTEMPTS) {
426
+ return fail2({
427
+ code: "story_review_exhausted",
428
+ message: `Story failed review ${MAX_STORY_REVIEW_ATTEMPTS} times in a row (last score ${review.score}/5).`,
429
+ details: { review, storyPath: input.currentStory.path }
430
+ });
431
+ }
432
+ return implementStoryStep({
433
+ currentStory: input.currentStory,
434
+ previousStoryReview: review,
435
+ attempt: input.attempt + 1
436
+ });
437
+ }
438
+ return commitReviewedStoryStep({
439
+ currentStory: input.currentStory,
440
+ implementationSummary: input.implementationSummary
441
+ });
442
+ });
443
+
444
+ // src/feature-implementation/implement-story/prompt.ts
445
+ import {
446
+ jsonSchema as jsonSchema3,
447
+ list,
448
+ loadFragments as loadFragments2,
449
+ promptSections as promptSections2,
450
+ section as section2
451
+ } from "@trailstep/authoring";
452
+ var fragments2 = loadFragments2(import.meta.dirname, {
453
+ methodology: "../shared/feature-methodology.md",
454
+ architectureGuidance: "../shared/project-architecture-guidance.md",
455
+ storyContract: "../shared/story-implementation-contract.md"
456
+ });
457
+ var implementStoryOutput = jsonSchema3({
458
+ type: "object",
459
+ properties: {
460
+ blocked: { type: "boolean" },
461
+ blockedReason: { type: "string" },
462
+ summary: {
463
+ type: "string",
464
+ description: "Files changed, commands run, and their results."
465
+ }
466
+ },
467
+ required: ["blocked", "summary"],
468
+ additionalProperties: false
469
+ });
470
+ function implementStoryPrompt({ input }) {
471
+ const taskBody = input.previousStoryReview === void 0 ? "Implement this story." : promptSections2(
472
+ `This is retry attempt ${input.attempt} for this story. A previous review scored the implementation ${input.previousStoryReview.score}/5: ${input.previousStoryReview.summary}`,
473
+ `Required improvements to address, without discarding what already works:
474
+
475
+ ${list(input.previousStoryReview.requiredImprovements)}`
476
+ );
477
+ return promptSections2(
478
+ fragments2.methodology,
479
+ fragments2.architectureGuidance,
480
+ fragments2.storyContract,
481
+ section2("Story", input.currentStory.content),
482
+ section2(
483
+ "Task",
484
+ `${taskBody}
485
+
486
+ Set \`blocked: true\` with a clear \`blockedReason\` instead of guessing or pretending the story is complete. Otherwise set \`blocked: false\` and use \`summary\` to report files changed, commands run, and their results.`
487
+ )
488
+ );
489
+ }
490
+
491
+ // src/feature-implementation/implement-story/step.ts
492
+ var implementStoryStep = step3({ id: "implement-story" }).prompt(implementStoryPrompt, {
493
+ agent: "implementer",
494
+ output: implementStoryOutput
495
+ }).do(async (promptOutput, input) => {
496
+ if (promptOutput.blocked) {
497
+ return fail3({
498
+ code: "story_blocked",
499
+ message: promptOutput.blockedReason ?? "Story implementation reported a blocked state.",
500
+ details: { storyPath: input.currentStory.path }
501
+ });
502
+ }
503
+ return reviewStoryImplementationStep({
504
+ currentStory: input.currentStory,
505
+ attempt: input.attempt,
506
+ implementationSummary: promptOutput.summary,
507
+ gitContext: await loadStoryReviewGitContext()
508
+ });
509
+ });
510
+
511
+ // src/feature-implementation/split-implementation-stories/step.ts
512
+ var splitImplementationStoriesStep = step4({ id: "split-implementation-stories" }).do(
513
+ async ({ implementationDoc }) => {
514
+ const contextStartCount = countOccurrences(implementationDoc.content, STORY_CONTEXT_START);
515
+ const contextEndCount = countOccurrences(implementationDoc.content, STORY_CONTEXT_END);
516
+ if (contextStartCount !== contextEndCount) {
517
+ return fail4({
518
+ code: "unbalanced_story_context",
519
+ message: `Found ${contextStartCount} \`${STORY_CONTEXT_START}\` marker(s) and ${contextEndCount} \`${STORY_CONTEXT_END}\` marker(s) in implementation-doc.md. Context blocks must be balanced.`,
520
+ details: { implementationDocPath: implementationDoc.path }
521
+ });
522
+ }
523
+ const contextMatches = Array.from(implementationDoc.content.matchAll(storyContextPattern()));
524
+ if (contextMatches.length !== contextStartCount) {
525
+ return fail4({
526
+ code: "invalid_story_context_order",
527
+ message: `Every \`${STORY_CONTEXT_START}\` marker in implementation-doc.md must be followed by a matching \`${STORY_CONTEXT_END}\` marker.`,
528
+ details: { implementationDocPath: implementationDoc.path }
529
+ });
530
+ }
531
+ const contextBlocks = contextMatches.map(([, context]) => context?.trim() ?? "").filter((context) => context.length > 0);
532
+ const sharedContext = contextBlocks.join("\n\n---\n\n");
533
+ const contentWithoutContextBlocks = implementationDoc.content.replace(
534
+ storyContextPattern(),
535
+ ""
536
+ );
537
+ const chunks = contentWithoutContextBlocks.split(STORY_BOUNDARY).slice(1).map((chunk) => chunk.trim()).filter((chunk) => chunk.length > 0).map((chunk) => prependSharedContext(chunk, sharedContext));
538
+ if (chunks.length === 0) {
539
+ return fail4({
540
+ code: "no_stories_found",
541
+ message: `No \`${STORY_BOUNDARY}\`-delimited stories found in implementation-doc.md.`,
542
+ details: { implementationDocPath: implementationDoc.path }
543
+ });
544
+ }
545
+ const storyDocs = [];
546
+ for (const chunk of chunks) {
547
+ storyDocs.push(await document(chunk));
548
+ }
549
+ const [firstStory, ...remaining] = storyDocs;
550
+ await state3.set(STORY_STATE_KEYS.storyQueue, remaining);
551
+ await state3.set(STORY_STATE_KEYS.completedStories, []);
552
+ await state3.set(STORY_STATE_KEYS.activeStory, firstStory);
553
+ await recordActiveStoryStartCommit();
554
+ return implementStoryStep({ currentStory: firstStory, attempt: 1 });
555
+ }
556
+ );
557
+ function countOccurrences(value, needle) {
558
+ if (needle.length === 0) {
559
+ return 0;
560
+ }
561
+ let count = 0;
562
+ let offset = 0;
563
+ while (true) {
564
+ const index = value.indexOf(needle, offset);
565
+ if (index === -1) {
566
+ return count;
567
+ }
568
+ count += 1;
569
+ offset = index + needle.length;
570
+ }
571
+ }
572
+ function storyContextPattern() {
573
+ return new RegExp(
574
+ `${escapeRegExp(STORY_CONTEXT_START)}([\\s\\S]*?)${escapeRegExp(STORY_CONTEXT_END)}`,
575
+ "g"
576
+ );
577
+ }
578
+ function prependSharedContext(story, sharedContext) {
579
+ if (sharedContext.length === 0) {
580
+ return story;
581
+ }
582
+ return ["## Shared implementation context", sharedContext, "## Active story", story].join("\n\n");
583
+ }
584
+ function escapeRegExp(value) {
585
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
586
+ }
587
+
588
+ // src/feature-implementation/review-implementation-doc/prompt.ts
589
+ import { list as list2, loadFragments as loadFragments3, promptSections as promptSections3, section as section3 } from "@trailstep/authoring";
590
+ var fragments3 = loadFragments3(import.meta.dirname, {
591
+ methodology: "../shared/feature-methodology.md",
592
+ implementationDocFormat: "../shared/implementation-doc-format.md"
593
+ });
594
+ function reviewImplementationDocPrompt({
595
+ input
596
+ }) {
597
+ const reviewCriteria = list2([
598
+ "traceability to the feature doc",
599
+ "strict behavioral-red TDD story design",
600
+ "vertical slices rather than horizontal tasks",
601
+ "a clear tracer-bullet strategy",
602
+ "hard dependency labels and topological ordering",
603
+ "acceptance criteria and validation commands",
604
+ "story instructions self-contained enough for an implementer who will only see one story plus the prepended shared context at a time",
605
+ "correct use of balanced `<context>` ... `</context>` blocks for shared implementer context",
606
+ "correct use of the `<!-- trailstep-story-boundary -->` marker between stories, and that no story-critical detail lives only in non-context overview text above the first marker"
607
+ ]);
608
+ return promptSections3(
609
+ fragments3.methodology,
610
+ fragments3.implementationDocFormat,
611
+ section3("Feature doc", input.featureDoc.content),
612
+ section3("Implementation doc under review", input.implementationDoc.content),
613
+ section3(
614
+ "Task",
615
+ `Critically review the implementation doc above against the feature doc and the methodology. Review for:
616
+
617
+ ${reviewCriteria}
618
+
619
+ Do not edit the implementation doc. Respond only with the structured review.`
620
+ )
621
+ );
622
+ }
623
+
624
+ // src/feature-implementation/review-implementation-doc/step.ts
625
+ var reviewImplementationDocStep = step5({ id: "review-implementation-doc" }).prompt(reviewImplementationDocPrompt, {
626
+ agent: "reviewer",
627
+ output: reviewOutput
628
+ }).do((review, input) => {
629
+ if (reviewPasses(review)) {
630
+ return splitImplementationStoriesStep({ implementationDoc: input.implementationDoc });
631
+ }
632
+ if (input.attempt >= MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS) {
633
+ return fail5({
634
+ code: "implementation_doc_review_exhausted",
635
+ message: `implementation-doc.md failed review ${MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS} times in a row (last score ${review.score}/5).`,
636
+ details: { review, implementationDocPath: input.implementationDoc.path }
637
+ });
638
+ }
639
+ return createOrImproveImplementationDocStep({
640
+ featureDoc: input.featureDoc,
641
+ previousReview: review,
642
+ attempt: input.attempt + 1
643
+ });
644
+ });
645
+
646
+ // src/feature-implementation/create-or-improve-implementation-doc/prompt.ts
647
+ import { list as list3, loadFragments as loadFragments4, promptSections as promptSections4, section as section4 } from "@trailstep/authoring";
648
+ var fragments4 = loadFragments4(import.meta.dirname, {
649
+ methodology: "../shared/feature-methodology.md",
650
+ architectureGuidance: "../shared/project-architecture-guidance.md",
651
+ implementationDocFormat: "../shared/implementation-doc-format.md"
652
+ });
653
+ function createOrImproveImplementationDocPrompt({
654
+ input
655
+ }) {
656
+ const taskBody = input.previousReview === void 0 ? "Create `implementation-doc.md` from the feature doc above, following the format exactly enough that stories can later be split mechanically on the `<!-- trailstep-story-boundary -->` marker and shared context can be prepended from balanced `<context>` blocks." : promptSections4(
657
+ `This is improvement attempt ${input.attempt}. A previous review scored this plan ${input.previousReview.score}/5: ${input.previousReview.summary}`,
658
+ `Required improvements to address, without discarding what already works:
659
+
660
+ ${list3(input.previousReview.requiredImprovements)}`
661
+ );
662
+ return promptSections4(
663
+ fragments4.methodology,
664
+ fragments4.architectureGuidance,
665
+ fragments4.implementationDocFormat,
666
+ section4("Feature doc", input.featureDoc.content),
667
+ section4(
668
+ "Task",
669
+ `${taskBody}
670
+
671
+ Design stories around strict behavioral-red TDD, vertical slicing, tracer-bullet methodology, and hard dependency labels only. Topologically order stories by dependency. Put shared implementation details in balanced \`<context>\` ... \`</context>\` blocks so split-stories prepends them to every story; repeat details inside individual stories when only selected stories need them. Write every story as implementation-ready instructions for an implementer who will only see that story plus the prepended context.`
672
+ )
673
+ );
674
+ }
675
+
676
+ // src/feature-implementation/create-or-improve-implementation-doc/step.ts
677
+ var createOrImproveImplementationDocStep = step6({
678
+ id: "create-or-improve-implementation-doc"
679
+ }).prompt(createOrImproveImplementationDocPrompt, {
680
+ agent: "planner",
681
+ output: Document
682
+ }).do(async (implementationDoc, input) => {
683
+ await state4.set("implementationDoc", implementationDoc);
684
+ return reviewImplementationDocStep({
685
+ featureDoc: input.featureDoc,
686
+ implementationDoc,
687
+ attempt: input.attempt
688
+ });
689
+ });
690
+
691
+ // src/feature-implementation/create-feature-doc/prompt.ts
692
+ import { loadFragments as loadFragments5, promptSections as promptSections5, section as section5 } from "@trailstep/authoring";
693
+ var fragments5 = loadFragments5(import.meta.dirname, {
694
+ methodology: "../shared/feature-methodology.md",
695
+ featureDocFormat: "../shared/feature-doc-format.md"
696
+ });
697
+ function createFeatureDocPrompt({ input }) {
698
+ return promptSections5(
699
+ fragments5.methodology,
700
+ fragments5.featureDocFormat,
701
+ section5("Conversation / feature request", input.conversation),
702
+ section5(
703
+ "Task",
704
+ 'Write `feature-doc.md` following the format above, based on the conversation/request. Make it detailed enough that another agent can plan implementation without reading the original conversation. Preserve uncertainty explicitly in "Open Questions and Assumptions" \u2014 do not invent missing product decisions.'
705
+ )
706
+ );
707
+ }
708
+
709
+ // src/feature-implementation/create-feature-doc/step.ts
710
+ var createFeatureDocStep = step7({ id: "create-feature-doc" }).prompt(createFeatureDocPrompt, {
711
+ agent: "featureWriter",
712
+ output: Document2
713
+ }).do(async (featureDoc) => {
714
+ await state5.set("featureDoc", featureDoc);
715
+ return createOrImproveImplementationDocStep({ featureDoc, attempt: 1 });
716
+ });
717
+
718
+ // src/feature-implementation/shared/input-schema.ts
719
+ import { shape } from "@trailstep/authoring";
720
+ var takeItAwayInput = shape({ conversation: "string" });
721
+
722
+ // src/grill-it-away/grill/prompt.ts
723
+ import { promptSections as promptSections6, section as section6 } from "@trailstep/authoring";
724
+ function grillPrompt() {
725
+ return promptSections6(
726
+ section6(
727
+ "Role",
728
+ "You are the interactive front door for starting a new TrailStep feature. Open by asking the user what they want to build."
729
+ ),
730
+ section6(
731
+ "Task",
732
+ "Keep asking follow-up questions until you are confident you understand the feature request well enough to hand off to a planning agent. There is no fixed checklist of required topics \u2014 use your judgment, and do not end the conversation prematurely just to finish quickly."
733
+ ),
734
+ section6(
735
+ "Output",
736
+ "Your structured output's `conversation` field must contain the full raw transcript of the conversation so far, not a summary. Preserve as much of the actual back-and-forth as possible."
737
+ )
738
+ );
739
+ }
740
+
741
+ // src/grill-it-away/grill/step.ts
742
+ var grillStep = step8({ id: "grill" }).prompt(grillPrompt, {
743
+ agent: "grillingAgent",
744
+ mode: "interactive",
745
+ output: takeItAwayInput
746
+ }).do((output) => createFeatureDocStep(output));
747
+
748
+ // src/grill-it-away/workflow.ts
749
+ var grillItAway = defineWorkflow({
750
+ id: "grill-it-away",
751
+ description: "Interactively grills the user until it understands the requested feature.",
752
+ inputShape: shape2({}),
753
+ outputShape: takeItAwayOutput,
754
+ agents: {
755
+ grillingAgent: {
756
+ size: "medium",
757
+ thinking: "medium",
758
+ description: "Grills the user until it understands the requested feature."
759
+ },
760
+ featureWriter: {
761
+ size: "medium",
762
+ thinking: "medium",
763
+ description: "Turns a conversation/feature request into a standalone feature doc."
764
+ },
765
+ planner: {
766
+ size: "large",
767
+ thinking: "high",
768
+ description: "Creates or improves the implementation doc: architecture-aware, TDD/vertical-slice/tracer-bullet story design."
769
+ },
770
+ reviewer: {
771
+ size: "large",
772
+ thinking: "high",
773
+ description: "Reviews isolated implementation docs and story diffs against methodology."
774
+ },
775
+ implementer: {
776
+ size: "medium",
777
+ thinking: "medium",
778
+ description: "Implements one story at a time using strict behavioral-red TDD."
779
+ }
780
+ },
781
+ start() {
782
+ return grillStep();
783
+ }
784
+ });
785
+
786
+ // src/take-it-away/workflow.ts
787
+ import { defineWorkflow as defineWorkflow2 } from "@trailstep/authoring";
788
+ var takeItAway = defineWorkflow2({
789
+ id: "take-it-away",
790
+ description: "Turns an already-organic conversation/feature request into a reviewed implementation plan, then implements it story by story.",
791
+ inputShape: takeItAwayInput,
792
+ outputShape: takeItAwayOutput,
793
+ agents: {
794
+ featureWriter: {
795
+ size: "medium",
796
+ thinking: "medium",
797
+ description: "Turns a conversation/feature request into a standalone feature doc."
798
+ },
799
+ planner: {
800
+ size: "large",
801
+ thinking: "high",
802
+ description: "Creates or improves the implementation doc: architecture-aware, TDD/vertical-slice/tracer-bullet story design."
803
+ },
804
+ reviewer: {
805
+ size: "large",
806
+ thinking: "high",
807
+ description: "Reviews isolated implementation docs and story diffs against methodology."
808
+ },
809
+ implementer: {
810
+ size: "medium",
811
+ thinking: "medium",
812
+ description: "Implements one story at a time using strict behavioral-red TDD."
813
+ }
814
+ },
815
+ start(input) {
816
+ return createFeatureDocStep(input);
817
+ }
818
+ });
819
+ export {
820
+ grillItAway,
821
+ takeItAway
822
+ };
823
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/grill-it-away/workflow.ts","../src/feature-implementation/shared/output-schema.ts","../src/grill-it-away/grill/step.ts","../src/feature-implementation/create-feature-doc/step.ts","../src/feature-implementation/create-or-improve-implementation-doc/step.ts","../src/feature-implementation/review-implementation-doc/step.ts","../src/feature-implementation/shared/constants.ts","../src/feature-implementation/shared/review-schema.ts","../src/feature-implementation/split-implementation-stories/step.ts","../src/feature-implementation/implement-story/step.ts","../src/feature-implementation/review-story-implementation/step.ts","../src/feature-implementation/commit-reviewed-story/step.ts","../src/feature-implementation/shared/story-state.ts","../src/feature-implementation/commit-reviewed-story/run-git.ts","../src/feature-implementation/review-story-implementation/prompt.ts","../src/feature-implementation/implement-story/prompt.ts","../src/feature-implementation/review-implementation-doc/prompt.ts","../src/feature-implementation/create-or-improve-implementation-doc/prompt.ts","../src/feature-implementation/create-feature-doc/prompt.ts","../src/feature-implementation/shared/input-schema.ts","../src/grill-it-away/grill/prompt.ts","../src/take-it-away/workflow.ts"],"sourcesContent":["import { defineWorkflow, shape } from \"@trailstep/authoring\";\nimport { takeItAwayOutput } from \"../feature-implementation/shared/output-schema.js\";\nimport { grillStep } from \"./grill/step.js\";\n\nexport const grillItAway = defineWorkflow({\n id: \"grill-it-away\",\n description: \"Interactively grills the user until it understands the requested feature.\",\n inputShape: shape<Record<string, never>>({}),\n outputShape: takeItAwayOutput,\n agents: {\n grillingAgent: {\n size: \"medium\",\n thinking: \"medium\",\n description: \"Grills the user until it understands the requested feature.\",\n },\n featureWriter: {\n size: \"medium\",\n thinking: \"medium\",\n description: \"Turns a conversation/feature request into a standalone feature doc.\",\n },\n planner: {\n size: \"large\",\n thinking: \"high\",\n description:\n \"Creates or improves the implementation doc: architecture-aware, TDD/vertical-slice/tracer-bullet story design.\",\n },\n reviewer: {\n size: \"large\",\n thinking: \"high\",\n description: \"Reviews isolated implementation docs and story diffs against methodology.\",\n },\n implementer: {\n size: \"medium\",\n thinking: \"medium\",\n description: \"Implements one story at a time using strict behavioral-red TDD.\",\n },\n },\n start() {\n return grillStep();\n },\n});\n","import { jsonSchema } from \"@trailstep/authoring\";\n\nexport interface TakeItAwayOutput extends Record<string, unknown> {\n readonly status: \"implemented\";\n readonly featureDocPath: string;\n readonly implementationDocPath: string;\n readonly storyCount: number;\n readonly completedStories: readonly string[];\n readonly summary: string;\n}\n\nexport const takeItAwayOutput = jsonSchema<TakeItAwayOutput>({\n type: \"object\",\n properties: {\n status: { type: \"string\", const: \"implemented\" },\n featureDocPath: { type: \"string\" },\n implementationDocPath: { type: \"string\" },\n storyCount: { type: \"number\" },\n completedStories: { type: \"array\", items: { type: \"string\" } },\n summary: { type: \"string\" },\n },\n required: [\n \"status\",\n \"featureDocPath\",\n \"implementationDocPath\",\n \"storyCount\",\n \"completedStories\",\n \"summary\",\n ],\n additionalProperties: false,\n});\n\nexport function extractStoryTitle(storyContent: string, fallbackIndex: number): string {\n const heading = /^#{1,6}\\s+(.+)$/m.exec(storyContent);\n return heading?.[1]?.trim() || `Story ${fallbackIndex}`;\n}\n","import { step } from \"@trailstep/authoring\";\nimport { createFeatureDocStep } from \"../../feature-implementation/create-feature-doc/step.js\";\nimport { takeItAwayInput } from \"../../feature-implementation/shared/input-schema.js\";\nimport { grillPrompt } from \"./prompt.js\";\n\nexport const grillStep = step({ id: \"grill\" })\n .prompt(grillPrompt, {\n agent: \"grillingAgent\",\n mode: \"interactive\",\n output: takeItAwayInput,\n })\n .do((output) => createFeatureDocStep(output));\n","import { Document, state, step } from \"@trailstep/authoring\";\nimport { createOrImproveImplementationDocStep } from \"../create-or-improve-implementation-doc/step.js\";\nimport { createFeatureDocPrompt } from \"./prompt.js\";\n\nexport const createFeatureDocStep = step({ id: \"create-feature-doc\" })\n .prompt(createFeatureDocPrompt, {\n agent: \"featureWriter\",\n output: Document,\n })\n .do(async (featureDoc) => {\n await state.set(\"featureDoc\", featureDoc);\n return createOrImproveImplementationDocStep({ featureDoc, attempt: 1 });\n });\n","import { Document, state, step } from \"@trailstep/authoring\";\nimport { reviewImplementationDocStep } from \"../review-implementation-doc/step.js\";\nimport { createOrImproveImplementationDocPrompt } from \"./prompt.js\";\n\nexport const createOrImproveImplementationDocStep = step({\n id: \"create-or-improve-implementation-doc\",\n})\n .prompt(createOrImproveImplementationDocPrompt, {\n agent: \"planner\",\n output: Document,\n })\n .do(async (implementationDoc, input) => {\n await state.set(\"implementationDoc\", implementationDoc);\n return reviewImplementationDocStep({\n featureDoc: input.featureDoc,\n implementationDoc,\n attempt: input.attempt,\n });\n });\n","import { fail, step } from \"@trailstep/authoring\";\nimport { createOrImproveImplementationDocStep } from \"../create-or-improve-implementation-doc/step.js\";\nimport { MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS } from \"../shared/constants.js\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\nimport { reviewOutput, reviewPasses } from \"../shared/review-schema.js\";\nimport { splitImplementationStoriesStep } from \"../split-implementation-stories/step.js\";\nimport { type ReviewImplementationDocInput, reviewImplementationDocPrompt } from \"./prompt.js\";\n\nexport const reviewImplementationDocStep = step({ id: \"review-implementation-doc\" })\n .prompt<ReviewImplementationDocInput, ReviewResult>(reviewImplementationDocPrompt, {\n agent: \"reviewer\",\n output: reviewOutput,\n })\n .do((review, input) => {\n if (reviewPasses(review)) {\n return splitImplementationStoriesStep({ implementationDoc: input.implementationDoc });\n }\n\n if (input.attempt >= MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS) {\n return fail({\n code: \"implementation_doc_review_exhausted\",\n message: `implementation-doc.md failed review ${MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS} times in a row (last score ${review.score}/5).`,\n details: { review, implementationDocPath: input.implementationDoc.path },\n });\n }\n\n return createOrImproveImplementationDocStep({\n featureDoc: input.featureDoc,\n previousReview: review,\n attempt: input.attempt + 1,\n });\n });\n","export const STORY_BOUNDARY = \"<!-- trailstep-story-boundary -->\";\n\nexport const STORY_CONTEXT_START = \"<context>\";\n\nexport const STORY_CONTEXT_END = \"</context>\";\n\nexport const REVIEW_PASS_THRESHOLD = 4;\n\nexport const MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS = 5;\n\nexport const MAX_STORY_REVIEW_ATTEMPTS = 3;\n","import { jsonSchema } from \"@trailstep/authoring\";\n\nimport { REVIEW_PASS_THRESHOLD } from \"./constants.js\";\n\nexport interface MethodologyRatings extends Record<string, unknown> {\n readonly tdd: number;\n readonly verticalSlicing: number;\n readonly tracerBullet: number;\n readonly dependencies: number;\n readonly architecture: number;\n}\n\nexport interface ReviewResult extends Record<string, unknown> {\n readonly score: number;\n readonly summary: string;\n readonly methodologyRatings: MethodologyRatings;\n readonly requiredImprovements: readonly string[];\n}\n\nconst RATING_SCHEMA = { type: \"integer\", minimum: 1, maximum: 5 } as const;\n\nexport const reviewOutput = jsonSchema<ReviewResult>({\n type: \"object\",\n properties: {\n score: RATING_SCHEMA,\n summary: { type: \"string\" },\n methodologyRatings: {\n type: \"object\",\n properties: {\n tdd: RATING_SCHEMA,\n verticalSlicing: RATING_SCHEMA,\n tracerBullet: RATING_SCHEMA,\n dependencies: RATING_SCHEMA,\n architecture: RATING_SCHEMA,\n },\n required: [\"tdd\", \"verticalSlicing\", \"tracerBullet\", \"dependencies\", \"architecture\"],\n additionalProperties: false,\n },\n requiredImprovements: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"score\", \"summary\", \"methodologyRatings\", \"requiredImprovements\"],\n additionalProperties: false,\n});\n\nexport function reviewPasses(review: ReviewResult): boolean {\n return review.score >= REVIEW_PASS_THRESHOLD;\n}\n","import { type Document, document, fail, state, step } from \"@trailstep/authoring\";\nimport type { ContinuationResult } from \"@trailstep/core\";\nimport { implementStoryStep } from \"../implement-story/step.js\";\nimport { STORY_BOUNDARY, STORY_CONTEXT_END, STORY_CONTEXT_START } from \"../shared/constants.js\";\nimport { recordActiveStoryStartCommit, STORY_STATE_KEYS } from \"../shared/story-state.js\";\n\nexport interface SplitImplementationStoriesInput extends Record<string, unknown> {\n readonly implementationDoc: Document;\n}\n\nexport const splitImplementationStoriesStep = step({ id: \"split-implementation-stories\" }).do(\n async ({ implementationDoc }: SplitImplementationStoriesInput): Promise<ContinuationResult> => {\n const contextStartCount = countOccurrences(implementationDoc.content, STORY_CONTEXT_START);\n const contextEndCount = countOccurrences(implementationDoc.content, STORY_CONTEXT_END);\n\n if (contextStartCount !== contextEndCount) {\n return fail({\n code: \"unbalanced_story_context\",\n message: `Found ${contextStartCount} \\`${STORY_CONTEXT_START}\\` marker(s) and ${contextEndCount} \\`${STORY_CONTEXT_END}\\` marker(s) in implementation-doc.md. Context blocks must be balanced.`,\n details: { implementationDocPath: implementationDoc.path },\n });\n }\n\n const contextMatches = Array.from(implementationDoc.content.matchAll(storyContextPattern()));\n if (contextMatches.length !== contextStartCount) {\n return fail({\n code: \"invalid_story_context_order\",\n message: `Every \\`${STORY_CONTEXT_START}\\` marker in implementation-doc.md must be followed by a matching \\`${STORY_CONTEXT_END}\\` marker.`,\n details: { implementationDocPath: implementationDoc.path },\n });\n }\n\n const contextBlocks = contextMatches\n .map(([, context]) => context?.trim() ?? \"\")\n .filter((context) => context.length > 0);\n const sharedContext = contextBlocks.join(\"\\n\\n---\\n\\n\");\n const contentWithoutContextBlocks = implementationDoc.content.replace(\n storyContextPattern(),\n \"\",\n );\n\n const chunks = contentWithoutContextBlocks\n .split(STORY_BOUNDARY)\n .slice(1) // drop overview-only text before the first boundary; <context> blocks are prepended below\n .map((chunk) => chunk.trim())\n .filter((chunk) => chunk.length > 0)\n .map((chunk) => prependSharedContext(chunk, sharedContext));\n\n if (chunks.length === 0) {\n return fail({\n code: \"no_stories_found\",\n message: `No \\`${STORY_BOUNDARY}\\`-delimited stories found in implementation-doc.md.`,\n details: { implementationDocPath: implementationDoc.path },\n });\n }\n\n const storyDocs: Document[] = [];\n for (const chunk of chunks) {\n storyDocs.push(await document(chunk));\n }\n\n // storyDocs.length === chunks.length, already guarded above to be > 0.\n const [firstStory, ...remaining] = storyDocs as [Document, ...Document[]];\n await state.set(STORY_STATE_KEYS.storyQueue, remaining);\n await state.set(STORY_STATE_KEYS.completedStories, []);\n await state.set(STORY_STATE_KEYS.activeStory, firstStory);\n await recordActiveStoryStartCommit();\n\n return implementStoryStep({ currentStory: firstStory, attempt: 1 });\n },\n);\n\nfunction countOccurrences(value: string, needle: string): number {\n if (needle.length === 0) {\n return 0;\n }\n\n let count = 0;\n let offset = 0;\n while (true) {\n const index = value.indexOf(needle, offset);\n if (index === -1) {\n return count;\n }\n\n count += 1;\n offset = index + needle.length;\n }\n}\n\nfunction storyContextPattern(): RegExp {\n return new RegExp(\n `${escapeRegExp(STORY_CONTEXT_START)}([\\\\s\\\\S]*?)${escapeRegExp(STORY_CONTEXT_END)}`,\n \"g\",\n );\n}\n\nfunction prependSharedContext(story: string, sharedContext: string): string {\n if (sharedContext.length === 0) {\n return story;\n }\n\n return [\"## Shared implementation context\", sharedContext, \"## Active story\", story].join(\"\\n\\n\");\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { fail, step } from \"@trailstep/authoring\";\nimport { reviewStoryImplementationStep } from \"../review-story-implementation/step.js\";\nimport { loadStoryReviewGitContext } from \"../shared/story-state.js\";\nimport {\n type ImplementStoryInput,\n type ImplementStoryOutput,\n implementStoryOutput,\n implementStoryPrompt,\n} from \"./prompt.js\";\n\nexport const implementStoryStep = step({ id: \"implement-story\" })\n .prompt<ImplementStoryInput, ImplementStoryOutput>(implementStoryPrompt, {\n agent: \"implementer\",\n output: implementStoryOutput,\n })\n .do(async (promptOutput, input) => {\n if (promptOutput.blocked) {\n return fail({\n code: \"story_blocked\",\n message: promptOutput.blockedReason ?? \"Story implementation reported a blocked state.\",\n details: { storyPath: input.currentStory.path },\n });\n }\n\n return reviewStoryImplementationStep({\n currentStory: input.currentStory,\n attempt: input.attempt,\n implementationSummary: promptOutput.summary,\n gitContext: await loadStoryReviewGitContext(),\n });\n });\n","import { fail, step } from \"@trailstep/authoring\";\nimport { commitReviewedStoryStep } from \"../commit-reviewed-story/step.js\";\nimport { implementStoryStep } from \"../implement-story/step.js\";\nimport { MAX_STORY_REVIEW_ATTEMPTS } from \"../shared/constants.js\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\nimport { reviewOutput, reviewPasses } from \"../shared/review-schema.js\";\nimport { type ReviewStoryImplementationInput, reviewStoryImplementationPrompt } from \"./prompt.js\";\n\nexport const reviewStoryImplementationStep = step({ id: \"review-story-implementation\" })\n .prompt<ReviewStoryImplementationInput, ReviewResult>(reviewStoryImplementationPrompt, {\n agent: \"reviewer\",\n output: reviewOutput,\n })\n .do(async (review, input) => {\n if (!reviewPasses(review)) {\n if (input.attempt >= MAX_STORY_REVIEW_ATTEMPTS) {\n return fail({\n code: \"story_review_exhausted\",\n message: `Story failed review ${MAX_STORY_REVIEW_ATTEMPTS} times in a row (last score ${review.score}/5).`,\n details: { review, storyPath: input.currentStory.path },\n });\n }\n\n return implementStoryStep({\n currentStory: input.currentStory,\n previousStoryReview: review,\n attempt: input.attempt + 1,\n });\n }\n\n return commitReviewedStoryStep({\n currentStory: input.currentStory,\n implementationSummary: input.implementationSummary,\n });\n });\n","import type { Document } from \"@trailstep/authoring\";\nimport { done, fail, state, step } from \"@trailstep/authoring\";\nimport type { ContinuationResult } from \"@trailstep/core\";\nimport { implementStoryStep } from \"../implement-story/step.js\";\nimport { extractStoryTitle, type TakeItAwayOutput } from \"../shared/output-schema.js\";\nimport {\n type ActiveStoryStartCommit,\n recordActiveStoryStartCommit,\n resetActiveStoryStartCommit,\n STORY_STATE_KEYS,\n} from \"../shared/story-state.js\";\nimport { runGit } from \"./run-git.js\";\n\nexport interface CommitReviewedStoryInput extends Record<string, unknown> {\n readonly currentStory: Document;\n readonly implementationSummary?: string;\n}\n\nexport const commitReviewedStoryStep = step({ id: \"commit-reviewed-story\" }).do(\n async (input: CommitReviewedStoryInput): Promise<ContinuationResult> => {\n const activeStory =\n (await state.get<Document | null>(STORY_STATE_KEYS.activeStory)) ?? input.currentStory;\n\n if (storyAutoCommitEnabled()) {\n const commitResult = await commitReviewedStoryChanges(\n activeStory,\n input.implementationSummary,\n );\n if (!commitResult.ok) {\n return fail({\n code: commitResult.code,\n message: commitResult.message,\n details: commitResult.details,\n });\n }\n }\n\n return completeReviewedStory(activeStory);\n },\n);\n\nfunction storyAutoCommitEnabled(): boolean {\n const mode = process.env.TRAILSTEP_STORY_COMMIT_MODE;\n return [\"1\", \"true\", \"enabled\", \"worktree\"].includes(mode?.toLowerCase() ?? \"\");\n}\n\nasync function commitReviewedStoryChanges(\n activeStory: Document,\n implementationSummary: string | undefined,\n): Promise<\n | { readonly ok: true }\n | {\n readonly ok: false;\n readonly code: string;\n readonly message: string;\n readonly details: Record<string, unknown>;\n }\n> {\n const cwd = state.cwd;\n if (!cwd) {\n return {\n ok: false,\n code: \"story_commit_missing_cwd\",\n message: \"Cannot commit reviewed story because the TrailStep workflow cwd is unavailable.\",\n details: { storyPath: activeStory.path },\n };\n }\n\n const insideWorkTree = await runGit([\"rev-parse\", \"--is-inside-work-tree\"], cwd);\n if (!insideWorkTree.ok || insideWorkTree.stdout !== \"true\") {\n return {\n ok: false,\n code: \"story_commit_not_git_worktree\",\n message:\n \"Cannot commit reviewed story because the workflow is not running inside a git worktree.\",\n details: {\n storyPath: activeStory.path,\n gitError: insideWorkTree.ok ? undefined : insideWorkTree.error,\n },\n };\n }\n\n const add = await runGit([\"add\", \"-A\"], cwd);\n if (!add.ok) {\n return {\n ok: false,\n code: \"story_commit_stage_failed\",\n message: \"Cannot commit reviewed story because `git add -A` failed.\",\n details: { storyPath: activeStory.path, gitError: add.error },\n };\n }\n\n const staged = await runGit([\"diff\", \"--cached\", \"--name-only\"], cwd);\n if (!staged.ok) {\n return {\n ok: false,\n code: \"story_commit_status_failed\",\n message: \"Cannot commit reviewed story because staged changes could not be inspected.\",\n details: { storyPath: activeStory.path, gitError: staged.error },\n };\n }\n\n if (staged.stdout.trim().length === 0) {\n const baseline = await state.get<ActiveStoryStartCommit | null>(\n STORY_STATE_KEYS.activeStoryStartCommit,\n );\n const head = await runGit([\"rev-parse\", \"HEAD\"], cwd);\n if (baseline?.commit && head.ok && head.stdout !== baseline.commit) {\n return { ok: true };\n }\n\n return {\n ok: false,\n code: \"story_commit_empty\",\n message:\n \"The story passed review, but there are no staged or already-committed changes since the story baseline to commit.\",\n details: {\n storyPath: activeStory.path,\n storyStartCommit: baseline?.commit,\n head: head.ok ? head.stdout : undefined,\n gitError: head.ok ? undefined : head.error,\n },\n };\n }\n\n const storyTitle = extractStoryTitle(activeStory.content, 1);\n const commit = await runGit(\n [\n \"commit\",\n \"-m\",\n truncateCommitSubject(`trailstep: ${storyTitle}`),\n \"-m\",\n commitBody(activeStory, implementationSummary, staged.stdout),\n ],\n cwd,\n );\n\n if (!commit.ok) {\n return {\n ok: false,\n code: \"story_commit_failed\",\n message: \"The story passed review, but TrailStep could not create the story commit.\",\n details: { storyPath: activeStory.path, gitError: commit.error },\n };\n }\n\n return { ok: true };\n}\n\nasync function completeReviewedStory(activeStory: Document): Promise<ContinuationResult> {\n const completed = (await state.get<string[]>(STORY_STATE_KEYS.completedStories)) ?? [];\n const updatedCompleted = [\n ...completed,\n extractStoryTitle(activeStory.content, completed.length + 1),\n ];\n await state.set(STORY_STATE_KEYS.completedStories, updatedCompleted);\n\n const storyQueue = (await state.get<Document[]>(STORY_STATE_KEYS.storyQueue)) ?? [];\n const [nextStory, ...remaining] = storyQueue;\n\n if (!nextStory) {\n await state.set(STORY_STATE_KEYS.activeStory, null);\n await resetActiveStoryStartCommit();\n const featureDoc = await state.get<Document>(\"featureDoc\");\n const implementationDoc = await state.get<Document>(\"implementationDoc\");\n const output: TakeItAwayOutput = {\n status: \"implemented\",\n featureDocPath: featureDoc?.path ?? \"\",\n implementationDocPath: implementationDoc?.path ?? \"\",\n storyCount: updatedCompleted.length,\n completedStories: updatedCompleted,\n summary: `Implemented and reviewed ${updatedCompleted.length} ${updatedCompleted.length === 1 ? \"story\" : \"stories\"}.`,\n };\n return done(output);\n }\n\n await state.set(STORY_STATE_KEYS.storyQueue, remaining);\n await state.set(STORY_STATE_KEYS.activeStory, nextStory);\n await resetActiveStoryStartCommit();\n await recordActiveStoryStartCommit();\n return implementStoryStep({ currentStory: nextStory, attempt: 1 });\n}\n\nfunction truncateCommitSubject(subject: string): string {\n return subject.length <= 72 ? subject : `${subject.slice(0, 69)}...`;\n}\n\nfunction commitBody(\n activeStory: Document,\n implementationSummary: string | undefined,\n stagedFiles: string,\n): string {\n return [\n \"Committed automatically by TrailStep after a passing story review.\",\n \"\",\n `Story artifact: ${activeStory.path}`,\n \"\",\n \"Implementer summary:\",\n implementationSummary?.trim() || \"Not provided.\",\n \"\",\n \"Staged files:\",\n stagedFiles\n .split(\"\\n\")\n .filter((file) => file.length > 0)\n .map((file) => `- ${file}`)\n .join(\"\\n\"),\n ].join(\"\\n\");\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport { state } from \"@trailstep/authoring\";\n\nconst execFileAsync = promisify(execFile);\n\nexport const STORY_STATE_KEYS = {\n activeStory: \"activeStory\",\n activeStoryStartCommit: \"activeStoryStartCommit\",\n completedStories: \"completedStories\",\n storyQueue: \"storyQueue\",\n} as const;\n\nexport interface ActiveStoryStartCommit {\n readonly commit?: string;\n readonly warning?: string;\n}\n\nexport interface StoryReviewGitContext {\n readonly storyStartCommit?: string;\n readonly statusShort?: string;\n readonly committedDiff?: string;\n readonly uncommittedDiff?: string;\n readonly warnings: readonly string[];\n}\n\nasync function runGit(\n args: readonly string[],\n cwd: string,\n): Promise<\n { readonly ok: true; readonly stdout: string } | { readonly ok: false; readonly error: string }\n> {\n try {\n const { stdout } = await execFileAsync(\"git\", [...args], {\n cwd,\n maxBuffer: 1024 * 1024 * 10,\n });\n return { ok: true, stdout: stdout.trimEnd() };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { ok: false, error: message };\n }\n}\n\nexport async function recordActiveStoryStartCommit(): Promise<ActiveStoryStartCommit> {\n const existing = await state.get<ActiveStoryStartCommit | null>(\n STORY_STATE_KEYS.activeStoryStartCommit,\n );\n if (existing?.commit || existing?.warning) {\n return existing;\n }\n\n const cwd = state.cwd;\n if (!cwd) {\n const missingCwd = {\n warning:\n \"Workflow cwd is unavailable; the story reviewer cannot verify committed story changes from a durable git baseline.\",\n };\n await state.set(STORY_STATE_KEYS.activeStoryStartCommit, missingCwd);\n return missingCwd;\n }\n\n const result = await runGit([\"rev-parse\", \"HEAD\"], cwd);\n if (!result.ok || result.stdout.length === 0) {\n const missingGitBaseline = {\n warning: `Unable to record story start commit with \\`git rev-parse HEAD\\`: ${result.ok ? \"no commit was returned\" : result.error}`,\n };\n await state.set(STORY_STATE_KEYS.activeStoryStartCommit, missingGitBaseline);\n return missingGitBaseline;\n }\n\n const baseline = { commit: result.stdout };\n await state.set(STORY_STATE_KEYS.activeStoryStartCommit, baseline);\n return baseline;\n}\n\nexport async function resetActiveStoryStartCommit(): Promise<void> {\n await state.set(STORY_STATE_KEYS.activeStoryStartCommit, null);\n}\n\nexport async function loadStoryReviewGitContext(): Promise<StoryReviewGitContext> {\n const baseline = await state.get<ActiveStoryStartCommit | null>(\n STORY_STATE_KEYS.activeStoryStartCommit,\n );\n const warnings: string[] = [];\n\n if (baseline?.warning) {\n warnings.push(baseline.warning);\n }\n\n const cwd = state.cwd;\n if (!cwd) {\n warnings.push(\n \"Workflow cwd is unavailable; reviewer must treat committed story-change context as missing.\",\n );\n return { storyStartCommit: baseline?.commit, warnings };\n }\n\n const status = await runGit([\"status\", \"--short\"], cwd);\n if (!status.ok) {\n warnings.push(`Unable to inspect \\`git status --short\\`: ${status.error}`);\n }\n\n const uncommittedDiff = await runGit([\"diff\"], cwd);\n if (!uncommittedDiff.ok) {\n warnings.push(\n `Unable to inspect uncommitted changes with \\`git diff\\`: ${uncommittedDiff.error}`,\n );\n }\n\n const storyStartCommit = baseline?.commit;\n let committedDiff: string | undefined;\n if (!storyStartCommit) {\n warnings.push(\n \"No durable story start commit is recorded; reviewer must not silently review only the current working tree diff.\",\n );\n } else {\n const baselineReachable = await runGit([\"cat-file\", \"-e\", `${storyStartCommit}^{commit}`], cwd);\n if (!baselineReachable.ok) {\n warnings.push(\n `Recorded story start commit \\`${storyStartCommit}\\` is invalid or unreachable: ${baselineReachable.error}`,\n );\n } else {\n const committed = await runGit([\"diff\", `${storyStartCommit}..HEAD`], cwd);\n if (!committed.ok) {\n warnings.push(\n `Unable to inspect committed story changes with \\`git diff ${storyStartCommit}..HEAD\\`: ${committed.error}`,\n );\n } else {\n committedDiff = committed.stdout;\n }\n }\n }\n\n return {\n storyStartCommit,\n statusShort: status.ok ? status.stdout : undefined,\n committedDiff,\n uncommittedDiff: uncommittedDiff.ok ? uncommittedDiff.stdout : undefined,\n warnings,\n };\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type GitResult =\n | { readonly ok: true; readonly stdout: string }\n | { readonly ok: false; readonly error: string };\n\nexport async function runGit(args: readonly string[], cwd: string): Promise<GitResult> {\n try {\n const { stdout } = await execFileAsync(\"git\", [...args], {\n cwd,\n maxBuffer: 1024 * 1024 * 10,\n });\n return { ok: true, stdout: stdout.trimEnd() };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { ok: false, error: message };\n }\n}\n","import type { Document } from \"@trailstep/authoring\";\nimport { loadFragments, promptSections, section } from \"@trailstep/authoring\";\nimport type { StoryReviewGitContext } from \"../shared/story-state.js\";\n\nconst fragments = loadFragments(import.meta.dirname, {\n methodology: \"../shared/feature-methodology.md\",\n storyContract: \"../shared/story-implementation-contract.md\",\n});\n\nexport interface ReviewStoryImplementationInput extends Record<string, unknown> {\n readonly currentStory: Document;\n readonly attempt: number;\n readonly implementationSummary?: string;\n readonly gitContext: StoryReviewGitContext;\n}\n\nexport function reviewStoryImplementationPrompt({\n input,\n}: {\n readonly input: ReviewStoryImplementationInput;\n}): string {\n const committedDiffCommand = input.gitContext.storyStartCommit\n ? `git diff ${input.gitContext.storyStartCommit}..HEAD`\n : \"git diff <missing-story-start-commit>..HEAD\";\n\n return promptSections(\n fragments.methodology,\n fragments.storyContract,\n section(\"Story\", input.currentStory.content),\n section(\"Implementer summary\", input.implementationSummary ?? \"Not provided.\"),\n section(\n \"Story review git baseline\",\n [\n `Recorded story start commit: ${input.gitContext.storyStartCommit ?? \"MISSING\"}`,\n `Inspect committed story changes with: \\`${committedDiffCommand}\\``,\n \"Inspect uncommitted working tree changes with: `git diff`\",\n \"Inspect status with: `git status --short`\",\n input.gitContext.warnings.length > 0\n ? [\n \"\",\n \"Warnings / blocked context:\",\n ...input.gitContext.warnings.map((warning) => `- ${warning}`),\n ].join(\"\\n\")\n : \"\",\n ]\n .filter((line) => line.length > 0)\n .join(\"\\n\"),\n ),\n section(\n \"Committed story changes (`git diff <storyStartCommit>..HEAD`)\",\n input.gitContext.committedDiff ?? \"Not available.\",\n ),\n section(\n \"Uncommitted working tree changes (`git diff`)\",\n input.gitContext.uncommittedDiff ?? \"Not available.\",\n ),\n section(\n \"Working tree status (`git status --short`)\",\n input.gitContext.statusShort ?? \"Not available.\",\n ),\n section(\n \"Task\",\n \"Review only the active story slice represented by the recorded story start commit through HEAD, plus the current uncommitted working tree changes, against the story above and the implementer summary. Prefer the supplied diff/status sections; if you need to inspect locally, use read-only commands only (`git status --short`, the listed `git diff <storyStartCommit>..HEAD`, and `git diff`) — do not run tests, edit code, revert files, clean files, or try to isolate the diff by changing the repository. If unrelated dirty files, a missing/invalid baseline, or ambiguous context prevents a trustworthy review, say so in the structured review and require the implementer/workflow to fix the isolation; never remove changes yourself. Respond only with the structured review.\",\n ),\n );\n}\n","import {\n type Document,\n jsonSchema,\n list,\n loadFragments,\n promptSections,\n section,\n} from \"@trailstep/authoring\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\n\nconst fragments = loadFragments(import.meta.dirname, {\n methodology: \"../shared/feature-methodology.md\",\n architectureGuidance: \"../shared/project-architecture-guidance.md\",\n storyContract: \"../shared/story-implementation-contract.md\",\n});\n\nexport interface ImplementStoryInput extends Record<string, unknown> {\n readonly currentStory: Document;\n readonly attempt: number;\n readonly previousStoryReview?: ReviewResult;\n}\n\nexport interface ImplementStoryOutput extends Record<string, unknown> {\n readonly blocked: boolean;\n readonly blockedReason?: string;\n readonly summary: string;\n}\n\nexport const implementStoryOutput = jsonSchema<ImplementStoryOutput>({\n type: \"object\",\n properties: {\n blocked: { type: \"boolean\" },\n blockedReason: { type: \"string\" },\n summary: {\n type: \"string\",\n description: \"Files changed, commands run, and their results.\",\n },\n },\n required: [\"blocked\", \"summary\"],\n additionalProperties: false,\n});\n\nexport function implementStoryPrompt({ input }: { readonly input: ImplementStoryInput }): string {\n const taskBody =\n input.previousStoryReview === undefined\n ? \"Implement this story.\"\n : promptSections(\n `This is retry attempt ${input.attempt} for this story. A previous review scored the implementation ${input.previousStoryReview.score}/5: ${input.previousStoryReview.summary}`,\n `Required improvements to address, without discarding what already works:\\n\\n${list(input.previousStoryReview.requiredImprovements)}`,\n );\n\n return promptSections(\n fragments.methodology,\n fragments.architectureGuidance,\n fragments.storyContract,\n section(\"Story\", input.currentStory.content),\n section(\n \"Task\",\n `${taskBody}\\n\\nSet \\`blocked: true\\` with a clear \\`blockedReason\\` instead of guessing or pretending the story is complete. Otherwise set \\`blocked: false\\` and use \\`summary\\` to report files changed, commands run, and their results.`,\n ),\n );\n}\n","import type { Document } from \"@trailstep/authoring\";\nimport { list, loadFragments, promptSections, section } from \"@trailstep/authoring\";\n\nconst fragments = loadFragments(import.meta.dirname, {\n methodology: \"../shared/feature-methodology.md\",\n implementationDocFormat: \"../shared/implementation-doc-format.md\",\n});\n\nexport interface ReviewImplementationDocInput extends Record<string, unknown> {\n readonly featureDoc: Document;\n readonly implementationDoc: Document;\n readonly attempt: number;\n}\n\nexport function reviewImplementationDocPrompt({\n input,\n}: {\n readonly input: ReviewImplementationDocInput;\n}): string {\n const reviewCriteria = list([\n \"traceability to the feature doc\",\n \"strict behavioral-red TDD story design\",\n \"vertical slices rather than horizontal tasks\",\n \"a clear tracer-bullet strategy\",\n \"hard dependency labels and topological ordering\",\n \"acceptance criteria and validation commands\",\n \"story instructions self-contained enough for an implementer who will only see one story plus the prepended shared context at a time\",\n \"correct use of balanced `<context>` ... `</context>` blocks for shared implementer context\",\n \"correct use of the `<!-- trailstep-story-boundary -->` marker between stories, and that no story-critical detail lives only in non-context overview text above the first marker\",\n ]);\n\n return promptSections(\n fragments.methodology,\n fragments.implementationDocFormat,\n section(\"Feature doc\", input.featureDoc.content),\n section(\"Implementation doc under review\", input.implementationDoc.content),\n section(\n \"Task\",\n `Critically review the implementation doc above against the feature doc and the methodology. Review for:\\n\\n${reviewCriteria}\\n\\nDo not edit the implementation doc. Respond only with the structured review.`,\n ),\n );\n}\n","import type { Document } from \"@trailstep/authoring\";\nimport { list, loadFragments, promptSections, section } from \"@trailstep/authoring\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\n\nconst fragments = loadFragments(import.meta.dirname, {\n methodology: \"../shared/feature-methodology.md\",\n architectureGuidance: \"../shared/project-architecture-guidance.md\",\n implementationDocFormat: \"../shared/implementation-doc-format.md\",\n});\n\nexport interface CreateOrImproveImplementationDocInput extends Record<string, unknown> {\n readonly featureDoc: Document;\n readonly previousReview?: ReviewResult;\n readonly attempt: number;\n}\n\nexport function createOrImproveImplementationDocPrompt({\n input,\n}: {\n readonly input: CreateOrImproveImplementationDocInput;\n}): string {\n const taskBody =\n input.previousReview === undefined\n ? \"Create `implementation-doc.md` from the feature doc above, following the format exactly enough that stories can later be split mechanically on the `<!-- trailstep-story-boundary -->` marker and shared context can be prepended from balanced `<context>` blocks.\"\n : promptSections(\n `This is improvement attempt ${input.attempt}. A previous review scored this plan ${input.previousReview.score}/5: ${input.previousReview.summary}`,\n `Required improvements to address, without discarding what already works:\\n\\n${list(input.previousReview.requiredImprovements)}`,\n );\n\n return promptSections(\n fragments.methodology,\n fragments.architectureGuidance,\n fragments.implementationDocFormat,\n section(\"Feature doc\", input.featureDoc.content),\n section(\n \"Task\",\n `${taskBody}\\n\\nDesign stories around strict behavioral-red TDD, vertical slicing, tracer-bullet methodology, and hard dependency labels only. Topologically order stories by dependency. Put shared implementation details in balanced \\`<context>\\` ... \\`</context>\\` blocks so split-stories prepends them to every story; repeat details inside individual stories when only selected stories need them. Write every story as implementation-ready instructions for an implementer who will only see that story plus the prepended context.`,\n ),\n );\n}\n","import { loadFragments, promptSections, section } from \"@trailstep/authoring\";\nimport type { TakeItAwayInput } from \"../shared/input-schema.js\";\n\nconst fragments = loadFragments(import.meta.dirname, {\n methodology: \"../shared/feature-methodology.md\",\n featureDocFormat: \"../shared/feature-doc-format.md\",\n});\n\nexport function createFeatureDocPrompt({ input }: { readonly input: TakeItAwayInput }): string {\n return promptSections(\n fragments.methodology,\n fragments.featureDocFormat,\n section(\"Conversation / feature request\", input.conversation),\n section(\n \"Task\",\n 'Write `feature-doc.md` following the format above, based on the conversation/request. Make it detailed enough that another agent can plan implementation without reading the original conversation. Preserve uncertainty explicitly in \"Open Questions and Assumptions\" — do not invent missing product decisions.',\n ),\n );\n}\n","import { shape } from \"@trailstep/authoring\";\n\nexport interface TakeItAwayInput extends Record<string, unknown> {\n readonly conversation: string;\n}\n\nexport const takeItAwayInput = shape<TakeItAwayInput>({ conversation: \"string\" });\n","import { promptSections, section } from \"@trailstep/authoring\";\n\nexport function grillPrompt(): string {\n return promptSections(\n section(\n \"Role\",\n \"You are the interactive front door for starting a new TrailStep feature. Open by asking the user what they want to build.\",\n ),\n section(\n \"Task\",\n \"Keep asking follow-up questions until you are confident you understand the feature request well enough to hand off to a planning agent. There is no fixed checklist of required topics — use your judgment, and do not end the conversation prematurely just to finish quickly.\",\n ),\n section(\n \"Output\",\n \"Your structured output's `conversation` field must contain the full raw transcript of the conversation so far, not a summary. Preserve as much of the actual back-and-forth as possible.\",\n ),\n );\n}\n","import { defineWorkflow } from \"@trailstep/authoring\";\nimport { createFeatureDocStep } from \"../feature-implementation/create-feature-doc/step.js\";\nimport { takeItAwayInput } from \"../feature-implementation/shared/input-schema.js\";\nimport { takeItAwayOutput } from \"../feature-implementation/shared/output-schema.js\";\n\nexport type { TakeItAwayInput } from \"../feature-implementation/shared/input-schema.js\";\n\nexport const takeItAway = defineWorkflow({\n id: \"take-it-away\",\n description:\n \"Turns an already-organic conversation/feature request into a reviewed implementation plan, then implements it story by story.\",\n inputShape: takeItAwayInput,\n outputShape: takeItAwayOutput,\n agents: {\n featureWriter: {\n size: \"medium\",\n thinking: \"medium\",\n description: \"Turns a conversation/feature request into a standalone feature doc.\",\n },\n planner: {\n size: \"large\",\n thinking: \"high\",\n description:\n \"Creates or improves the implementation doc: architecture-aware, TDD/vertical-slice/tracer-bullet story design.\",\n },\n reviewer: {\n size: \"large\",\n thinking: \"high\",\n description: \"Reviews isolated implementation docs and story diffs against methodology.\",\n },\n implementer: {\n size: \"medium\",\n thinking: \"medium\",\n description: \"Implements one story at a time using strict behavioral-red TDD.\",\n },\n },\n start(input) {\n return createFeatureDocStep(input);\n },\n});\n"],"mappings":"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","names":["shape","step","Document","state","step","state","step","fail","step","jsonSchema","jsonSchema","fail","state","step","fail","step","fail","step","state","execFile","promisify","execFileAsync","runGit","state","runGit","step","fail","jsonSchema","loadFragments","promptSections","section","fragments","step","fail","step","fail","state","list","loadFragments","promptSections","section","fragments","step","fail","list","loadFragments","promptSections","section","fragments","step","state","loadFragments","promptSections","section","fragments","step","Document","state","promptSections","section","step","shape","defineWorkflow","defineWorkflow"]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@trailstep/create-flows",
3
+ "version": "0.1.0",
4
+ "description": "Public reusable general-purpose TrailStep workflows.",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+ssh://git@github.com/chily-john/trailstep.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/chily-john/trailstep/issues"
13
+ },
14
+ "homepage": "https://github.com/chily-john/trailstep#readme",
15
+ "keywords": [
16
+ "trailstep-workflow"
17
+ ],
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ }
25
+ },
26
+ "dependencies": {
27
+ "@trailstep/authoring": "0.1.0"
28
+ },
29
+ "devDependencies": {
30
+ "@biomejs/biome": "^2.1.1",
31
+ "@types/node": "^26.1.1",
32
+ "tsup": "^8.5.0",
33
+ "typescript": "^5.8.3",
34
+ "vitest": "^3.2.4",
35
+ "@trailstep/core": "0.1.0"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "peerDependencies": {
46
+ "@trailstep/authoring": "^0.1.0"
47
+ },
48
+ "scripts": {
49
+ "build": "tsup src/index.ts --format esm --dts --sourcemap --clean",
50
+ "typecheck": "tsc --noEmit -p tsconfig.json",
51
+ "test": "vitest run",
52
+ "lint": "biome check src"
53
+ }
54
+ }