/** * discuss.ts — Discuss agent for failed user stories. * * Gathers context (failure report, code diff, plan section) for a failed story * and runs an interactive agent session so the user can have a back-and-forth * conversation about the failure and provide guidance for the next attempt. * * The discuss session spawns the configured AI CLI (claude by default) as a * subprocess, passing the failure context as the initial system prompt and * piping stdin/stdout so the user can interact directly with the agent. * * The session ends when: * - The user types 'done' or 'exit' in the conversation * - The user presses Escape (raw mode keypress detection) * - The agent subprocess exits */ export interface DiscussContext { /** The user story ID being discussed (e.g. 'US-018') */ storyId: string; /** The epic ID this story belongs to (e.g. 'EPIC-004') */ epicId: string; /** Failure details parsed from progress.txt */ failureReport: string; /** Git diff of commits relevant to this story */ codeDiff: string; /** The section of the plan file that describes this story */ planSection: string; } export interface FailedStoryContext extends DiscussContext { storyTitle: string; epicTitle: string; failureReason: string | null; } export interface DiscussResult { /** The story ID that was discussed */ storyId: string; /** Concatenated user guidance from the session */ guidance: string; } /** * A function that spawns a discuss agent for the given context prompt and * returns a Promise that resolves with any captured guidance when the session ends. * * Injectable for testing — the default implementation spawns `claude` in * interactive mode so the user can converse directly with the AI. */ export type AgentSpawner = (contextPrompt: string) => Promise; export interface DiscussSessionOptions { /** * Injectable agent spawner function. When omitted, the default spawner * runs `claude` in interactive mode with the context as the initial prompt. */ spawnAgent?: AgentSpawner; /** Backend to launch for the guided session. Defaults to 'claude'. */ backend?: 'claude' | 'copilot' | 'codex' | 'opencode'; } export interface FailedStoriesDiscussOptions { spawnAgent?: AgentSpawner; backend?: 'claude' | 'copilot' | 'codex' | 'opencode'; } /** * Parses progress.txt and extracts all lines related to a given story ID. * * A progress.txt entry starts with a `##` heading that contains the story ID * and continues until the next `---` separator. * * @param progressPath - Absolute path to progress.txt * @param storyId - Story ID to search for (e.g. 'US-018') */ export declare function parseFailureReport(progressPath: string, storyId: string): string; /** * Extracts the plan section for a specific story from a plan markdown file. * * Looks for a heading that contains the story ID and returns all content * until the next same-or-higher-level heading. * * @param plansDir - Directory containing plan files (e.g. 'plans/') * @param epicId - Epic ID used to construct the plan filename * @param storyId - Story ID to find in the plan */ export declare function extractPlanSection(plansDir: string, epicId: string, storyId: string): string; /** * Runs `git log --oneline` in worktreeDir and finds commits related to storyId, * then returns the diff for those commits. * * @param worktreeDir - The git worktree directory to run git commands in * @param storyId - Story ID to search for in commit messages */ export declare function getCodeDiff(worktreeDir: string, storyId: string): string; /** * Finds which epic a story belongs to by reading prd.json. * * @param prdPath - Path to prd.json * @param storyId - Story ID to look up * @returns The epic ID, or empty string if not found */ export declare function findEpicForStory(prdPath: string, storyId: string): string; /** * Gathers all context needed to discuss a failed story. * * @param storyId - The story ID to discuss * @param prdPath - Path to prd.json * @param progressPath - Path to progress.txt * @param plansDir - Directory containing plan markdown files * @param worktreeDir - Git worktree directory for the epic */ export declare function gatherDiscussContext(storyId: string, prdPath: string, progressPath: string, plansDir: string, worktreeDir: string): DiscussContext; /** * Builds the initial system prompt string that is passed to the AI agent. * Contains the failure report, code diff, and plan section for the story. * * @param context - The discuss context for the failed story */ export declare function buildContextPrompt(context: DiscussContext): string; export declare function buildFailedStoriesDiscussPrompt(contexts: FailedStoryContext[]): string; /** * Creates the default agent spawner that invokes `claude` (or the configured * backend) as an interactive child process. * * The context prompt is piped to the agent's stdin as the first message. * stdin/stdout are inherited so the user can interact directly in the terminal. * * Escape key is detected via raw mode on process.stdin. When Escape (\x1b) * is pressed, the agent subprocess is killed and the session ends. * * @param agentCommand - The CLI command to run (default: 'claude') * @param agentArgs - Additional args to pass to the agent (default: []) */ export declare function createDefaultSpawner(backend?: 'claude' | 'copilot' | 'codex' | 'opencode'): AgentSpawner; /** * Runs an interactive discuss session for a failed story by spawning an AI * agent subprocess (default: `claude` CLI). * * The agent receives the full failure context (failure report, code diff, * plan section) as its initial prompt and the user can interact directly. * The session ends when: * - The user types 'done' or 'exit' * - The user presses Escape (detected via raw mode) * - The agent subprocess exits * * For testing, inject a mock `spawnAgent` via options.spawnAgent. The mock * receives the context prompt string and returns a Promise (guidance). * * @param context - The discuss context to present to the agent * @param options - Optional configuration (injectable spawnAgent for testing) * @returns The collected guidance from the session */ export declare function runDiscussSession(context: DiscussContext, options?: DiscussSessionOptions): Promise; export declare function runFailedStoriesDiscussSession(contexts: FailedStoryContext[], options?: FailedStoriesDiscussOptions): Promise; //# sourceMappingURL=discuss.d.ts.map