@autonoma-ai/planner 0.1.1 → 0.1.2
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 +10 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.15_tsx@4.22.3_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js","../src/core/context.ts","../src/core/model.ts","../src/core/display.ts","../src/core/agent.ts","../src/core/gitignore.ts","../src/tools/bash.ts","../src/tools/glob.ts","../src/tools/grep.ts","../src/tools/list-directory.ts","../src/tools/read-file.ts","../src/tools/subagent.ts","../src/tools/write-file.ts","../src/tools/ask-user.ts","../src/tools/index.ts","../src/agents/00-pages-finder/index.ts","../src/core/notify.ts","../src/core/review.ts","../src/agents/01-kb-generator/prompt.ts","../src/agents/01-kb-generator/index.ts","../src/agents/02-entity-audit/prompt.ts","../src/agents/02-entity-audit/index.ts","../src/core/parse-entity-audit.ts","../src/agents/03-scenario-recipe/prompt.ts","../src/agents/03-scenario-recipe/index.ts","../src/agents/04-recipe-builder/state.ts","../src/agents/04-recipe-builder/entity-order.ts","../src/agents/04-recipe-builder/phases/tech-detect.ts","../src/core/detect-pkg-manager.ts","../src/core/highlight.ts","../src/agents/04-recipe-builder/recipe.ts","../src/agents/04-recipe-builder/http-client.ts","../src/agents/04-recipe-builder/phases/entity-loop.ts","../src/agents/04-recipe-builder/phases/full-validation.ts","../src/agents/04-recipe-builder/phases/submit.ts","../src/agents/04-recipe-builder/index.ts","../src/agents/05-test-generator/rubrics.ts","../src/agents/05-test-generator/review-pass.ts","../src/agents/05-test-generator/review.ts","../src/agents/05-test-generator/graph.ts","../src/agents/00b-feature-discovery/index.ts","../src/agents/05-test-generator/validation.ts","../src/agents/05-test-generator/tools.ts","../src/agents/05-test-generator/prompt.ts","../src/agents/05-test-generator/index.ts","../src/index.ts","../src/config.ts","../src/core/output.ts","../src/core/state.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ProjectContext {\n description: string;\n testingGoal: string;\n criticalFlows: string;\n pages?: Array<{ route: string; path: string; description: string }>;\n}\n\nconst CONTEXT_FILE = \".project-context.json\";\n\nexport async function saveContext(outputDir: string, ctx: ProjectContext): Promise<void> {\n await writeFile(join(outputDir, CONTEXT_FILE), JSON.stringify(ctx, null, 2), \"utf-8\");\n}\n\nexport async function loadContext(outputDir: string): Promise<ProjectContext | null> {\n try {\n const raw = await readFile(join(outputDir, CONTEXT_FILE), \"utf-8\");\n return JSON.parse(raw) as ProjectContext;\n } catch {\n return null;\n }\n}\n\nexport function formatContext(ctx: ProjectContext): string {\n let output = `## Project Context (from the user)\n\n**What this project is:** ${ctx.description}\n\n**Why they want testing:** ${ctx.testingGoal}\n\n**Critical flows to prioritize:** ${ctx.criticalFlows}\n\nUse this context to prioritize your exploration. Start with the critical flows the user mentioned, then expand to cover the rest of the application.`;\n\n if (ctx.pages?.length) {\n output += `\\n\\n## Discovered Pages (${ctx.pages.length} routes)\\n\\n`;\n output += ctx.pages\n .map((p) => `- \\`${p.route}\\` — ${p.description} (\\`${p.path}\\`)`)\n .join(\"\\n\");\n }\n\n return output;\n}\n","import { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n\nexport const DEFAULT_MODEL = \"google/gemini-3-flash-preview\";\n\nlet provider: ReturnType<typeof createOpenRouter> | null = null;\n\nfunction getProvider() {\n if (provider == null) {\n const apiKey = process.env.OPENROUTER_API_KEY;\n if (!apiKey) throw new Error(\"OPENROUTER_API_KEY is required\");\n provider = createOpenRouter({ apiKey });\n }\n return provider;\n}\n\nexport function getModel(modelId?: string) {\n return getProvider().languageModel(modelId ?? process.env.OPENROUTER_MODEL ?? DEFAULT_MODEL);\n}\n","const DIM = \"\\x1b[2m\";\nconst RESET = \"\\x1b[0m\";\nconst CYAN = \"\\x1b[36m\";\nconst GREEN = \"\\x1b[32m\";\nconst RED = \"\\x1b[31m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\nfunction formatArgs(input: Record<string, unknown>, keys: string[]): string {\n const parts: string[] = [];\n for (const key of keys) {\n if (key in input && input[key] !== undefined && input[key] !== null) {\n parts.push(`${key}=${String(input[key])}`);\n }\n }\n return parts.join(\" \");\n}\n\nfunction toolCallSummary(name: string, input: Record<string, unknown>): string {\n switch (name) {\n case \"read_file\":\n case \"read_output\": {\n const path = String(\n input.filePath ?? input.path ?? input.file_path ?? \"\",\n );\n const range = formatArgs(input, [\"offset\", \"limit\"]);\n return range ? `${path} (${range})` : path;\n }\n case \"write_file\":\n return String(input.filePath ?? input.path ?? input.file_path ?? \"\");\n case \"glob\":\n return formatArgs(input, [\"pattern\", \"path\"]);\n case \"grep\":\n return formatArgs(input, [\"query\", \"pattern\", \"path\", \"include\"]);\n case \"bash\":\n return String(input.command ?? \"\");\n case \"list_directory\":\n return formatArgs(input, [\"path\", \"depth\"]);\n case \"subagent\":\n case \"spawn_researcher\":\n return String(input.task ?? input.instruction ?? input.prompt ?? \"\");\n case \"write_test\":\n return formatArgs(input, [\"folder\", \"filename\"]);\n case \"enqueue_node\":\n return formatArgs(input, [\"id\", \"name\"]);\n case \"mark_visited\":\n return formatArgs(input, [\"files\"]);\n case \"get_coverage\":\n return formatArgs(input, [\"detail\"]);\n case \"finish\":\n return \"\";\n default: {\n const keys = Object.keys(input);\n if (keys.length === 0) return \"\";\n return keys.map((k) => `${k}=${String(input[k])}`).join(\" \");\n }\n }\n}\n\nconst SPINNER_FRAMES = [\"◒\", \"◐\", \"◓\", \"◑\"];\n\nexport interface StepInfo {\n stepNumber: number;\n maxSteps: number;\n reasoningText?: string;\n text: string;\n toolCalls: { name: string; input: Record<string, unknown> }[];\n toolErrors: { name: string; error: unknown }[];\n writtenFiles: string[];\n}\n\nexport interface ProgressStats {\n filesRead: number;\n filesWritten: number;\n}\n\nconst CLEAR_LINE = \"\\x1b[2K\\r\";\n\nexport function createStepLogger(agentId: string, maxSteps: number) {\n const stats: ProgressStats = {\n filesRead: 0,\n filesWritten: 0,\n };\n let frameIdx = 0;\n let lastSpinnerLine = false;\n\n function clearSpinner() {\n if (lastSpinnerLine) {\n process.stderr.write(CLEAR_LINE);\n lastSpinnerLine = false;\n }\n }\n\n function writeSpinner(message: string) {\n const frame = SPINNER_FRAMES[frameIdx % SPINNER_FRAMES.length];\n frameIdx++;\n process.stderr.write(`${CLEAR_LINE} ${DIM}${frame} ${message}${RESET}`);\n lastSpinnerLine = true;\n }\n\n function writePermanent(message: string) {\n clearSpinner();\n console.log(message);\n }\n\n function log(info: StepInfo) {\n const stepPrefix = `[${agentId}] ${info.stepNumber + 1}/${maxSteps}`;\n\n for (const tc of info.toolCalls) {\n const summary = toolCallSummary(tc.name, tc.input);\n\n switch (tc.name) {\n case \"read_file\":\n case \"read_output\":\n stats.filesRead++;\n writeSpinner(`${stepPrefix} — reading ${summary}`);\n break;\n\n case \"glob\":\n writeSpinner(`${stepPrefix} — glob ${summary}`);\n break;\n\n case \"grep\":\n writeSpinner(`${stepPrefix} — grep ${summary}`);\n break;\n\n case \"list_directory\":\n writeSpinner(`${stepPrefix} — listing ${summary}`);\n break;\n\n case \"bash\":\n writeSpinner(`${stepPrefix} — bash: ${summary}`);\n break;\n\n case \"write_file\": {\n stats.filesWritten++;\n const path = String(tc.input.path ?? tc.input.file_path ?? \"\");\n writePermanent(` ${GREEN}✎ write ${path}${RESET}`);\n break;\n }\n\n case \"write_test\":\n stats.filesWritten++;\n writePermanent(` ${GREEN}✎ test ${summary}${RESET}`);\n break;\n\n case \"finish\":\n writePermanent(` ${GREEN}${BOLD}✓ finish${RESET}`);\n break;\n\n case \"subagent\":\n case \"spawn_researcher\":\n writePermanent(` ${CYAN}⊕ subagent: ${summary}${RESET}`);\n break;\n\n default:\n writeSpinner(`${stepPrefix} — ${tc.name}${summary ? \" \" + summary : \"\"}`);\n }\n }\n\n for (const te of info.toolErrors) {\n writePermanent(` ${RED}✗ ${te.name}: ${te.error}${RESET}`);\n }\n\n for (const f of info.writtenFiles) {\n writePermanent(` ${GREEN}📄 wrote: ${f}${RESET}`);\n }\n }\n\n function checkpoint(message: string) {\n writePermanent(` ${YELLOW}▸ ${message}${RESET}`);\n }\n\n function summary() {\n clearSpinner();\n if (stats.filesRead > 0 || stats.filesWritten > 0) {\n console.log(` ${DIM}────────────────────────────────${RESET}`);\n console.log(\n ` ${DIM}files read: ${stats.filesRead} | files written: ${stats.filesWritten}${RESET}`,\n );\n }\n }\n\n return { log, checkpoint, summary, stats };\n}\n","import {\n type LanguageModel,\n type ToolSet,\n ToolLoopAgent,\n hasToolCall,\n stepCountIs,\n} from \"ai\";\nimport { createStepLogger, type StepInfo } from \"./display\";\nimport { getModel } from \"./model\";\n\nconst FALLBACK_MODELS = [\n \"moonshotai/kimi-k2.6\",\n \"deepseek/deepseek-v4-pro\",\n \"openai/gpt-5.4-nano\",\n];\n\nconst RETRIES_BEFORE_FALLBACK = 3;\nconst STEP_TIMEOUT_MS = 120_000;\n\nexport interface AgentConfig {\n id: string;\n systemPrompt: string;\n tools: ToolSet | ((heartbeat: () => void) => ToolSet | Promise<ToolSet>);\n model: LanguageModel;\n maxSteps: number;\n temperature?: number;\n stepTimeoutMs?: number;\n onStepFinish?: (info: StepInfo) => void;\n}\n\nexport interface AgentContext {\n projectRoot: string;\n outputDir: string;\n}\n\nexport interface AgentResult {\n success: boolean;\n paused?: boolean;\n artifacts: string[];\n summary: string;\n}\n\nexport function buildDefaultStepLogger(agentId: string, maxSteps: number) {\n const logger = createStepLogger(agentId, maxSteps);\n\n return {\n logger,\n onStepFinish: (info: StepInfo) => {\n logger.log(info);\n },\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction buildStepHandler(config: AgentConfig) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (step: any) => {\n if (!config.onStepFinish) return;\n\n const toolErrors: { name: string; error: unknown }[] = [];\n const writtenFiles: string[] = [];\n\n for (const part of step.content) {\n if (part.type === \"tool-error\") {\n toolErrors.push({ name: part.toolName, error: part.error });\n }\n if (part.type === \"tool-result\" && part.toolName === \"write_file\") {\n const output = part.output;\n if (typeof output === \"object\" && output !== null && \"path\" in output) {\n writtenFiles.push(String((output as Record<string, unknown>).path));\n }\n }\n }\n\n config.onStepFinish({\n stepNumber: step.stepNumber,\n maxSteps: config.maxSteps,\n reasoningText: step.reasoningText ?? undefined,\n text: step.text,\n toolCalls: step.toolCalls.map((tc: { toolName: string; input: unknown }) => ({\n name: tc.toolName,\n input: tc.input as Record<string, unknown>,\n })),\n toolErrors,\n writtenFiles,\n });\n };\n}\n\nexport async function runAgent<T>(\n config: AgentConfig,\n prompt: string,\n extractResult: () => T | undefined,\n): Promise<T | undefined> {\n const stepTimeout = config.stepTimeoutMs ?? STEP_TIMEOUT_MS;\n const modelsToTry = [config.model, ...FALLBACK_MODELS.map((id) => getModel(id))];\n\n const YELLOW = \"\\x1b[33m\";\n const RESET = \"\\x1b[0m\";\n\n for (let modelIdx = 0; modelIdx < modelsToTry.length; modelIdx++) {\n const model = modelsToTry[modelIdx]!;\n\n for (let retry = 0; retry < RETRIES_BEFORE_FALLBACK; retry++) {\n const heartbeat = () => {};\n const tools = typeof config.tools === \"function\"\n ? await config.tools(heartbeat)\n : config.tools;\n\n const agent = new ToolLoopAgent({\n model,\n instructions: config.systemPrompt,\n tools,\n temperature: config.temperature,\n stopWhen: [stepCountIs(config.maxSteps), hasToolCall(\"finish\")],\n onStepFinish: buildStepHandler(config),\n });\n\n try {\n await agent.generate({\n messages: [{ role: \"user\", content: prompt }],\n timeout: { stepMs: stepTimeout },\n });\n\n return extractResult();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const isTimeout = msg.includes(\"timed out\") || msg.includes(\"timeout\") || msg.includes(\"abort\");\n\n if (!isTimeout) throw err;\n\n console.log(` ${YELLOW}[${config.id}] step timed out after ${stepTimeout / 1000}s${RESET}`);\n\n if (retry < RETRIES_BEFORE_FALLBACK - 1) {\n console.log(\n ` ${YELLOW}[${config.id}] retrying (${retry + 1}/${RETRIES_BEFORE_FALLBACK})...${RESET}`,\n );\n continue;\n }\n\n if (modelIdx < modelsToTry.length - 1) {\n const nextModel = FALLBACK_MODELS[modelIdx];\n console.log(\n ` ${YELLOW}[${config.id}] ${RETRIES_BEFORE_FALLBACK} timeouts, switching to ${nextModel}${RESET}`,\n );\n break;\n }\n\n throw err;\n }\n }\n }\n\n return extractResult();\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { glob } from \"glob\";\n\nexport async function loadGitignorePatterns(\n projectRoot: string,\n): Promise<string[]> {\n const patterns: string[] = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.git/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/.nuxt/**\",\n \"**/coverage/**\",\n \"**/.turbo/**\",\n \"**/__pycache__/**\",\n \"**/.venv/**\",\n \"**/venv/**\",\n \"**/.cache/**\",\n \"**/.parcel-cache/**\",\n ];\n\n const matches = await glob(\"**/.gitignore\", { cwd: projectRoot, dot: true });\n for (const match of matches) {\n const fullPath = join(projectRoot, match);\n try {\n const content = await readFile(fullPath, \"utf-8\");\n const prefix = relative(projectRoot, join(projectRoot, match, \"..\"));\n const parsed = parseGitignore(content, prefix);\n patterns.push(...parsed);\n } catch (err) {\n // unreadable gitignore, skip\n console.error(`there was an error trying to read the gitignore on ${fullPath}. skipping.`, err)\n }\n }\n\n return [...new Set(patterns)];\n}\n\nexport function parseGitignore(content: string, prefix = \"\"): string[] {\n return content\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"))\n .map((line) => gitignoreToGlob(line, prefix));\n}\n\nfunction gitignoreToGlob(pattern: string, prefix: string): string {\n let negated = false;\n if (pattern.startsWith(\"!\")) {\n negated = true;\n pattern = pattern.slice(1);\n }\n\n if (pattern.startsWith(\"/\")) {\n pattern = pattern.slice(1);\n if (prefix) pattern = `${prefix}/${pattern}`;\n } else if (!pattern.includes(\"/\")) {\n pattern = prefix ? `${prefix}/**/${pattern}` : `**/${pattern}`;\n } else {\n if (prefix) pattern = `${prefix}/${pattern}`;\n }\n\n if (pattern.endsWith(\"/\")) {\n pattern = `${pattern}**`;\n }\n\n return negated ? `!${pattern}` : pattern;\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CHAINING_OPERATORS = /;|&&|\\|\\||`|\\$\\(|>>|<<|&\\s*$/;\n\nconst DEFAULT_ALLOWED = new Set([\n \"git\", \"wc\", \"sort\", \"head\", \"tail\", \"cat\", \"ls\", \"find\", \"diff\", \"echo\",\n]);\n\nconst TIMEOUT_MS = 30_000;\nconst MAX_OUTPUT_BYTES = 1024 * 512;\n\nconst inputSchema = z.object({\n command: z.string().describe(\"Shell command to execute\"),\n});\n\ninterface BashResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nexport function validateCommand(\n command: string,\n allowed: Set<string>,\n): string | undefined {\n const trimmed = command.trim();\n if (trimmed.length === 0) return \"Empty command\";\n\n if (CHAINING_OPERATORS.test(trimmed)) {\n return \"Command chaining (;, &&, ||), subshells, and redirects are not allowed. Use pipes (|) instead.\";\n }\n\n const segments = trimmed.split(/\\s*\\|\\s*/);\n for (const segment of segments) {\n const binary = segment.trim().split(/\\s+/)[0];\n if (binary == null || !allowed.has(binary)) {\n return `Command \"${binary ?? \"\"}\" is not allowed. Allowed: ${[...allowed].join(\", \")}`;\n }\n }\n\n return undefined;\n}\n\nexport function buildBashTool(\n workingDirectory: string,\n allowedCommands?: Set<string>,\n) {\n const allowed = allowedCommands ?? DEFAULT_ALLOWED;\n\n return tool({\n description:\n \"Execute a shell command. Primarily for git, ls, find, and basic unix utilities. \" +\n \"Pipes allowed; chaining (;, &&, ||) is not.\",\n inputSchema,\n execute: async (input): Promise<BashResult> => {\n const error = validateCommand(input.command, allowed);\n if (error != null) {\n return { exitCode: 1, stdout: \"\", stderr: error };\n }\n\n try {\n const { stdout, stderr } = await execFileAsync(\n \"sh\",\n [\"-c\", input.command],\n {\n cwd: workingDirectory,\n maxBuffer: MAX_OUTPUT_BYTES,\n timeout: TIMEOUT_MS,\n },\n );\n return {\n exitCode: 0,\n stdout: stdout.trimEnd(),\n stderr: stderr.trimEnd(),\n };\n } catch (err) {\n const execErr = err as {\n code?: number;\n stdout?: string;\n stderr?: string;\n killed?: boolean;\n };\n\n if (execErr.killed) {\n return {\n exitCode: 1,\n stdout: \"\",\n stderr: `Command timed out after ${TIMEOUT_MS / 1000}s`,\n };\n }\n\n return {\n exitCode: typeof execErr.code === \"number\" ? execErr.code : 1,\n stdout: execErr.stdout?.trimEnd() ?? \"\",\n stderr: execErr.stderr?.trimEnd() ?? \"\",\n };\n }\n },\n });\n}\n","import { tool } from \"ai\";\nimport { glob } from \"glob\";\nimport { z } from \"zod\";\n\nconst inputSchema = z.object({\n pattern: z.string().describe(\"Glob pattern to match files (e.g. '**/*.ts', 'src/**/*.py')\"),\n cwd: z.string().optional().describe(\"Directory to search in. Defaults to working directory.\"),\n});\n\nconst DEFAULT_IGNORE = [\"**/node_modules/**\", \"**/dist/**\", \"**/.git/**\"];\n\nexport interface GlobResult {\n matches: string[];\n count: number;\n error?: string;\n}\n\nexport async function executeGlob(\n pattern: string,\n cwd: string,\n ignorePatterns: string[] = DEFAULT_IGNORE,\n): Promise<GlobResult> {\n try {\n const matches = await glob(pattern, {\n cwd,\n nodir: true,\n ignore: ignorePatterns,\n });\n return { matches, count: matches.length };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Glob failed: ${message}`, matches: [], count: 0 };\n }\n}\n\nexport function buildGlobTool(workingDirectory: string, ignorePatterns?: string[]) {\n const ignore = ignorePatterns ?? DEFAULT_IGNORE;\n\n return tool({\n description:\n \"Find files matching a glob pattern. Returns paths relative to working directory.\",\n inputSchema,\n execute: (input) => executeGlob(input.pattern, input.cwd ?? workingDirectory, ignore),\n });\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst execFileAsync = promisify(execFile);\n\nconst inputSchema = z.object({\n pattern: z.string().describe(\"Regex pattern to search for in file contents\"),\n glob: z.string().optional().describe(\"Glob to filter files (e.g. '*.ts')\"),\n path: z.string().optional().describe(\"File or directory to search in\"),\n});\n\nexport function buildGrepTool(workingDirectory: string) {\n return tool({\n description:\n \"Search file contents with ripgrep. Returns matching lines with file paths and line numbers.\",\n inputSchema,\n execute: async (input) => {\n const args = [\n \"--no-heading\",\n \"--line-number\",\n \"--max-count=50\",\n \"--glob=!node_modules\",\n \"--glob=!dist\",\n \"--glob=!.git\",\n ];\n\n if (input.glob != null) {\n args.push(`--glob=${input.glob}`);\n }\n\n args.push(input.pattern);\n args.push(input.path ?? workingDirectory);\n\n try {\n const { stdout } = await execFileAsync(\"rg\", args, {\n cwd: workingDirectory,\n maxBuffer: 1024 * 1024,\n });\n\n const lines = stdout.trim().split(\"\\n\").filter(Boolean);\n return { matches: lines, count: lines.length };\n } catch (error) {\n const execError = error as { code?: number; stdout?: string };\n if (execError.code === 1) {\n return { matches: [], count: 0 };\n }\n const message = error instanceof Error ? error.message : String(error);\n return { error: `Grep failed: ${message}`, matches: [], count: 0 };\n }\n },\n });\n}\n","import { readdir } from \"node:fs/promises\";\nimport { stat } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { minimatch } from \"minimatch\";\nimport { loadGitignorePatterns } from \"../core/gitignore\";\n\n\ninterface TreeEntry {\n name: string;\n type: \"file\" | \"dir\";\n children?: TreeEntry[];\n}\n\nfunction buildMatcher(patterns: string[]): (path: string) => boolean {\n const positive = patterns.filter((p) => !p.startsWith(\"!\"));\n const negative = patterns.filter((p) => p.startsWith(\"!\")).map((p) => p.slice(1));\n\n return (path: string) => {\n const ignored = positive.some((p) => minimatch(path, p, { dot: true }));\n if (!ignored) return false;\n const restored = negative.some((p) => minimatch(path, p, { dot: true }));\n return !restored;\n };\n}\n\nasync function buildTree(\n dirPath: string,\n maxDepth: number,\n currentDepth: number,\n isIgnored?: (relativePath: string) => boolean,\n relativeBase?: string,\n): Promise<TreeEntry[]> {\n if (currentDepth >= maxDepth) return [];\n\n let rawEntries: string[];\n try {\n rawEntries = await readdir(dirPath);\n } catch {\n return [];\n }\n\n const withTypes: { name: string; isDir: boolean }[] = [];\n for (const name of rawEntries) {\n try {\n const s = await stat(join(dirPath, name));\n withTypes.push({ name, isDir: s.isDirectory() });\n } catch {\n withTypes.push({ name, isDir: false });\n }\n }\n\n withTypes.sort((a, b) => {\n if (a.isDir && !b.isDir) return -1;\n if (!a.isDir && b.isDir) return 1;\n return a.name.localeCompare(b.name);\n });\n\n const result: TreeEntry[] = [];\n\n for (const entry of withTypes) {\n const entryRelPath = relativeBase\n ? `${relativeBase}/${entry.name}`\n : entry.name;\n\n if (isIgnored) {\n const checkPath = entry.isDir ? `${entryRelPath}/` : entryRelPath;\n if (isIgnored(checkPath) || isIgnored(entryRelPath)) continue;\n }\n\n if (entry.isDir) {\n const children = await buildTree(\n join(dirPath, entry.name),\n maxDepth,\n currentDepth + 1,\n isIgnored,\n entryRelPath,\n );\n result.push({ name: entry.name, type: \"dir\", children });\n } else {\n result.push({ name: entry.name, type: \"file\" });\n }\n }\n\n return result;\n}\n\nfunction renderTree(entries: TreeEntry[], prefix = \"\"): string {\n const lines: string[] = [];\n\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i]!;\n const isLast = i === entries.length - 1;\n const connector = isLast ? \"└── \" : \"├── \";\n const childPrefix = isLast ? \" \" : \"│ \";\n\n if (entry.type === \"dir\") {\n const suffix = entry.children?.length ? \"/\" : \"/ (empty)\";\n lines.push(`${prefix}${connector}${entry.name}${suffix}`);\n if (entry.children?.length) {\n lines.push(renderTree(entry.children, prefix + childPrefix));\n }\n } else {\n lines.push(`${prefix}${connector}${entry.name}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport async function buildListDirectoryTool(\n workingDirectory: string,\n) {\n const seen = new Set<string>();\n const patterns = await loadGitignorePatterns(workingDirectory);\n const isIgnored = buildMatcher(patterns);\n\n return tool({\n description:\n \"List directory structure as a tree. Use this for an overview of the project layout. \" +\n \"Start at the root (path='.') with depth 3, then increase depth or narrow path if needed. \" +\n \"Do NOT call this on every subdirectory — use glob to find specific files instead. \" +\n \"Returns cached result if the same path+depth was already requested.\",\n inputSchema: z.object({\n path: z\n .string()\n .default(\".\")\n .describe(\"Directory path relative to project root. Defaults to root.\"),\n depth: z\n .number()\n .min(1)\n .max(15)\n .default(10)\n .describe(\"Max depth to traverse (1-15). Default 10.\"),\n gitignore: z.boolean()\n .describe(\"Whether to respect the gitignore or to ignore it. true will respect it. false \" +\n \"will ignore it. Default true\")\n .default(true)\n }),\n execute: async (input) => {\n const cacheKey = `${input.path}:${input.depth}`;\n if (seen.has(cacheKey)) {\n return {\n error: `Already listed ${input.path} at depth ${input.depth}. Use glob to find specific files, or read_file to read a known file.`,\n };\n }\n seen.add(cacheKey);\n\n const targetDir = input.path === \".\"\n ? workingDirectory\n : join(workingDirectory, input.path);\n\n try {\n const s = await stat(targetDir);\n if (!s.isDirectory()) {\n return { error: `Not a directory: ${input.path}` };\n }\n } catch {\n return { error: `Directory not found: ${input.path}` };\n }\n\n const relBase = targetDir === workingDirectory\n ? \"\"\n : relative(workingDirectory, targetDir);\n const maybeIgnored = input.gitignore ? isIgnored : undefined;\n\n const tree = await buildTree(targetDir, input.depth, 0, maybeIgnored, relBase || undefined);\n const rendered = renderTree(tree);\n const relPath = relative(workingDirectory, targetDir) || \".\";\n\n return {\n path: relPath,\n depth: input.depth,\n tree: `${relPath}/\\n${rendered}`,\n };\n },\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst MAX_LINES = 2000;\n\nconst inputSchema = z.object({\n filePath: z.string().describe(\"Path to the file (absolute or relative to working directory)\"),\n offset: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe(\"Line number to start reading from (0-based)\"),\n limit: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe(\"Maximum number of lines to read\"),\n});\n\nexport interface ReadFileResult {\n path?: string;\n content?: string;\n totalLines?: number;\n linesShown?: number;\n startLine?: number;\n endLine?: number;\n error?: string;\n}\n\nexport function resolveSandboxedPath(\n workingDirectory: string,\n filePath: string,\n): { absolutePath: string; relativePath: string } | { error: string } {\n const absolutePath = resolve(workingDirectory, filePath);\n const relativePath = relative(workingDirectory, absolutePath);\n\n if (relativePath.startsWith(\"..\")) {\n return { error: \"Cannot read files outside the working directory\" };\n }\n\n return { absolutePath, relativePath };\n}\n\nexport function sliceLines(\n content: string,\n offset: number,\n limit: number,\n): { numbered: string; totalLines: number; linesShown: number; startLine: number; endLine: number } {\n const allLines = content.split(\"\\n\");\n const lines = allLines.slice(offset, offset + limit);\n const numbered = lines\n .map((line, i) => `${offset + i + 1}\\t${line}`)\n .join(\"\\n\");\n\n return {\n numbered,\n totalLines: allLines.length,\n linesShown: lines.length,\n startLine: offset + 1,\n endLine: offset + lines.length,\n };\n}\n\nexport async function executeReadFile(\n workingDirectory: string,\n filePath: string,\n offset?: number,\n limit?: number,\n): Promise<ReadFileResult> {\n const resolved = resolveSandboxedPath(workingDirectory, filePath);\n if (\"error\" in resolved) return resolved;\n\n try {\n const content = await readFile(resolved.absolutePath, \"utf-8\");\n const sliced = sliceLines(content, offset ?? 0, limit ?? MAX_LINES);\n\n return {\n path: resolved.relativePath,\n content: sliced.numbered,\n totalLines: sliced.totalLines,\n linesShown: sliced.linesShown,\n startLine: sliced.startLine,\n endLine: sliced.endLine,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to read file: ${message}` };\n }\n}\n\nexport function buildReadFileTool(workingDirectory: string) {\n return tool({\n description:\n \"Read file contents with line numbers. Use offset and limit for large files.\",\n inputSchema,\n execute: (input) =>\n executeReadFile(workingDirectory, input.filePath, input.offset, input.limit),\n });\n}\n","import {\n type LanguageModel,\n ToolLoopAgent,\n hasToolCall,\n stepCountIs,\n tool,\n} from \"ai\";\nimport { z } from \"zod\";\nimport { buildBashTool } from \"./bash\";\nimport { buildGlobTool } from \"./glob\";\nimport { buildGrepTool } from \"./grep\";\nimport { buildReadFileTool } from \"./read-file\";\n\nconst inputSchema = z.object({\n instruction: z\n .string()\n .describe(\"Focused task for the subagent. Be specific about files and patterns to investigate.\"),\n});\n\nconst resultSchema = z.object({\n findings: z.string().describe(\"Summary of what was found\"),\n});\n\ntype SubagentResult = z.infer<typeof resultSchema>;\n\nconst SYSTEM_PROMPT = `You are a code research assistant. You have tools to explore a codebase: bash (shell commands, mainly git), glob (find files), grep (search content), and read_file (read files).\n\nFollow the instruction you're given. Explore the codebase, then call finish with a summary of your findings.\n\nBe thorough but focused - only investigate what's relevant to your instruction.`;\n\nfunction buildSubagentTools(workingDirectory: string, onFileRead?: (path: string) => void) {\n const baseReadFile = buildReadFileTool(workingDirectory);\n const readFile = onFileRead\n ? tool({\n description: baseReadFile.description,\n inputSchema: baseReadFile.inputSchema,\n execute: async (input, options) => {\n const filePath = (input as { filePath?: string; path?: string; file_path?: string }).filePath\n ?? (input as { path?: string }).path\n ?? (input as { file_path?: string }).file_path\n ?? \"\";\n onFileRead(filePath);\n return baseReadFile.execute!(input, options);\n },\n })\n : baseReadFile;\n\n return {\n bash: buildBashTool(workingDirectory),\n glob: buildGlobTool(workingDirectory),\n grep: buildGrepTool(workingDirectory),\n read_file: readFile,\n };\n}\n\nexport function buildSubagentTool(\n model: LanguageModel,\n workingDirectory: string,\n onHeartbeat?: () => void,\n onFileRead?: (path: string) => void,\n) {\n return tool({\n description:\n \"Spawn a subagent to research a specific part of the codebase. \" +\n \"Each subagent has glob, grep, read_file, and bash tools. \" +\n \"Give a focused, specific instruction.\",\n inputSchema,\n execute: async (input) => {\n let result: SubagentResult | undefined;\n\n const subagent = new ToolLoopAgent({\n model,\n instructions: SYSTEM_PROMPT,\n tools: {\n ...buildSubagentTools(workingDirectory, onFileRead),\n finish: tool({\n description: \"Call when you have completed your research.\",\n inputSchema: resultSchema,\n execute: async (output) => {\n result = output;\n },\n }),\n },\n stopWhen: [stepCountIs(15), hasToolCall(\"finish\")],\n onStepFinish: () => { onHeartbeat?.(); },\n });\n\n try {\n await subagent.generate({\n messages: [{ role: \"user\", content: input.instruction }],\n });\n return { findings: result?.findings ?? \"Subagent did not produce findings\" };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { findings: `Subagent error: ${message}` };\n }\n },\n });\n}\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst inputSchema = z.object({\n filePath: z.string().describe(\"Path to write (absolute or relative to output directory)\"),\n content: z.string().describe(\"File content to write\"),\n});\n\nexport interface WriteFileResult {\n path?: string;\n bytesWritten?: number;\n error?: string;\n}\n\nexport async function executeWriteFile(\n outputDirectory: string,\n filePath: string,\n content: string,\n): Promise<WriteFileResult> {\n const cleaned = filePath.replace(/^autonoma\\//, \"\");\n const absolutePath = resolve(outputDirectory, cleaned);\n const relativePath = relative(outputDirectory, absolutePath);\n\n if (relativePath.startsWith(\"..\")) {\n return { error: \"Cannot write files outside the output directory\" };\n }\n\n try {\n await mkdir(dirname(absolutePath), { recursive: true });\n await writeFile(absolutePath, content, \"utf-8\");\n return { path: relativePath, bytesWritten: content.length };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to write file: ${message}` };\n }\n}\n\nexport function buildWriteFileTool(outputDirectory: string) {\n return tool({\n description:\n \"Write content to a file in the output directory. Creates parent directories as needed.\",\n inputSchema,\n execute: (input) => executeWriteFile(outputDirectory, input.filePath, input.content),\n });\n}\n","import * as p from \"@clack/prompts\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nexport function buildAskUserTool() {\n return tool({\n description:\n \"Ask the user a question ONLY when the answer is truly unknowable from the codebase. \" +\n \"Valid reasons: untyped JSON/JSONB field schemas, business rules not in code, config values not in source. \" +\n \"NEVER ask about: field names (read the schema), field types (read the ORM model), \" +\n \"enum values (read the code), relationships (read foreign keys), numeric values (read the seed data or defaults). \" +\n \"If you can find it by reading a file, DO NOT ask — read the file instead.\",\n inputSchema: z.object({\n question: z.string().describe(\n \"A clear, plain-language question. State exactly what you need to know and why you can't find it in code. \" +\n \"BAD: 'What are the decimal values for checking_balance?' — GOOD: 'Your Account model has a metadata JSON column with no type definition. What fields go inside it?'\",\n ),\n }),\n execute: async (input) => {\n const answer = await p.text({ message: input.question });\n if (p.isCancel(answer)) return { answer: \"User skipped this question\" };\n return { answer: answer as string };\n },\n });\n}\n","import type { LanguageModel } from \"ai\";\nimport { loadGitignorePatterns } from \"../core/gitignore\";\nimport { buildBashTool } from \"./bash\";\nimport { buildGlobTool } from \"./glob\";\nimport { buildGrepTool } from \"./grep\";\nimport { buildListDirectoryTool } from \"./list-directory\";\nimport { buildReadFileTool } from \"./read-file\";\nimport { buildSubagentTool } from \"./subagent\";\nimport { buildWriteFileTool } from \"./write-file\";\n\nexport async function buildCodebaseTools(\n model: LanguageModel,\n projectRoot: string,\n outputDir: string,\n onHeartbeat?: () => void,\n onFileRead?: (path: string) => void,\n) {\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n\n return {\n read_file: buildReadFileTool(projectRoot),\n read_output: buildReadFileTool(outputDir),\n write_file: buildWriteFileTool(outputDir),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n grep: buildGrepTool(projectRoot),\n bash: buildBashTool(projectRoot),\n list_directory: await buildListDirectoryTool(projectRoot),\n subagent: buildSubagentTool(model, projectRoot, onHeartbeat, onFileRead),\n };\n}\n\nexport {\n buildBashTool,\n buildGlobTool,\n buildGrepTool,\n buildListDirectoryTool,\n buildReadFileTool,\n buildSubagentTool,\n buildWriteFileTool,\n};\n\nexport { buildAskUserTool } from \"./ask-user\";\n","import {type AgentResult, buildDefaultStepLogger, runAgent} from \"../../core/agent.ts\";\nimport {getModel} from \"../../core/model.ts\";\nimport {buildCodebaseTools} from \"../../tools\";\nimport * as path from \"node:path\";\nimport {z} from \"zod\"\nimport {existsSync} from \"fs\"\nimport {tool} from \"ai\";\n\nexport interface PageFinderGeneratorInput {\n projectRoot: string;\n modelId?: string;\n nonInteractive?: boolean;\n outputDir: string\n extraMessage?: string\n}\n\nconst Page = z.object({\n route: z.string().min(1),\n path: z.string().min(1),\n description: z.string().min(10)\n})\ntype Page = z.infer<typeof Page>\n\nclass PageCollector {\n // the key is the path\n readonly pages = new Map<string, Page>()\n\n addPage(page: Page): void {\n if (this.pages.has(page.path)) {\n console.warn(`page with path ${page.path} was already set. overwritting`)\n }\n this.pages.set(page.path, page)\n }\n\n viewPages(): string {\n return Array.from(this.pages)\n .sort(([aKey, aValue], [bKey, bValue]) => aValue.path.localeCompare(bValue.path))\n .join(\"\\n\")\n }\n\n static from(obj: unknown): Page | Error {\n const result = Page.safeParse(obj);\n if (!result.success) return result.error\n\n const data = result.data\n\n const foundPath = path.resolve(data.path)\n if (!existsSync(foundPath)) {\n return new Error(`resolved path ${foundPath} from returned path ${data.path} didn't exist`)\n }\n\n return data\n }\n}\n\nexport async function runPageFinder(input: PageFinderGeneratorInput): Promise<Map<string, Page>> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n const pageCollector = new PageCollector();\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"kb\", 150);\n\n let prompt = `You need to run the search on this directory ${input.projectRoot}.`;\n\n if (input.extraMessage != null) {\n prompt += `\\n${input.extraMessage}`\n }\n\n const agentConfig = {\n id: \"pages-finder\",\n systemPrompt: \"You are an agent in charge of finding all the pages in a codebase. You have a set of tools for \" +\n \"exploring the codebase and you're encouraged to use them extensively. Once you find a page, call the add_page tool.\\n\\n\" +\n \"The objective is to capture 100% of all the pages on the codebase. A page is a top-level route that renders a distinct view.\\n\\n\" +\n \"Start by understanding which technologies and frameworks the project uses — read config files, package manifests, \" +\n \"and project structure. Then use glob, grep, and list_directory to find all route/page definitions based on what you discover.\\n\\n\" +\n \"Ignore storybooks, docs, and test files. Focus on pages of the main application.\\n\\n\" +\n \"For monorepos: identify which package/app is the main frontend application and focus your search there.\\n\\n\" +\n \"Consider that list_directory has a default depth of 10 and you WON'T SEE MORE CHILDREN. \" +\n \"If you do list_directory, drill down to validate there are no more levels.\",\n model,\n maxSteps: 150,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n add_page: tool({\n description: \"use this tool to add a page that you found\",\n inputSchema: Page,\n execute: input => {\n const pageOrError = PageCollector.from(input)\n if (pageOrError instanceof Error) {\n return pageOrError.message\n }\n\n pageCollector.addPage(pageOrError)\n\n return `page ${JSON.stringify(input)} added`\n }\n }),\n view_pages: tool({\n description: \"use this tool to view all the pages that you already added\",\n inputSchema: z.object(),\n execute: () => pageCollector.viewPages()\n })\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n return pageCollector.pages;\n}\n","import { platform } from \"node:os\";\nimport { execFile } from \"node:child_process\";\n\nexport function notify(title: string, message: string): void {\n process.stderr.write(\"\\x07\");\n\n const os = platform();\n if (os === \"darwin\") {\n execFile(\n \"osascript\",\n [\"-e\", `display notification \"${message.replace(/\"/g, '\\\\\"')}\" with title \"${title.replace(/\"/g, '\\\\\"')}\"`],\n () => {},\n );\n } else if (os === \"linux\") {\n execFile(\"notify-send\", [title, message], () => {});\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { access } from \"node:fs/promises\";\nimport { join, isAbsolute } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport which from \"which\";\nimport type { AgentResult } from \"./agent\";\nimport { notify } from \"./notify\";\n\nconst DIM = \"\\x1b[2m\";\nconst CYAN = \"\\x1b[36m\";\nconst GREEN = \"\\x1b[32m\";\nconst RESET = \"\\x1b[0m\";\n\nexport interface ReviewLoopOptions {\n agentId: string;\n outputDir: string;\n nonInteractive?: boolean;\n onFeedback: (feedback: string) => Promise<AgentResult | undefined>;\n reviewGuidance?: string;\n showPreview?: boolean;\n}\n\nfunction resolvePath(artifact: string, outputDir: string): string {\n if (isAbsolute(artifact)) return artifact;\n return join(outputDir, artifact);\n}\n\ninterface EditorOption {\n command: string;\n label: string;\n args: (files: string[]) => string[];\n}\n\nconst EDITORS: EditorOption[] = [\n { command: \"cursor\", label: \"Cursor\", args: (f) => f },\n { command: \"code\", label: \"VS Code\", args: (f) => f },\n { command: \"zed\", label: \"Zed\", args: (f) => f },\n { command: \"nano\", label: \"nano\", args: (f) => [f[0]!] },\n { command: \"vim\", label: \"vim\", args: (f) => [f[0]!] },\n];\n\nlet cachedEditors: EditorOption[] | null = null;\n\nasync function detectEditors(): Promise<EditorOption[]> {\n if (cachedEditors) return cachedEditors;\n const available: EditorOption[] = [];\n for (const editor of EDITORS) {\n const path = await which(editor.command, { nothrow: true });\n if (path) available.push(editor);\n }\n cachedEditors = available;\n return available;\n}\n\nlet preferredEditor: string | null = null;\n\nasync function launchEditor(editor: EditorOption, files: string[]): Promise<void> {\n const args = editor.args(files);\n const proc = spawn(editor.command, args, { stdio: \"inherit\" });\n if ([\"nano\", \"vim\"].includes(editor.command)) {\n await new Promise<void>((resolve, reject) => {\n proc.on(\"close\", () => resolve());\n proc.on(\"error\", reject);\n });\n }\n}\n\nasync function openInEditor(files: string[]): Promise<void> {\n const editors = await detectEditors();\n if (editors.length === 0) {\n p.log.warn(\"No editors found. Review the files manually:\");\n for (const f of files) console.log(` ${CYAN}${f}${RESET}`);\n return;\n }\n\n if (preferredEditor) {\n const editor = editors.find((e) => e.command === preferredEditor);\n if (editor) {\n const open = await p.confirm({\n message: `Open in ${editor.label}?`,\n });\n if (!p.isCancel(open) && open) {\n await launchEditor(editor, files);\n }\n return;\n }\n }\n\n const options = editors.map((e) => ({\n value: e.command,\n label: e.label,\n }));\n\n const selected = await p.select({\n message: \"Open output files for review?\",\n options: [\n ...options,\n { value: \"skip\", label: \"No, skip — I'll review later\" },\n ],\n });\n\n if (p.isCancel(selected) || selected === \"skip\") return;\n\n const editor = editors.find((e) => e.command === selected)!;\n\n const remember = await p.select({\n message: `Use ${editor.label} for all future reviews?`,\n options: [\n { value: \"always\", label: `Yes, always use ${editor.label}` },\n { value: \"ask\", label: \"No, ask me each time\" },\n ],\n });\n\n if (!p.isCancel(remember) && remember === \"always\") {\n preferredEditor = editor.command;\n }\n\n await launchEditor(editor, files);\n}\n\nasync function showResults(\n result: AgentResult,\n options: ReviewLoopOptions,\n): Promise<void> {\n console.log(\"\");\n console.log(` ${GREEN}[${options.agentId}] Step complete.${RESET}`);\n\n if (result.artifacts.length === 0) {\n const knownFiles = [\"AUTONOMA.md\", \"entity-audit.md\", \"scenarios.md\"];\n for (const f of knownFiles) {\n const fullPath = join(options.outputDir, f);\n try {\n await access(fullPath);\n result.artifacts.push(f);\n } catch {}\n }\n }\n\n const resolvedPaths: string[] = [];\n if (result.artifacts.length > 0) {\n console.log(` ${DIM}Output files:${RESET}`);\n for (const a of result.artifacts) {\n const fullPath = resolvePath(a, options.outputDir);\n resolvedPaths.push(fullPath);\n console.log(` ${CYAN}${fullPath}${RESET}`);\n }\n }\n if (result.summary) {\n console.log(` ${result.summary}`);\n }\n console.log(\"\");\n\n if (options.reviewGuidance) {\n p.note(options.reviewGuidance, \"What to check\");\n }\n\n const showPreview = options.showPreview !== false;\n if (showPreview && resolvedPaths.length > 0 && !options.nonInteractive) {\n notify(\"Autonoma\", `${options.agentId} step complete — review needed`);\n await openInEditor(resolvedPaths);\n }\n}\n\nexport async function reviewLoop(\n result: AgentResult | undefined,\n options: ReviewLoopOptions,\n): Promise<AgentResult | undefined> {\n if (!result?.success) return result;\n\n await showResults(result, options);\n\n if (options.nonInteractive) return result;\n\n while (true) {\n const input = await p.text({\n message: \"Review the output. Press Enter to approve, or type feedback for the agent.\",\n placeholder: \"Looks good (Enter to approve)\",\n defaultValue: \"\",\n });\n\n if (p.isCancel(input)) {\n p.log.warn(\"Cancelled.\");\n return result;\n }\n\n const feedback = (input as string).trim();\n if (feedback === \"\") {\n p.log.success(\"Approved — moving on.\");\n return result;\n }\n\n p.log.info(`Sending feedback to ${options.agentId}...`);\n console.log(\"\");\n\n const revised = await options.onFeedback(feedback);\n if (revised) {\n result = revised;\n }\n\n await showResults(result, options);\n }\n}\n","export const SYSTEM_PROMPT = `You are a knowledge base generator for E2E test planning. You analyze a frontend codebase and produce a structured guide to EVERY page, flow, and interaction. You must be EXHAUSTIVE — missing a page means missing test coverage.\n\n## Your output\n\nA file called AUTONOMA.md with YAML frontmatter\n\n## How to analyze the codebase — MANDATORY PHASES\n\n### Phase 1: Technology discovery\n1. Explore the project structure to understand the tech stack, framework, and routing approach.\n2. Read project configuration files and documentation to orient yourself.\n3. Identify the routing pattern — how pages/routes are defined in this specific project.\n4. Read the main layout and navigation components.\n\nYou have full access to the codebase. Use your tools (list_directory, glob, grep, read_file) to explore freely. Every project is different — discover the patterns rather than assuming them.\n\n### Phase 2: EXHAUSTIVE page discovery (HARD GATE)\nThis is the critical step. You must find EVERY page/route, not a sample.\n\n1. Based on the routing pattern you discovered in Phase 1, use glob and grep to find ALL page/route definitions.\n2. For EACH page file found, read it. No exceptions. Every single one.\n3. Build a complete route map. Count them.\n\nHARD GATE: Before proceeding to Phase 3, verify:\n- You have read every page/route file in the project\n- Your route count matches what your search returned\n- If you found fewer pages than expected, GO BACK and search harder\n\n### Phase 3: Deep exploration of each page\nFor EACH page/route (you already read them all in Phase 2):\n1. Identify ALL interactive elements: forms, tables, modals, tabs, dropdowns, buttons\n2. Find all API calls and data fetching patterns\n3. Find sub-components that render on this page — read them too\n4. Note navigation links to other pages\n5. Identify dynamic routes and what parameters they take\n\nUse subagents to parallelize: you can spawn one subagent per page/area to read its component tree in parallel.\n\n### Phase 4: Core flow identification\nAsk yourself: \"If this flow broke silently, would users immediately notice and stop using the product?\"\nTypically 2-4 flows are core. They receive 50-60% of test coverage later.\n\n### Phase 5: Coverage self-check (HARD GATE)\nBefore calling finish:\n1. Search again for all page/route files\n2. Compare against the pages you documented in AUTONOMA.md core_flows\n3. If ANY page is missing from your output, go back and document it\n4. The feature_count in AUTONOMA.md MUST match the actual number of features found\n\nDO NOT call finish until every page is accounted for.\n\n## AUTONOMA.md format\n\nThe file MUST start with YAML frontmatter:\n\n\\`\\`\\`yaml\n---\napp_name: \"Name of the application\"\napp_description: \"2-4 sentences describing what the application does, who uses it, and its primary purpose.\"\ncore_flows:\n - feature: \"Feature Name\"\n description: \"What this feature/area does\"\n mission: \"The ONE thing this feature must do correctly\"\n core: true\n coreReason: \"If this breaks, users cannot do X — the product is unusable\"\n - feature: \"Another Feature\"\n description: \"What this feature/area does\"\n mission: \"The ONE thing this feature must do correctly\"\n core: false\nfeature_count: 12\npages:\n - page: \"/path/to/file\"\n description: \"brief description of the page\"\n---\n\\`\\`\\`\n\n### Frontmatter rules\n- app_name: The app's name as it appears in the UI\n- app_description: 2-4 sentences, at least 20 characters\n- core_flows: ALL features/areas discovered. Each has feature (string), description (string), mission (string), core (boolean), and optionally coreReason (string)\n- mission: A single sentence stating what this feature MUST do correctly. This is NOT a description — it's a quality bar. Think: \"If I could only test ONE thing about this feature, what would I test?\"\n GOOD mission: \"Show correct execution counts, growth trends, and success rates for the selected time range and folders\"\n BAD mission: \"Shows analytics charts\" (just restates the feature name)\n- coreReason (required when core: true): WHY breakage of this feature makes the product unusable.\n- At least one flow must have core: true\n- feature_count: total features identified (positive integer)\n- pages: a list of all pages discovered, with their path and brief description\n\n\n### Feature granularity rules (CRITICAL)\nEach NAVIGABLE area, tab, or distinct page MUST be its own feature entry in core_flows. Do NOT group related pages into one feature.\n\nWRONG (too coarse):\n - feature: \"Analytics\" — groups 4 separate pages into one\n\nRIGHT (granular):\n - feature: \"Analytics - Overview\"\n - feature: \"Analytics - Revenue\"\n - feature: \"Analytics - Users\"\n - feature: \"Analytics - Retention\"\n\nA complex app should have 20-40 features in core_flows. If you have fewer than 15, you are grouping too aggressively.\n\nOnly 2-5 features should be core: true — the ones where breakage stops users from using the product entirely. Most features are core: false.\n\n### Body sections\nAfter the frontmatter, include:\n- Application description\n- User roles\n- Entry point (login, landing page)\n- Navigation structure (sidebar items, top nav, all menu entries)\n- Core flows (detailed description of each)\n- ALL other pages/features (even minor ones — settings tabs, profile, etc.)\n- UI patterns (common components, toast messages, modals, form patterns)\n- Preferences (date formats, currencies, timezone handling)\n\n## Tool usage guidance\n\n- Use list_directory ONCE at the root (path='.', depth=3) to get the project overview\n- Use glob and grep to find all page/route files — adapt your search patterns to the project's framework\n- Use read_file to read specific files you found\n- Do NOT call list_directory on every subdirectory — that's what glob is for\n- Use subagents to parallelize reading multiple files\n\n## Rules\n\n- EXHAUSTIVE coverage is mandatory. Every page, every route, every feature.\n- Use the UI vocabulary — the same names the app uses\n- Treat README files as hints, not ground truth — the codebase is the source of truth\n- Document what you find, don't invent features\n- Be specific: mention exact button text, menu labels, URL paths\n- Use subagents aggressively to parallelize exploration\n- If a page has tabs, each tab is a feature. If a page has modals, each modal is a feature.\n- Read the actual component code, not just the page entry point`;\n","import {tool} from \"ai\";\nimport {z} from \"zod\";\nimport {readFile} from \"node:fs/promises\";\nimport {join} from \"node:path\";\nimport {type AgentResult, buildDefaultStepLogger, runAgent} from \"../../core/agent\";\nimport {formatContext, type ProjectContext} from \"../../core/context\";\nimport {getModel} from \"../../core/model\";\nimport {reviewLoop} from \"../../core/review\";\nimport {buildCodebaseTools, buildReadFileTool} from \"../../tools\";\nimport {SYSTEM_PROMPT} from \"./prompt\";\n\nexport interface KBGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\nclass PageTracker {\n registered = new Set<string>();\n read = new Set<string>();\n\n register(pages: string[]) {\n for (const p of pages) this.registered.add(p);\n }\n\n markRead(filePath: string) {\n if (this.registered.has(filePath)) {\n this.read.add(filePath);\n }\n }\n\n unread(): string[] {\n return [...this.registered].filter((p) => !this.read.has(p));\n }\n\n coverage(): { total: number; read: number; unread: string[] } {\n return {\n total: this.registered.size,\n read: this.read.size,\n unread: this.unread(),\n };\n }\n}\n\nfunction buildRegisterPagesTool(tracker: PageTracker) {\n return tool({\n description:\n \"Register ALL page/route files discovered via glob. \" +\n \"Call this ONCE after globbing for page files. \" +\n \"The system will track which ones you've read and block finish until all are covered.\",\n inputSchema: z.object({\n pages: z.array(z.string()).describe(\"All page file paths found by glob\"),\n }),\n execute: async (input) => {\n tracker.register(input.pages);\n return {\n registered: input.pages.length,\n message: `Registered ${input.pages.length} pages. You must read_file each one before calling finish.`,\n };\n },\n });\n}\n\nfunction buildPageCoverageTool(tracker: PageTracker) {\n return tool({\n description: \"Check how many registered pages you've read vs how many remain.\",\n inputSchema: z.object({}),\n execute: async () => tracker.coverage(),\n });\n}\n\nfunction buildFinishTool(\n tracker: PageTracker,\n onFinish: (result: AgentResult) => void,\n) {\n return tool({\n description:\n \"Call when you have finished generating the knowledge base. \" +\n \"BLOCKED if there are unread pages — call page_coverage first to check.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Summary of what was generated\"),\n artifacts: z.array(z.string()).describe(\"List of files written\"),\n }),\n execute: async (input) => {\n const cov = tracker.coverage();\n if (cov.unread.length > 0) {\n return {\n error: `Cannot finish: ${cov.unread.length}/${cov.total} pages not yet read. Read these files first:\\n${cov.unread.join(\"\\n\")}`,\n };\n }\n onFinish({\n success: true,\n artifacts: input.artifacts,\n summary: input.summary,\n });\n return { success: true };\n },\n });\n}\n\nfunction buildTrackedReadTool(\n tracker: PageTracker,\n baseTool: ReturnType<typeof buildReadFileTool>,\n) {\n return tool({\n description: baseTool.description,\n inputSchema: baseTool.inputSchema,\n execute: async (input, options) => {\n const filePath = (input as { filePath?: string; path?: string; file_path?: string }).filePath\n ?? (input as { path?: string }).path\n ?? (input as { file_path?: string }).file_path\n ?? \"\";\n tracker.markRead(filePath);\n return baseTool.execute!(input, options);\n },\n });\n}\n\n\nexport async function runKBGenerator(input: KBGeneratorInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n const tracker = new PageTracker();\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"kb\", 150);\n\n const contextBlock = input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\";\n\n const pages = input.projectContext?.pages;\n if (pages?.length) {\n tracker.register(pages.map((p) => p.path));\n }\n\n const prompt = pages?.length\n ? `Analyze the codebase at the working directory and generate a complete knowledge base.\n${contextBlock}\nMANDATORY PROCESS:\nPages have already been discovered (${pages.length} routes pre-registered). You do NOT need to glob for them.\n1. Use list_directory at root to understand the project structure\n2. Read EVERY registered page file with read_file — the system tracks this\n3. Write AUTONOMA.md progressively as you go (update it after each major area)\n4. Call page_coverage to verify you've read all pages\n5. Call finish — it will REJECT if pages are unread\n\nOutput files:\n1. AUTONOMA.md — with YAML frontmatter (app_name, app_description, core_flows, feature_count)`\n : `Analyze the codebase at the working directory and generate a complete knowledge base.\n${contextBlock}\nMANDATORY PROCESS:\n1. Use list_directory at root to understand the project structure\n2. Use glob to find ALL page/route files (e.g. '**/page.tsx', '**/page.ts')\n3. Call register_pages with the FULL list of page files from glob\n4. Read EVERY registered page file with read_file — the system tracks this\n5. Write AUTONOMA.md progressively as you go (update it after each major area)\n6. Call page_coverage to verify you've read all pages\n7. Call finish — it will REJECT if pages are unread\n\nOutput files:\n1. AUTONOMA.md — with YAML frontmatter (app_name, app_description, core_flows, feature_count)`;\n\n const agentConfig = {\n id: \"kb-generator\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 150,\n tools: async (heartbeat: () => void) => {\n const onFileRead = (path: string) => tracker.markRead(path);\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat, onFileRead);\n return {\n ...tools,\n read_file: buildTrackedReadTool(tracker, tools.read_file),\n register_pages: buildRegisterPagesTool(tracker),\n page_coverage: buildPageCoverageTool(tracker),\n finish: buildFinishTool(tracker, (r) => { result = r; }),\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n const reviewed = await reviewLoop(result, {\n agentId: \"kb-generator\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n reviewGuidance:\n \"Check that every page/route in your app appears in core_flows.\\n\" +\n \"Verify the mission for each feature describes the ONE thing it must do correctly.\\n\" +\n \"Look for missing features or incorrectly grouped pages.\\n\" +\n \"A complex app should have 20-40 features — if you see fewer than 15, features are probably grouped too aggressively.\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed your knowledge base output and has this feedback:\n\n\"${feedback}\"\n\nRead your previous output file (AUTONOMA.md) from the output directory to see what you produced.\nAdjust based on the feedback. You can read source files again if needed.\nCall page_coverage to see current state. When done with changes, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n if (!reviewed) {\n const autonomaPath = join(input.outputDir, \"AUTONOMA.md\");\n try {\n await readFile(autonomaPath, \"utf-8\");\n return {\n success: true,\n artifacts: [\"AUTONOMA.md\"],\n summary: \"Knowledge base generated (finish tool may not have captured the result, but AUTONOMA.md exists).\",\n };\n } catch {}\n }\n\n return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"KB generator did not produce a result\",\n };\n}\n","export const SYSTEM_PROMPT = `You audit a codebase to discover EVERY database model and every way each is created. You must find ALL models — missing one means the test data layer has a gap. This audit drives factory generation and scenario planning.\n\n## The two orthogonal questions\n\nFor every model, answer BOTH independently:\n\n1. **independently_created** — Does the codebase have an exported function/method that creates this model on its own? Boolean.\n2. **created_by** — When you trace every other model's creation function, does any of them produce this model as a side effect? List of {owner, via, why} entries; empty if none.\n\nThese are NOT mutually exclusive. A model can be both. Do not collapse the two.\n\n## The four states a model can be in\n\n| independently_created | created_by | Interpretation |\n|---|---|---|\n| true | [] | Pure root — only standalone creation exists |\n| true | non-empty | Dual — has standalone path AND is produced by owners |\n| false | non-empty | Pure dependent — only reachable via owner's creation |\n| false | [] | INVALID — unreachable model, fix before writing |\n\n## MANDATORY DISCOVERY PROCESS\n\n### Step 0: Identify the database framework\nDetermine which ORM/database tool the project uses. Explore the project structure — read config files, schema definitions, and imports to identify the data layer. Every project is different; use your tools (grep, glob, read_file) to discover the patterns.\n\n### Step 1: Find ALL model definitions and register them\nBased on the framework you identified, use grep and glob to find ALL model/table/entity definitions. Call register_models with the complete list. Real applications typically have 30-150 models — if you found fewer than 20, search harder before registering.\n\n### Step 2: Process models using the queue\nAfter registering, call next_model to get the first model. For each model:\n\n1. grep for creation patterns (e.g. \"ModelName.create\", \"new ModelName\", \"insert into model\") — 1 to 3 greps MAX\n2. If you find a creation path: read the file, call mark_model_audited with the details\n3. If you can't find it after 2-3 greps: call next_model to skip and move on\n\nIMPORTANT: Do NOT spend more than 3-4 steps per model. The queue ensures you process every model. If a model has no obvious creation path, skipping it is valid — it gets marked as \"no creation path found.\"\n\nWhen you call mark_model_audited, also note side effects you see in the creation function (other models created as part of the same operation). Record these in the created_by field of those other models when you reach them.\n\n### Step 3: Write output and finish\nWhen next_model returns done, write entity-audit.md and call finish.\n\n## Output files\n\nYou produce TWO files:\n\n### 1. entity-audit.md\n\nYAML frontmatter with ALL models, then markdown body organized by module/area.\n\nFrontmatter format:\n\\`\\`\\`yaml\n---\nmodel_count: 105\nfactory_count: 48\nmodels:\n # ============================================================\n # MODULE NAME\n # ============================================================\n - name: User\n independently_created: true\n creation_file: src/services/user.service.ts\n creation_function: UserService.create\n side_effects:\n - hashes password\n - creates default Settings row\n created_by: []\n - name: Settings\n independently_created: false\n created_by:\n - owner: User\n via: UserService.create\n why: \"Every new User gets a default Settings row created in the same transaction.\"\n---\n\\`\\`\\`\n\nGroup models by module/domain area with comment headers for readability.\n\nBody sections:\n- Database framework identified and version\n- Roots (independently_created: true) with details\n- Dependents (independently_created: false) with owner chains\n- Dual-creation models (both true AND non-empty created_by)\n- Dependency graph summary (which models must exist before others)\n\n### 2. factory-scaffold.ts\n\nA TypeScript file with defineFactory() stubs for every model with independently_created: true.\n\nFormat:\n\\`\\`\\`typescript\nimport { defineFactory } from '@autonoma-ai/sdk'\nimport { z } from 'zod'\n\nexport const User = defineFactory({\n inputSchema: z.object({\n email: z.string(),\n name: z.string(),\n organizationId: z.string(),\n }),\n create: async (data, ctx) => {\n // Suggested: return createUser({ ...data, password: 'test-password' })\n // Found at: src/services/user.service.ts:42 — UserService.create()\n throw new Error('TODO: implement')\n },\n teardown: async (record, ctx) => {\n // Suggested: await db.user.delete({ where: { id: record.id } })\n // Cascade: will also delete Settings (FK constraint)\n throw new Error('TODO: implement')\n },\n})\n\\`\\`\\`\n\n## Tool usage guidance\n\n- Use list_directory ONCE at root to understand project layout, then use grep/glob for targeted discovery\n- Use grep to find ALL model definitions — adapt your search patterns to the framework you discover\n- Use next_model to process models one at a time from the queue — never pick models yourself\n- Use read_file on creation files found by grep\n- Do NOT call list_directory on every subdirectory — use grep and glob instead\n\n## Rules\n\n- EXHAUSTIVE coverage is mandatory. Real apps have 30-150 models. If you found fewer than 20, you missed most of them.\n- Use grep to find models, not file browsing. Models can be defined anywhere.\n- Read the ACTUAL creation code, don't guess from file names\n- Do NOT spend more than 3-4 steps per model. Move on quickly.\n- When in doubt, prefer independently_created: true\n- Every enum type that maps to a DB column should be noted (useful for scenario generation later)\n- Junction tables and association tables ARE models — include them`;\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { glob } from \"glob\";\nimport { runAgent, buildDefaultStepLogger, type AgentResult } from \"../../core/agent\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport { reviewLoop } from \"../../core/review\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\n\nexport interface EntityAuditInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\ninterface CreatedByEntry {\n owner: string;\n via?: string;\n why?: string;\n}\n\ninterface AuditedModel {\n name: string;\n independently_created: boolean;\n creation_file?: string;\n creation_function?: string;\n side_effects?: string[];\n created_by: CreatedByEntry[];\n}\n\nclass ModelTracker {\n registered = new Set<string>();\n auditedModels = new Map<string, AuditedModel>();\n creationFilesRead = new Set<string>();\n framework = \"unknown\";\n queue: string[] = [];\n currentModel: string | null = null;\n\n register(models: string[]) {\n for (const m of models) this.registered.add(m);\n }\n\n initQueue() {\n this.queue = [...this.registered].filter((m) => !this.auditedModels.has(m));\n }\n\n nextModel(): { model: string; remaining: number } | null {\n if (this.currentModel && !this.auditedModels.has(this.currentModel)) {\n this.auditedModels.set(this.currentModel, {\n name: this.currentModel,\n independently_created: false,\n created_by: [],\n });\n }\n while (this.queue.length > 0) {\n const model = this.queue.shift()!;\n if (this.auditedModels.has(model)) continue;\n this.currentModel = model;\n return { model, remaining: this.queue.length };\n }\n this.currentModel = null;\n return null;\n }\n\n markAudited(model: AuditedModel) {\n this.auditedModels.set(model.name, model);\n }\n\n markFileRead(filePath: string) {\n this.creationFilesRead.add(filePath);\n }\n\n unaudited(): string[] {\n return [...this.registered].filter((m) => !this.auditedModels.has(m));\n }\n\n coverage() {\n return {\n totalModels: this.registered.size,\n audited: this.auditedModels.size,\n unaudited: this.unaudited(),\n creationFilesRead: this.creationFilesRead.size,\n };\n }\n\n generateAuditMarkdown(): string {\n const models = [...this.auditedModels.values()];\n const roots = models.filter((m) => m.independently_created);\n const dependents = models.filter((m) => !m.independently_created);\n const duals = models.filter((m) => m.independently_created && m.created_by.length > 0);\n\n const yamlModels = models.map((m) => {\n let entry = ` - name: ${m.name}\\n independently_created: ${m.independently_created}`;\n if (m.creation_file) entry += `\\n creation_file: ${m.creation_file}`;\n if (m.creation_function) entry += `\\n creation_function: ${m.creation_function}`;\n if (m.side_effects && m.side_effects.length > 0) {\n entry += `\\n side_effects:\\n${m.side_effects.map((s) => ` - ${s}`).join(\"\\n\")}`;\n }\n if (m.created_by.length > 0) {\n entry += `\\n created_by:`;\n for (const cb of m.created_by) {\n entry += `\\n - owner: ${cb.owner}`;\n if (cb.via) entry += `\\n via: ${cb.via}`;\n if (cb.why) entry += `\\n why: \"${cb.why}\"`;\n }\n } else {\n entry += `\\n created_by: []`;\n }\n return entry;\n }).join(\"\\n\");\n\n return `---\nmodel_count: ${models.length}\nfactory_count: ${roots.length}\nmodels:\n${yamlModels}\n---\n\n# Entity Audit\n\nFramework: ${this.framework}\n\n## Roots (independently_created: true)\n\n${roots.map((m) => `- **${m.name}** — ${m.creation_function ?? m.creation_file ?? \"unknown\"}`).join(\"\\n\")}\n\n## Dependents (independently_created: false)\n\n${dependents.map((m) => `- **${m.name}** — created by: ${m.created_by.map((cb) => `${cb.owner}${cb.via ? ` via ${cb.via}` : \"\"}`).join(\", \") || \"unknown\"}`).join(\"\\n\")}\n\n## Dual-creation models (independently_created AND created_by)\n\n${duals.length > 0 ? duals.map((m) => `- **${m.name}** — standalone: ${m.creation_function ?? m.creation_file ?? \"unknown\"}, also created by: ${m.created_by.map((cb) => cb.owner).join(\", \")}`).join(\"\\n\") : \"None\"}\n`;\n }\n}\n\nfunction buildRegisterModelsTool(tracker: ModelTracker) {\n return tool({\n description:\n \"Register ALL database models discovered via grep. \" +\n \"Call this ONCE after grepping for model definitions. \" +\n \"After registering, use next_model to process them one at a time.\",\n inputSchema: z.object({\n models: z.array(z.string()).describe(\"All model/table names found by grep\"),\n framework: z.string().describe(\"Database framework detected (e.g. 'sqlalchemy', 'prisma', 'drizzle')\"),\n }),\n execute: async (input) => {\n tracker.register(input.models);\n tracker.initQueue();\n return {\n registered: input.models.length,\n framework: input.framework,\n message: `Registered ${input.models.length} models (${input.framework}). Call next_model to start processing them one at a time.`,\n };\n },\n });\n}\n\nfunction buildNextModelTool(tracker: ModelTracker) {\n return tool({\n description:\n \"Get the next model to audit from the queue. If you called next_model before \" +\n \"without calling mark_model_audited, the previous model is auto-skipped \" +\n \"(marked as no creation path found). Returns done:true when all models are processed.\",\n inputSchema: z.object({}),\n execute: async () => {\n const next = tracker.nextModel();\n if (!next) {\n return {\n done: true,\n message: `All models processed (${tracker.auditedModels.size} total). Write entity-audit.md and call finish.`,\n };\n }\n return {\n model: next.model,\n remaining: next.remaining,\n instruction: `Audit \"${next.model}\": grep for its creation paths, read the relevant file, then call mark_model_audited. If you can't find how it's created after 2-3 greps, call next_model to skip it.`,\n };\n },\n });\n}\n\nfunction buildMarkModelAuditedTool(tracker: ModelTracker) {\n return tool({\n description:\n \"Mark a model as audited after you have determined its creation paths. \" +\n \"Call this for EACH model after reading its creation code and determining independently_created + created_by. \" +\n \"Include creation_function (e.g. 'UserService.create'), side_effects (list of things the creation does beyond the model itself), \" +\n \"and for each created_by entry include owner, via (function name), and why (one sentence explaining the relationship).\",\n inputSchema: z.object({\n model: z.string().describe(\"Model name\"),\n independently_created: z.boolean(),\n creation_file: z.string().optional().describe(\"File containing the creation function\"),\n creation_function: z.string().optional().describe(\"Function/method name (e.g. 'UserService.create' or 'create_user')\"),\n side_effects: z.array(z.string()).optional().describe(\"Side effects of creation (e.g. 'creates default Settings row', 'hashes password')\"),\n created_by: z.array(z.object({\n owner: z.string().describe(\"Owner model name\"),\n via: z.string().optional().describe(\"Function that creates this model (e.g. 'OrganizationService.create')\"),\n why: z.string().optional().describe(\"One sentence explaining why this model is created as a side effect\"),\n })).describe(\"List of owner models that create this as a side effect, empty array if none\"),\n }),\n execute: async (input) => {\n let modelName = input.model;\n\n if (tracker.registered.size > 0 && !tracker.registered.has(modelName)) {\n const exact = [...tracker.registered].find(\n (r) => r.toLowerCase() === modelName.toLowerCase() || modelName.startsWith(r),\n );\n if (exact) {\n modelName = exact;\n } else {\n return {\n error: `\"${modelName}\" is not a registered model. Use the exact name from register_models. Registered: ${[...tracker.registered].join(\", \")}`,\n };\n }\n }\n\n tracker.markAudited({\n name: modelName,\n independently_created: input.independently_created,\n creation_file: input.creation_file,\n creation_function: input.creation_function,\n side_effects: input.side_effects,\n created_by: input.created_by,\n });\n if (input.creation_file) tracker.markFileRead(input.creation_file);\n const cov = tracker.coverage();\n return {\n model: modelName,\n progress: `${cov.audited}/${cov.totalModels} models audited`,\n remaining: cov.unaudited.length,\n };\n },\n });\n}\n\nfunction buildModelCoverageTool(tracker: ModelTracker) {\n return tool({\n description: \"Check how many registered models you've audited vs how many remain.\",\n inputSchema: z.object({}),\n execute: async () => tracker.coverage(),\n });\n}\n\nfunction buildFinishTool(\n tracker: ModelTracker,\n onFinish: (result: AgentResult) => void,\n) {\n return tool({\n description:\n \"Call when entity audit is complete. \" +\n \"BLOCKED if there are unaudited models — call model_coverage first to check.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Summary of the audit\"),\n artifacts: z.array(z.string()).describe(\"Files written\"),\n }),\n execute: async (input) => {\n const cov = tracker.coverage();\n if (cov.unaudited.length > 0) {\n return {\n error: `Cannot finish: ${cov.unaudited.length}/${cov.totalModels} models not yet audited. Audit these models first:\\n${cov.unaudited.join(\"\\n\")}`,\n };\n }\n onFinish({\n success: true,\n artifacts: input.artifacts,\n summary: input.summary,\n });\n return { success: true };\n },\n });\n}\n\ntype FrameworkDetection = {\n framework: string;\n models: string[];\n schemaFile?: string;\n};\n\nasync function findPrismaSchema(projectRoot: string): Promise<string | null> {\n const candidates = await glob(\"**/schema.prisma\", {\n cwd: projectRoot,\n ignore: [\"**/node_modules/**\"],\n absolute: true,\n });\n return candidates[0] ?? null;\n}\n\nasync function extractPrismaModels(schemaPath: string): Promise<string[]> {\n const content = await readFile(schemaPath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"model \"))\n .map((line) => line.split(/\\s+/)[1])\n .filter((name): name is string => name != null);\n}\n\nasync function detectFrameworkAndModels(\n projectRoot: string,\n): Promise<FrameworkDetection | null> {\n const prismaPath = await findPrismaSchema(projectRoot);\n if (prismaPath) {\n const models = await extractPrismaModels(prismaPath);\n return { framework: \"prisma\", models, schemaFile: prismaPath };\n }\n\n // TODO: Add SQLAlchemy, Django, Drizzle, TypeORM detection\n return null;\n}\n\nexport async function runEntityAudit(input: EntityAuditInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n const tracker = new ModelTracker();\n\n const detection = await detectFrameworkAndModels(input.projectRoot);\n let preRegisteredCount = 0;\n if (detection) {\n tracker.framework = detection.framework;\n tracker.register(detection.models);\n tracker.initQueue();\n preRegisteredCount = detection.models.length;\n }\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"entity-audit\", 200);\n\n const contextBlock = input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\";\n\n const preRegBlock = preRegisteredCount > 0\n ? `\\n## Pre-registered models (${preRegisteredCount} found via ${detection!.framework} schema at ${detection!.schemaFile})\n\nThe system has already registered ${preRegisteredCount} models from the schema file. You do NOT need to call register_models — it's already done. Start with next_model to process them.\\n`\n : \"\";\n\n const prompt = `Use read_output to read AUTONOMA.md from the output directory to understand the application.\n\n${contextBlock}\nAudit the codebase at the working directory.\n${preRegBlock}\nMANDATORY PROCESS:\n\n${preRegisteredCount === 0 ? `1. Explore the project to identify the database framework and find ALL model definitions\n2. Call register_models with the full list of model names\n3. Call next_model` : \"1. Call next_model\"} to get the first model\n${preRegisteredCount === 0 ? \"4\" : \"2\"}. For each model returned by next_model:\n a. grep for creation patterns (e.g. \"ModelName.create\", \"new ModelName\") — 1 to 3 greps MAX\n b. If found: read the file, call mark_model_audited with the creation details\n c. If NOT found after 2-3 greps: call next_model to skip and move on (auto-skipped as \"no creation path found\")\n${preRegisteredCount === 0 ? \"5\" : \"3\"}. Repeat until next_model returns done\n${preRegisteredCount === 0 ? \"6\" : \"4\"}. Write entity-audit.md with all findings\n${preRegisteredCount === 0 ? \"7\" : \"5\"}. Call finish\n\nIMPORTANT: Do NOT spend more than 3-4 steps per model. The queue ensures you process every model.\nIf you can't find a creation path quickly, skip it — that's valid data.\nAfter every 10 mark_model_audited calls, use write_file to update entity-audit.md progressively.\nwrite_file already targets the output directory — use just the filename.`;\n\n const agentConfig = {\n id: \"entity-audit\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 200,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n register_models: buildRegisterModelsTool(tracker),\n next_model: buildNextModelTool(tracker),\n mark_model_audited: buildMarkModelAuditedTool(tracker),\n model_coverage: buildModelCoverageTool(tracker),\n ask_user: buildAskUserTool(),\n finish: buildFinishTool(tracker, (r) => { result = r; }),\n };\n },\n onStepFinish,\n };\n\n try {\n await runAgent(agentConfig, prompt, () => result);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Entity audit agent error: ${message}`);\n }\n logger.summary();\n\n if (!result && tracker.auditedModels.size > 0) {\n const markdown = tracker.generateAuditMarkdown();\n const auditPath = join(input.outputDir, \"entity-audit.md\");\n await writeFile(auditPath, markdown, \"utf-8\");\n const cov = tracker.coverage();\n result = {\n success: true,\n artifacts: [auditPath],\n summary: `Safety net: agent ran out of steps but audited ${cov.audited}/${cov.totalModels} models. File written from tracker data.`,\n };\n }\n\n const reviewed = await reviewLoop(result, {\n agentId: \"entity-audit\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n reviewGuidance:\n \"Each model entry has these key fields:\\n\" +\n \" independently_created — true if this entity has its own creation API/function, false if only created as a side effect\\n\" +\n \" creation_file / creation_function — where in YOUR code this entity gets created\\n\" +\n \" side_effects — other entities that get created automatically when this one is created\\n\" +\n \" created_by — which parent entity's creation triggers this one\\n\\n\" +\n \"What to check:\\n\" +\n \" - Every database model should be listed\\n\" +\n \" - independently_created should be correct — models created only as side effects should be false\\n\" +\n \" - creation_file and creation_function should reference real code in your project\\n\" +\n \" - Side effects should be complete (e.g., creating a User also creates a Profile)\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed your entity audit and has this feedback:\n\n\"${feedback}\"\n\nRead your previous output (entity-audit.md) from the output directory.\nCall model_coverage to see current state.\nAdjust based on the feedback. You can grep/read source files again if needed.\nWhen done with changes, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n if (!reviewed) {\n const auditPath = join(input.outputDir, \"entity-audit.md\");\n try {\n await readFile(auditPath, \"utf-8\");\n return {\n success: true,\n artifacts: [\"entity-audit.md\"],\n summary: \"Entity audit generated (finish tool may not have captured the result, but entity-audit.md exists).\",\n };\n } catch {}\n }\n\n return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Entity audit did not produce a result\",\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function parseEntityNames(outputDir: string): Promise<string[]> {\n try {\n const content = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n const names: string[] = [];\n for (const line of content.split(\"\\n\")) {\n const match = line.match(/^\\s+-\\s+name:\\s+(.+)$/);\n if (match) names.push(match[1]!.trim());\n }\n return names;\n } catch {\n return [];\n }\n}\n","export const SCENARIO_DESIGN_PROMPT = `You are a scenario designer for E2E testing. You read an entity audit and design a single \"standard\" test data scenario.\n\n## Your input\n- entity-audit.md: models, creation paths, side effects\n- AUTONOMA.md: app context, core flows\n\n## Your output\nA scenarios.md file with YAML frontmatter describing a single \"standard\" scenario.\n\n## Scenario design rules\n\n1. ONE scenario: \"standard\" — represents a realistic working state of the application\n2. Realistic data volumes:\n - An email app gets 50+ emails, not 1\n - A payment app gets all payment method types\n - A project management tool gets multiple projects with tasks in various states\n3. Enum coverage: for every enum field, include at least one record per value\n4. The scenario must exercise all entity types from the audit\n5. Entity tables must be consistent — FK references must point to real records\n\n## Output format\n\n\\`\\`\\`yaml\n---\nscenario_count: 1\nscenarios:\n - name: standard\n description: \"Realistic working state with diverse data\"\nentity_types:\n - name: Organization\n count: 1\n - name: User\n count: 3\n - name: Project\n count: 5\nvariable_fields:\n - token: \"{{user_email_1}}\"\n entity: User\n field: email\n test_reference: \"primary test user email\"\n---\n\\`\\`\\`\n\nAfter frontmatter, write entity tables showing the data for the standard scenario.\nUse markdown tables. Show enough detail that a recipe builder can generate the exact records.\n\n## Variable fields\nSome values must change between test runs (emails, unique slugs, timestamps).\nList these in variable_fields with a {{token}} placeholder.\nThe rest can be static.`;\n\nexport const RECIPE_ENTITY_PROMPT = `You generate a recipe payload for a single entity type. Given the entity name, count, field constraints, enum values to cover, and FK refs to previously created entities, output a JSON array of entity records.\n\nRules:\n- Cover all enum values (at least one record per value)\n- Use realistic, diverse data (not \"test1\", \"test2\")\n- Respect FK constraints — reference real IDs from previously created entities\n- Include all required fields\n- Output valid JSON that can be sent to the SDK endpoint\n\nOutput ONLY the JSON array, no explanation.`;\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { AppConfig } from \"../../config\";\nimport { runAgent, buildDefaultStepLogger, type AgentResult } from \"../../core/agent\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport { parseEntityNames } from \"../../core/parse-entity-audit\";\nimport { reviewLoop } from \"../../core/review\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { SCENARIO_DESIGN_PROMPT } from \"./prompt\";\n\nexport interface ScenarioRecipeInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n config: AppConfig;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\nfunction buildFinishTool(\n requiredEntities: string[],\n outputDir: string,\n onFinish: (result: AgentResult) => void,\n) {\n return tool({\n description:\n \"Call when scenario design is complete and scenarios.md is written. \" +\n \"BLOCKED if any required entities are missing from the scenario.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Summary of the scenario\"),\n entityCount: z.number().describe(\"Number of entity types in the scenario\"),\n artifacts: z.array(z.string()).describe(\"Files written\"),\n }),\n execute: async (input) => {\n if (requiredEntities.length > 0) {\n try {\n const content = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n const missing = requiredEntities.filter(\n (e) => !content.includes(e),\n );\n if (missing.length > 0) {\n return {\n error:\n `Cannot finish: ${missing.length} entities from the entity audit are missing from scenarios.md.\\n` +\n `Add these entities to the scenario before calling finish:\\n` +\n missing.map((e) => ` - ${e}`).join(\"\\n\"),\n };\n }\n } catch {\n return { error: \"Cannot finish: scenarios.md not found. Write it first.\" };\n }\n }\n\n onFinish({\n success: true,\n artifacts: input.artifacts,\n summary: input.summary,\n });\n return { success: true };\n },\n });\n}\n\nexport async function runScenarioRecipe(input: ScenarioRecipeInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"scenario\", 40);\n\n const contextBlock = input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\";\n\n const requiredEntities = await parseEntityNames(input.outputDir);\n\n const entityListBlock = requiredEntities.length > 0\n ? `\\n## Required entities (${requiredEntities.length} total — ALL must appear in the scenario)\\n\\n${requiredEntities.map((e) => `- ${e}`).join(\"\\n\")}\\n\\nThe finish tool will REJECT your output if any of these are missing.\\n`\n : \"\";\n\n const prompt = `Read the entity audit and knowledge base from the output directory, then design a single \"standard\" scenario.\n${contextBlock}${entityListBlock}\nIMPORTANT: Use read_output to read files from the output directory (AUTONOMA.md, entity-audit.md).\nUse write_file with just the filename (e.g. \"scenarios.md\", NOT \"autonoma/scenarios.md\") — write_file already targets the output directory.\n\nThe scenario should:\n1. Cover ALL ${requiredEntities.length || \"\"} entity types from the entity audit — no exceptions\n2. Use realistic data volumes (not just 1 of each)\n3. Cover all enum values (at least one record per value)\n4. Include variable_fields for values that must change between runs\n\nWhen done, call finish.`;\n\n const agentConfig = {\n id: \"scenario-recipe\",\n systemPrompt: SCENARIO_DESIGN_PROMPT,\n model,\n maxSteps: 40,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return { ...tools, ask_user: buildAskUserTool(), finish: buildFinishTool(requiredEntities, input.outputDir, (r) => { result = r; }) };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n const reviewed = await reviewLoop(result, {\n agentId: \"scenario-recipe\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n reviewGuidance:\n \"The scenario defines test data that will exist in the database during E2E tests.\\n\" +\n \"Each entity_type should have a realistic count and data values.\\n\\n\" +\n \"What to check:\\n\" +\n \" - Every entity from the entity audit should appear here\\n\" +\n \" - Counts should be realistic (not just 1 of each)\\n\" +\n \" - Enum fields should have diverse values (not all the same)\\n\" +\n \" - variable_fields should mark values that must change between runs (emails, slugs)\\n\" +\n \" - Data values should match your actual database patterns\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed the scenario design and has this feedback:\n\n\"${feedback}\"\n\nRead your previous output (scenarios.md) from the output directory.\nAdjust based on the feedback. You can read entity-audit.md or source files again if needed.\nWhen done with changes, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n if (!reviewed) {\n const scenariosPath = join(input.outputDir, \"scenarios.md\");\n try {\n await readFile(scenariosPath, \"utf-8\");\n return {\n success: true,\n artifacts: [\"scenarios.md\"],\n summary: \"Scenarios generated (finish tool may not have captured the result, but scenarios.md exists).\",\n };\n } catch {}\n }\n\n return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Scenario recipe agent did not produce a result\",\n };\n}\n\nexport async function feedbackToScenario(input: ScenarioRecipeInput, feedback: string): Promise<AgentResult> {\n const model = getModel(input.modelId);\n let result: AgentResult | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"scenario-feedback\", 30);\n\n const requiredEntities = await parseEntityNames(input.outputDir);\n\n const agentConfig = {\n id: \"scenario-recipe\",\n systemPrompt: SCENARIO_DESIGN_PROMPT,\n model,\n maxSteps: 30,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return { ...tools, ask_user: buildAskUserTool(), finish: buildFinishTool(requiredEntities, input.outputDir, (r) => { result = r; }) };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, feedback, () => result);\n logger.summary();\n\n return result ?? { success: false, artifacts: [], summary: \"Scenario feedback did not produce a result\" };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type EntityStatus =\n | \"pending\"\n | \"recipe-accepted\"\n | \"tested-up\"\n | \"tested-down\"\n | \"skipped\";\n\nexport interface EntityProgress {\n entityName: string;\n status: EntityStatus;\n recipeData: Record<string, unknown>[] | null;\n errorLog: string[];\n}\n\nexport type SdkAdapter =\n | { language: \"typescript\"; framework: \"express\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-express\" }\n | { language: \"typescript\"; framework: \"node\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-node\" }\n | { language: \"typescript\"; framework: \"hono\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-hono\" }\n | { language: \"typescript\"; framework: \"web\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-web\" }\n | { language: \"python\"; framework: \"flask\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma_flask\" }\n | { language: \"python\"; framework: \"fastapi\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma_fastapi\" }\n | { language: \"python\"; framework: \"django\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma_django\" }\n | { language: \"go\"; framework: \"gin\"; sdkPackage: \"github.com/autonoma-ai/sdk-go\"; adapterPackage: \"github.com/autonoma-ai/sdk-go\" }\n | { language: \"ruby\"; framework: \"rails\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma-ai\" }\n | { language: \"ruby\"; framework: \"rack\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma-ai\" }\n | { language: \"java\"; framework: \"spring\"; sdkPackage: \"autonoma-sdk\"; adapterPackage: \"autonoma-spring\" }\n | { language: \"php\"; framework: \"laravel\"; sdkPackage: \"autonoma-ai/sdk\"; adapterPackage: \"autonoma-ai/sdk\" }\n | { language: \"rust\"; framework: \"axum\"; sdkPackage: \"autonoma-sdk\"; adapterPackage: \"autonoma-sdk\" }\n | { language: \"rust\"; framework: \"actix\"; sdkPackage: \"autonoma-sdk\"; adapterPackage: \"autonoma-sdk\" }\n | { language: \"elixir\"; framework: \"plug\"; sdkPackage: \"autonoma\"; adapterPackage: \"autonoma\" };\n\nexport type TechStack = SdkAdapter;\n\nexport const ALL_ADAPTERS: SdkAdapter[] = [\n { language: \"typescript\", framework: \"web\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-web\" },\n { language: \"typescript\", framework: \"express\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-express\" },\n { language: \"typescript\", framework: \"node\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-node\" },\n { language: \"typescript\", framework: \"hono\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-hono\" },\n { language: \"python\", framework: \"flask\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma_flask\" },\n { language: \"python\", framework: \"fastapi\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma_fastapi\" },\n { language: \"python\", framework: \"django\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma_django\" },\n { language: \"go\", framework: \"gin\", sdkPackage: \"github.com/autonoma-ai/sdk-go\", adapterPackage: \"github.com/autonoma-ai/sdk-go\" },\n { language: \"ruby\", framework: \"rails\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma-ai\" },\n { language: \"ruby\", framework: \"rack\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma-ai\" },\n { language: \"java\", framework: \"spring\", sdkPackage: \"autonoma-sdk\", adapterPackage: \"autonoma-spring\" },\n { language: \"php\", framework: \"laravel\", sdkPackage: \"autonoma-ai/sdk\", adapterPackage: \"autonoma-ai/sdk\" },\n { language: \"rust\", framework: \"axum\", sdkPackage: \"autonoma-sdk\", adapterPackage: \"autonoma-sdk\" },\n { language: \"rust\", framework: \"actix\", sdkPackage: \"autonoma-sdk\", adapterPackage: \"autonoma-sdk\" },\n { language: \"elixir\", framework: \"plug\", sdkPackage: \"autonoma\", adapterPackage: \"autonoma\" },\n];\n\nexport function adapterKey(a: SdkAdapter): string {\n return `${a.language}:${a.framework}`;\n}\n\nexport function adapterLabel(a: SdkAdapter): string {\n const lang = a.language.charAt(0).toUpperCase() + a.language.slice(1);\n const fw = a.framework.charAt(0).toUpperCase() + a.framework.slice(1);\n return `${lang} + ${fw}`;\n}\n\nexport function findAdapter(language: string, framework: string): SdkAdapter | undefined {\n return ALL_ADAPTERS.find(\n (a) => a.language === language.toLowerCase() && a.framework === framework.toLowerCase(),\n );\n}\n\nexport const ADAPTER_HINTS: Record<string, string> = {\n \"typescript:express\": \"Express.js and Express-compatible frameworks\",\n \"typescript:node\": \"Plain Node.js HTTP server (built-in http module)\",\n \"typescript:hono\": \"Hono framework (works with Bun, Deno, Node)\",\n \"typescript:web\": \"Web Standard Request/Response — covers Next.js, Remix, Nuxt, Bun, Deno, SvelteKit, Astro\",\n \"python:flask\": \"Flask framework\",\n \"python:fastapi\": \"FastAPI framework\",\n \"python:django\": \"Django framework\",\n \"go:gin\": \"Gin framework for Go\",\n \"ruby:rails\": \"Ruby on Rails\",\n \"ruby:rack\": \"Rack-based Ruby frameworks (Sinatra, Hanami, etc.)\",\n \"java:spring\": \"Spring Boot / Spring Framework\",\n \"php:laravel\": \"Laravel framework\",\n \"rust:axum\": \"Axum framework for Rust\",\n \"rust:actix\": \"Actix Web framework for Rust\",\n \"elixir:plug\": \"Plug / Phoenix framework for Elixir\",\n};\n\nexport interface RecipeBuilderState {\n phase: \"tech-detect\" | \"entity-loop\" | \"full-validation\" | \"submit\" | \"done\";\n techStack: TechStack | null;\n entityOrder: string[];\n entities: Record<string, EntityProgress>;\n currentEntityIndex: number;\n sdkEndpointUrl: string | null;\n sharedSecret: string | null;\n}\n\nconst STATE_FILE = \".recipe-builder-state.json\";\n\nexport function initialRecipeState(): RecipeBuilderState {\n return {\n phase: \"tech-detect\",\n techStack: null,\n entityOrder: [],\n entities: {},\n currentEntityIndex: 0,\n sdkEndpointUrl: null,\n sharedSecret: null,\n };\n}\n\nexport async function loadRecipeState(outputDir: string): Promise<RecipeBuilderState | null> {\n try {\n const raw = await readFile(join(outputDir, STATE_FILE), \"utf-8\");\n return JSON.parse(raw) as RecipeBuilderState;\n } catch {\n return null;\n }\n}\n\nexport async function saveRecipeState(outputDir: string, state: RecipeBuilderState): Promise<void> {\n await writeFile(join(outputDir, STATE_FILE), JSON.stringify(state, null, 2), \"utf-8\");\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface AuditedModel {\n name: string;\n independently_created: boolean;\n creation_file?: string;\n creation_function?: string;\n side_effects?: string[];\n created_by: { owner: string; via?: string; why?: string }[];\n}\n\nexport async function parseEntityAudit(outputDir: string): Promise<AuditedModel[]> {\n const raw = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) throw new Error(\"entity-audit.md has no YAML frontmatter\");\n\n const yaml = fmMatch[1]!;\n const models: AuditedModel[] = [];\n let current: Partial<AuditedModel> | null = null;\n let inCreatedBy = false;\n let currentCreatedBy: { owner: string; via?: string; why?: string } | null = null;\n\n for (const line of yaml.split(\"\\n\")) {\n if (line.match(/^\\s{2}- name:/)) {\n if (current?.name) {\n if (currentCreatedBy?.owner) {\n (current.created_by ??= []).push(currentCreatedBy);\n currentCreatedBy = null;\n }\n models.push({\n name: current.name,\n independently_created: current.independently_created ?? false,\n creation_file: current.creation_file,\n creation_function: current.creation_function,\n side_effects: current.side_effects,\n created_by: current.created_by ?? [],\n });\n }\n current = { name: line.match(/name:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim() };\n inCreatedBy = false;\n currentCreatedBy = null;\n continue;\n }\n\n if (!current) continue;\n\n const kvMatch = line.match(/^\\s{4}(\\w+):\\s*(.+)/);\n if (kvMatch && !inCreatedBy) {\n const [, key, val] = kvMatch;\n const v = val!.replace(/^[\"']|[\"']$/g, \"\").trim();\n switch (key) {\n case \"independently_created\":\n current.independently_created = v === \"true\";\n break;\n case \"creation_file\":\n current.creation_file = v;\n break;\n case \"creation_function\":\n current.creation_function = v;\n break;\n }\n }\n\n if (line.match(/^\\s{4}side_effects:/)) {\n current.side_effects = [];\n continue;\n }\n if (current.side_effects !== undefined && line.match(/^\\s{6}-\\s/)) {\n const val = line.replace(/^\\s{6}-\\s*/, \"\").replace(/^[\"']|[\"']$/g, \"\").trim();\n if (val) current.side_effects.push(val);\n continue;\n }\n\n if (line.match(/^\\s{4}created_by:/)) {\n current.created_by = [];\n current.side_effects = undefined;\n inCreatedBy = true;\n continue;\n }\n\n if (inCreatedBy) {\n if (line.match(/^\\s{6}- owner:/)) {\n if (currentCreatedBy?.owner) {\n current.created_by!.push(currentCreatedBy);\n }\n currentCreatedBy = { owner: line.match(/owner:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim() ?? \"\" };\n continue;\n }\n if (currentCreatedBy && line.match(/^\\s{8}via:/)) {\n currentCreatedBy.via = line.match(/via:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim();\n continue;\n }\n if (currentCreatedBy && line.match(/^\\s{8}why:/)) {\n currentCreatedBy.why = line.match(/why:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim();\n continue;\n }\n }\n }\n\n if (current?.name) {\n if (currentCreatedBy?.owner) {\n (current.created_by ??= []).push(currentCreatedBy);\n }\n models.push({\n name: current.name,\n independently_created: current.independently_created ?? false,\n creation_file: current.creation_file,\n creation_function: current.creation_function,\n side_effects: current.side_effects,\n created_by: current.created_by ?? [],\n });\n }\n\n return models;\n}\n\nexport function resolveEntityOrder(models: AuditedModel[]): string[] {\n const factoryModels = models.filter((m) => m.independently_created);\n const nameSet = new Set(factoryModels.map((m) => m.name));\n\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, string[]>();\n for (const m of factoryModels) {\n inDegree.set(m.name, 0);\n dependents.set(m.name, []);\n }\n\n for (const m of factoryModels) {\n for (const dep of m.created_by) {\n if (nameSet.has(dep.owner)) {\n inDegree.set(m.name, (inDegree.get(m.name) ?? 0) + 1);\n dependents.get(dep.owner)!.push(m.name);\n }\n }\n }\n\n const queue: string[] = [];\n for (const [name, deg] of inDegree) {\n if (deg === 0) queue.push(name);\n }\n queue.sort();\n\n const result: string[] = [];\n while (queue.length > 0) {\n const name = queue.shift()!;\n result.push(name);\n for (const dep of dependents.get(name) ?? []) {\n const newDeg = (inDegree.get(dep) ?? 1) - 1;\n inDegree.set(dep, newDeg);\n if (newDeg === 0) {\n queue.push(dep);\n queue.sort();\n }\n }\n }\n\n if (result.length !== factoryModels.length) {\n const missing = factoryModels\n .filter((m) => !result.includes(m.name))\n .map((m) => m.name);\n console.warn(`[recipe-builder] Circular dependency detected for: ${missing.join(\", \")}. Appending in original order.`);\n for (const m of missing) result.push(m);\n }\n\n return result;\n}\n\nexport function getEntityDependencyChain(\n entityName: string,\n models: AuditedModel[],\n entityOrder: string[],\n): string[] {\n const modelMap = new Map(models.map((m) => [m.name, m]));\n const visited = new Set<string>();\n const chain: string[] = [];\n\n function walk(name: string) {\n if (visited.has(name)) return;\n visited.add(name);\n const model = modelMap.get(name);\n if (!model) return;\n for (const dep of model.created_by) {\n if (entityOrder.includes(dep.owner)) {\n walk(dep.owner);\n }\n }\n chain.push(name);\n }\n\n walk(entityName);\n return chain;\n}\n","import * as p from \"@clack/prompts\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { getModel } from \"../../../core/model\";\nimport { buildReadFileTool, buildGlobTool, buildGrepTool, buildBashTool } from \"../../../tools\";\nimport { loadGitignorePatterns } from \"../../../core/gitignore\";\nimport {\n ALL_ADAPTERS,\n ADAPTER_HINTS,\n adapterKey,\n adapterLabel,\n findAdapter,\n type TechStack,\n} from \"../state\";\n\nconst DOCS_BASE = \"https://docs.agent.autonoma.app\";\n\nconst SYSTEM_PROMPT = `You are a backend technology detector. Your job is to identify the programming language and web framework used by a project's backend/API server.\n\nExplore the project files to detect:\n1. The programming language (check package.json, requirements.txt, go.mod, Gemfile, pom.xml, composer.json, Cargo.toml, mix.exs)\n2. The web framework (check imports, config files, middleware setup)\n\nWhen done, call finish with your findings.`;\n\nexport async function detectTechStack(\n projectRoot: string,\n modelId?: string,\n nonInteractive?: boolean,\n): Promise<TechStack> {\n const model = getModel(modelId);\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n\n let detected: { language: string; framework: string } | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"tech-detect\", 10);\n\n const finishTool = tool({\n description: \"Report the detected backend technology stack.\",\n inputSchema: z.object({\n language: z.string().describe(\"Programming language: typescript, python, go, ruby, java, php, rust, elixir\"),\n framework: z.string().describe(\"Web framework: express, node, hono, web, flask, fastapi, django, gin, rails, rack, spring, laravel, axum, actix, plug\"),\n }),\n execute: async (input) => {\n detected = input;\n return { detected: input };\n },\n });\n\n const agentConfig = {\n id: \"tech-detect\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 10,\n tools: (_heartbeat: () => void) => ({\n read_file: buildReadFileTool(projectRoot),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n grep: buildGrepTool(projectRoot),\n bash: buildBashTool(projectRoot),\n finish: finishTool,\n }),\n onStepFinish,\n };\n\n p.log.info(\"First, we need to know your backend stack so we can point you to the right SDK adapter and give you correct code examples.\");\n\n await runAgent(agentConfig, \"Detect the backend programming language and web framework for this project. Check dependency files and imports. Call finish with your findings.\", () => detected);\n logger.summary();\n\n const suggested = detected ? findAdapter(detected.language, detected.framework) : undefined;\n\n if (nonInteractive && suggested) return suggested;\n\n if (!suggested) {\n p.log.warn(\n `Could not auto-detect an exact adapter for your backend.\\n` +\n ` If your framework uses the Web Standard Request/Response API (Next.js, Remix, Bun, etc.), choose \"Web Standard\".\\n` +\n ` You can also implement a custom adapter — see ${DOCS_BASE}/sdk/custom-adapter`,\n );\n }\n\n const options = ALL_ADAPTERS.map((a) => ({\n value: adapterKey(a),\n label: a === suggested ? `${adapterLabel(a)} (detected)` : adapterLabel(a),\n hint: ADAPTER_HINTS[adapterKey(a)] ?? a.adapterPackage,\n }));\n\n if (suggested) {\n const suggestedIdx = options.findIndex((o) => o.value === adapterKey(suggested));\n if (suggestedIdx > 0) {\n const [item] = options.splice(suggestedIdx, 1);\n options.unshift(item!);\n }\n }\n\n const selectMessage = detected\n ? `Select your backend adapter (we detected ${detected.language}/${detected.framework}):`\n : \"Select your backend adapter:\";\n\n const selected = await p.select({\n message: selectMessage,\n options,\n });\n\n if (p.isCancel(selected)) {\n throw new Error(\"Tech detection cancelled\");\n }\n\n const [lang, fw] = (selected as string).split(\":\");\n const adapter = findAdapter(lang!, fw!);\n if (!adapter) throw new Error(`Unknown adapter: ${selected}`);\n\n p.log.success(`Using ${adapterLabel(adapter)} — SDK: ${adapter.sdkPackage}, Adapter: ${adapter.adapterPackage}`);\n\n return adapter;\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"bun\" | \"pnpm\" | \"yarn\" | \"npm\";\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"bun.lock\")) || existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nexport function installCommand(pm: PackageManager, ...packages: string[]): string {\n const pkgs = packages.join(\" \");\n switch (pm) {\n case \"bun\": return `bun add ${pkgs}`;\n case \"pnpm\": return `pnpm add ${pkgs}`;\n case \"yarn\": return `yarn add ${pkgs}`;\n case \"npm\": return `npm install ${pkgs}`;\n }\n}\n\nexport function runCommand(pm: PackageManager): string {\n switch (pm) {\n case \"bun\": return \"bun run\";\n case \"pnpm\": return \"pnpm run\";\n case \"yarn\": return \"yarn run\";\n case \"npm\": return \"npm run\";\n }\n}\n\nexport function execCommand(pm: PackageManager, file: string): string {\n switch (pm) {\n case \"bun\": return `bun ${file}`;\n case \"pnpm\": return `pnpm tsx ${file}`;\n case \"yarn\": return `yarn tsx ${file}`;\n case \"npm\": return `npx tsx ${file}`;\n }\n}\n","import hljs from \"highlight.js\";\n\nconst RESET = \"\\x1b[0m\";\n\nconst ANSI: Record<string, string> = {\n reset: RESET,\n keyword: \"\\x1b[35m\",\n string: \"\\x1b[32m\",\n number: \"\\x1b[33m\",\n comment: \"\\x1b[2m\",\n built_in: \"\\x1b[33m\",\n type: \"\\x1b[33m\",\n title: \"\\x1b[36m\",\n literal: \"\\x1b[35m\",\n attr: \"\",\n params: \"\",\n function: \"\\x1b[36m\",\n property: \"\",\n punctuation: \"\\x1b[2m\",\n operator: \"\",\n variable: \"\",\n subst: \"\\x1b[36m\",\n \"template-variable\": \"\\x1b[36m\",\n meta: \"\\x1b[2m\",\n regexp: \"\\x1b[31m\",\n};\n\nfunction spanReplacer(_match: string, cls: string): string {\n const mainCls = cls.split(\" \")[0]!;\n return ANSI[mainCls] ?? \"\";\n}\n\nfunction htmlToAnsi(html: string): string {\n return html\n .replace(/<span class=\"hljs-([^\"]+)\">/g, spanReplacer)\n .replace(/<\\/span>/g, RESET)\n .replace(/'/g, \"'\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, '\"');\n}\n\nexport function highlightCode(code: string, language = \"typescript\"): string {\n try {\n const result = hljs.highlight(code, { language, ignoreIllegals: true });\n return htmlToAnsi(result.value);\n } catch {\n return code;\n }\n}\n\nexport function codeNoteFormat(line: string): string {\n if (line.includes(\"\\x1b[\")) return line;\n return highlightCode(line);\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { EntityProgress } from \"./state\";\nimport { getEntityDependencyChain, type AuditedModel } from \"./entity-order\";\n\nexport type RecipePayload = Record<string, Record<string, unknown>[]>;\n\nexport function buildSingleEntityRecipe(\n entityName: string,\n models: AuditedModel[],\n entityOrder: string[],\n allEntities: Record<string, EntityProgress>,\n): RecipePayload {\n const chain = getEntityDependencyChain(entityName, models, entityOrder);\n const recipe: RecipePayload = {};\n\n for (const name of chain) {\n const entity = allEntities[name];\n if (entity?.recipeData && entity.recipeData.length > 0) {\n recipe[name] = entity.recipeData;\n }\n }\n\n return recipe;\n}\n\nexport function buildFullRecipe(\n entityOrder: string[],\n allEntities: Record<string, EntityProgress>,\n): RecipePayload {\n const recipe: RecipePayload = {};\n\n for (const name of entityOrder) {\n const entity = allEntities[name];\n if (entity?.recipeData && entity.recipeData.length > 0) {\n recipe[name] = entity.recipeData;\n }\n }\n\n return recipe;\n}\n\nexport interface FullRecipeJson {\n version: number;\n source: { discoverPath: string; scenariosPath: string };\n validationMode: string;\n recipes: {\n name: string;\n description: string;\n create: RecipePayload;\n variables?: Record<string, unknown>[];\n validation: {\n status: string;\n method: string;\n up_ms?: number;\n down_ms?: number;\n };\n }[];\n}\n\nexport function buildSubmittableRecipe(\n create: RecipePayload,\n description: string,\n): FullRecipeJson {\n return {\n version: 1,\n source: {\n discoverPath: \"discover.json\",\n scenariosPath: \"scenarios.md\",\n },\n validationMode: \"endpoint-lifecycle\",\n recipes: [\n {\n name: \"standard\",\n description,\n create,\n validation: {\n status: \"validated\",\n method: \"endpoint-up-down\",\n },\n },\n ],\n };\n}\n\nconst RECIPE_FILE = \"recipe.json\";\n\nexport async function saveRecipe(outputDir: string, recipe: FullRecipeJson): Promise<void> {\n await writeFile(join(outputDir, RECIPE_FILE), JSON.stringify(recipe, null, 2), \"utf-8\");\n}\n\nexport async function loadRecipe(outputDir: string): Promise<FullRecipeJson | null> {\n try {\n const raw = await readFile(join(outputDir, RECIPE_FILE), \"utf-8\");\n return JSON.parse(raw) as FullRecipeJson;\n } catch {\n return null;\n }\n}\n","import { createHmac } from \"node:crypto\";\n\nexport interface SdkClientConfig {\n endpointUrl: string;\n sharedSecret: string;\n}\n\nexport interface SdkResponse {\n ok: boolean;\n status: number;\n body: unknown;\n}\n\nfunction sign(body: string, secret: string): string {\n return createHmac(\"sha256\", secret).update(body).digest(\"hex\");\n}\n\nasync function sendRequest(config: SdkClientConfig, payload: unknown): Promise<SdkResponse> {\n const rawBody = JSON.stringify(payload);\n const signature = sign(rawBody, config.sharedSecret);\n\n const res = await fetch(config.endpointUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-signature\": signature,\n },\n body: rawBody,\n });\n\n let body: unknown;\n const text = await res.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n return { ok: res.ok, status: res.status, body };\n}\n\nexport async function discover(config: SdkClientConfig): Promise<SdkResponse> {\n return sendRequest(config, { action: \"discover\" });\n}\n\nexport async function up(\n config: SdkClientConfig,\n create: Record<string, unknown[]>,\n testRunId: string,\n): Promise<SdkResponse> {\n return sendRequest(config, {\n action: \"up\",\n testRunId,\n environment: \"test\",\n create,\n });\n}\n\nexport async function down(\n config: SdkClientConfig,\n refsToken: string,\n): Promise<SdkResponse> {\n return sendRequest(config, {\n action: \"down\",\n refsToken,\n });\n}\n","import * as p from \"@clack/prompts\";\nimport { writeFile, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { spawn } from \"node:child_process\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { LanguageModel } from \"ai\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { buildReadFileTool, buildGlobTool, buildGrepTool } from \"../../../tools\";\nimport { buildAskUserTool } from \"../../../tools/ask-user\";\nimport { loadGitignorePatterns } from \"../../../core/gitignore\";\nimport { detectPackageManager, installCommand } from \"../../../core/detect-pkg-manager\";\nimport type { RecipeBuilderState, TechStack, EntityProgress } from \"../state\";\nimport { adapterLabel, saveRecipeState } from \"../state\";\nimport { codeNoteFormat } from \"../../../core/highlight\";\nimport type { AuditedModel } from \"../entity-order\";\nimport { notify } from \"../../../core/notify\";\nimport { buildSingleEntityRecipe } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\n\nconst PROPOSAL_PROMPT = `You are a recipe data designer. Given an entity from the entity audit and the scenario data, produce a JSON array of records for this entity.\n\nRules:\n- Use EXACT values from the scenarios.md file\n- Add _alias fields (e.g., \"entity_1\", \"entity_2\") for referencing\n- Use { \"_ref\": \"alias\" } syntax to reference previously-completed parent entities\n- Match the field names and types from the entity audit's creation schema\n- Include realistic, diverse data that covers different enum values\n- For JSON/JSONB fields, use actual nested objects and arrays — NOT stringified JSON.\n WRONG: \"metadata\": \"{\\\\\"key\\\\\": \\\\\"value\\\\\"}\"\n RIGHT: \"metadata\": {\"key\": \"value\"}\n- If you encounter untyped JSON/JSONB fields, use ask_user to ask the developer about the expected schema\n\nWhen done, call finish with the JSON array.`;\n\nconst INSTRUCTIONS_PROMPT = `You are a pedagogical guide helping a developer implement an Autonoma SDK factory.\n\nGiven the entity audit information and the project's source code, produce clear, copy-pasteable instructions for implementing this factory. The developer will likely hand these to Claude or another AI assistant.\n\nInclude:\n1. What to import (service classes, validators, Zod schemas)\n2. The factory shape (inputSchema, create function, teardown function)\n3. Where create() should call into (the project's existing service functions)\n4. What teardown() should delete\n\nBe specific — reference actual file paths, function names, and types from the codebase.\n\nWhen done, call finish with the instructions text.`;\n\nasync function proposeRecipeData(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n model: LanguageModel,\n outputDir: string,\n _projectRoot: string,\n completedEntities: Record<string, EntityProgress>,\n): Promise<Record<string, unknown>[]> {\n let result: Record<string, unknown>[] | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`propose:${entityName}`, 20);\n\n const finishTool = tool({\n description: \"Submit the proposed recipe data as a JSON array of records.\",\n inputSchema: z.object({\n records: z.array(z.record(z.string(), z.unknown())).describe(\"Array of record objects for this entity\"),\n }),\n execute: async (input) => {\n result = input.records;\n return { accepted: true };\n },\n });\n\n const completedAliases = Object.entries(completedEntities)\n .filter(([, e]) => e.recipeData && e.recipeData.length > 0)\n .map(([name, e]) => `${name}: aliases ${e.recipeData!.map((r) => r._alias ?? \"?\").join(\", \")}`)\n .join(\"\\n\");\n\n const prompt = `[${entityIndex + 1}/${totalEntities}] Propose recipe data for entity \"${entityName}\".\n\nRead scenarios.md and entity-audit.md from the output directory. Design records that match the scenario data.\n\n${completedAliases ? `Already completed entities (use _ref to reference their aliases):\\n${completedAliases}\\n` : \"This is a root entity — no parent references needed.\"}\n\nCall finish with the JSON array of records.`;\n\n const readOutputTool = buildReadFileTool(outputDir);\n\n await runAgent(\n {\n id: `propose-${entityName}`,\n systemPrompt: PROPOSAL_PROMPT,\n model,\n maxSteps: 20,\n tools: (_heartbeat: () => void) => ({\n read_output: readOutputTool,\n ask_user: buildAskUserTool(),\n finish: finishTool,\n }),\n onStepFinish,\n },\n prompt,\n () => result,\n );\n logger.summary();\n\n return result ?? [];\n}\n\nasync function reviseRecipeData(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n current: Record<string, unknown>[],\n feedback: string,\n model: LanguageModel,\n outputDir: string,\n): Promise<Record<string, unknown>[]> {\n let revised: Record<string, unknown>[] | undefined;\n\n const finishTool = tool({\n description: \"Submit the fixed recipe data.\",\n inputSchema: z.object({\n records: z.array(z.record(z.string(), z.unknown())),\n }),\n execute: async (input) => {\n revised = input.records;\n return { done: true };\n },\n });\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`fix:${entityName}`, 15);\n\n await runAgent(\n {\n id: `fix-${entityName}`,\n systemPrompt: `You are fixing recipe data that failed validation. Read the error, the current data, and the user's feedback. Read scenarios.md and entity-audit.md if needed. Fix the data and call finish.\n\nRules:\n- _alias fields must be unique identifiers (e.g., \"card_1\", \"transaction_1\")\n- _ref fields reference aliases from OTHER entities that were already created\n- Read scenarios.md to verify you're using correct alias names from parent entities\n- Field names must match the entity's schema from entity-audit.md`,\n model,\n maxSteps: 15,\n tools: (_heartbeat: () => void) => ({\n read_output: buildReadFileTool(outputDir),\n finish: finishTool,\n }),\n onStepFinish,\n },\n `[${entityIndex + 1}/${totalEntities}] Fix recipe data for \"${entityName}\".\n\nCurrent data that failed:\n${JSON.stringify(current, null, 2)}\n\nProblem:\n${feedback}\n\nRead scenarios.md and entity-audit.md to understand the correct aliases and schema. Fix the data and call finish.`,\n () => revised,\n );\n logger.summary();\n\n if (revised) {\n p.note(JSON.stringify(revised, null, 2), `Fixed data for ${entityName}`, { format: codeNoteFormat });\n return revised;\n }\n\n p.log.warn(\"Could not auto-fix. Returning original data.\");\n return current;\n}\n\nasync function generateInstructions(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n isFirst: boolean,\n techStack: TechStack,\n auditModel: AuditedModel,\n recipeData: Record<string, unknown>[],\n model: LanguageModel,\n projectRoot: string,\n outputDir: string,\n): Promise<string> {\n let result: string | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`instructions:${entityName}`, 15);\n\n const finishTool = tool({\n description: \"Submit the implementation instructions.\",\n inputSchema: z.object({\n instructions: z.string().describe(\"Complete, copy-pasteable implementation instructions\"),\n }),\n execute: async (input) => {\n result = input.instructions;\n return { done: true };\n },\n });\n\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n\n const pm = detectPackageManager(projectRoot);\n const installCmd = techStack.language === \"typescript\"\n ? installCommand(pm, techStack.sdkPackage, techStack.adapterPackage)\n : `pip install ${techStack.sdkPackage}[${techStack.framework}]`;\n\n const setupContext = isFirst\n ? `\\nThis is the FIRST entity. Include one-time setup instructions:\n- Install SDK: ${installCmd}\n- Create the route/endpoint file\n- Add env vars: AUTONOMA_SHARED_SECRET, AUTONOMA_SIGNING_SECRET\n- Explain: \"This single endpoint handles discover/up/down — the SDK routes internally\"\n- Include the auth callback in createHandler config. The auth callback receives the first User record created during UP and must return real credentials the test runner can use to authenticate. Three patterns:\n - Session cookies (most web apps): create a session, return { cookies: [{ name, value, httpOnly, sameSite, path }] }\n - JWT bearer token (SPAs/APIs): sign a JWT, return { headers: { Authorization: \"Bearer <real-token>\" } }\n - Email/password (mobile/native login): return { credentials: { email: user.email, password: \"the-test-password\" } }\n Choose the pattern that matches how this app authenticates users. Read the project's auth code to determine which.\\n`\n : \"\";\n\n const prompt = `[${entityIndex + 1}/${totalEntities}] Generate implementation instructions for the \"${entityName}\" factory.\n${setupContext}\nEntity audit info:\n- Creation file: ${auditModel.creation_file ?? \"unknown\"}\n- Creation function: ${auditModel.creation_function ?? \"unknown\"}\n- Side effects: ${auditModel.side_effects?.join(\", \") ?? \"none\"}\n- Dependencies: ${auditModel.created_by.map((d) => d.owner).join(\", \") || \"none (root entity)\"}\n\nAccepted recipe data (${recipeData.length} records):\n${JSON.stringify(recipeData, null, 2)}\n\nTech stack: ${adapterLabel(techStack)}\n\nRead the creation file from the project to understand the existing service/function. Then produce instructions.`;\n\n await runAgent(\n {\n id: `instructions-${entityName}`,\n systemPrompt: INSTRUCTIONS_PROMPT,\n model,\n maxSteps: 15,\n tools: (_heartbeat: () => void) => ({\n read_file: buildReadFileTool(projectRoot),\n read_output: buildReadFileTool(outputDir),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n grep: buildGrepTool(projectRoot),\n finish: finishTool,\n }),\n onStepFinish,\n },\n prompt,\n () => result,\n );\n logger.summary();\n\n return result ?? \"No instructions generated. Check the entity audit for creation_file and creation_function.\";\n}\n\nasync function reviewRecipeData(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n proposed: Record<string, unknown>[],\n model: LanguageModel,\n outputDir: string,\n): Promise<Record<string, unknown>[]> {\n p.log.info(\n \"Legend for recipe fields:\\n\" +\n \" _alias — Internal ID used to reference this record from other entities (e.g., { \\\"_ref\\\": \\\"org_1\\\" })\\n\" +\n \" _ref — Reference to a record created by a parent entity's _alias\\n\" +\n \" All other fields are the actual data that will be inserted into your database.\",\n );\n\n p.note(JSON.stringify(proposed, null, 2), `Proposed data for ${entityName} (${proposed.length} records)`, { format: codeNoteFormat });\n\n p.log.info(\n \"Review checklist:\\n\" +\n \" - Do field values match your real data patterns?\\n\" +\n \" - Are _ref references pointing to correct parent aliases?\\n\" +\n \" - Are enum fields varied across records (not all the same value)?\\n\" +\n \" - Are there enough records for your test scenarios?\",\n );\n\n while (true) {\n const action = await p.select({\n message: `[${entityIndex + 1}/${totalEntities}] ${entityName} — does this data look right?`,\n options: [\n { value: \"keep\", label: \"Yes, keep\" },\n { value: \"chat\", label: \"No, let's chat\" },\n { value: \"edit\", label: \"No, edit manually\" },\n ],\n });\n\n if (p.isCancel(action)) throw new Error(\"Recipe review cancelled\");\n\n if (action === \"keep\") return proposed;\n\n if (action === \"edit\") {\n const tmpPath = join(tmpdir(), `autonoma-recipe-${entityName}.json`);\n await writeFile(tmpPath, JSON.stringify(proposed, null, 2), \"utf-8\");\n\n const editor = process.env.EDITOR ?? process.env.VISUAL ?? \"vi\";\n p.log.info(`Opening ${editor}... Save and close when done.`);\n\n await new Promise<void>((resolve, reject) => {\n const proc = spawn(editor, [tmpPath], { stdio: \"inherit\" });\n proc.on(\"close\", () => resolve());\n proc.on(\"error\", reject);\n });\n\n const edited = await readFile(tmpPath, \"utf-8\");\n try {\n proposed = JSON.parse(edited);\n p.note(JSON.stringify(proposed, null, 2), `Updated data for ${entityName}`, { format: codeNoteFormat });\n } catch (err) {\n p.log.error(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}. Try again.`);\n }\n continue;\n }\n\n if (action === \"chat\") {\n const feedback = await p.text({\n message: \"What should be changed?\",\n placeholder: \"e.g., add more records, change field values, fix references...\",\n });\n\n if (p.isCancel(feedback) || !(feedback as string).trim()) continue;\n\n let revised: Record<string, unknown>[] | undefined;\n const finishTool = tool({\n description: \"Submit revised recipe data.\",\n inputSchema: z.object({\n records: z.array(z.record(z.string(), z.unknown())),\n }),\n execute: async (input) => {\n revised = input.records;\n return { done: true };\n },\n });\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`revise:${entityName}`, 10);\n\n await runAgent(\n {\n id: `revise-${entityName}`,\n systemPrompt: \"You are revising recipe data based on user feedback. Read the current data, apply the feedback, and call finish with the updated records.\",\n model,\n maxSteps: 10,\n tools: (_heartbeat: () => void) => ({\n read_output: buildReadFileTool(outputDir),\n finish: finishTool,\n }),\n onStepFinish,\n },\n `Current data for ${entityName}:\\n${JSON.stringify(proposed, null, 2)}\\n\\nUser feedback: \"${feedback}\"\\n\\nRevise the data and call finish.`,\n () => revised,\n );\n logger.summary();\n\n if (revised) {\n proposed = revised;\n p.note(JSON.stringify(proposed, null, 2), `Revised data for ${entityName}`, { format: codeNoteFormat });\n }\n }\n }\n}\n\ntype TestResult = \"success\" | \"skip\" | { feedback: string };\n\nasync function promptOnFailure(entityName: string, errorBody: unknown): Promise<\"retry\" | \"skip\" | { feedback: string }> {\n notify(\"Autonoma\", `${entityName} — failed, action needed`);\n const action = await p.select({\n message: \"What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Yes, retry — I fixed my handler code\", hint: \"Send the same request again\" },\n { value: \"feedback\", label: \"Yes, fix the recipe data\", hint: \"The request data is wrong — I'll explain what to change\" },\n { value: \"skip\", label: \"No, skip this entity\", hint: \"Move on to the next entity\" },\n ],\n });\n if (p.isCancel(action)) throw new Error(\"Entity loop cancelled\");\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") return \"retry\";\n\n const fb = await p.text({\n message: \"What's wrong with the recipe data?\",\n placeholder: \"e.g. Transaction references acc_1 but Account uses account_1 as its alias\",\n });\n if (p.isCancel(fb)) throw new Error(\"Entity loop cancelled\");\n const errorContext = errorBody ? `\\nServer error: ${JSON.stringify(errorBody)}` : \"\";\n return { feedback: `${(fb as string).trim()}${errorContext}` };\n}\n\nasync function testUpDown(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n sdkConfig: SdkClientConfig,\n recipe: Record<string, unknown[]>,\n): Promise<TestResult> {\n p.log.info(`Let's verify this factory works. We'll send a test request to create ${entityName}, then check the database.`);\n\n // UP with retry loop\n while (true) {\n const testRunId = `test-${Date.now()}`;\n\n p.log.step(`[${entityIndex + 1}/${totalEntities}] Sending UP request...`);\n\n let upResult: Awaited<ReturnType<typeof sdk.up>>;\n try {\n upResult = await sdk.up(sdkConfig, recipe, testRunId);\n } catch (err) {\n p.log.error(`UP request failed: ${err instanceof Error ? err.message : String(err)}`);\n const action = await promptOnFailure(entityName, null);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n if (!upResult.ok) {\n p.log.error(`UP failed (HTTP ${upResult.status}):`);\n console.log(JSON.stringify(upResult.body, null, 2));\n const action = await promptOnFailure(entityName, upResult.body);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n p.log.success(`UP succeeded!`);\n console.log(JSON.stringify(upResult.body, null, 2));\n\n const refsToken = (upResult.body as Record<string, unknown>)?.refsToken as string | undefined;\n if (!refsToken) {\n p.log.error(\"No refsToken in UP response — cannot test DOWN.\");\n return \"skip\";\n }\n\n // DOWN with retry loop\n p.log.info(\"Now let's verify teardown works — leftover test data would pollute your database.\");\n while (true) {\n p.log.step(`[${entityIndex + 1}/${totalEntities}] Sending DOWN request...`);\n\n let downResult: Awaited<ReturnType<typeof sdk.down>>;\n try {\n downResult = await sdk.down(sdkConfig, refsToken);\n } catch (err) {\n p.log.error(`DOWN request failed: ${err instanceof Error ? err.message : String(err)}`);\n const action = await promptOnFailure(entityName, null);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n if (!downResult.ok) {\n p.log.error(`DOWN failed (HTTP ${downResult.status}):`);\n console.log(JSON.stringify(downResult.body, null, 2));\n const action = await promptOnFailure(entityName, downResult.body);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n p.log.success(\"DOWN succeeded!\");\n return \"success\";\n }\n }\n}\n\nexport async function runEntityLoop(\n state: RecipeBuilderState,\n models: AuditedModel[],\n model: LanguageModel,\n projectRoot: string,\n outputDir: string,\n nonInteractive?: boolean,\n): Promise<void> {\n const total = state.entityOrder.length;\n const modelMap = new Map(models.map((m) => [m.name, m]));\n\n p.log.info(\n `We're going to set up your test data factories one entity at a time. Each factory teaches the Autonoma SDK how to create and tear down a specific type of record in YOUR database, using YOUR existing service functions.\\n\\n We'll test each one live before moving on — this way if something breaks, you'll know exactly which entity caused it. Let's start with the root entities (no dependencies), then work through the dependents.`,\n );\n\n for (let i = state.currentEntityIndex; i < total; i++) {\n const entityName = state.entityOrder[i]!;\n const auditModel = modelMap.get(entityName);\n if (!auditModel) {\n p.log.warn(`[${i + 1}/${total}] ${entityName} — not found in entity audit, skipping`);\n state.entities[entityName] = {\n entityName,\n status: \"skipped\",\n recipeData: null,\n errorLog: [\"Not found in entity audit\"],\n };\n state.currentEntityIndex = i + 1;\n await saveRecipeState(outputDir, state);\n continue;\n }\n\n const existing = state.entities[entityName];\n if (existing?.status === \"tested-down\") {\n p.log.info(`[${i + 1}/${total}] ${entityName} — already done, skipping`);\n continue;\n }\n\n const isRoot = auditModel.created_by.length === 0;\n const depInfo = isRoot\n ? \"This is a root entity — no dependencies.\"\n : `This depends on: ${auditModel.created_by.map((d) => d.owner).join(\", \")}`;\n\n p.log.step(`[${i + 1}/${total}] ${entityName}`);\n p.log.info(depInfo);\n\n // A. Propose recipe data\n let recipeData = existing?.recipeData;\n if (!recipeData || existing?.status === \"pending\") {\n recipeData = await proposeRecipeData(\n entityName, i, total, model, outputDir, projectRoot, state.entities,\n );\n }\n\n // B. User review\n if (!nonInteractive) {\n recipeData = await reviewRecipeData(entityName, i, total, recipeData, model, outputDir);\n }\n\n state.entities[entityName] = {\n entityName,\n status: \"recipe-accepted\",\n recipeData,\n errorLog: existing?.errorLog ?? [],\n };\n state.currentEntityIndex = i;\n await saveRecipeState(outputDir, state);\n\n // C. Implementation instructions\n if (!nonInteractive) {\n const instructions = await generateInstructions(\n entityName, i, total,\n i === 0,\n state.techStack!,\n auditModel,\n recipeData,\n model,\n projectRoot,\n outputDir,\n );\n p.note(instructions, `Implementation guide for ${entityName}`, { format: codeNoteFormat });\n\n const DOCS_BASE = \"https://docs.agent.autonoma.app\";\n p.log.info(\n `Copy the instructions above into Claude Code or your AI coding assistant.\\n` +\n ` They can implement the factory directly in your codebase.\\n\\n` +\n ` Autonoma SDK docs: ${DOCS_BASE}/sdk/environment-factory`,\n );\n\n if (i === 0) {\n p.log.info(\"This is your first factory — the instructions include one-time SDK setup. Subsequent entities will only need the factory function.\");\n }\n\n notify(\"Autonoma\", `${entityName} — implementation ready, waiting for you`);\n const ready = await p.confirm({\n message: `[${i + 1}/${total}] Is your server running with the ${entityName} factory?`,\n });\n if (p.isCancel(ready)) throw new Error(\"Entity loop cancelled\");\n\n if (!ready) {\n p.log.info(\"Take your time implementing. Run again with --resume to continue from here.\");\n return;\n }\n }\n\n // D + E. Test UP/DOWN\n if (!nonInteractive && state.techStack) {\n if (!state.sharedSecret) {\n const bytes = new Uint8Array(32);\n crypto.getRandomValues(bytes);\n const secret = [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n state.sharedSecret = secret;\n await saveRecipeState(outputDir, state);\n\n await writeFile(\n join(outputDir, \"autonoma-config.json\"),\n JSON.stringify({ sharedSecret: secret, endpointUrl: state.sdkEndpointUrl }, null, 2),\n \"utf-8\",\n );\n\n p.note(\n `AUTONOMA_SHARED_SECRET=${secret}\\n\\n` +\n `Add this to your server's .env file and restart it.\\n` +\n `This is a 64-character hex key used for HMAC-SHA256 request signing.\\n` +\n `The same value must be set in both your server and the Autonoma dashboard.\\n\\n` +\n `Saved to: ${join(outputDir, \"autonoma-config.json\")}`,\n \"Shared secret generated\",\n );\n\n const secretReady = await p.confirm({\n message: \"Did you add the secret to your .env and restart the server?\",\n });\n if (p.isCancel(secretReady)) throw new Error(\"Entity loop cancelled\");\n if (!secretReady) {\n p.log.info(\"Add the secret and run again with --resume to continue.\");\n return;\n }\n }\n\n if (!state.sdkEndpointUrl) {\n const url = await p.text({\n message: \"What's your SDK endpoint URL?\",\n placeholder: \"http://localhost:3000/api/autonoma\",\n defaultValue: \"http://localhost:3000/api/autonoma\",\n });\n if (p.isCancel(url)) throw new Error(\"Entity loop cancelled\");\n state.sdkEndpointUrl = (url as string).trim() || \"http://localhost:3000/api/autonoma\";\n await saveRecipeState(outputDir, state);\n\n await writeFile(\n join(outputDir, \"autonoma-config.json\"),\n JSON.stringify({ sharedSecret: state.sharedSecret, endpointUrl: state.sdkEndpointUrl }, null, 2),\n \"utf-8\",\n );\n }\n\n const sdkConfig: SdkClientConfig = {\n endpointUrl: state.sdkEndpointUrl,\n sharedSecret: state.sharedSecret,\n };\n\n let testDone = false;\n while (!testDone) {\n const singleRecipe = buildSingleEntityRecipe(entityName, models, state.entityOrder, state.entities);\n const testResult = await testUpDown(entityName, i, total, sdkConfig, singleRecipe);\n\n if (testResult === \"success\") {\n state.entities[entityName]!.status = \"tested-down\";\n p.log.success(`[${i + 1}/${total}] ${entityName} — factory verified`);\n testDone = true;\n } else if (testResult === \"skip\") {\n state.entities[entityName]!.status = \"skipped\";\n state.entities[entityName]!.errorLog.push(\"UP/DOWN test skipped by user\");\n p.log.warn(`[${i + 1}/${total}] ${entityName} — skipped, continuing to next entity`);\n testDone = true;\n } else {\n p.log.info(`Re-generating recipe data for ${entityName} based on your feedback...`);\n const revised = await reviseRecipeData(\n entityName, i, total, state.entities[entityName]!.recipeData!, testResult.feedback, model, outputDir,\n );\n state.entities[entityName]!.recipeData = revised;\n await saveRecipeState(outputDir, state);\n }\n }\n } else if (nonInteractive) {\n state.entities[entityName]!.status = \"tested-down\";\n }\n\n state.currentEntityIndex = i + 1;\n await saveRecipeState(outputDir, state);\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { notify } from \"../../../core/notify\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { saveRecipeState } from \"../state\";\nimport type { AuditedModel } from \"../entity-order\";\nimport { buildFullRecipe } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\n\nexport async function runFullValidation(\n state: RecipeBuilderState,\n _models: AuditedModel[],\n outputDir: string,\n): Promise<boolean> {\n const total = state.entityOrder.length;\n\n p.log.info(\n `All individual factories work. Now let's create EVERYTHING together and verify the app looks right with a full dataset. This is the recipe that will run before every test execution.`,\n );\n\n if (!state.sdkEndpointUrl) {\n const url = await p.text({\n message: \"What's your SDK endpoint URL?\",\n placeholder: \"http://localhost:3000/api/autonoma\",\n defaultValue: \"http://localhost:3000/api/autonoma\",\n });\n if (p.isCancel(url)) throw new Error(\"Cancelled\");\n state.sdkEndpointUrl = (url as string).trim() || \"http://localhost:3000/api/autonoma\";\n await saveRecipeState(outputDir, state);\n }\n\n const sdkConfig: SdkClientConfig = {\n endpointUrl: state.sdkEndpointUrl,\n sharedSecret: state.sharedSecret ?? \"\",\n };\n\n const fullRecipe = buildFullRecipe(state.entityOrder, state.entities);\n\n // UP with retry loop\n while (true) {\n const testRunId = `full-${Date.now()}`;\n p.log.step(`[Full validation] Creating all ${total} entities...`);\n\n let upResult: Awaited<ReturnType<typeof sdk.up>>;\n try {\n upResult = await sdk.up(sdkConfig, fullRecipe, testRunId);\n } catch (err) {\n p.log.error(`Full UP request failed: ${err instanceof Error ? err.message : String(err)}`);\n notify(\"Autonoma\", \"Full validation UP failed, action needed\");\n const action = await p.select({\n message: \"What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Yes, retry — I fixed it\", hint: \"Send the request again\" },\n { value: \"skip\", label: \"No, skip full validation\", hint: \"Continue to test generation\" },\n ],\n });\n if (p.isCancel(action)) throw new Error(\"Cancelled\");\n if (action === \"skip\") return false;\n continue;\n }\n\n if (!upResult.ok) {\n p.log.error(`Full UP failed (HTTP ${upResult.status}):`);\n console.log(JSON.stringify(upResult.body, null, 2));\n notify(\"Autonoma\", \"Full validation UP failed, action needed\");\n const action = await p.select({\n message: \"What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Yes, retry — I fixed it\", hint: \"Send the request again\" },\n { value: \"skip\", label: \"No, skip full validation\", hint: \"Continue to test generation\" },\n ],\n });\n if (p.isCancel(action)) throw new Error(\"Cancelled\");\n if (action === \"skip\") return false;\n continue;\n }\n\n p.log.success(\"Full UP succeeded!\");\n const body = upResult.body as Record<string, unknown>;\n const refsToken = body.refsToken as string | undefined;\n\n const auth = body.auth as Record<string, unknown> | undefined;\n if (auth && Object.keys(auth).length > 0) {\n const authJson = JSON.stringify(auth, null, 2);\n const looksPlaceholder = authJson.includes(\"test-token\") || authJson.includes(\"placeholder\") || authJson.includes(\"todo\");\n\n p.note(\n authJson + \"\\n\\n\" +\n \"These are the credentials your auth callback returns.\\n\" +\n \"The test runner will use them to authenticate as the test user when executing tests.\" +\n (looksPlaceholder\n ? \"\\n\\n⚠ This looks like a placeholder. Update your auth callback to return real credentials\\n\" +\n \"(a valid JWT, session cookie, or email/password) so the test runner can actually log in.\"\n : \"\"),\n \"Auth credentials\",\n );\n } else {\n p.log.warn(\n \"No auth credentials returned. Your createHandler's auth callback must return credentials \" +\n \"the test runner can use to log in (cookies, headers, or email/password). Without it, tests can't authenticate.\",\n );\n }\n\n p.log.info(\"Browse the app and check if the test data looks right.\");\n\n notify(\"Autonoma\", \"Full validation succeeded — review the app\");\n const looksGood = await p.confirm({\n message: \"Does the app look right with the test data?\",\n });\n\n if (p.isCancel(looksGood)) throw new Error(\"Cancelled\");\n\n if (!looksGood) {\n p.log.info(\"You can adjust the recipe by editing recipe.json or re-running individual entities with --resume.\");\n }\n\n if (refsToken) {\n p.log.step(\"[Full validation] Tearing down all entities...\");\n\n let downResult: Awaited<ReturnType<typeof sdk.down>>;\n try {\n downResult = await sdk.down(sdkConfig, refsToken);\n } catch (err) {\n p.log.error(`Full DOWN request failed: ${err instanceof Error ? err.message : String(err)}`);\n return false;\n }\n\n if (!downResult.ok) {\n p.log.error(`Full DOWN failed (HTTP ${downResult.status}):`);\n console.log(JSON.stringify(downResult.body, null, 2));\n return false;\n }\n\n p.log.success(\"Full lifecycle works. All data was created and torn down cleanly.\");\n }\n\n return true;\n }\n}\n","import * as p from \"@clack/prompts\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { buildFullRecipe, buildSubmittableRecipe, saveRecipe } from \"../recipe\";\n\nexport async function runSubmit(\n state: RecipeBuilderState,\n outputDir: string,\n autonomaApiUrl?: string,\n autonomaApiToken?: string,\n autonomaGenerationId?: string,\n): Promise<string> {\n const fullCreate = buildFullRecipe(state.entityOrder, state.entities);\n const recipe = buildSubmittableRecipe(fullCreate, \"Standard test scenario with realistic data\");\n\n await saveRecipe(outputDir, recipe);\n p.log.success(\"Recipe saved to recipe.json\");\n\n if (!autonomaApiUrl || !autonomaApiToken || !autonomaGenerationId) {\n p.log.info(\"Autonoma API credentials not configured — recipe saved locally. Submit manually or configure AUTONOMA_API_URL, AUTONOMA_API_TOKEN, AUTONOMA_GENERATION_ID.\");\n return \"recipe.json\";\n }\n\n const url = `${autonomaApiUrl}/v1/setup/setups/${autonomaGenerationId}/scenario-recipe-versions`;\n\n p.log.step(\"Submitting recipe to Autonoma...\");\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${autonomaApiToken}`,\n },\n body: JSON.stringify(recipe),\n });\n\n if (res.ok) {\n p.log.success(`Recipe submitted successfully (HTTP ${res.status})`);\n } else {\n const text = await res.text();\n p.log.error(`Recipe submission failed (HTTP ${res.status}): ${text}`);\n }\n\n return \"recipe.json\";\n}\n","import * as p from \"@clack/prompts\";\nimport type { AppConfig } from \"../../config\";\nimport type { AgentResult } from \"../../core/agent\";\nimport type { ProjectContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport {\n initialRecipeState,\n loadRecipeState,\n saveRecipeState,\n} from \"./state\";\nimport { parseEntityAudit, resolveEntityOrder } from \"./entity-order\";\nimport { detectTechStack } from \"./phases/tech-detect\";\nimport { runEntityLoop } from \"./phases/entity-loop\";\nimport { runFullValidation } from \"./phases/full-validation\";\nimport { runSubmit } from \"./phases/submit\";\n\nexport interface RecipeBuilderInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n config: AppConfig;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\nexport async function runRecipeBuilder(input: RecipeBuilderInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let state = await loadRecipeState(input.outputDir) ?? initialRecipeState();\n\n const models = await parseEntityAudit(input.outputDir);\n\n // Phase 1: Tech detection\n if (state.phase === \"tech-detect\") {\n state.techStack = await detectTechStack(\n input.projectRoot,\n input.modelId,\n input.nonInteractive,\n );\n\n const entityOrder = resolveEntityOrder(models);\n state.entityOrder = entityOrder;\n state.entities = {};\n for (const name of entityOrder) {\n state.entities[name] = {\n entityName: name,\n status: \"pending\",\n recipeData: null,\n errorLog: [],\n };\n }\n\n state.phase = \"entity-loop\";\n\n if (input.config.sdkEndpointUrl) {\n state.sdkEndpointUrl = input.config.sdkEndpointUrl;\n }\n\n await saveRecipeState(input.outputDir, state);\n p.log.info(`Found ${entityOrder.length} entities needing factories. Processing in dependency order.`);\n }\n\n // Phase 2: Entity-by-entity loop\n if (state.phase === \"entity-loop\") {\n await runEntityLoop(\n state,\n models,\n model,\n input.projectRoot,\n input.outputDir,\n input.nonInteractive,\n );\n\n const allDone = state.entityOrder.every(\n (name) => {\n const e = state.entities[name];\n return e?.status === \"tested-down\" || e?.status === \"skipped\";\n },\n );\n\n if (allDone) {\n state.phase = input.nonInteractive ? \"submit\" : \"full-validation\";\n await saveRecipeState(input.outputDir, state);\n } else {\n return {\n success: false,\n paused: true,\n artifacts: [],\n summary: \"Paused — run again with --resume to continue from where you left off\",\n };\n }\n }\n\n // Phase 3: Full validation\n if (state.phase === \"full-validation\") {\n const success = await runFullValidation(state, models, input.outputDir);\n if (success) {\n state.phase = \"submit\";\n await saveRecipeState(input.outputDir, state);\n } else {\n return {\n success: false,\n paused: true,\n artifacts: [],\n summary: \"Full validation skipped — run again with --resume to retry\",\n };\n }\n }\n\n // Phase 4: Submit\n if (state.phase === \"submit\") {\n const recipePath = await runSubmit(\n state,\n input.outputDir,\n process.env.AUTONOMA_API_URL,\n process.env.AUTONOMA_API_TOKEN,\n process.env.AUTONOMA_GENERATION_ID,\n );\n\n state.phase = \"done\";\n await saveRecipeState(input.outputDir, state);\n\n return {\n success: true,\n artifacts: [recipePath],\n summary: `Recipe builder complete. ${state.entityOrder.length} factories configured.`,\n };\n }\n\n return {\n success: true,\n artifacts: [],\n summary: \"Recipe builder already complete.\",\n };\n}\n","import { z } from \"zod\";\n\nexport interface ReviewRubric {\n name: string;\n systemPrompt: string;\n resultSchema: z.ZodObject<z.ZodRawShape>;\n maxSteps: number;\n dimensions: string[];\n}\n\nconst dimensionResultSchema = z.object({\n pass: z.boolean(),\n evidence: z.string().describe(\"What you checked and found — cite file paths, line content, or specific strings\"),\n suggestion: z.string().optional().describe(\"What the planner agent should fix, if failing\"),\n});\n\nexport type DimensionResult = z.infer<typeof dimensionResultSchema>;\n\n// --- RUBRIC 1: Structural & Intent ---\n\nexport const structuralIntentRubric: ReviewRubric = {\n name: \"structural-intent\",\n maxSteps: 8,\n dimensions: [\"structuralValidity\", \"intentQuality\", \"missionAlignment\"],\n resultSchema: z.object({\n structuralValidity: dimensionResultSchema.describe(\n \"Are all step verbs valid (click/type/scroll/assert/hover/drag/read/refresh)? Are asserts visual-only (no URLs, network, console)? No code selectors? No login steps?\",\n ),\n intentQuality: dimensionResultSchema.describe(\n \"Is the intent a specific, falsifiable behavioral claim — not just 'verify X is visible'?\",\n ),\n missionAlignment: dimensionResultSchema.describe(\n \"Does the test's intent + steps verify the feature's core purpose? Not just UI appearance.\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a structural reviewer for E2E test plans. Each test will be executed by a VISUAL agent that sees the screen like a human user — it cannot inspect code, network, URLs, or any non-visual state.\n\nYour job is to EVALUATE tests against a rubric, NOT to rewrite them. You have tools to read source code if needed.\n\n## Rubric dimensions\n\n### 1. Structural validity\n- All step verbs must be one of: click, type, scroll, assert, hover, drag, read, refresh\n- assert: can ONLY verify what a human sees on screen (no URLs, network, console, localStorage)\n- No code selectors (data-testid, aria-label, CSS classes, HTML element types)\n- No login/authentication instructions — user is always already authenticated\n- No internal/meta steps like \"(Internal: simulate X)\" or \"(Note: this assumes Y)\"\n- No \"or\" in assertions — test data is deterministic\n- Assertions must reference specific visible text, not vague descriptions (\"success indicator\", \"results are displayed\")\n\n### 2. Intent quality\nIs the intent a specific, falsifiable behavioral claim?\nFAIL: \"When a user clicks the clock icon, the Wait modal should open\" (just UI mechanics)\nPASS: \"Adding a 5-second wait step should insert a Wait action into the step list with the configured duration\"\n\n### 3. Mission alignment\nDoes the test's intent + steps actually verify the feature's core purpose?\nFAIL if the intent just describes UI appearance when the feature is about functionality.\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\n// --- RUBRIC 2: Flow & Completeness ---\n\nexport const flowCompletenessRubric: ReviewRubric = {\n name: \"flow-completeness\",\n maxSteps: 12,\n dimensions: [\"actionCompletion\", \"mutationVerification\"],\n resultSchema: z.object({\n actionCompletion: dimensionResultSchema.describe(\n \"Does the test complete a core action and reach an OUTCOME? Not just opening a modal or clicking a tab.\",\n ),\n mutationVerification: dimensionResultSchema.describe(\n \"Does the test verify its mutation at the source of truth — not just a toast or inline indicator?\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a flow completeness reviewer for E2E test plans. Each test will be executed by a VISUAL agent that sees the screen like a human user.\n\nYour job is to EVALUATE whether the test completes a meaningful action and verifies the result properly. You have tools to read the project's source code to understand what the feature actually does.\n\n## Rubric dimensions\n\n### 1. Action completion\nDoes the test complete a core action and reach an OUTCOME?\nFAIL if the last meaningful step is just opening a modal, clicking a tab, or viewing a page.\nPASS if the test creates, saves, deletes, configures, or otherwise produces a verifiable result.\n\nRead the source files to understand what the feature's complete workflow looks like. Does the test cover the full cycle?\n\n### 2. Mutation verification\nDoes the test verify its mutation at the source of truth?\nFAIL if the test ends at the point of action — checking a toast, a modal closing, or an inline success indicator.\nPASS if the test navigates to where the mutation's effect should be visible and asserts it there.\n\nFor example: after creating a record, does the test navigate back to the list and verify the record appears? After toggling a setting, does it refresh and verify the toggle persists?\n\nRead the source code to understand where the \"source of truth\" view is for each mutation.\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\n// --- RUBRIC 3: UI Text Authenticity ---\n\nexport const uiTextRubric: ReviewRubric = {\n name: \"ui-text\",\n maxSteps: 20,\n dimensions: [\"uiTextAuthenticity\"],\n resultSchema: z.object({\n uiTextAuthenticity: dimensionResultSchema.describe(\n \"Do all quoted strings in steps reference text a human would actually see on screen? Not translation keys, config paths, component names, enum identifiers, or CSS classes.\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a UI text authenticity reviewer for E2E test plans. Your ONLY job is verifying that every piece of quoted text in the test steps matches what a human user would actually see on screen.\n\nYou have tools to read source code. USE THEM AGGRESSIVELY. Do not guess — verify.\n\n## Your process for EVERY quoted string in the test:\n\n1. Grep for the exact string in the project source code\n2. Check WHERE it appears:\n - If it appears as rendered text in the template/markup → PASS (it's real visible text)\n - If it appears inside a translation/i18n function call → it's a TRANSLATION KEY, not visible text. FAIL.\n - If it looks like a code identifier (camelCase, dot.notation, SCREAMING_CASE, PascalCase names) → FAIL\n3. If the string is a translation key, trace it to the actual rendered value:\n - Find the translation/i18n file or dictionary\n - Look up the key to find what text actually appears on screen\n - Report both the key used and the correct visible text in your evidence\n\n## Common patterns to catch:\n- Translation keys used as labels: \"aiBackoffice.tabPipeline\" instead of \"Pipeline\"\n- Dot-notation config paths: \"settings.general.title\"\n- **Icon component names used as button descriptions**: if a quoted string in a test step refers to a button or clickable element, grep for that string in the source code. If it's imported as a component and renders an icon (SVG, image), it's a code identifier — NOT what the user sees. The test must describe the icon visually instead. To verify: find the icon's source file or infer from its name what it depicts, and check whether the test uses a visual description or the code name.\n- Enum values: \"QUOTE_REQUEST_RECEIVED\", \"IN_REVIEW\"\n- CSS class names or HTML attributes used as visible text\n\n## Important:\n- Check EVERY quoted string, not just suspicious ones\n- A string existing in source code is NOT enough — it must be the RENDERED text\n- When in doubt, read more files. You have 20 steps — use them all if needed.\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\n// --- RUBRIC 4: Data Accuracy ---\n\nexport const dataAccuracyRubric: ReviewRubric = {\n name: \"data-accuracy\",\n maxSteps: 20,\n dimensions: [\"dataAccuracy\"],\n resultSchema: z.object({\n dataAccuracy: dimensionResultSchema.describe(\n \"Do the referenced UI elements (buttons, labels, fields, headings, toasts) actually exist in the source code for this page? Are default states correct? Does all test data (names, values, entities) come from the scenario data — NOT from other tests?\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a data accuracy reviewer for E2E test plans. Your ONLY job is verifying that every UI element referenced in the test actually exists in the source code and behaves as the test expects.\n\nYou have tools to read source code. USE THEM AGGRESSIVELY. Do not guess — verify.\n\n## Your process:\n\n### 1. Identify the page/component\nRead the test's starting page and find the corresponding source file. Read it.\n\n### 2. For each UI element referenced in the test:\n- **Buttons**: grep for the button label. Verify it exists as a rendered string (not just a variable name).\n- **Tab names**: find the tab component, read the tab definitions, verify the names match.\n- **Field labels**: find the form component, verify field labels match.\n- **Headings**: verify section/modal headings exist in the JSX.\n- **Toast messages**: find where toasts are triggered, verify the message text.\n- **Dropdown options**: find the select/dropdown component, verify the options.\n\n### 3. Check default states:\n- Toggle/switch default positions (is it on or off by default?)\n- Default selected tabs (which tab is active on load?)\n- Default form values (what are the initial values?)\n- Conditional rendering (does the element actually show given the default state?)\n\n### 4. Check preconditions and scenario data grounding:\n- Does the test assume data exists that might not be seeded? (e.g., \"click on the first item\" when the list might be empty)\n- CRITICAL: If the prompt includes scenario data, every data value the test references (entity names, folder names, app names, URLs, email addresses, etc.) MUST appear in that scenario data. If the test uses a value that only exists because another test created it, that is a FAIL — tests must be independent.\n- Cross-reference every specific name/value in the test steps against the scenario data provided.\n\n## Important:\n- READ the actual component source files — don't just grep for strings\n- Check conditional rendering — an element might exist in code but only show under certain conditions\n- Verify the FLOW makes sense — after a page refresh, what state resets?\n- Tests MUST be independent — they cannot depend on data created by other tests\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\nexport const ALL_RUBRICS: ReviewRubric[] = [\n structuralIntentRubric,\n flowCompletenessRubric,\n uiTextRubric,\n dataAccuracyRubric,\n];\n","import { basename } from \"node:path\";\nimport { type LanguageModel } from \"ai\";\nimport { tool } from \"ai\";\nimport { runAgent, buildDefaultStepLogger } from \"../../core/agent\";\nimport { buildReadFileTool, buildGrepTool, buildGlobTool, buildBashTool } from \"../../tools\";\nimport type { ReviewRubric, DimensionResult } from \"./rubrics\";\n\nexport async function runReviewPass(\n testContent: string,\n testPath: string,\n rubric: ReviewRubric,\n projectRoot: string,\n model: LanguageModel,\n scenarioData?: string,\n): Promise<Record<string, DimensionResult> | null> {\n let result: Record<string, DimensionResult> | undefined;\n\n const agentLabel = `review:${rubric.name}:${basename(testPath)}`;\n const { onStepFinish } = buildDefaultStepLogger(agentLabel, rubric.maxSteps);\n\n const finishTool = tool({\n description: \"Submit your structured review. Every dimension must have evidence from your investigation.\",\n inputSchema: rubric.resultSchema,\n execute: async (input) => {\n result = input as Record<string, DimensionResult>;\n },\n });\n\n const agentConfig = {\n id: agentLabel,\n systemPrompt: rubric.systemPrompt,\n model,\n maxSteps: rubric.maxSteps,\n tools: (_heartbeat: () => void) => ({\n read_file: buildReadFileTool(projectRoot),\n grep: buildGrepTool(projectRoot),\n glob: buildGlobTool(projectRoot),\n bash: buildBashTool(projectRoot),\n finish: finishTool,\n }),\n onStepFinish,\n };\n\n const scenarioContext = scenarioData && rubric.name === \"data-accuracy\"\n ? `\\n## Scenario data (the ONLY test data that exists in the database)\\n\\`\\`\\`\\n${scenarioData}\\n\\`\\`\\`\\n\\nIMPORTANT: Every piece of data the test references (names, titles, URLs, folder names, etc.) MUST exist in the scenario data above. If the test uses a value that doesn't appear in scenarios, it FAILS the dataAccuracy dimension.\\n`\n : \"\";\n\n const prompt = `Review this E2E test plan:\n\n## Test file: ${testPath}\n\\`\\`\\`\n${testContent}\n\\`\\`\\`\n${scenarioContext}\nEvaluate EVERY dimension in your rubric: ${rubric.dimensions.join(\", \")}\n\nFor each one:\n1. Investigate using your tools (read source files, grep for strings referenced in the test)\n2. Provide specific evidence of what you found\n3. Pass or fail with a clear reason\n\nWhen done, call finish with your structured evaluation.`;\n\n await runAgent(agentConfig, prompt, () => result);\n return result ?? null;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative, basename } from \"node:path\";\nimport { glob } from \"glob\";\nimport { type LanguageModel } from \"ai\";\nimport { createStepLogger } from \"../../core/display\";\nimport { ALL_RUBRICS, type DimensionResult } from \"./rubrics\";\nimport { runReviewPass } from \"./review-pass\";\n\nconst MAX_CONCURRENT_TESTS = 4;\n\nexport type ReviewResult = Record<string, DimensionResult>;\n\nexport interface TestReviewFeedback {\n testPath: string;\n relativePath: string;\n content: string;\n flow: string;\n passed: boolean;\n dimensions: ReviewResult;\n failedDimensions: string[];\n}\n\nasync function reviewSingleTest(\n testContent: string,\n testPath: string,\n projectRoot: string,\n model: LanguageModel,\n scenarioData?: string,\n): Promise<ReviewResult> {\n const passes = await Promise.all(\n ALL_RUBRICS.map((rubric) =>\n runReviewPass(testContent, testPath, rubric, projectRoot, model, scenarioData).catch((err) => {\n console.warn(` [review] ${rubric.name} error on ${basename(testPath)}: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }),\n ),\n );\n\n const merged: ReviewResult = {};\n for (let i = 0; i < ALL_RUBRICS.length; i++) {\n const rubric = ALL_RUBRICS[i]!;\n const passResult = passes[i];\n for (const dim of rubric.dimensions) {\n if (passResult && dim in passResult) {\n merged[dim] = passResult[dim]!;\n } else {\n merged[dim] = { pass: true, evidence: \"Rubric pass did not return result — fail-open\" };\n }\n }\n }\n\n return merged;\n}\n\nexport async function runConsolidatedReview(\n outputDir: string,\n projectRoot: string,\n model: LanguageModel,\n): Promise<{ passed: number; failed: number; feedback: TestReviewFeedback[] }> {\n const testsDir = join(outputDir, \"qa-tests\");\n const logger = createStepLogger(\"review\", 5);\n\n let scenarioData: string | undefined;\n try {\n scenarioData = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch { /* scenarios not available */ }\n\n const testFiles = await glob(join(testsDir, \"**/*.md\"));\n const tests: { path: string; relativePath: string; content: string; flow: string }[] = [];\n for (const testPath of testFiles) {\n if (basename(testPath) === \"INDEX.md\") continue;\n if (testPath.includes(\"/_invalid/\")) continue;\n const content = await readFile(testPath, \"utf-8\");\n const flowMatch = content.match(/^---\\n[\\s\\S]*?flow:\\s*[\"']?([^\"'\\n]+)[\"']?\\s*\\n[\\s\\S]*?---/m);\n tests.push({\n path: testPath,\n relativePath: relative(testsDir, testPath),\n content,\n flow: flowMatch?.[1]?.trim() ?? \"unknown\",\n });\n }\n\n const totalAgents = tests.length * ALL_RUBRICS.length;\n logger.log({\n stepNumber: 1,\n maxSteps: 2,\n text: `Reviewing ${tests.length} tests × ${ALL_RUBRICS.length} rubrics = ${totalAgents} agents (${MAX_CONCURRENT_TESTS} tests concurrent)`,\n toolCalls: [],\n toolErrors: [],\n writtenFiles: [],\n });\n\n let passed = 0;\n let failed = 0;\n const feedback: TestReviewFeedback[] = [];\n\n for (let i = 0; i < tests.length; i += MAX_CONCURRENT_TESTS) {\n const batch = tests.slice(i, i + MAX_CONCURRENT_TESTS);\n const results = await Promise.all(\n batch.map(async (test) => {\n const result = await reviewSingleTest(test.content, test.relativePath, projectRoot, model, scenarioData);\n return { test, result };\n }),\n );\n\n for (const { test, result } of results) {\n const failedDimensions: string[] = [];\n for (const [key, dim] of Object.entries(result)) {\n if (!dim.pass) failedDimensions.push(key);\n }\n\n if (failedDimensions.length === 0) {\n passed++;\n } else {\n failed++;\n feedback.push({\n testPath: test.path,\n relativePath: test.relativePath,\n content: test.content,\n flow: test.flow,\n passed: false,\n dimensions: result,\n failedDimensions,\n });\n }\n }\n\n console.log(\n ` [review] Progress: ${Math.min(i + MAX_CONCURRENT_TESTS, tests.length)}/${tests.length} reviewed, ${passed} passed, ${failed} failed`,\n );\n }\n\n logger.log({\n stepNumber: 2,\n maxSteps: 2,\n text: `Review complete: ${passed} passed, ${failed} failed`,\n toolCalls: [],\n toolErrors: [],\n writtenFiles: [],\n });\n\n logger.summary();\n return { passed, failed, feedback };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface FeatureNode {\n id: string;\n name: string;\n routePath?: string;\n sourceFiles: string[];\n parentId: string | null;\n depth: number;\n status: \"queued\" | \"exploring\" | \"tested\" | \"skipped\";\n}\n\nexport interface SerializedCoverageState {\n nodes: Record<string, FeatureNode>;\n queue: string[];\n currentNode: string | null;\n testsWritten: Record<string, string[]>;\n}\n\nexport class CoverageState {\n nodes: Map<string, FeatureNode> = new Map();\n queue: string[] = [];\n testsWritten: Map<string, string[]> = new Map();\n currentNode: string | null = null;\n\n enqueue(node: FeatureNode): boolean {\n if (this.nodes.has(node.id)) return false;\n this.nodes.set(node.id, node);\n this.queue.push(node.id);\n return true;\n }\n\n nextNode(): { node: FeatureNode; remaining: number } | null {\n if (this.currentNode) {\n const current = this.nodes.get(this.currentNode);\n if (current && current.status !== \"tested\") {\n current.status = \"skipped\";\n }\n }\n\n while (this.queue.length > 0) {\n const id = this.queue.shift()!;\n const node = this.nodes.get(id);\n if (!node || node.status === \"tested\" || node.status === \"skipped\")\n continue;\n\n node.status = \"exploring\";\n this.currentNode = id;\n return { node, remaining: this.queue.length };\n }\n\n this.currentNode = null;\n return null;\n }\n\n markTested(nodeId: string, testPaths: string[]): void {\n const node = this.nodes.get(nodeId);\n if (node) node.status = \"tested\";\n this.currentNode = null;\n const existing = this.testsWritten.get(nodeId) ?? [];\n this.testsWritten.set(nodeId, [...existing, ...testPaths]);\n }\n\n allTestPaths(): string[] {\n const paths: string[] = [];\n for (const tests of this.testsWritten.values()) {\n paths.push(...tests);\n }\n return paths;\n }\n\n summary(): {\n totalNodes: number;\n tested: number;\n skipped: number;\n queued: number;\n totalTests: number;\n } {\n let tested = 0,\n skipped = 0,\n queued = 0;\n for (const node of this.nodes.values()) {\n if (node.status === \"tested\") tested++;\n else if (node.status === \"skipped\") skipped++;\n else queued++;\n }\n return {\n totalNodes: this.nodes.size,\n tested,\n skipped,\n queued,\n totalTests: this.allTestPaths().length,\n };\n }\n\n serialize(): SerializedCoverageState {\n return {\n nodes: Object.fromEntries(this.nodes),\n queue: [...this.queue],\n currentNode: this.currentNode,\n testsWritten: Object.fromEntries(this.testsWritten),\n };\n }\n\n static deserialize(data: SerializedCoverageState): CoverageState {\n const state = new CoverageState();\n state.nodes = new Map(Object.entries(data.nodes));\n state.queue = data.queue;\n state.currentNode = data.currentNode ?? null;\n state.testsWritten = new Map(Object.entries(data.testsWritten));\n return state;\n }\n}\n\nconst STATE_FILE = \".bfs-state.json\";\n\nexport async function saveBfsState(\n outputDir: string,\n state: CoverageState,\n): Promise<void> {\n const path = join(outputDir, STATE_FILE);\n await writeFile(path, JSON.stringify(state.serialize(), null, 2), \"utf-8\");\n}\n\nexport async function loadBfsState(\n outputDir: string,\n): Promise<CoverageState | null> {\n const path = join(outputDir, STATE_FILE);\n try {\n const raw = await readFile(path, \"utf-8\");\n return CoverageState.deserialize(JSON.parse(raw));\n } catch {\n return null;\n }\n}\n","import { type AgentResult, buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { tool } from \"ai\";\n\nconst FEATURES_FILE = \"features.json\";\n\nconst Feature = z.object({\n name: z.string().min(1).describe(\"Human-readable name (e.g. 'Settings > Notifications Tab', 'Create Project Modal')\"),\n type: z.enum([\"tab\", \"modal\", \"form\", \"table\", \"wizard\", \"nested-route\", \"complex-component\"]),\n parentPagePath: z.string().min(1).describe(\"The page path this feature belongs to (from the pages list)\"),\n sourceFiles: z.array(z.string()).min(1).describe(\"Relative paths to the source files for this sub-feature\"),\n interactiveElements: z.number().int().min(0).describe(\"Count of interactive elements found (buttons, inputs, toggles, etc.)\"),\n description: z.string().min(10).describe(\"What this sub-feature does\"),\n});\nexport type DiscoveredFeature = z.infer<typeof Feature> & { id: string };\n\nclass FeatureCollector {\n readonly features = new Map<string, DiscoveredFeature>();\n\n addFeature(id: string, feature: z.infer<typeof Feature>): void {\n if (this.features.has(id)) {\n console.warn(`feature ${id} already exists, overwriting`);\n }\n this.features.set(id, { ...feature, id });\n }\n\n viewFeatures(): string {\n if (this.features.size === 0) return \"No features discovered yet.\";\n const grouped = new Map<string, DiscoveredFeature[]>();\n for (const f of this.features.values()) {\n const existing = grouped.get(f.parentPagePath) ?? [];\n existing.push(f);\n grouped.set(f.parentPagePath, existing);\n }\n const lines: string[] = [];\n for (const [page, features] of grouped) {\n lines.push(`\\n${page}:`);\n for (const f of features) {\n lines.push(` - [${f.type}] ${f.name} (${f.interactiveElements} elements, ${f.sourceFiles.length} files)`);\n }\n }\n return lines.join(\"\\n\");\n }\n}\n\nexport interface FeatureDiscoveryInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n pages: Map<string, { route: string; path: string; description: string }>;\n nonInteractive?: boolean;\n}\n\nexport async function saveFeatures(outputDir: string, features: Map<string, DiscoveredFeature>): Promise<void> {\n const obj = Object.fromEntries(features);\n await writeFile(join(outputDir, FEATURES_FILE), JSON.stringify(obj, null, 2), \"utf-8\");\n}\n\nexport async function loadFeatures(outputDir: string): Promise<Map<string, DiscoveredFeature> | null> {\n try {\n const raw = await readFile(join(outputDir, FEATURES_FILE), \"utf-8\");\n const obj = JSON.parse(raw);\n return new Map(Object.entries(obj));\n } catch {\n return null;\n }\n}\n\nconst SYSTEM_PROMPT = `You are a feature discovery agent. Your job is to explore each page's source code and discover all sub-features that deserve their own test coverage.\n\nYou will be given a list of pages. For each page, you must:\n1. Read the page's source file\n2. Follow imports — use grep and glob to find all related components, utilities, hooks\n3. For each sub-feature you find, call add_feature\n\n## What counts as a sub-feature\n- **Tabs** that render different content (each tab = separate feature)\n- **Modals/dialogs** with their own form or workflow\n- **CRUD forms** (create entity, edit entity — each is a separate feature)\n- **Tables** with row-level actions (edit, delete, status change per row)\n- **Multi-step wizards** or flows\n- **Nested routes** that render distinct views within the page\n- **Complex components** with significant interactive elements (3+ buttons/inputs/toggles)\n\n## What does NOT count\n- Pure display components (headers, footers, breadcrumbs, loading spinners)\n- Shared UI primitives used across the app (generic Button, Input, Dropdown components)\n- Error/loading/empty states\n- Simple navigation elements (links, back buttons)\n\n## How to count interactive elements\nFor each sub-feature, count: buttons, text inputs, toggles/switches, checkboxes, radio buttons, dropdowns/selects, sliders, drag handles, date pickers, file uploads, rich text editors, search fields, table row actions.\n\n## Process\n1. Call view_pages to see all pages\n2. For each page:\n a. Read the page's source file\n b. Find all imports and trace them to their source files\n c. Identify sub-features by looking for: tab components, modal/dialog components, form components, table components with actions, stepper/wizard components\n d. For each sub-feature, read its source files and count interactive elements\n e. Call add_feature for each sub-feature found\n3. After processing all pages, call view_features to review your work\n4. Call finish\n\n## ID format\nUse kebab-case IDs that indicate the parent page and feature type:\n- \"settings-notifications-tab\"\n- \"projects-create-modal\"\n- \"users-table-actions\"\n- \"onboarding-step-2-form\"\n\n## Important\n- Explore the ACTUAL source code. Do not guess what sub-features exist.\n- If a page is simple (just displays content, no interactive sub-features), skip it — not every page needs sub-features.\n- Focus on features that would need DIFFERENT tests, not variations of the same thing.\n- Use spawn_researcher or subagent for pages with many files to avoid context bloat.`;\n\nexport async function runFeatureDiscovery(input: FeatureDiscoveryInput): Promise<Map<string, DiscoveredFeature>> {\n const model = getModel(input.modelId);\n const collector = new FeatureCollector();\n\n let result: AgentResult | undefined;\n const { logger, onStepFinish } = buildDefaultStepLogger(\"feature-discovery\", 300);\n\n const pagesDescription = Array.from(input.pages.entries())\n .map(([path, page]) => `- ${page.route} → ${path}\\n ${page.description}`)\n .join(\"\\n\");\n\n const prompt = `Discover sub-features for all pages in this project.\n\nProject root: ${input.projectRoot}\n\n## Pages to analyze\n${pagesDescription}\n\nProcess every page. Call add_feature for each sub-feature you discover. When done, call finish.`;\n\n const agentConfig = {\n id: \"feature-discovery\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 300,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n add_feature: tool({\n description: \"Add a discovered sub-feature\",\n inputSchema: Feature.extend({\n id: z.string().min(1).describe(\"Unique kebab-case ID (e.g. 'settings-notifications-tab')\"),\n }),\n execute: (featureInput) => {\n const { id, ...rest } = featureInput;\n const parsed = Feature.safeParse(rest);\n if (!parsed.success) {\n return `Invalid feature: ${parsed.error.issues.map(i => i.message).join(\", \")}`;\n }\n collector.addFeature(id, parsed.data);\n return `Feature \"${id}\" added (${collector.features.size} total)`;\n },\n }),\n view_features: tool({\n description: \"View all discovered features so far\",\n inputSchema: z.object({}),\n execute: () => collector.viewFeatures(),\n }),\n view_pages: tool({\n description: \"View the pages list to know what to analyze\",\n inputSchema: z.object({}),\n execute: () => pagesDescription,\n }),\n finish: tool({\n description: \"Signal that feature discovery is complete\",\n inputSchema: z.object({ summary: z.string() }),\n execute: async (finishInput) => {\n result = {\n success: true,\n artifacts: [...collector.features.keys()],\n summary: finishInput.summary,\n };\n await saveFeatures(input.outputDir, collector.features);\n return { done: true, featureCount: collector.features.size };\n },\n }),\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n if (collector.features.size > 0 && !result) {\n await saveFeatures(input.outputDir, collector.features);\n }\n\n return collector.features;\n}\n","import matter from \"gray-matter\";\n\nexport const VALID_VERBS = new Set([\n \"click\",\n \"type\",\n \"scroll\",\n \"assert\",\n \"hover\",\n \"drag\",\n \"read\",\n \"refresh\",\n]);\n\ninterface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport function validateTestContent(content: string): ValidationResult {\n const errors: string[] = [];\n\n if (!/^---\\n[\\s\\S]*?\\n---/.test(content)) {\n errors.push(\"Missing frontmatter\");\n } else {\n try {\n const { data } = matter(content);\n if (!data.verification || typeof data.verification !== \"string\" || data.verification.length < 20) {\n errors.push(\"Missing or insufficient 'verification' field in frontmatter — must describe WHERE to navigate and WHAT to assert at the source of truth\");\n }\n } catch {\n errors.push(\"Failed to parse frontmatter\");\n }\n }\n\n if (!/\\*\\*Intent\\*\\*:/.test(content)) {\n errors.push(\"Missing **Intent**: section\");\n }\n\n const stepMatches =\n content.match(\n /^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm,\n ) || [];\n const interactions = stepMatches.filter((s) =>\n /^\\d+\\.\\s+(click|type|drag):/.test(s),\n );\n if (interactions.length < 2) {\n errors.push(`Only ${interactions.length} interaction(s) (minimum 2)`);\n }\n\n const allSteps = content.match(/^\\d+\\.\\s+(\\w+):/gm) || [];\n for (const step of allSteps) {\n const verbMatch = step.match(/^\\d+\\.\\s+(\\w+):/);\n if (verbMatch && !VALID_VERBS.has(verbMatch[1]!)) {\n errors.push(`Invalid verb: \"${verbMatch[1]}\"`);\n }\n }\n\n\n const bodyStart = content.indexOf(\"---\", 3);\n const body = bodyStart > -1 ? content.slice(bodyStart + 3) : content;\n const stepsSection = body.slice(body.indexOf(\"**Steps**\") || 0);\n if (/Dynamic:\\s/i.test(stepsSection)) {\n errors.push('Contains \"Dynamic:\" placeholder in steps');\n }\n\n return { valid: errors.length === 0, errors };\n}\n","import {mkdir, writeFile} from \"node:fs/promises\";\nimport {dirname, join} from \"node:path\";\nimport {hasToolCall, type LanguageModel, stepCountIs, tool, ToolLoopAgent,} from \"ai\";\nimport matter from \"gray-matter\";\nimport {z} from \"zod\";\nimport {buildBashTool, buildGlobTool, buildGrepTool, buildReadFileTool} from \"../../tools\";\nimport {type CoverageState, saveBfsState,} from \"./graph\";\nimport {VALID_VERBS} from \"./validation\";\n\nconst testFrontmatterSchema = z.object({\n title: z.string().min(1),\n description: z.string().min(1),\n intent: z.string().min(30, \"Intent must be at least 30 characters — describe the BEHAVIOR being tested, not the steps\"),\n criticality: z.enum([\"critical\", \"high\", \"mid\", \"low\"]),\n scenario: z.string().min(1),\n flow: z.string().min(1),\n verification: z.string().min(20, \"Verification must describe WHERE to navigate and WHAT to assert at the source of truth — not UI acknowledgments like toasts\"),\n});\n\nexport function buildWriteTestTool(\n state: CoverageState,\n outputDir: string,\n) {\n return tool({\n description:\n \"Write a test file to qa-tests/{folder}/{filename}.md. \" +\n \"Validates frontmatter before writing. Returns error if frontmatter is invalid.\",\n inputSchema: z.object({\n folder: z.string().describe(\"Subfolder name under qa-tests/\"),\n filename: z.string().describe(\"File name (e.g. login-valid-credentials.md)\"),\n content: z.string().describe(\"Full file content including YAML frontmatter\"),\n nodeId: z.string().describe(\"The FeatureNode ID this test belongs to\"),\n }),\n execute: async (input) => {\n const frontmatter = extractFrontmatter(input.content);\n if (!frontmatter) {\n return { error: \"File must start with YAML frontmatter (--- delimiters)\" };\n }\n\n const parsed = testFrontmatterSchema.safeParse(frontmatter);\n if (!parsed.success) {\n return {\n error: `Invalid frontmatter: ${parsed.error.issues.map((i) => i.message).join(\", \")}`,\n };\n }\n\n if (!/\\*\\*Intent\\*\\*:/.test(input.content)) {\n return { error: \"Test must include an **Intent**: section between Setup and Steps describing what behavior is being tested\" };\n }\n\n const allSteps = input.content.match(/^\\d+\\.\\s+(\\w+):/gm) || [];\n for (const step of allSteps) {\n const verbMatch = step.match(/^\\d+\\.\\s+(\\w+):/);\n if (verbMatch && !VALID_VERBS.has(verbMatch[1]!)) {\n return {\n error: `Invalid step verb \"${verbMatch[1]}\". Only valid verbs are: ${[...VALID_VERBS].join(\", \")}`,\n };\n }\n }\n\n const stepMatches = input.content.match(/^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm) || [];\n const interactions = stepMatches.filter(s => /^\\d+\\.\\s+(click|type|drag):/.test(s));\n if (interactions.length < 2) {\n return {\n error: `Test has ${interactions.length} interaction(s) (click/type/drag). Minimum is 2. ` +\n `Visibility-only tests are not allowed — what BEHAVIOR does this test verify?`,\n };\n }\n\n const bodyStart = input.content.indexOf(\"---\", 3);\n const body = bodyStart > -1 ? input.content.slice(bodyStart + 3) : input.content;\n const stepsSection = body.slice(body.indexOf(\"**Steps**\") || 0);\n\n const placeholderPatterns = [\n { pattern: /Dynamic:\\s/gi, name: '\"Dynamic:\" placeholder' },\n { pattern: /(?<!\\{)\\{[a-z][a-zA-Z]*\\}(?!\\})/g, name: \"bare {variable}\" },\n { pattern: /\\(e\\.g\\./gi, name: '\"(e.g.\" example' },\n { pattern: /(?:^|\\s)e\\.g\\.,?\\s/gim, name: '\"e.g.\" example' },\n ];\n\n for (const { pattern, name } of placeholderPatterns) {\n const matches = stepsSection.match(pattern);\n if (matches && matches.length > 0) {\n return {\n error: `Test steps contain ${name}: \"${matches[0]}\". ` +\n `Use EXACT values from scenarios.md — not placeholders or examples.`,\n };\n }\n }\n\n const relPath = join(\"qa-tests\", input.folder, input.filename);\n const absPath = join(outputDir, relPath);\n\n try {\n await mkdir(dirname(absPath), { recursive: true });\n await writeFile(absPath, input.content, \"utf-8\");\n state.markTested(input.nodeId, [relPath]);\n await saveBfsState(outputDir, state);\n return { path: relPath, title: parsed.data.title };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to write test: ${message}` };\n }\n },\n });\n}\n\nexport function buildCreateFolderTool(outputDir: string) {\n return tool({\n description: \"Create a folder under qa-tests/ for organizing tests.\",\n inputSchema: z.object({\n folder: z.string().describe(\"Folder name (kebab-case)\"),\n }),\n execute: async (input) => {\n const absPath = join(outputDir, \"qa-tests\", input.folder);\n try {\n await mkdir(absPath, { recursive: true });\n return { path: join(\"qa-tests\", input.folder) };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to create folder: ${message}` };\n }\n },\n });\n}\n\nexport function buildNextNodeTool(state: CoverageState, outputDir: string) {\n return tool({\n description:\n \"Get the next node to write tests for. If you called next_node before \" +\n \"without writing any tests (via write_test), the previous node is auto-skipped. \" +\n \"Returns done:true when all nodes are processed.\",\n inputSchema: z.object({}),\n execute: async () => {\n const next = state.nextNode();\n await saveBfsState(outputDir, state);\n if (!next) {\n const stats = state.summary();\n return {\n done: true,\n message: `All ${stats.totalNodes} nodes processed (${stats.tested} tested, ${stats.skipped} skipped, ${stats.totalTests} tests). Call finish.`,\n };\n }\n return {\n node: {\n id: next.node.id,\n name: next.node.name,\n routePath: next.node.routePath,\n sourceFiles: next.node.sourceFiles,\n parentId: next.node.parentId,\n depth: next.node.depth,\n },\n remaining: next.remaining,\n instruction: `Explore \"${next.node.name}\": read its source files, find all interactive elements, then write tests with write_test. If no tests are needed after reading the source (e.g. utility route, redirect), call next_node to skip.`,\n };\n },\n });\n}\n\nexport function buildGetProgressTool(state: CoverageState) {\n return tool({\n description: \"Check how many nodes have been tested vs how many remain.\",\n inputSchema: z.object({}),\n execute: async () => {\n const stats = state.summary();\n const nodes = [...state.nodes.values()].map((n) => ({\n id: n.id,\n name: n.name,\n status: n.status,\n testCount: state.testsWritten.get(n.id)?.length ?? 0,\n }));\n return { ...stats, nodes };\n },\n });\n}\n\nexport function buildSpawnResearcherTool(\n model: LanguageModel,\n workingDirectory: string,\n onHeartbeat?: () => void,\n) {\n return tool({\n description:\n \"Spawn a research subagent to read and analyze source files without polluting your context. \" +\n \"Use for complex sub-features where you don't want to read 20 files yourself.\",\n inputSchema: z.object({\n instruction: z.string().describe(\"What to research — be specific about files and what to look for\"),\n }),\n execute: async (input) => {\n const resultSchema = z.object({\n findings: z.string().describe(\"Summary of what was found\"),\n });\n\n let result: z.infer<typeof resultSchema> | undefined;\n\n const subagent = new ToolLoopAgent({\n model,\n instructions:\n \"You are a code researcher. Read the files specified in your instruction, \" +\n \"analyze them, and call finish with a summary of what you found. \" +\n \"Focus on: UI elements, forms, buttons, navigation, API calls, state management.\",\n tools: {\n bash: buildBashTool(workingDirectory),\n glob: buildGlobTool(workingDirectory),\n grep: buildGrepTool(workingDirectory),\n read_file: buildReadFileTool(workingDirectory),\n finish: tool({\n description: \"Report your findings.\",\n inputSchema: resultSchema,\n execute: async (output) => { result = output; },\n }),\n },\n stopWhen: [stepCountIs(15), hasToolCall(\"finish\")],\n onStepFinish: () => { onHeartbeat?.(); },\n });\n\n try {\n await subagent.generate({\n messages: [{ role: \"user\", content: input.instruction }],\n });\n return { findings: result?.findings ?? \"Subagent did not produce findings\" };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { findings: `Research error: ${message}` };\n }\n },\n });\n}\n\nfunction extractFrontmatter(content: string): Record<string, unknown> | null {\n try {\n const { data } = matter(content);\n return data && Object.keys(data).length > 0 ? data : null;\n } catch {\n return null;\n }\n}\n","export const SYSTEM_PROMPT = `You are an E2E test generator that explores a frontend codebase as a BFS graph. You are ONE long-running agent that maintains all state about what's been explored and what hasn't.\n\n## Your process\n\n1. Call next_node to get the first node from the queue\n2. Read its source files, explore related components, write tests with write_test\n3. Call next_node again to get the next node\n4. Repeat until next_node returns done, then call finish\n\nIf a node has no testable behavior (utility, redirect), call next_node to skip it — it's auto-marked as skipped.\n\n## Tools you have\n\n### Exploration\n- read_file: Read source files to understand features\n- glob: Find files by pattern\n- grep: Search file contents\n- bash: Run shell commands (git, ls, find)\n\n### Queue management\n- next_node: Get the next node to test. Auto-skips previous node if no tests were written for it.\n- get_progress: Check how many nodes tested vs remaining\n\n### Writing\n- write_test: Write a test file with validated frontmatter\n- create_folder: Create a folder under qa-tests/\n\n### Research\n- spawn_researcher: Spawn a subagent to read/analyze files without polluting your context\n\n### Completion\n- finish: Signal you're done with a coverage report\n\n## Source code grounding (CRITICAL)\n\nBefore writing tests for any node, READ the source files for that page using read_file or spawn_researcher. Your tests MUST only reference elements you found in the actual source code.\n\nPay attention to:\n- **Conditional rendering**: elements inside conditionals are NOT always visible. Only assert them if your test steps trigger the condition first.\n- **Default states**: find where default values are set in the source code to know initial toggle/checkbox/dropdown states. If a toggle defaults to ON, clicking it turns it OFF, not ON. ALWAYS verify the initial state before writing interaction steps.\n- **Exact text**: use the actual string from the code, not paraphrased versions. If the button says \"New test\" in the source, don't write \"Create Test\".\n- **Icon buttons**: when you find a button that renders an icon with no text label, you MUST resolve what the icon looks like before writing the test. Find the icon's source file (SVG, image) and read it to see what it depicts, or infer from the icon's name/metadata in the library. Then describe the icon visually in the test step (e.g., \"three vertical dots icon button\", \"pencil icon button\", \"trash can icon button\"). NEVER use the icon's component or variable name (e.g., \"MoreVertical\", \"FaPencil\", \"IconTrash\") — these are code identifiers, not what the user sees on screen.\n- **Translated text**: if the source uses i18n/translation functions, trace the key to the actual rendered text. Never use translation keys as visible text.\n\nIf you can't find an element in the source, don't assert it. Read more files or skip it.\n\n## Feature Mission (CRITICAL)\n\nEach feature has a \"mission\" — the ONE thing it must do correctly. Your tests MUST verify the mission. Before writing tests for any node:\n\n1. Find the mission for this feature from the Feature Missions section below\n2. Ask: \"Does my planned test verify the mission, or just UI mechanics?\"\n3. At least ONE test per feature must directly assert the mission outcome\n4. Core features (core: true) also have a coreReason explaining the blast radius of failure — allocate more depth to these\n\nExample: If the mission is \"Show correct execution counts and success rates for the selected time range\":\n- BAD: assert: the \"Executions\" tab heading is visible (UI mechanics — proves nothing about data)\n- GOOD: assert: text \"12\" is visible in the executions count (verifies actual data from scenarios)\n\nIf you find yourself writing a test that only opens/closes UI elements without verifying the mission outcome, STOP and redesign the test.\n\n## BFS rules — EXPLORE DEEPLY, THEN WRITE THOROUGH TESTS\n\nFor each queued node, follow this process:\n\n### Step 1: Read source and catalog every interactive element\n1. The node has its page file path. Read it with read_file.\n2. Use glob, grep, and read_file to find ALL related source files — imports, shared components, utilities, sub-pages. Explore the codebase structure around this page to understand where the feature's code actually lives.\n3. Build a mental catalog of EVERY interactive element on the page:\n - Buttons (with exact text labels)\n - Input fields (with labels, placeholders, validation rules)\n - Toggles/checkboxes/switches (with default states)\n - Dropdowns/selects (with their options)\n - Forms (with all their fields)\n - Modals/dialogs (with their triggers and content)\n - Tables/lists (with row actions, sorting, filtering)\n - Tabs (with their labels and what they render)\n4. If you find sibling routes or related pages that are NOT already in the queue, enqueue them.\n\n### Step 2: Write tests that cover EVERY element\n5. Every button, input, toggle, and form field you cataloged MUST appear in at least one test. If you found 8 interactive elements and your tests only touch 3, you're missing coverage.\n6. A single test can (and should) interact with multiple elements — you don't need one test per element. A form test can fill all fields and submit.\n7. For each element type, apply these opinionated test patterns:\n\n**Input fields:**\n- Happy path: fill with valid data, submit, verify success\n- Validation: submit empty/required fields, verify error messages\n- Boundary: extremely long strings (can break rendering elsewhere), special characters, numbers in text fields\n- If the source has validation rules, write a test that triggers each validation error\n\n**Toggles/switches/checkboxes:**\n- Verify the default state matches the source code\n- Toggle and verify the state changed\n- Refresh the page and verify the state persisted\n- If multiple toggles exist in a section, test toggling each independently\n\n**Forms (create/edit/delete):**\n- Create: fill all fields, submit, verify the new item appears in the list WITHOUT refreshing\n- Edit: modify an existing item, save, verify the change is reflected\n- Delete: remove an item, verify it disappears, verify it stays gone after refresh\n- Partial submission: leave optional fields empty, verify it still works\n- Duplicate prevention: if the source has unique constraints, try creating a duplicate\n\n**Modals/dialogs:**\n- Open the modal, fill partially, close it, reopen it — is the state cleared or preserved? (check the source)\n- Complete the modal workflow end-to-end\n\n**Tables/lists:**\n- If there's search/filter: search for an item, verify filtering works\n- If there's pagination: verify it exists when there's enough data\n- If there are row actions (edit/delete buttons per row): test them\n\n**Behavioral variations (switch/map in source):**\n- If the source has a switch/map dispatching to different components per variant (e.g., different providers, different interaction types), write a test for EACH variant that renders differently. Read the source for each variant to get the correct element names — don't copy from another variant's test.\n\n### Step 3: Move to the next node\n8. After writing tests, call next_node to get the next node\n9. Use spawn_researcher for complex sub-features where reading 10+ files would clutter your context\n10. If a node has no clear page file (utility routes, redirects), call next_node to skip it\n11. NEVER write tests for error pages, 404s, or states that require navigating to invalid URLs.\n\n## Folder structure rules\n\nUse NESTED folders to mirror the app hierarchy. Use create_folder with \"/\" separators:\n- GOOD: create_folder \"settings/notifications\" → qa-tests/settings/notifications/\n- GOOD: create_folder \"settings/billing\" → qa-tests/settings/billing/\n- BAD: create_folder \"settings-notifications\" → qa-tests/settings-notifications/ (flat, no grouping)\n\nGroup related areas under parent folders.\n\n## Test file format\n\nEvery test file must start with YAML frontmatter:\n\n\\`\\`\\`yaml\n---\ntitle: \"Toggle recording stops active session\"\ndescription: \"Verify toggling recording OFF stops the session\"\nintent: \"When the recording toggle is ON (default), clicking it should stop recording and show a confirmation toast\"\ncriticality: critical\nscenario: standard\nflow: \"User Settings\"\nverification: \"Refresh the Settings page, assert the recording toggle is in the OFF position\"\n---\n\\`\\`\\`\n\n### Frontmatter rules\n- title: Short, descriptive test name\n- description: One sentence explaining what the test verifies\n- intent: A specific, falsifiable claim derived from the feature's MISSION — what the user does, what the feature produces, and why it matters. Focus on OUTCOMES, not UI mechanics.\n GOOD: \"Toggling recording from ON to OFF stops the active session and shows a confirmation toast\"\n BAD: \"Click the recording toggle\" (that's a step, not an intent)\n BAD: \"Verify the page displays correctly\" (visibility check, not a behavior)\n Derive from the mission: if the mission is \"Generate valid config files\", every test's intent must be about generating, previewing, or copying config — not about UI elements appearing.\n- criticality: One of: critical, high, mid, low\n- scenario: Which scenario this test uses (usually \"standard\")\n- flow: Which feature/flow this belongs to (must match a feature from AUTONOMA.md)\n- verification: (REQUIRED — write tool rejects without it) WHERE to navigate and WHAT to assert to prove the mutation worked. Every test performs a mutation — render-only tests should be folded into another test's flow. Must describe the source of truth, not a UI acknowledgment.\n GOOD: \"Navigate to the test list, assert 'Login Flow' is visible in the table\"\n GOOD: \"Refresh the page, assert the toggle retained its OFF state\"\n BAD: \"Assert toast 'Deleted' appears\" (UI acknowledgment, not verification)\n\n### Test body format\n\nAfter frontmatter:\n\n**Setup**: Which page the user starts on. Describe the clicks to reach the page. Read the app's layout/navigation code to determine the correct path. Look for sidebar, tab navigation, and route definitions. NEVER invent navigation paths — if you can't find how to reach a page, use spawn_researcher to investigate.\n\nNEVER write \"Login as...\" or \"Log in\" in Setup. The user is ALWAYS already authenticated. Setup only describes WHERE the user is, not authentication.\nNEVER write tests that require navigating to invalid URLs, 404 pages, or error states.\n\n**Intent**: A specific, falsifiable claim derived from the feature's MISSION. States what the user does, what should happen, and WHY it matters. Write this BEFORE writing steps — it's the \"north star\" that the execution agent uses to adapt if steps don't match reality.\n\nThe intent is NOT \"what UI appears\" — it's \"what the feature DOES\".\n\nInclude in your intent:\n- The expected INITIAL STATE of relevant elements\n- The ACTION the user takes\n- The EXPECTED OUTCOME (what the feature produces, not what UI appears)\n- Why this matters to the user\n\nThe intent is the source of truth. If your steps conflict with the intent, fix the STEPS.\n\n**Steps**: Numbered list using ONLY these actions (any other verb is INVALID):\n- click: Click a button, link, or element\n- type: Type text into an input field\n- scroll: Scroll to an element or position\n- assert: Verify something VISUALLY visible on screen — text, headings, buttons, labels, images. MUST include location context when the same text could appear in multiple places. Use visual landmarks: \"in the side panel\", \"in the modal\", \"in the table header\", \"below the form\", \"in the toast notification\". CANNOT assert URLs, network requests, console logs, cookies, localStorage, or any non-visual state.\n- hover: Hover over an element\n- drag: Drag an element\n- read: Read text from an element into a variable\n- refresh: Refresh the page\n\nBANNED actions (NEVER use these):\n- wait: — INVALID. Do not write \"wait:\" steps.\n- verify: — INVALID. Use \"assert:\" instead.\n- navigate: — INVALID. Put navigation in Setup, not in steps.\n- select: — INVALID. Use \"click:\" to select dropdown items.\n- check: — INVALID. Use \"click:\" to check checkboxes, \"assert:\" to verify state.\n\n**Verification**: Steps that usually navigate AWAY from the action screen to the source of truth and assert the mutation's effect. This section implements what the frontmatter 'verification' field describes.\n\n**Expected Result**: What should be true when the test passes\n\n### Interaction requirements (CRITICAL)\n- Every test MUST include at least 2 meaningful interactions (click, type, drag). Tests that ONLY assert visibility of elements are REJECTED.\n- Every test MUST perform a mutation (create, update, delete, toggle, configure, etc.). There are NO render-only tests. If you need to verify something renders, fold that assertion into a mutation test's flow as a pre-condition or post-verification step.\n- Ask: \"Does this test verify that something WORKS, or just that something EXISTS?\" If the latter, it is NOT a valid test.\n\n### Functional assertions (CRITICAL)\nEvery test must have a FUNCTIONAL ASSERTION — an assertion that verifies the feature DID SOMETHING, not just that UI appeared.\n\nBAD PATTERN (open/close cycle — tests nothing):\n1. click: the \"Import component\" button\n2. assert: \"Import component\" is visible in the modal header\n3. click: the \"Close\" button in the modal\n4. assert: \"Import component\" is no longer visible\nThis only proves the modal opens and closes. It does NOT test importing a component.\n\nGOOD PATTERN (completing the action — tests the feature):\n1. click: the \"Import component\" button\n2. assert: \"Import component\" is visible in the modal header\n3. click: \"Login Component\" in the component list\n4. click: the \"Import\" button\n5. assert: \"Login Component\" is visible in the step list\n\nIf your last assertion is about a modal being open, a heading being visible, or an element disappearing, you probably haven't tested anything. Ask: \"What is the OUTCOME of this action?\" Your test must prove the feature's MISSION is fulfilled.\n\n### Variation coverage\nWhen you find branching patterns in the source, decide whether each variant produces DIFFERENT BEHAVIOR (different code path, different UI, different output) or just passes different data through the SAME code path.\n\nThe question to ask: \"In the source code, is there a conditional that renders different components or runs different logic based on this variant?\" If yes → separate tests. If no → one test is enough.\n\nWhy this matters: tests that only vary in what string is passed through identical UI don't catch different bugs — they just inflate the test count.\n\nGOOD variations (code branches differently):\n- Different providers rendering different templates/forms per provider\n- Different platform types showing different upload/input components\n- Status states rendering different visual components per state\n\nBAD variations (same code path, different data):\n- Switching between different items that use the same component\n- Deleting different records through the same confirmation flow\n- Filtering by different values through the same dropdown\n\n### Default state awareness (CRITICAL)\nRead the source code to find default states for toggles, checkboxes, and dropdowns. BEFORE writing a step that interacts with a stateful element:\n- Check the source code for the element's initial value\n- If a toggle defaults to ON: clicking it turns it OFF (stops/disables)\n- ALWAYS state the expected state transition: \"click: the 'Recording' toggle to switch it from ON to OFF\" — not just \"click: the 'Recording' toggle\"\n- Assert the initial state BEFORE interacting\n\n### Assertion location context (CRITICAL)\nEVERY assertion MUST include location context — where on the page the element appears. Never write a bare \"assert: text X is visible\". Always specify: in the modal, in the sidebar, in the table, in the header, in the toast notification, in the dropdown, on the card, in the form, in the dialog, in the panel, as a page heading, as a button label, etc.\n- GOOD: assert: text \"Run preview\" is visible in the side panel\n- BAD: assert: text \"Status\" is visible (WHERE? column header? form label? sidebar?)\n\n### Test writing rules\n- Each test follows ONE deterministic path — no conditionals, no \"e.g.\", no \"(mocked or ...)\"\n- \"or\" in click/type steps is OK for naming the same element (click: the \"Edit\" or \"Pencil\" icon) — these are visual synonyms\n- \"or\" in assert steps is NEVER OK — since scenarios define the exact data, you always know what to expect\n- Assertions must specify EXACT text, element, or visual state — never \"or similar\", never \"e.g.\"\n- Be specific: use exact button text, field names, toast messages FROM THE CODE\n- One test per file\n- Never write meta-tests that \"audit\" scenario/fixture contents\n- Reference scenario data when needed for real user flows, using {{token}} placeholders for variable fields\n- Do NOT write tests that verify the test infrastructure itself\n- Every step must be concrete and reproducible. \"assert: text 'Deal Created' is visible in toast\" is GOOD. \"assert: success indicator appears\" is BAD.\n\n### Visual-only rules (CRITICAL)\nTests are executed by a VISUAL agent that sees the screen like a human. It can ONLY see what's rendered on screen.\n\nThe agent CANNOT access:\n- URLs or the browser address bar\n- Network requests or API calls\n- Console logs or errors\n- localStorage, cookies, or session data\n- HTML source, DOM structure, or element attributes\n\nTherefore:\n- NEVER assert URLs: \"assert: URL contains /creation\" is INVALID. Instead assert visible page content.\n- NEVER assert network: \"assert: API call was made\" is INVALID\n- NEVER assert non-visual state: \"assert: form state is valid\" is INVALID\n- NEVER reference HTML elements: no \"div\", \"span\", \"section\", \"input\", \"button\" as element types\n- NEVER reference data attributes: no \"data-testid\", \"data-cy\", \"data-test\"\n- NEVER reference aria attributes: no \"[aria-label]\", \"[role=dialog]\"\n- NEVER reference CSS selectors: no \"#id\", \".class-name\", \"[attribute=value]\"\n- NEVER use meta-steps: no \"(Internal: ...)\", \"(Note: ...)\", or parenthetical commentary\n- Instead, describe what the user SEES: button text, label text, placeholder text, heading text, visible icons, tab names\n\n### Scenario data references (CRITICAL)\nThe scenarios define EXACTLY what data exists in the database. Since WE control the test data, assertions should reference EXACT values from the scenario.\n- When a test needs to verify data is displayed, use the EXACT values from the scenario (names, emails, titles, counts)\n- Read scenarios.md carefully and use the exact entity names, counts, and field values in your assertions\n- Use {{token}} placeholders ONLY for values that genuinely vary between runs (like auto-generated IDs)\n- NEVER use \"Dynamic:\", \"{variableName}\", or \"e.g.\" in steps or assertions. You have exact data — use it.\n- NEVER assume facts not stated in the scenario data.\n\n## Test generation ordering (for consistency)\nWhen generating tests for a node, follow this deterministic order:\n1. First: CRUD operations for the primary entity (Create, Read/View, Update, Delete)\n2. Second: State transitions (toggle, enable/disable, activate/deactivate)\n3. Third: Validation (required fields, invalid input, boundary values)\n4. Fourth: Navigation and linking (links to detail pages, breadcrumbs, back navigation)\n5. Fifth: Edge cases (empty states, maximum values, permission boundaries)\n\n## Test depth — proportional to complexity (ENFORCED)\n\nYou determine feature complexity by READING THE SOURCE CODE, not by counting files. Before writing tests for a node:\n1. Read the page file and explore all related source files\n2. Count the interactive elements you find: forms, buttons, toggles, modals, tables, tabs\n3. Write tests proportional to what you found — more interactive elements = more tests\n\nA complex multi-step wizard with many forms needs 8-15 tests. A simple settings page with one toggle needs 2-3 tests. Use your judgment based on what you actually read in the source.\n\n## CRUD completeness (MANDATORY — zero tolerance)\n\nIf the source code for a feature supports Create, Read, Edit, and Delete for ANY entity, you MUST write tests for ALL of them. Missing even ONE CRUD operation is a critical failure.\n\n**How to detect CRUD support:** Look for:\n- Create: \"New\", \"Add\", \"Create\" buttons; form submission handlers; modals with input fields\n- Read/View: Detail pages, list pages, tables, cards displaying entity data\n- Edit: \"Edit\", \"Rename\", \"Update\" buttons; pre-filled forms\n- Delete: \"Delete\", \"Remove\", \"Trash\" buttons; confirmation dialogs\n\nIf you find yourself writing only 1-2 tests for a CRUD page, STOP. Re-read the source. Find ALL the entity operations. Write tests for each.\n\n## Outcome verification — STRUCTURALLY ENFORCED\n\nThe write_test tool REJECTS any test without a \\`verification\\` frontmatter field. This is not advisory — it's a hard gate.\n\nWhat does NOT count as verification (these are UI acknowledgments, not proof):\n- Toast messages\n- Confirmation dialogs\n- Inline success indicators\n- The action button changing state\n\nVerification destinations:\n- After CREATE → verify in list/table\n- After EDIT → verify changed field in detail/list view\n- After DELETE → verify absence in list, refresh, verify still absent\n- After TOGGLE → refresh, verify retained state\n\n## CRUD test templates (for any page with forms/CRUD):\n1. **Create**: fill all fields, submit, verify the item appears\n2. **Validation**: submit with empty required fields, verify error messages\n3. **Edit**: modify existing item, save, verify change reflected\n4. **Delete**: remove item, verify disappears, refresh, verify stays gone\n5. **Boundary**: extremely long strings, special characters\n\n**For pages with dropdowns/filters:**\n- You MUST click the dropdown trigger first, THEN click an option.\n\n**For elements revealed by hover:**\n- Include a hover step before clicking elements that only appear on hover.\n\n**After every action (create/edit/delete), verify the OUTCOME:**\n- BAD: click \"Save\" and move on\n- GOOD: click \"Save\" → assert the saved data appears in the list/detail view\n\n## Excluded routes\n- **Admin/backoffice pages**: routes under /admin/ are excluded from test generation. These require special auth, affect all users globally, and are not part of the standard user experience.\n- **Auth/login pages**: never test authentication flows — the user is always already logged in.\n\n## Test distribution guidelines\n- Core flows (from AUTONOMA.md where core: true): spend MOST of your time here. These features break → users leave.\n- Supporting flows: adequate coverage — happy path plus important variations.\n- Simple display/config pages: basic coverage.\n\n## Coverage dimensions\n\nYou track THREE kinds of coverage:\n1. Route/file coverage: which routes explored, which source files visited\n2. Entity coverage: which entity types and variations (enum values, states) appear in tests\n3. Behavioral variant coverage: which code-branching variants have dedicated tests. If a switch/map dispatches to N different renderers, you should have tests for the most important variants.\n\nWhen you finish, all dimensions are reported so the user knows what's covered and what gaps remain.`;\n","import {mkdir, readFile, rmdir, unlink, writeFile} from \"node:fs/promises\";\nimport {basename, join} from \"node:path\";\nimport {type LanguageModel, tool} from \"ai\";\nimport {z} from \"zod\";\nimport type { AppConfig } from \"../../config\";\nimport {type AgentResult, runAgent} from \"../../core/agent\";\nimport {formatContext, type ProjectContext} from \"../../core/context\";\nimport {createStepLogger} from \"../../core/display\";\nimport {loadGitignorePatterns} from \"../../core/gitignore\";\nimport {getModel} from \"../../core/model\";\nimport {reviewLoop} from \"../../core/review\";\nimport {runConsolidatedReview, type TestReviewFeedback} from \"./review\";\n\nconst MAX_CONCURRENCY = 8;\nimport {buildBashTool, buildGlobTool, buildGrepTool, buildListDirectoryTool, buildReadFileTool} from \"../../tools\";\nimport {CoverageState, type FeatureNode, loadBfsState} from \"./graph\";\nimport {type DiscoveredFeature, loadFeatures, runFeatureDiscovery} from \"../00b-feature-discovery/index\";\nimport {\n buildCreateFolderTool,\n buildGetProgressTool,\n buildNextNodeTool,\n buildSpawnResearcherTool,\n buildWriteTestTool,\n} from \"./tools\";\nimport {SYSTEM_PROMPT} from \"./prompt\";\nimport {validateTestContent} from \"./validation\";\nimport {glob} from \"glob\";\n\nexport interface TestGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n config?: AppConfig;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n pages: Map<string, { route: string; path: string; description: string }>;\n}\n\ninterface PageEntry {\n route: string;\n path: string;\n description: string;\n}\n\nasync function preseedQueue(\n state: CoverageState,\n projectRoot: string,\n pages: Map<string, PageEntry>,\n features?: Map<string, DiscoveredFeature>,\n): Promise<string> {\n let seeded = 0;\n\n const pageIdByPath = new Map<string, string>();\n\n for (const [absolutePath, page] of pages) {\n const routeSegments = page.route\n .split(\"/\")\n .filter(Boolean)\n .map((s) => s.replace(/[\\[\\]$:]/g, \"\").replace(/\\..*$/, \"\") || \"param\");\n\n if (routeSegments.length === 0) continue;\n\n const id = routeSegments.join(\"-\");\n const name = routeSegments\n .map((s) => s.replace(/-/g, \" \").replace(/\\bparam\\b/, \"[id]\"))\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join(\" / \");\n\n const relPath = absolutePath.startsWith(projectRoot)\n ? absolutePath.slice(projectRoot.length).replace(/^\\//, \"\")\n : page.path;\n\n pageIdByPath.set(absolutePath, id);\n\n const node: FeatureNode = {\n id,\n name,\n routePath: page.route.startsWith(\"/\") ? page.route : `/${page.route}`,\n sourceFiles: [relPath],\n parentId: null,\n depth: 0,\n status: \"queued\",\n };\n if (state.enqueue(node)) seeded++;\n }\n\n if (features) {\n for (const [featureId, feature] of features) {\n const parentId = pageIdByPath.get(feature.parentPagePath) ?? null;\n const parentNode = parentId ? state.nodes.get(parentId) : null;\n\n const node: FeatureNode = {\n id: featureId,\n name: feature.name,\n routePath: parentNode?.routePath,\n sourceFiles: feature.sourceFiles,\n parentId,\n depth: 1,\n status: \"queued\",\n };\n if (state.enqueue(node)) seeded++;\n }\n }\n\n return seeded > 0\n ? `\\nPre-seeded: ${seeded} nodes (pages + sub-features). Call next_node to start processing them one at a time.`\n : \"\";\n}\n\nexport async function runTestGenerator(\n input: TestGeneratorInput,\n): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n const ignorePatterns = await loadGitignorePatterns(input.projectRoot);\n const existingState = await loadBfsState(input.outputDir);\n const state = existingState ?? new CoverageState();\n\n let result: AgentResult | undefined;\n\n const finishTool = tool({\n description:\n \"Call when the BFS queue is empty and all routes have been explored.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Coverage summary\"),\n }),\n execute: async (finishInput) => {\n const stats = state.summary();\n const totalProcessed = stats.tested;\n if (stats.queued > 0) {\n return {\n error: `Cannot finish: ${stats.queued} nodes still in queue. Process them first.`,\n };\n }\n if (totalProcessed < 10 && stats.totalNodes > 10) {\n return {\n error: `Cannot finish: only ${totalProcessed} of ${stats.totalNodes} nodes were tested. ${stats.skipped} were skipped. Call next_node to continue processing.`,\n };\n }\n\n result = {\n success: true,\n artifacts: state.allTestPaths(),\n summary: finishInput.summary,\n };\n\n await generateIndex(input.outputDir, state);\n\n return {\n ...stats,\n message: \"Test generation complete. INDEX.md written.\",\n };\n },\n });\n\n let kbContext = \"\";\n try {\n const autonomaMd = await readFile(\n join(input.outputDir, \"AUTONOMA.md\"),\n \"utf-8\",\n );\n kbContext += `\\n## Knowledge Base (AUTONOMA.md)\\n\\n${autonomaMd}\\n`;\n } catch {\n /* KB not available */\n }\n\n try {\n const scenariosMd = await readFile(\n join(input.outputDir, \"scenarios.md\"),\n \"utf-8\",\n );\n kbContext += `\\n## Scenarios\\n\\n${scenariosMd}\\n`;\n } catch {\n /* scenarios not available */\n }\n\n let features: Map<string, DiscoveredFeature> | null = null;\n if (!existingState) {\n features = await loadFeatures(input.outputDir);\n if (!features) {\n console.log(\" Running feature discovery...\");\n features = await runFeatureDiscovery({\n projectRoot: input.projectRoot,\n outputDir: input.outputDir,\n modelId: input.modelId,\n pages: input.pages,\n });\n console.log(` Discovered ${features.size} sub-features`);\n } else {\n console.log(` Loaded ${features.size} cached sub-features from features.json`);\n }\n }\n\n const preseedContext = existingState\n ? \"\"\n : await preseedQueue(state, input.projectRoot, input.pages, features ?? undefined);\n\n const resumeContext = existingState\n ? `\\nYou are RESUMING a previous run. ${existingState.summary().tested} nodes tested, ${existingState.summary().totalTests} tests written. Call next_node to continue.`\n : \"\";\n\n const contextBlock = input.projectContext\n ? \"\\n\" + formatContext(input.projectContext) + \"\\n\"\n : \"\";\n\n let prompt = `Generate E2E test cases by processing every node in the queue.\n${contextBlock}${kbContext}${resumeContext}${preseedContext}\n\nThe project codebase is at the working directory.\n\nMANDATORY PROCESS:\n1. Call next_node to get the first node\n2. For EACH node returned by next_node:\n a. Read its source files and explore the surrounding codebase — use glob, grep, read_file to find ALL related components, utilities, and imports. Don't stop at the page file.\n b. Catalog every interactive element: buttons, inputs, toggles, forms, modals, tables, dropdowns\n c. Write tests PROPORTIONAL to the feature's actual complexity — the more interactive elements and workflows you find in the source, the more tests you write\n d. CRUD COMPLETENESS: if the source has Create/Edit/Delete for ANY entity, write tests for ALL of them\n e. OUTCOME VERIFICATION: after every action, navigate to where the result should be visible and ASSERT it\n f. After writing tests, call next_node to get the next node\n g. If a node has no testable behavior (utility, redirect): call next_node to skip it (auto-skipped)\n3. When next_node returns done, call finish\n\nDo NOT spend excessive time on any single node. Write tests for what you find, then move on.\nDo NOT try to finish early. Process EVERY node via next_node until it returns done.`;\n\n const CHUNK_STEPS = 3000;\n const MAX_STALE_CHUNKS = 3;\n let totalSteps = 0;\n\n const logger = createStepLogger(\"test-gen\", CHUNK_STEPS);\n\n const listDirectoryFn = await buildListDirectoryTool(input.projectRoot);\n const agentConfig = {\n id: \"test-generator\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: CHUNK_STEPS,\n temperature: 0.3,\n tools: (heartbeat: () => void) => ({\n read_file: buildReadFileTool(input.projectRoot),\n read_output: buildReadFileTool(input.outputDir),\n glob: buildGlobTool(input.projectRoot, ignorePatterns),\n grep: buildGrepTool(input.projectRoot),\n bash: buildBashTool(input.projectRoot),\n list_directory: listDirectoryFn,\n write_test: buildWriteTestTool(state, input.outputDir),\n create_folder: buildCreateFolderTool(input.outputDir),\n next_node: buildNextNodeTool(state, input.outputDir),\n get_progress: buildGetProgressTool(state),\n spawn_researcher: buildSpawnResearcherTool(\n model,\n input.projectRoot,\n heartbeat,\n ),\n finish: finishTool,\n }),\n onStepFinish: (info: Parameters<typeof logger.log>[0]) => {\n logger.log(info);\n\n const stats = state.summary();\n if (info.stepNumber > 0 && info.stepNumber % 10 === 0) {\n logger.checkpoint(\n `${stats.tested} nodes tested, ${stats.totalTests} tests written, ${stats.queued} in queue`,\n );\n }\n },\n };\n\n let staleChunks = 0;\n let lastTestCount = state.summary().totalTests;\n\n while (!result) {\n try {\n await runAgent(agentConfig, prompt, () => result);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(` [chunk] Agent error (will retry next chunk): ${message}`);\n }\n\n totalSteps += CHUNK_STEPS;\n\n if (result) break;\n\n const stats = state.summary();\n const newTests = stats.totalTests - lastTestCount;\n\n if (newTests === 0) {\n staleChunks++;\n console.log(\n ` [chunk] No progress in last ${CHUNK_STEPS} steps (stale ${staleChunks}/${MAX_STALE_CHUNKS})`,\n );\n if (staleChunks >= MAX_STALE_CHUNKS) {\n console.log(\n ` [chunk] Agent stuck — ${MAX_STALE_CHUNKS} consecutive chunks with no progress. Stopping.`,\n );\n break;\n }\n } else {\n staleChunks = 0;\n }\n\n lastTestCount = stats.totalTests;\n\n if (stats.queued === 0 && stats.tested > 0) {\n console.log(\n ` [chunk] Queue empty after ${totalSteps} steps. Finishing.`,\n );\n break;\n }\n\n console.log(\n ` [chunk] Continuing — ${stats.totalTests} tests, ${stats.queued} queued, ${totalSteps} total steps`,\n );\n\n prompt = `You are RESUMING a previous run. ${stats.tested} nodes tested, ${stats.totalTests} tests written.\nCall next_node to get the next node. Continue processing all remaining nodes.\nIMPORTANT: Do NOT try to finish early. Process every node via next_node until it returns done.`;\n }\n\n logger.summary();\n\n if (!result && state.allTestPaths().length > 0) {\n await generateIndex(input.outputDir, state);\n const stats = state.summary();\n result = {\n success: true,\n artifacts: state.allTestPaths(),\n summary: `${stats.totalTests} tests written across ${stats.tested} nodes in ${totalSteps} steps.`,\n };\n }\n\n if (state.allTestPaths().length > 0) {\n const journeyCount = await generateJourneyTests(\n input.outputDir,\n model,\n input.projectRoot,\n );\n if (journeyCount > 0) {\n console.log(` Generated ${journeyCount} journey tests`);\n }\n\n // --- Review → Fix cycle (max MAX_REVIEW_CYCLES) ---\n const MAX_REVIEW_CYCLES = 4;\n\n for (let cycle = 0; cycle < MAX_REVIEW_CYCLES; cycle++) {\n console.log(` Review cycle ${cycle + 1}/${MAX_REVIEW_CYCLES}`);\n\n const reviewResult = await runConsolidatedReview(\n input.outputDir,\n input.projectRoot,\n model,\n );\n\n console.log(\n ` Review: ${reviewResult.passed} passed, ${reviewResult.failed} failed`,\n );\n\n if (reviewResult.feedback.length === 0) {\n console.log(` All tests passed review — done`);\n break;\n }\n\n // Delete failing tests before feeding back to planner\n for (const fb of reviewResult.feedback) {\n try {\n await unlink(fb.testPath);\n } catch { /* already gone */ }\n }\n\n // Fix in parallel — each test gets its own focused prompt\n console.log(\n ` Feeding ${reviewResult.feedback.length} tests back to planner for fixes`,\n );\n\n const fixBatchSize = MAX_CONCURRENCY;\n for (let i = 0; i < reviewResult.feedback.length; i += fixBatchSize) {\n const batch = reviewResult.feedback.slice(i, i + fixBatchSize);\n await Promise.all(\n batch.map(async (fb) => {\n const fixPrompt = buildReviewFixPrompt(fb);\n let fixResult: AgentResult | undefined;\n try {\n await runAgent(\n { ...agentConfig, maxSteps: 30 },\n fixPrompt,\n () => fixResult,\n );\n } catch (err) {\n console.warn(\n ` [fix] Error fixing ${fb.relativePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }),\n );\n }\n\n console.log(` Fix pass complete`);\n }\n\n // --- Final validation sweep: move structurally invalid tests to _invalid/ ---\n const allTestFiles = await glob(\n join(input.outputDir, \"qa-tests\", \"**/*.md\"),\n );\n let markedInvalid = 0;\n for (const testPath of allTestFiles) {\n if (basename(testPath) === \"INDEX.md\") continue;\n if (testPath.includes(\"/_invalid/\")) continue;\n const content = await readFile(testPath, \"utf-8\");\n const validation = validateTestContent(content);\n if (!validation.valid) {\n const invalidDir = join(input.outputDir, \"qa-tests\", \"_invalid\");\n await mkdir(invalidDir, { recursive: true });\n const dest = join(invalidDir, basename(testPath));\n const annotated = `<!-- VALIDATION ERRORS: ${validation.errors.join(\"; \")} -->\\n${content}`;\n await writeFile(dest, annotated, \"utf-8\");\n await unlink(testPath);\n markedInvalid++;\n }\n }\n if (markedInvalid > 0) {\n console.log(\n ` ${markedInvalid} tests still invalid after review cycles — moved to _invalid/`,\n );\n }\n\n // --- Clean up empty directories ---\n const dirs = await glob(join(input.outputDir, \"qa-tests\", \"**/\"), {\n dot: false,\n });\n for (const dir of dirs.sort((a, b) => b.length - a.length)) {\n try {\n await rmdir(dir);\n } catch {\n /* not empty */\n }\n }\n }\n\n const reviewed = await reviewLoop(result, {\n agentId: \"test-generator\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n showPreview: false,\n reviewGuidance:\n \"Check that critical flows have test coverage.\\n\" +\n \"Verify test steps reference real UI elements (button labels, form fields, navigation paths).\\n\" +\n \"Look for tests that seem to duplicate each other or reference features that don't exist.\\n\" +\n \"Test files are in the qa-tests/ folder in the output directory shown above.\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed the generated tests and has this feedback:\n\n\"${feedback}\"\n\nCheck current progress with get_progress.\nRead your previous test files if needed.\nAdjust based on the feedback — add missing tests, fix existing ones, or explore new areas.\nWhen done, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n return (\n reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Test generator did not produce a result\",\n }\n );\n}\n\nfunction buildReviewFixPrompt(fb: TestReviewFeedback): string {\n const failedDetails = fb.failedDimensions.map((dim) => {\n const d = fb.dimensions[dim];\n if (!d) return `- **${dim}**: no evidence available`;\n return `- **${dim}**: ${d.evidence}${d.suggestion ? `\\n Suggestion: ${d.suggestion}` : \"\"}`;\n }).join(\"\\n\");\n\n return `Fix this ONE test that failed review. The reviewer found specific problems — read the feedback carefully and use your tools to investigate and fix.\n\n## Test: ${fb.relativePath}\n\\`\\`\\`\n${fb.content}\n\\`\\`\\`\n\n## Review feedback (failed dimensions):\n${failedDetails}\n\n## Instructions:\n1. Read the source files for this feature to understand what the real UI looks like\n2. If the feedback mentions scenario data issues, use read_output to read scenarios.md and use ONLY values that exist there\n3. Fix the specific issues the reviewer identified — use the evidence and suggestions\n4. Rewrite the test using write_test — the tool validates structure automatically\n5. If the test is unfixable (the feature doesn't support the intended behavior), skip it and call finish\n\nIMPORTANT: Focus ONLY on this test. Do not write new tests or modify other files.`;\n}\n\n\nasync function generateIndex(\n outputDir: string,\n state: CoverageState,\n): Promise<void> {\n const testsByFolder = new Map<string, string[]>();\n\n for (const paths of state.testsWritten.values()) {\n for (const p of paths) {\n const parts = p.split(\"/\");\n if (parts.length >= 3) {\n const folder = parts[1]!;\n const existing = testsByFolder.get(folder) ?? [];\n existing.push(p);\n testsByFolder.set(folder, existing);\n }\n }\n }\n\n const stats = state.summary();\n const folders = [...testsByFolder.entries()].map(([name, tests]) => ({\n name,\n test_count: tests.length,\n }));\n\n const critCounts = new Map([\n [\"critical\", 0],\n [\"high\", 0],\n [\"mid\", 0],\n [\"low\", 0],\n ]);\n const flowCounts = new Map<string, number>();\n let totalSteps = 0;\n let totalInteractions = 0;\n\n for (const paths of state.testsWritten.values()) {\n for (const p of paths) {\n try {\n const content = await readFile(join(outputDir, p), \"utf-8\");\n const critMatch = content.match(/criticality:\\s*(\\w+)/);\n const critVal = critMatch?.[1] ?? \"\";\n if (critCounts.has(critVal))\n critCounts.set(critVal, (critCounts.get(critVal) ?? 0) + 1);\n const flowMatch = content.match(/flow:\\s*\"([^\"]+)\"/);\n const flowVal = flowMatch?.[1];\n if (flowVal)\n flowCounts.set(flowVal, (flowCounts.get(flowVal) ?? 0) + 1);\n const stepMatches = content.match(\n /^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm,\n );\n if (stepMatches) totalSteps += stepMatches.length;\n const interactionMatches = content.match(\n /^\\d+\\.\\s+(click|type|drag):/gm,\n );\n if (interactionMatches) totalInteractions += interactionMatches.length;\n } catch {\n /* file may not exist */\n }\n }\n }\n\n const avgSteps =\n stats.totalTests > 0 ? (totalSteps / stats.totalTests).toFixed(1) : \"0\";\n\n let content = `---\ntotal_tests: ${stats.totalTests}\ntotal_folders: ${folders.length}\navg_steps_per_test: ${avgSteps}\ntotal_interactions: ${totalInteractions}\ncriticality:\n critical: ${critCounts.get(\"critical\") ?? 0}\n high: ${critCounts.get(\"high\") ?? 0}\n mid: ${critCounts.get(\"mid\") ?? 0}\n low: ${critCounts.get(\"low\") ?? 0}\nfolders:\n${folders.map((f) => ` - name: \"${f.name}\"\\n test_count: ${f.test_count}`).join(\"\\n\")}\n---\n\n# Test Suite Index\n\nGenerated by BFS exploration. ${stats.tested} nodes tested, ${stats.skipped} skipped.\n\n## Folders\n\n| Folder | Tests |\n|--------|-------|\n${folders.map((f) => `| ${f.name} | ${f.test_count} |`).join(\"\\n\")}\n\n## All Tests\n\n${[...testsByFolder.entries()]\n .flatMap(([_folder, tests]) => tests.map((t) => `- \\`${t}\\``))\n .join(\"\\n\")}\n`;\n\n await writeFile(join(outputDir, \"qa-tests\", \"INDEX.md\"), content, \"utf-8\");\n}\n\nasync function generateJourneyTests(\n outputDir: string,\n model: LanguageModel,\n projectRoot: string,\n): Promise<number> {\n const logger = createStepLogger(\"journeys\", 50);\n\n let autonomaMd = \"\";\n let scenariosMd = \"\";\n try {\n autonomaMd = await readFile(join(outputDir, \"AUTONOMA.md\"), \"utf-8\");\n } catch {}\n try {\n scenariosMd = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch {}\n\n if (!autonomaMd) return 0;\n\n const existingTests = await glob(join(outputDir, \"qa-tests\", \"**/*.md\"));\n const existingTitles: string[] = [];\n for (const t of existingTests) {\n if (basename(t) === \"INDEX.md\") continue;\n const content = await readFile(t, \"utf-8\");\n const titleMatch = content.match(/title:\\s*\"([^\"]+)\"/);\n if (titleMatch) existingTitles.push(titleMatch[1]!);\n }\n\n const featuresContext = \"\";\n\n const journeyPrompt = `Generate cross-feature JOURNEY tests that traverse the core product flow end-to-end.\n\n## Knowledge Base\n${autonomaMd}\n${featuresContext}\n\n## Scenarios (EXACT data in the database)\n${scenariosMd}\n\n## Existing test titles (do NOT duplicate)\n${existingTitles.join(\"\\n\")}\n\n## Instructions\n\nRead the core_flows from the Knowledge Base above. For each core feature, identify how it connects to other features in a real user workflow. Generate journey tests that traverse 2+ core features end-to-end.\n\nEach journey test:\n- Spans 2+ features/pages in sequence\n- Has 8-15 steps (longer than feature tests)\n- Uses EXACT data values from scenarios.md — NEVER use \"Dynamic:\", \"{variable}\", or \"e.g.\"\n- Has criticality: critical\n- Has scenario: standard\n- Includes an **Intent**: section explaining the cross-feature flow being tested\n- Verifies that the OUTPUT of one feature is correctly consumed by the NEXT feature\n- Goes in the \"journeys\" folder\n\nWrite 5-8 journey tests using the write_test tool with folder \"journeys\". Then call finish.`;\n\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n const journeyState = new CoverageState();\n journeyState.enqueue({\n id: \"journeys\",\n name: \"Journey Tests\",\n sourceFiles: [],\n parentId: null,\n depth: 0,\n status: \"queued\",\n });\n\n let journeyResult: AgentResult | undefined;\n const journeyFinish = tool({\n description: \"Signal journey generation is complete.\",\n inputSchema: z.object({ summary: z.string() }),\n execute: async (finishInput) => {\n journeyResult = {\n success: true,\n artifacts: journeyState.allTestPaths(),\n summary: finishInput.summary,\n };\n return { done: true, count: journeyState.allTestPaths().length };\n },\n });\n\n const config = {\n id: \"journey-gen\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 50,\n temperature: 0.3,\n tools: () => ({\n read_file: buildReadFileTool(projectRoot),\n read_output: buildReadFileTool(outputDir),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n write_test: buildWriteTestTool(journeyState, outputDir),\n create_folder: buildCreateFolderTool(outputDir),\n finish: journeyFinish,\n }),\n onStepFinish: (info: Parameters<typeof logger.log>[0]) => logger.log(info),\n };\n\n try {\n await runAgent(config, journeyPrompt, () => journeyResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Journey generator error: ${message}`);\n }\n\n logger.summary();\n return journeyState.allTestPaths().length;\n}\n","import * as p from \"@clack/prompts\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { loadConfig } from \"./config\";\nimport type { AgentResult } from \"./core/agent\";\nimport { type ProjectContext, saveContext, loadContext } from \"./core/context\";\nimport { DEFAULT_MODEL } from \"./core/model\";\nimport { ensureOutputDir } from \"./core/output\";\nimport {\n loadState,\n markStep,\n nextPendingStep,\n type StepName,\n type PipelineState,\n} from \"./core/state\";\n\nconst PAGES_FILE = \"pages.json\";\n\nasync function savePages(outputDir: string, pages: Map<string, { route: string; path: string; description: string }>): Promise<void> {\n const obj = Object.fromEntries(pages);\n await writeFile(join(outputDir, PAGES_FILE), JSON.stringify(obj, null, 2), \"utf-8\");\n}\n\nasync function loadPages(outputDir: string): Promise<Map<string, { route: string; path: string; description: string }>> {\n try {\n const raw = await readFile(join(outputDir, PAGES_FILE), \"utf-8\");\n const obj = JSON.parse(raw);\n return new Map(Object.entries(obj));\n } catch {\n return new Map();\n }\n}\n\nfunction parseArgs(argv: string[]) {\n const args: Record<string, string | boolean> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (arg.startsWith(\"--\")) {\n const key = arg.slice(2);\n const next = argv[i + 1];\n if (next && !next.startsWith(\"--\")) {\n args[key] = next;\n i++;\n } else {\n args[key] = true;\n }\n }\n }\n return args;\n}\n\nconst STEP_LABELS: Record<StepName, string> = {\n pagesFinder: \"Pages Finder\",\n kb: \"Knowledge Base\",\n entityAudit: \"Entity Audit\",\n scenarioRecipe: \"Scenario + Recipe Generator\",\n recipeBuilder: \"Recipe Builder\",\n testGenerator: \"E2E Test Generator (BFS)\",\n};\n\nconst STEP_INTROS: Record<StepName, string> = {\n pagesFinder:\n \"Scanning your codebase to discover every page and route. This maps the full surface area of your application so we know what needs test coverage.\",\n kb:\n \"Reading every page file to build a knowledge base (AUTONOMA.md). This gives the AI context about your features, flows, and UI patterns.\",\n entityAudit:\n \"Identifying every database model and tracing how each gets created — which service function, what side effects. This determines which entities need test data factories.\",\n scenarioRecipe:\n \"Designing test data scenarios with realistic values from your entity audit. The scenario defines exactly WHAT data will exist in the database during tests.\",\n recipeBuilder:\n \"Guiding you through implementing Autonoma SDK factories for each entity. You'll implement each factory and we'll test them live (create + teardown) before moving on.\",\n testGenerator:\n \"Generating exhaustive E2E test cases by exploring every page and feature. Each area gets test coverage proportional to its complexity.\",\n};\n\nasync function runStep(\n step: StepName,\n outputDir: string,\n state: PipelineState,\n config: ReturnType<typeof loadConfig>,\n projectContext?: ProjectContext,\n nonInteractive?: boolean,\n): Promise<PipelineState> {\n const label = STEP_LABELS[step];\n p.note(STEP_INTROS[step], `Step: ${label}`);\n\n state = await markStep(outputDir, state, step, \"running\");\n\n if (step !== \"pagesFinder\" && projectContext && !projectContext.pages) {\n const pages = await loadPages(outputDir);\n if (pages.size > 0) {\n projectContext = { ...projectContext, pages: [...pages.values()] };\n }\n }\n\n try {\n let result: AgentResult | undefined;\n\n switch (step) {\n case \"pagesFinder\": {\n const { runPageFinder } = await import(\"./agents/00-pages-finder/index\");\n const pages = await runPageFinder({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n nonInteractive,\n });\n await savePages(outputDir, pages);\n break;\n }\n case \"kb\": {\n const { runKBGenerator } = await import(\"./agents/01-kb-generator/index\");\n result = await runKBGenerator({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"entityAudit\": {\n const { runEntityAudit } = await import(\"./agents/02-entity-audit/index\");\n result = await runEntityAudit({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"scenarioRecipe\": {\n const { runScenarioRecipe } = await import(\"./agents/03-scenario-recipe/index\");\n result = await runScenarioRecipe({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"recipeBuilder\": {\n const { runRecipeBuilder } = await import(\"./agents/04-recipe-builder/index\");\n result = await runRecipeBuilder({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"testGenerator\": {\n const { runTestGenerator } = await import(\"./agents/05-test-generator/index\");\n const pages = await loadPages(outputDir);\n result = await runTestGenerator({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n pages,\n });\n break;\n }\n }\n\n if (result && !result.success) {\n if (result.paused) {\n state = await markStep(outputDir, state, step, \"paused\");\n p.log.info(`Paused: ${label} — ${result.summary}`);\n } else {\n state = await markStep(outputDir, state, step, \"failed\");\n p.log.error(`Failed: ${label} — ${result.summary}`);\n }\n } else {\n state = await markStep(outputDir, state, step, \"done\");\n p.log.success(`Completed: ${label}`);\n }\n } catch (err) {\n state = await markStep(outputDir, state, step, \"failed\");\n const message = err instanceof Error ? err.message : String(err);\n p.log.error(`Failed: ${label} — ${message}`);\n }\n\n return state;\n}\n\nasync function showStatus(outputDir: string) {\n const state = await loadState(outputDir);\n console.log(\"\\nPipeline Status:\");\n for (const [step, status] of Object.entries(state.steps)) {\n const icon =\n status === \"done\" ? \"+\" :\n status === \"running\" ? \"~\" :\n status === \"paused\" ? \"‖\" :\n status === \"failed\" ? \"x\" :\n \" \";\n const label = STEP_LABELS[step as StepName] ?? step;\n console.log(` [${icon}] ${label}: ${status}`);\n }\n}\n\nconst BANNER = `\n\\x1b[36m\\x1b[1m ___ _\n / _ \\\\ | |\n/ /_\\\\ \\\\_ _| |_ ___ _ __ ___ _ __ ___ __ _\n| _ | | | | __/ _ \\\\| '_ \\\\ / _ \\\\| '_ \\` _ \\\\ / _\\` |\n| | | | |_| | || (_) | | | | (_) | | | | | | (_| |\n\\\\_| |_/\\\\__,_|\\\\__\\\\___/|_| |_|\\\\___/|_| |_| |_|\\\\__,_|\n\\x1b[0m\n\\x1b[2m E2E Test Planner — Generate exhaustive test suites from your codebase\\x1b[0m\n`;\n\nasync function gatherProjectContext(): Promise<ProjectContext | undefined> {\n const description = await p.text({\n message: \"What is this project? (a short description so the agent knows what it's looking at)\",\n placeholder: \"e.g. An insurance underwriting platform with a Next.js frontend and Express API\",\n });\n if (p.isCancel(description)) return undefined;\n\n const testingGoal = await p.text({\n message: \"Why do you want E2E tests? (what are you trying to catch or protect?)\",\n placeholder: \"e.g. We're about to refactor the claims flow and want regression coverage\",\n });\n if (p.isCancel(testingGoal)) return undefined;\n\n const criticalFlows = await p.text({\n message: \"What are the most critical flows? (the ones that absolutely cannot break)\",\n placeholder: \"e.g. User signup, creating a policy, submitting a claim, payment processing\",\n });\n if (p.isCancel(criticalFlows)) return undefined;\n\n return {\n description: description as string,\n testingGoal: testingGoal as string,\n criticalFlows: criticalFlows as string,\n };\n}\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2));\n const command = process.argv[2];\n\n if (command === \"status\") {\n const config = loadConfig({\n project: args.project as string | undefined,\n slug: args.slug as string | undefined,\n });\n const outputDir = await ensureOutputDir(config.projectSlug);\n await showStatus(outputDir);\n return;\n }\n\n if (command !== \"run\") {\n console.log(\"Usage:\");\n console.log(\" test-planner run [--project <path>] [--model <id>] [--step <name>] [--resume] [--non-interactive]\");\n console.log(\" test-planner status [--project <path>]\");\n return;\n }\n\n console.log(BANNER);\n p.intro(\"Let's generate your test suite\");\n\n const config = loadConfig({\n project: args.project as string | undefined,\n model: args.model as string | undefined,\n slug: args.slug as string | undefined,\n });\n\n const modelName = config.modelId ?? process.env.OPENROUTER_MODEL ?? DEFAULT_MODEL;\n\n p.log.info(`Project: ${config.projectRoot}`);\n p.log.info(`Model: ${modelName}`);\n\n const nonInteractive = !!args[\"non-interactive\"];\n const outputDir = await ensureOutputDir(config.projectSlug);\n let state = await loadState(outputDir);\n\n let isResuming = !!(args.resume || args.step);\n let projectContext: ProjectContext | undefined;\n\n const hasProgress = Object.values(state.steps).some(\n (s) => s === \"done\" || s === \"running\",\n );\n\n if (!isResuming && !nonInteractive && hasProgress) {\n const completedSteps = Object.entries(state.steps)\n .filter(([, s]) => s === \"done\")\n .map(([name]) => STEP_LABELS[name as StepName])\n .join(\", \");\n\n const resume = await p.confirm({\n message: `Found a previous run${completedSteps ? ` (completed: ${completedSteps})` : \"\"}. Resume from where you left off?`,\n });\n\n if (p.isCancel(resume)) {\n p.log.warn(\"Cancelled.\");\n return;\n }\n\n if (resume) {\n isResuming = true;\n }\n }\n\n if (isResuming || nonInteractive) {\n const saved = await loadContext(outputDir);\n if (saved) {\n projectContext = saved;\n p.log.info(`Loaded project context from previous run`);\n }\n }\n\n if (!projectContext && nonInteractive) {\n p.log.error(\"Non-interactive mode requires saved project context. Run interactively first, or create .project-context.json manually.\");\n return;\n }\n\n if (!projectContext) {\n projectContext = await gatherProjectContext();\n if (!projectContext) {\n p.log.warn(\"Cancelled.\");\n return;\n }\n await saveContext(outputDir, projectContext);\n }\n\n p.log.step(`Output: ${outputDir}`);\n\n console.log(\"\");\n p.log.info(\n `Got it. I'll focus on: ${projectContext.criticalFlows}\\n` +\n ` Starting the pipeline now.`,\n );\n console.log(\"\");\n\n const targetStep = args.step as StepName | undefined;\n\n if (targetStep) {\n if (targetStep === \"testGenerator\" && state.steps.scenarioRecipe !== \"done\") {\n p.log.error(\"Cannot run test generation yet — the scenario recipe step must complete first.\");\n return;\n }\n state = await runStep(targetStep, outputDir, state, config, projectContext, nonInteractive);\n p.outro(\"Done\");\n return;\n }\n\n const startStep = isResuming ? nextPendingStep(state) : \"pagesFinder\" as StepName;\n if (!startStep) {\n p.log.success(\"All steps complete.\");\n return;\n }\n\n const steps: StepName[] = [\"pagesFinder\", \"kb\", \"entityAudit\", \"scenarioRecipe\", \"recipeBuilder\", \"testGenerator\"];\n const startIdx = steps.indexOf(startStep);\n\n try {\n for (let i = startIdx; i < steps.length; i++) {\n const step = steps[i]!;\n state = await runStep(step, outputDir, state, config, projectContext, nonInteractive);\n\n if (state.steps[step] === \"paused\") {\n break;\n }\n\n if (state.steps[step] === \"failed\") {\n p.log.error(\"Pipeline stopped due to failure.\");\n break;\n }\n\n if (i < steps.length - 1 && !nonInteractive) {\n const nextStep = steps[i + 1]!;\n const shouldContinue = await p.confirm({\n message: `Continue to ${STEP_LABELS[nextStep]}?`,\n });\n if (p.isCancel(shouldContinue) || !shouldContinue) {\n p.log.info(\"Pipeline paused. Use --resume to continue.\");\n break;\n }\n }\n }\n } catch (err) {\n if (err instanceof Error && (err.message.includes(\"cancelled\") || err.message.includes(\"Cancelled\"))) {\n p.log.warn(\"Your progress is saved. Run again with --resume to continue from where you left off.\");\n return;\n }\n throw err;\n }\n\n p.outro(\"Done\");\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","import { resolve, join } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\n\nexport interface AppConfig {\n projectRoot: string;\n projectSlug: string;\n modelId?: string;\n databaseUrl?: string;\n sdkEndpointUrl?: string;\n sharedSecret?: string;\n signingSecret?: string;\n autonomaApiUrl?: string;\n autonomaApiToken?: string;\n autonomaGenerationId?: string;\n}\n\nfunction loadProjectEnv(projectRoot: string): void {\n let content: string;\n try {\n content = readFileSync(join(projectRoot, \".env\"), \"utf-8\");\n } catch {\n return;\n }\n\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const key = trimmed.slice(0, eqIdx).trim();\n let value = trimmed.slice(eqIdx + 1).trim();\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n if (!(key in process.env)) {\n process.env[key] = value;\n }\n }\n}\n\nexport function loadConfig(args: {\n project?: string;\n model?: string;\n slug?: string;\n}): AppConfig {\n const projectRoot = resolve(args.project ?? process.cwd());\n\n loadProjectEnv(projectRoot);\n\n const projectSlug =\n args.slug ??\n projectRoot\n .split(\"/\")\n .pop()\n ?.toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") ??\n \"default\";\n\n return {\n projectRoot,\n projectSlug,\n modelId: args.model ?? process.env.OPENROUTER_MODEL,\n databaseUrl: process.env.DATABASE_URL,\n sdkEndpointUrl: process.env.SDK_ENDPOINT_URL,\n sharedSecret: process.env.AUTONOMA_SHARED_SECRET,\n signingSecret: process.env.AUTONOMA_SIGNING_SECRET,\n autonomaApiUrl: process.env.AUTONOMA_API_URL,\n autonomaApiToken: process.env.AUTONOMA_API_TOKEN,\n autonomaGenerationId: process.env.AUTONOMA_GENERATION_ID,\n };\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\n\nexport function slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nexport function getOutputDir(projectSlug: string): string {\n return join(AUTONOMA_HOME, projectSlug);\n}\n\nexport async function ensureOutputDir(projectSlug: string): Promise<string> {\n const dir = getOutputDir(projectSlug);\n await mkdir(dir, { recursive: true });\n return dir;\n}\n\nexport async function ensureSubDir(projectSlug: string, ...parts: string[]): Promise<string> {\n const dir = join(getOutputDir(projectSlug), ...parts);\n await mkdir(dir, { recursive: true });\n return dir;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type StepStatus = \"pending\" | \"running\" | \"done\" | \"failed\" | \"paused\";\n\nexport interface PipelineState {\n steps: {\n pagesFinder: StepStatus;\n kb: StepStatus;\n entityAudit: StepStatus;\n scenarioRecipe: StepStatus;\n recipeBuilder: StepStatus;\n testGenerator: StepStatus;\n };\n}\n\nconst STATE_FILE = \".pipeline-state.json\";\n\nexport function initialState(): PipelineState {\n return {\n steps: {\n pagesFinder: \"pending\",\n kb: \"pending\",\n entityAudit: \"pending\",\n scenarioRecipe: \"pending\",\n recipeBuilder: \"pending\",\n testGenerator: \"pending\",\n },\n };\n}\n\nexport async function loadState(outputDir: string): Promise<PipelineState> {\n const path = join(outputDir, STATE_FILE);\n try {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw) as PipelineState;\n } catch {\n return initialState();\n }\n}\n\nexport async function saveState(\n outputDir: string,\n state: PipelineState,\n): Promise<void> {\n const path = join(outputDir, STATE_FILE);\n await writeFile(path, JSON.stringify(state, null, 2), \"utf-8\");\n}\n\nexport type StepName = keyof PipelineState[\"steps\"];\n\nexport async function markStep(\n outputDir: string,\n state: PipelineState,\n step: StepName,\n status: StepStatus,\n): Promise<PipelineState> {\n const updated = {\n ...state,\n steps: { ...state.steps, [step]: status },\n };\n await saveState(outputDir, updated);\n return updated;\n}\n\nexport function nextPendingStep(state: PipelineState): StepName | null {\n const order: StepName[] = [\"pagesFinder\", \"kb\", \"entityAudit\", \"scenarioRecipe\", \"recipeBuilder\", \"testGenerator\"];\n return order.find((s) => state.steps[s] !== \"done\") ?? null;\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["join","p","path","log","summary","YELLOW","RESET","readFile","join","tool","glob","z","inputSchema","execFile","promisify","tool","z","inputSchema","execFileAsync","join","relative","tool","z","p","path","readFile","relative","resolve","tool","z","inputSchema","ToolLoopAgent","hasToolCall","stepCountIs","tool","z","readFile","inputSchema","writeFile","mkdir","relative","resolve","tool","z","inputSchema","tool","z","path","z","tool","input","execFile","p","join","path","resolve","CYAN","RESET","editor","GREEN","DIM","SYSTEM_PROMPT","tool","z","readFile","join","p","SYSTEM_PROMPT","path","SYSTEM_PROMPT","init_prompt","readFile","writeFile","join","tool","z","glob","buildFinishTool","SYSTEM_PROMPT","init_prompt","readFile","join","init_prompt","readFile","join","tool","z","buildFinishTool","init_prompt","readFile","writeFile","join","STATE_FILE","readFile","join","p","tool","z","SYSTEM_PROMPT","existsSync","join","RESET","readFile","writeFile","join","text","p","writeFile","readFile","join","spawn","tool","z","resolve","DOCS_BASE","p","p","text","p","z","tool","readFile","join","relative","basename","glob","init_review","readFile","writeFile","join","path","STATE_FILE","readFile","writeFile","join","z","tool","path","SYSTEM_PROMPT","mkdir","writeFile","dirname","join","hasToolCall","stepCountIs","tool","ToolLoopAgent","matter","z","resultSchema","init_tools","SYSTEM_PROMPT","init_prompt","mkdir","readFile","writeFile","basename","join","tool","z","glob","SYSTEM_PROMPT","p","content","init_review","init_tools","init_prompt","p","readFile","writeFile","join","join","join","readFile","writeFile","join","path","writeFile","join","readFile","runPageFinder","runKBGenerator","runEntityAudit","runScenarioRecipe","runRecipeBuilder","runTestGenerator","config","outputDir"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.15_tsx@4.22.3_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js","../src/core/context.ts","../src/core/model.ts","../src/core/display.ts","../src/core/agent.ts","../src/core/gitignore.ts","../src/tools/bash.ts","../src/tools/glob.ts","../src/tools/grep.ts","../src/tools/list-directory.ts","../src/tools/read-file.ts","../src/tools/subagent.ts","../src/tools/write-file.ts","../src/tools/ask-user.ts","../src/tools/index.ts","../src/agents/00-pages-finder/index.ts","../src/core/notify.ts","../src/core/review.ts","../src/agents/01-kb-generator/prompt.ts","../src/agents/01-kb-generator/index.ts","../src/agents/02-entity-audit/prompt.ts","../src/agents/02-entity-audit/index.ts","../src/core/parse-entity-audit.ts","../src/agents/03-scenario-recipe/prompt.ts","../src/agents/03-scenario-recipe/index.ts","../src/agents/04-recipe-builder/state.ts","../src/agents/04-recipe-builder/entity-order.ts","../src/agents/04-recipe-builder/phases/tech-detect.ts","../src/core/detect-pkg-manager.ts","../src/core/highlight.ts","../src/agents/04-recipe-builder/recipe.ts","../src/agents/04-recipe-builder/http-client.ts","../src/agents/04-recipe-builder/phases/entity-loop.ts","../src/agents/04-recipe-builder/phases/full-validation.ts","../src/agents/04-recipe-builder/phases/submit.ts","../src/agents/04-recipe-builder/index.ts","../src/agents/05-test-generator/rubrics.ts","../src/agents/05-test-generator/review-pass.ts","../src/agents/05-test-generator/review.ts","../src/agents/05-test-generator/graph.ts","../src/agents/00b-feature-discovery/index.ts","../src/agents/05-test-generator/validation.ts","../src/agents/05-test-generator/tools.ts","../src/agents/05-test-generator/prompt.ts","../src/agents/05-test-generator/index.ts","../src/index.ts","../src/config.ts","../src/core/output.ts","../src/core/state.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ProjectContext {\n description: string;\n testingGoal: string;\n criticalFlows: string;\n pages?: Array<{ route: string; path: string; description: string }>;\n}\n\nconst CONTEXT_FILE = \".project-context.json\";\n\nexport async function saveContext(outputDir: string, ctx: ProjectContext): Promise<void> {\n await writeFile(join(outputDir, CONTEXT_FILE), JSON.stringify(ctx, null, 2), \"utf-8\");\n}\n\nexport async function loadContext(outputDir: string): Promise<ProjectContext | null> {\n try {\n const raw = await readFile(join(outputDir, CONTEXT_FILE), \"utf-8\");\n return JSON.parse(raw) as ProjectContext;\n } catch {\n return null;\n }\n}\n\nexport function formatContext(ctx: ProjectContext): string {\n let output = `## Project Context (from the user)\n\n**What this project is:** ${ctx.description}\n\n**Why they want testing:** ${ctx.testingGoal}\n\n**Critical flows to prioritize:** ${ctx.criticalFlows}\n\nUse this context to prioritize your exploration. Start with the critical flows the user mentioned, then expand to cover the rest of the application.`;\n\n if (ctx.pages?.length) {\n output += `\\n\\n## Discovered Pages (${ctx.pages.length} routes)\\n\\n`;\n output += ctx.pages\n .map((p) => `- \\`${p.route}\\` — ${p.description} (\\`${p.path}\\`)`)\n .join(\"\\n\");\n }\n\n return output;\n}\n","import { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n\nexport const DEFAULT_MODEL = \"google/gemini-3-flash-preview\";\n\nlet provider: ReturnType<typeof createOpenRouter> | null = null;\n\nfunction getProvider() {\n if (provider == null) {\n const apiKey = process.env.OPENROUTER_API_KEY;\n if (!apiKey) throw new Error(\"OPENROUTER_API_KEY is required\");\n provider = createOpenRouter({ apiKey });\n }\n return provider;\n}\n\nexport function getModel(modelId?: string) {\n return getProvider().languageModel(modelId ?? process.env.OPENROUTER_MODEL ?? DEFAULT_MODEL);\n}\n","const DIM = \"\\x1b[2m\";\nconst RESET = \"\\x1b[0m\";\nconst CYAN = \"\\x1b[36m\";\nconst GREEN = \"\\x1b[32m\";\nconst RED = \"\\x1b[31m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\nfunction formatArgs(input: Record<string, unknown>, keys: string[]): string {\n const parts: string[] = [];\n for (const key of keys) {\n if (key in input && input[key] !== undefined && input[key] !== null) {\n parts.push(`${key}=${String(input[key])}`);\n }\n }\n return parts.join(\" \");\n}\n\nfunction toolCallSummary(name: string, input: Record<string, unknown>): string {\n switch (name) {\n case \"read_file\":\n case \"read_output\": {\n const path = String(\n input.filePath ?? input.path ?? input.file_path ?? \"\",\n );\n const range = formatArgs(input, [\"offset\", \"limit\"]);\n return range ? `${path} (${range})` : path;\n }\n case \"write_file\":\n return String(input.filePath ?? input.path ?? input.file_path ?? \"\");\n case \"glob\":\n return formatArgs(input, [\"pattern\", \"path\"]);\n case \"grep\":\n return formatArgs(input, [\"query\", \"pattern\", \"path\", \"include\"]);\n case \"bash\":\n return String(input.command ?? \"\");\n case \"list_directory\":\n return formatArgs(input, [\"path\", \"depth\"]);\n case \"subagent\":\n case \"spawn_researcher\":\n return String(input.task ?? input.instruction ?? input.prompt ?? \"\");\n case \"write_test\":\n return formatArgs(input, [\"folder\", \"filename\"]);\n case \"enqueue_node\":\n return formatArgs(input, [\"id\", \"name\"]);\n case \"mark_visited\":\n return formatArgs(input, [\"files\"]);\n case \"get_coverage\":\n return formatArgs(input, [\"detail\"]);\n case \"finish\":\n return \"\";\n default: {\n const keys = Object.keys(input);\n if (keys.length === 0) return \"\";\n return keys.map((k) => `${k}=${String(input[k])}`).join(\" \");\n }\n }\n}\n\nconst SPINNER_FRAMES = [\"◒\", \"◐\", \"◓\", \"◑\"];\n\nexport interface StepInfo {\n stepNumber: number;\n maxSteps: number;\n reasoningText?: string;\n text: string;\n toolCalls: { name: string; input: Record<string, unknown> }[];\n toolErrors: { name: string; error: unknown }[];\n writtenFiles: string[];\n}\n\nexport interface ProgressStats {\n filesRead: number;\n filesWritten: number;\n}\n\nconst CLEAR_LINE = \"\\x1b[2K\\r\";\n\nexport function createStepLogger(agentId: string, maxSteps: number) {\n const stats: ProgressStats = {\n filesRead: 0,\n filesWritten: 0,\n };\n let frameIdx = 0;\n let lastSpinnerLine = false;\n\n function clearSpinner() {\n if (lastSpinnerLine) {\n process.stderr.write(CLEAR_LINE);\n lastSpinnerLine = false;\n }\n }\n\n function writeSpinner(message: string) {\n const frame = SPINNER_FRAMES[frameIdx % SPINNER_FRAMES.length];\n frameIdx++;\n process.stderr.write(`${CLEAR_LINE} ${DIM}${frame} ${message}${RESET}`);\n lastSpinnerLine = true;\n }\n\n function writePermanent(message: string) {\n clearSpinner();\n console.log(message);\n }\n\n function log(info: StepInfo) {\n const stepPrefix = `[${agentId}] ${info.stepNumber + 1}/${maxSteps}`;\n\n for (const tc of info.toolCalls) {\n const summary = toolCallSummary(tc.name, tc.input);\n\n switch (tc.name) {\n case \"read_file\":\n case \"read_output\":\n stats.filesRead++;\n writeSpinner(`${stepPrefix} — reading ${summary}`);\n break;\n\n case \"glob\":\n writeSpinner(`${stepPrefix} — glob ${summary}`);\n break;\n\n case \"grep\":\n writeSpinner(`${stepPrefix} — grep ${summary}`);\n break;\n\n case \"list_directory\":\n writeSpinner(`${stepPrefix} — listing ${summary}`);\n break;\n\n case \"bash\":\n writeSpinner(`${stepPrefix} — bash: ${summary}`);\n break;\n\n case \"write_file\": {\n stats.filesWritten++;\n const path = String(tc.input.path ?? tc.input.file_path ?? \"\");\n writePermanent(` ${GREEN}✎ write ${path}${RESET}`);\n break;\n }\n\n case \"write_test\":\n stats.filesWritten++;\n writePermanent(` ${GREEN}✎ test ${summary}${RESET}`);\n break;\n\n case \"finish\":\n writePermanent(` ${GREEN}${BOLD}✓ finish${RESET}`);\n break;\n\n case \"subagent\":\n case \"spawn_researcher\":\n writePermanent(` ${CYAN}⊕ subagent: ${summary}${RESET}`);\n break;\n\n default:\n writeSpinner(`${stepPrefix} — ${tc.name}${summary ? \" \" + summary : \"\"}`);\n }\n }\n\n for (const te of info.toolErrors) {\n writePermanent(` ${RED}✗ ${te.name}: ${te.error}${RESET}`);\n }\n\n for (const f of info.writtenFiles) {\n writePermanent(` ${GREEN}📄 wrote: ${f}${RESET}`);\n }\n }\n\n function checkpoint(message: string) {\n writePermanent(` ${YELLOW}▸ ${message}${RESET}`);\n }\n\n function summary() {\n clearSpinner();\n if (stats.filesRead > 0 || stats.filesWritten > 0) {\n console.log(` ${DIM}────────────────────────────────${RESET}`);\n console.log(\n ` ${DIM}files read: ${stats.filesRead} | files written: ${stats.filesWritten}${RESET}`,\n );\n }\n }\n\n return { log, checkpoint, summary, stats };\n}\n","import {\n type LanguageModel,\n type ToolSet,\n ToolLoopAgent,\n hasToolCall,\n stepCountIs,\n} from \"ai\";\nimport { createStepLogger, type StepInfo } from \"./display\";\nimport { getModel } from \"./model\";\n\nconst FALLBACK_MODELS = [\n \"moonshotai/kimi-k2.6\",\n \"deepseek/deepseek-v4-pro\",\n \"openai/gpt-5.4-nano\",\n];\n\nconst RETRIES_BEFORE_FALLBACK = 3;\nconst STEP_TIMEOUT_MS = 120_000;\n\nexport interface AgentConfig {\n id: string;\n systemPrompt: string;\n tools: ToolSet | ((heartbeat: () => void) => ToolSet | Promise<ToolSet>);\n model: LanguageModel;\n maxSteps: number;\n temperature?: number;\n stepTimeoutMs?: number;\n onStepFinish?: (info: StepInfo) => void;\n}\n\nexport interface AgentContext {\n projectRoot: string;\n outputDir: string;\n}\n\nexport interface AgentResult {\n success: boolean;\n paused?: boolean;\n artifacts: string[];\n summary: string;\n}\n\nexport function buildDefaultStepLogger(agentId: string, maxSteps: number) {\n const logger = createStepLogger(agentId, maxSteps);\n\n return {\n logger,\n onStepFinish: (info: StepInfo) => {\n logger.log(info);\n },\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction buildStepHandler(config: AgentConfig) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (step: any) => {\n if (!config.onStepFinish) return;\n\n const toolErrors: { name: string; error: unknown }[] = [];\n const writtenFiles: string[] = [];\n\n for (const part of step.content) {\n if (part.type === \"tool-error\") {\n toolErrors.push({ name: part.toolName, error: part.error });\n }\n if (part.type === \"tool-result\" && part.toolName === \"write_file\") {\n const output = part.output;\n if (typeof output === \"object\" && output !== null && \"path\" in output) {\n writtenFiles.push(String((output as Record<string, unknown>).path));\n }\n }\n }\n\n config.onStepFinish({\n stepNumber: step.stepNumber,\n maxSteps: config.maxSteps,\n reasoningText: step.reasoningText ?? undefined,\n text: step.text,\n toolCalls: step.toolCalls.map((tc: { toolName: string; input: unknown }) => ({\n name: tc.toolName,\n input: tc.input as Record<string, unknown>,\n })),\n toolErrors,\n writtenFiles,\n });\n };\n}\n\nexport async function runAgent<T>(\n config: AgentConfig,\n prompt: string,\n extractResult: () => T | undefined,\n): Promise<T | undefined> {\n const stepTimeout = config.stepTimeoutMs ?? STEP_TIMEOUT_MS;\n const modelsToTry = [config.model, ...FALLBACK_MODELS.map((id) => getModel(id))];\n\n const YELLOW = \"\\x1b[33m\";\n const RESET = \"\\x1b[0m\";\n\n for (let modelIdx = 0; modelIdx < modelsToTry.length; modelIdx++) {\n const model = modelsToTry[modelIdx]!;\n\n for (let retry = 0; retry < RETRIES_BEFORE_FALLBACK; retry++) {\n const heartbeat = () => {};\n const tools = typeof config.tools === \"function\"\n ? await config.tools(heartbeat)\n : config.tools;\n\n const agent = new ToolLoopAgent({\n model,\n instructions: config.systemPrompt,\n tools,\n temperature: config.temperature,\n stopWhen: [stepCountIs(config.maxSteps), hasToolCall(\"finish\")],\n onStepFinish: buildStepHandler(config),\n });\n\n try {\n await agent.generate({\n messages: [{ role: \"user\", content: prompt }],\n timeout: { stepMs: stepTimeout },\n });\n\n return extractResult();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const isTimeout = msg.includes(\"timed out\") || msg.includes(\"timeout\") || msg.includes(\"abort\");\n\n if (!isTimeout) throw err;\n\n console.log(` ${YELLOW}[${config.id}] step timed out after ${stepTimeout / 1000}s${RESET}`);\n\n if (retry < RETRIES_BEFORE_FALLBACK - 1) {\n console.log(\n ` ${YELLOW}[${config.id}] retrying (${retry + 1}/${RETRIES_BEFORE_FALLBACK})...${RESET}`,\n );\n continue;\n }\n\n if (modelIdx < modelsToTry.length - 1) {\n const nextModel = FALLBACK_MODELS[modelIdx];\n console.log(\n ` ${YELLOW}[${config.id}] ${RETRIES_BEFORE_FALLBACK} timeouts, switching to ${nextModel}${RESET}`,\n );\n break;\n }\n\n throw err;\n }\n }\n }\n\n return extractResult();\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { glob } from \"glob\";\n\nexport async function loadGitignorePatterns(\n projectRoot: string,\n): Promise<string[]> {\n const patterns: string[] = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.git/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/.nuxt/**\",\n \"**/coverage/**\",\n \"**/.turbo/**\",\n \"**/__pycache__/**\",\n \"**/.venv/**\",\n \"**/venv/**\",\n \"**/.cache/**\",\n \"**/.parcel-cache/**\",\n ];\n\n const matches = await glob(\"**/.gitignore\", { cwd: projectRoot, dot: true });\n for (const match of matches) {\n const fullPath = join(projectRoot, match);\n try {\n const content = await readFile(fullPath, \"utf-8\");\n const prefix = relative(projectRoot, join(projectRoot, match, \"..\"));\n const parsed = parseGitignore(content, prefix);\n patterns.push(...parsed);\n } catch (err) {\n // unreadable gitignore, skip\n console.error(`there was an error trying to read the gitignore on ${fullPath}. skipping.`, err)\n }\n }\n\n return [...new Set(patterns)];\n}\n\nexport function parseGitignore(content: string, prefix = \"\"): string[] {\n return content\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"))\n .map((line) => gitignoreToGlob(line, prefix));\n}\n\nfunction gitignoreToGlob(pattern: string, prefix: string): string {\n let negated = false;\n if (pattern.startsWith(\"!\")) {\n negated = true;\n pattern = pattern.slice(1);\n }\n\n if (pattern.startsWith(\"/\")) {\n pattern = pattern.slice(1);\n if (prefix) pattern = `${prefix}/${pattern}`;\n } else if (!pattern.includes(\"/\")) {\n pattern = prefix ? `${prefix}/**/${pattern}` : `**/${pattern}`;\n } else {\n if (prefix) pattern = `${prefix}/${pattern}`;\n }\n\n if (pattern.endsWith(\"/\")) {\n pattern = `${pattern}**`;\n }\n\n return negated ? `!${pattern}` : pattern;\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CHAINING_OPERATORS = /;|&&|\\|\\||`|\\$\\(|>>|<<|&\\s*$/;\n\nconst DEFAULT_ALLOWED = new Set([\n \"git\", \"wc\", \"sort\", \"head\", \"tail\", \"cat\", \"ls\", \"find\", \"diff\", \"echo\",\n]);\n\nconst TIMEOUT_MS = 30_000;\nconst MAX_OUTPUT_BYTES = 1024 * 512;\n\nconst inputSchema = z.object({\n command: z.string().describe(\"Shell command to execute\"),\n});\n\ninterface BashResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nexport function validateCommand(\n command: string,\n allowed: Set<string>,\n): string | undefined {\n const trimmed = command.trim();\n if (trimmed.length === 0) return \"Empty command\";\n\n if (CHAINING_OPERATORS.test(trimmed)) {\n return \"Command chaining (;, &&, ||), subshells, and redirects are not allowed. Use pipes (|) instead.\";\n }\n\n const segments = trimmed.split(/\\s*\\|\\s*/);\n for (const segment of segments) {\n const binary = segment.trim().split(/\\s+/)[0];\n if (binary == null || !allowed.has(binary)) {\n return `Command \"${binary ?? \"\"}\" is not allowed. Allowed: ${[...allowed].join(\", \")}`;\n }\n }\n\n return undefined;\n}\n\nexport function buildBashTool(\n workingDirectory: string,\n allowedCommands?: Set<string>,\n) {\n const allowed = allowedCommands ?? DEFAULT_ALLOWED;\n\n return tool({\n description:\n \"Execute a shell command. Primarily for git, ls, find, and basic unix utilities. \" +\n \"Pipes allowed; chaining (;, &&, ||) is not.\",\n inputSchema,\n execute: async (input): Promise<BashResult> => {\n const error = validateCommand(input.command, allowed);\n if (error != null) {\n return { exitCode: 1, stdout: \"\", stderr: error };\n }\n\n try {\n const { stdout, stderr } = await execFileAsync(\n \"sh\",\n [\"-c\", input.command],\n {\n cwd: workingDirectory,\n maxBuffer: MAX_OUTPUT_BYTES,\n timeout: TIMEOUT_MS,\n },\n );\n return {\n exitCode: 0,\n stdout: stdout.trimEnd(),\n stderr: stderr.trimEnd(),\n };\n } catch (err) {\n const execErr = err as {\n code?: number;\n stdout?: string;\n stderr?: string;\n killed?: boolean;\n };\n\n if (execErr.killed) {\n return {\n exitCode: 1,\n stdout: \"\",\n stderr: `Command timed out after ${TIMEOUT_MS / 1000}s`,\n };\n }\n\n return {\n exitCode: typeof execErr.code === \"number\" ? execErr.code : 1,\n stdout: execErr.stdout?.trimEnd() ?? \"\",\n stderr: execErr.stderr?.trimEnd() ?? \"\",\n };\n }\n },\n });\n}\n","import { tool } from \"ai\";\nimport { glob } from \"glob\";\nimport { z } from \"zod\";\n\nconst inputSchema = z.object({\n pattern: z.string().describe(\"Glob pattern to match files (e.g. '**/*.ts', 'src/**/*.py')\"),\n cwd: z.string().optional().describe(\"Directory to search in. Defaults to working directory.\"),\n});\n\nconst DEFAULT_IGNORE = [\"**/node_modules/**\", \"**/dist/**\", \"**/.git/**\"];\n\nexport interface GlobResult {\n matches: string[];\n count: number;\n error?: string;\n}\n\nexport async function executeGlob(\n pattern: string,\n cwd: string,\n ignorePatterns: string[] = DEFAULT_IGNORE,\n): Promise<GlobResult> {\n try {\n const matches = await glob(pattern, {\n cwd,\n nodir: true,\n ignore: ignorePatterns,\n });\n return { matches, count: matches.length };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Glob failed: ${message}`, matches: [], count: 0 };\n }\n}\n\nexport function buildGlobTool(workingDirectory: string, ignorePatterns?: string[]) {\n const ignore = ignorePatterns ?? DEFAULT_IGNORE;\n\n return tool({\n description:\n \"Find files matching a glob pattern. Returns paths relative to working directory.\",\n inputSchema,\n execute: (input) => executeGlob(input.pattern, input.cwd ?? workingDirectory, ignore),\n });\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst execFileAsync = promisify(execFile);\n\nconst inputSchema = z.object({\n pattern: z.string().describe(\"Regex pattern to search for in file contents\"),\n glob: z.string().optional().describe(\"Glob to filter files (e.g. '*.ts')\"),\n path: z.string().optional().describe(\"File or directory to search in\"),\n});\n\nexport function buildGrepTool(workingDirectory: string) {\n return tool({\n description:\n \"Search file contents with ripgrep. Returns matching lines with file paths and line numbers.\",\n inputSchema,\n execute: async (input) => {\n const args = [\n \"--no-heading\",\n \"--line-number\",\n \"--max-count=50\",\n \"--glob=!node_modules\",\n \"--glob=!dist\",\n \"--glob=!.git\",\n ];\n\n if (input.glob != null) {\n args.push(`--glob=${input.glob}`);\n }\n\n args.push(input.pattern);\n args.push(input.path ?? workingDirectory);\n\n try {\n const { stdout } = await execFileAsync(\"rg\", args, {\n cwd: workingDirectory,\n maxBuffer: 1024 * 1024,\n });\n\n const lines = stdout.trim().split(\"\\n\").filter(Boolean);\n return { matches: lines, count: lines.length };\n } catch (error) {\n const execError = error as { code?: number; stdout?: string };\n if (execError.code === 1) {\n return { matches: [], count: 0 };\n }\n const message = error instanceof Error ? error.message : String(error);\n return { error: `Grep failed: ${message}`, matches: [], count: 0 };\n }\n },\n });\n}\n","import { readdir } from \"node:fs/promises\";\nimport { stat } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { minimatch } from \"minimatch\";\nimport { loadGitignorePatterns } from \"../core/gitignore\";\n\n\ninterface TreeEntry {\n name: string;\n type: \"file\" | \"dir\";\n children?: TreeEntry[];\n}\n\nfunction buildMatcher(patterns: string[]): (path: string) => boolean {\n const positive = patterns.filter((p) => !p.startsWith(\"!\"));\n const negative = patterns.filter((p) => p.startsWith(\"!\")).map((p) => p.slice(1));\n\n return (path: string) => {\n const ignored = positive.some((p) => minimatch(path, p, { dot: true }));\n if (!ignored) return false;\n const restored = negative.some((p) => minimatch(path, p, { dot: true }));\n return !restored;\n };\n}\n\nasync function buildTree(\n dirPath: string,\n maxDepth: number,\n currentDepth: number,\n isIgnored?: (relativePath: string) => boolean,\n relativeBase?: string,\n): Promise<TreeEntry[]> {\n if (currentDepth >= maxDepth) return [];\n\n let rawEntries: string[];\n try {\n rawEntries = await readdir(dirPath);\n } catch {\n return [];\n }\n\n const withTypes: { name: string; isDir: boolean }[] = [];\n for (const name of rawEntries) {\n try {\n const s = await stat(join(dirPath, name));\n withTypes.push({ name, isDir: s.isDirectory() });\n } catch {\n withTypes.push({ name, isDir: false });\n }\n }\n\n withTypes.sort((a, b) => {\n if (a.isDir && !b.isDir) return -1;\n if (!a.isDir && b.isDir) return 1;\n return a.name.localeCompare(b.name);\n });\n\n const result: TreeEntry[] = [];\n\n for (const entry of withTypes) {\n const entryRelPath = relativeBase\n ? `${relativeBase}/${entry.name}`\n : entry.name;\n\n if (isIgnored) {\n const checkPath = entry.isDir ? `${entryRelPath}/` : entryRelPath;\n if (isIgnored(checkPath) || isIgnored(entryRelPath)) continue;\n }\n\n if (entry.isDir) {\n const children = await buildTree(\n join(dirPath, entry.name),\n maxDepth,\n currentDepth + 1,\n isIgnored,\n entryRelPath,\n );\n result.push({ name: entry.name, type: \"dir\", children });\n } else {\n result.push({ name: entry.name, type: \"file\" });\n }\n }\n\n return result;\n}\n\nfunction renderTree(entries: TreeEntry[], prefix = \"\"): string {\n const lines: string[] = [];\n\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i]!;\n const isLast = i === entries.length - 1;\n const connector = isLast ? \"└── \" : \"├── \";\n const childPrefix = isLast ? \" \" : \"│ \";\n\n if (entry.type === \"dir\") {\n const suffix = entry.children?.length ? \"/\" : \"/ (empty)\";\n lines.push(`${prefix}${connector}${entry.name}${suffix}`);\n if (entry.children?.length) {\n lines.push(renderTree(entry.children, prefix + childPrefix));\n }\n } else {\n lines.push(`${prefix}${connector}${entry.name}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport async function buildListDirectoryTool(\n workingDirectory: string,\n) {\n const seen = new Set<string>();\n const patterns = await loadGitignorePatterns(workingDirectory);\n const isIgnored = buildMatcher(patterns);\n\n return tool({\n description:\n \"List directory structure as a tree. Use this for an overview of the project layout. \" +\n \"Start at the root (path='.') with depth 3, then increase depth or narrow path if needed. \" +\n \"Do NOT call this on every subdirectory — use glob to find specific files instead. \" +\n \"Returns cached result if the same path+depth was already requested.\",\n inputSchema: z.object({\n path: z\n .string()\n .default(\".\")\n .describe(\"Directory path relative to project root. Defaults to root.\"),\n depth: z\n .number()\n .min(1)\n .max(15)\n .default(10)\n .describe(\"Max depth to traverse (1-15). Default 10.\"),\n gitignore: z.boolean()\n .describe(\"Whether to respect the gitignore or to ignore it. true will respect it. false \" +\n \"will ignore it. Default true\")\n .default(true)\n }),\n execute: async (input) => {\n const cacheKey = `${input.path}:${input.depth}`;\n if (seen.has(cacheKey)) {\n return {\n error: `Already listed ${input.path} at depth ${input.depth}. Use glob to find specific files, or read_file to read a known file.`,\n };\n }\n seen.add(cacheKey);\n\n const targetDir = input.path === \".\"\n ? workingDirectory\n : join(workingDirectory, input.path);\n\n try {\n const s = await stat(targetDir);\n if (!s.isDirectory()) {\n return { error: `Not a directory: ${input.path}` };\n }\n } catch {\n return { error: `Directory not found: ${input.path}` };\n }\n\n const relBase = targetDir === workingDirectory\n ? \"\"\n : relative(workingDirectory, targetDir);\n const maybeIgnored = input.gitignore ? isIgnored : undefined;\n\n const tree = await buildTree(targetDir, input.depth, 0, maybeIgnored, relBase || undefined);\n const rendered = renderTree(tree);\n const relPath = relative(workingDirectory, targetDir) || \".\";\n\n return {\n path: relPath,\n depth: input.depth,\n tree: `${relPath}/\\n${rendered}`,\n };\n },\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst MAX_LINES = 2000;\n\nconst inputSchema = z.object({\n filePath: z.string().describe(\"Path to the file (absolute or relative to working directory)\"),\n offset: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe(\"Line number to start reading from (0-based)\"),\n limit: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe(\"Maximum number of lines to read\"),\n});\n\nexport interface ReadFileResult {\n path?: string;\n content?: string;\n totalLines?: number;\n linesShown?: number;\n startLine?: number;\n endLine?: number;\n error?: string;\n}\n\nexport function resolveSandboxedPath(\n workingDirectory: string,\n filePath: string,\n): { absolutePath: string; relativePath: string } | { error: string } {\n const absolutePath = resolve(workingDirectory, filePath);\n const relativePath = relative(workingDirectory, absolutePath);\n\n if (relativePath.startsWith(\"..\")) {\n return { error: \"Cannot read files outside the working directory\" };\n }\n\n return { absolutePath, relativePath };\n}\n\nexport function sliceLines(\n content: string,\n offset: number,\n limit: number,\n): { numbered: string; totalLines: number; linesShown: number; startLine: number; endLine: number } {\n const allLines = content.split(\"\\n\");\n const lines = allLines.slice(offset, offset + limit);\n const numbered = lines\n .map((line, i) => `${offset + i + 1}\\t${line}`)\n .join(\"\\n\");\n\n return {\n numbered,\n totalLines: allLines.length,\n linesShown: lines.length,\n startLine: offset + 1,\n endLine: offset + lines.length,\n };\n}\n\nexport async function executeReadFile(\n workingDirectory: string,\n filePath: string,\n offset?: number,\n limit?: number,\n): Promise<ReadFileResult> {\n const resolved = resolveSandboxedPath(workingDirectory, filePath);\n if (\"error\" in resolved) return resolved;\n\n try {\n const content = await readFile(resolved.absolutePath, \"utf-8\");\n const sliced = sliceLines(content, offset ?? 0, limit ?? MAX_LINES);\n\n return {\n path: resolved.relativePath,\n content: sliced.numbered,\n totalLines: sliced.totalLines,\n linesShown: sliced.linesShown,\n startLine: sliced.startLine,\n endLine: sliced.endLine,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to read file: ${message}` };\n }\n}\n\nexport function buildReadFileTool(workingDirectory: string) {\n return tool({\n description:\n \"Read file contents with line numbers. Use offset and limit for large files.\",\n inputSchema,\n execute: (input) =>\n executeReadFile(workingDirectory, input.filePath, input.offset, input.limit),\n });\n}\n","import {\n type LanguageModel,\n ToolLoopAgent,\n hasToolCall,\n stepCountIs,\n tool,\n} from \"ai\";\nimport { z } from \"zod\";\nimport { buildBashTool } from \"./bash\";\nimport { buildGlobTool } from \"./glob\";\nimport { buildGrepTool } from \"./grep\";\nimport { buildReadFileTool } from \"./read-file\";\n\nconst inputSchema = z.object({\n instruction: z\n .string()\n .describe(\"Focused task for the subagent. Be specific about files and patterns to investigate.\"),\n});\n\nconst resultSchema = z.object({\n findings: z.string().describe(\"Summary of what was found\"),\n});\n\ntype SubagentResult = z.infer<typeof resultSchema>;\n\nconst SYSTEM_PROMPT = `You are a code research assistant. You have tools to explore a codebase: bash (shell commands, mainly git), glob (find files), grep (search content), and read_file (read files).\n\nFollow the instruction you're given. Explore the codebase, then call finish with a summary of your findings.\n\nBe thorough but focused - only investigate what's relevant to your instruction.`;\n\nfunction buildSubagentTools(workingDirectory: string, onFileRead?: (path: string) => void) {\n const baseReadFile = buildReadFileTool(workingDirectory);\n const readFile = onFileRead\n ? tool({\n description: baseReadFile.description,\n inputSchema: baseReadFile.inputSchema,\n execute: async (input, options) => {\n const filePath = (input as { filePath?: string; path?: string; file_path?: string }).filePath\n ?? (input as { path?: string }).path\n ?? (input as { file_path?: string }).file_path\n ?? \"\";\n onFileRead(filePath);\n return baseReadFile.execute!(input, options);\n },\n })\n : baseReadFile;\n\n return {\n bash: buildBashTool(workingDirectory),\n glob: buildGlobTool(workingDirectory),\n grep: buildGrepTool(workingDirectory),\n read_file: readFile,\n };\n}\n\nexport function buildSubagentTool(\n model: LanguageModel,\n workingDirectory: string,\n onHeartbeat?: () => void,\n onFileRead?: (path: string) => void,\n) {\n return tool({\n description:\n \"Spawn a subagent to research a specific part of the codebase. \" +\n \"Each subagent has glob, grep, read_file, and bash tools. \" +\n \"Give a focused, specific instruction.\",\n inputSchema,\n execute: async (input) => {\n let result: SubagentResult | undefined;\n\n const subagent = new ToolLoopAgent({\n model,\n instructions: SYSTEM_PROMPT,\n tools: {\n ...buildSubagentTools(workingDirectory, onFileRead),\n finish: tool({\n description: \"Call when you have completed your research.\",\n inputSchema: resultSchema,\n execute: async (output) => {\n result = output;\n },\n }),\n },\n stopWhen: [stepCountIs(15), hasToolCall(\"finish\")],\n onStepFinish: () => { onHeartbeat?.(); },\n });\n\n try {\n await subagent.generate({\n messages: [{ role: \"user\", content: input.instruction }],\n });\n return { findings: result?.findings ?? \"Subagent did not produce findings\" };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { findings: `Subagent error: ${message}` };\n }\n },\n });\n}\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nconst inputSchema = z.object({\n filePath: z.string().describe(\"Path to write (absolute or relative to output directory)\"),\n content: z.string().describe(\"File content to write\"),\n});\n\nexport interface WriteFileResult {\n path?: string;\n bytesWritten?: number;\n error?: string;\n}\n\nexport async function executeWriteFile(\n outputDirectory: string,\n filePath: string,\n content: string,\n): Promise<WriteFileResult> {\n const cleaned = filePath.replace(/^autonoma\\//, \"\");\n const absolutePath = resolve(outputDirectory, cleaned);\n const relativePath = relative(outputDirectory, absolutePath);\n\n if (relativePath.startsWith(\"..\")) {\n return { error: \"Cannot write files outside the output directory\" };\n }\n\n try {\n await mkdir(dirname(absolutePath), { recursive: true });\n await writeFile(absolutePath, content, \"utf-8\");\n return { path: relativePath, bytesWritten: content.length };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to write file: ${message}` };\n }\n}\n\nexport function buildWriteFileTool(outputDirectory: string) {\n return tool({\n description:\n \"Write content to a file in the output directory. Creates parent directories as needed.\",\n inputSchema,\n execute: (input) => executeWriteFile(outputDirectory, input.filePath, input.content),\n });\n}\n","import * as p from \"@clack/prompts\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nexport function buildAskUserTool() {\n return tool({\n description:\n \"Ask the user a question ONLY when the answer is truly unknowable from the codebase. \" +\n \"Valid reasons: untyped JSON/JSONB field schemas, business rules not in code, config values not in source. \" +\n \"NEVER ask about: field names (read the schema), field types (read the ORM model), \" +\n \"enum values (read the code), relationships (read foreign keys), numeric values (read the seed data or defaults). \" +\n \"If you can find it by reading a file, DO NOT ask — read the file instead.\",\n inputSchema: z.object({\n question: z.string().describe(\n \"A clear, plain-language question. State exactly what you need to know and why you can't find it in code. \" +\n \"BAD: 'What are the decimal values for checking_balance?' — GOOD: 'Your Account model has a metadata JSON column with no type definition. What fields go inside it?'\",\n ),\n }),\n execute: async (input) => {\n const answer = await p.text({ message: input.question });\n if (p.isCancel(answer)) return { answer: \"User skipped this question\" };\n return { answer: answer as string };\n },\n });\n}\n","import type { LanguageModel } from \"ai\";\nimport { loadGitignorePatterns } from \"../core/gitignore\";\nimport { buildBashTool } from \"./bash\";\nimport { buildGlobTool } from \"./glob\";\nimport { buildGrepTool } from \"./grep\";\nimport { buildListDirectoryTool } from \"./list-directory\";\nimport { buildReadFileTool } from \"./read-file\";\nimport { buildSubagentTool } from \"./subagent\";\nimport { buildWriteFileTool } from \"./write-file\";\n\nexport async function buildCodebaseTools(\n model: LanguageModel,\n projectRoot: string,\n outputDir: string,\n onHeartbeat?: () => void,\n onFileRead?: (path: string) => void,\n) {\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n\n return {\n read_file: buildReadFileTool(projectRoot),\n read_output: buildReadFileTool(outputDir),\n write_file: buildWriteFileTool(outputDir),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n grep: buildGrepTool(projectRoot),\n bash: buildBashTool(projectRoot),\n list_directory: await buildListDirectoryTool(projectRoot),\n subagent: buildSubagentTool(model, projectRoot, onHeartbeat, onFileRead),\n };\n}\n\nexport {\n buildBashTool,\n buildGlobTool,\n buildGrepTool,\n buildListDirectoryTool,\n buildReadFileTool,\n buildSubagentTool,\n buildWriteFileTool,\n};\n\nexport { buildAskUserTool } from \"./ask-user\";\n","import {type AgentResult, buildDefaultStepLogger, runAgent} from \"../../core/agent.ts\";\nimport {getModel} from \"../../core/model.ts\";\nimport {buildCodebaseTools} from \"../../tools\";\nimport * as path from \"node:path\";\nimport {z} from \"zod\"\nimport {existsSync} from \"fs\"\nimport {tool} from \"ai\";\n\nexport interface PageFinderGeneratorInput {\n projectRoot: string;\n modelId?: string;\n nonInteractive?: boolean;\n outputDir: string\n extraMessage?: string\n}\n\nconst Page = z.object({\n route: z.string().min(1),\n path: z.string().min(1),\n description: z.string().min(10)\n})\ntype Page = z.infer<typeof Page>\n\nclass PageCollector {\n // the key is the path\n readonly pages = new Map<string, Page>()\n\n addPage(page: Page): void {\n if (this.pages.has(page.path)) {\n console.warn(`page with path ${page.path} was already set. overwritting`)\n }\n this.pages.set(page.path, page)\n }\n\n viewPages(): string {\n return Array.from(this.pages)\n .sort(([aKey, aValue], [bKey, bValue]) => aValue.path.localeCompare(bValue.path))\n .join(\"\\n\")\n }\n\n static from(obj: unknown): Page | Error {\n const result = Page.safeParse(obj);\n if (!result.success) return result.error\n\n const data = result.data\n\n const foundPath = path.resolve(data.path)\n if (!existsSync(foundPath)) {\n return new Error(`resolved path ${foundPath} from returned path ${data.path} didn't exist`)\n }\n\n return data\n }\n}\n\nexport async function runPageFinder(input: PageFinderGeneratorInput): Promise<Map<string, Page>> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n const pageCollector = new PageCollector();\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"kb\", 150);\n\n let prompt = `You need to run the search on this directory ${input.projectRoot}.`;\n\n if (input.extraMessage != null) {\n prompt += `\\n${input.extraMessage}`\n }\n\n const agentConfig = {\n id: \"pages-finder\",\n systemPrompt: \"You are an agent in charge of finding all the pages in a codebase. You have a set of tools for \" +\n \"exploring the codebase and you're encouraged to use them extensively. Once you find a page, call the add_page tool.\\n\\n\" +\n \"The objective is to capture 100% of all the pages on the codebase. A page is a top-level route that renders a distinct view.\\n\\n\" +\n \"Start by understanding which technologies and frameworks the project uses — read config files, package manifests, \" +\n \"and project structure. Then use glob, grep, and list_directory to find all route/page definitions based on what you discover.\\n\\n\" +\n \"Ignore storybooks, docs, and test files. Focus on pages of the main application.\\n\\n\" +\n \"For monorepos: identify which package/app is the main frontend application and focus your search there.\\n\\n\" +\n \"Consider that list_directory has a default depth of 10 and you WON'T SEE MORE CHILDREN. \" +\n \"If you do list_directory, drill down to validate there are no more levels.\",\n model,\n maxSteps: 150,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n add_page: tool({\n description: \"use this tool to add a page that you found\",\n inputSchema: Page,\n execute: input => {\n const pageOrError = PageCollector.from(input)\n if (pageOrError instanceof Error) {\n return pageOrError.message\n }\n\n pageCollector.addPage(pageOrError)\n\n return `page ${JSON.stringify(input)} added`\n }\n }),\n view_pages: tool({\n description: \"use this tool to view all the pages that you already added\",\n inputSchema: z.object(),\n execute: () => pageCollector.viewPages()\n })\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n return pageCollector.pages;\n}\n","import { platform } from \"node:os\";\nimport { execFile } from \"node:child_process\";\n\nexport function notify(title: string, message: string): void {\n process.stderr.write(\"\\x07\");\n\n const os = platform();\n if (os === \"darwin\") {\n execFile(\n \"osascript\",\n [\"-e\", `display notification \"${message.replace(/\"/g, '\\\\\"')}\" with title \"${title.replace(/\"/g, '\\\\\"')}\"`],\n () => {},\n );\n } else if (os === \"linux\") {\n execFile(\"notify-send\", [title, message], () => {});\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { access } from \"node:fs/promises\";\nimport { join, isAbsolute } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport which from \"which\";\nimport type { AgentResult } from \"./agent\";\nimport { notify } from \"./notify\";\n\nconst DIM = \"\\x1b[2m\";\nconst CYAN = \"\\x1b[36m\";\nconst GREEN = \"\\x1b[32m\";\nconst RESET = \"\\x1b[0m\";\n\nexport interface ReviewLoopOptions {\n agentId: string;\n outputDir: string;\n nonInteractive?: boolean;\n onFeedback: (feedback: string) => Promise<AgentResult | undefined>;\n reviewGuidance?: string;\n showPreview?: boolean;\n}\n\nfunction resolvePath(artifact: string, outputDir: string): string {\n if (isAbsolute(artifact)) return artifact;\n return join(outputDir, artifact);\n}\n\ninterface EditorOption {\n command: string;\n label: string;\n args: (files: string[]) => string[];\n}\n\nconst EDITORS: EditorOption[] = [\n { command: \"cursor\", label: \"Cursor\", args: (f) => f },\n { command: \"code\", label: \"VS Code\", args: (f) => f },\n { command: \"zed\", label: \"Zed\", args: (f) => f },\n { command: \"nano\", label: \"nano\", args: (f) => [f[0]!] },\n { command: \"vim\", label: \"vim\", args: (f) => [f[0]!] },\n];\n\nlet cachedEditors: EditorOption[] | null = null;\n\nasync function detectEditors(): Promise<EditorOption[]> {\n if (cachedEditors) return cachedEditors;\n const available: EditorOption[] = [];\n for (const editor of EDITORS) {\n const path = await which(editor.command, { nothrow: true });\n if (path) available.push(editor);\n }\n cachedEditors = available;\n return available;\n}\n\nlet preferredEditor: string | null = null;\n\nasync function launchEditor(editor: EditorOption, files: string[]): Promise<void> {\n const args = editor.args(files);\n const proc = spawn(editor.command, args, { stdio: \"inherit\" });\n if ([\"nano\", \"vim\"].includes(editor.command)) {\n await new Promise<void>((resolve, reject) => {\n proc.on(\"close\", () => resolve());\n proc.on(\"error\", reject);\n });\n }\n}\n\nasync function openInEditor(files: string[]): Promise<void> {\n const editors = await detectEditors();\n if (editors.length === 0) {\n p.log.warn(\"No editors found. Review the files manually:\");\n for (const f of files) console.log(` ${CYAN}${f}${RESET}`);\n return;\n }\n\n if (preferredEditor) {\n const editor = editors.find((e) => e.command === preferredEditor);\n if (editor) {\n const open = await p.confirm({\n message: `Open in ${editor.label}?`,\n });\n if (!p.isCancel(open) && open) {\n await launchEditor(editor, files);\n }\n return;\n }\n }\n\n const options = editors.map((e) => ({\n value: e.command,\n label: e.label,\n }));\n\n const selected = await p.select({\n message: \"Open output files for review?\",\n options: [\n ...options,\n { value: \"skip\", label: \"No, skip — I'll review later\" },\n ],\n });\n\n if (p.isCancel(selected) || selected === \"skip\") return;\n\n const editor = editors.find((e) => e.command === selected)!;\n\n const remember = await p.select({\n message: `Use ${editor.label} for all future reviews?`,\n options: [\n { value: \"always\", label: `Yes, always use ${editor.label}` },\n { value: \"ask\", label: \"No, ask me each time\" },\n ],\n });\n\n if (!p.isCancel(remember) && remember === \"always\") {\n preferredEditor = editor.command;\n }\n\n await launchEditor(editor, files);\n}\n\nasync function showResults(\n result: AgentResult,\n options: ReviewLoopOptions,\n): Promise<void> {\n console.log(\"\");\n console.log(` ${GREEN}[${options.agentId}] Step complete.${RESET}`);\n\n if (result.artifacts.length === 0) {\n const knownFiles = [\"AUTONOMA.md\", \"entity-audit.md\", \"scenarios.md\"];\n for (const f of knownFiles) {\n const fullPath = join(options.outputDir, f);\n try {\n await access(fullPath);\n result.artifacts.push(f);\n } catch {}\n }\n }\n\n const resolvedPaths: string[] = [];\n if (result.artifacts.length > 0) {\n console.log(` ${DIM}Output files:${RESET}`);\n for (const a of result.artifacts) {\n const fullPath = resolvePath(a, options.outputDir);\n resolvedPaths.push(fullPath);\n console.log(` ${CYAN}${fullPath}${RESET}`);\n }\n }\n if (result.summary) {\n console.log(` ${result.summary}`);\n }\n console.log(\"\");\n\n if (options.reviewGuidance) {\n p.note(options.reviewGuidance, \"What to check\");\n }\n\n const showPreview = options.showPreview !== false;\n if (showPreview && resolvedPaths.length > 0 && !options.nonInteractive) {\n notify(\"Autonoma\", `${options.agentId} step complete — review needed`);\n await openInEditor(resolvedPaths);\n }\n}\n\nexport async function reviewLoop(\n result: AgentResult | undefined,\n options: ReviewLoopOptions,\n): Promise<AgentResult | undefined> {\n if (!result?.success) return result;\n\n await showResults(result, options);\n\n if (options.nonInteractive) return result;\n\n while (true) {\n const input = await p.text({\n message: \"Review the output. Press Enter to approve, or type feedback for the agent.\",\n placeholder: \"Looks good (Enter to approve)\",\n defaultValue: \"\",\n });\n\n if (p.isCancel(input)) {\n p.log.warn(\"Cancelled.\");\n return result;\n }\n\n const feedback = (input as string).trim();\n if (feedback === \"\") {\n p.log.success(\"Approved — moving on.\");\n return result;\n }\n\n p.log.info(`Sending feedback to ${options.agentId}...`);\n console.log(\"\");\n\n const revised = await options.onFeedback(feedback);\n if (revised) {\n result = revised;\n }\n\n await showResults(result, options);\n }\n}\n","export const SYSTEM_PROMPT = `You are a knowledge base generator for E2E test planning. You analyze a frontend codebase and produce a structured guide to EVERY page, flow, and interaction. You must be EXHAUSTIVE — missing a page means missing test coverage.\n\n## Your output\n\nA file called AUTONOMA.md with YAML frontmatter\n\n## How to analyze the codebase — MANDATORY PHASES\n\n### Phase 1: Technology discovery\n1. Explore the project structure to understand the tech stack, framework, and routing approach.\n2. Read project configuration files and documentation to orient yourself.\n3. Identify the routing pattern — how pages/routes are defined in this specific project.\n4. Read the main layout and navigation components.\n\nYou have full access to the codebase. Use your tools (list_directory, glob, grep, read_file) to explore freely. Every project is different — discover the patterns rather than assuming them.\n\n### Phase 2: EXHAUSTIVE page discovery (HARD GATE)\nThis is the critical step. You must find EVERY page/route, not a sample.\n\n1. Based on the routing pattern you discovered in Phase 1, use glob and grep to find ALL page/route definitions.\n2. For EACH page file found, read it. No exceptions. Every single one.\n3. Build a complete route map. Count them.\n\nHARD GATE: Before proceeding to Phase 3, verify:\n- You have read every page/route file in the project\n- Your route count matches what your search returned\n- If you found fewer pages than expected, GO BACK and search harder\n\n### Phase 3: Deep exploration of each page\nFor EACH page/route (you already read them all in Phase 2):\n1. Identify ALL interactive elements: forms, tables, modals, tabs, dropdowns, buttons\n2. Find all API calls and data fetching patterns\n3. Find sub-components that render on this page — read them too\n4. Note navigation links to other pages\n5. Identify dynamic routes and what parameters they take\n\nUse subagents to parallelize: you can spawn one subagent per page/area to read its component tree in parallel.\n\n### Phase 4: Core flow identification\nAsk yourself: \"If this flow broke silently, would users immediately notice and stop using the product?\"\nTypically 2-4 flows are core. They receive 50-60% of test coverage later.\n\n### Phase 5: Coverage self-check (HARD GATE)\nBefore calling finish:\n1. Search again for all page/route files\n2. Compare against the pages you documented in AUTONOMA.md core_flows\n3. If ANY page is missing from your output, go back and document it\n4. The feature_count in AUTONOMA.md MUST match the actual number of features found\n\nDO NOT call finish until every page is accounted for.\n\n## AUTONOMA.md format\n\nThe file MUST start with YAML frontmatter:\n\n\\`\\`\\`yaml\n---\napp_name: \"Name of the application\"\napp_description: \"2-4 sentences describing what the application does, who uses it, and its primary purpose.\"\ncore_flows:\n - feature: \"Feature Name\"\n description: \"What this feature/area does\"\n mission: \"The ONE thing this feature must do correctly\"\n core: true\n coreReason: \"If this breaks, users cannot do X — the product is unusable\"\n - feature: \"Another Feature\"\n description: \"What this feature/area does\"\n mission: \"The ONE thing this feature must do correctly\"\n core: false\nfeature_count: 12\npages:\n - page: \"/path/to/file\"\n description: \"brief description of the page\"\n---\n\\`\\`\\`\n\n### Frontmatter rules\n- app_name: The app's name as it appears in the UI\n- app_description: 2-4 sentences, at least 20 characters\n- core_flows: ALL features/areas discovered. Each has feature (string), description (string), mission (string), core (boolean), and optionally coreReason (string)\n- mission: A single sentence stating what this feature MUST do correctly. This is NOT a description — it's a quality bar. Think: \"If I could only test ONE thing about this feature, what would I test?\"\n GOOD mission: \"Show correct execution counts, growth trends, and success rates for the selected time range and folders\"\n BAD mission: \"Shows analytics charts\" (just restates the feature name)\n- coreReason (required when core: true): WHY breakage of this feature makes the product unusable.\n- At least one flow must have core: true\n- feature_count: total features identified (positive integer)\n- pages: a list of all pages discovered, with their path and brief description\n\n\n### Feature granularity rules (CRITICAL)\nEach NAVIGABLE area, tab, or distinct page MUST be its own feature entry in core_flows. Do NOT group related pages into one feature.\n\nWRONG (too coarse):\n - feature: \"Analytics\" — groups 4 separate pages into one\n\nRIGHT (granular):\n - feature: \"Analytics - Overview\"\n - feature: \"Analytics - Revenue\"\n - feature: \"Analytics - Users\"\n - feature: \"Analytics - Retention\"\n\nA complex app should have 20-40 features in core_flows. If you have fewer than 15, you are grouping too aggressively.\n\nOnly 2-5 features should be core: true — the ones where breakage stops users from using the product entirely. Most features are core: false.\n\n### Body sections\nAfter the frontmatter, include:\n- Application description\n- User roles\n- Entry point (login, landing page)\n- Navigation structure (sidebar items, top nav, all menu entries)\n- Core flows (detailed description of each)\n- ALL other pages/features (even minor ones — settings tabs, profile, etc.)\n- UI patterns (common components, toast messages, modals, form patterns)\n- Preferences (date formats, currencies, timezone handling)\n\n## Tool usage guidance\n\n- Use list_directory ONCE at the root (path='.', depth=3) to get the project overview\n- Use glob and grep to find all page/route files — adapt your search patterns to the project's framework\n- Use read_file to read specific files you found\n- Do NOT call list_directory on every subdirectory — that's what glob is for\n- Use subagents to parallelize reading multiple files\n\n## Rules\n\n- EXHAUSTIVE coverage is mandatory. Every page, every route, every feature.\n- Use the UI vocabulary — the same names the app uses\n- Treat README files as hints, not ground truth — the codebase is the source of truth\n- Document what you find, don't invent features\n- Be specific: mention exact button text, menu labels, URL paths\n- Use subagents aggressively to parallelize exploration\n- If a page has tabs, each tab is a feature. If a page has modals, each modal is a feature.\n- Read the actual component code, not just the page entry point`;\n","import {tool} from \"ai\";\nimport {z} from \"zod\";\nimport {readFile} from \"node:fs/promises\";\nimport {join} from \"node:path\";\nimport {type AgentResult, buildDefaultStepLogger, runAgent} from \"../../core/agent\";\nimport {formatContext, type ProjectContext} from \"../../core/context\";\nimport {getModel} from \"../../core/model\";\nimport {reviewLoop} from \"../../core/review\";\nimport {buildCodebaseTools, buildReadFileTool} from \"../../tools\";\nimport {SYSTEM_PROMPT} from \"./prompt\";\n\nexport interface KBGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\nclass PageTracker {\n registered = new Set<string>();\n read = new Set<string>();\n\n register(pages: string[]) {\n for (const p of pages) this.registered.add(p);\n }\n\n markRead(filePath: string) {\n if (this.registered.has(filePath)) {\n this.read.add(filePath);\n }\n }\n\n unread(): string[] {\n return [...this.registered].filter((p) => !this.read.has(p));\n }\n\n coverage(): { total: number; read: number; unread: string[] } {\n return {\n total: this.registered.size,\n read: this.read.size,\n unread: this.unread(),\n };\n }\n}\n\nfunction buildRegisterPagesTool(tracker: PageTracker) {\n return tool({\n description:\n \"Register ALL page/route files discovered via glob. \" +\n \"Call this ONCE after globbing for page files. \" +\n \"The system will track which ones you've read and block finish until all are covered.\",\n inputSchema: z.object({\n pages: z.array(z.string()).describe(\"All page file paths found by glob\"),\n }),\n execute: async (input) => {\n tracker.register(input.pages);\n return {\n registered: input.pages.length,\n message: `Registered ${input.pages.length} pages. You must read_file each one before calling finish.`,\n };\n },\n });\n}\n\nfunction buildPageCoverageTool(tracker: PageTracker) {\n return tool({\n description: \"Check how many registered pages you've read vs how many remain.\",\n inputSchema: z.object({}),\n execute: async () => tracker.coverage(),\n });\n}\n\nfunction buildFinishTool(\n tracker: PageTracker,\n onFinish: (result: AgentResult) => void,\n) {\n return tool({\n description:\n \"Call when you have finished generating the knowledge base. \" +\n \"BLOCKED if there are unread pages — call page_coverage first to check.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Summary of what was generated\"),\n artifacts: z.array(z.string()).describe(\"List of files written\"),\n }),\n execute: async (input) => {\n const cov = tracker.coverage();\n if (cov.unread.length > 0) {\n return {\n error: `Cannot finish: ${cov.unread.length}/${cov.total} pages not yet read. Read these files first:\\n${cov.unread.join(\"\\n\")}`,\n };\n }\n onFinish({\n success: true,\n artifacts: input.artifacts,\n summary: input.summary,\n });\n return { success: true };\n },\n });\n}\n\nfunction buildTrackedReadTool(\n tracker: PageTracker,\n baseTool: ReturnType<typeof buildReadFileTool>,\n) {\n return tool({\n description: baseTool.description,\n inputSchema: baseTool.inputSchema,\n execute: async (input, options) => {\n const filePath = (input as { filePath?: string; path?: string; file_path?: string }).filePath\n ?? (input as { path?: string }).path\n ?? (input as { file_path?: string }).file_path\n ?? \"\";\n tracker.markRead(filePath);\n return baseTool.execute!(input, options);\n },\n });\n}\n\n\nexport async function runKBGenerator(input: KBGeneratorInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n const tracker = new PageTracker();\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"kb\", 150);\n\n const contextBlock = input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\";\n\n const pages = input.projectContext?.pages;\n if (pages?.length) {\n tracker.register(pages.map((p) => p.path));\n }\n\n const prompt = pages?.length\n ? `Analyze the codebase at the working directory and generate a complete knowledge base.\n${contextBlock}\nMANDATORY PROCESS:\nPages have already been discovered (${pages.length} routes pre-registered). You do NOT need to glob for them.\n1. Use list_directory at root to understand the project structure\n2. Read EVERY registered page file with read_file — the system tracks this\n3. Write AUTONOMA.md progressively as you go (update it after each major area)\n4. Call page_coverage to verify you've read all pages\n5. Call finish — it will REJECT if pages are unread\n\nOutput files:\n1. AUTONOMA.md — with YAML frontmatter (app_name, app_description, core_flows, feature_count)`\n : `Analyze the codebase at the working directory and generate a complete knowledge base.\n${contextBlock}\nMANDATORY PROCESS:\n1. Use list_directory at root to understand the project structure\n2. Use glob to find ALL page/route files (e.g. '**/page.tsx', '**/page.ts')\n3. Call register_pages with the FULL list of page files from glob\n4. Read EVERY registered page file with read_file — the system tracks this\n5. Write AUTONOMA.md progressively as you go (update it after each major area)\n6. Call page_coverage to verify you've read all pages\n7. Call finish — it will REJECT if pages are unread\n\nOutput files:\n1. AUTONOMA.md — with YAML frontmatter (app_name, app_description, core_flows, feature_count)`;\n\n const agentConfig = {\n id: \"kb-generator\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 150,\n tools: async (heartbeat: () => void) => {\n const onFileRead = (path: string) => tracker.markRead(path);\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat, onFileRead);\n return {\n ...tools,\n read_file: buildTrackedReadTool(tracker, tools.read_file),\n register_pages: buildRegisterPagesTool(tracker),\n page_coverage: buildPageCoverageTool(tracker),\n finish: buildFinishTool(tracker, (r) => { result = r; }),\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n const reviewed = await reviewLoop(result, {\n agentId: \"kb-generator\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n reviewGuidance:\n \"Check that every page/route in your app appears in core_flows.\\n\" +\n \"Verify the mission for each feature describes the ONE thing it must do correctly.\\n\" +\n \"Look for missing features or incorrectly grouped pages.\\n\" +\n \"A complex app should have 20-40 features — if you see fewer than 15, features are probably grouped too aggressively.\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed your knowledge base output and has this feedback:\n\n\"${feedback}\"\n\nRead your previous output file (AUTONOMA.md) from the output directory to see what you produced.\nAdjust based on the feedback. You can read source files again if needed.\nCall page_coverage to see current state. When done with changes, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n if (!reviewed) {\n const autonomaPath = join(input.outputDir, \"AUTONOMA.md\");\n try {\n await readFile(autonomaPath, \"utf-8\");\n return {\n success: true,\n artifacts: [\"AUTONOMA.md\"],\n summary: \"Knowledge base generated (finish tool may not have captured the result, but AUTONOMA.md exists).\",\n };\n } catch {}\n }\n\n return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"KB generator did not produce a result\",\n };\n}\n","export const SYSTEM_PROMPT = `You audit a codebase to discover EVERY database model and every way each is created. You must find ALL models — missing one means the test data layer has a gap. This audit drives factory generation and scenario planning.\n\n## The two orthogonal questions\n\nFor every model, answer BOTH independently:\n\n1. **independently_created** — Does the codebase have an exported function/method that creates this model on its own? Boolean.\n2. **created_by** — When you trace every other model's creation function, does any of them produce this model as a side effect? List of {owner, via, why} entries; empty if none.\n\nThese are NOT mutually exclusive. A model can be both. Do not collapse the two.\n\n## The four states a model can be in\n\n| independently_created | created_by | Interpretation |\n|---|---|---|\n| true | [] | Pure root — only standalone creation exists |\n| true | non-empty | Dual — has standalone path AND is produced by owners |\n| false | non-empty | Pure dependent — only reachable via owner's creation |\n| false | [] | INVALID — unreachable model, fix before writing |\n\n## MANDATORY DISCOVERY PROCESS\n\n### Step 0: Identify the database framework\nDetermine which ORM/database tool the project uses. Explore the project structure — read config files, schema definitions, and imports to identify the data layer. Every project is different; use your tools (grep, glob, read_file) to discover the patterns.\n\n### Step 1: Find ALL model definitions and register them\nBased on the framework you identified, use grep and glob to find ALL model/table/entity definitions. Call register_models with the complete list. Real applications typically have 30-150 models — if you found fewer than 20, search harder before registering.\n\n### Step 2: Process models using the queue\nAfter registering, call next_model to get the first model. For each model:\n\n1. grep for creation patterns (e.g. \"ModelName.create\", \"new ModelName\", \"insert into model\") — 1 to 3 greps MAX\n2. If you find a creation path: read the file, call mark_model_audited with the details\n3. If you can't find it after 2-3 greps: call next_model to skip and move on\n\nIMPORTANT: Do NOT spend more than 3-4 steps per model. The queue ensures you process every model. If a model has no obvious creation path, skipping it is valid — it gets marked as \"no creation path found.\"\n\nWhen you call mark_model_audited, also note side effects you see in the creation function (other models created as part of the same operation). Record these in the created_by field of those other models when you reach them.\n\n### Step 3: Write output and finish\nWhen next_model returns done, write entity-audit.md and call finish.\n\n## Output files\n\nYou produce TWO files:\n\n### 1. entity-audit.md\n\nYAML frontmatter with ALL models, then markdown body organized by module/area.\n\nFrontmatter format:\n\\`\\`\\`yaml\n---\nmodel_count: 105\nfactory_count: 48\nmodels:\n # ============================================================\n # MODULE NAME\n # ============================================================\n - name: User\n independently_created: true\n creation_file: src/services/user.service.ts\n creation_function: UserService.create\n side_effects:\n - hashes password\n - creates default Settings row\n created_by: []\n - name: Settings\n independently_created: false\n created_by:\n - owner: User\n via: UserService.create\n why: \"Every new User gets a default Settings row created in the same transaction.\"\n---\n\\`\\`\\`\n\nGroup models by module/domain area with comment headers for readability.\n\nBody sections:\n- Database framework identified and version\n- Roots (independently_created: true) with details\n- Dependents (independently_created: false) with owner chains\n- Dual-creation models (both true AND non-empty created_by)\n- Dependency graph summary (which models must exist before others)\n\n### 2. factory-scaffold.ts\n\nA TypeScript file with defineFactory() stubs for every model with independently_created: true.\n\nFormat:\n\\`\\`\\`typescript\nimport { defineFactory } from '@autonoma-ai/sdk'\nimport { z } from 'zod'\n\nexport const User = defineFactory({\n inputSchema: z.object({\n email: z.string(),\n name: z.string(),\n organizationId: z.string(),\n }),\n create: async (data, ctx) => {\n // Suggested: return createUser({ ...data, password: 'test-password' })\n // Found at: src/services/user.service.ts:42 — UserService.create()\n throw new Error('TODO: implement')\n },\n teardown: async (record, ctx) => {\n // Suggested: await db.user.delete({ where: { id: record.id } })\n // Cascade: will also delete Settings (FK constraint)\n throw new Error('TODO: implement')\n },\n})\n\\`\\`\\`\n\n## Tool usage guidance\n\n- Use list_directory ONCE at root to understand project layout, then use grep/glob for targeted discovery\n- Use grep to find ALL model definitions — adapt your search patterns to the framework you discover\n- Use next_model to process models one at a time from the queue — never pick models yourself\n- Use read_file on creation files found by grep\n- Do NOT call list_directory on every subdirectory — use grep and glob instead\n\n## Rules\n\n- EXHAUSTIVE coverage is mandatory. Real apps have 30-150 models. If you found fewer than 20, you missed most of them.\n- Use grep to find models, not file browsing. Models can be defined anywhere.\n- Read the ACTUAL creation code, don't guess from file names\n- Do NOT spend more than 3-4 steps per model. Move on quickly.\n- When in doubt, prefer independently_created: true\n- Every enum type that maps to a DB column should be noted (useful for scenario generation later)\n- Junction tables and association tables ARE models — include them`;\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { glob } from \"glob\";\nimport { runAgent, buildDefaultStepLogger, type AgentResult } from \"../../core/agent\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport { reviewLoop } from \"../../core/review\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\n\nexport interface EntityAuditInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\ninterface CreatedByEntry {\n owner: string;\n via?: string;\n why?: string;\n}\n\ninterface AuditedModel {\n name: string;\n independently_created: boolean;\n creation_file?: string;\n creation_function?: string;\n side_effects?: string[];\n created_by: CreatedByEntry[];\n}\n\nclass ModelTracker {\n registered = new Set<string>();\n auditedModels = new Map<string, AuditedModel>();\n creationFilesRead = new Set<string>();\n framework = \"unknown\";\n queue: string[] = [];\n currentModel: string | null = null;\n\n register(models: string[]) {\n for (const m of models) this.registered.add(m);\n }\n\n initQueue() {\n this.queue = [...this.registered].filter((m) => !this.auditedModels.has(m));\n }\n\n nextModel(): { model: string; remaining: number } | null {\n if (this.currentModel && !this.auditedModels.has(this.currentModel)) {\n this.auditedModels.set(this.currentModel, {\n name: this.currentModel,\n independently_created: false,\n created_by: [],\n });\n }\n while (this.queue.length > 0) {\n const model = this.queue.shift()!;\n if (this.auditedModels.has(model)) continue;\n this.currentModel = model;\n return { model, remaining: this.queue.length };\n }\n this.currentModel = null;\n return null;\n }\n\n markAudited(model: AuditedModel) {\n this.auditedModels.set(model.name, model);\n }\n\n markFileRead(filePath: string) {\n this.creationFilesRead.add(filePath);\n }\n\n unaudited(): string[] {\n return [...this.registered].filter((m) => !this.auditedModels.has(m));\n }\n\n coverage() {\n return {\n totalModels: this.registered.size,\n audited: this.auditedModels.size,\n unaudited: this.unaudited(),\n creationFilesRead: this.creationFilesRead.size,\n };\n }\n\n generateAuditMarkdown(): string {\n const models = [...this.auditedModels.values()];\n const roots = models.filter((m) => m.independently_created);\n const dependents = models.filter((m) => !m.independently_created);\n const duals = models.filter((m) => m.independently_created && m.created_by.length > 0);\n\n const yamlModels = models.map((m) => {\n let entry = ` - name: ${m.name}\\n independently_created: ${m.independently_created}`;\n if (m.creation_file) entry += `\\n creation_file: ${m.creation_file}`;\n if (m.creation_function) entry += `\\n creation_function: ${m.creation_function}`;\n if (m.side_effects && m.side_effects.length > 0) {\n entry += `\\n side_effects:\\n${m.side_effects.map((s) => ` - ${s}`).join(\"\\n\")}`;\n }\n if (m.created_by.length > 0) {\n entry += `\\n created_by:`;\n for (const cb of m.created_by) {\n entry += `\\n - owner: ${cb.owner}`;\n if (cb.via) entry += `\\n via: ${cb.via}`;\n if (cb.why) entry += `\\n why: \"${cb.why}\"`;\n }\n } else {\n entry += `\\n created_by: []`;\n }\n return entry;\n }).join(\"\\n\");\n\n return `---\nmodel_count: ${models.length}\nfactory_count: ${roots.length}\nmodels:\n${yamlModels}\n---\n\n# Entity Audit\n\nFramework: ${this.framework}\n\n## Roots (independently_created: true)\n\n${roots.map((m) => `- **${m.name}** — ${m.creation_function ?? m.creation_file ?? \"unknown\"}`).join(\"\\n\")}\n\n## Dependents (independently_created: false)\n\n${dependents.map((m) => `- **${m.name}** — created by: ${m.created_by.map((cb) => `${cb.owner}${cb.via ? ` via ${cb.via}` : \"\"}`).join(\", \") || \"unknown\"}`).join(\"\\n\")}\n\n## Dual-creation models (independently_created AND created_by)\n\n${duals.length > 0 ? duals.map((m) => `- **${m.name}** — standalone: ${m.creation_function ?? m.creation_file ?? \"unknown\"}, also created by: ${m.created_by.map((cb) => cb.owner).join(\", \")}`).join(\"\\n\") : \"None\"}\n`;\n }\n}\n\nfunction buildRegisterModelsTool(tracker: ModelTracker) {\n return tool({\n description:\n \"Register ALL database models discovered via grep. \" +\n \"Call this ONCE after grepping for model definitions. \" +\n \"After registering, use next_model to process them one at a time.\",\n inputSchema: z.object({\n models: z.array(z.string()).describe(\"All model/table names found by grep\"),\n framework: z.string().describe(\"Database framework detected (e.g. 'sqlalchemy', 'prisma', 'drizzle')\"),\n }),\n execute: async (input) => {\n tracker.register(input.models);\n tracker.initQueue();\n return {\n registered: input.models.length,\n framework: input.framework,\n message: `Registered ${input.models.length} models (${input.framework}). Call next_model to start processing them one at a time.`,\n };\n },\n });\n}\n\nfunction buildNextModelTool(tracker: ModelTracker) {\n return tool({\n description:\n \"Get the next model to audit from the queue. If you called next_model before \" +\n \"without calling mark_model_audited, the previous model is auto-skipped \" +\n \"(marked as no creation path found). Returns done:true when all models are processed.\",\n inputSchema: z.object({}),\n execute: async () => {\n const next = tracker.nextModel();\n if (!next) {\n return {\n done: true,\n message: `All models processed (${tracker.auditedModels.size} total). Write entity-audit.md and call finish.`,\n };\n }\n return {\n model: next.model,\n remaining: next.remaining,\n instruction: `Audit \"${next.model}\": grep for its creation paths, read the relevant file, then call mark_model_audited. If you can't find how it's created after 2-3 greps, call next_model to skip it.`,\n };\n },\n });\n}\n\nfunction buildMarkModelAuditedTool(tracker: ModelTracker) {\n return tool({\n description:\n \"Mark a model as audited after you have determined its creation paths. \" +\n \"Call this for EACH model after reading its creation code and determining independently_created + created_by. \" +\n \"Include creation_function (e.g. 'UserService.create'), side_effects (list of things the creation does beyond the model itself), \" +\n \"and for each created_by entry include owner, via (function name), and why (one sentence explaining the relationship).\",\n inputSchema: z.object({\n model: z.string().describe(\"Model name\"),\n independently_created: z.boolean(),\n creation_file: z.string().optional().describe(\"File containing the creation function\"),\n creation_function: z.string().optional().describe(\"Function/method name (e.g. 'UserService.create' or 'create_user')\"),\n side_effects: z.array(z.string()).optional().describe(\"Side effects of creation (e.g. 'creates default Settings row', 'hashes password')\"),\n created_by: z.array(z.object({\n owner: z.string().describe(\"Owner model name\"),\n via: z.string().optional().describe(\"Function that creates this model (e.g. 'OrganizationService.create')\"),\n why: z.string().optional().describe(\"One sentence explaining why this model is created as a side effect\"),\n })).describe(\"List of owner models that create this as a side effect, empty array if none\"),\n }),\n execute: async (input) => {\n let modelName = input.model;\n\n if (tracker.registered.size > 0 && !tracker.registered.has(modelName)) {\n const exact = [...tracker.registered].find(\n (r) => r.toLowerCase() === modelName.toLowerCase() || modelName.startsWith(r),\n );\n if (exact) {\n modelName = exact;\n } else {\n return {\n error: `\"${modelName}\" is not a registered model. Use the exact name from register_models. Registered: ${[...tracker.registered].join(\", \")}`,\n };\n }\n }\n\n tracker.markAudited({\n name: modelName,\n independently_created: input.independently_created,\n creation_file: input.creation_file,\n creation_function: input.creation_function,\n side_effects: input.side_effects,\n created_by: input.created_by,\n });\n if (input.creation_file) tracker.markFileRead(input.creation_file);\n const cov = tracker.coverage();\n return {\n model: modelName,\n progress: `${cov.audited}/${cov.totalModels} models audited`,\n remaining: cov.unaudited.length,\n };\n },\n });\n}\n\nfunction buildModelCoverageTool(tracker: ModelTracker) {\n return tool({\n description: \"Check how many registered models you've audited vs how many remain.\",\n inputSchema: z.object({}),\n execute: async () => tracker.coverage(),\n });\n}\n\nfunction buildFinishTool(\n tracker: ModelTracker,\n onFinish: (result: AgentResult) => void,\n) {\n return tool({\n description:\n \"Call when entity audit is complete. \" +\n \"BLOCKED if there are unaudited models — call model_coverage first to check.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Summary of the audit\"),\n artifacts: z.array(z.string()).describe(\"Files written\"),\n }),\n execute: async (input) => {\n const cov = tracker.coverage();\n if (cov.unaudited.length > 0) {\n return {\n error: `Cannot finish: ${cov.unaudited.length}/${cov.totalModels} models not yet audited. Audit these models first:\\n${cov.unaudited.join(\"\\n\")}`,\n };\n }\n onFinish({\n success: true,\n artifacts: input.artifacts,\n summary: input.summary,\n });\n return { success: true };\n },\n });\n}\n\ntype FrameworkDetection = {\n framework: string;\n models: string[];\n schemaFile?: string;\n};\n\nasync function findPrismaSchema(projectRoot: string): Promise<string | null> {\n const candidates = await glob(\"**/schema.prisma\", {\n cwd: projectRoot,\n ignore: [\"**/node_modules/**\"],\n absolute: true,\n });\n return candidates[0] ?? null;\n}\n\nasync function extractPrismaModels(schemaPath: string): Promise<string[]> {\n const content = await readFile(schemaPath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"model \"))\n .map((line) => line.split(/\\s+/)[1])\n .filter((name): name is string => name != null);\n}\n\nasync function detectFrameworkAndModels(\n projectRoot: string,\n): Promise<FrameworkDetection | null> {\n const prismaPath = await findPrismaSchema(projectRoot);\n if (prismaPath) {\n const models = await extractPrismaModels(prismaPath);\n return { framework: \"prisma\", models, schemaFile: prismaPath };\n }\n\n // TODO: Add SQLAlchemy, Django, Drizzle, TypeORM detection\n return null;\n}\n\nexport async function runEntityAudit(input: EntityAuditInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n const tracker = new ModelTracker();\n\n const detection = await detectFrameworkAndModels(input.projectRoot);\n let preRegisteredCount = 0;\n if (detection) {\n tracker.framework = detection.framework;\n tracker.register(detection.models);\n tracker.initQueue();\n preRegisteredCount = detection.models.length;\n }\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"entity-audit\", 200);\n\n const contextBlock = input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\";\n\n const preRegBlock = preRegisteredCount > 0\n ? `\\n## Pre-registered models (${preRegisteredCount} found via ${detection!.framework} schema at ${detection!.schemaFile})\n\nThe system has already registered ${preRegisteredCount} models from the schema file. You do NOT need to call register_models — it's already done. Start with next_model to process them.\\n`\n : \"\";\n\n const prompt = `Use read_output to read AUTONOMA.md from the output directory to understand the application.\n\n${contextBlock}\nAudit the codebase at the working directory.\n${preRegBlock}\nMANDATORY PROCESS:\n\n${preRegisteredCount === 0 ? `1. Explore the project to identify the database framework and find ALL model definitions\n2. Call register_models with the full list of model names\n3. Call next_model` : \"1. Call next_model\"} to get the first model\n${preRegisteredCount === 0 ? \"4\" : \"2\"}. For each model returned by next_model:\n a. grep for creation patterns (e.g. \"ModelName.create\", \"new ModelName\") — 1 to 3 greps MAX\n b. If found: read the file, call mark_model_audited with the creation details\n c. If NOT found after 2-3 greps: call next_model to skip and move on (auto-skipped as \"no creation path found\")\n${preRegisteredCount === 0 ? \"5\" : \"3\"}. Repeat until next_model returns done\n${preRegisteredCount === 0 ? \"6\" : \"4\"}. Write entity-audit.md with all findings\n${preRegisteredCount === 0 ? \"7\" : \"5\"}. Call finish\n\nIMPORTANT: Do NOT spend more than 3-4 steps per model. The queue ensures you process every model.\nIf you can't find a creation path quickly, skip it — that's valid data.\nAfter every 10 mark_model_audited calls, use write_file to update entity-audit.md progressively.\nwrite_file already targets the output directory — use just the filename.`;\n\n const agentConfig = {\n id: \"entity-audit\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 200,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n register_models: buildRegisterModelsTool(tracker),\n next_model: buildNextModelTool(tracker),\n mark_model_audited: buildMarkModelAuditedTool(tracker),\n model_coverage: buildModelCoverageTool(tracker),\n ask_user: buildAskUserTool(),\n finish: buildFinishTool(tracker, (r) => { result = r; }),\n };\n },\n onStepFinish,\n };\n\n try {\n await runAgent(agentConfig, prompt, () => result);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Entity audit agent error: ${message}`);\n }\n logger.summary();\n\n if (!result && tracker.auditedModels.size > 0) {\n const markdown = tracker.generateAuditMarkdown();\n const auditPath = join(input.outputDir, \"entity-audit.md\");\n await writeFile(auditPath, markdown, \"utf-8\");\n const cov = tracker.coverage();\n result = {\n success: true,\n artifacts: [auditPath],\n summary: `Safety net: agent ran out of steps but audited ${cov.audited}/${cov.totalModels} models. File written from tracker data.`,\n };\n }\n\n const reviewed = await reviewLoop(result, {\n agentId: \"entity-audit\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n reviewGuidance:\n \"Each model entry has these key fields:\\n\" +\n \" independently_created — true if this entity has its own creation API/function, false if only created as a side effect\\n\" +\n \" creation_file / creation_function — where in YOUR code this entity gets created\\n\" +\n \" side_effects — other entities that get created automatically when this one is created\\n\" +\n \" created_by — which parent entity's creation triggers this one\\n\\n\" +\n \"What to check:\\n\" +\n \" - Every database model should be listed\\n\" +\n \" - independently_created should be correct — models created only as side effects should be false\\n\" +\n \" - creation_file and creation_function should reference real code in your project\\n\" +\n \" - Side effects should be complete (e.g., creating a User also creates a Profile)\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed your entity audit and has this feedback:\n\n\"${feedback}\"\n\nRead your previous output (entity-audit.md) from the output directory.\nCall model_coverage to see current state.\nAdjust based on the feedback. You can grep/read source files again if needed.\nWhen done with changes, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n if (!reviewed) {\n const auditPath = join(input.outputDir, \"entity-audit.md\");\n try {\n await readFile(auditPath, \"utf-8\");\n return {\n success: true,\n artifacts: [\"entity-audit.md\"],\n summary: \"Entity audit generated (finish tool may not have captured the result, but entity-audit.md exists).\",\n };\n } catch {}\n }\n\n return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Entity audit did not produce a result\",\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function parseEntityNames(outputDir: string): Promise<string[]> {\n try {\n const content = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n const names: string[] = [];\n for (const line of content.split(\"\\n\")) {\n const match = line.match(/^\\s+-\\s+name:\\s+(.+)$/);\n if (match) names.push(match[1]!.trim());\n }\n return names;\n } catch {\n return [];\n }\n}\n","export const SCENARIO_DESIGN_PROMPT = `You are a scenario designer for E2E testing. You read an entity audit and design a single \"standard\" test data scenario.\n\n## Your input\n- entity-audit.md: models, creation paths, side effects\n- AUTONOMA.md: app context, core flows\n\n## Your output\nA scenarios.md file with YAML frontmatter describing a single \"standard\" scenario.\n\n## Scenario design rules\n\n1. ONE scenario: \"standard\" — represents a realistic working state of the application\n2. Realistic data volumes:\n - An email app gets 50+ emails, not 1\n - A payment app gets all payment method types\n - A project management tool gets multiple projects with tasks in various states\n3. Enum coverage: for every enum field, include at least one record per value\n4. The scenario must exercise all entity types from the audit\n5. Entity tables must be consistent — FK references must point to real records\n\n## Output format\n\n\\`\\`\\`yaml\n---\nscenario_count: 1\nscenarios:\n - name: standard\n description: \"Realistic working state with diverse data\"\nentity_types:\n - name: Organization\n count: 1\n - name: User\n count: 3\n - name: Project\n count: 5\nvariable_fields:\n - token: \"{{user_email_1}}\"\n entity: User\n field: email\n test_reference: \"primary test user email\"\n---\n\\`\\`\\`\n\nAfter frontmatter, write entity tables showing the data for the standard scenario.\nUse markdown tables. Show enough detail that a recipe builder can generate the exact records.\n\n## Variable fields\nSome values must change between test runs (emails, unique slugs, timestamps).\nList these in variable_fields with a {{token}} placeholder.\nThe rest can be static.`;\n\nexport const RECIPE_ENTITY_PROMPT = `You generate a recipe payload for a single entity type. Given the entity name, count, field constraints, enum values to cover, and FK refs to previously created entities, output a JSON array of entity records.\n\nRules:\n- Cover all enum values (at least one record per value)\n- Use realistic, diverse data (not \"test1\", \"test2\")\n- Respect FK constraints — reference real IDs from previously created entities\n- Include all required fields\n- Output valid JSON that can be sent to the SDK endpoint\n\nOutput ONLY the JSON array, no explanation.`;\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { AppConfig } from \"../../config\";\nimport { runAgent, buildDefaultStepLogger, type AgentResult } from \"../../core/agent\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport { parseEntityNames } from \"../../core/parse-entity-audit\";\nimport { reviewLoop } from \"../../core/review\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { SCENARIO_DESIGN_PROMPT } from \"./prompt\";\n\nexport interface ScenarioRecipeInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n config: AppConfig;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\nfunction buildFinishTool(\n requiredEntities: string[],\n outputDir: string,\n onFinish: (result: AgentResult) => void,\n) {\n return tool({\n description:\n \"Call when scenario design is complete and scenarios.md is written. \" +\n \"BLOCKED if any required entities are missing from the scenario.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Summary of the scenario\"),\n entityCount: z.number().describe(\"Number of entity types in the scenario\"),\n artifacts: z.array(z.string()).describe(\"Files written\"),\n }),\n execute: async (input) => {\n if (requiredEntities.length > 0) {\n try {\n const content = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n const missing = requiredEntities.filter(\n (e) => !content.includes(e),\n );\n if (missing.length > 0) {\n return {\n error:\n `Cannot finish: ${missing.length} entities from the entity audit are missing from scenarios.md.\\n` +\n `Add these entities to the scenario before calling finish:\\n` +\n missing.map((e) => ` - ${e}`).join(\"\\n\"),\n };\n }\n } catch {\n return { error: \"Cannot finish: scenarios.md not found. Write it first.\" };\n }\n }\n\n onFinish({\n success: true,\n artifacts: input.artifacts,\n summary: input.summary,\n });\n return { success: true };\n },\n });\n}\n\nexport async function runScenarioRecipe(input: ScenarioRecipeInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let result: AgentResult | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"scenario\", 40);\n\n const contextBlock = input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\";\n\n const requiredEntities = await parseEntityNames(input.outputDir);\n\n const entityListBlock = requiredEntities.length > 0\n ? `\\n## Required entities (${requiredEntities.length} total — ALL must appear in the scenario)\\n\\n${requiredEntities.map((e) => `- ${e}`).join(\"\\n\")}\\n\\nThe finish tool will REJECT your output if any of these are missing.\\n`\n : \"\";\n\n const prompt = `Read the entity audit and knowledge base from the output directory, then design a single \"standard\" scenario.\n${contextBlock}${entityListBlock}\nIMPORTANT: Use read_output to read files from the output directory (AUTONOMA.md, entity-audit.md).\nUse write_file with just the filename (e.g. \"scenarios.md\", NOT \"autonoma/scenarios.md\") — write_file already targets the output directory.\n\nThe scenario should:\n1. Cover ALL ${requiredEntities.length || \"\"} entity types from the entity audit — no exceptions\n2. Use realistic data volumes (not just 1 of each)\n3. Cover all enum values (at least one record per value)\n4. Include variable_fields for values that must change between runs\n\nWhen done, call finish.`;\n\n const agentConfig = {\n id: \"scenario-recipe\",\n systemPrompt: SCENARIO_DESIGN_PROMPT,\n model,\n maxSteps: 40,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return { ...tools, ask_user: buildAskUserTool(), finish: buildFinishTool(requiredEntities, input.outputDir, (r) => { result = r; }) };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n const reviewed = await reviewLoop(result, {\n agentId: \"scenario-recipe\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n reviewGuidance:\n \"The scenario defines test data that will exist in the database during E2E tests.\\n\" +\n \"Each entity_type should have a realistic count and data values.\\n\\n\" +\n \"What to check:\\n\" +\n \" - Every entity from the entity audit should appear here\\n\" +\n \" - Counts should be realistic (not just 1 of each)\\n\" +\n \" - Enum fields should have diverse values (not all the same)\\n\" +\n \" - variable_fields should mark values that must change between runs (emails, slugs)\\n\" +\n \" - Data values should match your actual database patterns\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed the scenario design and has this feedback:\n\n\"${feedback}\"\n\nRead your previous output (scenarios.md) from the output directory.\nAdjust based on the feedback. You can read entity-audit.md or source files again if needed.\nWhen done with changes, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n if (!reviewed) {\n const scenariosPath = join(input.outputDir, \"scenarios.md\");\n try {\n await readFile(scenariosPath, \"utf-8\");\n return {\n success: true,\n artifacts: [\"scenarios.md\"],\n summary: \"Scenarios generated (finish tool may not have captured the result, but scenarios.md exists).\",\n };\n } catch {}\n }\n\n return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Scenario recipe agent did not produce a result\",\n };\n}\n\nexport async function feedbackToScenario(input: ScenarioRecipeInput, feedback: string): Promise<AgentResult> {\n const model = getModel(input.modelId);\n let result: AgentResult | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"scenario-feedback\", 30);\n\n const requiredEntities = await parseEntityNames(input.outputDir);\n\n const agentConfig = {\n id: \"scenario-recipe\",\n systemPrompt: SCENARIO_DESIGN_PROMPT,\n model,\n maxSteps: 30,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return { ...tools, ask_user: buildAskUserTool(), finish: buildFinishTool(requiredEntities, input.outputDir, (r) => { result = r; }) };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, feedback, () => result);\n logger.summary();\n\n return result ?? { success: false, artifacts: [], summary: \"Scenario feedback did not produce a result\" };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type EntityStatus =\n | \"pending\"\n | \"recipe-accepted\"\n | \"tested-up\"\n | \"tested-down\"\n | \"skipped\";\n\nexport interface EntityProgress {\n entityName: string;\n status: EntityStatus;\n recipeData: Record<string, unknown>[] | null;\n errorLog: string[];\n}\n\nexport type SdkAdapter =\n | { language: \"typescript\"; framework: \"express\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-express\" }\n | { language: \"typescript\"; framework: \"node\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-node\" }\n | { language: \"typescript\"; framework: \"hono\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-hono\" }\n | { language: \"typescript\"; framework: \"web\"; sdkPackage: \"@autonoma-ai/sdk\"; adapterPackage: \"@autonoma-ai/server-web\" }\n | { language: \"python\"; framework: \"flask\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma_flask\" }\n | { language: \"python\"; framework: \"fastapi\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma_fastapi\" }\n | { language: \"python\"; framework: \"django\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma_django\" }\n | { language: \"go\"; framework: \"gin\"; sdkPackage: \"github.com/autonoma-ai/sdk-go\"; adapterPackage: \"github.com/autonoma-ai/sdk-go\" }\n | { language: \"ruby\"; framework: \"rails\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma-ai\" }\n | { language: \"ruby\"; framework: \"rack\"; sdkPackage: \"autonoma-ai\"; adapterPackage: \"autonoma-ai\" }\n | { language: \"java\"; framework: \"spring\"; sdkPackage: \"autonoma-sdk\"; adapterPackage: \"autonoma-spring\" }\n | { language: \"php\"; framework: \"laravel\"; sdkPackage: \"autonoma-ai/sdk\"; adapterPackage: \"autonoma-ai/sdk\" }\n | { language: \"rust\"; framework: \"axum\"; sdkPackage: \"autonoma-sdk\"; adapterPackage: \"autonoma-sdk\" }\n | { language: \"rust\"; framework: \"actix\"; sdkPackage: \"autonoma-sdk\"; adapterPackage: \"autonoma-sdk\" }\n | { language: \"elixir\"; framework: \"plug\"; sdkPackage: \"autonoma\"; adapterPackage: \"autonoma\" };\n\nexport type TechStack = SdkAdapter;\n\nexport const ALL_ADAPTERS: SdkAdapter[] = [\n { language: \"typescript\", framework: \"web\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-web\" },\n { language: \"typescript\", framework: \"express\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-express\" },\n { language: \"typescript\", framework: \"node\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-node\" },\n { language: \"typescript\", framework: \"hono\", sdkPackage: \"@autonoma-ai/sdk\", adapterPackage: \"@autonoma-ai/server-hono\" },\n { language: \"python\", framework: \"flask\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma_flask\" },\n { language: \"python\", framework: \"fastapi\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma_fastapi\" },\n { language: \"python\", framework: \"django\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma_django\" },\n { language: \"go\", framework: \"gin\", sdkPackage: \"github.com/autonoma-ai/sdk-go\", adapterPackage: \"github.com/autonoma-ai/sdk-go\" },\n { language: \"ruby\", framework: \"rails\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma-ai\" },\n { language: \"ruby\", framework: \"rack\", sdkPackage: \"autonoma-ai\", adapterPackage: \"autonoma-ai\" },\n { language: \"java\", framework: \"spring\", sdkPackage: \"autonoma-sdk\", adapterPackage: \"autonoma-spring\" },\n { language: \"php\", framework: \"laravel\", sdkPackage: \"autonoma-ai/sdk\", adapterPackage: \"autonoma-ai/sdk\" },\n { language: \"rust\", framework: \"axum\", sdkPackage: \"autonoma-sdk\", adapterPackage: \"autonoma-sdk\" },\n { language: \"rust\", framework: \"actix\", sdkPackage: \"autonoma-sdk\", adapterPackage: \"autonoma-sdk\" },\n { language: \"elixir\", framework: \"plug\", sdkPackage: \"autonoma\", adapterPackage: \"autonoma\" },\n];\n\nexport function adapterKey(a: SdkAdapter): string {\n return `${a.language}:${a.framework}`;\n}\n\nexport function adapterLabel(a: SdkAdapter): string {\n const lang = a.language.charAt(0).toUpperCase() + a.language.slice(1);\n const fw = a.framework.charAt(0).toUpperCase() + a.framework.slice(1);\n return `${lang} + ${fw}`;\n}\n\nexport function findAdapter(language: string, framework: string): SdkAdapter | undefined {\n return ALL_ADAPTERS.find(\n (a) => a.language === language.toLowerCase() && a.framework === framework.toLowerCase(),\n );\n}\n\nexport const ADAPTER_HINTS: Record<string, string> = {\n \"typescript:express\": \"Express.js and Express-compatible frameworks\",\n \"typescript:node\": \"Plain Node.js HTTP server (built-in http module)\",\n \"typescript:hono\": \"Hono framework (works with Bun, Deno, Node)\",\n \"typescript:web\": \"Web Standard Request/Response — covers Next.js, Remix, Nuxt, Bun, Deno, SvelteKit, Astro\",\n \"python:flask\": \"Flask framework\",\n \"python:fastapi\": \"FastAPI framework\",\n \"python:django\": \"Django framework\",\n \"go:gin\": \"Gin framework for Go\",\n \"ruby:rails\": \"Ruby on Rails\",\n \"ruby:rack\": \"Rack-based Ruby frameworks (Sinatra, Hanami, etc.)\",\n \"java:spring\": \"Spring Boot / Spring Framework\",\n \"php:laravel\": \"Laravel framework\",\n \"rust:axum\": \"Axum framework for Rust\",\n \"rust:actix\": \"Actix Web framework for Rust\",\n \"elixir:plug\": \"Plug / Phoenix framework for Elixir\",\n};\n\nexport interface RecipeBuilderState {\n phase: \"tech-detect\" | \"entity-loop\" | \"full-validation\" | \"submit\" | \"done\";\n techStack: TechStack | null;\n entityOrder: string[];\n entities: Record<string, EntityProgress>;\n currentEntityIndex: number;\n sdkEndpointUrl: string | null;\n sharedSecret: string | null;\n}\n\nconst STATE_FILE = \".recipe-builder-state.json\";\n\nexport function initialRecipeState(): RecipeBuilderState {\n return {\n phase: \"tech-detect\",\n techStack: null,\n entityOrder: [],\n entities: {},\n currentEntityIndex: 0,\n sdkEndpointUrl: null,\n sharedSecret: null,\n };\n}\n\nexport async function loadRecipeState(outputDir: string): Promise<RecipeBuilderState | null> {\n try {\n const raw = await readFile(join(outputDir, STATE_FILE), \"utf-8\");\n return JSON.parse(raw) as RecipeBuilderState;\n } catch {\n return null;\n }\n}\n\nexport async function saveRecipeState(outputDir: string, state: RecipeBuilderState): Promise<void> {\n await writeFile(join(outputDir, STATE_FILE), JSON.stringify(state, null, 2), \"utf-8\");\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface AuditedModel {\n name: string;\n independently_created: boolean;\n creation_file?: string;\n creation_function?: string;\n side_effects?: string[];\n created_by: { owner: string; via?: string; why?: string }[];\n}\n\nexport async function parseEntityAudit(outputDir: string): Promise<AuditedModel[]> {\n const raw = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) throw new Error(\"entity-audit.md has no YAML frontmatter\");\n\n const yaml = fmMatch[1]!;\n const models: AuditedModel[] = [];\n let current: Partial<AuditedModel> | null = null;\n let inCreatedBy = false;\n let currentCreatedBy: { owner: string; via?: string; why?: string } | null = null;\n\n for (const line of yaml.split(\"\\n\")) {\n if (line.match(/^\\s{2}- name:/)) {\n if (current?.name) {\n if (currentCreatedBy?.owner) {\n (current.created_by ??= []).push(currentCreatedBy);\n currentCreatedBy = null;\n }\n models.push({\n name: current.name,\n independently_created: current.independently_created ?? false,\n creation_file: current.creation_file,\n creation_function: current.creation_function,\n side_effects: current.side_effects,\n created_by: current.created_by ?? [],\n });\n }\n current = { name: line.match(/name:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim() };\n inCreatedBy = false;\n currentCreatedBy = null;\n continue;\n }\n\n if (!current) continue;\n\n const kvMatch = line.match(/^\\s{4}(\\w+):\\s*(.+)/);\n if (kvMatch && !inCreatedBy) {\n const [, key, val] = kvMatch;\n const v = val!.replace(/^[\"']|[\"']$/g, \"\").trim();\n switch (key) {\n case \"independently_created\":\n current.independently_created = v === \"true\";\n break;\n case \"creation_file\":\n current.creation_file = v;\n break;\n case \"creation_function\":\n current.creation_function = v;\n break;\n }\n }\n\n if (line.match(/^\\s{4}side_effects:/)) {\n current.side_effects = [];\n continue;\n }\n if (current.side_effects !== undefined && line.match(/^\\s{6}-\\s/)) {\n const val = line.replace(/^\\s{6}-\\s*/, \"\").replace(/^[\"']|[\"']$/g, \"\").trim();\n if (val) current.side_effects.push(val);\n continue;\n }\n\n if (line.match(/^\\s{4}created_by:/)) {\n current.created_by = [];\n current.side_effects = undefined;\n inCreatedBy = true;\n continue;\n }\n\n if (inCreatedBy) {\n if (line.match(/^\\s{6}- owner:/)) {\n if (currentCreatedBy?.owner) {\n current.created_by!.push(currentCreatedBy);\n }\n currentCreatedBy = { owner: line.match(/owner:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim() ?? \"\" };\n continue;\n }\n if (currentCreatedBy && line.match(/^\\s{8}via:/)) {\n currentCreatedBy.via = line.match(/via:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim();\n continue;\n }\n if (currentCreatedBy && line.match(/^\\s{8}why:/)) {\n currentCreatedBy.why = line.match(/why:\\s*\"?([^\"'\\n]+)\"?/)?.[1]?.trim();\n continue;\n }\n }\n }\n\n if (current?.name) {\n if (currentCreatedBy?.owner) {\n (current.created_by ??= []).push(currentCreatedBy);\n }\n models.push({\n name: current.name,\n independently_created: current.independently_created ?? false,\n creation_file: current.creation_file,\n creation_function: current.creation_function,\n side_effects: current.side_effects,\n created_by: current.created_by ?? [],\n });\n }\n\n return models;\n}\n\nexport function resolveEntityOrder(models: AuditedModel[]): string[] {\n const factoryModels = models.filter((m) => m.independently_created);\n const nameSet = new Set(factoryModels.map((m) => m.name));\n\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, string[]>();\n for (const m of factoryModels) {\n inDegree.set(m.name, 0);\n dependents.set(m.name, []);\n }\n\n for (const m of factoryModels) {\n for (const dep of m.created_by) {\n if (nameSet.has(dep.owner)) {\n inDegree.set(m.name, (inDegree.get(m.name) ?? 0) + 1);\n dependents.get(dep.owner)!.push(m.name);\n }\n }\n }\n\n const queue: string[] = [];\n for (const [name, deg] of inDegree) {\n if (deg === 0) queue.push(name);\n }\n queue.sort();\n\n const result: string[] = [];\n while (queue.length > 0) {\n const name = queue.shift()!;\n result.push(name);\n for (const dep of dependents.get(name) ?? []) {\n const newDeg = (inDegree.get(dep) ?? 1) - 1;\n inDegree.set(dep, newDeg);\n if (newDeg === 0) {\n queue.push(dep);\n queue.sort();\n }\n }\n }\n\n if (result.length !== factoryModels.length) {\n const missing = factoryModels\n .filter((m) => !result.includes(m.name))\n .map((m) => m.name);\n console.warn(`[recipe-builder] Circular dependency detected for: ${missing.join(\", \")}. Appending in original order.`);\n for (const m of missing) result.push(m);\n }\n\n return result;\n}\n\nexport function getEntityDependencyChain(\n entityName: string,\n models: AuditedModel[],\n entityOrder: string[],\n): string[] {\n const modelMap = new Map(models.map((m) => [m.name, m]));\n const visited = new Set<string>();\n const chain: string[] = [];\n\n function walk(name: string) {\n if (visited.has(name)) return;\n visited.add(name);\n const model = modelMap.get(name);\n if (!model) return;\n for (const dep of model.created_by) {\n if (entityOrder.includes(dep.owner)) {\n walk(dep.owner);\n }\n }\n chain.push(name);\n }\n\n walk(entityName);\n return chain;\n}\n","import * as p from \"@clack/prompts\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { getModel } from \"../../../core/model\";\nimport { buildReadFileTool, buildGlobTool, buildGrepTool, buildBashTool } from \"../../../tools\";\nimport { loadGitignorePatterns } from \"../../../core/gitignore\";\nimport {\n ALL_ADAPTERS,\n ADAPTER_HINTS,\n adapterKey,\n adapterLabel,\n findAdapter,\n type TechStack,\n} from \"../state\";\n\nconst DOCS_BASE = \"https://docs.agent.autonoma.app\";\n\nconst SYSTEM_PROMPT = `You are a backend technology detector. Your job is to identify the programming language and web framework used by a project's backend/API server.\n\nExplore the project files to detect:\n1. The programming language (check package.json, requirements.txt, go.mod, Gemfile, pom.xml, composer.json, Cargo.toml, mix.exs)\n2. The web framework (check imports, config files, middleware setup)\n\nWhen done, call finish with your findings.`;\n\nexport async function detectTechStack(\n projectRoot: string,\n modelId?: string,\n nonInteractive?: boolean,\n): Promise<TechStack> {\n const model = getModel(modelId);\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n\n let detected: { language: string; framework: string } | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"tech-detect\", 10);\n\n const finishTool = tool({\n description: \"Report the detected backend technology stack.\",\n inputSchema: z.object({\n language: z.string().describe(\"Programming language: typescript, python, go, ruby, java, php, rust, elixir\"),\n framework: z.string().describe(\"Web framework: express, node, hono, web, flask, fastapi, django, gin, rails, rack, spring, laravel, axum, actix, plug\"),\n }),\n execute: async (input) => {\n detected = input;\n return { detected: input };\n },\n });\n\n const agentConfig = {\n id: \"tech-detect\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 10,\n tools: (_heartbeat: () => void) => ({\n read_file: buildReadFileTool(projectRoot),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n grep: buildGrepTool(projectRoot),\n bash: buildBashTool(projectRoot),\n finish: finishTool,\n }),\n onStepFinish,\n };\n\n p.log.info(\"First, we need to know your backend stack so we can point you to the right SDK adapter and give you correct code examples.\");\n\n await runAgent(agentConfig, \"Detect the backend programming language and web framework for this project. Check dependency files and imports. Call finish with your findings.\", () => detected);\n logger.summary();\n\n const suggested = detected ? findAdapter(detected.language, detected.framework) : undefined;\n\n if (nonInteractive && suggested) return suggested;\n\n if (!suggested) {\n p.log.warn(\n `Could not auto-detect an exact adapter for your backend.\\n` +\n ` If your framework uses the Web Standard Request/Response API (Next.js, Remix, Bun, etc.), choose \"Web Standard\".\\n` +\n ` You can also implement a custom adapter — see ${DOCS_BASE}/sdk/custom-adapter`,\n );\n }\n\n const options = ALL_ADAPTERS.map((a) => ({\n value: adapterKey(a),\n label: a === suggested ? `${adapterLabel(a)} (detected)` : adapterLabel(a),\n hint: ADAPTER_HINTS[adapterKey(a)] ?? a.adapterPackage,\n }));\n\n if (suggested) {\n const suggestedIdx = options.findIndex((o) => o.value === adapterKey(suggested));\n if (suggestedIdx > 0) {\n const [item] = options.splice(suggestedIdx, 1);\n options.unshift(item!);\n }\n }\n\n const selectMessage = detected\n ? `Select your backend adapter (we detected ${detected.language}/${detected.framework}):`\n : \"Select your backend adapter:\";\n\n const selected = await p.select({\n message: selectMessage,\n options,\n });\n\n if (p.isCancel(selected)) {\n throw new Error(\"Tech detection cancelled\");\n }\n\n const [lang, fw] = (selected as string).split(\":\");\n const adapter = findAdapter(lang!, fw!);\n if (!adapter) throw new Error(`Unknown adapter: ${selected}`);\n\n p.log.success(`Using ${adapterLabel(adapter)} — SDK: ${adapter.sdkPackage}, Adapter: ${adapter.adapterPackage}`);\n\n return adapter;\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"bun\" | \"pnpm\" | \"yarn\" | \"npm\";\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"bun.lock\")) || existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nexport function installCommand(pm: PackageManager, ...packages: string[]): string {\n const pkgs = packages.join(\" \");\n switch (pm) {\n case \"bun\": return `bun add ${pkgs}`;\n case \"pnpm\": return `pnpm add ${pkgs}`;\n case \"yarn\": return `yarn add ${pkgs}`;\n case \"npm\": return `npm install ${pkgs}`;\n }\n}\n\nexport function runCommand(pm: PackageManager): string {\n switch (pm) {\n case \"bun\": return \"bun run\";\n case \"pnpm\": return \"pnpm run\";\n case \"yarn\": return \"yarn run\";\n case \"npm\": return \"npm run\";\n }\n}\n\nexport function execCommand(pm: PackageManager, file: string): string {\n switch (pm) {\n case \"bun\": return `bun ${file}`;\n case \"pnpm\": return `pnpm tsx ${file}`;\n case \"yarn\": return `yarn tsx ${file}`;\n case \"npm\": return `npx tsx ${file}`;\n }\n}\n","import hljs from \"highlight.js\";\n\nconst RESET = \"\\x1b[0m\";\n\nconst ANSI: Record<string, string> = {\n reset: RESET,\n keyword: \"\\x1b[35m\",\n string: \"\\x1b[32m\",\n number: \"\\x1b[33m\",\n comment: \"\\x1b[2m\",\n built_in: \"\\x1b[33m\",\n type: \"\\x1b[33m\",\n title: \"\\x1b[36m\",\n literal: \"\\x1b[35m\",\n attr: \"\",\n params: \"\",\n function: \"\\x1b[36m\",\n property: \"\",\n punctuation: \"\\x1b[2m\",\n operator: \"\",\n variable: \"\",\n subst: \"\\x1b[36m\",\n \"template-variable\": \"\\x1b[36m\",\n meta: \"\\x1b[2m\",\n regexp: \"\\x1b[31m\",\n};\n\nfunction spanReplacer(_match: string, cls: string): string {\n const mainCls = cls.split(\" \")[0]!;\n return ANSI[mainCls] ?? \"\";\n}\n\nfunction htmlToAnsi(html: string): string {\n return html\n .replace(/<span class=\"hljs-([^\"]+)\">/g, spanReplacer)\n .replace(/<\\/span>/g, RESET)\n .replace(/'/g, \"'\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, '\"');\n}\n\nexport function highlightCode(code: string, language = \"typescript\"): string {\n try {\n const result = hljs.highlight(code, { language, ignoreIllegals: true });\n return htmlToAnsi(result.value);\n } catch {\n return code;\n }\n}\n\nexport function codeNoteFormat(line: string): string {\n if (line.includes(\"\\x1b[\")) return line;\n return highlightCode(line);\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { EntityProgress } from \"./state\";\nimport { getEntityDependencyChain, type AuditedModel } from \"./entity-order\";\n\nexport type RecipePayload = Record<string, Record<string, unknown>[]>;\n\nexport function buildSingleEntityRecipe(\n entityName: string,\n models: AuditedModel[],\n entityOrder: string[],\n allEntities: Record<string, EntityProgress>,\n): RecipePayload {\n const chain = getEntityDependencyChain(entityName, models, entityOrder);\n const recipe: RecipePayload = {};\n\n for (const name of chain) {\n const entity = allEntities[name];\n if (entity?.recipeData && entity.recipeData.length > 0) {\n recipe[name] = entity.recipeData;\n }\n }\n\n return recipe;\n}\n\nexport function buildFullRecipe(\n entityOrder: string[],\n allEntities: Record<string, EntityProgress>,\n): RecipePayload {\n const recipe: RecipePayload = {};\n\n for (const name of entityOrder) {\n const entity = allEntities[name];\n if (entity?.recipeData && entity.recipeData.length > 0) {\n recipe[name] = entity.recipeData;\n }\n }\n\n return recipe;\n}\n\nexport interface FullRecipeJson {\n version: number;\n source: { discoverPath: string; scenariosPath: string };\n validationMode: string;\n recipes: {\n name: string;\n description: string;\n create: RecipePayload;\n variables?: Record<string, unknown>[];\n validation: {\n status: string;\n method: string;\n up_ms?: number;\n down_ms?: number;\n };\n }[];\n}\n\nexport function buildSubmittableRecipe(\n create: RecipePayload,\n description: string,\n): FullRecipeJson {\n return {\n version: 1,\n source: {\n discoverPath: \"discover.json\",\n scenariosPath: \"scenarios.md\",\n },\n validationMode: \"endpoint-lifecycle\",\n recipes: [\n {\n name: \"standard\",\n description,\n create,\n validation: {\n status: \"validated\",\n method: \"endpoint-up-down\",\n },\n },\n ],\n };\n}\n\nconst RECIPE_FILE = \"recipe.json\";\n\nexport async function saveRecipe(outputDir: string, recipe: FullRecipeJson): Promise<void> {\n await writeFile(join(outputDir, RECIPE_FILE), JSON.stringify(recipe, null, 2), \"utf-8\");\n}\n\nexport async function loadRecipe(outputDir: string): Promise<FullRecipeJson | null> {\n try {\n const raw = await readFile(join(outputDir, RECIPE_FILE), \"utf-8\");\n return JSON.parse(raw) as FullRecipeJson;\n } catch {\n return null;\n }\n}\n","import { createHmac } from \"node:crypto\";\n\nexport interface SdkClientConfig {\n endpointUrl: string;\n sharedSecret: string;\n}\n\nexport interface SdkResponse {\n ok: boolean;\n status: number;\n body: unknown;\n}\n\nfunction sign(body: string, secret: string): string {\n return createHmac(\"sha256\", secret).update(body).digest(\"hex\");\n}\n\nasync function sendRequest(config: SdkClientConfig, payload: unknown): Promise<SdkResponse> {\n const rawBody = JSON.stringify(payload);\n const signature = sign(rawBody, config.sharedSecret);\n\n const res = await fetch(config.endpointUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-signature\": signature,\n },\n body: rawBody,\n });\n\n let body: unknown;\n const text = await res.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n return { ok: res.ok, status: res.status, body };\n}\n\nexport async function discover(config: SdkClientConfig): Promise<SdkResponse> {\n return sendRequest(config, { action: \"discover\" });\n}\n\nexport async function up(\n config: SdkClientConfig,\n create: Record<string, unknown[]>,\n testRunId: string,\n): Promise<SdkResponse> {\n return sendRequest(config, {\n action: \"up\",\n testRunId,\n environment: \"test\",\n create,\n });\n}\n\nexport async function down(\n config: SdkClientConfig,\n refsToken: string,\n): Promise<SdkResponse> {\n return sendRequest(config, {\n action: \"down\",\n refsToken,\n });\n}\n","import * as p from \"@clack/prompts\";\nimport { writeFile, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { spawn } from \"node:child_process\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { LanguageModel } from \"ai\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { buildReadFileTool, buildGlobTool, buildGrepTool } from \"../../../tools\";\nimport { buildAskUserTool } from \"../../../tools/ask-user\";\nimport { loadGitignorePatterns } from \"../../../core/gitignore\";\nimport { detectPackageManager, installCommand } from \"../../../core/detect-pkg-manager\";\nimport type { RecipeBuilderState, TechStack, EntityProgress } from \"../state\";\nimport { adapterLabel, saveRecipeState } from \"../state\";\nimport { codeNoteFormat } from \"../../../core/highlight\";\nimport type { AuditedModel } from \"../entity-order\";\nimport { notify } from \"../../../core/notify\";\nimport { buildSingleEntityRecipe } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\n\nconst PROPOSAL_PROMPT = `You are a recipe data designer. Given an entity from the entity audit and the scenario data, produce a JSON array of records for this entity.\n\nRules:\n- Use EXACT values from the scenarios.md file\n- Add _alias fields (e.g., \"entity_1\", \"entity_2\") for referencing\n- Use { \"_ref\": \"alias\" } syntax to reference previously-completed parent entities\n- Match the field names and types from the entity audit's creation schema\n- Include realistic, diverse data that covers different enum values\n- For JSON/JSONB fields, use actual nested objects and arrays — NOT stringified JSON.\n WRONG: \"metadata\": \"{\\\\\"key\\\\\": \\\\\"value\\\\\"}\"\n RIGHT: \"metadata\": {\"key\": \"value\"}\n- If you encounter untyped JSON/JSONB fields, use ask_user to ask the developer about the expected schema\n\nWhen done, call finish with the JSON array.`;\n\nconst INSTRUCTIONS_PROMPT = `You are a pedagogical guide helping a developer implement an Autonoma SDK factory.\n\nGiven the entity audit information and the project's source code, produce clear, copy-pasteable instructions for implementing this factory. The developer will likely hand these to Claude or another AI assistant.\n\nInclude:\n1. What to import (service classes, validators, Zod schemas)\n2. The factory shape (inputSchema, create function, teardown function)\n3. Where create() should call into (the project's existing service functions)\n4. What teardown() should delete\n\nBe specific — reference actual file paths, function names, and types from the codebase.\n\nWhen done, call finish with the instructions text.`;\n\nasync function proposeRecipeData(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n model: LanguageModel,\n outputDir: string,\n _projectRoot: string,\n completedEntities: Record<string, EntityProgress>,\n): Promise<Record<string, unknown>[]> {\n let result: Record<string, unknown>[] | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`propose:${entityName}`, 20);\n\n const finishTool = tool({\n description: \"Submit the proposed recipe data as a JSON array of records.\",\n inputSchema: z.object({\n records: z.array(z.record(z.string(), z.unknown())).describe(\"Array of record objects for this entity\"),\n }),\n execute: async (input) => {\n result = input.records;\n return { accepted: true };\n },\n });\n\n const completedAliases = Object.entries(completedEntities)\n .filter(([, e]) => e.recipeData && e.recipeData.length > 0)\n .map(([name, e]) => `${name}: aliases ${e.recipeData!.map((r) => r._alias ?? \"?\").join(\", \")}`)\n .join(\"\\n\");\n\n const prompt = `[${entityIndex + 1}/${totalEntities}] Propose recipe data for entity \"${entityName}\".\n\nRead scenarios.md and entity-audit.md from the output directory. Design records that match the scenario data.\n\n${completedAliases ? `Already completed entities (use _ref to reference their aliases):\\n${completedAliases}\\n` : \"This is a root entity — no parent references needed.\"}\n\nCall finish with the JSON array of records.`;\n\n const readOutputTool = buildReadFileTool(outputDir);\n\n await runAgent(\n {\n id: `propose-${entityName}`,\n systemPrompt: PROPOSAL_PROMPT,\n model,\n maxSteps: 20,\n tools: (_heartbeat: () => void) => ({\n read_output: readOutputTool,\n ask_user: buildAskUserTool(),\n finish: finishTool,\n }),\n onStepFinish,\n },\n prompt,\n () => result,\n );\n logger.summary();\n\n return result ?? [];\n}\n\nasync function reviseRecipeData(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n current: Record<string, unknown>[],\n feedback: string,\n model: LanguageModel,\n outputDir: string,\n): Promise<Record<string, unknown>[]> {\n let revised: Record<string, unknown>[] | undefined;\n\n const finishTool = tool({\n description: \"Submit the fixed recipe data.\",\n inputSchema: z.object({\n records: z.array(z.record(z.string(), z.unknown())),\n }),\n execute: async (input) => {\n revised = input.records;\n return { done: true };\n },\n });\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`fix:${entityName}`, 15);\n\n await runAgent(\n {\n id: `fix-${entityName}`,\n systemPrompt: `You are fixing recipe data that failed validation. Read the error, the current data, and the user's feedback. Read scenarios.md and entity-audit.md if needed. Fix the data and call finish.\n\nRules:\n- _alias fields must be unique identifiers (e.g., \"card_1\", \"transaction_1\")\n- _ref fields reference aliases from OTHER entities that were already created\n- Read scenarios.md to verify you're using correct alias names from parent entities\n- Field names must match the entity's schema from entity-audit.md`,\n model,\n maxSteps: 15,\n tools: (_heartbeat: () => void) => ({\n read_output: buildReadFileTool(outputDir),\n finish: finishTool,\n }),\n onStepFinish,\n },\n `[${entityIndex + 1}/${totalEntities}] Fix recipe data for \"${entityName}\".\n\nCurrent data that failed:\n${JSON.stringify(current, null, 2)}\n\nProblem:\n${feedback}\n\nRead scenarios.md and entity-audit.md to understand the correct aliases and schema. Fix the data and call finish.`,\n () => revised,\n );\n logger.summary();\n\n if (revised) {\n p.note(JSON.stringify(revised, null, 2), `Fixed data for ${entityName}`, { format: codeNoteFormat });\n return revised;\n }\n\n p.log.warn(\"Could not auto-fix. Returning original data.\");\n return current;\n}\n\nasync function generateInstructions(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n isFirst: boolean,\n techStack: TechStack,\n auditModel: AuditedModel,\n recipeData: Record<string, unknown>[],\n model: LanguageModel,\n projectRoot: string,\n outputDir: string,\n): Promise<string> {\n let result: string | undefined;\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`instructions:${entityName}`, 15);\n\n const finishTool = tool({\n description: \"Submit the implementation instructions.\",\n inputSchema: z.object({\n instructions: z.string().describe(\"Complete, copy-pasteable implementation instructions\"),\n }),\n execute: async (input) => {\n result = input.instructions;\n return { done: true };\n },\n });\n\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n\n const pm = detectPackageManager(projectRoot);\n const installCmd = techStack.language === \"typescript\"\n ? installCommand(pm, techStack.sdkPackage, techStack.adapterPackage)\n : `pip install ${techStack.sdkPackage}[${techStack.framework}]`;\n\n const setupContext = isFirst\n ? `\\nThis is the FIRST entity. Include one-time setup instructions:\n- Install SDK: ${installCmd}\n- Create the route/endpoint file\n- Add env vars: AUTONOMA_SHARED_SECRET, AUTONOMA_SIGNING_SECRET\n- Explain: \"This single endpoint handles discover/up/down — the SDK routes internally\"\n- Include the auth callback in createHandler config. The auth callback receives the first User record created during UP and must return real credentials the test runner can use to authenticate. Three patterns:\n - Session cookies (most web apps): create a session, return { cookies: [{ name, value, httpOnly, sameSite, path }] }\n - JWT bearer token (SPAs/APIs): sign a JWT, return { headers: { Authorization: \"Bearer <real-token>\" } }\n - Email/password (mobile/native login): return { credentials: { email: user.email, password: \"the-test-password\" } }\n Choose the pattern that matches how this app authenticates users. Read the project's auth code to determine which.\\n`\n : \"\";\n\n const prompt = `[${entityIndex + 1}/${totalEntities}] Generate implementation instructions for the \"${entityName}\" factory.\n${setupContext}\nEntity audit info:\n- Creation file: ${auditModel.creation_file ?? \"unknown\"}\n- Creation function: ${auditModel.creation_function ?? \"unknown\"}\n- Side effects: ${auditModel.side_effects?.join(\", \") ?? \"none\"}\n- Dependencies: ${auditModel.created_by.map((d) => d.owner).join(\", \") || \"none (root entity)\"}\n\nAccepted recipe data (${recipeData.length} records):\n${JSON.stringify(recipeData, null, 2)}\n\nTech stack: ${adapterLabel(techStack)}\n\nRead the creation file from the project to understand the existing service/function. Then produce instructions.`;\n\n await runAgent(\n {\n id: `instructions-${entityName}`,\n systemPrompt: INSTRUCTIONS_PROMPT,\n model,\n maxSteps: 15,\n tools: (_heartbeat: () => void) => ({\n read_file: buildReadFileTool(projectRoot),\n read_output: buildReadFileTool(outputDir),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n grep: buildGrepTool(projectRoot),\n finish: finishTool,\n }),\n onStepFinish,\n },\n prompt,\n () => result,\n );\n logger.summary();\n\n return result ?? \"No instructions generated. Check the entity audit for creation_file and creation_function.\";\n}\n\nasync function reviewRecipeData(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n proposed: Record<string, unknown>[],\n model: LanguageModel,\n outputDir: string,\n): Promise<Record<string, unknown>[]> {\n p.log.info(\n \"Legend for recipe fields:\\n\" +\n \" _alias — Internal ID used to reference this record from other entities (e.g., { \\\"_ref\\\": \\\"org_1\\\" })\\n\" +\n \" _ref — Reference to a record created by a parent entity's _alias\\n\" +\n \" All other fields are the actual data that will be inserted into your database.\",\n );\n\n p.note(JSON.stringify(proposed, null, 2), `Proposed data for ${entityName} (${proposed.length} records)`, { format: codeNoteFormat });\n\n p.log.info(\n \"Review checklist:\\n\" +\n \" - Do field values match your real data patterns?\\n\" +\n \" - Are _ref references pointing to correct parent aliases?\\n\" +\n \" - Are enum fields varied across records (not all the same value)?\\n\" +\n \" - Are there enough records for your test scenarios?\",\n );\n\n while (true) {\n const action = await p.select({\n message: `[${entityIndex + 1}/${totalEntities}] ${entityName} — does this data look right?`,\n options: [\n { value: \"keep\", label: \"Yes, keep\" },\n { value: \"chat\", label: \"No, let's chat\" },\n { value: \"edit\", label: \"No, edit manually\" },\n ],\n });\n\n if (p.isCancel(action)) throw new Error(\"Recipe review cancelled\");\n\n if (action === \"keep\") return proposed;\n\n if (action === \"edit\") {\n const tmpPath = join(tmpdir(), `autonoma-recipe-${entityName}.json`);\n await writeFile(tmpPath, JSON.stringify(proposed, null, 2), \"utf-8\");\n\n const editor = process.env.EDITOR ?? process.env.VISUAL ?? \"vi\";\n p.log.info(`Opening ${editor}... Save and close when done.`);\n\n await new Promise<void>((resolve, reject) => {\n const proc = spawn(editor, [tmpPath], { stdio: \"inherit\" });\n proc.on(\"close\", () => resolve());\n proc.on(\"error\", reject);\n });\n\n const edited = await readFile(tmpPath, \"utf-8\");\n try {\n proposed = JSON.parse(edited);\n p.note(JSON.stringify(proposed, null, 2), `Updated data for ${entityName}`, { format: codeNoteFormat });\n } catch (err) {\n p.log.error(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}. Try again.`);\n }\n continue;\n }\n\n if (action === \"chat\") {\n const feedback = await p.text({\n message: \"What should be changed?\",\n placeholder: \"e.g., add more records, change field values, fix references...\",\n });\n\n if (p.isCancel(feedback) || !(feedback as string).trim()) continue;\n\n let revised: Record<string, unknown>[] | undefined;\n const finishTool = tool({\n description: \"Submit revised recipe data.\",\n inputSchema: z.object({\n records: z.array(z.record(z.string(), z.unknown())),\n }),\n execute: async (input) => {\n revised = input.records;\n return { done: true };\n },\n });\n\n const { logger, onStepFinish } = buildDefaultStepLogger(`revise:${entityName}`, 10);\n\n await runAgent(\n {\n id: `revise-${entityName}`,\n systemPrompt: \"You are revising recipe data based on user feedback. Read the current data, apply the feedback, and call finish with the updated records.\",\n model,\n maxSteps: 10,\n tools: (_heartbeat: () => void) => ({\n read_output: buildReadFileTool(outputDir),\n finish: finishTool,\n }),\n onStepFinish,\n },\n `Current data for ${entityName}:\\n${JSON.stringify(proposed, null, 2)}\\n\\nUser feedback: \"${feedback}\"\\n\\nRevise the data and call finish.`,\n () => revised,\n );\n logger.summary();\n\n if (revised) {\n proposed = revised;\n p.note(JSON.stringify(proposed, null, 2), `Revised data for ${entityName}`, { format: codeNoteFormat });\n }\n }\n }\n}\n\ntype TestResult = \"success\" | \"skip\" | { feedback: string };\n\nasync function promptOnFailure(entityName: string, errorBody: unknown): Promise<\"retry\" | \"skip\" | { feedback: string }> {\n notify(\"Autonoma\", `${entityName} — failed, action needed`);\n const action = await p.select({\n message: \"What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Yes, retry — I fixed my handler code\", hint: \"Send the same request again\" },\n { value: \"feedback\", label: \"Yes, fix the recipe data\", hint: \"The request data is wrong — I'll explain what to change\" },\n { value: \"skip\", label: \"No, skip this entity\", hint: \"Move on to the next entity\" },\n ],\n });\n if (p.isCancel(action)) throw new Error(\"Entity loop cancelled\");\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") return \"retry\";\n\n const fb = await p.text({\n message: \"What's wrong with the recipe data?\",\n placeholder: \"e.g. Transaction references acc_1 but Account uses account_1 as its alias\",\n });\n if (p.isCancel(fb)) throw new Error(\"Entity loop cancelled\");\n const errorContext = errorBody ? `\\nServer error: ${JSON.stringify(errorBody)}` : \"\";\n return { feedback: `${(fb as string).trim()}${errorContext}` };\n}\n\nasync function testUpDown(\n entityName: string,\n entityIndex: number,\n totalEntities: number,\n sdkConfig: SdkClientConfig,\n recipe: Record<string, unknown[]>,\n): Promise<TestResult> {\n p.log.info(`Let's verify this factory works. We'll send a test request to create ${entityName}, then check the database.`);\n\n // UP with retry loop\n while (true) {\n const testRunId = `test-${Date.now()}`;\n\n p.log.step(`[${entityIndex + 1}/${totalEntities}] Sending UP request...`);\n\n let upResult: Awaited<ReturnType<typeof sdk.up>>;\n try {\n upResult = await sdk.up(sdkConfig, recipe, testRunId);\n } catch (err) {\n p.log.error(`UP request failed: ${err instanceof Error ? err.message : String(err)}`);\n const action = await promptOnFailure(entityName, null);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n if (!upResult.ok) {\n p.log.error(`UP failed (HTTP ${upResult.status}):`);\n console.log(JSON.stringify(upResult.body, null, 2));\n const action = await promptOnFailure(entityName, upResult.body);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n p.log.success(`UP succeeded!`);\n console.log(JSON.stringify(upResult.body, null, 2));\n\n const refsToken = (upResult.body as Record<string, unknown>)?.refsToken as string | undefined;\n if (!refsToken) {\n p.log.error(\"No refsToken in UP response — cannot test DOWN.\");\n return \"skip\";\n }\n\n // DOWN with retry loop\n p.log.info(\"Now let's verify teardown works — leftover test data would pollute your database.\");\n while (true) {\n p.log.step(`[${entityIndex + 1}/${totalEntities}] Sending DOWN request...`);\n\n let downResult: Awaited<ReturnType<typeof sdk.down>>;\n try {\n downResult = await sdk.down(sdkConfig, refsToken);\n } catch (err) {\n p.log.error(`DOWN request failed: ${err instanceof Error ? err.message : String(err)}`);\n const action = await promptOnFailure(entityName, null);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n if (!downResult.ok) {\n p.log.error(`DOWN failed (HTTP ${downResult.status}):`);\n console.log(JSON.stringify(downResult.body, null, 2));\n const action = await promptOnFailure(entityName, downResult.body);\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n\n p.log.success(\"DOWN succeeded!\");\n return \"success\";\n }\n }\n}\n\nexport async function runEntityLoop(\n state: RecipeBuilderState,\n models: AuditedModel[],\n model: LanguageModel,\n projectRoot: string,\n outputDir: string,\n nonInteractive?: boolean,\n): Promise<void> {\n const total = state.entityOrder.length;\n const modelMap = new Map(models.map((m) => [m.name, m]));\n\n p.log.info(\n `We're going to set up your test data factories one entity at a time. Each factory teaches the Autonoma SDK how to create and tear down a specific type of record in YOUR database, using YOUR existing service functions.\\n\\n We'll test each one live before moving on — this way if something breaks, you'll know exactly which entity caused it. Let's start with the root entities (no dependencies), then work through the dependents.`,\n );\n\n for (let i = state.currentEntityIndex; i < total; i++) {\n const entityName = state.entityOrder[i]!;\n const auditModel = modelMap.get(entityName);\n if (!auditModel) {\n p.log.warn(`[${i + 1}/${total}] ${entityName} — not found in entity audit, skipping`);\n state.entities[entityName] = {\n entityName,\n status: \"skipped\",\n recipeData: null,\n errorLog: [\"Not found in entity audit\"],\n };\n state.currentEntityIndex = i + 1;\n await saveRecipeState(outputDir, state);\n continue;\n }\n\n const existing = state.entities[entityName];\n if (existing?.status === \"tested-down\") {\n p.log.info(`[${i + 1}/${total}] ${entityName} — already done, skipping`);\n continue;\n }\n\n const isRoot = auditModel.created_by.length === 0;\n const depInfo = isRoot\n ? \"This is a root entity — no dependencies.\"\n : `This depends on: ${auditModel.created_by.map((d) => d.owner).join(\", \")}`;\n\n p.log.step(`[${i + 1}/${total}] ${entityName}`);\n p.log.info(depInfo);\n\n // A. Propose recipe data\n let recipeData = existing?.recipeData;\n if (!recipeData || existing?.status === \"pending\") {\n recipeData = await proposeRecipeData(\n entityName, i, total, model, outputDir, projectRoot, state.entities,\n );\n }\n\n // B. User review\n if (!nonInteractive) {\n recipeData = await reviewRecipeData(entityName, i, total, recipeData, model, outputDir);\n }\n\n state.entities[entityName] = {\n entityName,\n status: \"recipe-accepted\",\n recipeData,\n errorLog: existing?.errorLog ?? [],\n };\n state.currentEntityIndex = i;\n await saveRecipeState(outputDir, state);\n\n // C. Implementation instructions\n if (!nonInteractive) {\n const instructions = await generateInstructions(\n entityName, i, total,\n i === 0,\n state.techStack!,\n auditModel,\n recipeData,\n model,\n projectRoot,\n outputDir,\n );\n p.note(instructions, `Implementation guide for ${entityName}`, { format: codeNoteFormat });\n\n const DOCS_BASE = \"https://docs.agent.autonoma.app\";\n p.log.info(\n `Copy the instructions above into Claude Code or your AI coding assistant.\\n` +\n ` They can implement the factory directly in your codebase.\\n\\n` +\n ` Autonoma SDK docs: ${DOCS_BASE}/sdk/environment-factory`,\n );\n\n if (i === 0) {\n p.log.info(\"This is your first factory — the instructions include one-time SDK setup. Subsequent entities will only need the factory function.\");\n }\n\n notify(\"Autonoma\", `${entityName} — implementation ready, waiting for you`);\n const ready = await p.confirm({\n message: `[${i + 1}/${total}] Is your server running with the ${entityName} factory?`,\n });\n if (p.isCancel(ready)) throw new Error(\"Entity loop cancelled\");\n\n if (!ready) {\n p.log.info(\"Take your time implementing. Run again with --resume to continue from here.\");\n return;\n }\n }\n\n // D + E. Test UP/DOWN\n if (!nonInteractive && state.techStack) {\n if (!state.sharedSecret) {\n const bytes = new Uint8Array(32);\n crypto.getRandomValues(bytes);\n const secret = [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n state.sharedSecret = secret;\n await saveRecipeState(outputDir, state);\n\n await writeFile(\n join(outputDir, \"autonoma-config.json\"),\n JSON.stringify({ sharedSecret: secret, endpointUrl: state.sdkEndpointUrl }, null, 2),\n \"utf-8\",\n );\n\n p.note(\n `AUTONOMA_SHARED_SECRET=${secret}\\n\\n` +\n `Add this to your server's .env file and restart it.\\n` +\n `This is a 64-character hex key used for HMAC-SHA256 request signing.\\n` +\n `The same value must be set in both your server and the Autonoma dashboard.\\n\\n` +\n `Saved to: ${join(outputDir, \"autonoma-config.json\")}`,\n \"Shared secret generated\",\n );\n\n const secretReady = await p.confirm({\n message: \"Did you add the secret to your .env and restart the server?\",\n });\n if (p.isCancel(secretReady)) throw new Error(\"Entity loop cancelled\");\n if (!secretReady) {\n p.log.info(\"Add the secret and run again with --resume to continue.\");\n return;\n }\n }\n\n if (!state.sdkEndpointUrl) {\n const url = await p.text({\n message: \"What's your SDK endpoint URL?\",\n placeholder: \"http://localhost:3000/api/autonoma\",\n defaultValue: \"http://localhost:3000/api/autonoma\",\n });\n if (p.isCancel(url)) throw new Error(\"Entity loop cancelled\");\n state.sdkEndpointUrl = (url as string).trim() || \"http://localhost:3000/api/autonoma\";\n await saveRecipeState(outputDir, state);\n\n await writeFile(\n join(outputDir, \"autonoma-config.json\"),\n JSON.stringify({ sharedSecret: state.sharedSecret, endpointUrl: state.sdkEndpointUrl }, null, 2),\n \"utf-8\",\n );\n }\n\n const sdkConfig: SdkClientConfig = {\n endpointUrl: state.sdkEndpointUrl,\n sharedSecret: state.sharedSecret,\n };\n\n let testDone = false;\n while (!testDone) {\n const singleRecipe = buildSingleEntityRecipe(entityName, models, state.entityOrder, state.entities);\n const testResult = await testUpDown(entityName, i, total, sdkConfig, singleRecipe);\n\n if (testResult === \"success\") {\n state.entities[entityName]!.status = \"tested-down\";\n p.log.success(`[${i + 1}/${total}] ${entityName} — factory verified`);\n testDone = true;\n } else if (testResult === \"skip\") {\n state.entities[entityName]!.status = \"skipped\";\n state.entities[entityName]!.errorLog.push(\"UP/DOWN test skipped by user\");\n p.log.warn(`[${i + 1}/${total}] ${entityName} — skipped, continuing to next entity`);\n testDone = true;\n } else {\n p.log.info(`Re-generating recipe data for ${entityName} based on your feedback...`);\n const revised = await reviseRecipeData(\n entityName, i, total, state.entities[entityName]!.recipeData!, testResult.feedback, model, outputDir,\n );\n state.entities[entityName]!.recipeData = revised;\n await saveRecipeState(outputDir, state);\n }\n }\n } else if (nonInteractive) {\n state.entities[entityName]!.status = \"tested-down\";\n }\n\n state.currentEntityIndex = i + 1;\n await saveRecipeState(outputDir, state);\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { notify } from \"../../../core/notify\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { saveRecipeState } from \"../state\";\nimport type { AuditedModel } from \"../entity-order\";\nimport { buildFullRecipe } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\n\nexport async function runFullValidation(\n state: RecipeBuilderState,\n _models: AuditedModel[],\n outputDir: string,\n): Promise<boolean> {\n const total = state.entityOrder.length;\n\n p.log.info(\n `All individual factories work. Now let's create EVERYTHING together and verify the app looks right with a full dataset. This is the recipe that will run before every test execution.`,\n );\n\n if (!state.sdkEndpointUrl) {\n const url = await p.text({\n message: \"What's your SDK endpoint URL?\",\n placeholder: \"http://localhost:3000/api/autonoma\",\n defaultValue: \"http://localhost:3000/api/autonoma\",\n });\n if (p.isCancel(url)) throw new Error(\"Cancelled\");\n state.sdkEndpointUrl = (url as string).trim() || \"http://localhost:3000/api/autonoma\";\n await saveRecipeState(outputDir, state);\n }\n\n const sdkConfig: SdkClientConfig = {\n endpointUrl: state.sdkEndpointUrl,\n sharedSecret: state.sharedSecret ?? \"\",\n };\n\n const fullRecipe = buildFullRecipe(state.entityOrder, state.entities);\n\n // UP with retry loop\n while (true) {\n const testRunId = `full-${Date.now()}`;\n p.log.step(`[Full validation] Creating all ${total} entities...`);\n\n let upResult: Awaited<ReturnType<typeof sdk.up>>;\n try {\n upResult = await sdk.up(sdkConfig, fullRecipe, testRunId);\n } catch (err) {\n p.log.error(`Full UP request failed: ${err instanceof Error ? err.message : String(err)}`);\n notify(\"Autonoma\", \"Full validation UP failed, action needed\");\n const action = await p.select({\n message: \"What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Yes, retry — I fixed it\", hint: \"Send the request again\" },\n { value: \"skip\", label: \"No, skip full validation\", hint: \"Continue to test generation\" },\n ],\n });\n if (p.isCancel(action)) throw new Error(\"Cancelled\");\n if (action === \"skip\") return false;\n continue;\n }\n\n if (!upResult.ok) {\n p.log.error(`Full UP failed (HTTP ${upResult.status}):`);\n console.log(JSON.stringify(upResult.body, null, 2));\n notify(\"Autonoma\", \"Full validation UP failed, action needed\");\n const action = await p.select({\n message: \"What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Yes, retry — I fixed it\", hint: \"Send the request again\" },\n { value: \"skip\", label: \"No, skip full validation\", hint: \"Continue to test generation\" },\n ],\n });\n if (p.isCancel(action)) throw new Error(\"Cancelled\");\n if (action === \"skip\") return false;\n continue;\n }\n\n p.log.success(\"Full UP succeeded!\");\n const body = upResult.body as Record<string, unknown>;\n const refsToken = body.refsToken as string | undefined;\n\n const auth = body.auth as Record<string, unknown> | undefined;\n if (auth && Object.keys(auth).length > 0) {\n const authJson = JSON.stringify(auth, null, 2);\n const looksPlaceholder = authJson.includes(\"test-token\") || authJson.includes(\"placeholder\") || authJson.includes(\"todo\");\n\n p.note(\n authJson + \"\\n\\n\" +\n \"These are the credentials your auth callback returns.\\n\" +\n \"The test runner will use them to authenticate as the test user when executing tests.\" +\n (looksPlaceholder\n ? \"\\n\\n⚠ This looks like a placeholder. Update your auth callback to return real credentials\\n\" +\n \"(a valid JWT, session cookie, or email/password) so the test runner can actually log in.\"\n : \"\"),\n \"Auth credentials\",\n );\n } else {\n p.log.warn(\n \"No auth credentials returned. Your createHandler's auth callback must return credentials \" +\n \"the test runner can use to log in (cookies, headers, or email/password). Without it, tests can't authenticate.\",\n );\n }\n\n p.log.info(\"Browse the app and check if the test data looks right.\");\n\n notify(\"Autonoma\", \"Full validation succeeded — review the app\");\n const looksGood = await p.confirm({\n message: \"Does the app look right with the test data?\",\n });\n\n if (p.isCancel(looksGood)) throw new Error(\"Cancelled\");\n\n if (!looksGood) {\n p.log.info(\"You can adjust the recipe by editing recipe.json or re-running individual entities with --resume.\");\n }\n\n if (refsToken) {\n p.log.step(\"[Full validation] Tearing down all entities...\");\n\n let downResult: Awaited<ReturnType<typeof sdk.down>>;\n try {\n downResult = await sdk.down(sdkConfig, refsToken);\n } catch (err) {\n p.log.error(`Full DOWN request failed: ${err instanceof Error ? err.message : String(err)}`);\n return false;\n }\n\n if (!downResult.ok) {\n p.log.error(`Full DOWN failed (HTTP ${downResult.status}):`);\n console.log(JSON.stringify(downResult.body, null, 2));\n return false;\n }\n\n p.log.success(\"Full lifecycle works. All data was created and torn down cleanly.\");\n }\n\n return true;\n }\n}\n","import * as p from \"@clack/prompts\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { buildFullRecipe, buildSubmittableRecipe, saveRecipe } from \"../recipe\";\n\nexport async function runSubmit(\n state: RecipeBuilderState,\n outputDir: string,\n autonomaApiUrl?: string,\n autonomaApiToken?: string,\n autonomaGenerationId?: string,\n): Promise<string> {\n const fullCreate = buildFullRecipe(state.entityOrder, state.entities);\n const recipe = buildSubmittableRecipe(fullCreate, \"Standard test scenario with realistic data\");\n\n await saveRecipe(outputDir, recipe);\n p.log.success(\"Recipe saved to recipe.json\");\n\n if (!autonomaApiUrl || !autonomaApiToken || !autonomaGenerationId) {\n p.log.info(\"Autonoma API credentials not configured — recipe saved locally. Submit manually or configure AUTONOMA_API_URL, AUTONOMA_API_TOKEN, AUTONOMA_GENERATION_ID.\");\n return \"recipe.json\";\n }\n\n const url = `${autonomaApiUrl}/v1/setup/setups/${autonomaGenerationId}/scenario-recipe-versions`;\n\n p.log.step(\"Submitting recipe to Autonoma...\");\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${autonomaApiToken}`,\n },\n body: JSON.stringify(recipe),\n });\n\n if (res.ok) {\n p.log.success(`Recipe submitted successfully (HTTP ${res.status})`);\n } else {\n const text = await res.text();\n p.log.error(`Recipe submission failed (HTTP ${res.status}): ${text}`);\n }\n\n return \"recipe.json\";\n}\n","import * as p from \"@clack/prompts\";\nimport type { AppConfig } from \"../../config\";\nimport type { AgentResult } from \"../../core/agent\";\nimport type { ProjectContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport {\n initialRecipeState,\n loadRecipeState,\n saveRecipeState,\n} from \"./state\";\nimport { parseEntityAudit, resolveEntityOrder } from \"./entity-order\";\nimport { detectTechStack } from \"./phases/tech-detect\";\nimport { runEntityLoop } from \"./phases/entity-loop\";\nimport { runFullValidation } from \"./phases/full-validation\";\nimport { runSubmit } from \"./phases/submit\";\n\nexport interface RecipeBuilderInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n config: AppConfig;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n}\n\nexport async function runRecipeBuilder(input: RecipeBuilderInput): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n let state = await loadRecipeState(input.outputDir) ?? initialRecipeState();\n\n const models = await parseEntityAudit(input.outputDir);\n\n // Phase 1: Tech detection\n if (state.phase === \"tech-detect\") {\n state.techStack = await detectTechStack(\n input.projectRoot,\n input.modelId,\n input.nonInteractive,\n );\n\n const entityOrder = resolveEntityOrder(models);\n state.entityOrder = entityOrder;\n state.entities = {};\n for (const name of entityOrder) {\n state.entities[name] = {\n entityName: name,\n status: \"pending\",\n recipeData: null,\n errorLog: [],\n };\n }\n\n state.phase = \"entity-loop\";\n\n if (input.config.sdkEndpointUrl) {\n state.sdkEndpointUrl = input.config.sdkEndpointUrl;\n }\n\n await saveRecipeState(input.outputDir, state);\n p.log.info(`Found ${entityOrder.length} entities needing factories. Processing in dependency order.`);\n }\n\n // Phase 2: Entity-by-entity loop\n if (state.phase === \"entity-loop\") {\n await runEntityLoop(\n state,\n models,\n model,\n input.projectRoot,\n input.outputDir,\n input.nonInteractive,\n );\n\n const allDone = state.entityOrder.every(\n (name) => {\n const e = state.entities[name];\n return e?.status === \"tested-down\" || e?.status === \"skipped\";\n },\n );\n\n if (allDone) {\n state.phase = input.nonInteractive ? \"submit\" : \"full-validation\";\n await saveRecipeState(input.outputDir, state);\n } else {\n return {\n success: false,\n paused: true,\n artifacts: [],\n summary: \"Paused — run again with --resume to continue from where you left off\",\n };\n }\n }\n\n // Phase 3: Full validation\n if (state.phase === \"full-validation\") {\n const success = await runFullValidation(state, models, input.outputDir);\n if (success) {\n state.phase = \"submit\";\n await saveRecipeState(input.outputDir, state);\n } else {\n return {\n success: false,\n paused: true,\n artifacts: [],\n summary: \"Full validation skipped — run again with --resume to retry\",\n };\n }\n }\n\n // Phase 4: Submit\n if (state.phase === \"submit\") {\n const recipePath = await runSubmit(\n state,\n input.outputDir,\n process.env.AUTONOMA_API_URL,\n process.env.AUTONOMA_API_TOKEN,\n process.env.AUTONOMA_GENERATION_ID,\n );\n\n state.phase = \"done\";\n await saveRecipeState(input.outputDir, state);\n\n return {\n success: true,\n artifacts: [recipePath],\n summary: `Recipe builder complete. ${state.entityOrder.length} factories configured.`,\n };\n }\n\n return {\n success: true,\n artifacts: [],\n summary: \"Recipe builder already complete.\",\n };\n}\n","import { z } from \"zod\";\n\nexport interface ReviewRubric {\n name: string;\n systemPrompt: string;\n resultSchema: z.ZodObject<z.ZodRawShape>;\n maxSteps: number;\n dimensions: string[];\n}\n\nconst dimensionResultSchema = z.object({\n pass: z.boolean(),\n evidence: z.string().describe(\"What you checked and found — cite file paths, line content, or specific strings\"),\n suggestion: z.string().optional().describe(\"What the planner agent should fix, if failing\"),\n});\n\nexport type DimensionResult = z.infer<typeof dimensionResultSchema>;\n\n// --- RUBRIC 1: Structural & Intent ---\n\nexport const structuralIntentRubric: ReviewRubric = {\n name: \"structural-intent\",\n maxSteps: 8,\n dimensions: [\"structuralValidity\", \"intentQuality\", \"missionAlignment\"],\n resultSchema: z.object({\n structuralValidity: dimensionResultSchema.describe(\n \"Are all step verbs valid (click/type/scroll/assert/hover/drag/read/refresh)? Are asserts visual-only (no URLs, network, console)? No code selectors? No login steps?\",\n ),\n intentQuality: dimensionResultSchema.describe(\n \"Is the intent a specific, falsifiable behavioral claim — not just 'verify X is visible'?\",\n ),\n missionAlignment: dimensionResultSchema.describe(\n \"Does the test's intent + steps verify the feature's core purpose? Not just UI appearance.\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a structural reviewer for E2E test plans. Each test will be executed by a VISUAL agent that sees the screen like a human user — it cannot inspect code, network, URLs, or any non-visual state.\n\nYour job is to EVALUATE tests against a rubric, NOT to rewrite them. You have tools to read source code if needed.\n\n## Rubric dimensions\n\n### 1. Structural validity\n- All step verbs must be one of: click, type, scroll, assert, hover, drag, read, refresh\n- assert: can ONLY verify what a human sees on screen (no URLs, network, console, localStorage)\n- No code selectors (data-testid, aria-label, CSS classes, HTML element types)\n- No login/authentication instructions — user is always already authenticated\n- No internal/meta steps like \"(Internal: simulate X)\" or \"(Note: this assumes Y)\"\n- No \"or\" in assertions — test data is deterministic\n- Assertions must reference specific visible text, not vague descriptions (\"success indicator\", \"results are displayed\")\n\n### 2. Intent quality\nIs the intent a specific, falsifiable behavioral claim?\nFAIL: \"When a user clicks the clock icon, the Wait modal should open\" (just UI mechanics)\nPASS: \"Adding a 5-second wait step should insert a Wait action into the step list with the configured duration\"\n\n### 3. Mission alignment\nDoes the test's intent + steps actually verify the feature's core purpose?\nFAIL if the intent just describes UI appearance when the feature is about functionality.\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\n// --- RUBRIC 2: Flow & Completeness ---\n\nexport const flowCompletenessRubric: ReviewRubric = {\n name: \"flow-completeness\",\n maxSteps: 12,\n dimensions: [\"actionCompletion\", \"mutationVerification\"],\n resultSchema: z.object({\n actionCompletion: dimensionResultSchema.describe(\n \"Does the test complete a core action and reach an OUTCOME? Not just opening a modal or clicking a tab.\",\n ),\n mutationVerification: dimensionResultSchema.describe(\n \"Does the test verify its mutation at the source of truth — not just a toast or inline indicator?\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a flow completeness reviewer for E2E test plans. Each test will be executed by a VISUAL agent that sees the screen like a human user.\n\nYour job is to EVALUATE whether the test completes a meaningful action and verifies the result properly. You have tools to read the project's source code to understand what the feature actually does.\n\n## Rubric dimensions\n\n### 1. Action completion\nDoes the test complete a core action and reach an OUTCOME?\nFAIL if the last meaningful step is just opening a modal, clicking a tab, or viewing a page.\nPASS if the test creates, saves, deletes, configures, or otherwise produces a verifiable result.\n\nRead the source files to understand what the feature's complete workflow looks like. Does the test cover the full cycle?\n\n### 2. Mutation verification\nDoes the test verify its mutation at the source of truth?\nFAIL if the test ends at the point of action — checking a toast, a modal closing, or an inline success indicator.\nPASS if the test navigates to where the mutation's effect should be visible and asserts it there.\n\nFor example: after creating a record, does the test navigate back to the list and verify the record appears? After toggling a setting, does it refresh and verify the toggle persists?\n\nRead the source code to understand where the \"source of truth\" view is for each mutation.\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\n// --- RUBRIC 3: UI Text Authenticity ---\n\nexport const uiTextRubric: ReviewRubric = {\n name: \"ui-text\",\n maxSteps: 20,\n dimensions: [\"uiTextAuthenticity\"],\n resultSchema: z.object({\n uiTextAuthenticity: dimensionResultSchema.describe(\n \"Do all quoted strings in steps reference text a human would actually see on screen? Not translation keys, config paths, component names, enum identifiers, or CSS classes.\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a UI text authenticity reviewer for E2E test plans. Your ONLY job is verifying that every piece of quoted text in the test steps matches what a human user would actually see on screen.\n\nYou have tools to read source code. USE THEM AGGRESSIVELY. Do not guess — verify.\n\n## Your process for EVERY quoted string in the test:\n\n1. Grep for the exact string in the project source code\n2. Check WHERE it appears:\n - If it appears as rendered text in the template/markup → PASS (it's real visible text)\n - If it appears inside a translation/i18n function call → it's a TRANSLATION KEY, not visible text. FAIL.\n - If it looks like a code identifier (camelCase, dot.notation, SCREAMING_CASE, PascalCase names) → FAIL\n3. If the string is a translation key, trace it to the actual rendered value:\n - Find the translation/i18n file or dictionary\n - Look up the key to find what text actually appears on screen\n - Report both the key used and the correct visible text in your evidence\n\n## Common patterns to catch:\n- Translation keys used as labels: \"aiBackoffice.tabPipeline\" instead of \"Pipeline\"\n- Dot-notation config paths: \"settings.general.title\"\n- **Icon component names used as button descriptions**: if a quoted string in a test step refers to a button or clickable element, grep for that string in the source code. If it's imported as a component and renders an icon (SVG, image), it's a code identifier — NOT what the user sees. The test must describe the icon visually instead. To verify: find the icon's source file or infer from its name what it depicts, and check whether the test uses a visual description or the code name.\n- Enum values: \"QUOTE_REQUEST_RECEIVED\", \"IN_REVIEW\"\n- CSS class names or HTML attributes used as visible text\n\n## Important:\n- Check EVERY quoted string, not just suspicious ones\n- A string existing in source code is NOT enough — it must be the RENDERED text\n- When in doubt, read more files. You have 20 steps — use them all if needed.\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\n// --- RUBRIC 4: Data Accuracy ---\n\nexport const dataAccuracyRubric: ReviewRubric = {\n name: \"data-accuracy\",\n maxSteps: 20,\n dimensions: [\"dataAccuracy\"],\n resultSchema: z.object({\n dataAccuracy: dimensionResultSchema.describe(\n \"Do the referenced UI elements (buttons, labels, fields, headings, toasts) actually exist in the source code for this page? Are default states correct? Does all test data (names, values, entities) come from the scenario data — NOT from other tests?\",\n ),\n }) as z.ZodObject<z.ZodRawShape>,\n systemPrompt: `You are a data accuracy reviewer for E2E test plans. Your ONLY job is verifying that every UI element referenced in the test actually exists in the source code and behaves as the test expects.\n\nYou have tools to read source code. USE THEM AGGRESSIVELY. Do not guess — verify.\n\n## Your process:\n\n### 1. Identify the page/component\nRead the test's starting page and find the corresponding source file. Read it.\n\n### 2. For each UI element referenced in the test:\n- **Buttons**: grep for the button label. Verify it exists as a rendered string (not just a variable name).\n- **Tab names**: find the tab component, read the tab definitions, verify the names match.\n- **Field labels**: find the form component, verify field labels match.\n- **Headings**: verify section/modal headings exist in the JSX.\n- **Toast messages**: find where toasts are triggered, verify the message text.\n- **Dropdown options**: find the select/dropdown component, verify the options.\n\n### 3. Check default states:\n- Toggle/switch default positions (is it on or off by default?)\n- Default selected tabs (which tab is active on load?)\n- Default form values (what are the initial values?)\n- Conditional rendering (does the element actually show given the default state?)\n\n### 4. Check preconditions and scenario data grounding:\n- Does the test assume data exists that might not be seeded? (e.g., \"click on the first item\" when the list might be empty)\n- CRITICAL: If the prompt includes scenario data, every data value the test references (entity names, folder names, app names, URLs, email addresses, etc.) MUST appear in that scenario data. If the test uses a value that only exists because another test created it, that is a FAIL — tests must be independent.\n- Cross-reference every specific name/value in the test steps against the scenario data provided.\n\n## Important:\n- READ the actual component source files — don't just grep for strings\n- Check conditional rendering — an element might exist in code but only show under certain conditions\n- Verify the FLOW makes sense — after a page refresh, what state resets?\n- Tests MUST be independent — they cannot depend on data created by other tests\n\nWhen done reviewing, call finish with your structured evaluation.`,\n};\n\nexport const ALL_RUBRICS: ReviewRubric[] = [\n structuralIntentRubric,\n flowCompletenessRubric,\n uiTextRubric,\n dataAccuracyRubric,\n];\n","import { basename } from \"node:path\";\nimport { type LanguageModel } from \"ai\";\nimport { tool } from \"ai\";\nimport { runAgent, buildDefaultStepLogger } from \"../../core/agent\";\nimport { buildReadFileTool, buildGrepTool, buildGlobTool, buildBashTool } from \"../../tools\";\nimport type { ReviewRubric, DimensionResult } from \"./rubrics\";\n\nexport async function runReviewPass(\n testContent: string,\n testPath: string,\n rubric: ReviewRubric,\n projectRoot: string,\n model: LanguageModel,\n scenarioData?: string,\n): Promise<Record<string, DimensionResult> | null> {\n let result: Record<string, DimensionResult> | undefined;\n\n const agentLabel = `review:${rubric.name}:${basename(testPath)}`;\n const { onStepFinish } = buildDefaultStepLogger(agentLabel, rubric.maxSteps);\n\n const finishTool = tool({\n description: \"Submit your structured review. Every dimension must have evidence from your investigation.\",\n inputSchema: rubric.resultSchema,\n execute: async (input) => {\n result = input as Record<string, DimensionResult>;\n },\n });\n\n const agentConfig = {\n id: agentLabel,\n systemPrompt: rubric.systemPrompt,\n model,\n maxSteps: rubric.maxSteps,\n tools: (_heartbeat: () => void) => ({\n read_file: buildReadFileTool(projectRoot),\n grep: buildGrepTool(projectRoot),\n glob: buildGlobTool(projectRoot),\n bash: buildBashTool(projectRoot),\n finish: finishTool,\n }),\n onStepFinish,\n };\n\n const scenarioContext = scenarioData && rubric.name === \"data-accuracy\"\n ? `\\n## Scenario data (the ONLY test data that exists in the database)\\n\\`\\`\\`\\n${scenarioData}\\n\\`\\`\\`\\n\\nIMPORTANT: Every piece of data the test references (names, titles, URLs, folder names, etc.) MUST exist in the scenario data above. If the test uses a value that doesn't appear in scenarios, it FAILS the dataAccuracy dimension.\\n`\n : \"\";\n\n const prompt = `Review this E2E test plan:\n\n## Test file: ${testPath}\n\\`\\`\\`\n${testContent}\n\\`\\`\\`\n${scenarioContext}\nEvaluate EVERY dimension in your rubric: ${rubric.dimensions.join(\", \")}\n\nFor each one:\n1. Investigate using your tools (read source files, grep for strings referenced in the test)\n2. Provide specific evidence of what you found\n3. Pass or fail with a clear reason\n\nWhen done, call finish with your structured evaluation.`;\n\n await runAgent(agentConfig, prompt, () => result);\n return result ?? null;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative, basename } from \"node:path\";\nimport { glob } from \"glob\";\nimport { type LanguageModel } from \"ai\";\nimport { createStepLogger } from \"../../core/display\";\nimport { ALL_RUBRICS, type DimensionResult } from \"./rubrics\";\nimport { runReviewPass } from \"./review-pass\";\n\nconst MAX_CONCURRENT_TESTS = 4;\n\nexport type ReviewResult = Record<string, DimensionResult>;\n\nexport interface TestReviewFeedback {\n testPath: string;\n relativePath: string;\n content: string;\n flow: string;\n passed: boolean;\n dimensions: ReviewResult;\n failedDimensions: string[];\n}\n\nasync function reviewSingleTest(\n testContent: string,\n testPath: string,\n projectRoot: string,\n model: LanguageModel,\n scenarioData?: string,\n): Promise<ReviewResult> {\n const passes = await Promise.all(\n ALL_RUBRICS.map((rubric) =>\n runReviewPass(testContent, testPath, rubric, projectRoot, model, scenarioData).catch((err) => {\n console.warn(` [review] ${rubric.name} error on ${basename(testPath)}: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }),\n ),\n );\n\n const merged: ReviewResult = {};\n for (let i = 0; i < ALL_RUBRICS.length; i++) {\n const rubric = ALL_RUBRICS[i]!;\n const passResult = passes[i];\n for (const dim of rubric.dimensions) {\n if (passResult && dim in passResult) {\n merged[dim] = passResult[dim]!;\n } else {\n merged[dim] = { pass: true, evidence: \"Rubric pass did not return result — fail-open\" };\n }\n }\n }\n\n return merged;\n}\n\nexport async function runConsolidatedReview(\n outputDir: string,\n projectRoot: string,\n model: LanguageModel,\n): Promise<{ passed: number; failed: number; feedback: TestReviewFeedback[] }> {\n const testsDir = join(outputDir, \"qa-tests\");\n const logger = createStepLogger(\"review\", 5);\n\n let scenarioData: string | undefined;\n try {\n scenarioData = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch { /* scenarios not available */ }\n\n const testFiles = await glob(join(testsDir, \"**/*.md\"));\n const tests: { path: string; relativePath: string; content: string; flow: string }[] = [];\n for (const testPath of testFiles) {\n if (basename(testPath) === \"INDEX.md\") continue;\n if (testPath.includes(\"/_invalid/\")) continue;\n const content = await readFile(testPath, \"utf-8\");\n const flowMatch = content.match(/^---\\n[\\s\\S]*?flow:\\s*[\"']?([^\"'\\n]+)[\"']?\\s*\\n[\\s\\S]*?---/m);\n tests.push({\n path: testPath,\n relativePath: relative(testsDir, testPath),\n content,\n flow: flowMatch?.[1]?.trim() ?? \"unknown\",\n });\n }\n\n const totalAgents = tests.length * ALL_RUBRICS.length;\n logger.log({\n stepNumber: 1,\n maxSteps: 2,\n text: `Reviewing ${tests.length} tests × ${ALL_RUBRICS.length} rubrics = ${totalAgents} agents (${MAX_CONCURRENT_TESTS} tests concurrent)`,\n toolCalls: [],\n toolErrors: [],\n writtenFiles: [],\n });\n\n let passed = 0;\n let failed = 0;\n const feedback: TestReviewFeedback[] = [];\n\n for (let i = 0; i < tests.length; i += MAX_CONCURRENT_TESTS) {\n const batch = tests.slice(i, i + MAX_CONCURRENT_TESTS);\n const results = await Promise.all(\n batch.map(async (test) => {\n const result = await reviewSingleTest(test.content, test.relativePath, projectRoot, model, scenarioData);\n return { test, result };\n }),\n );\n\n for (const { test, result } of results) {\n const failedDimensions: string[] = [];\n for (const [key, dim] of Object.entries(result)) {\n if (!dim.pass) failedDimensions.push(key);\n }\n\n if (failedDimensions.length === 0) {\n passed++;\n } else {\n failed++;\n feedback.push({\n testPath: test.path,\n relativePath: test.relativePath,\n content: test.content,\n flow: test.flow,\n passed: false,\n dimensions: result,\n failedDimensions,\n });\n }\n }\n\n console.log(\n ` [review] Progress: ${Math.min(i + MAX_CONCURRENT_TESTS, tests.length)}/${tests.length} reviewed, ${passed} passed, ${failed} failed`,\n );\n }\n\n logger.log({\n stepNumber: 2,\n maxSteps: 2,\n text: `Review complete: ${passed} passed, ${failed} failed`,\n toolCalls: [],\n toolErrors: [],\n writtenFiles: [],\n });\n\n logger.summary();\n return { passed, failed, feedback };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface FeatureNode {\n id: string;\n name: string;\n routePath?: string;\n sourceFiles: string[];\n parentId: string | null;\n depth: number;\n status: \"queued\" | \"exploring\" | \"tested\" | \"skipped\";\n}\n\nexport interface SerializedCoverageState {\n nodes: Record<string, FeatureNode>;\n queue: string[];\n currentNode: string | null;\n testsWritten: Record<string, string[]>;\n}\n\nexport class CoverageState {\n nodes: Map<string, FeatureNode> = new Map();\n queue: string[] = [];\n testsWritten: Map<string, string[]> = new Map();\n currentNode: string | null = null;\n\n enqueue(node: FeatureNode): boolean {\n if (this.nodes.has(node.id)) return false;\n this.nodes.set(node.id, node);\n this.queue.push(node.id);\n return true;\n }\n\n nextNode(): { node: FeatureNode; remaining: number } | null {\n if (this.currentNode) {\n const current = this.nodes.get(this.currentNode);\n if (current && current.status !== \"tested\") {\n current.status = \"skipped\";\n }\n }\n\n while (this.queue.length > 0) {\n const id = this.queue.shift()!;\n const node = this.nodes.get(id);\n if (!node || node.status === \"tested\" || node.status === \"skipped\")\n continue;\n\n node.status = \"exploring\";\n this.currentNode = id;\n return { node, remaining: this.queue.length };\n }\n\n this.currentNode = null;\n return null;\n }\n\n markTested(nodeId: string, testPaths: string[]): void {\n const node = this.nodes.get(nodeId);\n if (node) node.status = \"tested\";\n this.currentNode = null;\n const existing = this.testsWritten.get(nodeId) ?? [];\n this.testsWritten.set(nodeId, [...existing, ...testPaths]);\n }\n\n allTestPaths(): string[] {\n const paths: string[] = [];\n for (const tests of this.testsWritten.values()) {\n paths.push(...tests);\n }\n return paths;\n }\n\n summary(): {\n totalNodes: number;\n tested: number;\n skipped: number;\n queued: number;\n totalTests: number;\n } {\n let tested = 0,\n skipped = 0,\n queued = 0;\n for (const node of this.nodes.values()) {\n if (node.status === \"tested\") tested++;\n else if (node.status === \"skipped\") skipped++;\n else queued++;\n }\n return {\n totalNodes: this.nodes.size,\n tested,\n skipped,\n queued,\n totalTests: this.allTestPaths().length,\n };\n }\n\n serialize(): SerializedCoverageState {\n return {\n nodes: Object.fromEntries(this.nodes),\n queue: [...this.queue],\n currentNode: this.currentNode,\n testsWritten: Object.fromEntries(this.testsWritten),\n };\n }\n\n static deserialize(data: SerializedCoverageState): CoverageState {\n const state = new CoverageState();\n state.nodes = new Map(Object.entries(data.nodes));\n state.queue = data.queue;\n state.currentNode = data.currentNode ?? null;\n state.testsWritten = new Map(Object.entries(data.testsWritten));\n return state;\n }\n}\n\nconst STATE_FILE = \".bfs-state.json\";\n\nexport async function saveBfsState(\n outputDir: string,\n state: CoverageState,\n): Promise<void> {\n const path = join(outputDir, STATE_FILE);\n await writeFile(path, JSON.stringify(state.serialize(), null, 2), \"utf-8\");\n}\n\nexport async function loadBfsState(\n outputDir: string,\n): Promise<CoverageState | null> {\n const path = join(outputDir, STATE_FILE);\n try {\n const raw = await readFile(path, \"utf-8\");\n return CoverageState.deserialize(JSON.parse(raw));\n } catch {\n return null;\n }\n}\n","import { type AgentResult, buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { tool } from \"ai\";\n\nconst FEATURES_FILE = \"features.json\";\n\nconst Feature = z.object({\n name: z.string().min(1).describe(\"Human-readable name (e.g. 'Settings > Notifications Tab', 'Create Project Modal')\"),\n type: z.enum([\"tab\", \"modal\", \"form\", \"table\", \"wizard\", \"nested-route\", \"complex-component\"]),\n parentPagePath: z.string().min(1).describe(\"The page path this feature belongs to (from the pages list)\"),\n sourceFiles: z.array(z.string()).min(1).describe(\"Relative paths to the source files for this sub-feature\"),\n interactiveElements: z.number().int().min(0).describe(\"Count of interactive elements found (buttons, inputs, toggles, etc.)\"),\n description: z.string().min(10).describe(\"What this sub-feature does\"),\n});\nexport type DiscoveredFeature = z.infer<typeof Feature> & { id: string };\n\nclass FeatureCollector {\n readonly features = new Map<string, DiscoveredFeature>();\n\n addFeature(id: string, feature: z.infer<typeof Feature>): void {\n if (this.features.has(id)) {\n console.warn(`feature ${id} already exists, overwriting`);\n }\n this.features.set(id, { ...feature, id });\n }\n\n viewFeatures(): string {\n if (this.features.size === 0) return \"No features discovered yet.\";\n const grouped = new Map<string, DiscoveredFeature[]>();\n for (const f of this.features.values()) {\n const existing = grouped.get(f.parentPagePath) ?? [];\n existing.push(f);\n grouped.set(f.parentPagePath, existing);\n }\n const lines: string[] = [];\n for (const [page, features] of grouped) {\n lines.push(`\\n${page}:`);\n for (const f of features) {\n lines.push(` - [${f.type}] ${f.name} (${f.interactiveElements} elements, ${f.sourceFiles.length} files)`);\n }\n }\n return lines.join(\"\\n\");\n }\n}\n\nexport interface FeatureDiscoveryInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n pages: Map<string, { route: string; path: string; description: string }>;\n nonInteractive?: boolean;\n}\n\nexport async function saveFeatures(outputDir: string, features: Map<string, DiscoveredFeature>): Promise<void> {\n const obj = Object.fromEntries(features);\n await writeFile(join(outputDir, FEATURES_FILE), JSON.stringify(obj, null, 2), \"utf-8\");\n}\n\nexport async function loadFeatures(outputDir: string): Promise<Map<string, DiscoveredFeature> | null> {\n try {\n const raw = await readFile(join(outputDir, FEATURES_FILE), \"utf-8\");\n const obj = JSON.parse(raw);\n return new Map(Object.entries(obj));\n } catch {\n return null;\n }\n}\n\nconst SYSTEM_PROMPT = `You are a feature discovery agent. Your job is to explore each page's source code and discover all sub-features that deserve their own test coverage.\n\nYou will be given a list of pages. For each page, you must:\n1. Read the page's source file\n2. Follow imports — use grep and glob to find all related components, utilities, hooks\n3. For each sub-feature you find, call add_feature\n\n## What counts as a sub-feature\n- **Tabs** that render different content (each tab = separate feature)\n- **Modals/dialogs** with their own form or workflow\n- **CRUD forms** (create entity, edit entity — each is a separate feature)\n- **Tables** with row-level actions (edit, delete, status change per row)\n- **Multi-step wizards** or flows\n- **Nested routes** that render distinct views within the page\n- **Complex components** with significant interactive elements (3+ buttons/inputs/toggles)\n\n## What does NOT count\n- Pure display components (headers, footers, breadcrumbs, loading spinners)\n- Shared UI primitives used across the app (generic Button, Input, Dropdown components)\n- Error/loading/empty states\n- Simple navigation elements (links, back buttons)\n\n## How to count interactive elements\nFor each sub-feature, count: buttons, text inputs, toggles/switches, checkboxes, radio buttons, dropdowns/selects, sliders, drag handles, date pickers, file uploads, rich text editors, search fields, table row actions.\n\n## Process\n1. Call view_pages to see all pages\n2. For each page:\n a. Read the page's source file\n b. Find all imports and trace them to their source files\n c. Identify sub-features by looking for: tab components, modal/dialog components, form components, table components with actions, stepper/wizard components\n d. For each sub-feature, read its source files and count interactive elements\n e. Call add_feature for each sub-feature found\n3. After processing all pages, call view_features to review your work\n4. Call finish\n\n## ID format\nUse kebab-case IDs that indicate the parent page and feature type:\n- \"settings-notifications-tab\"\n- \"projects-create-modal\"\n- \"users-table-actions\"\n- \"onboarding-step-2-form\"\n\n## Important\n- Explore the ACTUAL source code. Do not guess what sub-features exist.\n- If a page is simple (just displays content, no interactive sub-features), skip it — not every page needs sub-features.\n- Focus on features that would need DIFFERENT tests, not variations of the same thing.\n- Use spawn_researcher or subagent for pages with many files to avoid context bloat.`;\n\nexport async function runFeatureDiscovery(input: FeatureDiscoveryInput): Promise<Map<string, DiscoveredFeature>> {\n const model = getModel(input.modelId);\n const collector = new FeatureCollector();\n\n let result: AgentResult | undefined;\n const { logger, onStepFinish } = buildDefaultStepLogger(\"feature-discovery\", 300);\n\n const pagesDescription = Array.from(input.pages.entries())\n .map(([path, page]) => `- ${page.route} → ${path}\\n ${page.description}`)\n .join(\"\\n\");\n\n const prompt = `Discover sub-features for all pages in this project.\n\nProject root: ${input.projectRoot}\n\n## Pages to analyze\n${pagesDescription}\n\nProcess every page. Call add_feature for each sub-feature you discover. When done, call finish.`;\n\n const agentConfig = {\n id: \"feature-discovery\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 300,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n add_feature: tool({\n description: \"Add a discovered sub-feature\",\n inputSchema: Feature.extend({\n id: z.string().min(1).describe(\"Unique kebab-case ID (e.g. 'settings-notifications-tab')\"),\n }),\n execute: (featureInput) => {\n const { id, ...rest } = featureInput;\n const parsed = Feature.safeParse(rest);\n if (!parsed.success) {\n return `Invalid feature: ${parsed.error.issues.map(i => i.message).join(\", \")}`;\n }\n collector.addFeature(id, parsed.data);\n return `Feature \"${id}\" added (${collector.features.size} total)`;\n },\n }),\n view_features: tool({\n description: \"View all discovered features so far\",\n inputSchema: z.object({}),\n execute: () => collector.viewFeatures(),\n }),\n view_pages: tool({\n description: \"View the pages list to know what to analyze\",\n inputSchema: z.object({}),\n execute: () => pagesDescription,\n }),\n finish: tool({\n description: \"Signal that feature discovery is complete\",\n inputSchema: z.object({ summary: z.string() }),\n execute: async (finishInput) => {\n result = {\n success: true,\n artifacts: [...collector.features.keys()],\n summary: finishInput.summary,\n };\n await saveFeatures(input.outputDir, collector.features);\n return { done: true, featureCount: collector.features.size };\n },\n }),\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n if (collector.features.size > 0 && !result) {\n await saveFeatures(input.outputDir, collector.features);\n }\n\n return collector.features;\n}\n","import matter from \"gray-matter\";\n\nexport const VALID_VERBS = new Set([\n \"click\",\n \"type\",\n \"scroll\",\n \"assert\",\n \"hover\",\n \"drag\",\n \"read\",\n \"refresh\",\n]);\n\ninterface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport function validateTestContent(content: string): ValidationResult {\n const errors: string[] = [];\n\n if (!/^---\\n[\\s\\S]*?\\n---/.test(content)) {\n errors.push(\"Missing frontmatter\");\n } else {\n try {\n const { data } = matter(content);\n if (!data.verification || typeof data.verification !== \"string\" || data.verification.length < 20) {\n errors.push(\"Missing or insufficient 'verification' field in frontmatter — must describe WHERE to navigate and WHAT to assert at the source of truth\");\n }\n } catch {\n errors.push(\"Failed to parse frontmatter\");\n }\n }\n\n if (!/\\*\\*Intent\\*\\*:/.test(content)) {\n errors.push(\"Missing **Intent**: section\");\n }\n\n const stepMatches =\n content.match(\n /^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm,\n ) || [];\n const interactions = stepMatches.filter((s) =>\n /^\\d+\\.\\s+(click|type|drag):/.test(s),\n );\n if (interactions.length < 2) {\n errors.push(`Only ${interactions.length} interaction(s) (minimum 2)`);\n }\n\n const allSteps = content.match(/^\\d+\\.\\s+(\\w+):/gm) || [];\n for (const step of allSteps) {\n const verbMatch = step.match(/^\\d+\\.\\s+(\\w+):/);\n if (verbMatch && !VALID_VERBS.has(verbMatch[1]!)) {\n errors.push(`Invalid verb: \"${verbMatch[1]}\"`);\n }\n }\n\n\n const bodyStart = content.indexOf(\"---\", 3);\n const body = bodyStart > -1 ? content.slice(bodyStart + 3) : content;\n const stepsSection = body.slice(body.indexOf(\"**Steps**\") || 0);\n if (/Dynamic:\\s/i.test(stepsSection)) {\n errors.push('Contains \"Dynamic:\" placeholder in steps');\n }\n\n return { valid: errors.length === 0, errors };\n}\n","import {mkdir, writeFile} from \"node:fs/promises\";\nimport {dirname, join} from \"node:path\";\nimport {hasToolCall, type LanguageModel, stepCountIs, tool, ToolLoopAgent,} from \"ai\";\nimport matter from \"gray-matter\";\nimport {z} from \"zod\";\nimport {buildBashTool, buildGlobTool, buildGrepTool, buildReadFileTool} from \"../../tools\";\nimport {type CoverageState, saveBfsState,} from \"./graph\";\nimport {VALID_VERBS} from \"./validation\";\n\nconst testFrontmatterSchema = z.object({\n title: z.string().min(1),\n description: z.string().min(1),\n intent: z.string().min(30, \"Intent must be at least 30 characters — describe the BEHAVIOR being tested, not the steps\"),\n criticality: z.enum([\"critical\", \"high\", \"mid\", \"low\"]),\n scenario: z.string().min(1),\n flow: z.string().min(1),\n verification: z.string().min(20, \"Verification must describe WHERE to navigate and WHAT to assert at the source of truth — not UI acknowledgments like toasts\"),\n});\n\nexport function buildWriteTestTool(\n state: CoverageState,\n outputDir: string,\n) {\n return tool({\n description:\n \"Write a test file to qa-tests/{folder}/{filename}.md. \" +\n \"Validates frontmatter before writing. Returns error if frontmatter is invalid.\",\n inputSchema: z.object({\n folder: z.string().describe(\"Subfolder name under qa-tests/\"),\n filename: z.string().describe(\"File name (e.g. login-valid-credentials.md)\"),\n content: z.string().describe(\"Full file content including YAML frontmatter\"),\n nodeId: z.string().describe(\"The FeatureNode ID this test belongs to\"),\n }),\n execute: async (input) => {\n const frontmatter = extractFrontmatter(input.content);\n if (!frontmatter) {\n return { error: \"File must start with YAML frontmatter (--- delimiters)\" };\n }\n\n const parsed = testFrontmatterSchema.safeParse(frontmatter);\n if (!parsed.success) {\n return {\n error: `Invalid frontmatter: ${parsed.error.issues.map((i) => i.message).join(\", \")}`,\n };\n }\n\n if (!/\\*\\*Intent\\*\\*:/.test(input.content)) {\n return { error: \"Test must include an **Intent**: section between Setup and Steps describing what behavior is being tested\" };\n }\n\n const allSteps = input.content.match(/^\\d+\\.\\s+(\\w+):/gm) || [];\n for (const step of allSteps) {\n const verbMatch = step.match(/^\\d+\\.\\s+(\\w+):/);\n if (verbMatch && !VALID_VERBS.has(verbMatch[1]!)) {\n return {\n error: `Invalid step verb \"${verbMatch[1]}\". Only valid verbs are: ${[...VALID_VERBS].join(\", \")}`,\n };\n }\n }\n\n const stepMatches = input.content.match(/^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm) || [];\n const interactions = stepMatches.filter(s => /^\\d+\\.\\s+(click|type|drag):/.test(s));\n if (interactions.length < 2) {\n return {\n error: `Test has ${interactions.length} interaction(s) (click/type/drag). Minimum is 2. ` +\n `Visibility-only tests are not allowed — what BEHAVIOR does this test verify?`,\n };\n }\n\n const bodyStart = input.content.indexOf(\"---\", 3);\n const body = bodyStart > -1 ? input.content.slice(bodyStart + 3) : input.content;\n const stepsSection = body.slice(body.indexOf(\"**Steps**\") || 0);\n\n const placeholderPatterns = [\n { pattern: /Dynamic:\\s/gi, name: '\"Dynamic:\" placeholder' },\n { pattern: /(?<!\\{)\\{[a-z][a-zA-Z]*\\}(?!\\})/g, name: \"bare {variable}\" },\n { pattern: /\\(e\\.g\\./gi, name: '\"(e.g.\" example' },\n { pattern: /(?:^|\\s)e\\.g\\.,?\\s/gim, name: '\"e.g.\" example' },\n ];\n\n for (const { pattern, name } of placeholderPatterns) {\n const matches = stepsSection.match(pattern);\n if (matches && matches.length > 0) {\n return {\n error: `Test steps contain ${name}: \"${matches[0]}\". ` +\n `Use EXACT values from scenarios.md — not placeholders or examples.`,\n };\n }\n }\n\n const relPath = join(\"qa-tests\", input.folder, input.filename);\n const absPath = join(outputDir, relPath);\n\n try {\n await mkdir(dirname(absPath), { recursive: true });\n await writeFile(absPath, input.content, \"utf-8\");\n state.markTested(input.nodeId, [relPath]);\n await saveBfsState(outputDir, state);\n return { path: relPath, title: parsed.data.title };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to write test: ${message}` };\n }\n },\n });\n}\n\nexport function buildCreateFolderTool(outputDir: string) {\n return tool({\n description: \"Create a folder under qa-tests/ for organizing tests.\",\n inputSchema: z.object({\n folder: z.string().describe(\"Folder name (kebab-case)\"),\n }),\n execute: async (input) => {\n const absPath = join(outputDir, \"qa-tests\", input.folder);\n try {\n await mkdir(absPath, { recursive: true });\n return { path: join(\"qa-tests\", input.folder) };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: `Failed to create folder: ${message}` };\n }\n },\n });\n}\n\nexport function buildNextNodeTool(state: CoverageState, outputDir: string) {\n return tool({\n description:\n \"Get the next node to write tests for. If you called next_node before \" +\n \"without writing any tests (via write_test), the previous node is auto-skipped. \" +\n \"Returns done:true when all nodes are processed.\",\n inputSchema: z.object({}),\n execute: async () => {\n const next = state.nextNode();\n await saveBfsState(outputDir, state);\n if (!next) {\n const stats = state.summary();\n return {\n done: true,\n message: `All ${stats.totalNodes} nodes processed (${stats.tested} tested, ${stats.skipped} skipped, ${stats.totalTests} tests). Call finish.`,\n };\n }\n return {\n node: {\n id: next.node.id,\n name: next.node.name,\n routePath: next.node.routePath,\n sourceFiles: next.node.sourceFiles,\n parentId: next.node.parentId,\n depth: next.node.depth,\n },\n remaining: next.remaining,\n instruction: `Explore \"${next.node.name}\": read its source files, find all interactive elements, then write tests with write_test. If no tests are needed after reading the source (e.g. utility route, redirect), call next_node to skip.`,\n };\n },\n });\n}\n\nexport function buildGetProgressTool(state: CoverageState) {\n return tool({\n description: \"Check how many nodes have been tested vs how many remain.\",\n inputSchema: z.object({}),\n execute: async () => {\n const stats = state.summary();\n const nodes = [...state.nodes.values()].map((n) => ({\n id: n.id,\n name: n.name,\n status: n.status,\n testCount: state.testsWritten.get(n.id)?.length ?? 0,\n }));\n return { ...stats, nodes };\n },\n });\n}\n\nexport function buildSpawnResearcherTool(\n model: LanguageModel,\n workingDirectory: string,\n onHeartbeat?: () => void,\n) {\n return tool({\n description:\n \"Spawn a research subagent to read and analyze source files without polluting your context. \" +\n \"Use for complex sub-features where you don't want to read 20 files yourself.\",\n inputSchema: z.object({\n instruction: z.string().describe(\"What to research — be specific about files and what to look for\"),\n }),\n execute: async (input) => {\n const resultSchema = z.object({\n findings: z.string().describe(\"Summary of what was found\"),\n });\n\n let result: z.infer<typeof resultSchema> | undefined;\n\n const subagent = new ToolLoopAgent({\n model,\n instructions:\n \"You are a code researcher. Read the files specified in your instruction, \" +\n \"analyze them, and call finish with a summary of what you found. \" +\n \"Focus on: UI elements, forms, buttons, navigation, API calls, state management.\",\n tools: {\n bash: buildBashTool(workingDirectory),\n glob: buildGlobTool(workingDirectory),\n grep: buildGrepTool(workingDirectory),\n read_file: buildReadFileTool(workingDirectory),\n finish: tool({\n description: \"Report your findings.\",\n inputSchema: resultSchema,\n execute: async (output) => { result = output; },\n }),\n },\n stopWhen: [stepCountIs(15), hasToolCall(\"finish\")],\n onStepFinish: () => { onHeartbeat?.(); },\n });\n\n try {\n await subagent.generate({\n messages: [{ role: \"user\", content: input.instruction }],\n });\n return { findings: result?.findings ?? \"Subagent did not produce findings\" };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { findings: `Research error: ${message}` };\n }\n },\n });\n}\n\nfunction extractFrontmatter(content: string): Record<string, unknown> | null {\n try {\n const { data } = matter(content);\n return data && Object.keys(data).length > 0 ? data : null;\n } catch {\n return null;\n }\n}\n","export const SYSTEM_PROMPT = `You are an E2E test generator that explores a frontend codebase as a BFS graph. You are ONE long-running agent that maintains all state about what's been explored and what hasn't.\n\n## Your process\n\n1. Call next_node to get the first node from the queue\n2. Read its source files, explore related components, write tests with write_test\n3. Call next_node again to get the next node\n4. Repeat until next_node returns done, then call finish\n\nIf a node has no testable behavior (utility, redirect), call next_node to skip it — it's auto-marked as skipped.\n\n## Tools you have\n\n### Exploration\n- read_file: Read source files to understand features\n- glob: Find files by pattern\n- grep: Search file contents\n- bash: Run shell commands (git, ls, find)\n\n### Queue management\n- next_node: Get the next node to test. Auto-skips previous node if no tests were written for it.\n- get_progress: Check how many nodes tested vs remaining\n\n### Writing\n- write_test: Write a test file with validated frontmatter\n- create_folder: Create a folder under qa-tests/\n\n### Research\n- spawn_researcher: Spawn a subagent to read/analyze files without polluting your context\n\n### Completion\n- finish: Signal you're done with a coverage report\n\n## Source code grounding (CRITICAL)\n\nBefore writing tests for any node, READ the source files for that page using read_file or spawn_researcher. Your tests MUST only reference elements you found in the actual source code.\n\nPay attention to:\n- **Conditional rendering**: elements inside conditionals are NOT always visible. Only assert them if your test steps trigger the condition first.\n- **Default states**: find where default values are set in the source code to know initial toggle/checkbox/dropdown states. If a toggle defaults to ON, clicking it turns it OFF, not ON. ALWAYS verify the initial state before writing interaction steps.\n- **Exact text**: use the actual string from the code, not paraphrased versions. If the button says \"New test\" in the source, don't write \"Create Test\".\n- **Icon buttons**: when you find a button that renders an icon with no text label, you MUST resolve what the icon looks like before writing the test. Find the icon's source file (SVG, image) and read it to see what it depicts, or infer from the icon's name/metadata in the library. Then describe the icon visually in the test step (e.g., \"three vertical dots icon button\", \"pencil icon button\", \"trash can icon button\"). NEVER use the icon's component or variable name (e.g., \"MoreVertical\", \"FaPencil\", \"IconTrash\") — these are code identifiers, not what the user sees on screen.\n- **Translated text**: if the source uses i18n/translation functions, trace the key to the actual rendered text. Never use translation keys as visible text.\n\nIf you can't find an element in the source, don't assert it. Read more files or skip it.\n\n## Feature Mission (CRITICAL)\n\nEach feature has a \"mission\" — the ONE thing it must do correctly. Your tests MUST verify the mission. Before writing tests for any node:\n\n1. Find the mission for this feature from the Feature Missions section below\n2. Ask: \"Does my planned test verify the mission, or just UI mechanics?\"\n3. At least ONE test per feature must directly assert the mission outcome\n4. Core features (core: true) also have a coreReason explaining the blast radius of failure — allocate more depth to these\n\nExample: If the mission is \"Show correct execution counts and success rates for the selected time range\":\n- BAD: assert: the \"Executions\" tab heading is visible (UI mechanics — proves nothing about data)\n- GOOD: assert: text \"12\" is visible in the executions count (verifies actual data from scenarios)\n\nIf you find yourself writing a test that only opens/closes UI elements without verifying the mission outcome, STOP and redesign the test.\n\n## BFS rules — EXPLORE DEEPLY, THEN WRITE THOROUGH TESTS\n\nFor each queued node, follow this process:\n\n### Step 1: Read source and catalog every interactive element\n1. The node has its page file path. Read it with read_file.\n2. Use glob, grep, and read_file to find ALL related source files — imports, shared components, utilities, sub-pages. Explore the codebase structure around this page to understand where the feature's code actually lives.\n3. Build a mental catalog of EVERY interactive element on the page:\n - Buttons (with exact text labels)\n - Input fields (with labels, placeholders, validation rules)\n - Toggles/checkboxes/switches (with default states)\n - Dropdowns/selects (with their options)\n - Forms (with all their fields)\n - Modals/dialogs (with their triggers and content)\n - Tables/lists (with row actions, sorting, filtering)\n - Tabs (with their labels and what they render)\n4. If you find sibling routes or related pages that are NOT already in the queue, enqueue them.\n\n### Step 2: Write tests that cover EVERY element\n5. Every button, input, toggle, and form field you cataloged MUST appear in at least one test. If you found 8 interactive elements and your tests only touch 3, you're missing coverage.\n6. A single test can (and should) interact with multiple elements — you don't need one test per element. A form test can fill all fields and submit.\n7. For each element type, apply these opinionated test patterns:\n\n**Input fields:**\n- Happy path: fill with valid data, submit, verify success\n- Validation: submit empty/required fields, verify error messages\n- Boundary: extremely long strings (can break rendering elsewhere), special characters, numbers in text fields\n- If the source has validation rules, write a test that triggers each validation error\n\n**Toggles/switches/checkboxes:**\n- Verify the default state matches the source code\n- Toggle and verify the state changed\n- Refresh the page and verify the state persisted\n- If multiple toggles exist in a section, test toggling each independently\n\n**Forms (create/edit/delete):**\n- Create: fill all fields, submit, verify the new item appears in the list WITHOUT refreshing\n- Edit: modify an existing item, save, verify the change is reflected\n- Delete: remove an item, verify it disappears, verify it stays gone after refresh\n- Partial submission: leave optional fields empty, verify it still works\n- Duplicate prevention: if the source has unique constraints, try creating a duplicate\n\n**Modals/dialogs:**\n- Open the modal, fill partially, close it, reopen it — is the state cleared or preserved? (check the source)\n- Complete the modal workflow end-to-end\n\n**Tables/lists:**\n- If there's search/filter: search for an item, verify filtering works\n- If there's pagination: verify it exists when there's enough data\n- If there are row actions (edit/delete buttons per row): test them\n\n**Behavioral variations (switch/map in source):**\n- If the source has a switch/map dispatching to different components per variant (e.g., different providers, different interaction types), write a test for EACH variant that renders differently. Read the source for each variant to get the correct element names — don't copy from another variant's test.\n\n### Step 3: Move to the next node\n8. After writing tests, call next_node to get the next node\n9. Use spawn_researcher for complex sub-features where reading 10+ files would clutter your context\n10. If a node has no clear page file (utility routes, redirects), call next_node to skip it\n11. NEVER write tests for error pages, 404s, or states that require navigating to invalid URLs.\n\n## Folder structure rules\n\nUse NESTED folders to mirror the app hierarchy. Use create_folder with \"/\" separators:\n- GOOD: create_folder \"settings/notifications\" → qa-tests/settings/notifications/\n- GOOD: create_folder \"settings/billing\" → qa-tests/settings/billing/\n- BAD: create_folder \"settings-notifications\" → qa-tests/settings-notifications/ (flat, no grouping)\n\nGroup related areas under parent folders.\n\n## Test file format\n\nEvery test file must start with YAML frontmatter:\n\n\\`\\`\\`yaml\n---\ntitle: \"Toggle recording stops active session\"\ndescription: \"Verify toggling recording OFF stops the session\"\nintent: \"When the recording toggle is ON (default), clicking it should stop recording and show a confirmation toast\"\ncriticality: critical\nscenario: standard\nflow: \"User Settings\"\nverification: \"Refresh the Settings page, assert the recording toggle is in the OFF position\"\n---\n\\`\\`\\`\n\n### Frontmatter rules\n- title: Short, descriptive test name\n- description: One sentence explaining what the test verifies\n- intent: A specific, falsifiable claim derived from the feature's MISSION — what the user does, what the feature produces, and why it matters. Focus on OUTCOMES, not UI mechanics.\n GOOD: \"Toggling recording from ON to OFF stops the active session and shows a confirmation toast\"\n BAD: \"Click the recording toggle\" (that's a step, not an intent)\n BAD: \"Verify the page displays correctly\" (visibility check, not a behavior)\n Derive from the mission: if the mission is \"Generate valid config files\", every test's intent must be about generating, previewing, or copying config — not about UI elements appearing.\n- criticality: One of: critical, high, mid, low\n- scenario: Which scenario this test uses (usually \"standard\")\n- flow: Which feature/flow this belongs to (must match a feature from AUTONOMA.md)\n- verification: (REQUIRED — write tool rejects without it) WHERE to navigate and WHAT to assert to prove the mutation worked. Every test performs a mutation — render-only tests should be folded into another test's flow. Must describe the source of truth, not a UI acknowledgment.\n GOOD: \"Navigate to the test list, assert 'Login Flow' is visible in the table\"\n GOOD: \"Refresh the page, assert the toggle retained its OFF state\"\n BAD: \"Assert toast 'Deleted' appears\" (UI acknowledgment, not verification)\n\n### Test body format\n\nAfter frontmatter:\n\n**Setup**: Which page the user starts on. Describe the clicks to reach the page. Read the app's layout/navigation code to determine the correct path. Look for sidebar, tab navigation, and route definitions. NEVER invent navigation paths — if you can't find how to reach a page, use spawn_researcher to investigate.\n\nNEVER write \"Login as...\" or \"Log in\" in Setup. The user is ALWAYS already authenticated. Setup only describes WHERE the user is, not authentication.\nNEVER write tests that require navigating to invalid URLs, 404 pages, or error states.\n\n**Intent**: A specific, falsifiable claim derived from the feature's MISSION. States what the user does, what should happen, and WHY it matters. Write this BEFORE writing steps — it's the \"north star\" that the execution agent uses to adapt if steps don't match reality.\n\nThe intent is NOT \"what UI appears\" — it's \"what the feature DOES\".\n\nInclude in your intent:\n- The expected INITIAL STATE of relevant elements\n- The ACTION the user takes\n- The EXPECTED OUTCOME (what the feature produces, not what UI appears)\n- Why this matters to the user\n\nThe intent is the source of truth. If your steps conflict with the intent, fix the STEPS.\n\n**Steps**: Numbered list using ONLY these actions (any other verb is INVALID):\n- click: Click a button, link, or element\n- type: Type text into an input field\n- scroll: Scroll to an element or position\n- assert: Verify something VISUALLY visible on screen — text, headings, buttons, labels, images. MUST include location context when the same text could appear in multiple places. Use visual landmarks: \"in the side panel\", \"in the modal\", \"in the table header\", \"below the form\", \"in the toast notification\". CANNOT assert URLs, network requests, console logs, cookies, localStorage, or any non-visual state.\n- hover: Hover over an element\n- drag: Drag an element\n- read: Read text from an element into a variable\n- refresh: Refresh the page\n\nBANNED actions (NEVER use these):\n- wait: — INVALID. Do not write \"wait:\" steps.\n- verify: — INVALID. Use \"assert:\" instead.\n- navigate: — INVALID. Put navigation in Setup, not in steps.\n- select: — INVALID. Use \"click:\" to select dropdown items.\n- check: — INVALID. Use \"click:\" to check checkboxes, \"assert:\" to verify state.\n\n**Verification**: Steps that usually navigate AWAY from the action screen to the source of truth and assert the mutation's effect. This section implements what the frontmatter 'verification' field describes.\n\n**Expected Result**: What should be true when the test passes\n\n### Interaction requirements (CRITICAL)\n- Every test MUST include at least 2 meaningful interactions (click, type, drag). Tests that ONLY assert visibility of elements are REJECTED.\n- Every test MUST perform a mutation (create, update, delete, toggle, configure, etc.). There are NO render-only tests. If you need to verify something renders, fold that assertion into a mutation test's flow as a pre-condition or post-verification step.\n- Ask: \"Does this test verify that something WORKS, or just that something EXISTS?\" If the latter, it is NOT a valid test.\n\n### Functional assertions (CRITICAL)\nEvery test must have a FUNCTIONAL ASSERTION — an assertion that verifies the feature DID SOMETHING, not just that UI appeared.\n\nBAD PATTERN (open/close cycle — tests nothing):\n1. click: the \"Import component\" button\n2. assert: \"Import component\" is visible in the modal header\n3. click: the \"Close\" button in the modal\n4. assert: \"Import component\" is no longer visible\nThis only proves the modal opens and closes. It does NOT test importing a component.\n\nGOOD PATTERN (completing the action — tests the feature):\n1. click: the \"Import component\" button\n2. assert: \"Import component\" is visible in the modal header\n3. click: \"Login Component\" in the component list\n4. click: the \"Import\" button\n5. assert: \"Login Component\" is visible in the step list\n\nIf your last assertion is about a modal being open, a heading being visible, or an element disappearing, you probably haven't tested anything. Ask: \"What is the OUTCOME of this action?\" Your test must prove the feature's MISSION is fulfilled.\n\n### Variation coverage\nWhen you find branching patterns in the source, decide whether each variant produces DIFFERENT BEHAVIOR (different code path, different UI, different output) or just passes different data through the SAME code path.\n\nThe question to ask: \"In the source code, is there a conditional that renders different components or runs different logic based on this variant?\" If yes → separate tests. If no → one test is enough.\n\nWhy this matters: tests that only vary in what string is passed through identical UI don't catch different bugs — they just inflate the test count.\n\nGOOD variations (code branches differently):\n- Different providers rendering different templates/forms per provider\n- Different platform types showing different upload/input components\n- Status states rendering different visual components per state\n\nBAD variations (same code path, different data):\n- Switching between different items that use the same component\n- Deleting different records through the same confirmation flow\n- Filtering by different values through the same dropdown\n\n### Default state awareness (CRITICAL)\nRead the source code to find default states for toggles, checkboxes, and dropdowns. BEFORE writing a step that interacts with a stateful element:\n- Check the source code for the element's initial value\n- If a toggle defaults to ON: clicking it turns it OFF (stops/disables)\n- ALWAYS state the expected state transition: \"click: the 'Recording' toggle to switch it from ON to OFF\" — not just \"click: the 'Recording' toggle\"\n- Assert the initial state BEFORE interacting\n\n### Assertion location context (CRITICAL)\nEVERY assertion MUST include location context — where on the page the element appears. Never write a bare \"assert: text X is visible\". Always specify: in the modal, in the sidebar, in the table, in the header, in the toast notification, in the dropdown, on the card, in the form, in the dialog, in the panel, as a page heading, as a button label, etc.\n- GOOD: assert: text \"Run preview\" is visible in the side panel\n- BAD: assert: text \"Status\" is visible (WHERE? column header? form label? sidebar?)\n\n### Test writing rules\n- Each test follows ONE deterministic path — no conditionals, no \"e.g.\", no \"(mocked or ...)\"\n- \"or\" in click/type steps is OK for naming the same element (click: the \"Edit\" or \"Pencil\" icon) — these are visual synonyms\n- \"or\" in assert steps is NEVER OK — since scenarios define the exact data, you always know what to expect\n- Assertions must specify EXACT text, element, or visual state — never \"or similar\", never \"e.g.\"\n- Be specific: use exact button text, field names, toast messages FROM THE CODE\n- One test per file\n- Never write meta-tests that \"audit\" scenario/fixture contents\n- Reference scenario data when needed for real user flows, using {{token}} placeholders for variable fields\n- Do NOT write tests that verify the test infrastructure itself\n- Every step must be concrete and reproducible. \"assert: text 'Deal Created' is visible in toast\" is GOOD. \"assert: success indicator appears\" is BAD.\n\n### Visual-only rules (CRITICAL)\nTests are executed by a VISUAL agent that sees the screen like a human. It can ONLY see what's rendered on screen.\n\nThe agent CANNOT access:\n- URLs or the browser address bar\n- Network requests or API calls\n- Console logs or errors\n- localStorage, cookies, or session data\n- HTML source, DOM structure, or element attributes\n\nTherefore:\n- NEVER assert URLs: \"assert: URL contains /creation\" is INVALID. Instead assert visible page content.\n- NEVER assert network: \"assert: API call was made\" is INVALID\n- NEVER assert non-visual state: \"assert: form state is valid\" is INVALID\n- NEVER reference HTML elements: no \"div\", \"span\", \"section\", \"input\", \"button\" as element types\n- NEVER reference data attributes: no \"data-testid\", \"data-cy\", \"data-test\"\n- NEVER reference aria attributes: no \"[aria-label]\", \"[role=dialog]\"\n- NEVER reference CSS selectors: no \"#id\", \".class-name\", \"[attribute=value]\"\n- NEVER use meta-steps: no \"(Internal: ...)\", \"(Note: ...)\", or parenthetical commentary\n- Instead, describe what the user SEES: button text, label text, placeholder text, heading text, visible icons, tab names\n\n### Scenario data references (CRITICAL)\nThe scenarios define EXACTLY what data exists in the database. Since WE control the test data, assertions should reference EXACT values from the scenario.\n- When a test needs to verify data is displayed, use the EXACT values from the scenario (names, emails, titles, counts)\n- Read scenarios.md carefully and use the exact entity names, counts, and field values in your assertions\n- Use {{token}} placeholders ONLY for values that genuinely vary between runs (like auto-generated IDs)\n- NEVER use \"Dynamic:\", \"{variableName}\", or \"e.g.\" in steps or assertions. You have exact data — use it.\n- NEVER assume facts not stated in the scenario data.\n\n## Test generation ordering (for consistency)\nWhen generating tests for a node, follow this deterministic order:\n1. First: CRUD operations for the primary entity (Create, Read/View, Update, Delete)\n2. Second: State transitions (toggle, enable/disable, activate/deactivate)\n3. Third: Validation (required fields, invalid input, boundary values)\n4. Fourth: Navigation and linking (links to detail pages, breadcrumbs, back navigation)\n5. Fifth: Edge cases (empty states, maximum values, permission boundaries)\n\n## Test depth — proportional to complexity (ENFORCED)\n\nYou determine feature complexity by READING THE SOURCE CODE, not by counting files. Before writing tests for a node:\n1. Read the page file and explore all related source files\n2. Count the interactive elements you find: forms, buttons, toggles, modals, tables, tabs\n3. Write tests proportional to what you found — more interactive elements = more tests\n\nA complex multi-step wizard with many forms needs 8-15 tests. A simple settings page with one toggle needs 2-3 tests. Use your judgment based on what you actually read in the source.\n\n## CRUD completeness (MANDATORY — zero tolerance)\n\nIf the source code for a feature supports Create, Read, Edit, and Delete for ANY entity, you MUST write tests for ALL of them. Missing even ONE CRUD operation is a critical failure.\n\n**How to detect CRUD support:** Look for:\n- Create: \"New\", \"Add\", \"Create\" buttons; form submission handlers; modals with input fields\n- Read/View: Detail pages, list pages, tables, cards displaying entity data\n- Edit: \"Edit\", \"Rename\", \"Update\" buttons; pre-filled forms\n- Delete: \"Delete\", \"Remove\", \"Trash\" buttons; confirmation dialogs\n\nIf you find yourself writing only 1-2 tests for a CRUD page, STOP. Re-read the source. Find ALL the entity operations. Write tests for each.\n\n## Outcome verification — STRUCTURALLY ENFORCED\n\nThe write_test tool REJECTS any test without a \\`verification\\` frontmatter field. This is not advisory — it's a hard gate.\n\nWhat does NOT count as verification (these are UI acknowledgments, not proof):\n- Toast messages\n- Confirmation dialogs\n- Inline success indicators\n- The action button changing state\n\nVerification destinations:\n- After CREATE → verify in list/table\n- After EDIT → verify changed field in detail/list view\n- After DELETE → verify absence in list, refresh, verify still absent\n- After TOGGLE → refresh, verify retained state\n\n## CRUD test templates (for any page with forms/CRUD):\n1. **Create**: fill all fields, submit, verify the item appears\n2. **Validation**: submit with empty required fields, verify error messages\n3. **Edit**: modify existing item, save, verify change reflected\n4. **Delete**: remove item, verify disappears, refresh, verify stays gone\n5. **Boundary**: extremely long strings, special characters\n\n**For pages with dropdowns/filters:**\n- You MUST click the dropdown trigger first, THEN click an option.\n\n**For elements revealed by hover:**\n- Include a hover step before clicking elements that only appear on hover.\n\n**After every action (create/edit/delete), verify the OUTCOME:**\n- BAD: click \"Save\" and move on\n- GOOD: click \"Save\" → assert the saved data appears in the list/detail view\n\n## Excluded routes\n- **Admin/backoffice pages**: routes under /admin/ are excluded from test generation. These require special auth, affect all users globally, and are not part of the standard user experience.\n- **Auth/login pages**: never test authentication flows — the user is always already logged in.\n\n## Test distribution guidelines\n- Core flows (from AUTONOMA.md where core: true): spend MOST of your time here. These features break → users leave.\n- Supporting flows: adequate coverage — happy path plus important variations.\n- Simple display/config pages: basic coverage.\n\n## Coverage dimensions\n\nYou track THREE kinds of coverage:\n1. Route/file coverage: which routes explored, which source files visited\n2. Entity coverage: which entity types and variations (enum values, states) appear in tests\n3. Behavioral variant coverage: which code-branching variants have dedicated tests. If a switch/map dispatches to N different renderers, you should have tests for the most important variants.\n\nWhen you finish, all dimensions are reported so the user knows what's covered and what gaps remain.`;\n","import {mkdir, readFile, rmdir, unlink, writeFile} from \"node:fs/promises\";\nimport {basename, join} from \"node:path\";\nimport {type LanguageModel, tool} from \"ai\";\nimport {z} from \"zod\";\nimport type { AppConfig } from \"../../config\";\nimport {type AgentResult, runAgent} from \"../../core/agent\";\nimport {formatContext, type ProjectContext} from \"../../core/context\";\nimport {createStepLogger} from \"../../core/display\";\nimport {loadGitignorePatterns} from \"../../core/gitignore\";\nimport {getModel} from \"../../core/model\";\nimport {reviewLoop} from \"../../core/review\";\nimport {runConsolidatedReview, type TestReviewFeedback} from \"./review\";\n\nconst MAX_CONCURRENCY = 8;\nimport {buildBashTool, buildGlobTool, buildGrepTool, buildListDirectoryTool, buildReadFileTool} from \"../../tools\";\nimport {CoverageState, type FeatureNode, loadBfsState} from \"./graph\";\nimport {type DiscoveredFeature, loadFeatures, runFeatureDiscovery} from \"../00b-feature-discovery/index\";\nimport {\n buildCreateFolderTool,\n buildGetProgressTool,\n buildNextNodeTool,\n buildSpawnResearcherTool,\n buildWriteTestTool,\n} from \"./tools\";\nimport {SYSTEM_PROMPT} from \"./prompt\";\nimport {validateTestContent} from \"./validation\";\nimport {glob} from \"glob\";\n\nexport interface TestGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n config?: AppConfig;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n pages: Map<string, { route: string; path: string; description: string }>;\n}\n\ninterface PageEntry {\n route: string;\n path: string;\n description: string;\n}\n\nasync function preseedQueue(\n state: CoverageState,\n projectRoot: string,\n pages: Map<string, PageEntry>,\n features?: Map<string, DiscoveredFeature>,\n): Promise<string> {\n let seeded = 0;\n\n const pageIdByPath = new Map<string, string>();\n\n for (const [absolutePath, page] of pages) {\n const routeSegments = page.route\n .split(\"/\")\n .filter(Boolean)\n .map((s) => s.replace(/[\\[\\]$:]/g, \"\").replace(/\\..*$/, \"\") || \"param\");\n\n if (routeSegments.length === 0) continue;\n\n const id = routeSegments.join(\"-\");\n const name = routeSegments\n .map((s) => s.replace(/-/g, \" \").replace(/\\bparam\\b/, \"[id]\"))\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join(\" / \");\n\n const relPath = absolutePath.startsWith(projectRoot)\n ? absolutePath.slice(projectRoot.length).replace(/^\\//, \"\")\n : page.path;\n\n pageIdByPath.set(absolutePath, id);\n\n const node: FeatureNode = {\n id,\n name,\n routePath: page.route.startsWith(\"/\") ? page.route : `/${page.route}`,\n sourceFiles: [relPath],\n parentId: null,\n depth: 0,\n status: \"queued\",\n };\n if (state.enqueue(node)) seeded++;\n }\n\n if (features) {\n for (const [featureId, feature] of features) {\n const parentId = pageIdByPath.get(feature.parentPagePath) ?? null;\n const parentNode = parentId ? state.nodes.get(parentId) : null;\n\n const node: FeatureNode = {\n id: featureId,\n name: feature.name,\n routePath: parentNode?.routePath,\n sourceFiles: feature.sourceFiles,\n parentId,\n depth: 1,\n status: \"queued\",\n };\n if (state.enqueue(node)) seeded++;\n }\n }\n\n return seeded > 0\n ? `\\nPre-seeded: ${seeded} nodes (pages + sub-features). Call next_node to start processing them one at a time.`\n : \"\";\n}\n\nexport async function runTestGenerator(\n input: TestGeneratorInput,\n): Promise<AgentResult> {\n const model = getModel(input.modelId);\n\n const ignorePatterns = await loadGitignorePatterns(input.projectRoot);\n const existingState = await loadBfsState(input.outputDir);\n const state = existingState ?? new CoverageState();\n\n let result: AgentResult | undefined;\n\n const finishTool = tool({\n description:\n \"Call when the BFS queue is empty and all routes have been explored.\",\n inputSchema: z.object({\n summary: z.string().describe(\"Coverage summary\"),\n }),\n execute: async (finishInput) => {\n const stats = state.summary();\n const totalProcessed = stats.tested;\n if (stats.queued > 0) {\n return {\n error: `Cannot finish: ${stats.queued} nodes still in queue. Process them first.`,\n };\n }\n if (totalProcessed < 10 && stats.totalNodes > 10) {\n return {\n error: `Cannot finish: only ${totalProcessed} of ${stats.totalNodes} nodes were tested. ${stats.skipped} were skipped. Call next_node to continue processing.`,\n };\n }\n\n result = {\n success: true,\n artifacts: state.allTestPaths(),\n summary: finishInput.summary,\n };\n\n await generateIndex(input.outputDir, state);\n\n return {\n ...stats,\n message: \"Test generation complete. INDEX.md written.\",\n };\n },\n });\n\n let kbContext = \"\";\n try {\n const autonomaMd = await readFile(\n join(input.outputDir, \"AUTONOMA.md\"),\n \"utf-8\",\n );\n kbContext += `\\n## Knowledge Base (AUTONOMA.md)\\n\\n${autonomaMd}\\n`;\n } catch {\n /* KB not available */\n }\n\n try {\n const scenariosMd = await readFile(\n join(input.outputDir, \"scenarios.md\"),\n \"utf-8\",\n );\n kbContext += `\\n## Scenarios\\n\\n${scenariosMd}\\n`;\n } catch {\n /* scenarios not available */\n }\n\n let features: Map<string, DiscoveredFeature> | null = null;\n if (!existingState) {\n features = await loadFeatures(input.outputDir);\n if (!features) {\n console.log(\" Running feature discovery...\");\n features = await runFeatureDiscovery({\n projectRoot: input.projectRoot,\n outputDir: input.outputDir,\n modelId: input.modelId,\n pages: input.pages,\n });\n console.log(` Discovered ${features.size} sub-features`);\n } else {\n console.log(` Loaded ${features.size} cached sub-features from features.json`);\n }\n }\n\n const preseedContext = existingState\n ? \"\"\n : await preseedQueue(state, input.projectRoot, input.pages, features ?? undefined);\n\n const resumeContext = existingState\n ? `\\nYou are RESUMING a previous run. ${existingState.summary().tested} nodes tested, ${existingState.summary().totalTests} tests written. Call next_node to continue.`\n : \"\";\n\n const contextBlock = input.projectContext\n ? \"\\n\" + formatContext(input.projectContext) + \"\\n\"\n : \"\";\n\n let prompt = `Generate E2E test cases by processing every node in the queue.\n${contextBlock}${kbContext}${resumeContext}${preseedContext}\n\nThe project codebase is at the working directory.\n\nMANDATORY PROCESS:\n1. Call next_node to get the first node\n2. For EACH node returned by next_node:\n a. Read its source files and explore the surrounding codebase — use glob, grep, read_file to find ALL related components, utilities, and imports. Don't stop at the page file.\n b. Catalog every interactive element: buttons, inputs, toggles, forms, modals, tables, dropdowns\n c. Write tests PROPORTIONAL to the feature's actual complexity — the more interactive elements and workflows you find in the source, the more tests you write\n d. CRUD COMPLETENESS: if the source has Create/Edit/Delete for ANY entity, write tests for ALL of them\n e. OUTCOME VERIFICATION: after every action, navigate to where the result should be visible and ASSERT it\n f. After writing tests, call next_node to get the next node\n g. If a node has no testable behavior (utility, redirect): call next_node to skip it (auto-skipped)\n3. When next_node returns done, call finish\n\nDo NOT spend excessive time on any single node. Write tests for what you find, then move on.\nDo NOT try to finish early. Process EVERY node via next_node until it returns done.`;\n\n const CHUNK_STEPS = 3000;\n const MAX_STALE_CHUNKS = 3;\n let totalSteps = 0;\n\n const logger = createStepLogger(\"test-gen\", CHUNK_STEPS);\n\n const listDirectoryFn = await buildListDirectoryTool(input.projectRoot);\n const agentConfig = {\n id: \"test-generator\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: CHUNK_STEPS,\n temperature: 0.3,\n tools: (heartbeat: () => void) => ({\n read_file: buildReadFileTool(input.projectRoot),\n read_output: buildReadFileTool(input.outputDir),\n glob: buildGlobTool(input.projectRoot, ignorePatterns),\n grep: buildGrepTool(input.projectRoot),\n bash: buildBashTool(input.projectRoot),\n list_directory: listDirectoryFn,\n write_test: buildWriteTestTool(state, input.outputDir),\n create_folder: buildCreateFolderTool(input.outputDir),\n next_node: buildNextNodeTool(state, input.outputDir),\n get_progress: buildGetProgressTool(state),\n spawn_researcher: buildSpawnResearcherTool(\n model,\n input.projectRoot,\n heartbeat,\n ),\n finish: finishTool,\n }),\n onStepFinish: (info: Parameters<typeof logger.log>[0]) => {\n logger.log(info);\n\n const stats = state.summary();\n if (info.stepNumber > 0 && info.stepNumber % 10 === 0) {\n logger.checkpoint(\n `${stats.tested} nodes tested, ${stats.totalTests} tests written, ${stats.queued} in queue`,\n );\n }\n },\n };\n\n let staleChunks = 0;\n let lastTestCount = state.summary().totalTests;\n\n while (!result) {\n try {\n await runAgent(agentConfig, prompt, () => result);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(` [chunk] Agent error (will retry next chunk): ${message}`);\n }\n\n totalSteps += CHUNK_STEPS;\n\n if (result) break;\n\n const stats = state.summary();\n const newTests = stats.totalTests - lastTestCount;\n\n if (newTests === 0) {\n staleChunks++;\n console.log(\n ` [chunk] No progress in last ${CHUNK_STEPS} steps (stale ${staleChunks}/${MAX_STALE_CHUNKS})`,\n );\n if (staleChunks >= MAX_STALE_CHUNKS) {\n console.log(\n ` [chunk] Agent stuck — ${MAX_STALE_CHUNKS} consecutive chunks with no progress. Stopping.`,\n );\n break;\n }\n } else {\n staleChunks = 0;\n }\n\n lastTestCount = stats.totalTests;\n\n if (stats.queued === 0 && stats.tested > 0) {\n console.log(\n ` [chunk] Queue empty after ${totalSteps} steps. Finishing.`,\n );\n break;\n }\n\n console.log(\n ` [chunk] Continuing — ${stats.totalTests} tests, ${stats.queued} queued, ${totalSteps} total steps`,\n );\n\n prompt = `You are RESUMING a previous run. ${stats.tested} nodes tested, ${stats.totalTests} tests written.\nCall next_node to get the next node. Continue processing all remaining nodes.\nIMPORTANT: Do NOT try to finish early. Process every node via next_node until it returns done.`;\n }\n\n logger.summary();\n\n if (!result && state.allTestPaths().length > 0) {\n await generateIndex(input.outputDir, state);\n const stats = state.summary();\n result = {\n success: true,\n artifacts: state.allTestPaths(),\n summary: `${stats.totalTests} tests written across ${stats.tested} nodes in ${totalSteps} steps.`,\n };\n }\n\n if (state.allTestPaths().length > 0) {\n const journeyCount = await generateJourneyTests(\n input.outputDir,\n model,\n input.projectRoot,\n );\n if (journeyCount > 0) {\n console.log(` Generated ${journeyCount} journey tests`);\n }\n\n // --- Review → Fix cycle (max MAX_REVIEW_CYCLES) ---\n const MAX_REVIEW_CYCLES = 4;\n\n for (let cycle = 0; cycle < MAX_REVIEW_CYCLES; cycle++) {\n console.log(` Review cycle ${cycle + 1}/${MAX_REVIEW_CYCLES}`);\n\n const reviewResult = await runConsolidatedReview(\n input.outputDir,\n input.projectRoot,\n model,\n );\n\n console.log(\n ` Review: ${reviewResult.passed} passed, ${reviewResult.failed} failed`,\n );\n\n if (reviewResult.feedback.length === 0) {\n console.log(` All tests passed review — done`);\n break;\n }\n\n // Delete failing tests before feeding back to planner\n for (const fb of reviewResult.feedback) {\n try {\n await unlink(fb.testPath);\n } catch { /* already gone */ }\n }\n\n // Fix in parallel — each test gets its own focused prompt\n console.log(\n ` Feeding ${reviewResult.feedback.length} tests back to planner for fixes`,\n );\n\n const fixBatchSize = MAX_CONCURRENCY;\n for (let i = 0; i < reviewResult.feedback.length; i += fixBatchSize) {\n const batch = reviewResult.feedback.slice(i, i + fixBatchSize);\n await Promise.all(\n batch.map(async (fb) => {\n const fixPrompt = buildReviewFixPrompt(fb);\n let fixResult: AgentResult | undefined;\n try {\n await runAgent(\n { ...agentConfig, maxSteps: 30 },\n fixPrompt,\n () => fixResult,\n );\n } catch (err) {\n console.warn(\n ` [fix] Error fixing ${fb.relativePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }),\n );\n }\n\n console.log(` Fix pass complete`);\n }\n\n // --- Final validation sweep: move structurally invalid tests to _invalid/ ---\n const allTestFiles = await glob(\n join(input.outputDir, \"qa-tests\", \"**/*.md\"),\n );\n let markedInvalid = 0;\n for (const testPath of allTestFiles) {\n if (basename(testPath) === \"INDEX.md\") continue;\n if (testPath.includes(\"/_invalid/\")) continue;\n const content = await readFile(testPath, \"utf-8\");\n const validation = validateTestContent(content);\n if (!validation.valid) {\n const invalidDir = join(input.outputDir, \"qa-tests\", \"_invalid\");\n await mkdir(invalidDir, { recursive: true });\n const dest = join(invalidDir, basename(testPath));\n const annotated = `<!-- VALIDATION ERRORS: ${validation.errors.join(\"; \")} -->\\n${content}`;\n await writeFile(dest, annotated, \"utf-8\");\n await unlink(testPath);\n markedInvalid++;\n }\n }\n if (markedInvalid > 0) {\n console.log(\n ` ${markedInvalid} tests still invalid after review cycles — moved to _invalid/`,\n );\n }\n\n // --- Clean up empty directories ---\n const dirs = await glob(join(input.outputDir, \"qa-tests\", \"**/\"), {\n dot: false,\n });\n for (const dir of dirs.sort((a, b) => b.length - a.length)) {\n try {\n await rmdir(dir);\n } catch {\n /* not empty */\n }\n }\n }\n\n const reviewed = await reviewLoop(result, {\n agentId: \"test-generator\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n showPreview: false,\n reviewGuidance:\n \"Check that critical flows have test coverage.\\n\" +\n \"Verify test steps reference real UI elements (button labels, form fields, navigation paths).\\n\" +\n \"Look for tests that seem to duplicate each other or reference features that don't exist.\\n\" +\n \"Test files are in the qa-tests/ folder in the output directory shown above.\",\n onFeedback: async (feedback) => {\n result = undefined;\n const feedbackPrompt = `The user reviewed the generated tests and has this feedback:\n\n\"${feedback}\"\n\nCheck current progress with get_progress.\nRead your previous test files if needed.\nAdjust based on the feedback — add missing tests, fix existing ones, or explore new areas.\nWhen done, call finish again.`;\n\n await runAgent(agentConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n return (\n reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Test generator did not produce a result\",\n }\n );\n}\n\nfunction buildReviewFixPrompt(fb: TestReviewFeedback): string {\n const failedDetails = fb.failedDimensions.map((dim) => {\n const d = fb.dimensions[dim];\n if (!d) return `- **${dim}**: no evidence available`;\n return `- **${dim}**: ${d.evidence}${d.suggestion ? `\\n Suggestion: ${d.suggestion}` : \"\"}`;\n }).join(\"\\n\");\n\n return `Fix this ONE test that failed review. The reviewer found specific problems — read the feedback carefully and use your tools to investigate and fix.\n\n## Test: ${fb.relativePath}\n\\`\\`\\`\n${fb.content}\n\\`\\`\\`\n\n## Review feedback (failed dimensions):\n${failedDetails}\n\n## Instructions:\n1. Read the source files for this feature to understand what the real UI looks like\n2. If the feedback mentions scenario data issues, use read_output to read scenarios.md and use ONLY values that exist there\n3. Fix the specific issues the reviewer identified — use the evidence and suggestions\n4. Rewrite the test using write_test — the tool validates structure automatically\n5. If the test is unfixable (the feature doesn't support the intended behavior), skip it and call finish\n\nIMPORTANT: Focus ONLY on this test. Do not write new tests or modify other files.`;\n}\n\n\nasync function generateIndex(\n outputDir: string,\n state: CoverageState,\n): Promise<void> {\n const testsByFolder = new Map<string, string[]>();\n\n for (const paths of state.testsWritten.values()) {\n for (const p of paths) {\n const parts = p.split(\"/\");\n if (parts.length >= 3) {\n const folder = parts[1]!;\n const existing = testsByFolder.get(folder) ?? [];\n existing.push(p);\n testsByFolder.set(folder, existing);\n }\n }\n }\n\n const stats = state.summary();\n const folders = [...testsByFolder.entries()].map(([name, tests]) => ({\n name,\n test_count: tests.length,\n }));\n\n const critCounts = new Map([\n [\"critical\", 0],\n [\"high\", 0],\n [\"mid\", 0],\n [\"low\", 0],\n ]);\n const flowCounts = new Map<string, number>();\n let totalSteps = 0;\n let totalInteractions = 0;\n\n for (const paths of state.testsWritten.values()) {\n for (const p of paths) {\n try {\n const content = await readFile(join(outputDir, p), \"utf-8\");\n const critMatch = content.match(/criticality:\\s*(\\w+)/);\n const critVal = critMatch?.[1] ?? \"\";\n if (critCounts.has(critVal))\n critCounts.set(critVal, (critCounts.get(critVal) ?? 0) + 1);\n const flowMatch = content.match(/flow:\\s*\"([^\"]+)\"/);\n const flowVal = flowMatch?.[1];\n if (flowVal)\n flowCounts.set(flowVal, (flowCounts.get(flowVal) ?? 0) + 1);\n const stepMatches = content.match(\n /^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm,\n );\n if (stepMatches) totalSteps += stepMatches.length;\n const interactionMatches = content.match(\n /^\\d+\\.\\s+(click|type|drag):/gm,\n );\n if (interactionMatches) totalInteractions += interactionMatches.length;\n } catch {\n /* file may not exist */\n }\n }\n }\n\n const avgSteps =\n stats.totalTests > 0 ? (totalSteps / stats.totalTests).toFixed(1) : \"0\";\n\n let content = `---\ntotal_tests: ${stats.totalTests}\ntotal_folders: ${folders.length}\navg_steps_per_test: ${avgSteps}\ntotal_interactions: ${totalInteractions}\ncriticality:\n critical: ${critCounts.get(\"critical\") ?? 0}\n high: ${critCounts.get(\"high\") ?? 0}\n mid: ${critCounts.get(\"mid\") ?? 0}\n low: ${critCounts.get(\"low\") ?? 0}\nfolders:\n${folders.map((f) => ` - name: \"${f.name}\"\\n test_count: ${f.test_count}`).join(\"\\n\")}\n---\n\n# Test Suite Index\n\nGenerated by BFS exploration. ${stats.tested} nodes tested, ${stats.skipped} skipped.\n\n## Folders\n\n| Folder | Tests |\n|--------|-------|\n${folders.map((f) => `| ${f.name} | ${f.test_count} |`).join(\"\\n\")}\n\n## All Tests\n\n${[...testsByFolder.entries()]\n .flatMap(([_folder, tests]) => tests.map((t) => `- \\`${t}\\``))\n .join(\"\\n\")}\n`;\n\n await writeFile(join(outputDir, \"qa-tests\", \"INDEX.md\"), content, \"utf-8\");\n}\n\nasync function generateJourneyTests(\n outputDir: string,\n model: LanguageModel,\n projectRoot: string,\n): Promise<number> {\n const logger = createStepLogger(\"journeys\", 50);\n\n let autonomaMd = \"\";\n let scenariosMd = \"\";\n try {\n autonomaMd = await readFile(join(outputDir, \"AUTONOMA.md\"), \"utf-8\");\n } catch {}\n try {\n scenariosMd = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch {}\n\n if (!autonomaMd) return 0;\n\n const existingTests = await glob(join(outputDir, \"qa-tests\", \"**/*.md\"));\n const existingTitles: string[] = [];\n for (const t of existingTests) {\n if (basename(t) === \"INDEX.md\") continue;\n const content = await readFile(t, \"utf-8\");\n const titleMatch = content.match(/title:\\s*\"([^\"]+)\"/);\n if (titleMatch) existingTitles.push(titleMatch[1]!);\n }\n\n const featuresContext = \"\";\n\n const journeyPrompt = `Generate cross-feature JOURNEY tests that traverse the core product flow end-to-end.\n\n## Knowledge Base\n${autonomaMd}\n${featuresContext}\n\n## Scenarios (EXACT data in the database)\n${scenariosMd}\n\n## Existing test titles (do NOT duplicate)\n${existingTitles.join(\"\\n\")}\n\n## Instructions\n\nRead the core_flows from the Knowledge Base above. For each core feature, identify how it connects to other features in a real user workflow. Generate journey tests that traverse 2+ core features end-to-end.\n\nEach journey test:\n- Spans 2+ features/pages in sequence\n- Has 8-15 steps (longer than feature tests)\n- Uses EXACT data values from scenarios.md — NEVER use \"Dynamic:\", \"{variable}\", or \"e.g.\"\n- Has criticality: critical\n- Has scenario: standard\n- Includes an **Intent**: section explaining the cross-feature flow being tested\n- Verifies that the OUTPUT of one feature is correctly consumed by the NEXT feature\n- Goes in the \"journeys\" folder\n\nWrite 5-8 journey tests using the write_test tool with folder \"journeys\". Then call finish.`;\n\n const ignorePatterns = await loadGitignorePatterns(projectRoot);\n const journeyState = new CoverageState();\n journeyState.enqueue({\n id: \"journeys\",\n name: \"Journey Tests\",\n sourceFiles: [],\n parentId: null,\n depth: 0,\n status: \"queued\",\n });\n\n let journeyResult: AgentResult | undefined;\n const journeyFinish = tool({\n description: \"Signal journey generation is complete.\",\n inputSchema: z.object({ summary: z.string() }),\n execute: async (finishInput) => {\n journeyResult = {\n success: true,\n artifacts: journeyState.allTestPaths(),\n summary: finishInput.summary,\n };\n return { done: true, count: journeyState.allTestPaths().length };\n },\n });\n\n const config = {\n id: \"journey-gen\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: 50,\n temperature: 0.3,\n tools: () => ({\n read_file: buildReadFileTool(projectRoot),\n read_output: buildReadFileTool(outputDir),\n glob: buildGlobTool(projectRoot, ignorePatterns),\n write_test: buildWriteTestTool(journeyState, outputDir),\n create_folder: buildCreateFolderTool(outputDir),\n finish: journeyFinish,\n }),\n onStepFinish: (info: Parameters<typeof logger.log>[0]) => logger.log(info),\n };\n\n try {\n await runAgent(config, journeyPrompt, () => journeyResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`Journey generator error: ${message}`);\n }\n\n logger.summary();\n return journeyState.allTestPaths().length;\n}\n","import * as p from \"@clack/prompts\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { loadConfig } from \"./config\";\nimport type { AgentResult } from \"./core/agent\";\nimport { type ProjectContext, saveContext, loadContext } from \"./core/context\";\nimport { DEFAULT_MODEL } from \"./core/model\";\nimport { ensureOutputDir } from \"./core/output\";\nimport {\n loadState,\n markStep,\n nextPendingStep,\n type StepName,\n type PipelineState,\n} from \"./core/state\";\n\nconst PAGES_FILE = \"pages.json\";\n\nasync function savePages(outputDir: string, pages: Map<string, { route: string; path: string; description: string }>): Promise<void> {\n const obj = Object.fromEntries(pages);\n await writeFile(join(outputDir, PAGES_FILE), JSON.stringify(obj, null, 2), \"utf-8\");\n}\n\nasync function loadPages(outputDir: string): Promise<Map<string, { route: string; path: string; description: string }>> {\n try {\n const raw = await readFile(join(outputDir, PAGES_FILE), \"utf-8\");\n const obj = JSON.parse(raw);\n return new Map(Object.entries(obj));\n } catch {\n return new Map();\n }\n}\n\nfunction parseArgs(argv: string[]) {\n const args: Record<string, string | boolean> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (arg.startsWith(\"--\")) {\n const key = arg.slice(2);\n const next = argv[i + 1];\n if (next && !next.startsWith(\"--\")) {\n args[key] = next;\n i++;\n } else {\n args[key] = true;\n }\n }\n }\n return args;\n}\n\nconst STEP_LABELS: Record<StepName, string> = {\n pagesFinder: \"Pages Finder\",\n kb: \"Knowledge Base\",\n entityAudit: \"Entity Audit\",\n scenarioRecipe: \"Scenario + Recipe Generator\",\n recipeBuilder: \"Recipe Builder\",\n testGenerator: \"E2E Test Generator (BFS)\",\n};\n\nconst STEP_INTROS: Record<StepName, string> = {\n pagesFinder:\n \"Scanning your codebase to discover every page and route. This maps the full surface area of your application so we know what needs test coverage.\",\n kb:\n \"Reading every page file to build a knowledge base (AUTONOMA.md). This gives the AI context about your features, flows, and UI patterns.\",\n entityAudit:\n \"Identifying every database model and tracing how each gets created — which service function, what side effects. This determines which entities need test data factories.\",\n scenarioRecipe:\n \"Designing test data scenarios with realistic values from your entity audit. The scenario defines exactly WHAT data will exist in the database during tests.\",\n recipeBuilder:\n \"Guiding you through implementing Autonoma SDK factories for each entity. You'll implement each factory and we'll test them live (create + teardown) before moving on.\",\n testGenerator:\n \"Generating exhaustive E2E test cases by exploring every page and feature. Each area gets test coverage proportional to its complexity.\",\n};\n\nasync function runStep(\n step: StepName,\n outputDir: string,\n state: PipelineState,\n config: ReturnType<typeof loadConfig>,\n projectContext?: ProjectContext,\n nonInteractive?: boolean,\n): Promise<PipelineState> {\n const label = STEP_LABELS[step];\n p.note(STEP_INTROS[step], `Step: ${label}`);\n\n state = await markStep(outputDir, state, step, \"running\");\n\n if (step !== \"pagesFinder\" && projectContext && !projectContext.pages) {\n const pages = await loadPages(outputDir);\n if (pages.size > 0) {\n projectContext = { ...projectContext, pages: [...pages.values()] };\n }\n }\n\n try {\n let result: AgentResult | undefined;\n\n switch (step) {\n case \"pagesFinder\": {\n const { runPageFinder } = await import(\"./agents/00-pages-finder/index\");\n const pages = await runPageFinder({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n nonInteractive,\n });\n await savePages(outputDir, pages);\n break;\n }\n case \"kb\": {\n const { runKBGenerator } = await import(\"./agents/01-kb-generator/index\");\n result = await runKBGenerator({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"entityAudit\": {\n const { runEntityAudit } = await import(\"./agents/02-entity-audit/index\");\n result = await runEntityAudit({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"scenarioRecipe\": {\n const { runScenarioRecipe } = await import(\"./agents/03-scenario-recipe/index\");\n result = await runScenarioRecipe({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"recipeBuilder\": {\n const { runRecipeBuilder } = await import(\"./agents/04-recipe-builder/index\");\n result = await runRecipeBuilder({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n });\n break;\n }\n case \"testGenerator\": {\n const { runTestGenerator } = await import(\"./agents/05-test-generator/index\");\n const pages = await loadPages(outputDir);\n result = await runTestGenerator({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n pages,\n });\n break;\n }\n }\n\n if (result && !result.success) {\n if (result.paused) {\n state = await markStep(outputDir, state, step, \"paused\");\n p.log.info(`Paused: ${label} — ${result.summary}`);\n } else {\n state = await markStep(outputDir, state, step, \"failed\");\n p.log.error(`Failed: ${label} — ${result.summary}`);\n }\n } else {\n state = await markStep(outputDir, state, step, \"done\");\n p.log.success(`Completed: ${label}`);\n }\n } catch (err) {\n state = await markStep(outputDir, state, step, \"failed\");\n const message = err instanceof Error ? err.message : String(err);\n p.log.error(`Failed: ${label} — ${message}`);\n }\n\n return state;\n}\n\nasync function showStatus(outputDir: string) {\n const state = await loadState(outputDir);\n console.log(\"\\nPipeline Status:\");\n for (const [step, status] of Object.entries(state.steps)) {\n const icon =\n status === \"done\" ? \"+\" :\n status === \"running\" ? \"~\" :\n status === \"paused\" ? \"‖\" :\n status === \"failed\" ? \"x\" :\n \" \";\n const label = STEP_LABELS[step as StepName] ?? step;\n console.log(` [${icon}] ${label}: ${status}`);\n }\n}\n\nconst BANNER = `\n\\x1b[36m\\x1b[1m ___ _\n / _ \\\\ | |\n/ /_\\\\ \\\\_ _| |_ ___ _ __ ___ _ __ ___ __ _\n| _ | | | | __/ _ \\\\| '_ \\\\ / _ \\\\| '_ \\` _ \\\\ / _\\` |\n| | | | |_| | || (_) | | | | (_) | | | | | | (_| |\n\\\\_| |_/\\\\__,_|\\\\__\\\\___/|_| |_|\\\\___/|_| |_| |_|\\\\__,_|\n\\x1b[0m\n\\x1b[2m E2E Test Planner — Generate exhaustive test suites from your codebase\\x1b[0m\n`;\n\nasync function gatherProjectContext(): Promise<ProjectContext | undefined> {\n const description = await p.text({\n message: \"What is this project? (a short description so the agent knows what it's looking at)\",\n placeholder: \"e.g. An insurance underwriting platform with a Next.js frontend and Express API\",\n });\n if (p.isCancel(description)) return undefined;\n\n const testingGoal = await p.text({\n message: \"Why do you want E2E tests? (what are you trying to catch or protect?)\",\n placeholder: \"e.g. We're about to refactor the claims flow and want regression coverage\",\n });\n if (p.isCancel(testingGoal)) return undefined;\n\n const criticalFlows = await p.text({\n message: \"What are the most critical flows? (the ones that absolutely cannot break)\",\n placeholder: \"e.g. User signup, creating a policy, submitting a claim, payment processing\",\n });\n if (p.isCancel(criticalFlows)) return undefined;\n\n return {\n description: description as string,\n testingGoal: testingGoal as string,\n criticalFlows: criticalFlows as string,\n };\n}\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2));\n const command = process.argv[2];\n\n if (command === \"status\") {\n const config = loadConfig({\n project: args.project as string | undefined,\n slug: args.slug as string | undefined,\n });\n if (!args.project) {\n console.log(`No --project flag passed; using current working directory: ${config.projectRoot}`);\n }\n const outputDir = await ensureOutputDir(config.projectSlug);\n await showStatus(outputDir);\n return;\n }\n\n if (command === \"help\" || args.help) {\n console.log(\"Usage:\");\n console.log(\" test-planner [run] [--project <path>] [--model <id>] [--step <name>] [--resume] [--non-interactive]\");\n console.log(\" test-planner status [--project <path>]\");\n console.log(\"\");\n console.log(\"`run` is the default command; it may be omitted.\");\n return;\n }\n\n console.log(BANNER);\n p.intro(\"Let's generate your test suite\");\n\n const config = loadConfig({\n project: args.project as string | undefined,\n model: args.model as string | undefined,\n slug: args.slug as string | undefined,\n });\n\n const modelName = config.modelId ?? process.env.OPENROUTER_MODEL ?? DEFAULT_MODEL;\n\n if (!args.project) {\n p.log.info(`No --project flag passed; using current working directory.`);\n }\n p.log.info(`Project: ${config.projectRoot}`);\n p.log.info(`Model: ${modelName}`);\n\n const nonInteractive = !!args[\"non-interactive\"];\n const outputDir = await ensureOutputDir(config.projectSlug);\n let state = await loadState(outputDir);\n\n let isResuming = !!(args.resume || args.step);\n let projectContext: ProjectContext | undefined;\n\n const hasProgress = Object.values(state.steps).some(\n (s) => s === \"done\" || s === \"running\",\n );\n\n if (!isResuming && !nonInteractive && hasProgress) {\n const completedSteps = Object.entries(state.steps)\n .filter(([, s]) => s === \"done\")\n .map(([name]) => STEP_LABELS[name as StepName])\n .join(\", \");\n\n const resume = await p.confirm({\n message: `Found a previous run${completedSteps ? ` (completed: ${completedSteps})` : \"\"}. Resume from where you left off?`,\n });\n\n if (p.isCancel(resume)) {\n p.log.warn(\"Cancelled.\");\n return;\n }\n\n if (resume) {\n isResuming = true;\n }\n }\n\n if (isResuming || nonInteractive) {\n const saved = await loadContext(outputDir);\n if (saved) {\n projectContext = saved;\n p.log.info(`Loaded project context from previous run`);\n }\n }\n\n if (!projectContext && nonInteractive) {\n p.log.error(\"Non-interactive mode requires saved project context. Run interactively first, or create .project-context.json manually.\");\n return;\n }\n\n if (!projectContext) {\n projectContext = await gatherProjectContext();\n if (!projectContext) {\n p.log.warn(\"Cancelled.\");\n return;\n }\n await saveContext(outputDir, projectContext);\n }\n\n p.log.step(`Output: ${outputDir}`);\n\n console.log(\"\");\n p.log.info(\n `Got it. I'll focus on: ${projectContext.criticalFlows}\\n` +\n ` Starting the pipeline now.`,\n );\n console.log(\"\");\n\n const targetStep = args.step as StepName | undefined;\n\n if (targetStep) {\n if (targetStep === \"testGenerator\" && state.steps.scenarioRecipe !== \"done\") {\n p.log.error(\"Cannot run test generation yet — the scenario recipe step must complete first.\");\n return;\n }\n state = await runStep(targetStep, outputDir, state, config, projectContext, nonInteractive);\n p.outro(\"Done\");\n return;\n }\n\n const startStep = isResuming ? nextPendingStep(state) : \"pagesFinder\" as StepName;\n if (!startStep) {\n p.log.success(\"All steps complete.\");\n return;\n }\n\n const steps: StepName[] = [\"pagesFinder\", \"kb\", \"entityAudit\", \"scenarioRecipe\", \"recipeBuilder\", \"testGenerator\"];\n const startIdx = steps.indexOf(startStep);\n\n try {\n for (let i = startIdx; i < steps.length; i++) {\n const step = steps[i]!;\n state = await runStep(step, outputDir, state, config, projectContext, nonInteractive);\n\n if (state.steps[step] === \"paused\") {\n break;\n }\n\n if (state.steps[step] === \"failed\") {\n p.log.error(\"Pipeline stopped due to failure.\");\n break;\n }\n\n if (i < steps.length - 1 && !nonInteractive) {\n const nextStep = steps[i + 1]!;\n const shouldContinue = await p.confirm({\n message: `Continue to ${STEP_LABELS[nextStep]}?`,\n });\n if (p.isCancel(shouldContinue) || !shouldContinue) {\n p.log.info(\"Pipeline paused. Use --resume to continue.\");\n break;\n }\n }\n }\n } catch (err) {\n if (err instanceof Error && (err.message.includes(\"cancelled\") || err.message.includes(\"Cancelled\"))) {\n p.log.warn(\"Your progress is saved. Run again with --resume to continue from where you left off.\");\n return;\n }\n throw err;\n }\n\n p.outro(\"Done\");\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","import { resolve, join } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\n\nexport interface AppConfig {\n projectRoot: string;\n projectSlug: string;\n modelId?: string;\n databaseUrl?: string;\n sdkEndpointUrl?: string;\n sharedSecret?: string;\n signingSecret?: string;\n autonomaApiUrl?: string;\n autonomaApiToken?: string;\n autonomaGenerationId?: string;\n}\n\nfunction loadProjectEnv(projectRoot: string): void {\n let content: string;\n try {\n content = readFileSync(join(projectRoot, \".env\"), \"utf-8\");\n } catch {\n return;\n }\n\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const key = trimmed.slice(0, eqIdx).trim();\n let value = trimmed.slice(eqIdx + 1).trim();\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n if (!(key in process.env)) {\n process.env[key] = value;\n }\n }\n}\n\nexport function loadConfig(args: {\n project?: string;\n model?: string;\n slug?: string;\n}): AppConfig {\n const projectRoot = resolve(args.project ?? process.cwd());\n\n loadProjectEnv(projectRoot);\n\n const projectSlug =\n args.slug ??\n projectRoot\n .split(\"/\")\n .pop()\n ?.toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") ??\n \"default\";\n\n return {\n projectRoot,\n projectSlug,\n modelId: args.model ?? process.env.OPENROUTER_MODEL,\n databaseUrl: process.env.DATABASE_URL,\n sdkEndpointUrl: process.env.SDK_ENDPOINT_URL,\n sharedSecret: process.env.AUTONOMA_SHARED_SECRET,\n signingSecret: process.env.AUTONOMA_SIGNING_SECRET,\n autonomaApiUrl: process.env.AUTONOMA_API_URL,\n autonomaApiToken: process.env.AUTONOMA_API_TOKEN,\n autonomaGenerationId: process.env.AUTONOMA_GENERATION_ID,\n };\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\n\nexport function slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nexport function getOutputDir(projectSlug: string): string {\n return join(AUTONOMA_HOME, projectSlug);\n}\n\nexport async function ensureOutputDir(projectSlug: string): Promise<string> {\n const dir = getOutputDir(projectSlug);\n await mkdir(dir, { recursive: true });\n return dir;\n}\n\nexport async function ensureSubDir(projectSlug: string, ...parts: string[]): Promise<string> {\n const dir = join(getOutputDir(projectSlug), ...parts);\n await mkdir(dir, { recursive: true });\n return dir;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type StepStatus = \"pending\" | \"running\" | \"done\" | \"failed\" | \"paused\";\n\nexport interface PipelineState {\n steps: {\n pagesFinder: StepStatus;\n kb: StepStatus;\n entityAudit: StepStatus;\n scenarioRecipe: StepStatus;\n recipeBuilder: StepStatus;\n testGenerator: StepStatus;\n };\n}\n\nconst STATE_FILE = \".pipeline-state.json\";\n\nexport function initialState(): PipelineState {\n return {\n steps: {\n pagesFinder: \"pending\",\n kb: \"pending\",\n entityAudit: \"pending\",\n scenarioRecipe: \"pending\",\n recipeBuilder: \"pending\",\n testGenerator: \"pending\",\n },\n };\n}\n\nexport async function loadState(outputDir: string): Promise<PipelineState> {\n const path = join(outputDir, STATE_FILE);\n try {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw) as PipelineState;\n } catch {\n return initialState();\n }\n}\n\nexport async function saveState(\n outputDir: string,\n state: PipelineState,\n): Promise<void> {\n const path = join(outputDir, STATE_FILE);\n await writeFile(path, JSON.stringify(state, null, 2), \"utf-8\");\n}\n\nexport type StepName = keyof PipelineState[\"steps\"];\n\nexport async function markStep(\n outputDir: string,\n state: PipelineState,\n step: StepName,\n status: StepStatus,\n): Promise<PipelineState> {\n const updated = {\n ...state,\n steps: { ...state.steps, [step]: status },\n };\n await saveState(outputDir, updated);\n return updated;\n}\n\nexport function nextPendingStep(state: PipelineState): StepName | null {\n const order: StepName[] = [\"pagesFinder\", \"kb\", \"entityAudit\", \"scenarioRecipe\", \"recipeBuilder\", \"testGenerator\"];\n return order.find((s) => state.steps[s] !== \"done\") ?? null;\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA7B;AAAA;AAAA;AAAA;AAAA,SAAQ,SAAAE,QAAO,YAAAC,YAAU,OAAO,QAAQ,aAAAC,mBAAgB;AACxD,SAAQ,YAAAC,WAAU,QAAAC,cAAW;AAC7B,SAA4B,QAAAC,cAAW;AACvC,SAAQ,KAAAC,WAAQ;AAuBhB,SAAQ,QAAAC,aAAW;AAkBnB,eAAe,aACb,OACA,aACA,OACA,UACiB;AACjB,MAAI,SAAS;AAEb,QAAM,eAAe,oBAAI,IAAoB;AAE7C,aAAW,CAAC,cAAc,IAAI,KAAK,OAAO;AACxC,UAAM,gBAAgB,KAAK,MACxB,MAAM,GAAG,EACT,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,EAAE,QAAQ,aAAa,EAAE,EAAE,QAAQ,SAAS,EAAE,KAAK,OAAO;AAExE,QAAI,cAAc,WAAW,EAAG;AAEhC,UAAM,KAAK,cAAc,KAAK,GAAG;AACjC,UAAM,OAAO,cACV,IAAI,CAAC,MAAM,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,aAAa,MAAM,CAAC,EAC5D,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EACjD,KAAK,KAAK;AAEb,UAAM,UAAU,aAAa,WAAW,WAAW,IAC/C,aAAa,MAAM,YAAY,MAAM,EAAE,QAAQ,OAAO,EAAE,IACxD,KAAK;AAET,iBAAa,IAAI,cAAc,EAAE;AAEjC,UAAM,OAAoB;AAAA,MACxB;AAAA,MACA;AAAA,MACA,WAAW,KAAK,MAAM,WAAW,GAAG,IAAI,KAAK,QAAQ,IAAI,KAAK,KAAK;AAAA,MACnE,aAAa,CAAC,OAAO;AAAA,MACrB,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AACA,QAAI,MAAM,QAAQ,IAAI,EAAG;AAAA,EAC3B;AAEA,MAAI,UAAU;AACZ,eAAW,CAAC,WAAW,OAAO,KAAK,UAAU;AAC3C,YAAM,WAAW,aAAa,IAAI,QAAQ,cAAc,KAAK;AAC7D,YAAM,aAAa,WAAW,MAAM,MAAM,IAAI,QAAQ,IAAI;AAE1D,YAAM,OAAoB;AAAA,QACxB,IAAI;AAAA,QACJ,MAAM,QAAQ;AAAA,QACd,WAAW,YAAY;AAAA,QACvB,aAAa,QAAQ;AAAA,QACrB;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,MACV;AACA,UAAI,MAAM,QAAQ,IAAI,EAAG;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO,SAAS,IACZ;AAAA,cAAiB,MAAM,0FACvB;AACN;AAEA,eAAsB,iBACpB,OACsB;AACtB,QAAM,QAAQ,SAAS,MAAM,OAAO;AAEpC,QAAM,iBAAiB,MAAM,sBAAsB,MAAM,WAAW;AACpE,QAAM,gBAAgB,MAAM,aAAa,MAAM,SAAS;AACxD,QAAM,QAAQ,iBAAiB,IAAI,cAAc;AAEjD,MAAI;AAEJ,QAAM,aAAaF,OAAK;AAAA,IACtB,aACE;AAAA,IACF,aAAaC,IAAE,OAAO;AAAA,MACpB,SAASA,IAAE,OAAO,EAAE,SAAS,kBAAkB;AAAA,IACjD,CAAC;AAAA,IACD,SAAS,OAAO,gBAAgB;AAC9B,YAAM,QAAQ,MAAM,QAAQ;AAC5B,YAAM,iBAAiB,MAAM;AAC7B,UAAI,MAAM,SAAS,GAAG;AACpB,eAAO;AAAA,UACL,OAAO,kBAAkB,MAAM,MAAM;AAAA,QACvC;AAAA,MACF;AACA,UAAI,iBAAiB,MAAM,MAAM,aAAa,IAAI;AAChD,eAAO;AAAA,UACL,OAAO,uBAAuB,cAAc,OAAO,MAAM,UAAU,uBAAuB,MAAM,OAAO;AAAA,QACzG;AAAA,MACF;AAEA,eAAS;AAAA,QACP,SAAS;AAAA,QACT,WAAW,MAAM,aAAa;AAAA,QAC9B,SAAS,YAAY;AAAA,MACvB;AAEA,YAAM,cAAc,MAAM,WAAW,KAAK;AAE1C,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,YAAY;AAChB,MAAI;AACF,UAAM,aAAa,MAAML;AAAA,MACvBG,OAAK,MAAM,WAAW,aAAa;AAAA,MACnC;AAAA,IACF;AACA,iBAAa;AAAA;AAAA;AAAA,EAAwC,UAAU;AAAA;AAAA,EACjE,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,UAAM,cAAc,MAAMH;AAAA,MACxBG,OAAK,MAAM,WAAW,cAAc;AAAA,MACpC;AAAA,IACF;AACA,iBAAa;AAAA;AAAA;AAAA,EAAqB,WAAW;AAAA;AAAA,EAC/C,QAAQ;AAAA,EAER;AAEA,MAAI,WAAkD;AACtD,MAAI,CAAC,eAAe;AAClB,eAAW,MAAM,aAAa,MAAM,SAAS;AAC7C,QAAI,CAAC,UAAU;AACb,cAAQ,IAAI,gCAAgC;AAC5C,iBAAW,MAAM,oBAAoB;AAAA,QACnC,aAAa,MAAM;AAAA,QACnB,WAAW,MAAM;AAAA,QACjB,SAAS,MAAM;AAAA,QACf,OAAO,MAAM;AAAA,MACf,CAAC;AACD,cAAQ,IAAI,gBAAgB,SAAS,IAAI,eAAe;AAAA,IAC1D,OAAO;AACL,cAAQ,IAAI,YAAY,SAAS,IAAI,yCAAyC;AAAA,IAChF;AAAA,EACF;AAEA,QAAM,iBAAiB,gBACnB,KACA,MAAM,aAAa,OAAO,MAAM,aAAa,MAAM,OAAO,YAAY,MAAS;AAEnF,QAAM,gBAAgB,gBAClB;AAAA,mCAAsC,cAAc,QAAQ,EAAE,MAAM,kBAAkB,cAAc,QAAQ,EAAE,UAAU,gDACxH;AAEJ,QAAM,eAAe,MAAM,iBACvB,OAAO,cAAc,MAAM,cAAc,IAAI,OAC7C;AAEJ,MAAI,SAAS;AAAA,EACb,YAAY,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBzD,QAAM,cAAc;AACpB,QAAM,mBAAmB;AACzB,MAAI,aAAa;AAEjB,QAAM,SAAS,iBAAiB,YAAY,WAAW;AAEvD,QAAM,kBAAkB,MAAM,uBAAuB,MAAM,WAAW;AACtE,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,cAAcI;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV,aAAa;AAAA,IACb,OAAO,CAAC,eAA2B;AAAA,MACjC,WAAW,kBAAkB,MAAM,WAAW;AAAA,MAC9C,aAAa,kBAAkB,MAAM,SAAS;AAAA,MAC9C,MAAM,cAAc,MAAM,aAAa,cAAc;AAAA,MACrD,MAAM,cAAc,MAAM,WAAW;AAAA,MACrC,MAAM,cAAc,MAAM,WAAW;AAAA,MACrC,gBAAgB;AAAA,MAChB,YAAY,mBAAmB,OAAO,MAAM,SAAS;AAAA,MACrD,eAAe,sBAAsB,MAAM,SAAS;AAAA,MACpD,WAAW,kBAAkB,OAAO,MAAM,SAAS;AAAA,MACnD,cAAc,qBAAqB,KAAK;AAAA,MACxC,kBAAkB;AAAA,QAChB;AAAA,QACA,MAAM;AAAA,QACN;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IACA,cAAc,CAAC,SAA2C;AACxD,aAAO,IAAI,IAAI;AAEf,YAAM,QAAQ,MAAM,QAAQ;AAC5B,UAAI,KAAK,aAAa,KAAK,KAAK,aAAa,OAAO,GAAG;AACrD,eAAO;AAAA,UACL,GAAG,MAAM,MAAM,kBAAkB,MAAM,UAAU,mBAAmB,MAAM,MAAM;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,cAAc;AAClB,MAAI,gBAAgB,MAAM,QAAQ,EAAE;AAEpC,SAAO,CAAC,QAAQ;AACd,QAAI;AACF,YAAM,SAAS,aAAa,QAAQ,MAAM,MAAM;AAAA,IAClD,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,cAAQ,IAAI,kDAAkD,OAAO,EAAE;AAAA,IACzE;AAEA,kBAAc;AAEd,QAAI,OAAQ;AAEZ,UAAM,QAAQ,MAAM,QAAQ;AAC5B,UAAM,WAAW,MAAM,aAAa;AAEpC,QAAI,aAAa,GAAG;AAClB;AACA,cAAQ;AAAA,QACN,iCAAiC,WAAW,iBAAiB,WAAW,IAAI,gBAAgB;AAAA,MAC9F;AACA,UAAI,eAAe,kBAAkB;AACnC,gBAAQ;AAAA,UACN,gCAA2B,gBAAgB;AAAA,QAC7C;AACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,oBAAc;AAAA,IAChB;AAEA,oBAAgB,MAAM;AAEtB,QAAI,MAAM,WAAW,KAAK,MAAM,SAAS,GAAG;AAC1C,cAAQ;AAAA,QACN,+BAA+B,UAAU;AAAA,MAC3C;AACA;AAAA,IACF;AAEA,YAAQ;AAAA,MACN,+BAA0B,MAAM,UAAU,WAAW,MAAM,MAAM,YAAY,UAAU;AAAA,IACzF;AAEA,aAAS,oCAAoC,MAAM,MAAM,kBAAkB,MAAM,UAAU;AAAA;AAAA;AAAA,EAG7F;AAEA,SAAO,QAAQ;AAEf,MAAI,CAAC,UAAU,MAAM,aAAa,EAAE,SAAS,GAAG;AAC9C,UAAM,cAAc,MAAM,WAAW,KAAK;AAC1C,UAAM,QAAQ,MAAM,QAAQ;AAC5B,aAAS;AAAA,MACP,SAAS;AAAA,MACT,WAAW,MAAM,aAAa;AAAA,MAC9B,SAAS,GAAG,MAAM,UAAU,yBAAyB,MAAM,MAAM,aAAa,UAAU;AAAA,IAC1F;AAAA,EACF;AAEA,MAAI,MAAM,aAAa,EAAE,SAAS,GAAG;AACnC,UAAM,eAAe,MAAM;AAAA,MACzB,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AACA,QAAI,eAAe,GAAG;AACpB,cAAQ,IAAI,eAAe,YAAY,gBAAgB;AAAA,IACzD;AAGA,UAAM,oBAAoB;AAE1B,aAAS,QAAQ,GAAG,QAAQ,mBAAmB,SAAS;AACtD,cAAQ,IAAI,kBAAkB,QAAQ,CAAC,IAAI,iBAAiB,EAAE;AAE9D,YAAM,eAAe,MAAM;AAAA,QACzB,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,MACF;AAEA,cAAQ;AAAA,QACN,aAAa,aAAa,MAAM,YAAY,aAAa,MAAM;AAAA,MACjE;AAEA,UAAI,aAAa,SAAS,WAAW,GAAG;AACtC,gBAAQ,IAAI,uCAAkC;AAC9C;AAAA,MACF;AAGA,iBAAW,MAAM,aAAa,UAAU;AACtC,YAAI;AACF,gBAAM,OAAO,GAAG,QAAQ;AAAA,QAC1B,QAAQ;AAAA,QAAqB;AAAA,MAC/B;AAGA,cAAQ;AAAA,QACN,aAAa,aAAa,SAAS,MAAM;AAAA,MAC3C;AAEA,YAAM,eAAe;AACrB,eAAS,IAAI,GAAG,IAAI,aAAa,SAAS,QAAQ,KAAK,cAAc;AACnE,cAAM,QAAQ,aAAa,SAAS,MAAM,GAAG,IAAI,YAAY;AAC7D,cAAM,QAAQ;AAAA,UACZ,MAAM,IAAI,OAAO,OAAO;AACtB,kBAAM,YAAY,qBAAqB,EAAE;AACzC,gBAAI;AACJ,gBAAI;AACF,oBAAM;AAAA,gBACJ,EAAE,GAAG,aAAa,UAAU,GAAG;AAAA,gBAC/B;AAAA,gBACA,MAAM;AAAA,cACR;AAAA,YACF,SAAS,KAAK;AACZ,sBAAQ;AAAA,gBACN,wBAAwB,GAAG,YAAY,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,cAC9F;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,cAAQ,IAAI,qBAAqB;AAAA,IACnC;AAGA,UAAM,eAAe,MAAMD;AAAA,MACzBH,OAAK,MAAM,WAAW,YAAY,SAAS;AAAA,IAC7C;AACA,QAAI,gBAAgB;AACpB,eAAW,YAAY,cAAc;AACnC,UAAID,UAAS,QAAQ,MAAM,WAAY;AACvC,UAAI,SAAS,SAAS,YAAY,EAAG;AACrC,YAAM,UAAU,MAAMF,WAAS,UAAU,OAAO;AAChD,YAAM,aAAa,oBAAoB,OAAO;AAC9C,UAAI,CAAC,WAAW,OAAO;AACrB,cAAM,aAAaG,OAAK,MAAM,WAAW,YAAY,UAAU;AAC/D,cAAMJ,OAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3C,cAAM,OAAOI,OAAK,YAAYD,UAAS,QAAQ,CAAC;AAChD,cAAM,YAAY,2BAA2B,WAAW,OAAO,KAAK,IAAI,CAAC;AAAA,EAAS,OAAO;AACzF,cAAMD,YAAU,MAAM,WAAW,OAAO;AACxC,cAAM,OAAO,QAAQ;AACrB;AAAA,MACF;AAAA,IACF;AACA,QAAI,gBAAgB,GAAG;AACrB,cAAQ;AAAA,QACN,KAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAGA,UAAM,OAAO,MAAMK,MAAKH,OAAK,MAAM,WAAW,YAAY,KAAK,GAAG;AAAA,MAChE,KAAK;AAAA,IACP,CAAC;AACD,eAAW,OAAO,KAAK,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;AAC1D,UAAI;AACF,cAAM,MAAM,GAAG;AAAA,MACjB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,WAAW,QAAQ;AAAA,IACxC,SAAS;AAAA,IACT,WAAW,MAAM;AAAA,IACjB,gBAAgB,MAAM;AAAA,IACtB,aAAa;AAAA,IACb,gBACE;AAAA,IAIF,YAAY,OAAO,aAAa;AAC9B,eAAS;AACT,YAAM,iBAAiB;AAAA;AAAA,GAE1B,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAOL,YAAM,SAAS,aAAa,gBAAgB,MAAM,MAAM;AACxD,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,SACE,YAAY;AAAA,IACV,SAAS;AAAA,IACT,WAAW,CAAC;AAAA,IACZ,SAAS;AAAA,EACX;AAEJ;AAEA,SAAS,qBAAqB,IAAgC;AAC5D,QAAM,gBAAgB,GAAG,iBAAiB,IAAI,CAAC,QAAQ;AACrD,UAAM,IAAI,GAAG,WAAW,GAAG;AAC3B,QAAI,CAAC,EAAG,QAAO,OAAO,GAAG;AACzB,WAAO,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,EAAE,aAAa;AAAA,gBAAmB,EAAE,UAAU,KAAK,EAAE;AAAA,EAC5F,CAAC,EAAE,KAAK,IAAI;AAEZ,SAAO;AAAA;AAAA,WAEE,GAAG,YAAY;AAAA;AAAA,EAExB,GAAG,OAAO;AAAA;AAAA;AAAA;AAAA,EAIV,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUf;AAGA,eAAe,cACb,WACA,OACe;AACf,QAAM,gBAAgB,oBAAI,IAAsB;AAEhD,aAAW,SAAS,MAAM,aAAa,OAAO,GAAG;AAC/C,eAAWK,MAAK,OAAO;AACrB,YAAM,QAAQA,GAAE,MAAM,GAAG;AACzB,UAAI,MAAM,UAAU,GAAG;AACrB,cAAM,SAAS,MAAM,CAAC;AACtB,cAAM,WAAW,cAAc,IAAI,MAAM,KAAK,CAAC;AAC/C,iBAAS,KAAKA,EAAC;AACf,sBAAc,IAAI,QAAQ,QAAQ;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,QAAQ;AAC5B,QAAM,UAAU,CAAC,GAAG,cAAc,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO;AAAA,IACnE;AAAA,IACA,YAAY,MAAM;AAAA,EACpB,EAAE;AAEF,QAAM,aAAa,oBAAI,IAAI;AAAA,IACzB,CAAC,YAAY,CAAC;AAAA,IACd,CAAC,QAAQ,CAAC;AAAA,IACV,CAAC,OAAO,CAAC;AAAA,IACT,CAAC,OAAO,CAAC;AAAA,EACX,CAAC;AACD,QAAM,aAAa,oBAAI,IAAoB;AAC3C,MAAI,aAAa;AACjB,MAAI,oBAAoB;AAExB,aAAW,SAAS,MAAM,aAAa,OAAO,GAAG;AAC/C,eAAWA,MAAK,OAAO;AACrB,UAAI;AACF,cAAMC,WAAU,MAAMT,WAASG,OAAK,WAAWK,EAAC,GAAG,OAAO;AAC1D,cAAM,YAAYC,SAAQ,MAAM,sBAAsB;AACtD,cAAM,UAAU,YAAY,CAAC,KAAK;AAClC,YAAI,WAAW,IAAI,OAAO;AACxB,qBAAW,IAAI,UAAU,WAAW,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,cAAM,YAAYA,SAAQ,MAAM,mBAAmB;AACnD,cAAM,UAAU,YAAY,CAAC;AAC7B,YAAI;AACF,qBAAW,IAAI,UAAU,WAAW,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,cAAM,cAAcA,SAAQ;AAAA,UAC1B;AAAA,QACF;AACA,YAAI,YAAa,eAAc,YAAY;AAC3C,cAAM,qBAAqBA,SAAQ;AAAA,UACjC;AAAA,QACF;AACA,YAAI,mBAAoB,sBAAqB,mBAAmB;AAAA,MAClE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WACJ,MAAM,aAAa,KAAK,aAAa,MAAM,YAAY,QAAQ,CAAC,IAAI;AAEtE,MAAI,UAAU;AAAA,eACD,MAAM,UAAU;AAAA,iBACd,QAAQ,MAAM;AAAA,sBACT,QAAQ;AAAA,sBACR,iBAAiB;AAAA;AAAA,cAEzB,WAAW,IAAI,UAAU,KAAK,CAAC;AAAA,UACnC,WAAW,IAAI,MAAM,KAAK,CAAC;AAAA,SAC5B,WAAW,IAAI,KAAK,KAAK,CAAC;AAAA,SAC1B,WAAW,IAAI,KAAK,KAAK,CAAC;AAAA;AAAA,EAEjC,QAAQ,IAAI,CAAC,MAAM,cAAc,EAAE,IAAI;AAAA,kBAAsB,EAAE,UAAU,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,gCAKzD,MAAM,MAAM,kBAAkB,MAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzE,QAAQ,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,MAAM,EAAE,UAAU,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,EAIhE,CAAC,GAAG,cAAc,QAAQ,CAAC,EAC1B,QAAQ,CAAC,CAAC,SAAS,KAAK,MAAM,MAAM,IAAI,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,EAC5D,KAAK,IAAI,CAAC;AAAA;AAGX,QAAMR,YAAUE,OAAK,WAAW,YAAY,UAAU,GAAG,SAAS,OAAO;AAC3E;AAEA,eAAe,qBACb,WACA,OACA,aACiB;AACjB,QAAM,SAAS,iBAAiB,YAAY,EAAE;AAE9C,MAAI,aAAa;AACjB,MAAI,cAAc;AAClB,MAAI;AACF,iBAAa,MAAMH,WAASG,OAAK,WAAW,aAAa,GAAG,OAAO;AAAA,EACrE,QAAQ;AAAA,EAAC;AACT,MAAI;AACF,kBAAc,MAAMH,WAASG,OAAK,WAAW,cAAc,GAAG,OAAO;AAAA,EACvE,QAAQ;AAAA,EAAC;AAET,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,gBAAgB,MAAMG,MAAKH,OAAK,WAAW,YAAY,SAAS,CAAC;AACvE,QAAM,iBAA2B,CAAC;AAClC,aAAW,KAAK,eAAe;AAC7B,QAAID,UAAS,CAAC,MAAM,WAAY;AAChC,UAAM,UAAU,MAAMF,WAAS,GAAG,OAAO;AACzC,UAAM,aAAa,QAAQ,MAAM,oBAAoB;AACrD,QAAI,WAAY,gBAAe,KAAK,WAAW,CAAC,CAAE;AAAA,EACpD;AAEA,QAAM,kBAAkB;AAExB,QAAM,gBAAgB;AAAA;AAAA;AAAA,EAGtB,UAAU;AAAA,EACV,eAAe;AAAA;AAAA;AAAA,EAGf,WAAW;AAAA;AAAA;AAAA,EAGX,eAAe,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBzB,QAAM,iBAAiB,MAAM,sBAAsB,WAAW;AAC9D,QAAM,eAAe,IAAI,cAAc;AACvC,eAAa,QAAQ;AAAA,IACnB,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,CAAC;AAAA,IACd,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,EACV,CAAC;AAED,MAAI;AACJ,QAAM,gBAAgBI,OAAK;AAAA,IACzB,aAAa;AAAA,IACb,aAAaC,IAAE,OAAO,EAAE,SAASA,IAAE,OAAO,EAAE,CAAC;AAAA,IAC7C,SAAS,OAAO,gBAAgB;AAC9B,sBAAgB;AAAA,QACd,SAAS;AAAA,QACT,WAAW,aAAa,aAAa;AAAA,QACrC,SAAS,YAAY;AAAA,MACvB;AACA,aAAO,EAAE,MAAM,MAAM,OAAO,aAAa,aAAa,EAAE,OAAO;AAAA,IACjE;AAAA,EACF,CAAC;AAED,QAAM,SAAS;AAAA,IACb,IAAI;AAAA,IACJ,cAAcE;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV,aAAa;AAAA,IACb,OAAO,OAAO;AAAA,MACZ,WAAW,kBAAkB,WAAW;AAAA,MACxC,aAAa,kBAAkB,SAAS;AAAA,MACxC,MAAM,cAAc,aAAa,cAAc;AAAA,MAC/C,YAAY,mBAAmB,cAAc,SAAS;AAAA,MACtD,eAAe,sBAAsB,SAAS;AAAA,MAC9C,QAAQ;AAAA,IACV;AAAA,IACA,cAAc,CAAC,SAA2C,OAAO,IAAI,IAAI;AAAA,EAC3E;AAEA,MAAI;AACF,UAAM,SAAS,QAAQ,eAAe,MAAM,aAAa;AAAA,EAC3D,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,4BAA4B,OAAO,EAAE;AAAA,EACrD;AAEA,SAAO,QAAQ;AACf,SAAO,aAAa,aAAa,EAAE;AACrC;AAlsBA,IAaM;AAbN;AAAA;AAAA;AAAA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA,IAAAG;AAGA;AACA;AACA;AACA,IAAAC;AAOA,IAAAC;AACA;AAZA,IAAM,kBAAkB;AAAA;AAAA;;;ACbxB;AAAA,YAAYC,QAAO;AACnB,SAAS,YAAAC,YAAU,aAAAC,mBAAiB;AACpC,SAAS,QAAAC,cAAY;;;ACFrB;AAAA,SAAS,SAAS,YAAY;AAC9B,SAAS,oBAAoB;AAe7B,SAAS,eAAe,aAA2B;AACjD,MAAI;AACJ,MAAI;AACF,cAAU,aAAa,KAAK,aAAa,MAAM,GAAG,OAAO;AAAA,EAC3D,QAAQ;AACN;AAAA,EACF;AAEA,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,UAAM,QAAQ,QAAQ,QAAQ,GAAG;AACjC,QAAI,UAAU,GAAI;AAClB,UAAM,MAAM,QAAQ,MAAM,GAAG,KAAK,EAAE,KAAK;AACzC,QAAI,QAAQ,QAAQ,MAAM,QAAQ,CAAC,EAAE,KAAK;AAC1C,QAAK,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAAO,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAAI;AACpG,cAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,IAC3B;AACA,QAAI,EAAE,OAAO,QAAQ,MAAM;AACzB,cAAQ,IAAI,GAAG,IAAI;AAAA,IACrB;AAAA,EACF;AACF;AAEO,SAAS,WAAW,MAIb;AACZ,QAAM,cAAc,QAAQ,KAAK,WAAW,QAAQ,IAAI,CAAC;AAEzD,iBAAe,WAAW;AAE1B,QAAM,cACJ,KAAK,QACL,YACG,MAAM,GAAG,EACT,IAAI,GACH,YAAY,EACb,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE,KACzB;AAEF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,KAAK,SAAS,QAAQ,IAAI;AAAA,IACnC,aAAa,QAAQ,IAAI;AAAA,IACzB,gBAAgB,QAAQ,IAAI;AAAA,IAC5B,cAAc,QAAQ,IAAI;AAAA,IAC1B,eAAe,QAAQ,IAAI;AAAA,IAC3B,gBAAgB,QAAQ,IAAI;AAAA,IAC5B,kBAAkB,QAAQ,IAAI;AAAA,IAC9B,sBAAsB,QAAQ,IAAI;AAAA,EACpC;AACF;;;ADlEA;AACA;;;AENA;AAAA,SAAS,aAAa;AACtB,SAAS,QAAAC,aAAY;AACrB,SAAS,eAAe;AAExB,IAAM,gBAAgBA,MAAK,QAAQ,GAAG,WAAW;AAS1C,SAAS,aAAa,aAA6B;AACxD,SAAOC,MAAK,eAAe,WAAW;AACxC;AAEA,eAAsB,gBAAgB,aAAsC;AAC1E,QAAM,MAAM,aAAa,WAAW;AACpC,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,SAAO;AACT;;;ACrBA;AAAA,SAAS,YAAAC,WAAU,aAAAC,kBAAiB;AACpC,SAAS,QAAAC,aAAY;AAerB,IAAM,aAAa;AAEZ,SAAS,eAA8B;AAC5C,SAAO;AAAA,IACL,OAAO;AAAA,MACL,aAAa;AAAA,MACb,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,eAAe;AAAA,IACjB;AAAA,EACF;AACF;AAEA,eAAsB,UAAU,WAA2C;AACzE,QAAMC,QAAOD,MAAK,WAAW,UAAU;AACvC,MAAI;AACF,UAAM,MAAM,MAAMF,UAASG,OAAM,OAAO;AACxC,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,aAAa;AAAA,EACtB;AACF;AAEA,eAAsB,UACpB,WACA,OACe;AACf,QAAMA,QAAOD,MAAK,WAAW,UAAU;AACvC,QAAMD,WAAUE,OAAM,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,OAAO;AAC/D;AAIA,eAAsB,SACpB,WACA,OACA,MACA,QACwB;AACxB,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,OAAO,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,GAAG,OAAO;AAAA,EAC1C;AACA,QAAM,UAAU,WAAW,OAAO;AAClC,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAuC;AACrE,QAAM,QAAoB,CAAC,eAAe,MAAM,eAAe,kBAAkB,iBAAiB,eAAe;AACjH,SAAO,MAAM,KAAK,CAAC,MAAM,MAAM,MAAM,CAAC,MAAM,MAAM,KAAK;AACzD;;;AHpDA,IAAM,aAAa;AAEnB,eAAe,UAAU,WAAmB,OAAyF;AACnI,QAAM,MAAM,OAAO,YAAY,KAAK;AACpC,QAAMC,YAAUC,OAAK,WAAW,UAAU,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,GAAG,OAAO;AACpF;AAEA,eAAe,UAAU,WAA+F;AACtH,MAAI;AACF,UAAM,MAAM,MAAMC,WAASD,OAAK,WAAW,UAAU,GAAG,OAAO;AAC/D,UAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,WAAO,IAAI,IAAI,OAAO,QAAQ,GAAG,CAAC;AAAA,EACpC,QAAQ;AACN,WAAO,oBAAI,IAAI;AAAA,EACjB;AACF;AAEA,SAAS,UAAU,MAAgB;AACjC,QAAM,OAAyC,CAAC;AAChD,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,YAAM,MAAM,IAAI,MAAM,CAAC;AACvB,YAAM,OAAO,KAAK,IAAI,CAAC;AACvB,UAAI,QAAQ,CAAC,KAAK,WAAW,IAAI,GAAG;AAClC,aAAK,GAAG,IAAI;AACZ;AAAA,MACF,OAAO;AACL,aAAK,GAAG,IAAI;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,cAAwC;AAAA,EAC5C,aAAa;AAAA,EACb,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,eAAe;AACjB;AAEA,IAAM,cAAwC;AAAA,EAC5C,aACE;AAAA,EACF,IACE;AAAA,EACF,aACE;AAAA,EACF,gBACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AACJ;AAEA,eAAe,QACb,MACA,WACA,OACA,QACA,gBACA,gBACwB;AACxB,QAAM,QAAQ,YAAY,IAAI;AAC9B,EAAE,QAAK,YAAY,IAAI,GAAG,SAAS,KAAK,EAAE;AAE1C,UAAQ,MAAM,SAAS,WAAW,OAAO,MAAM,SAAS;AAExD,MAAI,SAAS,iBAAiB,kBAAkB,CAAC,eAAe,OAAO;AACrE,UAAM,QAAQ,MAAM,UAAU,SAAS;AACvC,QAAI,MAAM,OAAO,GAAG;AAClB,uBAAiB,EAAE,GAAG,gBAAgB,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE;AAAA,IACnE;AAAA,EACF;AAEA,MAAI;AACF,QAAI;AAEJ,YAAQ,MAAM;AAAA,MACZ,KAAK,eAAe;AAClB,cAAM,EAAE,eAAAE,eAAc,IAAI,MAAM;AAChC,cAAM,QAAQ,MAAMA,eAAc;AAAA,UAChC,aAAa,OAAO;AAAA,UACpB;AAAA,UACA,SAAS,OAAO;AAAA,UAChB;AAAA,QACF,CAAC;AACD,cAAM,UAAU,WAAW,KAAK;AAChC;AAAA,MACF;AAAA,MACA,KAAK,MAAM;AACT,cAAM,EAAE,gBAAAC,gBAAe,IAAI,MAAM;AACjC,iBAAS,MAAMA,gBAAe;AAAA,UAC5B,aAAa,OAAO;AAAA,UACpB;AAAA,UACA,SAAS,OAAO;AAAA,UAChB;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,eAAe;AAClB,cAAM,EAAE,gBAAAC,gBAAe,IAAI,MAAM;AACjC,iBAAS,MAAMA,gBAAe;AAAA,UAC5B,aAAa,OAAO;AAAA,UACpB;AAAA,UACA,SAAS,OAAO;AAAA,UAChB;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,kBAAkB;AACrB,cAAM,EAAE,mBAAAC,mBAAkB,IAAI,MAAM;AACpC,iBAAS,MAAMA,mBAAkB;AAAA,UAC/B,aAAa,OAAO;AAAA,UACpB;AAAA,UACA,SAAS,OAAO;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,iBAAiB;AACpB,cAAM,EAAE,kBAAAC,kBAAiB,IAAI,MAAM;AACnC,iBAAS,MAAMA,kBAAiB;AAAA,UAC9B,aAAa,OAAO;AAAA,UACpB;AAAA,UACA,SAAS,OAAO;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,iBAAiB;AACpB,cAAM,EAAE,kBAAAC,kBAAiB,IAAI,MAAM;AACnC,cAAM,QAAQ,MAAM,UAAU,SAAS;AACvC,iBAAS,MAAMA,kBAAiB;AAAA,UAC9B,aAAa,OAAO;AAAA,UACpB;AAAA,UACA,SAAS,OAAO;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,CAAC,OAAO,SAAS;AAC7B,UAAI,OAAO,QAAQ;AACjB,gBAAQ,MAAM,SAAS,WAAW,OAAO,MAAM,QAAQ;AACvD,QAAE,OAAI,KAAK,WAAW,KAAK,WAAM,OAAO,OAAO,EAAE;AAAA,MACnD,OAAO;AACL,gBAAQ,MAAM,SAAS,WAAW,OAAO,MAAM,QAAQ;AACvD,QAAE,OAAI,MAAM,WAAW,KAAK,WAAM,OAAO,OAAO,EAAE;AAAA,MACpD;AAAA,IACF,OAAO;AACL,cAAQ,MAAM,SAAS,WAAW,OAAO,MAAM,MAAM;AACrD,MAAE,OAAI,QAAQ,cAAc,KAAK,EAAE;AAAA,IACrC;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,MAAM,SAAS,WAAW,OAAO,MAAM,QAAQ;AACvD,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,IAAE,OAAI,MAAM,WAAW,KAAK,WAAM,OAAO,EAAE;AAAA,EAC7C;AAEA,SAAO;AACT;AAEA,eAAe,WAAW,WAAmB;AAC3C,QAAM,QAAQ,MAAM,UAAU,SAAS;AACvC,UAAQ,IAAI,oBAAoB;AAChC,aAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,MAAM,KAAK,GAAG;AACxD,UAAM,OACJ,WAAW,SAAS,MACpB,WAAW,YAAY,MACvB,WAAW,WAAW,WACtB,WAAW,WAAW,MACtB;AACF,UAAM,QAAQ,YAAY,IAAgB,KAAK;AAC/C,YAAQ,IAAI,MAAM,IAAI,KAAK,KAAK,KAAK,MAAM,EAAE;AAAA,EAC/C;AACF;AAEA,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWf,eAAe,uBAA4D;AACzE,QAAM,cAAc,MAAQ,QAAK;AAAA,IAC/B,SAAS;AAAA,IACT,aAAa;AAAA,EACf,CAAC;AACD,MAAM,YAAS,WAAW,EAAG,QAAO;AAEpC,QAAM,cAAc,MAAQ,QAAK;AAAA,IAC/B,SAAS;AAAA,IACT,aAAa;AAAA,EACf,CAAC;AACD,MAAM,YAAS,WAAW,EAAG,QAAO;AAEpC,QAAM,gBAAgB,MAAQ,QAAK;AAAA,IACjC,SAAS;AAAA,IACT,aAAa;AAAA,EACf,CAAC;AACD,MAAM,YAAS,aAAa,EAAG,QAAO;AAEtC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,OAAO;AACpB,QAAM,OAAO,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC5C,QAAM,UAAU,QAAQ,KAAK,CAAC;AAE9B,MAAI,YAAY,UAAU;AACxB,UAAMC,UAAS,WAAW;AAAA,MACxB,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,IACb,CAAC;AACD,QAAI,CAAC,KAAK,SAAS;AACjB,cAAQ,IAAI,8DAA8DA,QAAO,WAAW,EAAE;AAAA,IAChG;AACA,UAAMC,aAAY,MAAM,gBAAgBD,QAAO,WAAW;AAC1D,UAAM,WAAWC,UAAS;AAC1B;AAAA,EACF;AAEA,MAAI,YAAY,UAAU,KAAK,MAAM;AACnC,YAAQ,IAAI,QAAQ;AACpB,YAAQ,IAAI,uGAAuG;AACnH,YAAQ,IAAI,0CAA0C;AACtD,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,kDAAkD;AAC9D;AAAA,EACF;AAEA,UAAQ,IAAI,MAAM;AAClB,EAAE,SAAM,gCAAgC;AAExC,QAAM,SAAS,WAAW;AAAA,IACxB,SAAS,KAAK;AAAA,IACd,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,EACb,CAAC;AAED,QAAM,YAAY,OAAO,WAAW,QAAQ,IAAI,oBAAoB;AAEpE,MAAI,CAAC,KAAK,SAAS;AACjB,IAAE,OAAI,KAAK,4DAA4D;AAAA,EACzE;AACA,EAAE,OAAI,KAAK,YAAY,OAAO,WAAW,EAAE;AAC3C,EAAE,OAAI,KAAK,UAAU,SAAS,EAAE;AAEhC,QAAM,iBAAiB,CAAC,CAAC,KAAK,iBAAiB;AAC/C,QAAM,YAAY,MAAM,gBAAgB,OAAO,WAAW;AAC1D,MAAI,QAAQ,MAAM,UAAU,SAAS;AAErC,MAAI,aAAa,CAAC,EAAE,KAAK,UAAU,KAAK;AACxC,MAAI;AAEJ,QAAM,cAAc,OAAO,OAAO,MAAM,KAAK,EAAE;AAAA,IAC7C,CAAC,MAAM,MAAM,UAAU,MAAM;AAAA,EAC/B;AAEA,MAAI,CAAC,cAAc,CAAC,kBAAkB,aAAa;AACjD,UAAM,iBAAiB,OAAO,QAAQ,MAAM,KAAK,EAC9C,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAM,EAC9B,IAAI,CAAC,CAAC,IAAI,MAAM,YAAY,IAAgB,CAAC,EAC7C,KAAK,IAAI;AAEZ,UAAM,SAAS,MAAQ,WAAQ;AAAA,MAC7B,SAAS,uBAAuB,iBAAiB,gBAAgB,cAAc,MAAM,EAAE;AAAA,IACzF,CAAC;AAED,QAAM,YAAS,MAAM,GAAG;AACtB,MAAE,OAAI,KAAK,YAAY;AACvB;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,MAAI,cAAc,gBAAgB;AAChC,UAAM,QAAQ,MAAM,YAAY,SAAS;AACzC,QAAI,OAAO;AACT,uBAAiB;AACjB,MAAE,OAAI,KAAK,0CAA0C;AAAA,IACvD;AAAA,EACF;AAEA,MAAI,CAAC,kBAAkB,gBAAgB;AACrC,IAAE,OAAI,MAAM,yHAAyH;AACrI;AAAA,EACF;AAEA,MAAI,CAAC,gBAAgB;AACnB,qBAAiB,MAAM,qBAAqB;AAC5C,QAAI,CAAC,gBAAgB;AACnB,MAAE,OAAI,KAAK,YAAY;AACvB;AAAA,IACF;AACA,UAAM,YAAY,WAAW,cAAc;AAAA,EAC7C;AAEA,EAAE,OAAI,KAAK,WAAW,SAAS,EAAE;AAEjC,UAAQ,IAAI,EAAE;AACd,EAAE,OAAI;AAAA,IACJ,0BAA0B,eAAe,aAAa;AAAA;AAAA,EAExD;AACA,UAAQ,IAAI,EAAE;AAEd,QAAM,aAAa,KAAK;AAExB,MAAI,YAAY;AACd,QAAI,eAAe,mBAAmB,MAAM,MAAM,mBAAmB,QAAQ;AAC3E,MAAE,OAAI,MAAM,qFAAgF;AAC5F;AAAA,IACF;AACA,YAAQ,MAAM,QAAQ,YAAY,WAAW,OAAO,QAAQ,gBAAgB,cAAc;AAC1F,IAAE,SAAM,MAAM;AACd;AAAA,EACF;AAEA,QAAM,YAAY,aAAa,gBAAgB,KAAK,IAAI;AACxD,MAAI,CAAC,WAAW;AACd,IAAE,OAAI,QAAQ,qBAAqB;AACnC;AAAA,EACF;AAEA,QAAM,QAAoB,CAAC,eAAe,MAAM,eAAe,kBAAkB,iBAAiB,eAAe;AACjH,QAAM,WAAW,MAAM,QAAQ,SAAS;AAExC,MAAI;AACF,aAAS,IAAI,UAAU,IAAI,MAAM,QAAQ,KAAK;AAC5C,YAAM,OAAO,MAAM,CAAC;AACpB,cAAQ,MAAM,QAAQ,MAAM,WAAW,OAAO,QAAQ,gBAAgB,cAAc;AAEpF,UAAI,MAAM,MAAM,IAAI,MAAM,UAAU;AAClC;AAAA,MACF;AAEA,UAAI,MAAM,MAAM,IAAI,MAAM,UAAU;AAClC,QAAE,OAAI,MAAM,kCAAkC;AAC9C;AAAA,MACF;AAEA,UAAI,IAAI,MAAM,SAAS,KAAK,CAAC,gBAAgB;AAC3C,cAAM,WAAW,MAAM,IAAI,CAAC;AAC5B,cAAM,iBAAiB,MAAQ,WAAQ;AAAA,UACrC,SAAS,eAAe,YAAY,QAAQ,CAAC;AAAA,QAC/C,CAAC;AACD,YAAM,YAAS,cAAc,KAAK,CAAC,gBAAgB;AACjD,UAAE,OAAI,KAAK,4CAA4C;AACvD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAe,UAAU,IAAI,QAAQ,SAAS,WAAW,KAAK,IAAI,QAAQ,SAAS,WAAW,IAAI;AACpG,MAAE,OAAI,KAAK,sFAAsF;AACjG;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,EAAE,SAAM,MAAM;AAChB;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["join","p","path","log","summary","YELLOW","RESET","readFile","join","tool","glob","z","inputSchema","execFile","promisify","tool","z","inputSchema","execFileAsync","join","relative","tool","z","p","path","readFile","relative","resolve","tool","z","inputSchema","ToolLoopAgent","hasToolCall","stepCountIs","tool","z","readFile","inputSchema","writeFile","mkdir","relative","resolve","tool","z","inputSchema","tool","z","path","z","tool","input","execFile","p","join","path","resolve","CYAN","RESET","editor","GREEN","DIM","SYSTEM_PROMPT","tool","z","readFile","join","p","SYSTEM_PROMPT","path","SYSTEM_PROMPT","init_prompt","readFile","writeFile","join","tool","z","glob","buildFinishTool","SYSTEM_PROMPT","init_prompt","readFile","join","init_prompt","readFile","join","tool","z","buildFinishTool","init_prompt","readFile","writeFile","join","STATE_FILE","readFile","join","p","tool","z","SYSTEM_PROMPT","existsSync","join","RESET","readFile","writeFile","join","text","p","writeFile","readFile","join","spawn","tool","z","resolve","DOCS_BASE","p","p","text","p","z","tool","readFile","join","relative","basename","glob","init_review","readFile","writeFile","join","path","STATE_FILE","readFile","writeFile","join","z","tool","path","SYSTEM_PROMPT","mkdir","writeFile","dirname","join","hasToolCall","stepCountIs","tool","ToolLoopAgent","matter","z","resultSchema","init_tools","SYSTEM_PROMPT","init_prompt","mkdir","readFile","writeFile","basename","join","tool","z","glob","SYSTEM_PROMPT","p","content","init_review","init_tools","init_prompt","p","readFile","writeFile","join","join","join","readFile","writeFile","join","path","writeFile","join","readFile","runPageFinder","runKBGenerator","runEntityAudit","runScenarioRecipe","runRecipeBuilder","runTestGenerator","config","outputDir"]}
|