@trailstep/create-flows 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +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/shared/feature-methodology.md","../src/feature-implementation/shared/story-implementation-contract.md","../src/feature-implementation/implement-story/prompt.ts","../src/feature-implementation/shared/project-architecture-guidance.md","../src/feature-implementation/review-implementation-doc/prompt.ts","../src/feature-implementation/shared/implementation-doc-format.md","../src/feature-implementation/create-or-improve-implementation-doc/prompt.ts","../src/feature-implementation/create-feature-doc/prompt.ts","../src/feature-implementation/shared/feature-doc-format.md","../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 { promptSections, section } from \"@trailstep/authoring\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport storyImplementationContractFragment from \"../shared/story-implementation-contract.md?raw\";\nimport type { StoryReviewGitContext } from \"../shared/story-state.js\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n storyContract: storyImplementationContractFragment.trimEnd(),\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","# Feature workflow methodology\n\n## Planning principles\n\n- Start from observable behavior and user value.\n- Preserve uncertainty explicitly; do not invent missing product decisions.\n- Prefer the smallest vertical slice that proves a complete path through the system.\n- Use tracer bullets to de-risk integration seams early with thin end-to-end behavior.\n- Every implementation story must begin with a behavioral red test that fails for the right reason.\n- The green phase should add only enough production code to pass the focused red test.\n- Refactor only after focused tests pass, and keep refactors scoped to the feature.\n- Dependencies are hard dependencies only: story B depends on story A when B cannot pass its own tests until A is complete.\n\n## Review scoring\n\nScore on a 1-5 integer scale:\n\n- 5: excellent; strongly aligned with TDD, vertical slicing, tracer-bullet risk reduction, dependency clarity, and local architecture.\n- 4: good; acceptable with only minor non-blocking improvements.\n- 3: incomplete; useful but needs material changes before continuing.\n- 2: poor; misses core methodology or important requirements.\n- 1: unusable; unsafe, incoherent, or not traceable to the feature.\n\nScores of 4 or 5 pass. Scores below 4 must list specific `requiredImprovements` so the next attempt can address them directly.\n","# Story implementation contract\n\nThe story loop works one story at a time. Each story is self-contained. You will not see non-context overview text or other stories; you will see only the active story plus any shared `<context>` content prepended by the split-stories step.\n\n## Protect pre-existing uncommitted work\n\nRun `git status --short` before making any change.\n\n- The preferred execution mode is a TrailStep-created isolated worktree/branch. In that mode, a successful review is followed by an automatic story commit, so the next story starts from a clean diff boundary.\n- Treat every pre-existing uncommitted file as protected — it may be unfinished human work, another run's in-progress work, or a sign that isolation failed.\n- Do not run destructive cleanup: no `git reset`, `git checkout --`, broad `git clean`, or equivalent revert/format-away operations.\n- Do not delete or rewrite unrelated chunks in a file that already has changes.\n- If this story requires editing a file that is already dirty, preserve the existing changes and make only the minimal additional change the story requires.\n- If dirty work makes the story ambiguous or blocked, stop and report a blocked state instead of removing it.\n- Do not create git commits yourself unless the story explicitly requires it. TrailStep creates the reviewed story commit after the reviewer passes the story when auto-commit mode is enabled.\n\n## Implementer responsibilities\n\n- Implement only the current story and required dependency-compatible adjustments. Do not start later stories.\n- Use strict behavioral-red TDD: write or update a focused failing behavioral test first, confirm it fails for the intended reason when feasible, implement the smallest change to pass it, then refactor only after it's green.\n- Run the story's validation commands before reporting completion when feasible.\n- Do not report success until implementation and focused validation are done, or until a true blocked state is reached — report the blocker clearly instead of pretending the story is complete.\n\n## Reviewer responsibilities\n\n- Review only the active story diff from the recorded story baseline through HEAD plus the current uncommitted diff. Do not try to review every dirty change in the checkout as global context.\n- Inspect with read-only commands only (`git status --short`, the exact `git diff <storyStartCommit>..HEAD` command supplied in your prompt, and `git diff`). Do not run tests or other commands — the implementer is responsible for passing focused validation; this is an AI-only review.\n- Never edit code, delete files, revert files, run cleanup, stage files, commit files, or otherwise modify the working tree to isolate your review.\n- If unrelated dirty files, missing baseline information, or overlapping changes make the active story diff unreviewable, return a failing structured review that explains the isolation problem instead of changing the repository.\n- Review against: the story's acceptance criteria, TDD evidence and test quality, vertical-slice completeness, tracer-bullet alignment where applicable, minimal scope with no gold-plating, and integration with existing architecture/project conventions.\n\n## Completion\n\nA story is complete when code is changed as needed, behavioral tests exist, focused validation passes according to the implementer, and the implementation is well integrated with the existing architecture.\n","import { type Document, jsonSchema, list, promptSections, section } from \"@trailstep/authoring\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport projectArchitectureGuidanceFragment from \"../shared/project-architecture-guidance.md?raw\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\nimport storyImplementationContractFragment from \"../shared/story-implementation-contract.md?raw\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n architectureGuidance: projectArchitectureGuidanceFragment.trimEnd(),\n storyContract: storyImplementationContractFragment.trimEnd(),\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","# Architecture awareness\n\nBefore naming files, choosing package/module boundaries, picking integration seams, or ordering stories/dependencies, ground the decision in the target project's own conventions rather than inventing structure:\n\n- Look for and read the project's own architecture/convention docs at its root and nearby — `CLAUDE.md`, `AGENTS.md`, `.pi/rules/`, ADRs, architecture docs, or an equivalent README section.\n- Prefer existing module/package boundaries, naming conventions, and file layout patterns already established in the project over introducing new ones.\n- When the project's own guidance is silent or ambiguous on a non-trivial integration choice, say so explicitly as an assumption rather than silently picking one convention over another.\n","import type { Document } from \"@trailstep/authoring\";\nimport { list, promptSections, section } from \"@trailstep/authoring\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport implementationDocFormatFragment from \"../shared/implementation-doc-format.md?raw\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n implementationDocFormat: implementationDocFormatFragment.trimEnd(),\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","# Implementation doc format\n\n`implementation-doc.md` converts `feature-doc.md` into implementation-ready stories.\n\nUse this structure:\n\n```markdown\n# Implementation Plan: <Feature Name>\n\n## Overview for planner/reviewer\n\nOptional high-level planning notes that do not need to be seen by story implementers.\n\n<context>\n\n## Shared Implementation Context\n\nPut every cross-story detail that an implementer may need here: outcome and constraints, architecture/integration notes, tracer-bullet strategy, repository conventions, shared validation commands, edge cases, assumptions, and hard dependency graph notes.\n\nAnything inside this balanced `<context>` block is prepended programmatically to every story by the split-stories step.\n\n</context>\n\n<!-- trailstep-story-boundary -->\n\n### Story 001: <title>\n\nDependencies: none\n\n#### Goal\n\n#### User-Visible / Integration-Visible Slice\n\n#### Acceptance Criteria\n\n#### Red Phase\n\n- Test file:\n- Test case:\n- Expected failing assertion:\n\n#### Green Phase\n\n#### Refactor Phase\n\n#### Validation Commands\n\n#### Notes for Implementer\n\n<!-- trailstep-story-boundary -->\n\n### Story 002: <title>\n\nDependencies: Story 001\n\n...\n```\n\nRules:\n\n- Text above the first `<!-- trailstep-story-boundary -->` is never read by an implementer unless it is inside a balanced `<context>` ... `</context>` block. The split-stories step prepends all context blocks to every story.\n- If a detail applies to most/all stories, put it in `<context>`; if it applies only to selected stories, repeat it inside those stories. No story-critical detail may live only in non-context overview text.\n- Every `<context>` marker must have a matching `</context>` marker, and context blocks should be outside story bodies unless there is a deliberate reason to prepend that block to every story.\n- Every story must start right after a `<!-- trailstep-story-boundary -->` line, on its own line, with nothing else on that line. Splitting is mechanical and depends on this exact marker — do not use markdown headings alone to separate stories, and do not add or omit a boundary marker except between/before stories.\n- Stories must be topologically ordered.\n- Every story must be implementation-ready and self-contained, written as instructions to an implementer who will not see this file, only their own story's content.\n- Avoid horizontal stories unless they are embedded in an observable vertical slice.\n- Name concrete files/tests/commands when they can be inferred from the repository.\n- Preserve uncertainty as assumptions or blocked states instead of guessing.\n","import type { Document } from \"@trailstep/authoring\";\nimport { list, promptSections, section } from \"@trailstep/authoring\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport implementationDocFormatFragment from \"../shared/implementation-doc-format.md?raw\";\nimport projectArchitectureGuidanceFragment from \"../shared/project-architecture-guidance.md?raw\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n architectureGuidance: projectArchitectureGuidanceFragment.trimEnd(),\n implementationDocFormat: implementationDocFormatFragment.trimEnd(),\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 { promptSections, section } from \"@trailstep/authoring\";\nimport featureDocFormatFragment from \"../shared/feature-doc-format.md?raw\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport type { TakeItAwayInput } from \"../shared/input-schema.js\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n featureDocFormat: featureDocFormatFragment.trimEnd(),\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","# Feature doc format\n\n`feature-doc.md` is an intermediate product-quality feature description used as input to implementation planning.\n\nUse this structure:\n\n```markdown\n# <Feature Name>\n\n## Outcome\n\n## Users / Jobs / Pain\n\n## Proposed Behavior\n\n## Non-Goals\n\n## Examples and Acceptance Criteria\n\n## Edge Cases and Failure Modes\n\n## Affected Areas and Integration Points\n\n## Testing Expectations\n\n## Documentation / Migration / Rollout Notes\n\n## Open Questions and Assumptions\n```\n\nThe document should be detailed enough that another agent can plan implementation without reading the original conversation, while still preserving important uncertainty.\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 feature in the current project. 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":";AAAA,SAAS,gBAAgB,SAAAA,cAAa;;;ACAtC,SAAS,kBAAkB;AAWpB,IAAM,mBAAmB,WAA6B;AAAA,EAC3D,MAAM;AAAA,EACN,YAAY;AAAA,IACV,QAAQ,EAAE,MAAM,UAAU,OAAO,cAAc;AAAA,IAC/C,gBAAgB,EAAE,MAAM,SAAS;AAAA,IACjC,uBAAuB,EAAE,MAAM,SAAS;AAAA,IACxC,YAAY,EAAE,MAAM,SAAS;AAAA,IAC7B,kBAAkB,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,IAC7D,SAAS,EAAE,MAAM,SAAS;AAAA,EAC5B;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,sBAAsB;AACxB,CAAC;AAEM,SAAS,kBAAkB,cAAsB,eAA+B;AACrF,QAAM,UAAU,mBAAmB,KAAK,YAAY;AACpD,SAAO,UAAU,CAAC,GAAG,KAAK,KAAK,SAAS,aAAa;AACvD;;;ACnCA,SAAS,QAAAC,aAAY;;;ACArB,SAAS,YAAAC,WAAU,SAAAC,QAAO,QAAAC,aAAY;;;ACAtC,SAAS,UAAU,SAAAC,QAAO,QAAAC,aAAY;;;ACAtC,SAAS,QAAAC,OAAM,QAAAC,aAAY;;;ACApB,IAAM,iBAAiB;AAEvB,IAAM,sBAAsB;AAE5B,IAAM,oBAAoB;AAE1B,IAAM,wBAAwB;AAE9B,IAAM,yCAAyC;AAE/C,IAAM,4BAA4B;;;ACVzC,SAAS,cAAAC,mBAAkB;AAmB3B,IAAM,gBAAgB,EAAE,MAAM,WAAW,SAAS,GAAG,SAAS,EAAE;AAEzD,IAAM,eAAeC,YAAyB;AAAA,EACnD,MAAM;AAAA,EACN,YAAY;AAAA,IACV,OAAO;AAAA,IACP,SAAS,EAAE,MAAM,SAAS;AAAA,IAC1B,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,YAAY;AAAA,QACV,KAAK;AAAA,QACL,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,cAAc;AAAA,QACd,cAAc;AAAA,MAChB;AAAA,MACA,UAAU,CAAC,OAAO,mBAAmB,gBAAgB,gBAAgB,cAAc;AAAA,MACnF,sBAAsB;AAAA,IACxB;AAAA,IACA,sBAAsB,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,EACnE;AAAA,EACA,UAAU,CAAC,SAAS,WAAW,sBAAsB,sBAAsB;AAAA,EAC3E,sBAAsB;AACxB,CAAC;AAEM,SAAS,aAAa,QAA+B;AAC1D,SAAO,OAAO,SAAS;AACzB;;;AC9CA,SAAwB,UAAU,QAAAC,OAAM,SAAAC,QAAO,QAAAC,aAAY;;;ACA3D,SAAS,QAAAC,OAAM,QAAAC,aAAY;;;ACA3B,SAAS,QAAAC,OAAM,QAAAC,aAAY;;;ACC3B,SAAS,MAAM,MAAM,SAAAC,QAAO,YAAY;;;ACDxC,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAE1B,SAAS,aAAa;AAEtB,IAAM,gBAAgB,UAAU,QAAQ;AAEjC,IAAM,mBAAmB;AAAA,EAC9B,aAAa;AAAA,EACb,wBAAwB;AAAA,EACxB,kBAAkB;AAAA,EAClB,YAAY;AACd;AAeA,eAAe,OACb,MACA,KAGA;AACA,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,CAAC,GAAG,IAAI,GAAG;AAAA,MACvD;AAAA,MACA,WAAW,OAAO,OAAO;AAAA,IAC3B,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,QAAQ,OAAO,QAAQ,EAAE;AAAA,EAC9C,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO,EAAE,IAAI,OAAO,OAAO,QAAQ;AAAA,EACrC;AACF;AAEA,eAAsB,+BAAgE;AACpF,QAAM,WAAW,MAAM,MAAM;AAAA,IAC3B,iBAAiB;AAAA,EACnB;AACA,MAAI,UAAU,UAAU,UAAU,SAAS;AACzC,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,MAAM;AAClB,MAAI,CAAC,KAAK;AACR,UAAM,aAAa;AAAA,MACjB,SACE;AAAA,IACJ;AACA,UAAM,MAAM,IAAI,iBAAiB,wBAAwB,UAAU;AACnE,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,MAAM,OAAO,CAAC,aAAa,MAAM,GAAG,GAAG;AACtD,MAAI,CAAC,OAAO,MAAM,OAAO,OAAO,WAAW,GAAG;AAC5C,UAAM,qBAAqB;AAAA,MACzB,SAAS,oEAAoE,OAAO,KAAK,2BAA2B,OAAO,KAAK;AAAA,IAClI;AACA,UAAM,MAAM,IAAI,iBAAiB,wBAAwB,kBAAkB;AAC3E,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,EAAE,QAAQ,OAAO,OAAO;AACzC,QAAM,MAAM,IAAI,iBAAiB,wBAAwB,QAAQ;AACjE,SAAO;AACT;AAEA,eAAsB,8BAA6C;AACjE,QAAM,MAAM,IAAI,iBAAiB,wBAAwB,IAAI;AAC/D;AAEA,eAAsB,4BAA4D;AAChF,QAAM,WAAW,MAAM,MAAM;AAAA,IAC3B,iBAAiB;AAAA,EACnB;AACA,QAAM,WAAqB,CAAC;AAE5B,MAAI,UAAU,SAAS;AACrB,aAAS,KAAK,SAAS,OAAO;AAAA,EAChC;AAEA,QAAM,MAAM,MAAM;AAClB,MAAI,CAAC,KAAK;AACR,aAAS;AAAA,MACP;AAAA,IACF;AACA,WAAO,EAAE,kBAAkB,UAAU,QAAQ,SAAS;AAAA,EACxD;AAEA,QAAM,SAAS,MAAM,OAAO,CAAC,UAAU,SAAS,GAAG,GAAG;AACtD,MAAI,CAAC,OAAO,IAAI;AACd,aAAS,KAAK,6CAA6C,OAAO,KAAK,EAAE;AAAA,EAC3E;AAEA,QAAM,kBAAkB,MAAM,OAAO,CAAC,MAAM,GAAG,GAAG;AAClD,MAAI,CAAC,gBAAgB,IAAI;AACvB,aAAS;AAAA,MACP,4DAA4D,gBAAgB,KAAK;AAAA,IACnF;AAAA,EACF;AAEA,QAAM,mBAAmB,UAAU;AACnC,MAAI;AACJ,MAAI,CAAC,kBAAkB;AACrB,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,oBAAoB,MAAM,OAAO,CAAC,YAAY,MAAM,GAAG,gBAAgB,WAAW,GAAG,GAAG;AAC9F,QAAI,CAAC,kBAAkB,IAAI;AACzB,eAAS;AAAA,QACP,iCAAiC,gBAAgB,iCAAiC,kBAAkB,KAAK;AAAA,MAC3G;AAAA,IACF,OAAO;AACL,YAAM,YAAY,MAAM,OAAO,CAAC,QAAQ,GAAG,gBAAgB,QAAQ,GAAG,GAAG;AACzE,UAAI,CAAC,UAAU,IAAI;AACjB,iBAAS;AAAA,UACP,6DAA6D,gBAAgB,aAAa,UAAU,KAAK;AAAA,QAC3G;AAAA,MACF,OAAO;AACL,wBAAgB,UAAU;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,aAAa,OAAO,KAAK,OAAO,SAAS;AAAA,IACzC;AAAA,IACA,iBAAiB,gBAAgB,KAAK,gBAAgB,SAAS;AAAA,IAC/D;AAAA,EACF;AACF;;;AC9IA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,aAAAC,kBAAiB;AAE1B,IAAMC,iBAAgBD,WAAUD,SAAQ;AAMxC,eAAsBG,QAAO,MAAyB,KAAiC;AACrF,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAMD,eAAc,OAAO,CAAC,GAAG,IAAI,GAAG;AAAA,MACvD;AAAA,MACA,WAAW,OAAO,OAAO;AAAA,IAC3B,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,QAAQ,OAAO,QAAQ,EAAE;AAAA,EAC9C,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO,EAAE,IAAI,OAAO,OAAO,QAAQ;AAAA,EACrC;AACF;;;AFFO,IAAM,0BAA0B,KAAK,EAAE,IAAI,wBAAwB,CAAC,EAAE;AAAA,EAC3E,OAAO,UAAiE;AACtE,UAAM,cACH,MAAME,OAAM,IAAqB,iBAAiB,WAAW,KAAM,MAAM;AAE5E,QAAI,uBAAuB,GAAG;AAC5B,YAAM,eAAe,MAAM;AAAA,QACzB;AAAA,QACA,MAAM;AAAA,MACR;AACA,UAAI,CAAC,aAAa,IAAI;AACpB,eAAO,KAAK;AAAA,UACV,MAAM,aAAa;AAAA,UACnB,SAAS,aAAa;AAAA,UACtB,SAAS,aAAa;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO,sBAAsB,WAAW;AAAA,EAC1C;AACF;AAEA,SAAS,yBAAkC;AACzC,QAAM,OAAO,QAAQ,IAAI;AACzB,SAAO,CAAC,KAAK,QAAQ,WAAW,UAAU,EAAE,SAAS,MAAM,YAAY,KAAK,EAAE;AAChF;AAEA,eAAe,2BACb,aACA,uBASA;AACA,QAAM,MAAMA,OAAM;AAClB,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,EAAE,WAAW,YAAY,KAAK;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,iBAAiB,MAAMC,QAAO,CAAC,aAAa,uBAAuB,GAAG,GAAG;AAC/E,MAAI,CAAC,eAAe,MAAM,eAAe,WAAW,QAAQ;AAC1D,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SACE;AAAA,MACF,SAAS;AAAA,QACP,WAAW,YAAY;AAAA,QACvB,UAAU,eAAe,KAAK,SAAY,eAAe;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,MAAMA,QAAO,CAAC,OAAO,IAAI,GAAG,GAAG;AAC3C,MAAI,CAAC,IAAI,IAAI;AACX,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,EAAE,WAAW,YAAY,MAAM,UAAU,IAAI,MAAM;AAAA,IAC9D;AAAA,EACF;AAEA,QAAM,SAAS,MAAMA,QAAO,CAAC,QAAQ,YAAY,aAAa,GAAG,GAAG;AACpE,MAAI,CAAC,OAAO,IAAI;AACd,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,EAAE,WAAW,YAAY,MAAM,UAAU,OAAO,MAAM;AAAA,IACjE;AAAA,EACF;AAEA,MAAI,OAAO,OAAO,KAAK,EAAE,WAAW,GAAG;AACrC,UAAM,WAAW,MAAMD,OAAM;AAAA,MAC3B,iBAAiB;AAAA,IACnB;AACA,UAAM,OAAO,MAAMC,QAAO,CAAC,aAAa,MAAM,GAAG,GAAG;AACpD,QAAI,UAAU,UAAU,KAAK,MAAM,KAAK,WAAW,SAAS,QAAQ;AAClE,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAEA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SACE;AAAA,MACF,SAAS;AAAA,QACP,WAAW,YAAY;AAAA,QACvB,kBAAkB,UAAU;AAAA,QAC5B,MAAM,KAAK,KAAK,KAAK,SAAS;AAAA,QAC9B,UAAU,KAAK,KAAK,SAAY,KAAK;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,kBAAkB,YAAY,SAAS,CAAC;AAC3D,QAAM,SAAS,MAAMA;AAAA,IACnB;AAAA,MACE;AAAA,MACA;AAAA,MACA,sBAAsB,cAAc,UAAU,EAAE;AAAA,MAChD;AAAA,MACA,WAAW,aAAa,uBAAuB,OAAO,MAAM;AAAA,IAC9D;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,IAAI;AACd,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,EAAE,WAAW,YAAY,MAAM,UAAU,OAAO,MAAM;AAAA,IACjE;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,KAAK;AACpB;AAEA,eAAe,sBAAsB,aAAoD;AACvF,QAAM,YAAa,MAAMD,OAAM,IAAc,iBAAiB,gBAAgB,KAAM,CAAC;AACrF,QAAM,mBAAmB;AAAA,IACvB,GAAG;AAAA,IACH,kBAAkB,YAAY,SAAS,UAAU,SAAS,CAAC;AAAA,EAC7D;AACA,QAAMA,OAAM,IAAI,iBAAiB,kBAAkB,gBAAgB;AAEnE,QAAM,aAAc,MAAMA,OAAM,IAAgB,iBAAiB,UAAU,KAAM,CAAC;AAClF,QAAM,CAAC,WAAW,GAAG,SAAS,IAAI;AAElC,MAAI,CAAC,WAAW;AACd,UAAMA,OAAM,IAAI,iBAAiB,aAAa,IAAI;AAClD,UAAM,4BAA4B;AAClC,UAAM,aAAa,MAAMA,OAAM,IAAc,YAAY;AACzD,UAAM,oBAAoB,MAAMA,OAAM,IAAc,mBAAmB;AACvE,UAAM,SAA2B;AAAA,MAC/B,QAAQ;AAAA,MACR,gBAAgB,YAAY,QAAQ;AAAA,MACpC,uBAAuB,mBAAmB,QAAQ;AAAA,MAClD,YAAY,iBAAiB;AAAA,MAC7B,kBAAkB;AAAA,MAClB,SAAS,4BAA4B,iBAAiB,MAAM,IAAI,iBAAiB,WAAW,IAAI,UAAU,SAAS;AAAA,IACrH;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AAEA,QAAMA,OAAM,IAAI,iBAAiB,YAAY,SAAS;AACtD,QAAMA,OAAM,IAAI,iBAAiB,aAAa,SAAS;AACvD,QAAM,4BAA4B;AAClC,QAAM,6BAA6B;AACnC,SAAO,mBAAmB,EAAE,cAAc,WAAW,SAAS,EAAE,CAAC;AACnE;AAEA,SAAS,sBAAsB,SAAyB;AACtD,SAAO,QAAQ,UAAU,KAAK,UAAU,GAAG,QAAQ,MAAM,GAAG,EAAE,CAAC;AACjE;AAEA,SAAS,WACP,aACA,uBACA,aACQ;AACR,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,mBAAmB,YAAY,IAAI;AAAA,IACnC;AAAA,IACA;AAAA,IACA,uBAAuB,KAAK,KAAK;AAAA,IACjC;AAAA,IACA;AAAA,IACA,YACG,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,EAChC,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,EACzB,KAAK,IAAI;AAAA,EACd,EAAE,KAAK,IAAI;AACb;;;AG9MA,SAAS,gBAAgB,eAAe;;;ACDxC;;;ACAA;;;AFMA,IAAM,YAAY;AAAA,EAChB,aAAa,4BAAoB,QAAQ;AAAA,EACzC,eAAe,sCAAoC,QAAQ;AAC7D;AASO,SAAS,gCAAgC;AAAA,EAC9C;AACF,GAEW;AACT,QAAM,uBAAuB,MAAM,WAAW,mBAC1C,YAAY,MAAM,WAAW,gBAAgB,WAC7C;AAEJ,SAAO;AAAA,IACL,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ,SAAS,MAAM,aAAa,OAAO;AAAA,IAC3C,QAAQ,uBAAuB,MAAM,yBAAyB,eAAe;AAAA,IAC7E;AAAA,MACE;AAAA,MACA;AAAA,QACE,gCAAgC,MAAM,WAAW,oBAAoB,SAAS;AAAA,QAC9E,2CAA2C,oBAAoB;AAAA,QAC/D;AAAA,QACA;AAAA,QACA,MAAM,WAAW,SAAS,SAAS,IAC/B;AAAA,UACE;AAAA,UACA;AAAA,UACA,GAAG,MAAM,WAAW,SAAS,IAAI,CAAC,YAAY,KAAK,OAAO,EAAE;AAAA,QAC9D,EAAE,KAAK,IAAI,IACX;AAAA,MACN,EACG,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,EAChC,KAAK,IAAI;AAAA,IACd;AAAA,IACA;AAAA,MACE;AAAA,MACA,MAAM,WAAW,iBAAiB;AAAA,IACpC;AAAA,IACA;AAAA,MACE;AAAA,MACA,MAAM,WAAW,mBAAmB;AAAA,IACtC;AAAA,IACA;AAAA,MACE;AAAA,MACA,MAAM,WAAW,eAAe;AAAA,IAClC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AJ3DO,IAAM,gCAAgCE,MAAK,EAAE,IAAI,8BAA8B,CAAC,EACpF,OAAqD,iCAAiC;AAAA,EACrF,OAAO;AAAA,EACP,QAAQ;AACV,CAAC,EACA,GAAG,OAAO,QAAQ,UAAU;AAC3B,MAAI,CAAC,aAAa,MAAM,GAAG;AACzB,QAAI,MAAM,WAAW,2BAA2B;AAC9C,aAAOC,MAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,uBAAuB,yBAAyB,+BAA+B,OAAO,KAAK;AAAA,QACpG,SAAS,EAAE,QAAQ,WAAW,MAAM,aAAa,KAAK;AAAA,MACxD,CAAC;AAAA,IACH;AAEA,WAAO,mBAAmB;AAAA,MACxB,cAAc,MAAM;AAAA,MACpB,qBAAqB;AAAA,MACrB,SAAS,MAAM,UAAU;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,SAAO,wBAAwB;AAAA,IAC7B,cAAc,MAAM;AAAA,IACpB,uBAAuB,MAAM;AAAA,EAC/B,CAAC;AACH,CAAC;;;AOlCH,SAAwB,cAAAC,aAAY,MAAM,kBAAAC,iBAAgB,WAAAC,gBAAe;;;ACAzE;;;ADMA,IAAMC,aAAY;AAAA,EAChB,aAAa,4BAAoB,QAAQ;AAAA,EACzC,sBAAsB,sCAAoC,QAAQ;AAAA,EAClE,eAAe,sCAAoC,QAAQ;AAC7D;AAcO,IAAM,uBAAuBC,YAAiC;AAAA,EACnE,MAAM;AAAA,EACN,YAAY;AAAA,IACV,SAAS,EAAE,MAAM,UAAU;AAAA,IAC3B,eAAe,EAAE,MAAM,SAAS;AAAA,IAChC,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU,CAAC,WAAW,SAAS;AAAA,EAC/B,sBAAsB;AACxB,CAAC;AAEM,SAAS,qBAAqB,EAAE,MAAM,GAAoD;AAC/F,QAAM,WACJ,MAAM,wBAAwB,SAC1B,0BACAC;AAAA,IACE,yBAAyB,MAAM,OAAO,gEAAgE,MAAM,oBAAoB,KAAK,OAAO,MAAM,oBAAoB,OAAO;AAAA,IAC7K;AAAA;AAAA,EAA+E,KAAK,MAAM,oBAAoB,oBAAoB,CAAC;AAAA,EACrI;AAEN,SAAOA;AAAA,IACLF,WAAU;AAAA,IACVA,WAAU;AAAA,IACVA,WAAU;AAAA,IACVG,SAAQ,SAAS,MAAM,aAAa,OAAO;AAAA,IAC3CA;AAAA,MACE;AAAA,MACA,GAAG,QAAQ;AAAA;AAAA;AAAA,IACb;AAAA,EACF;AACF;;;AR/CO,IAAM,qBAAqBC,MAAK,EAAE,IAAI,kBAAkB,CAAC,EAC7D,OAAkD,sBAAsB;AAAA,EACvE,OAAO;AAAA,EACP,QAAQ;AACV,CAAC,EACA,GAAG,OAAO,cAAc,UAAU;AACjC,MAAI,aAAa,SAAS;AACxB,WAAOC,MAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS,aAAa,iBAAiB;AAAA,MACvC,SAAS,EAAE,WAAW,MAAM,aAAa,KAAK;AAAA,IAChD,CAAC;AAAA,EACH;AAEA,SAAO,8BAA8B;AAAA,IACnC,cAAc,MAAM;AAAA,IACpB,SAAS,MAAM;AAAA,IACf,uBAAuB,aAAa;AAAA,IACpC,YAAY,MAAM,0BAA0B;AAAA,EAC9C,CAAC;AACH,CAAC;;;ADpBI,IAAM,iCAAiCC,MAAK,EAAE,IAAI,+BAA+B,CAAC,EAAE;AAAA,EACzF,OAAO,EAAE,kBAAkB,MAAoE;AAC7F,UAAM,oBAAoB,iBAAiB,kBAAkB,SAAS,mBAAmB;AACzF,UAAM,kBAAkB,iBAAiB,kBAAkB,SAAS,iBAAiB;AAErF,QAAI,sBAAsB,iBAAiB;AACzC,aAAOC,MAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,SAAS,iBAAiB,MAAM,mBAAmB,oBAAoB,eAAe,MAAM,iBAAiB;AAAA,QACtH,SAAS,EAAE,uBAAuB,kBAAkB,KAAK;AAAA,MAC3D,CAAC;AAAA,IACH;AAEA,UAAM,iBAAiB,MAAM,KAAK,kBAAkB,QAAQ,SAAS,oBAAoB,CAAC,CAAC;AAC3F,QAAI,eAAe,WAAW,mBAAmB;AAC/C,aAAOA,MAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,WAAW,mBAAmB,uEAAuE,iBAAiB;AAAA,QAC/H,SAAS,EAAE,uBAAuB,kBAAkB,KAAK;AAAA,MAC3D,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,eACnB,IAAI,CAAC,CAAC,EAAE,OAAO,MAAM,SAAS,KAAK,KAAK,EAAE,EAC1C,OAAO,CAAC,YAAY,QAAQ,SAAS,CAAC;AACzC,UAAM,gBAAgB,cAAc,KAAK,aAAa;AACtD,UAAM,8BAA8B,kBAAkB,QAAQ;AAAA,MAC5D,oBAAoB;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,SAAS,4BACZ,MAAM,cAAc,EACpB,MAAM,CAAC,EACP,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC,EAClC,IAAI,CAAC,UAAU,qBAAqB,OAAO,aAAa,CAAC;AAE5D,QAAI,OAAO,WAAW,GAAG;AACvB,aAAOA,MAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,QAAQ,cAAc;AAAA,QAC/B,SAAS,EAAE,uBAAuB,kBAAkB,KAAK;AAAA,MAC3D,CAAC;AAAA,IACH;AAEA,UAAM,YAAwB,CAAC;AAC/B,eAAW,SAAS,QAAQ;AAC1B,gBAAU,KAAK,MAAM,SAAS,KAAK,CAAC;AAAA,IACtC;AAGA,UAAM,CAAC,YAAY,GAAG,SAAS,IAAI;AACnC,UAAMC,OAAM,IAAI,iBAAiB,YAAY,SAAS;AACtD,UAAMA,OAAM,IAAI,iBAAiB,kBAAkB,CAAC,CAAC;AACrD,UAAMA,OAAM,IAAI,iBAAiB,aAAa,UAAU;AACxD,UAAM,6BAA6B;AAEnC,WAAO,mBAAmB,EAAE,cAAc,YAAY,SAAS,EAAE,CAAC;AAAA,EACpE;AACF;AAEA,SAAS,iBAAiB,OAAe,QAAwB;AAC/D,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,SAAO,MAAM;AACX,UAAM,QAAQ,MAAM,QAAQ,QAAQ,MAAM;AAC1C,QAAI,UAAU,IAAI;AAChB,aAAO;AAAA,IACT;AAEA,aAAS;AACT,aAAS,QAAQ,OAAO;AAAA,EAC1B;AACF;AAEA,SAAS,sBAA8B;AACrC,SAAO,IAAI;AAAA,IACT,GAAG,aAAa,mBAAmB,CAAC,eAAe,aAAa,iBAAiB,CAAC;AAAA,IAClF;AAAA,EACF;AACF;AAEA,SAAS,qBAAqB,OAAe,eAA+B;AAC1E,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,oCAAoC,eAAe,mBAAmB,KAAK,EAAE,KAAK,MAAM;AAClG;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;;;AW1GA,SAAS,QAAAC,OAAM,kBAAAC,iBAAgB,WAAAC,gBAAe;;;ACD9C;;;ADKA,IAAMC,aAAY;AAAA,EAChB,aAAa,4BAAoB,QAAQ;AAAA,EACzC,yBAAyB,kCAAgC,QAAQ;AACnE;AAQO,SAAS,8BAA8B;AAAA,EAC5C;AACF,GAEW;AACT,QAAM,iBAAiBC,MAAK;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAOC;AAAA,IACLF,WAAU;AAAA,IACVA,WAAU;AAAA,IACVG,SAAQ,eAAe,MAAM,WAAW,OAAO;AAAA,IAC/CA,SAAQ,mCAAmC,MAAM,kBAAkB,OAAO;AAAA,IAC1EA;AAAA,MACE;AAAA,MACA;AAAA;AAAA,EAA8G,cAAc;AAAA;AAAA;AAAA,IAC9H;AAAA,EACF;AACF;;;AdnCO,IAAM,8BAA8BC,MAAK,EAAE,IAAI,4BAA4B,CAAC,EAChF,OAAmD,+BAA+B;AAAA,EACjF,OAAO;AAAA,EACP,QAAQ;AACV,CAAC,EACA,GAAG,CAAC,QAAQ,UAAU;AACrB,MAAI,aAAa,MAAM,GAAG;AACxB,WAAO,+BAA+B,EAAE,mBAAmB,MAAM,kBAAkB,CAAC;AAAA,EACtF;AAEA,MAAI,MAAM,WAAW,wCAAwC;AAC3D,WAAOC,MAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS,uCAAuC,sCAAsC,+BAA+B,OAAO,KAAK;AAAA,MACjI,SAAS,EAAE,QAAQ,uBAAuB,MAAM,kBAAkB,KAAK;AAAA,IACzE,CAAC;AAAA,EACH;AAEA,SAAO,qCAAqC;AAAA,IAC1C,YAAY,MAAM;AAAA,IAClB,gBAAgB;AAAA,IAChB,SAAS,MAAM,UAAU;AAAA,EAC3B,CAAC;AACH,CAAC;;;AgB9BH,SAAS,QAAAC,OAAM,kBAAAC,iBAAgB,WAAAC,gBAAe;AAM9C,IAAMC,aAAY;AAAA,EAChB,aAAa,4BAAoB,QAAQ;AAAA,EACzC,sBAAsB,sCAAoC,QAAQ;AAAA,EAClE,yBAAyB,kCAAgC,QAAQ;AACnE;AAQO,SAAS,uCAAuC;AAAA,EACrD;AACF,GAEW;AACT,QAAM,WACJ,MAAM,mBAAmB,SACrB,wQACAC;AAAA,IACE,+BAA+B,MAAM,OAAO,wCAAwC,MAAM,eAAe,KAAK,OAAO,MAAM,eAAe,OAAO;AAAA,IACjJ;AAAA;AAAA,EAA+EC,MAAK,MAAM,eAAe,oBAAoB,CAAC;AAAA,EAChI;AAEN,SAAOD;AAAA,IACLD,WAAU;AAAA,IACVA,WAAU;AAAA,IACVA,WAAU;AAAA,IACVG,SAAQ,eAAe,MAAM,WAAW,OAAO;AAAA,IAC/CA;AAAA,MACE;AAAA,MACA,GAAG,QAAQ;AAAA;AAAA;AAAA,IACb;AAAA,EACF;AACF;;;AjBtCO,IAAM,uCAAuCC,MAAK;AAAA,EACvD,IAAI;AACN,CAAC,EACE,OAAO,wCAAwC;AAAA,EAC9C,OAAO;AAAA,EACP,QAAQ;AACV,CAAC,EACA,GAAG,OAAO,mBAAmB,UAAU;AACtC,QAAMC,OAAM,IAAI,qBAAqB,iBAAiB;AACtD,SAAO,4BAA4B;AAAA,IACjC,YAAY,MAAM;AAAA,IAClB;AAAA,IACA,SAAS,MAAM;AAAA,EACjB,CAAC;AACH,CAAC;;;AkBlBH,SAAS,kBAAAC,iBAAgB,WAAAC,gBAAe;;;ACAxC;;;ADKA,IAAMC,aAAY;AAAA,EAChB,aAAa,4BAAoB,QAAQ;AAAA,EACzC,kBAAkB,2BAAyB,QAAQ;AACrD;AAEO,SAAS,uBAAuB,EAAE,MAAM,GAAgD;AAC7F,SAAOC;AAAA,IACLD,WAAU;AAAA,IACVA,WAAU;AAAA,IACVE,SAAQ,kCAAkC,MAAM,YAAY;AAAA,IAC5DA;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AnBhBO,IAAM,uBAAuBC,MAAK,EAAE,IAAI,qBAAqB,CAAC,EAClE,OAAO,wBAAwB;AAAA,EAC9B,OAAO;AAAA,EACP,QAAQC;AACV,CAAC,EACA,GAAG,OAAO,eAAe;AACxB,QAAMC,OAAM,IAAI,cAAc,UAAU;AACxC,SAAO,qCAAqC,EAAE,YAAY,SAAS,EAAE,CAAC;AACxE,CAAC;;;AqBZH,SAAS,aAAa;AAMf,IAAM,kBAAkB,MAAuB,EAAE,cAAc,SAAS,CAAC;;;ACNhF,SAAS,kBAAAC,iBAAgB,WAAAC,gBAAe;AAEjC,SAAS,cAAsB;AACpC,SAAOD;AAAA,IACLC;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,IACAA;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,IACAA;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AvBZO,IAAM,YAAYC,MAAK,EAAE,IAAI,QAAQ,CAAC,EAC1C,OAAO,aAAa;AAAA,EACnB,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AACV,CAAC,EACA,GAAG,CAAC,WAAW,qBAAqB,MAAM,CAAC;;;AFPvC,IAAM,cAAc,eAAe;AAAA,EACxC,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,YAAYC,OAA6B,CAAC,CAAC;AAAA,EAC3C,aAAa;AAAA,EACb,QAAQ;AAAA,IACN,eAAe;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,eAAe;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aACE;AAAA,IACJ;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ;AACN,WAAO,UAAU;AAAA,EACnB;AACF,CAAC;;;A0BxCD,SAAS,kBAAAC,uBAAsB;AAOxB,IAAM,aAAaC,gBAAe;AAAA,EACvC,IAAI;AAAA,EACJ,aACE;AAAA,EACF,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,QAAQ;AAAA,IACN,eAAe;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aACE;AAAA,IACJ;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,MAAM,OAAO;AACX,WAAO,qBAAqB,KAAK;AAAA,EACnC;AACF,CAAC;","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","promptSections","section","fragments","jsonSchema","promptSections","section","step","fail","step","fail","state","list","promptSections","section","fragments","list","promptSections","section","step","fail","list","promptSections","section","fragments","promptSections","list","section","step","state","promptSections","section","fragments","promptSections","section","step","Document","state","promptSections","section","step","shape","defineWorkflow","defineWorkflow"]}
1
+ {"version":3,"sources":["../src/grill-it-away/workflow.ts","../src/feature-implementation/shared/agent-roles.ts","../src/grill-it-away/grill/step.ts","../src/feature-implementation/initialize-take-it-away/step.ts","../src/feature-implementation/create-feature-doc/step.ts","../src/feature-implementation/create-or-improve-implementation-strategy/step.ts","../src/feature-implementation/review-implementation-strategy/step.ts","../src/feature-implementation/slice-implementation-stories/step.ts","../src/feature-implementation/split-implementation-stories/step.ts","../src/feature-implementation/planning-checkpoint/step.ts","../src/feature-implementation/split-implementation-stories/story-context.ts","../src/feature-implementation/slice-implementation-stories/prompt.ts","../src/feature-implementation/shared/feature-methodology.md","../src/feature-implementation/shared/implementation-doc-format.md","../src/feature-implementation/review-implementation-strategy/prompt.ts","../src/feature-implementation/shared/implementation-strategy-format.md","../src/feature-implementation/create-or-improve-implementation-strategy/prompt.ts","../src/feature-implementation/shared/project-architecture-guidance.md","../src/feature-implementation/create-feature-doc/prompt.ts","../src/feature-implementation/shared/feature-doc-format.md","../src/grill-it-away/grill/prompt.ts","../src/take-it-away/workflow.ts"],"sourcesContent":["import { defineWorkflow, shape } from \"@trailstep/authoring\";\nimport { featureImplementationAgents } from \"../feature-implementation/shared/agent-roles.js\";\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 ...featureImplementationAgents,\n },\n start() {\n return grillStep();\n },\n});\n","export const featureImplementationAgents = {\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 strategy: architecture-aware, TDD/vertical-slice/tracer-bullet story design.\",\n },\n reviewer: {\n size: \"large\",\n thinking: \"high\",\n description: \"Reviews implementation strategies before story slicing.\",\n },\n slicer: {\n size: \"large\",\n thinking: \"high\",\n description: \"Slices an approved implementation strategy into coherent implementation stories.\",\n },\n storyExplorer: {\n size: \"small\",\n thinking: \"low\",\n description: \"Finds story-specific files, seams, and validation hints without editing.\",\n },\n testWriter: {\n size: \"medium\",\n thinking: \"medium\",\n description: \"Writes focused behavioral red tests for the active story.\",\n },\n storyImplementer: {\n size: \"medium\",\n thinking: \"medium\",\n description: \"Implements the smallest green slice for the active story.\",\n },\n storyDoctor: {\n size: \"large\",\n thinking: \"high\",\n description:\n \"Diagnoses and repairs repeated active-story validation failures before the workflow exhausts retries.\",\n },\n validator: {\n size: \"small\",\n thinking: \"low\",\n description: \"Runs focused validation commands and reports concise results.\",\n },\n storyReviewer: {\n size: \"large\",\n thinking: \"high\",\n description: \"Reviews isolated story diffs and phase evidence before commit.\",\n },\n} as const;\n","import { step } from \"@trailstep/authoring\";\nimport { initializeTakeItAwayStep } from \"../../feature-implementation/initialize-take-it-away/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) => initializeTakeItAwayStep(output));\n","import { state, step } from \"@trailstep/authoring\";\nimport type { ContinuationResult } from \"@trailstep/core\";\nimport { createFeatureDocStep } from \"../create-feature-doc/step.js\";\nimport {\n normalizeTakeItAwayWorkflowOptions,\n type TakeItAwayInput,\n} from \"../shared/input-schema.js\";\nimport { STORY_STATE_KEYS } from \"../shared/story-state.js\";\n\nexport const initializeTakeItAwayStep = step({ id: \"initialize-take-it-away\" }).do(\n async (input: TakeItAwayInput): Promise<ContinuationResult> => {\n await state.set(STORY_STATE_KEYS.workflowOptions, normalizeTakeItAwayWorkflowOptions(input));\n await state.set(STORY_STATE_KEYS.workflowWarnings, []);\n return createFeatureDocStep(input);\n },\n);\n","import { Document, state, step } from \"@trailstep/authoring\";\nimport { createOrImproveImplementationStrategyStep } from \"../create-or-improve-implementation-strategy/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 createOrImproveImplementationStrategyStep({ featureDoc, attempt: 1 });\n });\n","import { Document, type StepFactory, state, step } from \"@trailstep/authoring\";\nimport { reviewImplementationStrategyStep } from \"../review-implementation-strategy/step.js\";\nimport {\n type CreateOrImproveImplementationStrategyInput,\n createOrImproveImplementationStrategyPrompt,\n} from \"./prompt.js\";\n\nexport const createOrImproveImplementationStrategyStep: StepFactory<\n CreateOrImproveImplementationStrategyInput,\n Document\n> = step({\n id: \"create-or-improve-implementation-strategy\",\n})\n .prompt(createOrImproveImplementationStrategyPrompt, {\n agent: \"planner\",\n output: Document,\n })\n .do(async (implementationStrategy, input) => {\n await state.set(\"implementationStrategy\", implementationStrategy);\n return reviewImplementationStrategyStep({\n featureDoc: input.featureDoc,\n implementationStrategy,\n attempt: input.attempt,\n });\n });\n","import { fail, type StepFactory, step } from \"@trailstep/authoring\";\nimport { createOrImproveImplementationStrategyStep } from \"../create-or-improve-implementation-strategy/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 { sliceImplementationStoriesStep } from \"../slice-implementation-stories/step.js\";\nimport {\n type ReviewImplementationStrategyInput,\n reviewImplementationStrategyPrompt,\n} from \"./prompt.js\";\n\nexport const reviewImplementationStrategyStep: StepFactory<\n ReviewImplementationStrategyInput,\n ReviewResult\n> = step({ id: \"review-implementation-strategy\" })\n .prompt<ReviewImplementationStrategyInput, ReviewResult>(reviewImplementationStrategyPrompt, {\n agent: \"reviewer\",\n output: reviewOutput,\n })\n .do((review, input) => {\n if (reviewPasses(review)) {\n return sliceImplementationStoriesStep({\n featureDoc: input.featureDoc,\n implementationStrategy: input.implementationStrategy,\n });\n }\n\n if (input.attempt >= MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS) {\n return fail({\n code: \"implementation_strategy_review_exhausted\",\n message: `implementation-strategy.md failed review ${MAX_IMPLEMENTATION_DOC_REVIEW_ATTEMPTS} times in a row (last score ${review.score}/5).`,\n details: { review, implementationStrategyPath: input.implementationStrategy.path },\n });\n }\n\n return createOrImproveImplementationStrategyStep({\n featureDoc: input.featureDoc,\n previousReview: review,\n attempt: input.attempt + 1,\n });\n });\n","import { Document, type StepFactory, state, step } from \"@trailstep/authoring\";\nimport { splitImplementationStoriesStep } from \"../split-implementation-stories/step.js\";\nimport {\n type SliceImplementationStoriesInput,\n sliceImplementationStoriesPrompt,\n} from \"./prompt.js\";\n\nexport const sliceImplementationStoriesStep: StepFactory<\n SliceImplementationStoriesInput,\n Document\n> = step({ id: \"slice-implementation-stories\" })\n .prompt(sliceImplementationStoriesPrompt, {\n agent: \"slicer\",\n output: Document,\n })\n .do(async (implementationDoc, input) => {\n await state.set(\"implementationDoc\", implementationDoc);\n return splitImplementationStoriesStep({ featureDoc: input.featureDoc, implementationDoc });\n });\n","import { type Document, document, fail, state, step } from \"@trailstep/authoring\";\nimport type { ContinuationResult } from \"@trailstep/core\";\nimport {\n planningCheckpointStep,\n shouldPauseForPlanningCheckpoint,\n} from \"../planning-checkpoint/step.js\";\nimport { STORY_BOUNDARY, STORY_CONTEXT_END, STORY_CONTEXT_START } from \"../shared/constants.js\";\nimport {\n resetStoryLocalState,\n STORY_STATE_KEYS,\n type StoryPhaseContexts,\n type StoryRoutedContextPhase,\n} from \"../shared/story-state.js\";\nimport { storyRouterStep } from \"../story-router/step.js\";\nimport {\n type ParsedStoryContextBlock,\n parseStoryContextBlocks,\n selectStoryContext,\n} from \"./story-context.js\";\n\nexport interface SplitImplementationStoriesInput extends Record<string, unknown> {\n readonly implementationDoc: Document;\n readonly featureDoc?: Document;\n}\n\nexport const splitImplementationStoriesStep = step({ id: \"split-implementation-stories\" }).do(\n async ({\n featureDoc,\n implementationDoc,\n }: SplitImplementationStoriesInput): Promise<ContinuationResult> => {\n const contextStartCount = countStandaloneMarkerLines(\n implementationDoc.content,\n STORY_CONTEXT_START,\n );\n const contextEndCount = countStandaloneMarkerLines(\n implementationDoc.content,\n STORY_CONTEXT_END,\n );\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 parsedContextBlocks = parseStoryContextBlocks(\n contextMatches.map(([, context]) => context ?? \"\"),\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\n .map((chunk) => chunk.trim())\n .filter((chunk) => chunk.length > 0);\n const storyContexts = chunks.map((chunk) =>\n buildStoryPhaseContexts(parsedContextBlocks, chunk),\n );\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 const [firstStoryContext = {}, ...remainingStoryContexts] = storyContexts;\n await state.set(STORY_STATE_KEYS.storyQueue, remaining);\n await state.set(STORY_STATE_KEYS.storyContextQueue, remainingStoryContexts);\n await state.set(STORY_STATE_KEYS.completedStories, []);\n await state.set(STORY_STATE_KEYS.activeStory, firstStory);\n await state.set(STORY_STATE_KEYS.activeStoryContext, firstStoryContext);\n await state.set(STORY_STATE_KEYS.activePhase, \"story-router\");\n await resetStoryLocalState({\n preserveActiveStoryStartCommit: true,\n preserveLatestStoryRouterState: true,\n preserveStoryBaseline: true,\n });\n\n if (featureDoc && (await shouldPauseForPlanningCheckpoint())) {\n return planningCheckpointStep({ featureDoc, implementationDoc });\n }\n\n return storyRouterStep({ reason: \"start-story\", currentStory: firstStory });\n },\n);\n\nfunction buildStoryPhaseContexts(\n blocks: readonly ParsedStoryContextBlock[],\n storyContent: string,\n): StoryPhaseContexts {\n const phases: readonly StoryRoutedContextPhase[] = [\n \"deterministic-context-preflight\",\n \"explore-story\",\n \"write-red-tests\",\n \"implement-green\",\n \"validate-story\",\n \"review-story-implementation\",\n ];\n return Object.fromEntries(\n phases.map((phase) => [\n phase,\n selectStoryContext({\n blocks,\n storyContent,\n audience: phase === \"review-story-implementation\" ? \"reviewer\" : \"implementer\",\n phase,\n }),\n ]),\n ) as StoryPhaseContexts;\n}\n\nfunction countStandaloneMarkerLines(value: string, marker: string): number {\n return Array.from(value.matchAll(standaloneMarkerLinePattern(marker))).length;\n}\n\nfunction standaloneMarkerLinePattern(marker: string): RegExp {\n return new RegExp(`^[ \\\\t]*${escapeRegExp(marker)}[ \\\\t]*$`, \"gm\");\n}\n\nfunction storyContextPattern(): RegExp {\n return new RegExp(\n `^[ \\\\t]*${escapeRegExp(STORY_CONTEXT_START)}[ \\\\t]*\\\\r?\\\\n([\\\\s\\\\S]*?)^[ \\\\t]*${escapeRegExp(STORY_CONTEXT_END)}[ \\\\t]*$`,\n \"gm\",\n );\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import {\n type Document,\n fail,\n jsonSchema,\n type StepFactory,\n state,\n step,\n} from \"@trailstep/authoring\";\nimport type { ContinuationResult } from \"@trailstep/core\";\nimport { createOrImproveImplementationStrategyStep } from \"../create-or-improve-implementation-strategy/step.js\";\nimport type { TakeItAwayWorkflowOptions } from \"../shared/input-schema.js\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\nimport { STORY_STATE_KEYS } from \"../shared/story-state.js\";\nimport { storyRouterStep } from \"../story-router/step.js\";\n\nexport interface PlanningCheckpointInput extends Record<string, unknown> {\n readonly featureDoc: Document;\n readonly implementationDoc: Document;\n}\n\nexport interface PlanningCheckpointAnswer extends Record<string, unknown> {\n readonly action: \"approve\" | \"revise\" | \"abort\";\n readonly notes?: string;\n}\n\nconst planningCheckpointAnswer = jsonSchema<PlanningCheckpointAnswer>({\n type: \"object\",\n properties: {\n action: { type: \"string\", enum: [\"approve\", \"revise\", \"abort\"] },\n notes: { type: \"string\" },\n },\n required: [\"action\"],\n additionalProperties: false,\n});\n\nexport const planningCheckpointStep: StepFactory<PlanningCheckpointInput, PlanningCheckpointInput> =\n step({ id: \"planning-checkpoint\" })\n .wait(async (context) => {\n const input = context.input as PlanningCheckpointInput;\n const waitId = await nextPlanningCheckpointWaitId();\n return {\n id: waitId,\n kind: \"input\",\n message: [\n \"Review the accepted implementation plan and story slices before execution.\",\n `Implementation doc: ${input.implementationDoc.path}`,\n 'Answer with {\"action\":\"approve\"} to continue, {\"action\":\"revise\",\"notes\":\"...\"} to return to planning, or {\"action\":\"abort\",\"notes\":\"...\"} to stop.',\n ].join(\"\\n\"),\n output: planningCheckpointAnswer,\n };\n })\n .do(async (context, input): Promise<ContinuationResult> => {\n const answer = readPlanningCheckpointAnswer(context.waits);\n\n if (!answer) {\n return fail({\n code: \"planning_checkpoint_missing_answer\",\n message: \"Planning checkpoint resumed without a recorded human answer.\",\n });\n }\n\n if (answer.action === \"abort\") {\n return fail({\n code: \"planning_checkpoint_aborted\",\n message: answer.notes?.trim() || \"Human aborted at the planning checkpoint.\",\n details: { implementationDocPath: input.implementationDoc.path },\n });\n }\n\n if (answer.action === \"revise\") {\n await state.set(STORY_STATE_KEYS.skipNextPlanningCheckpoint, true);\n return createOrImproveImplementationStrategyStep({\n featureDoc: input.featureDoc,\n previousReview: humanRevisionReview(answer.notes),\n attempt: 1,\n });\n }\n\n const activeStory = await state.get<Document>(STORY_STATE_KEYS.activeStory);\n if (!activeStory) {\n return fail({\n code: \"planning_checkpoint_missing_active_story\",\n message: \"Planning checkpoint approved, but no active story was prepared for execution.\",\n details: { implementationDocPath: input.implementationDoc.path },\n });\n }\n\n return storyRouterStep({ reason: \"start-story\", currentStory: activeStory });\n });\n\nexport async function shouldPauseForPlanningCheckpoint(): Promise<boolean> {\n const options = await state.get<TakeItAwayWorkflowOptions>(STORY_STATE_KEYS.workflowOptions);\n if (!(options?.planningCheckpoint.enabled ?? false)) {\n return false;\n }\n\n const skipNextCheckpoint = await state.get<boolean | null>(\n STORY_STATE_KEYS.skipNextPlanningCheckpoint,\n );\n if (skipNextCheckpoint) {\n await state.set(STORY_STATE_KEYS.skipNextPlanningCheckpoint, false);\n return false;\n }\n\n return true;\n}\n\nasync function nextPlanningCheckpointWaitId(): Promise<string> {\n const previousCount =\n (await state.get<number | null>(STORY_STATE_KEYS.planningCheckpointCount)) ?? 0;\n const nextCount = previousCount + 1;\n await state.set(STORY_STATE_KEYS.planningCheckpointCount, nextCount);\n return nextCount === 1 ? \"planning-checkpoint\" : `planning-checkpoint-${nextCount}`;\n}\n\nfunction readPlanningCheckpointAnswer(\n waits: Readonly<Record<string, unknown>>,\n): PlanningCheckpointAnswer | undefined {\n for (const [waitId, value] of Object.entries(waits)) {\n if (!waitId.startsWith(\"planning-checkpoint\") || !isPlanningCheckpointAnswer(value)) {\n continue;\n }\n return value;\n }\n return undefined;\n}\n\nfunction isPlanningCheckpointAnswer(value: unknown): value is PlanningCheckpointAnswer {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const action = (value as { readonly action?: unknown }).action;\n return action === \"approve\" || action === \"revise\" || action === \"abort\";\n}\n\nfunction humanRevisionReview(notes: string | undefined): ReviewResult {\n const trimmedNotes = notes?.trim();\n return {\n score: 1,\n summary: trimmedNotes\n ? `Human requested planning revision: ${trimmedNotes}`\n : \"Human requested planning revision at the checkpoint.\",\n methodologyRatings: {\n tdd: 1,\n verticalSlicing: 1,\n tracerBullet: 1,\n dependencies: 1,\n architecture: 1,\n },\n requiredImprovements: [\n trimmedNotes || \"Revise the implementation plan per human checkpoint feedback.\",\n ],\n };\n}\n","export type StoryContextAudience = \"implementer\" | \"reviewer\" | \"all\";\n\nexport type StoryContextPhase =\n | \"deterministic-context-preflight\"\n | \"explore-story\"\n | \"write-red-tests\"\n | \"implement-green\"\n | \"validate-story\"\n | \"review-story-implementation\";\n\nexport interface ParsedStoryContextBlock {\n readonly audience?: StoryContextAudience;\n readonly stories?: readonly string[] | \"all\";\n readonly phases?: readonly StoryContextPhase[] | \"all\";\n readonly body: string;\n}\n\nexport function parseStoryContextBlocks(\n rawBlocks: readonly string[],\n): readonly ParsedStoryContextBlock[] {\n return rawBlocks.flatMap((rawBlock) => {\n const parsed = parseStoryContextBlock(rawBlock);\n return parsed ? [parsed] : [];\n });\n}\n\nexport function selectStoryContext({\n blocks,\n storyContent,\n audience,\n phase,\n}: {\n readonly blocks: readonly ParsedStoryContextBlock[];\n readonly storyContent: string;\n readonly audience: Exclude<StoryContextAudience, \"all\">;\n readonly phase: StoryContextPhase;\n}): string {\n return blocks\n .filter(\n (block) =>\n blockMatchesAudience(block, audience) &&\n blockMatchesStory(block, storyContent) &&\n blockMatchesPhase(block, phase),\n )\n .map((block) => block.body)\n .join(\"\\n\\n---\\n\\n\");\n}\n\nfunction parseStoryContextBlock(rawBlock: string): ParsedStoryContextBlock | undefined {\n const lines = rawBlock.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n const firstBlankLine = lines.findIndex((line) => line.trim().length === 0);\n const metadataLines = firstBlankLine === -1 ? lines : lines.slice(0, firstBlankLine);\n const bodyLines = firstBlankLine === -1 ? [] : lines.slice(firstBlankLine + 1);\n const metadata = parseMetadataLines(metadataLines);\n const body = bodyLines.join(\"\\n\").trim();\n\n if (body.length === 0 || !hasRecognizedScopeMetadata(metadata)) {\n return undefined;\n }\n\n return { ...metadata, body };\n}\n\ninterface ParsedStoryContextMetadata {\n audience?: StoryContextAudience;\n stories?: readonly string[] | \"all\";\n phases?: readonly StoryContextPhase[] | \"all\";\n}\n\nfunction parseMetadataLines(lines: readonly string[]): ParsedStoryContextMetadata {\n const metadata: ParsedStoryContextMetadata = {};\n\n for (const line of lines) {\n const match = /^([A-Za-z-]+):\\s*(.*?)\\s*$/.exec(line.trim());\n if (!match) {\n continue;\n }\n\n const key = match[1]?.toLowerCase();\n const value = match[2] ?? \"\";\n if (key === \"audience\") {\n const audience = parseAudience(value);\n if (audience) {\n metadata.audience = audience;\n }\n continue;\n }\n\n if (key === \"stories\") {\n const stories = parseStoryList(value);\n if (stories) {\n metadata.stories = stories;\n }\n continue;\n }\n\n if (key === \"phases\") {\n const phases = parsePhaseList(value);\n if (phases) {\n metadata.phases = phases;\n }\n }\n }\n\n return metadata;\n}\n\nfunction parseAudience(value: string): StoryContextAudience | undefined {\n const normalized = value.trim().toLowerCase();\n if (normalized === \"implementer\" || normalized === \"reviewer\" || normalized === \"all\") {\n return normalized;\n }\n return undefined;\n}\n\nfunction parseStoryList(value: string): readonly string[] | \"all\" | undefined {\n const items = splitMetadataList(value);\n if (items.length === 0) {\n return undefined;\n }\n\n if (items.length === 1 && items[0]?.toLowerCase() === \"all\") {\n return \"all\";\n }\n\n return items.filter((item) => item.toLowerCase() !== \"all\");\n}\n\nfunction parsePhaseList(value: string): readonly StoryContextPhase[] | \"all\" | undefined {\n const items = splitMetadataList(value);\n if (items.length === 0) {\n return undefined;\n }\n\n if (items.length === 1 && items[0]?.toLowerCase() === \"all\") {\n return \"all\";\n }\n\n const phases = items.filter(isStoryContextPhase);\n return phases.length > 0 ? phases : undefined;\n}\n\nfunction splitMetadataList(value: string): readonly string[] {\n return value\n .split(\",\")\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n}\n\nfunction isStoryContextPhase(value: string): value is StoryContextPhase {\n return [\n \"deterministic-context-preflight\",\n \"explore-story\",\n \"write-red-tests\",\n \"implement-green\",\n \"validate-story\",\n \"review-story-implementation\",\n ].includes(value);\n}\n\nfunction hasRecognizedScopeMetadata(metadata: ParsedStoryContextMetadata): boolean {\n return Boolean(metadata.audience || metadata.stories || metadata.phases);\n}\n\nfunction blockMatchesAudience(\n block: ParsedStoryContextBlock,\n audience: Exclude<StoryContextAudience, \"all\">,\n): boolean {\n return block.audience === audience || block.audience === \"all\";\n}\n\nfunction blockMatchesStory(block: ParsedStoryContextBlock, storyContent: string): boolean {\n if (block.stories === \"all\") {\n return true;\n }\n\n if (!block.stories) {\n return false;\n }\n\n const storyLabels = extractStoryLabels(storyContent).map(normalizeStoryLabel);\n return block.stories.some((story) => storyLabels.includes(normalizeStoryLabel(story)));\n}\n\nfunction blockMatchesPhase(block: ParsedStoryContextBlock, phase: StoryContextPhase): boolean {\n if (!block.phases || block.phases === \"all\" || block.phases.includes(phase)) {\n return true;\n }\n return phase === \"deterministic-context-preflight\" && block.phases.includes(\"explore-story\");\n}\n\nfunction extractStoryLabels(storyContent: string): readonly string[] {\n const match = /^#{1,6}\\s+(Story\\s+\\d+)(?::\\s*(.+))?\\s*$/im.exec(storyContent);\n const ordinal = match?.[1]?.trim();\n if (!ordinal) {\n return [];\n }\n\n const title = match?.[2]?.trim();\n return title ? [ordinal, `${ordinal}: ${title}`] : [ordinal];\n}\n\nfunction normalizeStoryLabel(value: string): string {\n return value.trim().replace(/\\s+/g, \" \").toLowerCase();\n}\n","import type { Document } from \"@trailstep/authoring\";\nimport { promptSections, section } from \"@trailstep/authoring\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport implementationDocFormatFragment from \"../shared/implementation-doc-format.md?raw\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n implementationDocFormat: implementationDocFormatFragment.trimEnd(),\n};\n\nexport interface SliceImplementationStoriesInput extends Record<string, unknown> {\n readonly featureDoc: Document;\n readonly implementationStrategy: Document;\n}\n\nexport function sliceImplementationStoriesPrompt({\n input,\n}: {\n readonly input: SliceImplementationStoriesInput;\n}): string {\n return promptSections(\n fragments.methodology,\n fragments.implementationDocFormat,\n section(\"Feature doc\", input.featureDoc.content),\n section(\"Reviewed implementation strategy\", input.implementationStrategy.content),\n section(\n \"Task\",\n \"Generate only the implementation-ready story document to be mechanically split for execution. Consume the feature doc and reviewed strategy, but do not copy broad architecture/risk planning into overview prose that implementers will not see. Use `<!-- trailstep-story-boundary -->` only to delimit story bodies. Keep each story self-contained for its implementer; put genuinely shared implementer-only phase context in balanced `<context>` blocks with metadata. Do not add a separate strategy section, reviewer notes, or non-story planning artifact content.\",\n ),\n );\n}\n","# Feature workflow methodology\n\n## Planning principles\n\n- Start from observable behavior and user value.\n- Preserve uncertainty explicitly; do not invent missing product decisions.\n- Prefer the smallest vertical slice that proves a complete path through the system.\n- Slice by integration-visible value and risk, not by numeric story budgets.\n- Split a story when it contains separable user-visible/integration-visible outcomes, independent risk seams, or hard dependency boundaries that can each be proven by distinct behavioral tests.\n- Bundle work into the same story when splitting would create micro-stories, docs/package-metadata-only tasks, duplicate validation-only paths, or horizontal setup/refactor/test-only tasks that are not independently observable.\n- Use tracer bullets to de-risk integration seams early with thin end-to-end behavior.\n- Every implementation story must begin with a behavioral red test that fails for the right reason.\n- The green phase should add only enough production code to pass the focused red test.\n- Refactor only after focused tests pass, and keep refactors scoped to the feature.\n- Dependencies are hard dependencies only: story B depends on story A when B cannot pass its own tests until A is complete.\n\n## Review scoring\n\nScore on a 1-5 integer scale:\n\n- 5: excellent; strongly aligned with TDD, cost-aware vertical slicing, tracer-bullet risk reduction, dependency clarity, and local architecture.\n- 4: good; acceptable with only minor non-blocking improvements.\n- 3: incomplete; useful but needs material changes before continuing.\n- 2: poor; misses core methodology or important requirements.\n- 1: unusable; unsafe, incoherent, or not traceable to the feature.\n\nScores of 4 or 5 pass. Scores below 4 must list specific `requiredImprovements` so the next attempt can address them directly.\n","# Implementation doc format\n\n`implementation-doc.md` converts `feature-doc.md` into implementation-ready stories.\n\nUse this structure:\n\n```markdown\n# Implementation Plan: <Feature Name>\n\n## Overview for planner/reviewer\n\nOptional high-level planning notes that do not need to be seen by story implementers.\n\n<context>\naudience: implementer\nstories: all\nphases: deterministic-context-preflight\n\n## Shared Implementer Exploration Context\n\nPut only cross-story details that an implementer needs during story exploration: outcome constraints, architecture/integration notes, repository conventions, shared validation command hints, assumptions, and hard dependency graph notes. Do not put reviewer-only instructions, full implementation-doc process guidance, or unrelated story details here.\n\nScoped context blocks are stored separately from story bodies. They are not prepended to every split story. The router passes matching implementer context only to the narrow phase that needs it.\n\n</context>\n\n<!-- trailstep-story-boundary -->\n\n### Story 001: <title>\n\nDependencies: none\n\n#### Goal\n\n#### User-Visible / Integration-Visible Slice\n\n#### Acceptance Criteria\n\n#### Red Phase\n\n- Test file:\n- Test case:\n- Expected failing assertion:\n\n#### Green Phase\n\n#### Refactor Phase\n\n#### Validation Commands\n\n#### Notes for Implementer\n\n<!-- trailstep-story-boundary -->\n\n### Story 002: <title>\n\nDependencies: Story 001\n\n...\n```\n\nRules:\n\n- Text above the first `<!-- trailstep-story-boundary -->` is never part of an active story body. Only scoped `<context>` ... `</context>` blocks with recognized metadata can be selected as separate phase context.\n- Context blocks must begin with metadata lines before the first blank line. Recognized keys are `audience: implementer|reviewer|all`, `stories: all|Story 001|Story 001: Title`, and `phases: all|deterministic-context-preflight|explore-story|write-red-tests|implement-green|validate-story|review-story-implementation`.\n- Unscoped context blocks are ignored instead of being blindly prepended to every story. If a detail applies to only one story, prefer putting it directly in that story. No story-critical detail may live only in non-context overview text.\n- Every `<context>` marker must have a matching `</context>` marker. Context markers are recognized only when the marker is the sole non-whitespace content on its line; inline mentions of `<context>` in prose are ignored by the splitter.\n- Every story must start right after a `<!-- trailstep-story-boundary -->` line, on its own line, with nothing else on that line. Splitting is mechanical and depends on this exact marker — do not use markdown headings alone to separate stories, and do not add or omit a boundary marker except between/before stories.\n- Stories must be topologically ordered.\n- Every story must be implementation-ready and self-contained, written as instructions to an implementer who will not see this file, only their own story's content.\n- Avoid horizontal stories unless they are embedded in an observable vertical slice.\n- Split versus bundle by delivery value, risk, and validation distinctness, not by numeric story budgets.\n- Split a candidate story when it contains separable integration-visible outcomes, independent high-risk seams, or true hard dependency boundaries that can each be proven by a distinct behavioral red test.\n- Bundle small changes when splitting would produce micro-stories, duplicate validation paths, docs/package-metadata-only stories, package metadata wiring without behavior, or horizontal setup/refactor/test-only work that is not independently observable.\n- Keep slicing rationale in the overview or reviewer context only; do not put split/bundle justification inside story bodies shown to implementers.\n- Name concrete files/tests/commands when they can be inferred from the repository.\n- Preserve uncertainty as assumptions or blocked states instead of guessing.\n","import type { Document } from \"@trailstep/authoring\";\nimport { list, promptSections, section } from \"@trailstep/authoring\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport implementationStrategyFormatFragment from \"../shared/implementation-strategy-format.md?raw\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n implementationStrategyFormat: implementationStrategyFormatFragment.trimEnd(),\n};\n\nexport interface ReviewImplementationStrategyInput extends Record<string, unknown> {\n readonly featureDoc: Document;\n readonly implementationStrategy: Document;\n readonly attempt: number;\n}\n\nexport function reviewImplementationStrategyPrompt({\n input,\n}: {\n readonly input: ReviewImplementationStrategyInput;\n}): string {\n const reviewCriteria = list([\n \"traceability to the feature doc\",\n \"sound architecture and integration planning\",\n \"explicit risk and uncertainty handling\",\n \"a clear tracer-bullet strategy\",\n \"hard dependency reasoning without over-constraining\",\n \"testing and validation strategy\",\n \"useful slicing guidance for a later story slicer\",\n \"absence of `<!-- trailstep-story-boundary -->` markers or executable story bodies\",\n ]);\n\n return promptSections(\n fragments.methodology,\n fragments.implementationStrategyFormat,\n section(\"Feature doc\", input.featureDoc.content),\n section(\"Implementation strategy under review\", input.implementationStrategy.content),\n section(\n \"Task\",\n `Critically review the implementation strategy above against the feature doc and the methodology. Review for:\\n\\n${reviewCriteria}\\n\\nDo not edit the strategy. Respond only with the structured review.`,\n ),\n );\n}\n","# Implementation strategy format\n\n`implementation-strategy.md` captures architecture and risk planning before executable story slicing.\n\nUse this structure:\n\n```markdown\n# Implementation Strategy: <Feature Name>\n\n## Objective and Scope\n\n## Architecture Approach\n\n## Key Files and Integration Points\n\n## Risk Plan\n\n## Testing Strategy\n\n## Slicing Guidance\n```\n\nRules:\n\n- Do not include `<!-- trailstep-story-boundary -->` or any other TrailStep story boundary markup.\n- Do not write executable story bodies in this artifact.\n- Focus on architecture, risk, sequencing rationale, tracer-bullet path, hard dependencies, and validation strategy.\n- Preserve uncertainty as assumptions or explicit risks instead of guessing.\n","import type { Document } from \"@trailstep/authoring\";\nimport { list, promptSections, section } from \"@trailstep/authoring\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport implementationStrategyFormatFragment from \"../shared/implementation-strategy-format.md?raw\";\nimport projectArchitectureGuidanceFragment from \"../shared/project-architecture-guidance.md?raw\";\nimport type { ReviewResult } from \"../shared/review-schema.js\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n architectureGuidance: projectArchitectureGuidanceFragment.trimEnd(),\n implementationStrategyFormat: implementationStrategyFormatFragment.trimEnd(),\n};\n\nexport interface CreateOrImproveImplementationStrategyInput extends Record<string, unknown> {\n readonly featureDoc: Document;\n readonly previousReview?: ReviewResult;\n readonly attempt: number;\n}\n\nexport function createOrImproveImplementationStrategyPrompt({\n input,\n}: {\n readonly input: CreateOrImproveImplementationStrategyInput;\n}): string {\n const taskBody =\n input.previousReview === undefined\n ? \"Create `implementation-strategy.md` from the feature doc above. This is architecture/risk planning only, not executable story generation.\"\n : promptSections(\n `This is improvement attempt ${input.attempt}. A previous review scored this strategy ${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.implementationStrategyFormat,\n section(\"Feature doc\", input.featureDoc.content),\n section(\n \"Task\",\n `${taskBody}\\n\\nPlan the implementation architecture, risks, tracer-bullet path, hard dependencies, test strategy, and slicing guidance. Do not include story boundary markers and do not write full story bodies; a separate slicer will turn this strategy into implementation-ready stories.`,\n ),\n );\n}\n","# Architecture awareness\n\nBefore naming files, choosing package/module boundaries, picking integration seams, or ordering stories/dependencies, ground the decision in the target project's own conventions rather than inventing structure:\n\n- Look for and read the project's own architecture/convention docs at its root and nearby — `CLAUDE.md`, `AGENTS.md`, `.pi/rules/`, ADRs, architecture docs, or an equivalent README section.\n- Prefer existing module/package boundaries, naming conventions, and file layout patterns already established in the project over introducing new ones.\n- When the project's own guidance is silent or ambiguous on a non-trivial integration choice, say so explicitly as an assumption rather than silently picking one convention over another.\n","import { promptSections, section } from \"@trailstep/authoring\";\nimport featureDocFormatFragment from \"../shared/feature-doc-format.md?raw\";\nimport methodologyFragment from \"../shared/feature-methodology.md?raw\";\nimport type { TakeItAwayInput } from \"../shared/input-schema.js\";\n\nconst fragments = {\n methodology: methodologyFragment.trimEnd(),\n featureDocFormat: featureDocFormatFragment.trimEnd(),\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 \"Distillation guardrails\",\n [\n \"Treat the conversation/request as evidence, not as permission to finish a product vision.\",\n \"Preserve the user's actual must-have outcome, explicit constraints, uncertainty, and explicit non-goals; include implied scope limits only when tied to clear evidence.\",\n \"Do not invent scope, acceptance criteria, integrations, personas, product decisions, or polish that the user did not ask for.\",\n \"When a broad request includes brainstorming, ambitions, or adjacent possibilities, keep the confirmed current scope in the must-have/in-scope sections and move nonessential ideas to Optional / Future Ideas.\",\n \"Use Structured Scope Facts for compact planning metadata copied or derived directly from the conversation; do not let that fact list add new requirements.\",\n \"If a detail is unknown, record it as an assumption or open question instead of choosing an answer.\",\n \"A later planning agent may implement the must-have and in-scope sections; optional/future ideas are context only and must not become story scope unless explicitly promoted by the user.\",\n ].join(\"\\n\"),\n ),\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, while preserving scope boundaries and uncertainty. Do not inflate the request into an idealized product spec.\",\n ),\n );\n}\n","# Feature doc format\n\n`feature-doc.md` is an intermediate, scope-preserving feature description used as input to implementation planning. It should distill the real request without turning it into an idealized product specification.\n\nUse this structure:\n\n```markdown\n# <Feature Name>\n\n## Must-Have Outcome\n\nSummarize the smallest confirmed outcome the user actually requested. Prefer the user's concrete wording and avoid expanding into adjacent product vision.\n\n## Users / Jobs / Pain\n\n## In-Scope Proposed Behavior\n\nDescribe only behavior needed for the must-have outcome. If something seems useful but was not requested or is uncertain, keep it out of this section.\n\n## Explicit Non-Goals\n\nList non-goals, exclusions, and scope limits explicitly stated by the conversation. Include strongly implied exclusions only when tied to clear evidence. If none were stated, say so instead of inventing exclusions.\n\n## Examples and Acceptance Criteria\n\n## Edge Cases and Failure Modes\n\n## Affected Areas and Integration Points\n\n## Testing Expectations\n\n## Documentation / Migration / Rollout Notes\n\n## Assumptions and Open Questions\n\nCapture missing product decisions, uncertain details, and assumptions required for planning. Do not resolve uncertainty by inventing answers.\n\n## Conversation Context Worth Preserving\n\nRecord constraints, rationale, terminology, user preferences, tradeoffs, and notable uncertainty that a planner or implementer should know without rereading the full conversation.\n\n## Optional / Future Ideas\n\nList explicitly mentioned nice-to-haves, possible follow-ups, or adjacent ideas separately from the current implementation scope. These ideas are not acceptance criteria unless the conversation explicitly makes them must-haves.\n\n## Structured Scope Facts\n\nProvide a compact, planning-friendly fact list without introducing new scope. Use `- Key: value` bullets for confirmed actors, in-scope surfaces, data/entities, integrations, constraints, explicit exclusions, and open decisions that later planning should preserve mechanically.\n```\n\nThe document should be detailed enough that another agent can plan implementation without reading the original conversation, while still preserving important uncertainty and scope boundaries.\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 feature in the current project. 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 { initializeTakeItAwayStep } from \"../feature-implementation/initialize-take-it-away/step.js\";\nimport { featureImplementationAgents } from \"../feature-implementation/shared/agent-roles.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: featureImplementationAgents,\n start(input) {\n return initializeTakeItAwayStep(input);\n },\n});\n"],"mappings":"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","names":["step","state","step","Document","state","step","Document","state","step","fail","step","state","step","fail","state","step","step","fail","state","step","state","promptSections","section","fragments","promptSections","section","step","fail","list","promptSections","section","fragments","promptSections","list","section","step","Document","state","promptSections","section","fragments","promptSections","section","step","Document","state","step","state","promptSections","section","step","defineWorkflow","defineWorkflow"]}
@@ -0,0 +1,7 @@
1
+ import {
2
+ storyRouterStep
3
+ } from "./chunk-RF3PMHPX.js";
4
+ export {
5
+ storyRouterStep
6
+ };
7
+ //# sourceMappingURL=step-ZAE3Y7FI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trailstep/create-flows",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Public reusable general-purpose TrailStep workflows.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -19,6 +19,198 @@
19
19
  "workflows": {
20
20
  "takeItAway": "./dist/index.js#takeItAway",
21
21
  "grillItAway": "./dist/index.js#grillItAway"
22
+ },
23
+ "recommendedConfig": {
24
+ "agents": {
25
+ "generalist": [
26
+ {
27
+ "provider": "pi",
28
+ "model": "openrouter/meta/muse-spark-1.3",
29
+ "thinking": "medium"
30
+ },
31
+ {
32
+ "provider": "pi",
33
+ "model": "openrouter/xiaomi/mimo-v2.6-pro",
34
+ "thinking": "medium"
35
+ }
36
+ ],
37
+ "planner": [
38
+ {
39
+ "provider": "pi",
40
+ "model": "openrouter/xiaomi/mimo-v2.6-pro",
41
+ "thinking": "high"
42
+ }
43
+ ],
44
+ "explorer": [
45
+ {
46
+ "provider": "pi",
47
+ "model": "openrouter/deepseek/deepseek-v4-flash-0731",
48
+ "thinking": "low"
49
+ }
50
+ ],
51
+ "quick-implementor": [
52
+ {
53
+ "provider": "pi",
54
+ "model": "openrouter/z-ai/glm-5.3-flash",
55
+ "thinking": "medium"
56
+ }
57
+ ],
58
+ "smart-implementor": [
59
+ {
60
+ "provider": "pi",
61
+ "model": "openrouter/xiaomi/mimo-v2.6-pro",
62
+ "thinking": "high"
63
+ }
64
+ ],
65
+ "debugger": [
66
+ {
67
+ "provider": "pi",
68
+ "model": "openrouter/xiaomi/mimo-v2.6-pro",
69
+ "thinking": "high"
70
+ }
71
+ ],
72
+ "reviewer": [
73
+ {
74
+ "provider": "pi",
75
+ "model": "openrouter/z-ai/glm-5.3-flash",
76
+ "thinking": "medium"
77
+ }
78
+ ],
79
+ "expert": [
80
+ {
81
+ "provider": "pi",
82
+ "model": "openrouter/xiaomi/mimo-v2.6-pro",
83
+ "thinking": "high"
84
+ }
85
+ ],
86
+ "formatter": [
87
+ {
88
+ "provider": "pi",
89
+ "model": "openrouter/z-ai/glm-5.3-flash",
90
+ "thinking": "low"
91
+ }
92
+ ],
93
+ "fixer": [
94
+ {
95
+ "ref": "debugger"
96
+ }
97
+ ]
98
+ },
99
+ "workflows": {
100
+ "take-it-away": {
101
+ "agents": {
102
+ "featureWriter": [
103
+ {
104
+ "ref": "planner"
105
+ }
106
+ ],
107
+ "planner": [
108
+ {
109
+ "ref": "planner"
110
+ }
111
+ ],
112
+ "reviewer": [
113
+ {
114
+ "ref": "reviewer"
115
+ }
116
+ ],
117
+ "slicer": [
118
+ {
119
+ "ref": "planner"
120
+ }
121
+ ],
122
+ "storyExplorer": [
123
+ {
124
+ "ref": "explorer"
125
+ }
126
+ ],
127
+ "testWriter": [
128
+ {
129
+ "ref": "quick-implementor"
130
+ }
131
+ ],
132
+ "storyImplementer": [
133
+ {
134
+ "ref": "smart-implementor"
135
+ }
136
+ ],
137
+ "storyDoctor": [
138
+ {
139
+ "ref": "debugger"
140
+ }
141
+ ],
142
+ "validator": [
143
+ {
144
+ "ref": "explorer"
145
+ }
146
+ ],
147
+ "storyReviewer": [
148
+ {
149
+ "ref": "reviewer"
150
+ }
151
+ ]
152
+ }
153
+ },
154
+ "grill-it-away": {
155
+ "agents": {
156
+ "featureWriter": [
157
+ {
158
+ "ref": "planner"
159
+ }
160
+ ],
161
+ "planner": [
162
+ {
163
+ "ref": "planner"
164
+ }
165
+ ],
166
+ "reviewer": [
167
+ {
168
+ "ref": "reviewer"
169
+ }
170
+ ],
171
+ "slicer": [
172
+ {
173
+ "ref": "planner"
174
+ }
175
+ ],
176
+ "storyExplorer": [
177
+ {
178
+ "ref": "explorer"
179
+ }
180
+ ],
181
+ "testWriter": [
182
+ {
183
+ "ref": "quick-implementor"
184
+ }
185
+ ],
186
+ "storyImplementer": [
187
+ {
188
+ "ref": "smart-implementor"
189
+ }
190
+ ],
191
+ "storyDoctor": [
192
+ {
193
+ "ref": "debugger"
194
+ }
195
+ ],
196
+ "validator": [
197
+ {
198
+ "ref": "explorer"
199
+ }
200
+ ],
201
+ "storyReviewer": [
202
+ {
203
+ "ref": "reviewer"
204
+ }
205
+ ],
206
+ "grillingAgent": [
207
+ {
208
+ "ref": "planner"
209
+ }
210
+ ]
211
+ }
212
+ }
213
+ }
22
214
  }
23
215
  },
24
216
  "main": "./dist/index.js",
@@ -30,15 +222,15 @@
30
222
  }
31
223
  },
32
224
  "dependencies": {
33
- "@trailstep/authoring": "0.1.2"
225
+ "@trailstep/authoring": "0.2.0"
34
226
  },
35
227
  "devDependencies": {
36
228
  "@biomejs/biome": "^2.5.8",
229
+ "@trailstep/core": "0.2.0",
37
230
  "@types/node": "^26.2.0",
38
231
  "tsup": "^8.5.0",
39
232
  "typescript": "^5.8.3",
40
- "vitest": "^3.2.4",
41
- "@trailstep/core": "0.1.1"
233
+ "vitest": "^3.2.4"
42
234
  },
43
235
  "publishConfig": {
44
236
  "access": "public"
@@ -49,7 +241,7 @@
49
241
  "LICENSE"
50
242
  ],
51
243
  "peerDependencies": {
52
- "@trailstep/authoring": "^0.1.2"
244
+ "@trailstep/authoring": "^0.2.0"
53
245
  },
54
246
  "scripts": {
55
247
  "build": "tsup src/index.ts --format esm --dts --sourcemap --clean --loader .md=text",