@autonoma-ai/planner 0.1.12 → 0.1.13
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 +34 -12
- package/dist/index.js.map +1 -1
- package/package.json +3 -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/version.ts","../src/core/analytics.ts","../src/core/errors.ts","../src/core/notify.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/review.ts","../src/agents/01-kb-generator/prompt.ts","../src/agents/01-kb-generator/flows.ts","../src/agents/01-kb-generator/index.ts","../src/agents/04-recipe-builder/entity-order.ts","../src/agents/02-entity-audit/audit-table.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/scenario-table.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-relevance.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/discover-schema.ts","../src/agents/04-recipe-builder/phases/failure-classifier.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/global-env.ts","../src/core/output.ts","../src/core/interrupt.ts","../src/core/upload.ts","../src/core/git.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 (user-declared — these MUST be covered):** ${ctx.criticalFlows}\n\nThese are flows the user explicitly said cannot break. Treat them as authoritative: every one of them must be represented faithfully in your output — never drop or downplay them. Start with these, 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 // Trim so a stray space or newline in the env var doesn't get sent as the\n // key and come back as a confusing \"Missing Authentication header\".\n const apiKey = process.env.OPENROUTER_API_KEY?.trim();\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","import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\nconst PACKAGE_NAME = \"@autonoma-ai/planner\";\n\n/**\n * The CLI's own version, read from this package's package.json.\n *\n * We deliberately do NOT use `process.env.npm_package_version`: that variable\n * is set by the package manager from whatever package.json context the process\n * was launched under. When a user runs the CLI inside their own repo (npx, a\n * project script, etc.) it reports the *user's* project version — which is why\n * analytics saw a scatter of bogus versions (0.0.0, 1.9.0, …) and `None` when\n * run as a bare global binary. Reading our own manifest fixes that.\n */\nfunction resolveVersion(): string {\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n // Bundled: this code lives in dist/index.js, so package.json is one level\n // up. In dev (src/core/version.ts) it's two levels up. The name guard keeps\n // us from accidentally picking up the user's package.json.\n for (const rel of [\"../package.json\", \"../../package.json\", \"../../../package.json\"]) {\n try {\n const pkg = JSON.parse(readFileSync(join(here, rel), \"utf-8\"));\n if (pkg?.name === PACKAGE_NAME && typeof pkg.version === \"string\") {\n return pkg.version;\n }\n } catch {\n // Keep looking — a missing or unrelated package.json at this level is fine.\n }\n }\n } catch {\n // import.meta.url unavailable or unreadable — fall through to \"unknown\".\n }\n return \"unknown\";\n}\n\nexport const CLI_VERSION = resolveVersion();\n","import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { randomUUID } from \"node:crypto\";\nimport { CLI_VERSION } from \"./version\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\nconst DEVICE_ID_PATH = join(AUTONOMA_HOME, \".device-id\");\n\n// PostHog project (public/ingestion) key. Safe to ship in a client — it can\n// only write events, not read. Same project as the landing page + app, so the\n// CLI events land in the same funnel. Override with AUTONOMA_POSTHOG_KEY.\nconst POSTHOG_PUBLIC_KEY = \"phc_mUOwUj62r8vyiisFPvXLC3G5RftETIBMnKNSHqTBdka\";\nconst DEFAULT_HOST = \"https://us.i.posthog.com\";\n\nfunction resolveKey(): string {\n return (process.env.AUTONOMA_POSTHOG_KEY ?? POSTHOG_PUBLIC_KEY).trim();\n}\n\nfunction resolveHost(): string {\n return (process.env.AUTONOMA_POSTHOG_HOST ?? DEFAULT_HOST).replace(/\\/+$/, \"\");\n}\n\n// Tracking is ON by default; users opt out with DONT_TRACK=1 (or =true).\nfunction trackingDisabled(): boolean {\n const v = process.env.DONT_TRACK;\n return v === \"1\" || v === \"true\";\n}\n\n// To stitch the CLI into the landing → app → auth → CLI funnel, the app/portal\n// passes the user's PostHog distinct_id to the CLI via AUTONOMA_DISTINCT_ID.\n// When present we use it (and let PostHog build the person profile so the funnel\n// connects). Otherwise we fall back to an anonymous per-machine device id and\n// suppress person processing so we don't create junk persons.\nfunction getIdentity(): string | undefined {\n const id = process.env.AUTONOMA_DISTINCT_ID?.trim();\n return id && id.length > 0 ? id : undefined;\n}\n\n// One id per process, attached to every event — lets you group a run's events,\n// count distinct runs, and dedupe. Stable for the life of the CLI invocation.\nconst RUN_ID = randomUUID();\n\n/**\n * The current run's id. Printed in failure output as a support reference so a\n * user-reported error maps 1:1 to its `$exception` event(s) in analytics.\n */\nexport function getRunId(): string {\n return RUN_ID;\n}\n\nlet cachedDeviceId: string | null = null;\n\nfunction getDeviceId(): string {\n if (cachedDeviceId) return cachedDeviceId;\n try {\n cachedDeviceId = readFileSync(DEVICE_ID_PATH, \"utf-8\").trim();\n if (cachedDeviceId) return cachedDeviceId;\n } catch {}\n cachedDeviceId = randomUUID();\n try {\n mkdirSync(AUTONOMA_HOME, { recursive: true });\n writeFileSync(DEVICE_ID_PATH, cachedDeviceId, { encoding: \"utf-8\", mode: 0o600 });\n } catch {}\n return cachedDeviceId;\n}\n\nlet enabled: boolean | null = null;\n\nfunction isEnabled(): boolean {\n if (enabled === null) {\n enabled = !trackingDisabled() && resolveKey().length > 0;\n }\n return enabled;\n}\n\nconst pending = new Set<Promise<unknown>>();\n\n/**\n * Fire-and-forget anonymous event capture. Never throws and never blocks the\n * CLI — failures are swallowed. No PII or source code is ever sent.\n */\nexport function track(event: string, properties: Record<string, unknown> = {}): void {\n if (!isEnabled()) return;\n\n const identity = getIdentity();\n const body = JSON.stringify({\n api_key: resolveKey(),\n event,\n distinct_id: identity ?? getDeviceId(),\n properties: {\n ...properties,\n run_id: RUN_ID,\n // Only build a person profile when we have a real identity from the app,\n // so the CLI joins the existing funnel person instead of creating a new one.\n $process_person_profile: identity != null,\n cli_version: CLI_VERSION,\n },\n });\n\n const promise = fetch(`${resolveHost()}/capture/`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n })\n .catch(() => {})\n .finally(() => pending.delete(promise));\n\n pending.add(promise);\n}\n\n/**\n * Capture an exception in PostHog error tracking (`$exception` event).\n * Same fire-and-forget guarantees as `track`. Error messages and stacks may\n * reference CLI-internal file paths, never the user's source code.\n */\nexport function trackError(\n error: unknown,\n properties: Record<string, unknown> = {},\n handled = true,\n): void {\n const err = error instanceof Error ? error : new Error(String(error));\n track(\"$exception\", {\n ...properties,\n $exception_list: [\n {\n type: err.name,\n value: err.message,\n mechanism: { handled, synthetic: !(error instanceof Error) },\n },\n ],\n error_stack: err.stack,\n });\n}\n\n/** Flush in-flight events before exit. Best-effort, bounded by `timeoutMs`. */\nexport async function flushAnalytics(timeoutMs = 1500): Promise<void> {\n if (pending.size === 0) return;\n await Promise.race([\n Promise.allSettled([...pending]),\n new Promise((resolve) => setTimeout(resolve, timeoutMs)),\n ]);\n}\n","import { APICallError, RetryError, LoadAPIKeyError, InvalidPromptError, NoSuchModelError } from \"ai\";\nimport { getRunId } from \"./analytics\";\nimport { CLI_VERSION } from \"./version\";\n\nexport class AgentError extends Error {\n constructor(\n message: string,\n public readonly phase: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"AgentError\";\n }\n}\n\nexport class ToolError extends Error {\n constructor(\n message: string,\n public readonly toolName: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"ToolError\";\n }\n}\n\nexport interface RetryOptions {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n}\n\nconst DEFAULT_RETRY: RetryOptions = {\n maxRetries: 3,\n baseDelayMs: 1000,\n maxDelayMs: 30_000,\n};\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: Partial<RetryOptions> = {},\n): Promise<T> {\n const opts = { ...DEFAULT_RETRY, ...options };\n\n for (let attempt = 1; attempt <= opts.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n const isLast = attempt === opts.maxRetries;\n const shouldRetry = opts.shouldRetry?.(error, attempt) ?? isRetryable(error);\n\n if (isLast || !shouldRetry) throw error;\n\n const delay = Math.min(\n opts.baseDelayMs * 2 ** (attempt - 1) + Math.random() * 500,\n opts.maxDelayMs,\n );\n await sleep(delay);\n }\n }\n\n throw new Error(\"Unreachable\");\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n return (\n msg.includes(\"rate limit\") ||\n msg.includes(\"429\") ||\n msg.includes(\"503\") ||\n msg.includes(\"timeout\") ||\n msg.includes(\"econnreset\") ||\n msg.includes(\"econnrefused\")\n );\n }\n return false;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * True when an error represents the user deliberately stopping the run — a\n * Ctrl+C or a \"cancel\" choice at an interactive prompt (clack throws/returns a\n * cancel that we surface as a \"... cancelled\" error). These are not failures:\n * callers should save progress and exit quietly, and must NOT report them to\n * error tracking, where they'd masquerade as bugs.\n */\nexport function isUserCancellation(err: unknown): boolean {\n return err instanceof Error && /\\bcancell?ed\\b/i.test(err.message);\n}\n\n/**\n * A failure we recognize and can explain. When `describeKnownError` returns one,\n * the caller prints the friendly title + hint and suppresses the raw stack —\n * the stack is library-internal noise that wouldn't help the user act.\n */\nexport interface KnownError {\n title: string;\n hint: string;\n}\n\n/**\n * Collapse an exception to every message in its cause chain, lowercased, so a\n * matcher can look for a substring regardless of how deeply the SDK wrapped it.\n */\nfunction chainMessages(err: unknown): string {\n const parts: string[] = [];\n let cur: unknown = err;\n for (let depth = 0; cur != null && depth < 10; depth++) {\n if (cur instanceof Error) {\n parts.push(cur.message);\n cur = cur.cause;\n } else {\n parts.push(String(cur));\n break;\n }\n }\n return parts.join(\" ← \").toLowerCase();\n}\n\n/**\n * Translate the failures we've seen in the wild into an actionable one-liner.\n * These are almost always configuration problems, not bugs — a raw stack just\n * buries the fix. Returns null for anything we don't recognize, so the caller\n * falls back to printing the full stack + a support reference.\n */\nexport function describeKnownError(err: unknown): KnownError | null {\n const msg = chainMessages(err);\n const status = APICallError.isInstance(err) ? err.statusCode : undefined;\n\n const looksLikeAuth =\n msg.includes(\"missing authentication header\") ||\n msg.includes(\"no auth credentials\") ||\n msg.includes(\"openrouter_api_key\") ||\n msg.includes(\"user not found\") ||\n status === 401 ||\n status === 403;\n if (looksLikeAuth) {\n return {\n title: \"OpenRouter rejected the request — your API key looks missing or invalid.\",\n hint: \"Set a valid OPENROUTER_API_KEY (https://openrouter.ai/keys). If it's already set, the key may be revoked, empty, or have a stray space.\",\n };\n }\n\n // OpenRouter rejects a request when the account balance can't cover the\n // tokens it would reserve — the message literally reads \"requires more\n // credits, or fewer max_tokens ... can only afford N\". This is the most\n // common paid-tier blocker and almost always means an empty/near-empty\n // balance, so point straight at the top-up page.\n if (msg.includes(\"fewer max_tokens\") || msg.includes(\"can only afford\")) {\n return {\n title: \"Your OpenRouter account doesn't have enough credit for this run.\",\n hint: \"Add credit (even a few dollars goes a long way) at https://openrouter.ai/settings/credits, then re-run. A free balance can't cover a full request.\",\n };\n }\n\n if (msg.includes(\"insufficient\") || msg.includes(\"credits\") || msg.includes(\"quota\") || status === 402) {\n return {\n title: \"OpenRouter ran out of credits for this account.\",\n hint: \"Add credit at https://openrouter.ai/settings/credits, then re-run.\",\n };\n }\n\n if (\n NoSuchModelError.isInstance(err) ||\n msg.includes(\"not a valid model\") ||\n msg.includes(\"no endpoints found\") ||\n msg.includes(\"model not found\")\n ) {\n return {\n title: \"The requested model isn't available on OpenRouter.\",\n hint: \"Check OPENROUTER_MODEL, or unset it to use the default.\",\n };\n }\n\n if (msg.includes(\"rate limit\") || msg.includes(\"too many requests\") || status === 429) {\n return {\n title: \"OpenRouter is rate-limiting this account.\",\n hint: \"Wait a minute and re-run. If it persists, your key may be on a low-throughput tier.\",\n };\n }\n\n return null;\n}\n\n/**\n * A short support reference block printed under an unrecognized failure. The\n * `ref` is this run's id — it ties the printed error to the exact `$exception`\n * event(s) in analytics, so a user only has to paste one short string for us to\n * find their full stack and context.\n */\nexport function supportReference(extra: Record<string, string | undefined> = {}): string {\n const fields: Record<string, string | undefined> = {\n ref: getRunId(),\n version: CLI_VERSION,\n node: process.version,\n platform: `${process.platform}-${process.arch}`,\n ...extra,\n };\n return Object.entries(fields)\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\" \");\n}\n\n/**\n * Render an exception with its full stack and cause chain, so users can\n * copy-paste it when reporting an issue. The CLI is open source — stacks\n * reference CLI internals, never the user's source code.\n */\nexport function formatException(err: unknown): string {\n if (!(err instanceof Error)) return String(err);\n let out = err.stack ?? `${err.name}: ${err.message}`;\n if (err.cause != null) {\n out += `\\nCaused by: ${formatException(err.cause)}`;\n }\n return out;\n}\n\nexport type AgentErrorClass = \"timeout\" | \"transient\" | \"fatal\";\n\nconst FATAL_STATUS_CODES = new Set([400, 401, 403, 404, 422]);\n\n// Recoverable provider quirks that arrive disguised as fatal client errors\n// (usually a 400). They are not malformed requests we can fix — a fresh retry,\n// or falling back to a different model, gets past them — so they must be\n// classified \"transient\" before the status-code check marks them fatal.\n//\n// \"corrupted thought signature\": Google's Gemini reasoning models (via\n// OpenRouter) intermittently reject a request when the reasoning-token\n// signature carried over from a prior turn fails to validate. It returns as a\n// 400 but is transient — retrying or switching to a non-reasoning fallback\n// model clears it.\nconst RETRYABLE_PROVIDER_QUIRKS = [\"corrupted thought signature\"];\n\nconst TRANSIENT_MESSAGE_PATTERNS = [\n \"econnreset\",\n \"econnrefused\",\n \"etimedout\",\n \"socket hang up\",\n \"fetch failed\",\n \"network\",\n \"overloaded\",\n \"rate limit\",\n \"too many requests\",\n \"429\",\n \"500\",\n \"502\",\n \"503\",\n \"529\",\n];\n\n/**\n * Classify an error thrown by an agent run so the caller can decide whether to\n * retry. Everything unknown defaults to \"transient\" — retries are bounded and\n * a wrong \"fatal\" kills the step, while a wrong \"transient\" only costs a few\n * retries before the failure surfaces anyway.\n */\nexport function classifyAgentError(err: unknown): AgentErrorClass {\n const message = err instanceof Error ? err.message : String(err);\n const msg = message.toLowerCase();\n\n if (msg.includes(\"timed out\") || msg.includes(\"timeout\") || msg.includes(\"abort\")) {\n return \"timeout\";\n }\n\n // Check known recoverable quirks across the whole cause chain first, so a 400\n // status from the underlying APICallError doesn't pre-empt them as fatal.\n const chain = chainMessages(err);\n if (RETRYABLE_PROVIDER_QUIRKS.some((pattern) => chain.includes(pattern))) {\n return \"transient\";\n }\n\n if (APICallError.isInstance(err)) {\n if (err.statusCode != null && FATAL_STATUS_CODES.has(err.statusCode)) return \"fatal\";\n return \"transient\";\n }\n\n if (\n LoadAPIKeyError.isInstance(err) ||\n InvalidPromptError.isInstance(err) ||\n NoSuchModelError.isInstance(err)\n ) {\n return \"fatal\";\n }\n\n if (RetryError.isInstance(err)) {\n if (err.reason === \"errorNotRetryable\" && err.lastError !== err) {\n return classifyAgentError(err.lastError);\n }\n return \"transient\";\n }\n\n if (TRANSIENT_MESSAGE_PATTERNS.some((pattern) => msg.includes(pattern))) {\n return \"transient\";\n }\n\n return \"transient\";\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","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 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(`reading ${summary}`);\n break;\n\n case \"glob\":\n writeSpinner(`glob ${summary}`);\n break;\n\n case \"grep\":\n writeSpinner(`grep ${summary}`);\n break;\n\n case \"list_directory\":\n writeSpinner(`listing ${summary}`);\n break;\n\n case \"bash\":\n writeSpinner(`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 // Label which agent/area finished — otherwise a BFS run ends in a\n // wall of identical \"✓ finish\" lines with no context.\n writePermanent(` ${GREEN}${BOLD}✓ done:${RESET} ${GREEN}${agentId}${RESET}`);\n break;\n\n case \"subagent\":\n case \"spawn_researcher\":\n writePermanent(` ${CYAN}⊕ subagent: ${summary}${RESET}`);\n break;\n\n default:\n writeSpinner(`${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 ModelMessage,\n type ToolSet,\n ToolLoopAgent,\n hasToolCall,\n stepCountIs,\n} from \"ai\";\nimport { track } from \"./analytics\";\nimport { createStepLogger, type StepInfo } from \"./display\";\nimport { AgentError, classifyAgentError, sleep } from \"./errors\";\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\n// The tool loop stops as soon as the model calls `finish` — even when the\n// finish tool rejected with a validation error — or when the model replies\n// with plain text. In both cases no result was captured, so we re-prompt the\n// same conversation a bounded number of times instead of failing the step.\nconst MAX_NUDGES = 2;\nconst NUDGE_PROMPT =\n \"You stopped before completing the task. The task is only complete once the finish tool \" +\n \"has been called and succeeded. If your last finish call returned an error, fix exactly what \" +\n \"it reported. Otherwise, continue where you left off and call the finish tool when done.\";\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\n/**\n * Block appended to a step's prompt when the user retries a failed step with\n * guidance. Returns \"\" when there is no guidance so call sites can always\n * interpolate it.\n */\nexport function formatRetryGuidance(guidance?: string): string {\n if (!guidance?.trim()) return \"\";\n return (\n `\\nA previous attempt at this task did not complete successfully. ` +\n `The user provided this guidance for the retry:\\n\"${guidance.trim()}\"\\n`\n );\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 modelIdOf = (m: LanguageModel) => (typeof m === \"string\" ? m : m.modelId);\n\n // Tag a terminal failure with the agent and model it came from, preserving the\n // original error as the cause so the known-error matcher can still read it.\n const fail = (err: unknown, model: LanguageModel): never => {\n const msg = err instanceof Error ? err.message : String(err);\n throw new AgentError(\n `agent \"${config.id}\" (model ${modelIdOf(model)}) failed: ${msg}`,\n config.id,\n err,\n );\n };\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 const messages: ModelMessage[] = [{ role: \"user\", content: prompt }];\n let generation = await agent.generate({\n messages,\n timeout: { stepMs: stepTimeout },\n });\n\n let nudges = 0;\n while (extractResult() === undefined && nudges < MAX_NUDGES) {\n nudges++;\n console.log(\n ` ${YELLOW}[${config.id}] agent stopped without finishing — nudging (${nudges}/${MAX_NUDGES})...${RESET}`,\n );\n track(\"cli_agent_nudged\", { agent: config.id, nudge: nudges });\n messages.push(...generation.response.messages);\n messages.push({ role: \"user\", content: NUDGE_PROMPT });\n generation = await agent.generate({\n messages,\n timeout: { stepMs: stepTimeout },\n });\n }\n\n return extractResult();\n } catch (err) {\n const errorClass = classifyAgentError(err);\n\n if (errorClass === \"fatal\") fail(err, model);\n\n const msg = err instanceof Error ? err.message : String(err);\n if (errorClass === \"timeout\") {\n console.log(` ${YELLOW}[${config.id}] step timed out after ${stepTimeout / 1000}s${RESET}`);\n } else {\n console.log(` ${YELLOW}[${config.id}] provider error: ${msg}${RESET}`);\n }\n track(\"cli_agent_retryable_error\", { agent: config.id, error_class: errorClass, retry });\n\n if (retry < RETRIES_BEFORE_FALLBACK - 1) {\n console.log(\n ` ${YELLOW}[${config.id}] retrying (${retry + 1}/${RETRIES_BEFORE_FALLBACK})...${RESET}`,\n );\n if (errorClass === \"transient\") {\n await sleep(Math.min(2000 * 2 ** retry, 10_000));\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} failed attempts, switching to ${nextModel}${RESET}`,\n );\n break;\n }\n\n fail(err, model);\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(\"pages\", 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 * 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 * Optional renderer for an inline, human-readable summary of the step's\n * output (e.g. a table of flows). Printed before the review guidance and the\n * feedback prompt. Re-run on every loop iteration so edits are reflected.\n */\n renderSummary?: () => Promise<string | undefined>;\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.renderSummary) {\n const rendered = await options.renderSummary();\n if (rendered) {\n console.log(rendered);\n console.log(\"\");\n }\n }\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- Any flow the user explicitly named as critical in the Project Context MUST appear as a feature in core_flows AND be marked core: true with a coreReason. Map the user's wording to the matching feature(s) — never drop a user-declared critical flow or leave it as core: false.\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 { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport matter from \"gray-matter\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\nexport interface CoreFlow {\n feature: string;\n description?: string;\n mission?: string;\n core?: boolean;\n coreReason?: string;\n}\n\n/** Read AUTONOMA.md and return its `core_flows` frontmatter entries (or []). */\nexport async function parseCoreFlows(outputDir: string): Promise<CoreFlow[]> {\n let raw: string;\n try {\n raw = await readFile(join(outputDir, \"AUTONOMA.md\"), \"utf-8\");\n } catch {\n return [];\n }\n\n try {\n const parsed = matter(raw);\n const flows = (parsed.data as { core_flows?: unknown }).core_flows;\n if (!Array.isArray(flows)) return [];\n return flows\n .filter((f): f is Record<string, unknown> => !!f && typeof f === \"object\")\n .map((f) => ({\n feature: String(f.feature ?? \"\").trim(),\n description: f.description != null ? String(f.description) : undefined,\n mission: f.mission != null ? String(f.mission) : undefined,\n core: f.core === true,\n coreReason: f.coreReason != null ? String(f.coreReason) : undefined,\n }))\n .filter((f) => f.feature.length > 0);\n } catch {\n return [];\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1).trimEnd() + \"…\";\n}\n\nfunction pad(s: string, width: number): string {\n return s + \" \".repeat(Math.max(0, width - s.length));\n}\n\n/** Render core flows as an aligned terminal table, core flows highlighted. */\nexport function renderFlowsTable(flows: CoreFlow[]): string {\n if (flows.length === 0) return \"\";\n\n const DESC_MAX = 60;\n const NAME_MAX = 32;\n\n const rows = flows.map((f, i) => ({\n num: String(i + 1),\n name: truncate(f.feature, NAME_MAX),\n crit: f.core ? \"core\" : \"normal\",\n desc: truncate((f.description ?? \"\").replace(/\\s+/g, \" \").trim(), DESC_MAX),\n }));\n\n const numW = Math.max(1, ...rows.map((r) => r.num.length));\n const nameW = Math.max(\"Flow\".length, ...rows.map((r) => r.name.length));\n const critW = Math.max(\"Criticality\".length, ...rows.map((r) => r.crit.length));\n\n const coreCount = flows.filter((f) => f.core).length;\n const header =\n `${BOLD}${pad(\"#\", numW)} ${pad(\"Flow\", nameW)} ${pad(\"Criticality\", critW)} Description${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + critW + DESC_MAX + 6)}${RESET}`;\n\n const body = rows\n .map((r) => {\n const line = `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.crit, critW)} ${r.desc}`;\n // Highlight core flows so the user can eyeball criticality fast.\n return r.crit === \"core\" ? `${YELLOW}${line}${RESET}` : line;\n })\n .join(\"\\n\");\n\n const caption = `${DIM}${flows.length} flows · ${coreCount} marked core${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\n}\n","import {tool} from \"ai\";\nimport {z} from \"zod\";\nimport {readFile} from \"node:fs/promises\";\nimport {join} from \"node:path\";\nimport {type AgentResult, buildDefaultStepLogger, formatRetryGuidance, 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\";\nimport {parseCoreFlows, renderFlowsTable} from \"./flows\";\n\nexport interface KBGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n retryGuidance?: string;\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 + formatRetryGuidance(input.retryGuidance);\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 // The finish tool can be blocked (e.g. by the page-coverage gate) even though\n // the agent already wrote AUTONOMA.md — which would leave `result` undefined\n // and silently skip the whole review. Don't let that happen: if the file\n // exists, treat the step as done so the user still gets the flows table, the\n // file path, and the editor/chat review below.\n const autonomaPath = join(input.outputDir, \"AUTONOMA.md\");\n const autonomaExists = await readFile(autonomaPath, \"utf-8\").then(() => true).catch(() => false);\n if (!result?.success && autonomaExists) {\n result = {\n success: true,\n artifacts: [\"AUTONOMA.md\"],\n summary: \"Knowledge base generated.\",\n };\n }\n\n // Self-review pass: before involving the user, make the agent verify that the\n // flows the user explicitly declared critical actually landed in core_flows as\n // core: true — and fix the file if not. Targets \"a starting input was ignored\".\n const declaredCriticalFlows = input.projectContext?.criticalFlows?.trim();\n if (result?.success && declaredCriticalFlows) {\n const beforeSelfReview = result;\n result = undefined;\n const selfReviewPrompt = `Before this knowledge base is shown to the user, verify it honors the critical flows they explicitly declared.\n\nThe user said these flows are critical and cannot break:\n\"${declaredCriticalFlows}\"\n\nRead your AUTONOMA.md output. For EACH critical flow the user named:\n- Confirm it appears as a feature in core_flows (map the user's wording to the matching feature).\n- Confirm that feature is marked core: true with a coreReason.\n\nIf any declared critical flow is missing, mismatched, or left core: false, FIX AUTONOMA.md now — add the feature if it is genuinely absent, or flip core to true with a coreReason. Do not downgrade or drop anything the user declared critical.\n\nWhen AUTONOMA.md correctly reflects every declared critical flow, call finish.`;\n await runAgent(agentConfig, selfReviewPrompt, () => result);\n // If the agent didn't re-call finish (e.g. no changes needed), keep the prior result.\n if (!result) result = beforeSelfReview;\n }\n\n const reviewed = await reviewLoop(result, {\n agentId: \"kb-generator\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n renderSummary: async () => {\n const flows = await parseCoreFlows(input.outputDir);\n return flows.length ? renderFlowsTable(flows) : undefined;\n },\n reviewGuidance:\n \"Check that every page/route in your app appears in core_flows.\\n\" +\n \"Verify that every flow the user named as critical in the Project Context appears in core_flows and is marked core: true with a coreReason.\\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 return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"KB generator agent stopped without producing AUTONOMA.md\",\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport { z } from \"zod\";\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\nconst createdBySchema = z.object({\n owner: z.string(),\n via: z.string().optional(),\n why: z.string().optional(),\n});\n\nconst auditedModelSchema = z.object({\n name: z.string(),\n independently_created: z.coerce.boolean().default(false),\n creation_file: z.string().optional(),\n creation_function: z.string().optional(),\n side_effects: z.array(z.string()).optional(),\n // Tolerate a stray `created_by:` with no entries (parsed as null by YAML).\n created_by: z.array(createdBySchema).nullish().transform((v) => v ?? []),\n});\n\nconst frontmatterSchema = z.object({\n models: z.array(auditedModelSchema).nullish().transform((v) => v ?? []),\n});\n\n/**\n * Parse entity-audit.md into structured models. The frontmatter (`models:`) is\n * the contract every downstream step depends on, so this is deliberately\n * forgiving: it first parses real YAML frontmatter (validated with zod), and\n * only if that yields nothing does it fall back to scanning the document line\n * by line. A malformed audit should degrade to partial data, never hard-crash\n * the recipe builder — earlier versions threw \"no YAML frontmatter\" here and\n * took the whole run down.\n */\nexport async function parseEntityAudit(outputDir: string): Promise<AuditedModel[]> {\n const raw = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n\n try {\n const parsed = frontmatterSchema.safeParse(matter(raw).data);\n if (parsed.success && parsed.data.models.length > 0) {\n return parsed.data.models.map((m) => ({\n name: m.name,\n independently_created: m.independently_created,\n creation_file: m.creation_file,\n creation_function: m.creation_function,\n side_effects: m.side_effects,\n created_by: m.created_by,\n }));\n }\n } catch {\n // gray-matter/js-yaml choked on malformed YAML — fall through to the\n // line scanner below, which copes with partial or non-standard output.\n }\n\n return parseAuditByLineScan(raw);\n}\n\n/**\n * Last-resort parser: walk the document and reconstruct models from `- name:`\n * blocks. Works even when the content isn't valid YAML or has no `---` fence.\n */\nfunction parseAuditByLineScan(raw: string): AuditedModel[] {\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---/);\n // Prefer the fenced frontmatter when present, else scan the whole document.\n const yaml = fmMatch ? fmMatch[1]! : raw;\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\n/**\n * Resolve the order entities are processed in: a topological sort of the\n * `created_by` dependency graph (owners before the entities they spawn). Among\n * entities that are simultaneously available (no unmet dependency), ties are\n * broken by `importanceRank` (lower index = more important, surfaced first) when\n * provided, otherwise alphabetically.\n */\nexport function resolveEntityOrder(\n models: AuditedModel[],\n importanceRank?: Map<string, number>,\n): string[] {\n const rankOf = (name: string) => importanceRank?.get(name) ?? Number.MAX_SAFE_INTEGER;\n const compare = (a: string, b: string) => rankOf(a) - rankOf(b) || a.localeCompare(b);\n\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(compare);\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(compare);\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 { parseEntityAudit, type AuditedModel } from \"../04-recipe-builder/entity-order\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\n/** Parse the audited models from entity-audit.md (empty on any failure). */\nexport async function parseAuditedModels(outputDir: string): Promise<AuditedModel[]> {\n try {\n return await parseEntityAudit(outputDir);\n } catch {\n return [];\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1).trimEnd() + \"…\";\n}\n\nfunction pad(s: string, width: number): string {\n return s + \" \".repeat(Math.max(0, width - s.length));\n}\n\nfunction creationSource(m: AuditedModel): string {\n if (m.independently_created) {\n return m.creation_function ?? m.creation_file ?? \"(own creation API)\";\n }\n const parents = m.created_by.map((cb) => cb.owner).filter(Boolean);\n return parents.length ? `← ${parents.join(\", \")}` : \"(no known creator)\";\n}\n\n/**\n * Render the entity audit as an aligned terminal table, mirroring the KB flows\n * table. Standalone (independently-created) models are highlighted since those\n * are the ones that get their own factories.\n */\nexport function renderEntityAuditTable(models: AuditedModel[]): string {\n if (models.length === 0) return \"\";\n\n const NAME_MAX = 32;\n const SRC_MAX = 52;\n\n const rows = models.map((m, i) => ({\n num: String(i + 1),\n name: truncate(m.name, NAME_MAX),\n creation: m.independently_created ? \"standalone\" : \"side-effect\",\n source: truncate(creationSource(m).replace(/\\s+/g, \" \").trim(), SRC_MAX),\n }));\n\n const numW = Math.max(1, ...rows.map((r) => r.num.length));\n const nameW = Math.max(\"Entity\".length, ...rows.map((r) => r.name.length));\n const critW = Math.max(\"Creation\".length, ...rows.map((r) => r.creation.length));\n\n const standalone = models.filter((m) => m.independently_created).length;\n const header =\n `${BOLD}${pad(\"#\", numW)} ${pad(\"Entity\", nameW)} ${pad(\"Creation\", critW)} Created from${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + critW + SRC_MAX + 6)}${RESET}`;\n\n const body = rows\n .map((r) => {\n const line = `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.creation, critW)} ${r.source}`;\n // Highlight standalone models — those get their own factories.\n return r.creation === \"standalone\" ? `${YELLOW}${line}${RESET}` : line;\n })\n .join(\"\\n\");\n\n const caption = `${DIM}${models.length} models · ${standalone} standalone · ${models.length - standalone} side-effect-only${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\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, formatRetryGuidance, type AgentResult } from \"../../core/agent\";\nimport { formatException } from \"../../core/errors\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport { reviewLoop } from \"../../core/review\";\nimport { parseAuditedModels, renderEntityAuditTable } from \"./audit-table\";\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 retryGuidance?: string;\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 + formatRetryGuidance(input.retryGuidance);\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 let agentError: string | undefined;\n try {\n await runAgent(agentConfig, prompt, () => result);\n } catch (err) {\n agentError = err instanceof Error ? err.message : String(err);\n console.error(`Entity audit agent error:\\n${formatException(err)}`);\n }\n logger.summary();\n\n // The frontmatter in entity-audit.md is the contract every later step parses,\n // and the tracker holds the authoritative structured data (one entry per\n // mark_model_audited call). Always (re)write the file from the tracker so the\n // on-disk frontmatter is guaranteed well-formed — the agent's own write_file\n // occasionally emitted a file with missing or garbled frontmatter, which used\n // to crash the recipe builder downstream with \"no YAML frontmatter\".\n const writeCanonicalAudit = async (): Promise<string | null> => {\n if (tracker.auditedModels.size === 0) return null;\n const auditPath = join(input.outputDir, \"entity-audit.md\");\n await writeFile(auditPath, tracker.generateAuditMarkdown(), \"utf-8\");\n return auditPath;\n };\n\n const canonicalPath = await writeCanonicalAudit();\n if (!result && canonicalPath) {\n const cov = tracker.coverage();\n result = {\n success: true,\n artifacts: [canonicalPath],\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 renderSummary: async () => {\n const models = await parseAuditedModels(input.outputDir);\n return models.length ? renderEntityAuditTable(models) : undefined;\n },\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 // Re-canonicalize after the agent revised its answers, so the file stays\n // parseable regardless of how the agent rewrote it.\n await writeCanonicalAudit();\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: agentError\n ? `Entity audit failed: ${agentError}`\n : \"Entity audit agent stopped without producing entity-audit.md\",\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","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport matter from \"gray-matter\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\nexport interface ScenarioEntityType {\n name: string;\n count: number;\n variableFields: string[];\n}\n\nexport interface ParsedScenario {\n scenarioNames: string[];\n entityTypes: ScenarioEntityType[];\n}\n\n/** Parse scenarios.md frontmatter into entity types + their variable fields. */\nexport async function parseScenario(outputDir: string): Promise<ParsedScenario> {\n let raw: string;\n try {\n raw = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch {\n return { scenarioNames: [], entityTypes: [] };\n }\n\n try {\n const data = matter(raw).data as {\n scenarios?: { name?: unknown }[];\n entity_types?: { name?: unknown; count?: unknown }[];\n variable_fields?: { entity?: unknown; field?: unknown }[];\n };\n\n // entity name -> [field names that vary]\n const varsByEntity = new Map<string, string[]>();\n for (const vf of data.variable_fields ?? []) {\n const entity = vf?.entity != null ? String(vf.entity) : \"\";\n const field = vf?.field != null ? String(vf.field) : \"\";\n if (!entity || !field) continue;\n const list = varsByEntity.get(entity) ?? [];\n list.push(field);\n varsByEntity.set(entity, list);\n }\n\n const entityTypes: ScenarioEntityType[] = (data.entity_types ?? [])\n .map((e) => {\n const name = e?.name != null ? String(e.name).trim() : \"\";\n const count = typeof e?.count === \"number\" ? e.count : Number(e?.count ?? 0) || 0;\n return { name, count, variableFields: varsByEntity.get(name) ?? [] };\n })\n .filter((e) => e.name.length > 0);\n\n const scenarioNames = (data.scenarios ?? [])\n .map((s) => (s?.name != null ? String(s.name).trim() : \"\"))\n .filter((n) => n.length > 0);\n\n return { scenarioNames, entityTypes };\n } catch {\n return { scenarioNames: [], entityTypes: [] };\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1).trimEnd() + \"…\";\n}\n\nfunction pad(s: string, width: number): string {\n return s + \" \".repeat(Math.max(0, width - s.length));\n}\n\n/**\n * Render the scenario as an aligned terminal table, mirroring the KB flows and\n * entity audit tables. Entities with variable fields (values that change\n * between runs) are highlighted.\n */\nexport function renderScenarioTable(parsed: ParsedScenario): string {\n if (parsed.entityTypes.length === 0) return \"\";\n\n const NAME_MAX = 32;\n const VARS_MAX = 40;\n\n const rows = parsed.entityTypes.map((e, i) => ({\n num: String(i + 1),\n name: truncate(e.name, NAME_MAX),\n count: String(e.count),\n vars: e.variableFields.length ? truncate(e.variableFields.join(\", \"), VARS_MAX) : \"—\",\n hasVars: e.variableFields.length > 0,\n }));\n\n const numW = Math.max(1, ...rows.map((r) => r.num.length));\n const nameW = Math.max(\"Entity\".length, ...rows.map((r) => r.name.length));\n const countW = Math.max(\"Count\".length, ...rows.map((r) => r.count.length));\n\n const totalRecords = parsed.entityTypes.reduce((sum, e) => sum + e.count, 0);\n const withVars = parsed.entityTypes.filter((e) => e.variableFields.length > 0).length;\n\n const header =\n `${BOLD}${pad(\"#\", numW)} ${pad(\"Entity\", nameW)} ${pad(\"Count\", countW)} Variable fields${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + countW + VARS_MAX + 6)}${RESET}`;\n\n const body = rows\n .map((r) => {\n const line = `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.count, countW)} ${r.vars}`;\n // Highlight entities with variable fields — those change between runs.\n return r.hasVars ? `${YELLOW}${line}${RESET}` : line;\n })\n .join(\"\\n\");\n\n const scenarioLabel = parsed.scenarioNames.length\n ? `scenario: ${parsed.scenarioNames.join(\", \")} · `\n : \"\";\n const caption = `${DIM}${scenarioLabel}${parsed.entityTypes.length} entity types · ${totalRecords} records · ${withVars} with variable fields${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\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, formatRetryGuidance, 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 { parseScenario, renderScenarioTable } from \"./scenario-table\";\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 retryGuidance?: string;\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 + formatRetryGuidance(input.retryGuidance);\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 renderSummary: async () => {\n const parsed = await parseScenario(input.outputDir);\n return parsed.entityTypes.length ? renderScenarioTable(parsed) : undefined;\n },\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 agent stopped without producing scenarios.md\",\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 { type LanguageModel, Output, generateText } from \"ai\";\nimport { z } from \"zod\";\nimport { formatException } from \"../../core/errors\";\nimport type { AuditedModel } from \"./entity-order\";\n\nconst rankedSchema = z.object({\n ranked: z\n .array(z.string())\n .describe(\"Every entity name, ordered most-important first.\"),\n});\n\nasync function callRanker(model: LanguageModel, prompt: string): Promise<string[]> {\n const result = await generateText({\n model,\n prompt,\n output: Output.object({ schema: rankedSchema }),\n });\n return result.output.ranked;\n}\n\nexport interface ReconcileResult {\n /** Canonical names in the final, reconciled order. */\n order: string[];\n /** Canonical names the AI omitted (appended to the end in original order). */\n missing: string[];\n /** Names the AI returned that aren't in the canonical set (dropped). */\n invented: string[];\n /** Names the AI returned more than once (later occurrences dropped). */\n duplicates: string[];\n}\n\n/**\n * Reconcile an AI-produced ordering against the canonical set of entity names.\n * Pure and deterministic so the validation logic is testable without a model.\n *\n * - Names not in the canonical set are dropped (recorded as `invented`).\n * - Repeated names keep their first occurrence (extras recorded as `duplicates`).\n * - Canonical names the AI omitted are appended at the end in their original\n * order (recorded as `missing`).\n */\nexport function reconcileRanking(\n canonicalInOrder: string[],\n aiRanked: string[],\n): ReconcileResult {\n const canonical = new Set(canonicalInOrder);\n const order: string[] = [];\n const seen = new Set<string>();\n const invented: string[] = [];\n const duplicates: string[] = [];\n\n for (const name of aiRanked) {\n if (!canonical.has(name)) {\n invented.push(name);\n continue;\n }\n if (seen.has(name)) {\n duplicates.push(name);\n continue;\n }\n seen.add(name);\n order.push(name);\n }\n\n const missing = canonicalInOrder.filter((name) => !seen.has(name));\n order.push(...missing);\n\n return { order, missing, invented, duplicates };\n}\n\nfunction buildPrompt(auditMarkdown: string, feedback?: string): string {\n return `You are ranking the database entities of an application by how foundational they are, so a user can configure them starting from the ones they understand best.\n\nRank from MOST important to LEAST important:\n- HIGH: entities that many others depend on, and entities representing the primary concepts of the domain — the accounts, users, workspaces/tenants, and core business objects a developer would name first when describing the product.\n- LOW: peripheral entities — feature-specific records, integration/audit/logging details, join tables, and narrow or client-specific tables a developer would not have top of mind.\n\nUse the audit below as your only source of truth. The \"created_by\" relationships and how often an entity owns/spawns others are strong signals of importance.\n\nReturn EVERY entity name from the audit, each exactly once, ordered most-important first. Use the names exactly as written in the audit. Do not invent, rename, merge, or omit any entity.${feedback ? `\\n\\n${feedback}` : \"\"}\n\n--- ENTITY AUDIT ---\n${auditMarkdown}`;\n}\n\n/**\n * Ask the model to rank the audited entities by perceived importance and return\n * a `name -> rank index` map (0 = most important) covering every model.\n *\n * Best-effort: on an unrecoverable failure (the call throws, or the result is\n * still broken after one feedback retry) it returns an empty map, signalling the\n * caller to fall back to the default alphabetical ordering. Importance ranking is\n * a UX nicety and must never block recipe building.\n */\nexport async function rankEntitiesByImportance(\n models: AuditedModel[],\n auditMarkdown: string,\n model: LanguageModel,\n): Promise<Map<string, number>> {\n const canonical = models.map((m) => m.name);\n if (canonical.length === 0) return new Map();\n\n // A result is acceptable if the AI named most entities itself; if it dropped\n // a large fraction we retry once with explicit feedback before giving up.\n const acceptableMissing = Math.floor(canonical.length / 2);\n\n try {\n let reconciled = reconcileRanking(canonical, await callRanker(model, buildPrompt(auditMarkdown)));\n\n if (\n reconciled.missing.length > acceptableMissing ||\n reconciled.invented.length > 0 ||\n reconciled.duplicates.length > 0\n ) {\n const feedbackParts: string[] = [\"Your previous response had problems. Fix them:\"];\n if (reconciled.missing.length > 0)\n feedbackParts.push(`- You omitted these entities, include them: ${reconciled.missing.join(\", \")}`);\n if (reconciled.invented.length > 0)\n feedbackParts.push(`- These names are not in the audit, do not use them: ${reconciled.invented.join(\", \")}`);\n if (reconciled.duplicates.length > 0)\n feedbackParts.push(`- These were listed more than once, list each exactly once: ${reconciled.duplicates.join(\", \")}`);\n\n const retry = reconcileRanking(\n canonical,\n await callRanker(model, buildPrompt(auditMarkdown, feedbackParts.join(\"\\n\"))),\n );\n // Keep the retry only if it's actually better than the first attempt.\n if (retry.missing.length <= reconciled.missing.length) reconciled = retry;\n }\n\n return new Map(reconciled.order.map((name, i) => [name, i]));\n } catch (err) {\n console.warn(\n `[recipe-builder] Importance ranking failed, falling back to alphabetical order:\\n${formatException(err)}`,\n );\n return new Map();\n }\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 type { AuditedModel } from \"./entity-order\";\n\nexport type RecipePayload = Record<string, Record<string, unknown>[]>;\n\n/** Recursively collect every alias referenced via `{ _ref: \"...\" }` in a value. */\nfunction collectRefs(value: unknown, out: Set<string>): void {\n if (Array.isArray(value)) {\n for (const v of value) collectRefs(v, out);\n } else if (value !== null && typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n if (typeof obj._ref === \"string\") out.add(obj._ref);\n for (const v of Object.values(obj)) collectRefs(v, out);\n }\n}\n\n/**\n * Build the payload for testing a single entity: that entity plus every other\n * entity it depends on, emitted in dependency order (parents before children).\n *\n * The SDK resolves `_ref`s WITHIN the request body, so any alias a record\n * references must be declared by a record in the same request. The recipe agent\n * is free to `_ref` any already-completed entity (not just the audit's\n * `created_by` parents), so we can't rely on the audit chain alone — a `_ref`\n * the audit never recorded as a dependency would otherwise be missing from the\n * payload and fail with \"references unknown alias(es)\". We therefore include the\n * transitive closure of BOTH the audit's `created_by` owners AND the entities\n * whose aliases actually appear in the recipe data.\n */\nexport function buildSingleEntityRecipe(\n entityName: string,\n models: AuditedModel[],\n entityOrder: string[],\n allEntities: Record<string, EntityProgress>,\n): RecipePayload {\n const modelMap = new Map(models.map((m) => [m.name, m]));\n\n // Which entity declares each alias, from the data we've accepted so far.\n const aliasOwner = new Map<string, string>();\n for (const [name, entity] of Object.entries(allEntities)) {\n for (const rec of entity?.recipeData ?? []) {\n if (typeof rec._alias === \"string\") aliasOwner.set(rec._alias, name);\n }\n }\n\n const recipe: RecipePayload = {};\n const done = new Set<string>();\n const onStack = new Set<string>();\n\n function include(name: string): void {\n if (done.has(name) || onStack.has(name)) return; // skip done + break cycles\n onStack.add(name);\n\n const records = allEntities[name]?.recipeData ?? [];\n\n // Dependencies must be created first: audit-declared owners…\n for (const dep of modelMap.get(name)?.created_by ?? []) {\n if (entityOrder.includes(dep.owner)) include(dep.owner);\n }\n // …plus every entity whose alias this one actually references.\n const refs = new Set<string>();\n collectRefs(records, refs);\n for (const alias of refs) {\n const owner = aliasOwner.get(alias);\n if (owner && owner !== name) include(owner);\n }\n\n onStack.delete(name);\n done.add(name);\n // Insertion order = dependency order, since deps are added above.\n if (records.length > 0) recipe[name] = records;\n }\n\n include(entityName);\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","/**\n * Live schema grounding for the recipe builder.\n *\n * The SDK's `discover` action returns the SOURCE OF TRUTH for what each\n * factory accepts: every registered model with its field names, coarse\n * types, and — critically — which fields are required. (See the SDK's\n * `buildSchemaFromFactories` / `schemaToWire`.)\n *\n * Until now the recipe builder never consumed this: it guessed field\n * names and shapes from the markdown entity audit, so a factory whose\n * `inputSchema` required a tenant FK (e.g. `clientId`) — which the SDK\n * does NOT auto-inject — would fail with an opaque HTTP 500 and the only\n * feedback into the fix loop was that raw error. Grounding propose/revise/\n * triage in this schema replaces guessing with fact.\n */\nimport type { RecipePayload } from \"./recipe\";\nimport * as sdk from \"./http-client\";\nimport type { SdkClientConfig } from \"./http-client\";\n\n/** One field as reported by the SDK's discover response. */\nexport interface DiscoverField {\n name: string;\n /** Coarse type string: string | number | integer | boolean | timestamp | json. */\n type: string;\n isRequired: boolean;\n isId: boolean;\n hasDefault: boolean;\n}\n\nexport interface DiscoverModel {\n name: string;\n tableName: string;\n fields: DiscoverField[];\n}\n\nexport interface DiscoverSchema {\n /** Keyed by model name (matches the factory registry / audit model names). */\n models: Map<string, DiscoverModel>;\n /** The tenant/scope field the dashboard isolates on, e.g. \"organizationId\".\n * The SDK does NOT auto-inject it — factories own the write and the recipe\n * must supply it explicitly wherever a model declares it. */\n scopeField: string | null;\n}\n\n/** Parse the wire JSON from a discover response into a typed schema. Returns\n * null when the body doesn't look like a discover schema (defensive). */\nexport function parseDiscoverBody(body: unknown): DiscoverSchema | null {\n if (!body || typeof body !== \"object\") return null;\n const schema = (body as Record<string, unknown>).schema as Record<string, unknown> | undefined;\n if (!schema || typeof schema !== \"object\") return null;\n\n const rawModels = schema.models;\n if (!Array.isArray(rawModels)) return null;\n\n const models = new Map<string, DiscoverModel>();\n for (const m of rawModels) {\n if (!m || typeof m !== \"object\") continue;\n const mm = m as Record<string, unknown>;\n if (typeof mm.name !== \"string\") continue;\n const rawFields = Array.isArray(mm.fields) ? mm.fields : [];\n const fields: DiscoverField[] = [];\n for (const f of rawFields) {\n if (!f || typeof f !== \"object\") continue;\n const ff = f as Record<string, unknown>;\n if (typeof ff.name !== \"string\") continue;\n fields.push({\n name: ff.name,\n type: typeof ff.type === \"string\" ? ff.type : \"string\",\n isRequired: ff.isRequired === true,\n isId: ff.isId === true,\n hasDefault: ff.hasDefault === true,\n });\n }\n models.set(mm.name, { name: mm.name, tableName: typeof mm.tableName === \"string\" ? mm.tableName : mm.name, fields });\n }\n\n const scopeField = typeof schema.scopeField === \"string\" && schema.scopeField.length > 0\n ? schema.scopeField\n : null;\n\n return { models, scopeField };\n}\n\n/**\n * Fetch the live schema from the SDK endpoint. Best-effort: returns null on\n * any network/HTTP/parse failure so it can never block the recipe builder.\n * Discover reflects only the factories CURRENTLY registered, so call it fresh\n * as the developer wires up more entities rather than caching it forever.\n */\nexport async function fetchDiscoverSchema(config: SdkClientConfig): Promise<DiscoverSchema | null> {\n try {\n const res = await sdk.discover(config);\n if (!res.ok) return null;\n return parseDiscoverBody(res.body);\n } catch {\n return null;\n }\n}\n\n/** True for a field the recipe MUST supply: required, not the synthetic id,\n * and without a factory-side default. */\nfunction isMandatory(field: DiscoverField): boolean {\n return field.isRequired && !field.isId && !field.hasDefault;\n}\n\n/**\n * Render a model's field spec for an LLM prompt. Returns null when the model\n * isn't in the live schema (factory not registered yet) so callers can fall\n * back to the audit-derived schema instead of asserting a wrong one.\n */\nexport function renderModelSchema(schema: DiscoverSchema, modelName: string): string | null {\n const m = schema.models.get(modelName);\n if (!m) return null;\n\n const lines = m.fields\n .filter((f) => !f.isId)\n .map((f) => {\n const req = isMandatory(f) ? \"REQUIRED\" : f.hasDefault ? \"optional (has default)\" : \"optional\";\n const scopeNote = schema.scopeField && f.name === schema.scopeField\n ? \" ← scope/tenant field — the SDK does NOT auto-fill it; set it explicitly (use a { \\\"_ref\\\": \\\"...\\\" } to the scope entity)\"\n : \"\";\n return ` - ${f.name}: ${f.type} (${req})${scopeNote}`;\n });\n\n return `Live schema for \"${modelName}\" (from the SDK /discover endpoint — this is the SOURCE OF TRUTH; it overrides the entity audit when they disagree):\n${lines.join(\"\\n\")}\n\nEvery REQUIRED field above must be present on every record. Do not send fields that are not listed.`;\n}\n\nexport interface RecipeValidationProblem {\n model: string;\n /** Index of the offending record within its model's array. */\n recordIndex: number;\n message: string;\n}\n\n/**\n * Validate an assembled create payload against the live schema BEFORE sending\n * it, turning blind HTTP 500s into precise, local diagnostics.\n *\n * Conservative by design — it only flags problems it is sure about:\n * - a model present in the payload AND in the live schema that omits a\n * mandatory field (required, no default, not the id);\n * - a `_ref` whose alias is declared by no record in the same payload (the\n * SDK resolves refs within the request body).\n *\n * Models absent from the live schema (factory not registered yet) are skipped\n * — we can't assert their shape — so this never produces false positives for\n * not-yet-implemented factories.\n */\nexport function validateRecipeAgainstSchema(\n recipe: RecipePayload,\n schema: DiscoverSchema,\n): RecipeValidationProblem[] {\n const problems: RecipeValidationProblem[] = [];\n\n // Collect every alias declared anywhere in the payload.\n const declaredAliases = new Set<string>();\n for (const records of Object.values(recipe)) {\n for (const rec of records) {\n if (typeof rec._alias === \"string\") declaredAliases.add(rec._alias);\n }\n }\n\n for (const [modelName, records] of Object.entries(recipe)) {\n const model = schema.models.get(modelName);\n records.forEach((record, recordIndex) => {\n // Required-field check (only when we know the model's real shape).\n if (model) {\n for (const field of model.fields) {\n if (!isMandatory(field)) continue;\n const value = record[field.name];\n if (value === undefined || value === null) {\n problems.push({\n model: modelName,\n recordIndex,\n message: `missing required field \"${field.name}\" (${field.type})`,\n });\n }\n }\n }\n // _ref resolvability check (independent of whether the model is known).\n const refs = new Set<string>();\n collectRefs(record, refs);\n for (const alias of refs) {\n if (!declaredAliases.has(alias)) {\n problems.push({\n model: modelName,\n recordIndex,\n message: `_ref points at \"${alias}\", which no record in this payload declares with an _alias`,\n });\n }\n }\n });\n }\n\n return problems;\n}\n\nfunction collectRefs(value: unknown, out: Set<string>): void {\n if (Array.isArray(value)) {\n for (const v of value) collectRefs(v, out);\n } else if (value !== null && typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n if (typeof obj._ref === \"string\") {\n out.add(obj._ref);\n return;\n }\n for (const v of Object.values(obj)) collectRefs(v, out);\n }\n}\n\n/** Format validation problems into a server-error-shaped string the fix loop\n * can consume, mirroring how a real HTTP error body reads. */\nexport function formatValidationProblems(problems: RecipeValidationProblem[]): string {\n const byModel = new Map<string, string[]>();\n for (const p of problems) {\n const key = `${p.model}[${p.recordIndex}]`;\n if (!byModel.has(key)) byModel.set(key, []);\n byModel.get(key)!.push(p.message);\n }\n return [...byModel.entries()]\n .map(([key, msgs]) => `${key}: ${msgs.join(\"; \")}`)\n .join(\"\\n\");\n}\n","import { type LanguageModel, Output, generateText } from \"ai\";\nimport { z } from \"zod\";\nimport { formatException } from \"../../../core/errors\";\n\n/**\n * Which side of the test a failure originates from.\n *\n * - `recipe` — the test DATA we sent is wrong (a _ref points at a\n * non-existent alias, a bad field value, a missing/extra\n * field, a type mismatch). Regenerating the data can fix it,\n * so autofix is worth running.\n * - `implementation` — the developer's HANDLER code is wrong (an unregistered\n * factory, a bug in their insert/delete logic, a wrong\n * column/table name, a server crash). No amount of data\n * regeneration fixes this — the user must change code.\n * - `unclear` — not confidently attributable to either side.\n */\nexport type FailureSide = \"recipe\" | \"implementation\" | \"unclear\";\n\n/** Which leg of the test failed: UP (create test data) or DOWN (tear it down). */\nexport type FailurePhase = \"create\" | \"teardown\";\n\nexport interface FailureClassification {\n side: FailureSide;\n /** One plain-language sentence the user sees explaining the verdict. */\n reason: string;\n}\n\nconst classificationSchema = z.object({\n side: z\n .enum([\"recipe\", \"implementation\", \"unclear\"])\n .describe(\n \"recipe = the test data we sent is wrong and regenerating it could fix the failure; \" +\n \"implementation = the developer's handler/factory code is wrong and only a code change fixes it; \" +\n \"unclear = cannot confidently attribute the failure to either side.\",\n ),\n reason: z\n .string()\n .describe(\"One short, plain-language sentence explaining the verdict for the user. No code, no jargon dumps.\"),\n});\n\nexport interface ClassifyArgs {\n entityName: string;\n /** UP (create) or DOWN (teardown) — teardown failures skew strongly implementation-side. */\n phase: FailurePhase;\n /** HTTP status of the failed response, when the request got one (5xx skews implementation-side). */\n httpStatus?: number;\n /** The raw server error body or formatted exception string. */\n error: unknown;\n /** The recipe payload that was sent (so the model can judge whether different data would help). */\n recipe: unknown;\n /** The _alias values declared by already-created parent entities — the ONLY valid _ref targets. */\n validRefAliases?: string;\n /** What the entity audit recorded about how this entity is created (factory existence, owners). */\n entityAudit?: string;\n /** The live field schema for this entity from the SDK /discover endpoint, if\n * available — the source of truth for required fields and types. */\n liveSchema?: string;\n}\n\n/**\n * A primer on the system under test. Without this the model has no idea what an\n * \"Environment Factory\", a recipe, a _ref, or an UP/DOWN request even is, and\n * can't reason about which side of the contract broke.\n */\nconst PRIMER = `## Background — what you are looking at\n\nThe Autonoma SDK lets a developer seed and tear down test data through a single HTTP endpoint on their own backend (the \"Environment Factory\"). For each database entity the developer registers a *factory* with two functions: a create() that inserts records, and a teardown() that deletes them. Their handler code calls into their app's real service/ORM layer.\n\nA separate tool (not the developer) generates the *recipe*: JSON test data, one array of records per entity. Each record may carry an \"_alias\" (a unique handle, e.g. \"account_1\") and \"_ref\" fields ({ \"_ref\": \"account_1\" }) that point at an alias declared by an already-created parent entity. The tool sends this recipe to the endpoint:\n- An **UP** request asks the factory to create the records (calls create()).\n- A **DOWN** request asks the factory to tear them down (calls teardown()).\n\nSo a failure has exactly two possible origins, and your only job is to tell them apart:`;\n\nexport function buildClassifierPrompt(args: ClassifyArgs): string {\n const errorText = typeof args.error === \"string\" ? args.error : JSON.stringify(args.error, null, 2);\n const phaseLine =\n args.phase === \"teardown\"\n ? `This was a DOWN (teardown) request. Teardown runs the developer's delete logic against data the create() step already accepted, so teardown failures are usually implementation-side (wrong delete order, foreign-key cleanup bugs) rather than caused by the recipe.`\n : `This was an UP (create) request — the factory tried to insert the recipe records.`;\n const statusLine =\n args.httpStatus != null\n ? `HTTP status: ${args.httpStatus}. (A 5xx usually means the handler threw; a 4xx is more often a rejected payload, but use the error text — status alone is not decisive.)`\n : `No HTTP status (the request threw before a response — often a network/server-process problem, lean implementation or unclear).`;\n\n return `${PRIMER}\n\n- RECIPE DATA is wrong — the JSON the tool sent doesn't fit the developer's (correct) schema. Examples of the *kind* of problem (not an exhaustive list): the request body references an alias (_ref) that no record in THIS SAME request declares with an _alias, a field holds a value the backend rejects, a required field is missing or an unknown field was sent, or a value has the wrong type. These are fixable by regenerating the data — the developer's code is fine. NOTE: an error like \"references unknown alias(es): X\" is recipe-side whenever X is not declared by an _alias in the test data shown below — the SDK resolves _refs WITHIN the request body, so it does not matter whether X appears in the \"valid targets\" list (that list is historical context about other entities' own runs, NOT the contents of this request).\n- IMPLEMENTATION is wrong — the developer's own handler/factory code is broken. Examples of the *kind* of problem: the factory for this entity is not registered, the handler references a column or table that does not exist (even though the recipe never mentioned it), the insert/delete logic has a bug, or the server threw an unhandled exception. No change to the test data can fix this; the developer must edit code.\n\n## How to decide\n\nAsk: \"Would sending DIFFERENT, corrected test data — still matching the intended schema — plausibly make this request succeed?\"\n- If yes → **recipe**.\n- If the data shown below looks valid and the error points at the server's own logic, a missing factory, or a column/table the recipe never referenced → **implementation**.\n- If you genuinely cannot tell from the evidence → **unclear**. Prefer \"unclear\" over a confident guess; a wrong confident answer is worse than admitting uncertainty.\n\nCross-check the error against the actual data sent below before deciding. For an \"unknown alias\" error, look at whether a record in the test data declares that alias with an _alias — NOT at the valid-targets list. If the alias the error names is missing from (or spelled differently in) the data we sent, it is recipe-side, even when that alias appears in the valid-targets list.\n\n## Evidence\n\n${phaseLine}\n${statusLine}\n\nEntity: \"${args.entityName}\"\n\nValid _ref targets (aliases declared by already-created parent entities):\n${args.validRefAliases?.trim() || \"(none — this is a root entity with no parents to reference)\"}\n\nWhat the entity audit recorded about how \"${args.entityName}\" is created:\n${args.entityAudit?.trim() || \"(not available)\"}\n\n${args.liveSchema?.trim() || \"(no live schema available — the /discover endpoint was unreachable)\"}\n\nTest data sent:\n${JSON.stringify(args.recipe, null, 2)}\n\nError:\n${errorText}`;\n}\n\n/**\n * Ask the model whether a failure is recipe-side or implementation-side.\n *\n * Best-effort: any failure of the classifier itself resolves to `unclear`, which\n * the caller treats as \"show the user the full menu and let them decide.\" The\n * classifier must never block or crash the failure-handling path.\n */\nexport async function classifyFailure(model: LanguageModel, args: ClassifyArgs): Promise<FailureClassification> {\n try {\n const result = await generateText({\n model,\n prompt: buildClassifierPrompt(args),\n output: Output.object({ schema: classificationSchema }),\n });\n return result.output;\n } catch (err) {\n return { side: \"unclear\", reason: `Could not auto-triage this error (${formatException(err)}).` };\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 { formatException } from \"../../../core/errors\";\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, type RecipePayload } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\nimport {\n fetchDiscoverSchema,\n renderModelSchema,\n validateRecipeAgainstSchema,\n formatValidationProblems,\n type DiscoverSchema,\n} from \"../discover-schema\";\nimport { classifyFailure, type FailurePhase } from \"./failure-classifier\";\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\n/**\n * Summarize the _alias values declared by already-completed entities, so a\n * revise/propose agent knows exactly which aliases it can target with _ref.\n * Without this the agent is blind to other entities and produces broken refs.\n */\nfunction summarizeCompletedAliases(\n completedEntities: Record<string, EntityProgress>,\n excludeName?: string,\n): string {\n return Object.entries(completedEntities)\n .filter(([name, e]) => name !== excludeName && e.recipeData && e.recipeData.length > 0)\n .map(([name, e]) => `${name}: aliases ${e.recipeData!.map((r) => r._alias ?? \"?\").join(\", \")}`)\n .join(\"\\n\");\n}\n\n/** A one-line summary of how the audit says an entity is created, used to ground\n * the failure classifier (e.g. so a \"no factory registered\" error is judgeable). */\nfunction summarizeEntityAudit(model?: AuditedModel): string | undefined {\n if (!model) return undefined;\n const parts = [`independently_created: ${model.independently_created}`];\n if (model.creation_function) parts.push(`creation function: ${model.creation_function}`);\n if (model.created_by.length > 0) parts.push(`created by: ${model.created_by.map((c) => c.owner).join(\", \")}`);\n if (model.side_effects?.length) parts.push(`side effects: ${model.side_effects.join(\", \")}`);\n return parts.join(\"; \");\n}\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 schemaSpec?: string,\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 = summarizeCompletedAliases(completedEntities, entityName);\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${schemaSpec ? `${schemaSpec}\\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\nProduce records for \"${entityName}\" ONLY — one object per record. Do not include records for other models; the tool assembles parent entities automatically.\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 completedEntities: Record<string, EntityProgress>,\n schemaSpec?: 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 const completedAliases = summarizeCompletedAliases(completedEntities, entityName);\n const aliasBlock = completedAliases\n ? `Aliases declared by already-created parent entities (these are the ONLY valid _ref targets):\\n${completedAliases}\\n`\n : `This is a root entity — it has no parent entities to _ref.\\n`;\n\n await runAgent(\n {\n id: `fix-${entityName}`,\n systemPrompt: `You are fixing recipe data based on user feedback (or a validation failure). 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- Return records for \"${entityName}\" ONLY — a flat JSON array, one object per record. NEVER group records by model name or nest other models (Client/User/etc.) inside this array. The tool assembles parent entities into the request automatically; your job is only this one entity's rows.\n- _alias fields must be unique identifiers (e.g., \"card_1\", \"transaction_1\")\n- _ref fields must reference an alias that ALREADY EXISTS on a parent entity — see the list of valid targets below. Never invent a _ref to an alias that isn't listed.\n- If the error says \"references unknown alias(es): X\", a _ref points at \"X\" but nothing being created declares it. Correct that _ref to one of the valid targets listed below (it's usually a typo, e.g. \"users_1\" vs \"user_1\"), or drop the reference if the field is optional. Do NOT leave a _ref pointing at an alias that isn't in the valid targets list.\n- Read scenarios.md to verify you're using correct alias names from parent entities\n- Field names and required fields must match the live schema below when present (it is the source of truth), otherwise 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:\n${JSON.stringify(current, null, 2)}\n\nWhat's wrong / what to change:\n${feedback}\n\n${aliasBlock}\n${schemaSpec ? `${schemaSpec}\\n` : \"\"}\nRead scenarios.md and entity-audit.md to understand the correct aliases and schema. Apply the change 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 completedEntities: Record<string, EntityProgress>,\n schemaSpec?: 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 proposed = await reviseRecipeData(\n entityName, entityIndex, totalEntities, proposed, (feedback as string).trim(),\n model, outputDir, completedEntities, schemaSpec,\n );\n }\n }\n}\n\ntype TestResult = \"success\" | \"skip\" | { feedback: string };\n\nexport function formatErrorContext(errorBody: unknown): string {\n if (errorBody == null) return \"\";\n const rendered = typeof errorBody === \"string\" ? errorBody : JSON.stringify(errorBody);\n return `\\nServer error: ${rendered}`;\n}\n\n/**\n * The most times we'll route a failure into the recipe-fix agent before we stop\n * offering it and hand control back to the user. Autofix regenerates the test\n * data; if that many rounds haven't resolved the failure, the data was never the\n * cause — it's a handler/code issue the agent can't touch.\n */\nexport const MAX_AUTOFIX_ATTEMPTS = 2;\n\n/** Mutable per-entity counter, threaded through a whole test cycle so auto- and\n * manual autofix rounds share one budget. */\nexport interface AutofixBudget {\n attempts: number;\n}\n\nexport interface FailureContext {\n model: LanguageModel;\n /** The payload that was sent — context for the failure classifier. */\n recipe: unknown;\n budget: AutofixBudget;\n /** Aliases declared by already-created parents — the valid _ref targets. */\n validRefAliases?: string;\n /** What the entity audit recorded about how this entity is created. */\n entityAudit?: string;\n /** This entity's live field schema from /discover, rendered for prompts. */\n liveSchema?: string;\n}\n\nfunction seedFeedbackFromError(errorContext: string, reason?: string): { feedback: string } {\n const triage = reason ? ` (Auto-triage: ${reason})` : \"\";\n return { feedback: `The request failed — read the error and fix the recipe data.${triage}${errorContext}` };\n}\n\nexport async function promptOnFailure(\n entityName: string,\n errorBody: unknown,\n ctx: FailureContext,\n phase: FailurePhase,\n httpStatus?: number,\n): Promise<\"retry\" | \"skip\" | { feedback: string }> {\n notify(\"Autonoma\", `${entityName} — failed, action needed`);\n const errorContext = formatErrorContext(errorBody);\n\n // Classify the failure for CONTEXT only. The verdict is informational — we hand\n // it to the fix agent and show it to the user, but it never gates which actions\n // are available. (Letting `side` decide that is exactly what hid the autofix on\n // self-evident recipe errors like \"references unknown alias(es)\".)\n const { reason } = await classifyFailure(ctx.model, {\n entityName,\n phase,\n httpStatus,\n error: errorBody,\n recipe: ctx.recipe,\n validRefAliases: ctx.validRefAliases,\n entityAudit: ctx.entityAudit,\n liveSchema: ctx.liveSchema,\n });\n\n // While there's budget, always hand the raw failure (plus the triage note as\n // context) straight to the agent and let it decide whether and how to fix the\n // recipe. No \"is this recipe-side?\" gate in front of it.\n if (ctx.budget.attempts < MAX_AUTOFIX_ATTEMPTS) {\n ctx.budget.attempts++;\n p.log.info(`Triage: ${reason}`);\n p.log.info(\n `Handing the failure to the agent to fix from the error (attempt ${ctx.budget.attempts}/${MAX_AUTOFIX_ATTEMPTS})...`,\n );\n return seedFeedbackFromError(errorContext, reason);\n }\n\n // Budget spent — the agent's fixes didn't resolve it, so it's most likely your\n // handler code. Hand control back, with every option available (nothing hidden).\n p.log.warn(`The agent tried ${MAX_AUTOFIX_ATTEMPTS}× without resolving it. Latest triage: ${reason}`);\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 {\n value: \"autofix\",\n label: \"Let the agent try again from the error\",\n hint: \"Hand the raw error back to the agent, no typing\",\n },\n { value: \"feedback\", label: \"Let me explain what's wrong\", hint: \"Describe the change and the agent will apply it\" },\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 if (action === \"autofix\") {\n ctx.budget.attempts++;\n return seedFeedbackFromError(errorContext, reason);\n }\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 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: RecipePayload,\n grounding: Omit<FailureContext, \"recipe\">,\n discoverSchema?: DiscoverSchema,\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 const failureCtx: FailureContext = { ...grounding, recipe };\n\n // UP with retry loop\n while (true) {\n // Pre-flight: catch schema violations locally, before bothering the server,\n // so a missing required field surfaces as a precise diagnostic instead of an\n // opaque HTTP 500. Only validates models the live schema actually knows.\n if (discoverSchema) {\n const problems = validateRecipeAgainstSchema(recipe, discoverSchema);\n if (problems.length > 0) {\n const errorBody = `Recipe failed local schema validation against /discover (not sent to the server):\\n${formatValidationProblems(problems)}`;\n p.log.error(errorBody);\n const action = await promptOnFailure(entityName, errorBody, failureCtx, \"create\");\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n }\n\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:\\n${formatException(err)}`);\n const action = await promptOnFailure(entityName, formatException(err), failureCtx, \"create\");\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, failureCtx, \"create\", upResult.status);\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:\\n${formatException(err)}`);\n const action = await promptOnFailure(entityName, formatException(err), failureCtx, \"teardown\");\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, failureCtx, \"teardown\", downResult.status);\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 // Best-effort live schema from the SDK's /discover endpoint. It is the source\n // of truth for each factory's required fields and types, so we use it to\n // ground recipe generation instead of guessing from the markdown audit.\n // Refetched per use rather than cached: discover only reflects the factories\n // registered SO FAR, and that set grows as the developer wires up entities.\n async function loadLiveSchema(name: string): Promise<{ schema: DiscoverSchema | null; spec?: string }> {\n if (!state.sdkEndpointUrl || !state.sharedSecret) return { schema: null };\n const schema = await fetchDiscoverSchema({\n endpointUrl: state.sdkEndpointUrl,\n sharedSecret: state.sharedSecret,\n });\n if (!schema) return { schema: null };\n return { schema, spec: renderModelSchema(schema, name) ?? undefined };\n }\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 // Live schema for grounding propose/review (null until the endpoint is\n // configured — i.e. from the second entity onward, or a resumed run).\n const { spec: recipeSchemaSpec } = await loadLiveSchema(entityName);\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, recipeSchemaSpec,\n );\n }\n\n // B. User review\n if (!nonInteractive) {\n recipeData = await reviewRecipeData(entityName, i, total, recipeData, model, outputDir, state.entities, recipeSchemaSpec);\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 const DOCS_BASE = \"https://docs.agent.autonoma.app\";\n\n p.log.info(\n `Next: implement the ${entityName} factory. The block below is a copy-paste guide —\\n` +\n ` paste it into Claude Code (or your AI assistant) and it will write the factory in your codebase.\\n` +\n ` A factory teaches the Autonoma SDK how to create and tear down ${entityName} records using your app's own code.\\n` +\n ` Keep it local for now: implement it, run your app on localhost, and we'll test it live here. You deploy later.`,\n );\n\n p.note(instructions, `Implementation guide for ${entityName} (paste into your AI assistant)`, { format: codeNoteFormat });\n\n p.log.info(`Autonoma SDK docs: ${DOCS_BASE}/sdk/environment-factory`);\n\n if (i === 0) {\n p.log.info(\"This is your first factory — the guide includes one-time SDK setup. Later entities 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 app running locally with the ${entityName} factory wired up?`,\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 // Now that the endpoint is configured, pull the live schema once for the\n // whole test cycle: it grounds the classifier, pre-flight validation, and\n // any recipe fixes the agent makes from a failure.\n const { schema: discoverSchema, spec: liveSchemaSpec } = await loadLiveSchema(entityName);\n\n // One autofix budget per entity test cycle — auto- and manual autofix\n // rounds share it, so a wrongly \"recipe\"-classified failure can't loop forever.\n const autofixBudget: AutofixBudget = { attempts: 0 };\n // Grounding for the failure classifier: which _ref targets are valid, what\n // the audit knows about how this entity is created, and the live schema.\n const grounding: Omit<FailureContext, \"recipe\"> = {\n model,\n budget: autofixBudget,\n validRefAliases: summarizeCompletedAliases(state.entities, entityName),\n entityAudit: summarizeEntityAudit(models.find((m) => m.name === entityName)),\n liveSchema: liveSchemaSpec,\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, grounding, discoverSchema ?? undefined);\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, state.entities, liveSchemaSpec,\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 { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { LanguageModel } from \"ai\";\nimport { notify } from \"../../../core/notify\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { formatException } from \"../../../core/errors\";\nimport { buildReadFileTool } from \"../../../tools\";\nimport { codeNoteFormat } from \"../../../core/highlight\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { saveRecipeState } from \"../state\";\nimport type { AuditedModel } from \"../entity-order\";\nimport { buildFullRecipe, type RecipePayload } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\nimport {\n fetchDiscoverSchema,\n renderModelSchema,\n validateRecipeAgainstSchema,\n formatValidationProblems,\n} from \"../discover-schema\";\n\n/**\n * Revise the entire recipe based on user feedback after they reviewed the app.\n * Unlike the per-entity revise, this agent sees the whole recipe so it can fix\n * issues that span entities (e.g. cross-references between records).\n */\nasync function reviseFullRecipe(\n current: RecipePayload,\n feedback: string,\n model: LanguageModel,\n outputDir: string,\n entityOrder: string[],\n schemaSpec?: string,\n): Promise<RecipePayload | undefined> {\n let revised: RecipePayload | undefined;\n\n const finishTool = tool({\n description: \"Submit the revised full recipe: an object mapping each entity name to its array of records.\",\n inputSchema: z.object({\n recipe: z.record(z.string(), z.array(z.record(z.string(), z.unknown()))),\n }),\n execute: async (input) => {\n revised = input.recipe;\n return { done: true };\n },\n });\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"revise:full-recipe\", 20);\n\n await runAgent(\n {\n id: \"revise-full-recipe\",\n systemPrompt: `You are revising a full test-data recipe based on user feedback after they reviewed the app populated with this data.\n\nThe recipe is an object mapping entity names to arrays of records. Records use:\n- _alias: a unique id for a record so other records can point to it\n- _ref: { \"_ref\": \"alias\" } points to a parent record's _alias\n\nRules:\n- Apply the user's feedback across whatever entities it touches.\n- Keep _ref values pointing to aliases that actually exist in the recipe. Never invent a _ref to a missing alias.\n- Entities are created in this order (parents first): ${entityOrder.join(\" → \")}. A record may only _ref an alias declared by an entity earlier in that order.\n- Field names, types, and required fields must match the live schema below when present (it is the source of truth), otherwise the schema in entity-audit.md.\n- Read scenarios.md and entity-audit.md from the output directory as needed.\n${schemaSpec ? `\\n${schemaSpec}\\n` : \"\"}\nReturn the COMPLETE revised recipe (all entities, not just the changed ones) via finish.`,\n model,\n maxSteps: 20,\n tools: (_heartbeat: () => void) => ({\n read_output: buildReadFileTool(outputDir),\n finish: finishTool,\n }),\n onStepFinish,\n },\n `The user reviewed the app with this test data and said it doesn't look right.\n\nCurrent full recipe:\n${JSON.stringify(current, null, 2)}\n\nUser feedback:\n\"${feedback}\"\n\nRevise the recipe to address the feedback, then call finish with the complete updated recipe.`,\n () => revised,\n );\n logger.summary();\n\n return revised;\n}\n\nasync function teardown(sdkConfig: SdkClientConfig, refsToken: string | undefined, successMessage: string): Promise<boolean> {\n if (!refsToken) return true;\n\n p.log.step(\"[Full validation] Tearing down all entities...\");\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:\\n${formatException(err)}`);\n return false;\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 p.log.success(successMessage);\n return true;\n}\n\nexport async function runFullValidation(\n state: RecipeBuilderState,\n _models: AuditedModel[],\n outputDir: string,\n model: LanguageModel,\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 // By this phase every factory is registered, so /discover returns the full\n // schema. Use it to ground revisions and to flag schema violations up front.\n const discoverSchema = await fetchDiscoverSchema(sdkConfig);\n const fullSchemaSpec = discoverSchema\n ? state.entityOrder.map((name) => renderModelSchema(discoverSchema, name)).filter(Boolean).join(\"\\n\\n\") || undefined\n : undefined;\n\n let fullRecipe = buildFullRecipe(state.entityOrder, state.entities);\n\n // UP → review → (teardown) → approve or revise-and-retry loop\n while (true) {\n if (discoverSchema) {\n const problems = validateRecipeAgainstSchema(fullRecipe, discoverSchema);\n if (problems.length > 0) {\n p.log.warn(\n `Heads up — the recipe has likely schema problems (from /discover); the full UP may fail:\\n${formatValidationProblems(problems)}`,\n );\n }\n }\n\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:\\n${formatException(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 if (p.isCancel(looksGood)) throw new Error(\"Cancelled\");\n\n // Always tear down the data we just created before deciding the next step.\n const torndown = await teardown(\n sdkConfig,\n refsToken,\n looksGood\n ? \"Full lifecycle works. All data was created and torn down cleanly.\"\n : \"Tore down the test data so we can regenerate it.\",\n );\n if (!torndown) return false;\n\n if (looksGood) return true;\n\n // Not right: collect feedback, revise the FULL recipe, and retry.\n const feedback = await p.text({\n message: \"What's wrong with the test data? Describe what to change.\",\n placeholder: \"e.g. accounts need realistic balances, transactions should reference the right account...\",\n });\n if (p.isCancel(feedback) || !(feedback as string).trim()) {\n p.log.info(\"No feedback given. You can edit recipe.json manually and re-run with --resume.\");\n return false;\n }\n\n p.log.info(\"Revising the full recipe based on your feedback...\");\n const revised = await reviseFullRecipe(fullRecipe, (feedback as string).trim(), model, outputDir, state.entityOrder, fullSchemaSpec);\n if (!revised) {\n p.log.warn(\"Couldn't revise automatically. Edit recipe.json manually and re-run with --resume.\");\n return false;\n }\n\n // Persist the revised records back into state, then rebuild and retry.\n for (const [name, records] of Object.entries(revised)) {\n if (state.entities[name]) {\n state.entities[name]!.recipeData = records;\n }\n }\n await saveRecipeState(outputDir, state);\n fullRecipe = buildFullRecipe(state.entityOrder, state.entities);\n\n p.note(JSON.stringify(fullRecipe, null, 2), \"Revised recipe — re-running full validation\", { format: codeNoteFormat });\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 { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport * 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 { rankEntitiesByImportance } from \"./entity-relevance\";\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 /** User guidance from a pipeline-level retry. The recipe builder has its own\n * per-entity recovery prompts, so this is accepted but currently unused. */\n retryGuidance?: string;\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 // Prefer the shared secret provided by onboarding (the application's secret\n // from the dashboard) so the deployment, dashboard, and CLI all sign with the\n // same key. The entity loop only generates a fresh one when none was provided.\n if (state.sharedSecret == null && input.config.sharedSecret != null) {\n state.sharedSecret = input.config.sharedSecret;\n await saveRecipeState(input.outputDir, state);\n }\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 let importanceRank: Map<string, number> | undefined;\n try {\n const auditMarkdown = await readFile(join(input.outputDir, \"entity-audit.md\"), \"utf-8\");\n importanceRank = await rankEntitiesByImportance(models, auditMarkdown, model);\n } catch {\n // Ranking is a UX nicety; on any failure fall back to alphabetical order.\n importanceRank = undefined;\n }\n\n const entityOrder = resolveEntityOrder(models, importanceRank);\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 core entities first, 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, model);\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, formatRetryGuidance, runAgent} from \"../../core/agent\";\nimport {formatException} from \"../../core/errors\";\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 retryGuidance?: 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 : \"\") + formatRetryGuidance(input.retryGuidance);\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 console.log(` [chunk] Agent error (will retry next chunk):\\n${formatException(err)}`);\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 console.error(`Journey generator error:\\n${formatException(err)}`);\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 { setGlobalEnv, getGlobalEnvPath } from \"./core/global-env\";\nimport { installInterruptHandler, restoreTerminal } from \"./core/interrupt\";\nimport { track, trackError, flushAnalytics } from \"./core/analytics\";\nimport { formatException, describeKnownError, supportReference, isUserCancellation } from \"./core/errors\";\n\n// tsup emits source maps; ask Node to apply them so any stack that does reach\n// our own code points at src/* instead of the bundled dist/index.js.\nprocess.setSourceMapsEnabled(true);\nimport { notify } from \"./core/notify\";\nimport { uploadArtifacts } from \"./core/upload\";\nimport { loadGitInfo, readGitInfo, saveGitInfo } from \"./core/git\";\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: \"Find your pages\",\n kb: \"Build a knowledge base\",\n entityAudit: \"Map your data models\",\n scenarioRecipe: \"Design test scenarios\",\n recipeBuilder: \"Set up test data\",\n testGenerator: \"Generate the tests\",\n};\n\n// One-line plain-language summary per step, used in the upfront overview and the\n// \"continue?\" prompts so it's always clear what's coming before it runs.\nconst STEP_SUMMARIES: Record<StepName, string> = {\n pagesFinder: \"Map every page and route in your app.\",\n kb: \"Learn your app's features, flows, and UI patterns.\",\n entityAudit: \"Find what your app stores (users, orgs, ...) and how each one is created.\",\n scenarioRecipe: \"Decide the realistic data each test will run against.\",\n recipeBuilder: \"Wire up small helpers that create and clean up that data in your database.\",\n testGenerator: \"Write the end-to-end tests, covering every page and feature.\",\n};\n\nconst STEP_INTROS: Record<StepName, string> = {\n pagesFinder:\n \"Scanning your codebase to find every page and route, so we know the full surface area that needs test coverage.\",\n kb: \"Reading those pages to learn your app's features, flows, and UI patterns - the context everything after this builds on.\",\n entityAudit:\n \"Finding the things your app stores (users, organizations, orders, ...) and how each one gets created, so we can generate realistic test data for them.\",\n scenarioRecipe:\n \"Designing the data each test will run against - concrete, realistic values that match how your app actually uses them.\",\n recipeBuilder:\n \"Helping you wire up small helpers that create and clean up test data in your own database. We give you a copy-paste guide for each one and test it live against your app running locally - you deploy later, once everything passes.\",\n testGenerator:\n \"Writing the actual end-to-end tests, covering every page and feature with depth 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 retryGuidance?: string,\n): Promise<PipelineState> {\n const label = STEP_LABELS[step];\n p.note(STEP_INTROS[step], `Step: ${label}`);\n\n const stepStartedAt = Date.now();\n track(\"cli_step_started\", { step });\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 retryGuidance,\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 retryGuidance,\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 retryGuidance,\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 retryGuidance,\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 retryGuidance,\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 trackError(new Error(result.summary), { step, source: \"step_result\" });\n }\n } else {\n state = await markStep(outputDir, state, step, \"done\");\n p.log.success(`Completed: ${label}`);\n }\n } catch (err) {\n // The user deliberately stopped (Ctrl+C / \"cancel\" at a prompt). That's not\n // a failure: let the run-level handler save progress and exit quietly, and\n // don't report it to error tracking, where it would look like a bug.\n if (isUserCancellation(err)) throw err;\n state = await markStep(outputDir, state, step, \"failed\");\n const known = describeKnownError(err);\n if (known) {\n // A recognized, actionable failure — the raw stack is library-internal\n // noise here, so we show the fix instead.\n p.log.error(`Failed: ${label} — ${known.title}`);\n p.log.info(known.hint);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n p.log.error(`Failed: ${label} — ${message}`);\n // Full stack so users can copy-paste it when reporting the issue.\n console.error(`\\x1b[2m${formatException(err)}\\x1b[0m`);\n // One short line that maps this failure to its analytics event(s).\n console.error(`\\x1b[2m${supportReference({ step })}\\x1b[0m`);\n p.log.info(\"If you report this, please include the error output above.\");\n }\n trackError(err, { step, source: \"step_exception\" });\n }\n\n track(\"cli_step_completed\", {\n step,\n status: state.steps[step],\n duration_ms: Date.now() - stepStartedAt,\n });\n\n return state;\n}\n\ntype FailureAction = { kind: \"retry\"; guidance?: string } | { kind: \"exit\" };\n\nasync function promptStepFailure(label: string): Promise<FailureAction> {\n notify(\"Autonoma\", `${label} failed — action needed`);\n\n const action = await p.select({\n message: \"This step failed. What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Retry this step\", hint: \"Run it again from the top\" },\n { value: \"guidance\", label: \"Retry with guidance\", hint: \"Tell the agent what went wrong or what to focus on\" },\n { value: \"exit\", label: \"Stop here (progress saved)\", hint: \"Resume later with --resume\" },\n ],\n });\n\n if (p.isCancel(action) || action === \"exit\") return { kind: \"exit\" };\n if (action === \"retry\") return { kind: \"retry\" };\n\n const guidance = await p.text({\n message: \"What should the agent do differently?\",\n placeholder: \"e.g. the part that failed, or what to focus on\",\n });\n if (p.isCancel(guidance)) return { kind: \"exit\" };\n\n const trimmed = (guidance as string).trim();\n return { kind: \"retry\", guidance: trimmed || undefined };\n}\n\n// A failed step should never hard-stop an interactive run — the user gets to\n// retry (optionally steering the agent) until it passes or they bail out.\nasync function runStepWithRecovery(\n step: StepName,\n outputDir: string,\n state: PipelineState,\n config: ReturnType<typeof loadConfig>,\n projectContext?: ProjectContext,\n nonInteractive?: boolean,\n): Promise<PipelineState> {\n let guidance: string | undefined;\n\n while (true) {\n state = await runStep(step, outputDir, state, config, projectContext, nonInteractive, guidance);\n\n if (state.steps[step] !== \"failed\" || nonInteractive) return state;\n\n const action = await promptStepFailure(STEP_LABELS[step]);\n if (action.kind === \"exit\") return state;\n\n guidance = action.guidance;\n track(\"cli_step_retried\", { step, with_guidance: guidance != null });\n }\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\n/**\n * Make sure an OpenRouter API key is available before we ask anything else.\n * If it's already in the environment (shell, project .env, or global\n * ~/.autonoma/.env) we use it silently. Otherwise we prompt for it as the very\n * first input and persist it to the global env so it's reused on future runs.\n * Returns false if the user cancels.\n */\nasync function ensureOpenRouterKey(nonInteractive?: boolean): Promise<boolean> {\n if (process.env.OPENROUTER_API_KEY) return true;\n\n if (nonInteractive) {\n p.log.error(\n \"OPENROUTER_API_KEY is not set. Set it in your environment or run interactively once to save it.\",\n );\n return false;\n }\n\n p.log.info(\"You'll need an OpenRouter API key to run the planner. Get one at https://openrouter.ai/keys\");\n\n const key = await p.password({\n message: \"Paste your OpenRouter API key\",\n validate: (value) => ((value ?? \"\").trim().length === 0 ? \"API key cannot be empty\" : undefined),\n });\n\n if (p.isCancel(key)) return false;\n\n setGlobalEnv(\"OPENROUTER_API_KEY\", key.trim());\n p.log.success(`Saved your API key to ${getGlobalEnvPath()} — you won't be asked again.`);\n return true;\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 // ESC no longer exits; Ctrl+C twice (within 3s) does, with a resume hint.\n const resumeCommand =\n `autonoma-planner --resume` + (args.project ? ` --project ${args.project}` : \"\");\n installInterruptHandler({\n onExit: () => {\n track(\"cli_run_exited\");\n restoreTerminal();\n console.log(\"\");\n p.log.warn(`Your progress is saved. To resume, run:\\n ${resumeCommand}`);\n void flushAnalytics().finally(() => process.exit(0));\n },\n });\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 nonInteractive = !!args[\"non-interactive\"];\n if (!(await ensureOpenRouterKey(nonInteractive))) {\n p.log.warn(\"Cancelled.\");\n return;\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\n track(\"cli_run_started\", { model: modelName, non_interactive: nonInteractive });\n\n const outputDir = await ensureOutputDir(config.projectSlug);\n let state = await loadState(outputDir);\n\n // Record the commit the analysis is based on, once, on the first run - so a\n // --resume keeps the original commit and the upload can report it to Autonoma.\n if ((await loadGitInfo(outputDir)) == null) {\n const gitInfo = await readGitInfo(config.projectRoot);\n if (gitInfo != null) {\n await saveGitInfo(outputDir, gitInfo);\n p.log.info(`Git commit: ${gitInfo.sha.slice(0, 8)}${gitInfo.dirty ? \" (working tree dirty)\" : \"\"}`);\n }\n }\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.note(\n `${outputDir}\\n\\n` +\n `All generated files (knowledge base, scenarios, recipe, tests) live here.\\n` +\n `It's a hidden folder in your home directory — in Finder/Explorer use \"Go to folder\"\\n` +\n `or reveal hidden files (macOS: Cmd+Shift+. ) to see it.`,\n \"Output folder\",\n );\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 runStepWithRecovery(targetStep, outputDir, state, config, projectContext, nonInteractive);\n if (state.steps[targetStep] === \"failed\") {\n const retryCommand =\n `autonoma-planner --step ${targetStep}` + (args.project ? ` --project ${args.project}` : \"\");\n p.log.warn(`Your progress is saved. To retry this step, run:\\n ${retryCommand}`);\n process.exitCode = 1;\n }\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 // Up-front overview so it's clear what each step does before any of them run.\n p.note(\n steps.map((s, idx) => `${idx + 1}. ${STEP_LABELS[s]} - ${STEP_SUMMARIES[s]}`).join(\"\\n\"),\n \"Here's the plan\",\n );\n\n try {\n for (let i = startIdx; i < steps.length; i++) {\n const step = steps[i]!;\n state = await runStepWithRecovery(step, outputDir, state, config, projectContext, nonInteractive);\n\n if (state.steps[step] === \"paused\") {\n break;\n }\n\n // Only reached when the user chose to stop after a failure, or in\n // non-interactive mode where there's nobody to ask.\n if (state.steps[step] === \"failed\") {\n p.log.error(\"Pipeline stopped due to failure.\");\n p.log.warn(`Your progress is saved. To retry this step, run:\\n ${resumeCommand}`);\n process.exitCode = 1;\n break;\n }\n\n // Pages Finder runs silently and continues on its own — there's nothing\n // actionable to confirm at that point, so we skip the prompt after it.\n const skipConfirmAfter: StepName[] = [\"pagesFinder\"];\n\n if (i < steps.length - 1 && !nonInteractive && !skipConfirmAfter.includes(step)) {\n const nextStep = steps[i + 1]!;\n const shouldContinue = await p.confirm({\n message: `Next: ${STEP_LABELS[nextStep]} - ${STEP_SUMMARIES[nextStep]}\\nContinue?`,\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 (isUserCancellation(err)) {\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 const stepsDone = Object.values(state.steps).filter((s) => s === \"done\").length;\n track(\"cli_run_completed\", { steps_done: stepsDone });\n\n // Only upload once the whole pipeline finished — a paused/failed run has\n // incomplete artifacts and would publish a half-built test suite.\n const allStepsDone = Object.values(state.steps).every((s) => s === \"done\");\n if (allStepsDone) {\n try {\n await uploadArtifacts(config, outputDir);\n track(\"cli_artifacts_uploaded\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n p.log.error(`Failed to upload artifacts: ${message}`);\n console.error(`\\x1b[2m${formatException(err)}\\x1b[0m`);\n console.error(`\\x1b[2m${supportReference({ phase: \"artifact_upload\" })}\\x1b[0m`);\n p.log.info(`Your artifacts are saved in ${outputDir}. Re-run the CLI to retry the upload.`);\n track(\"cli_artifacts_upload_failed\", { message });\n trackError(err, { source: \"artifact_upload\" });\n }\n }\n\n p.outro(\"Done\");\n}\n\nmain()\n .then(() => flushAnalytics())\n .catch(async (err) => {\n // A cancellation that bubbled all the way up — exit quietly without a stack\n // or an error-tracking event; the user chose to stop.\n if (isUserCancellation(err)) {\n await flushAnalytics();\n process.exit(0);\n }\n const known = describeKnownError(err);\n if (known) {\n console.error(`\\x1b[31m${known.title}\\x1b[0m`);\n console.error(known.hint);\n } else {\n console.error(err);\n console.error(`\\x1b[2m${supportReference()}\\x1b[0m`);\n }\n trackError(err, { source: \"uncaught\" }, false);\n await flushAnalytics();\n process.exit(1);\n });\n","import { resolve, join } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport { loadGlobalEnv } from \"./core/global-env\";\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 // Precedence: real shell env > project .env > global ~/.autonoma/.env.\n // Each loader only sets a key if it isn't already present, so loading the\n // project env first lets it win over the global fallback.\n loadProjectEnv(projectRoot);\n loadGlobalEnv();\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 // Endpoint the CLI talks to. Defaults to production; override with\n // AUTONOMA_API_URL to point at an alpha/preview host (alpha-<sha>.autonoma.app, ...).\n autonomaApiUrl: process.env.AUTONOMA_API_URL ?? \"https://agent.autonoma.app\",\n autonomaApiToken: process.env.AUTONOMA_API_TOKEN,\n autonomaGenerationId: process.env.AUTONOMA_GENERATION_ID,\n };\n}\n","import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\nconst GLOBAL_ENV_PATH = join(AUTONOMA_HOME, \".env\");\n\nexport function getGlobalEnvPath(): string {\n return GLOBAL_ENV_PATH;\n}\n\nfunction parseEnvContent(content: string): Record<string, string> {\n const out: Record<string, string> = {};\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 (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[key] = value;\n }\n return out;\n}\n\n/**\n * Load `~/.autonoma/.env` into process.env as a fallback. Existing process.env\n * values (real shell env, project .env loaded earlier) always win.\n */\nexport function loadGlobalEnv(): void {\n let content: string;\n try {\n content = readFileSync(GLOBAL_ENV_PATH, \"utf-8\");\n } catch {\n return;\n }\n for (const [key, value] of Object.entries(parseEnvContent(content))) {\n if (!(key in process.env)) {\n process.env[key] = value;\n }\n }\n}\n\n/**\n * Upsert a key in `~/.autonoma/.env` and reflect it in process.env immediately.\n * Preserves other lines/comments in the file.\n */\nexport function setGlobalEnv(key: string, value: string): void {\n mkdirSync(AUTONOMA_HOME, { recursive: true });\n\n let lines: string[] = [];\n try {\n lines = readFileSync(GLOBAL_ENV_PATH, \"utf-8\").split(\"\\n\");\n } catch {\n lines = [];\n }\n\n const serialized = `${key}=${value}`;\n let replaced = false;\n lines = lines.map((line) => {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\") || !trimmed.includes(\"=\")) return line;\n const lineKey = trimmed.slice(0, trimmed.indexOf(\"=\")).trim();\n if (lineKey === key) {\n replaced = true;\n return serialized;\n }\n return line;\n });\n\n if (!replaced) {\n if (lines.length > 0 && lines[lines.length - 1]!.trim() === \"\") {\n lines.splice(lines.length - 1, 0, serialized);\n } else {\n lines.push(serialized);\n }\n }\n\n const output = lines.join(\"\\n\").replace(/\\n*$/, \"\\n\");\n writeFileSync(GLOBAL_ENV_PATH, output, { encoding: \"utf-8\", mode: 0o600 });\n\n process.env[key] = value;\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 readline from \"node:readline\";\nimport { settings } from \"@clack/core\";\n\nconst DIM = \"\\x1b[2m\";\nconst RESET = \"\\x1b[0m\";\nconst SHOW_CURSOR = \"\\x1b[?25h\";\n\nconst EXIT_HINT = `${DIM}(press Ctrl+C again to exit)${RESET}`;\nconst ARM_WINDOW_MS = 3000;\n// If the graceful exit (analytics flush -> process.exit) hasn't terminated the\n// process within this window, bail unconditionally. onExit defers the real\n// process.exit behind an async flush; if that chain ever fails to resolve, this\n// is what guarantees the CLI still closes on a plain double-tap.\nconst FORCE_EXIT_MS = 2500;\n\nlet installed = false;\nlet armed = false;\nlet armTimer: ReturnType<typeof setTimeout> | null = null;\nlet onExit: (() => void) | null = null;\nlet quitting = false;\n\nfunction disarm(): void {\n if (armTimer) clearTimeout(armTimer);\n armTimer = null;\n armed = false;\n}\n\n/** Last-resort synchronous exit. Never waits on a promise or the event loop. */\nfunction forceExit(): void {\n restoreTerminal();\n // 130 = 128 + SIGINT, the conventional code for \"terminated by Ctrl+C\".\n process.exit(130);\n}\n\nfunction handleInterrupt(): void {\n // A graceful exit is already underway. Don't just swallow the signal — if the\n // async flush in onExit stalled, the user is now stuck with no way out. Treat\n // any further press as \"get me out NOW\" and exit synchronously, bypassing the\n // flush entirely.\n if (quitting) {\n forceExit();\n return;\n }\n\n if (armed) {\n quitting = true;\n disarm();\n // Failsafe: onExit hands off the real exit to an async analytics flush. If\n // that never lands process.exit, force it. unref so the timer itself can't\n // keep the process alive past a clean exit.\n setTimeout(forceExit, FORCE_EXIT_MS).unref?.();\n onExit?.();\n return;\n }\n // First press: arm a short window and tell the user how to actually exit.\n // Claude Code-style: a second Ctrl+C within the window quits; otherwise it\n // disarms and the run continues untouched.\n armed = true;\n process.stderr.write(`\\n${EXIT_HINT}\\n`);\n armTimer = setTimeout(disarm, ARM_WINDOW_MS);\n}\n\n/**\n * Install Ctrl+C double-press handling and neuter ESC-as-exit.\n *\n * - ESC no longer cancels prompts (the alias is removed).\n * - Ctrl+C requires two presses within a 3s window to quit. The first press\n * shows a hint; if no second press lands, the run continues.\n *\n * Works both while a clack prompt owns stdin (via a SIGINT listener injected\n * onto each readline interface) and between prompts (via process SIGINT).\n */\nexport function installInterruptHandler(opts: { onExit: () => void }): void {\n onExit = opts.onExit;\n if (installed) return;\n installed = true;\n\n // ESC should do nothing. clack maps \"escape\" -> \"cancel\" by default and\n // updateSettings can't remove an existing alias, so delete it on the live map.\n settings.aliases.delete(\"escape\");\n\n // Between prompts (raw mode off), Ctrl+C arrives as a normal process signal.\n process.on(\"SIGINT\", handleInterrupt);\n\n // During a clack prompt, readline owns stdin in raw mode. Node's readline\n // closes the interface on Ctrl+C ONLY when it has no \"SIGINT\" listener; if a\n // listener exists it emits \"SIGINT\" and leaves the prompt running. So inject\n // one onto every interface clack creates.\n const original = readline.createInterface.bind(readline);\n readline.createInterface = ((...args: Parameters<typeof readline.createInterface>) => {\n const iface = original(...args);\n iface.on(\"SIGINT\", handleInterrupt);\n return iface;\n }) as typeof readline.createInterface;\n}\n\n/** Best-effort terminal restore before an abrupt exit. */\nexport function restoreTerminal(): void {\n try {\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n } catch {}\n process.stdout.write(SHOW_CURSOR);\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename, join, relative } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { glob } from \"glob\";\nimport type { AppConfig } from \"../config\";\nimport { loadGitInfo } from \"./git\";\n\ninterface UploadFile {\n name: string;\n content: string;\n folder?: string;\n}\n\n// Mirrors the artifacts the web UI used to accept when the user uploaded the\n// `~/.autonoma/<app>/` folder by hand. `recipe.json` is intentionally excluded:\n// it is submitted through the versioned scenario-recipe endpoint during the\n// recipe-builder step (see agents/04-recipe-builder/phases/submit.ts), and the\n// generic artifacts endpoint rejects it.\nconst ARTIFACT_FILES = [\"AUTONOMA.md\", \"scenarios.md\", \"entity-audit.md\"];\n\nasync function readArtifacts(outputDir: string): Promise<UploadFile[]> {\n const files: UploadFile[] = [];\n for (const name of ARTIFACT_FILES) {\n try {\n const content = await readFile(join(outputDir, name), \"utf-8\");\n files.push({ name, content });\n } catch {\n // Not every run produces every artifact (e.g. no entity audit); skip\n // the ones that aren't on disk.\n }\n }\n return files;\n}\n\nasync function readTestCases(outputDir: string): Promise<UploadFile[]> {\n const testsDir = join(outputDir, \"qa-tests\");\n const matches = await glob(\"**/*.md\", { cwd: testsDir, nodir: true });\n\n const files: UploadFile[] = [];\n for (const match of matches) {\n const name = basename(match);\n if (name === \"INDEX.md\") continue;\n\n const content = await readFile(join(testsDir, match), \"utf-8\");\n const folderPath = relative(\".\", match).split(\"/\").slice(0, -1).join(\"/\");\n files.push({ name, content, folder: folderPath.length > 0 ? folderPath : undefined });\n }\n return files;\n}\n\nasync function postJson(url: string, token: string, body: unknown): Promise<void> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Upload failed (HTTP ${res.status}): ${text}`);\n }\n}\n\nasync function patchJson(url: string, token: string, body: unknown): Promise<void> {\n const res = await fetch(url, {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Failed to mark setup complete (HTTP ${res.status}): ${text}`);\n }\n}\n\n/**\n * Uploads the generated artifacts (test cases + knowledge base + scenarios) to\n * the Autonoma backend at the end of a run, then marks the setup complete so\n * the onboarding UI auto-advances. The recipe is submitted separately during\n * the recipe-builder step.\n *\n * No-ops when the upload credentials are not configured, so the CLI still runs\n * standalone (outside onboarding) and just leaves the artifacts on disk.\n */\nexport async function uploadArtifacts(config: AppConfig, outputDir: string): Promise<void> {\n const { autonomaApiUrl, autonomaApiToken, autonomaGenerationId } = config;\n\n if (autonomaApiUrl == null || autonomaApiToken == null || autonomaGenerationId == null) {\n p.log.info(\n \"Autonoma upload credentials not configured — artifacts saved locally only. \" +\n `They live in ${outputDir}.`,\n );\n return;\n }\n\n const baseUrl = autonomaApiUrl.replace(/\\/+$/, \"\");\n const setupUrl = `${baseUrl}/v1/setup/setups/${autonomaGenerationId}`;\n\n p.log.step(\"Uploading artifacts to Autonoma...\");\n\n const [testCases, artifacts, gitInfo] = await Promise.all([\n readTestCases(outputDir),\n readArtifacts(outputDir),\n loadGitInfo(outputDir),\n ]);\n\n // commitSha lets the backend stamp the resulting snapshot (head_sha) and the\n // branch (last_handled_sha) with the commit the suite was generated from.\n await postJson(`${setupUrl}/artifacts`, autonomaApiToken, { testCases, artifacts, commitSha: gitInfo?.sha });\n await patchJson(setupUrl, autonomaApiToken, { status: \"completed\" });\n\n p.log.success(\n `Uploaded ${testCases.length} test case${testCases.length === 1 ? \"\" : \"s\"} and ` +\n `${artifacts.length} artifact${artifacts.length === 1 ? \"\" : \"s\"}. ` +\n \"Return to your browser to continue onboarding.\",\n );\n}\n","import { execFile } from \"node:child_process\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nconst GIT_INFO_FILE = \".git-info.json\";\n\nexport interface GitInfo {\n /** Full HEAD commit SHA at the time analysis started. */\n sha: string;\n /** Current branch name, or \"HEAD\" when detached. */\n branch?: string;\n /** True when the working tree had uncommitted changes (so the SHA doesn't fully represent the analyzed state). */\n dirty: boolean;\n}\n\nasync function git(projectRoot: string, args: string[]): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", args, { cwd: projectRoot });\n return stdout.trim();\n } catch {\n // Not a git repo, git not installed, or detached/empty - treat as \"no git\".\n return undefined;\n }\n}\n\n/**\n * Reads the current commit, branch, and dirty state of the project's git repo.\n * Returns undefined when the project is not a git repository (or git is\n * unavailable) - the caller should just skip recording commit info in that case.\n */\nexport async function readGitInfo(projectRoot: string): Promise<GitInfo | undefined> {\n const sha = await git(projectRoot, [\"rev-parse\", \"HEAD\"]);\n if (sha == null || sha.length === 0) return undefined;\n\n const branch = await git(projectRoot, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n const status = await git(projectRoot, [\"status\", \"--porcelain\"]);\n\n return {\n sha,\n branch: branch != null && branch.length > 0 ? branch : undefined,\n dirty: status != null && status.length > 0,\n };\n}\n\nexport async function saveGitInfo(outputDir: string, info: GitInfo): Promise<void> {\n await writeFile(join(outputDir, GIT_INFO_FILE), JSON.stringify(info, null, 2), \"utf-8\");\n}\n\nexport async function loadGitInfo(outputDir: string): Promise<GitInfo | undefined> {\n try {\n const raw = await readFile(join(outputDir, GIT_INFO_FILE), \"utf-8\");\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed === \"object\" && parsed != null && \"sha\" in parsed && typeof parsed.sha === \"string\") {\n const branch = \"branch\" in parsed && typeof parsed.branch === \"string\" ? parsed.branch : undefined;\n const dirty = \"dirty\" in parsed && typeof parsed.dirty === \"boolean\" ? parsed.dirty : false;\n return { sha: parsed.sha, branch, dirty };\n }\n return undefined;\n } catch {\n return undefined;\n }\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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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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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","names":["join","p","readFileSync","fileURLToPath","join","readFileSync","writeFileSync","mkdirSync","join","homedir","AUTONOMA_HOME","resolve","resolve","path","DIM","RESET","log","summary","YELLOW","RESET","readFile","join","relative","glob","execFile","promisify","execFileAsync","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","dirname","relative","resolve","tool","z","inputSchema","p","tool","z","path","z","tool","input","p","join","path","resolve","CYAN","RESET","editor","GREEN","DIM","SYSTEM_PROMPT","readFile","join","BOLD","RESET","DIM","YELLOW","tool","z","readFile","join","p","SYSTEM_PROMPT","path","readFile","join","matter","z","truncate","pad","BOLD","RESET","DIM","YELLOW","SYSTEM_PROMPT","init_prompt","readFile","writeFile","join","tool","z","glob","buildFinishTool","SYSTEM_PROMPT","init_prompt","readFile","join","readFile","join","matter","truncate","pad","BOLD","RESET","DIM","YELLOW","init_prompt","readFile","join","tool","z","buildFinishTool","init_prompt","readFile","writeFile","join","STATE_FILE","z","p","tool","z","SYSTEM_PROMPT","existsSync","join","RESET","readFile","writeFile","join","text","collectRefs","p","Output","generateText","z","p","writeFile","readFile","join","spawn","tool","z","resolve","DOCS_BASE","p","tool","z","p","text","readFile","join","p","z","basename","tool","readFile","join","relative","basename","glob","init_review","readFile","writeFile","join","path","STATE_FILE","readFile","writeFile","join","z","tool","path","SYSTEM_PROMPT","matter","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","readFileSync","readFileSync","join","join","homedir","AUTONOMA_HOME","join","AUTONOMA_HOME","readFile","join","execFile","readFile","writeFile","join","readFile","join","text","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/version.ts","../src/core/analytics.ts","../src/core/errors.ts","../src/core/notify.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/review.ts","../src/agents/01-kb-generator/prompt.ts","../src/agents/01-kb-generator/flows.ts","../src/agents/01-kb-generator/index.ts","../src/agents/04-recipe-builder/entity-order.ts","../src/agents/02-entity-audit/audit-table.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/scenario-table.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-relevance.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/discover-schema.ts","../src/agents/04-recipe-builder/phases/failure-classifier.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/global-env.ts","../src/core/output.ts","../src/core/interrupt.ts","../src/core/upload.ts","../src/core/git.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 (user-declared — these MUST be covered):** ${ctx.criticalFlows}\n\nThese are flows the user explicitly said cannot break. Treat them as authoritative: every one of them must be represented faithfully in your output — never drop or downplay them. Start with these, 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 // Trim so a stray space or newline in the env var doesn't get sent as the\n // key and come back as a confusing \"Missing Authentication header\".\n const apiKey = process.env.OPENROUTER_API_KEY?.trim();\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","import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\nconst PACKAGE_NAME = \"@autonoma-ai/planner\";\n\n/**\n * The CLI's own version, read from this package's package.json.\n *\n * We deliberately do NOT use `process.env.npm_package_version`: that variable\n * is set by the package manager from whatever package.json context the process\n * was launched under. When a user runs the CLI inside their own repo (npx, a\n * project script, etc.) it reports the *user's* project version — which is why\n * analytics saw a scatter of bogus versions (0.0.0, 1.9.0, …) and `None` when\n * run as a bare global binary. Reading our own manifest fixes that.\n */\nfunction resolveVersion(): string {\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n // Bundled: this code lives in dist/index.js, so package.json is one level\n // up. In dev (src/core/version.ts) it's two levels up. The name guard keeps\n // us from accidentally picking up the user's package.json.\n for (const rel of [\"../package.json\", \"../../package.json\", \"../../../package.json\"]) {\n try {\n const pkg = JSON.parse(readFileSync(join(here, rel), \"utf-8\"));\n if (pkg?.name === PACKAGE_NAME && typeof pkg.version === \"string\") {\n return pkg.version;\n }\n } catch {\n // Keep looking — a missing or unrelated package.json at this level is fine.\n }\n }\n } catch {\n // import.meta.url unavailable or unreadable — fall through to \"unknown\".\n }\n return \"unknown\";\n}\n\nexport const CLI_VERSION = resolveVersion();\n","import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { randomUUID } from \"node:crypto\";\nimport { CLI_VERSION } from \"./version\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\nconst DEVICE_ID_PATH = join(AUTONOMA_HOME, \".device-id\");\n\n// PostHog project (public/ingestion) key. Safe to ship in a client — it can\n// only write events, not read. Same project as the landing page + app, so the\n// CLI events land in the same funnel. Override with AUTONOMA_POSTHOG_KEY.\nconst POSTHOG_PUBLIC_KEY = \"phc_mUOwUj62r8vyiisFPvXLC3G5RftETIBMnKNSHqTBdka\";\nconst DEFAULT_HOST = \"https://us.i.posthog.com\";\n\nfunction resolveKey(): string {\n return (process.env.AUTONOMA_POSTHOG_KEY ?? POSTHOG_PUBLIC_KEY).trim();\n}\n\nfunction resolveHost(): string {\n return (process.env.AUTONOMA_POSTHOG_HOST ?? DEFAULT_HOST).replace(/\\/+$/, \"\");\n}\n\n// Tracking is ON by default; users opt out with DONT_TRACK=1 (or =true).\nfunction trackingDisabled(): boolean {\n const v = process.env.DONT_TRACK;\n return v === \"1\" || v === \"true\";\n}\n\n// To stitch the CLI into the landing → app → auth → CLI funnel, the app/portal\n// passes the user's PostHog distinct_id to the CLI via AUTONOMA_DISTINCT_ID.\n// When present we use it (and let PostHog build the person profile so the funnel\n// connects). Otherwise we fall back to an anonymous per-machine device id and\n// suppress person processing so we don't create junk persons.\nfunction getIdentity(): string | undefined {\n const id = process.env.AUTONOMA_DISTINCT_ID?.trim();\n return id && id.length > 0 ? id : undefined;\n}\n\n// One id per process, attached to every event — lets you group a run's events,\n// count distinct runs, and dedupe. Stable for the life of the CLI invocation.\nconst RUN_ID = randomUUID();\n\n/**\n * The current run's id. Printed in failure output as a support reference so a\n * user-reported error maps 1:1 to its `$exception` event(s) in analytics.\n */\nexport function getRunId(): string {\n return RUN_ID;\n}\n\nlet cachedDeviceId: string | null = null;\n\nfunction getDeviceId(): string {\n if (cachedDeviceId) return cachedDeviceId;\n try {\n cachedDeviceId = readFileSync(DEVICE_ID_PATH, \"utf-8\").trim();\n if (cachedDeviceId) return cachedDeviceId;\n } catch {}\n cachedDeviceId = randomUUID();\n try {\n mkdirSync(AUTONOMA_HOME, { recursive: true });\n writeFileSync(DEVICE_ID_PATH, cachedDeviceId, { encoding: \"utf-8\", mode: 0o600 });\n } catch {}\n return cachedDeviceId;\n}\n\nlet enabled: boolean | null = null;\n\nfunction isEnabled(): boolean {\n if (enabled === null) {\n enabled = !trackingDisabled() && resolveKey().length > 0;\n }\n return enabled;\n}\n\nconst pending = new Set<Promise<unknown>>();\n\n/**\n * Fire-and-forget anonymous event capture. Never throws and never blocks the\n * CLI — failures are swallowed. No PII or source code is ever sent.\n */\nexport function track(event: string, properties: Record<string, unknown> = {}): void {\n if (!isEnabled()) return;\n\n const identity = getIdentity();\n const body = JSON.stringify({\n api_key: resolveKey(),\n event,\n distinct_id: identity ?? getDeviceId(),\n properties: {\n ...properties,\n run_id: RUN_ID,\n // Only build a person profile when we have a real identity from the app,\n // so the CLI joins the existing funnel person instead of creating a new one.\n $process_person_profile: identity != null,\n cli_version: CLI_VERSION,\n },\n });\n\n const promise = fetch(`${resolveHost()}/capture/`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n })\n .catch(() => {})\n .finally(() => pending.delete(promise));\n\n pending.add(promise);\n}\n\n/**\n * Capture an exception in PostHog error tracking (`$exception` event).\n * Same fire-and-forget guarantees as `track`. Error messages and stacks may\n * reference CLI-internal file paths, never the user's source code.\n */\nexport function trackError(\n error: unknown,\n properties: Record<string, unknown> = {},\n handled = true,\n): void {\n const err = error instanceof Error ? error : new Error(String(error));\n track(\"$exception\", {\n ...properties,\n $exception_list: [\n {\n type: err.name,\n value: err.message,\n mechanism: { handled, synthetic: !(error instanceof Error) },\n },\n ],\n error_stack: err.stack,\n });\n}\n\n/** Flush in-flight events before exit. Best-effort, bounded by `timeoutMs`. */\nexport async function flushAnalytics(timeoutMs = 1500): Promise<void> {\n if (pending.size === 0) return;\n await Promise.race([\n Promise.allSettled([...pending]),\n new Promise((resolve) => setTimeout(resolve, timeoutMs)),\n ]);\n}\n","import { APICallError, RetryError, LoadAPIKeyError, InvalidPromptError, NoSuchModelError } from \"ai\";\nimport { getRunId } from \"./analytics\";\nimport { CLI_VERSION } from \"./version\";\n\nexport class AgentError extends Error {\n constructor(\n message: string,\n public readonly phase: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"AgentError\";\n }\n}\n\nexport class ToolError extends Error {\n constructor(\n message: string,\n public readonly toolName: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"ToolError\";\n }\n}\n\nexport interface RetryOptions {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n}\n\nconst DEFAULT_RETRY: RetryOptions = {\n maxRetries: 3,\n baseDelayMs: 1000,\n maxDelayMs: 30_000,\n};\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: Partial<RetryOptions> = {},\n): Promise<T> {\n const opts = { ...DEFAULT_RETRY, ...options };\n\n for (let attempt = 1; attempt <= opts.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n const isLast = attempt === opts.maxRetries;\n const shouldRetry = opts.shouldRetry?.(error, attempt) ?? isRetryable(error);\n\n if (isLast || !shouldRetry) throw error;\n\n const delay = Math.min(\n opts.baseDelayMs * 2 ** (attempt - 1) + Math.random() * 500,\n opts.maxDelayMs,\n );\n await sleep(delay);\n }\n }\n\n throw new Error(\"Unreachable\");\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n return (\n msg.includes(\"rate limit\") ||\n msg.includes(\"429\") ||\n msg.includes(\"503\") ||\n msg.includes(\"timeout\") ||\n msg.includes(\"econnreset\") ||\n msg.includes(\"econnrefused\")\n );\n }\n return false;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * True when an error represents the user deliberately stopping the run — a\n * Ctrl+C or a \"cancel\" choice at an interactive prompt (clack throws/returns a\n * cancel that we surface as a \"... cancelled\" error). These are not failures:\n * callers should save progress and exit quietly, and must NOT report them to\n * error tracking, where they'd masquerade as bugs.\n */\nexport function isUserCancellation(err: unknown): boolean {\n return err instanceof Error && /\\bcancell?ed\\b/i.test(err.message);\n}\n\n/**\n * A failure we recognize and can explain. When `describeKnownError` returns one,\n * the caller prints the friendly title + hint and suppresses the raw stack —\n * the stack is library-internal noise that wouldn't help the user act.\n */\nexport interface KnownError {\n title: string;\n hint: string;\n}\n\n/**\n * Collapse an exception to every message in its cause chain, lowercased, so a\n * matcher can look for a substring regardless of how deeply the SDK wrapped it.\n */\nfunction chainMessages(err: unknown): string {\n const parts: string[] = [];\n let cur: unknown = err;\n for (let depth = 0; cur != null && depth < 10; depth++) {\n if (cur instanceof Error) {\n parts.push(cur.message);\n cur = cur.cause;\n } else {\n parts.push(String(cur));\n break;\n }\n }\n return parts.join(\" ← \").toLowerCase();\n}\n\n/**\n * Translate the failures we've seen in the wild into an actionable one-liner.\n * These are almost always configuration problems, not bugs — a raw stack just\n * buries the fix. Returns null for anything we don't recognize, so the caller\n * falls back to printing the full stack + a support reference.\n */\nexport function describeKnownError(err: unknown): KnownError | null {\n const msg = chainMessages(err);\n const status = APICallError.isInstance(err) ? err.statusCode : undefined;\n\n const looksLikeAuth =\n msg.includes(\"missing authentication header\") ||\n msg.includes(\"no auth credentials\") ||\n msg.includes(\"openrouter_api_key\") ||\n msg.includes(\"user not found\") ||\n status === 401 ||\n status === 403;\n if (looksLikeAuth) {\n return {\n title: \"OpenRouter rejected the request — your API key looks missing or invalid.\",\n hint: \"Set a valid OPENROUTER_API_KEY (https://openrouter.ai/keys). If it's already set, the key may be revoked, empty, or have a stray space.\",\n };\n }\n\n // OpenRouter rejects a request when the account balance can't cover the\n // tokens it would reserve — the message literally reads \"requires more\n // credits, or fewer max_tokens ... can only afford N\". This is the most\n // common paid-tier blocker and almost always means an empty/near-empty\n // balance, so point straight at the top-up page.\n if (msg.includes(\"fewer max_tokens\") || msg.includes(\"can only afford\")) {\n return {\n title: \"Your OpenRouter account doesn't have enough credit for this run.\",\n hint: \"Add credit (even a few dollars goes a long way) at https://openrouter.ai/settings/credits, then re-run. A free balance can't cover a full request.\",\n };\n }\n\n if (msg.includes(\"insufficient\") || msg.includes(\"credits\") || msg.includes(\"quota\") || status === 402) {\n return {\n title: \"OpenRouter ran out of credits for this account.\",\n hint: \"Add credit at https://openrouter.ai/settings/credits, then re-run.\",\n };\n }\n\n if (\n NoSuchModelError.isInstance(err) ||\n msg.includes(\"not a valid model\") ||\n msg.includes(\"no endpoints found\") ||\n msg.includes(\"model not found\")\n ) {\n return {\n title: \"The requested model isn't available on OpenRouter.\",\n hint: \"Check OPENROUTER_MODEL, or unset it to use the default.\",\n };\n }\n\n if (msg.includes(\"rate limit\") || msg.includes(\"too many requests\") || status === 429) {\n return {\n title: \"OpenRouter is rate-limiting this account.\",\n hint: \"Wait a minute and re-run. If it persists, your key may be on a low-throughput tier.\",\n };\n }\n\n return null;\n}\n\n/**\n * A short support reference block printed under an unrecognized failure. The\n * `ref` is this run's id — it ties the printed error to the exact `$exception`\n * event(s) in analytics, so a user only has to paste one short string for us to\n * find their full stack and context.\n */\nexport function supportReference(extra: Record<string, string | undefined> = {}): string {\n const fields: Record<string, string | undefined> = {\n ref: getRunId(),\n version: CLI_VERSION,\n node: process.version,\n platform: `${process.platform}-${process.arch}`,\n ...extra,\n };\n return Object.entries(fields)\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\" \");\n}\n\n/**\n * Render an exception with its full stack and cause chain, so users can\n * copy-paste it when reporting an issue. The CLI is open source — stacks\n * reference CLI internals, never the user's source code.\n */\nexport function formatException(err: unknown): string {\n if (!(err instanceof Error)) return String(err);\n let out = err.stack ?? `${err.name}: ${err.message}`;\n if (err.cause != null) {\n out += `\\nCaused by: ${formatException(err.cause)}`;\n }\n return out;\n}\n\nexport type AgentErrorClass = \"timeout\" | \"transient\" | \"fatal\";\n\nconst FATAL_STATUS_CODES = new Set([400, 401, 403, 404, 422]);\n\n// Recoverable provider quirks that arrive disguised as fatal client errors\n// (usually a 400). They are not malformed requests we can fix — a fresh retry,\n// or falling back to a different model, gets past them — so they must be\n// classified \"transient\" before the status-code check marks them fatal.\n//\n// \"corrupted thought signature\": Google's Gemini reasoning models (via\n// OpenRouter) intermittently reject a request when the reasoning-token\n// signature carried over from a prior turn fails to validate. It returns as a\n// 400 but is transient — retrying or switching to a non-reasoning fallback\n// model clears it.\nconst RETRYABLE_PROVIDER_QUIRKS = [\"corrupted thought signature\"];\n\nconst TRANSIENT_MESSAGE_PATTERNS = [\n \"econnreset\",\n \"econnrefused\",\n \"etimedout\",\n \"socket hang up\",\n \"fetch failed\",\n \"network\",\n \"overloaded\",\n \"rate limit\",\n \"too many requests\",\n \"429\",\n \"500\",\n \"502\",\n \"503\",\n \"529\",\n];\n\n/**\n * Classify an error thrown by an agent run so the caller can decide whether to\n * retry. Everything unknown defaults to \"transient\" — retries are bounded and\n * a wrong \"fatal\" kills the step, while a wrong \"transient\" only costs a few\n * retries before the failure surfaces anyway.\n */\nexport function classifyAgentError(err: unknown): AgentErrorClass {\n const message = err instanceof Error ? err.message : String(err);\n const msg = message.toLowerCase();\n\n if (msg.includes(\"timed out\") || msg.includes(\"timeout\") || msg.includes(\"abort\")) {\n return \"timeout\";\n }\n\n // Check known recoverable quirks across the whole cause chain first, so a 400\n // status from the underlying APICallError doesn't pre-empt them as fatal.\n const chain = chainMessages(err);\n if (RETRYABLE_PROVIDER_QUIRKS.some((pattern) => chain.includes(pattern))) {\n return \"transient\";\n }\n\n if (APICallError.isInstance(err)) {\n if (err.statusCode != null && FATAL_STATUS_CODES.has(err.statusCode)) return \"fatal\";\n return \"transient\";\n }\n\n if (\n LoadAPIKeyError.isInstance(err) ||\n InvalidPromptError.isInstance(err) ||\n NoSuchModelError.isInstance(err)\n ) {\n return \"fatal\";\n }\n\n if (RetryError.isInstance(err)) {\n if (err.reason === \"errorNotRetryable\" && err.lastError !== err) {\n return classifyAgentError(err.lastError);\n }\n return \"transient\";\n }\n\n if (TRANSIENT_MESSAGE_PATTERNS.some((pattern) => msg.includes(pattern))) {\n return \"transient\";\n }\n\n return \"transient\";\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","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 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(`reading ${summary}`);\n break;\n\n case \"glob\":\n writeSpinner(`glob ${summary}`);\n break;\n\n case \"grep\":\n writeSpinner(`grep ${summary}`);\n break;\n\n case \"list_directory\":\n writeSpinner(`listing ${summary}`);\n break;\n\n case \"bash\":\n writeSpinner(`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 // Label which agent/area finished — otherwise a BFS run ends in a\n // wall of identical \"✓ finish\" lines with no context.\n writePermanent(` ${GREEN}${BOLD}✓ done:${RESET} ${GREEN}${agentId}${RESET}`);\n break;\n\n case \"subagent\":\n case \"spawn_researcher\":\n writePermanent(` ${CYAN}⊕ subagent: ${summary}${RESET}`);\n break;\n\n default:\n writeSpinner(`${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 ModelMessage,\n type ToolSet,\n ToolLoopAgent,\n hasToolCall,\n stepCountIs,\n} from \"ai\";\nimport { track } from \"./analytics\";\nimport { createStepLogger, type StepInfo } from \"./display\";\nimport { AgentError, classifyAgentError, sleep } from \"./errors\";\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\n// The tool loop stops as soon as the model calls `finish` — even when the\n// finish tool rejected with a validation error — or when the model replies\n// with plain text. In both cases no result was captured, so we re-prompt the\n// same conversation a bounded number of times instead of failing the step.\nconst MAX_NUDGES = 2;\nconst NUDGE_PROMPT =\n \"You stopped before completing the task. The task is only complete once the finish tool \" +\n \"has been called and succeeded. If your last finish call returned an error, fix exactly what \" +\n \"it reported. Otherwise, continue where you left off and call the finish tool when done.\";\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\n/**\n * Block appended to a step's prompt when the user retries a failed step with\n * guidance. Returns \"\" when there is no guidance so call sites can always\n * interpolate it.\n */\nexport function formatRetryGuidance(guidance?: string): string {\n if (!guidance?.trim()) return \"\";\n return (\n `\\nA previous attempt at this task did not complete successfully. ` +\n `The user provided this guidance for the retry:\\n\"${guidance.trim()}\"\\n`\n );\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 modelIdOf = (m: LanguageModel) => (typeof m === \"string\" ? m : m.modelId);\n\n // Tag a terminal failure with the agent and model it came from, preserving the\n // original error as the cause so the known-error matcher can still read it.\n const fail = (err: unknown, model: LanguageModel): never => {\n const msg = err instanceof Error ? err.message : String(err);\n throw new AgentError(\n `agent \"${config.id}\" (model ${modelIdOf(model)}) failed: ${msg}`,\n config.id,\n err,\n );\n };\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 const messages: ModelMessage[] = [{ role: \"user\", content: prompt }];\n let generation = await agent.generate({\n messages,\n timeout: { stepMs: stepTimeout },\n });\n\n let nudges = 0;\n while (extractResult() === undefined && nudges < MAX_NUDGES) {\n nudges++;\n console.log(\n ` ${YELLOW}[${config.id}] agent stopped without finishing — nudging (${nudges}/${MAX_NUDGES})...${RESET}`,\n );\n track(\"cli_agent_nudged\", { agent: config.id, nudge: nudges });\n messages.push(...generation.response.messages);\n messages.push({ role: \"user\", content: NUDGE_PROMPT });\n generation = await agent.generate({\n messages,\n timeout: { stepMs: stepTimeout },\n });\n }\n\n return extractResult();\n } catch (err) {\n const errorClass = classifyAgentError(err);\n\n if (errorClass === \"fatal\") fail(err, model);\n\n const msg = err instanceof Error ? err.message : String(err);\n if (errorClass === \"timeout\") {\n console.log(` ${YELLOW}[${config.id}] step timed out after ${stepTimeout / 1000}s${RESET}`);\n } else {\n console.log(` ${YELLOW}[${config.id}] provider error: ${msg}${RESET}`);\n }\n track(\"cli_agent_retryable_error\", { agent: config.id, error_class: errorClass, retry });\n\n if (retry < RETRIES_BEFORE_FALLBACK - 1) {\n console.log(\n ` ${YELLOW}[${config.id}] retrying (${retry + 1}/${RETRIES_BEFORE_FALLBACK})...${RESET}`,\n );\n if (errorClass === \"transient\") {\n await sleep(Math.min(2000 * 2 ** retry, 10_000));\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} failed attempts, switching to ${nextModel}${RESET}`,\n );\n break;\n }\n\n fail(err, model);\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(\"pages\", 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 * as p from \"@clack/prompts\";\nimport { access } from \"node:fs/promises\";\nimport { join, isAbsolute } from \"node:path\";\nimport spawn from \"cross-spawn\";\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 * Optional renderer for an inline, human-readable summary of the step's\n * output (e.g. a table of flows). Printed before the review guidance and the\n * feedback prompt. Re-run on every loop iteration so edits are reflected.\n */\n renderSummary?: () => Promise<string | undefined>;\n}\n\nfunction resolvePath(artifact: string, outputDir: string): string {\n if (isAbsolute(artifact)) return artifact;\n return join(outputDir, artifact);\n}\n\nexport interface 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\nconst TERMINAL_EDITORS = new Set([\"nano\", \"vim\"]);\n\nexport async function launchEditor(editor: EditorOption, files: string[]): Promise<void> {\n const args = editor.args(files);\n const isTerminalEditor = TERMINAL_EDITORS.has(editor.command);\n\n await new Promise<void>((resolve) => {\n let settled = false;\n const settle = () => {\n if (settled) return;\n settled = true;\n resolve();\n };\n\n // cross-spawn resolves `.cmd`/`.bat` launcher shims — e.g. VS Code's\n // `code` on Windows — which a bare child_process.spawn can't exec and\n // would reject with ENOENT.\n const proc = spawn(editor.command, args, { stdio: \"inherit\" });\n\n // Always listen for `error`: a GUI launcher that fails to spawn emits it\n // asynchronously, and an unhandled `error` event crashes the process.\n proc.on(\"error\", (err: Error) => {\n p.log.warn(\n `Couldn't open ${editor.label} (${err.message}). Review the files manually:`,\n );\n for (const f of files) console.log(` ${CYAN}${f}${RESET}`);\n settle();\n });\n\n if (isTerminalEditor) {\n // Terminal editors take over stdio — block until the user exits.\n proc.on(\"close\", () => settle());\n } else {\n // GUI launchers return immediately; don't block the review loop waiting\n // for the window to close. Resolve once the process is spawned.\n proc.on(\"spawn\", () => settle());\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.renderSummary) {\n const rendered = await options.renderSummary();\n if (rendered) {\n console.log(rendered);\n console.log(\"\");\n }\n }\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- Any flow the user explicitly named as critical in the Project Context MUST appear as a feature in core_flows AND be marked core: true with a coreReason. Map the user's wording to the matching feature(s) — never drop a user-declared critical flow or leave it as core: false.\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 { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport matter from \"gray-matter\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\nexport interface CoreFlow {\n feature: string;\n description?: string;\n mission?: string;\n core?: boolean;\n coreReason?: string;\n}\n\n/** Read AUTONOMA.md and return its `core_flows` frontmatter entries (or []). */\nexport async function parseCoreFlows(outputDir: string): Promise<CoreFlow[]> {\n let raw: string;\n try {\n raw = await readFile(join(outputDir, \"AUTONOMA.md\"), \"utf-8\");\n } catch {\n return [];\n }\n\n try {\n const parsed = matter(raw);\n const flows = (parsed.data as { core_flows?: unknown }).core_flows;\n if (!Array.isArray(flows)) return [];\n return flows\n .filter((f): f is Record<string, unknown> => !!f && typeof f === \"object\")\n .map((f) => ({\n feature: String(f.feature ?? \"\").trim(),\n description: f.description != null ? String(f.description) : undefined,\n mission: f.mission != null ? String(f.mission) : undefined,\n core: f.core === true,\n coreReason: f.coreReason != null ? String(f.coreReason) : undefined,\n }))\n .filter((f) => f.feature.length > 0);\n } catch {\n return [];\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1).trimEnd() + \"…\";\n}\n\nfunction pad(s: string, width: number): string {\n return s + \" \".repeat(Math.max(0, width - s.length));\n}\n\n/** Render core flows as an aligned terminal table, core flows highlighted. */\nexport function renderFlowsTable(flows: CoreFlow[]): string {\n if (flows.length === 0) return \"\";\n\n const DESC_MAX = 60;\n const NAME_MAX = 32;\n\n const rows = flows.map((f, i) => ({\n num: String(i + 1),\n name: truncate(f.feature, NAME_MAX),\n crit: f.core ? \"core\" : \"normal\",\n desc: truncate((f.description ?? \"\").replace(/\\s+/g, \" \").trim(), DESC_MAX),\n }));\n\n const numW = Math.max(1, ...rows.map((r) => r.num.length));\n const nameW = Math.max(\"Flow\".length, ...rows.map((r) => r.name.length));\n const critW = Math.max(\"Criticality\".length, ...rows.map((r) => r.crit.length));\n\n const coreCount = flows.filter((f) => f.core).length;\n const header =\n `${BOLD}${pad(\"#\", numW)} ${pad(\"Flow\", nameW)} ${pad(\"Criticality\", critW)} Description${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + critW + DESC_MAX + 6)}${RESET}`;\n\n const body = rows\n .map((r) => {\n const line = `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.crit, critW)} ${r.desc}`;\n // Highlight core flows so the user can eyeball criticality fast.\n return r.crit === \"core\" ? `${YELLOW}${line}${RESET}` : line;\n })\n .join(\"\\n\");\n\n const caption = `${DIM}${flows.length} flows · ${coreCount} marked core${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\n}\n","import {tool} from \"ai\";\nimport {z} from \"zod\";\nimport {readFile} from \"node:fs/promises\";\nimport {join} from \"node:path\";\nimport {type AgentResult, buildDefaultStepLogger, formatRetryGuidance, 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\";\nimport {parseCoreFlows, renderFlowsTable} from \"./flows\";\n\nexport interface KBGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n retryGuidance?: string;\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 + formatRetryGuidance(input.retryGuidance);\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 // The finish tool can be blocked (e.g. by the page-coverage gate) even though\n // the agent already wrote AUTONOMA.md — which would leave `result` undefined\n // and silently skip the whole review. Don't let that happen: if the file\n // exists, treat the step as done so the user still gets the flows table, the\n // file path, and the editor/chat review below.\n const autonomaPath = join(input.outputDir, \"AUTONOMA.md\");\n const autonomaExists = await readFile(autonomaPath, \"utf-8\").then(() => true).catch(() => false);\n if (!result?.success && autonomaExists) {\n result = {\n success: true,\n artifacts: [\"AUTONOMA.md\"],\n summary: \"Knowledge base generated.\",\n };\n }\n\n // Self-review pass: before involving the user, make the agent verify that the\n // flows the user explicitly declared critical actually landed in core_flows as\n // core: true — and fix the file if not. Targets \"a starting input was ignored\".\n const declaredCriticalFlows = input.projectContext?.criticalFlows?.trim();\n if (result?.success && declaredCriticalFlows) {\n const beforeSelfReview = result;\n result = undefined;\n const selfReviewPrompt = `Before this knowledge base is shown to the user, verify it honors the critical flows they explicitly declared.\n\nThe user said these flows are critical and cannot break:\n\"${declaredCriticalFlows}\"\n\nRead your AUTONOMA.md output. For EACH critical flow the user named:\n- Confirm it appears as a feature in core_flows (map the user's wording to the matching feature).\n- Confirm that feature is marked core: true with a coreReason.\n\nIf any declared critical flow is missing, mismatched, or left core: false, FIX AUTONOMA.md now — add the feature if it is genuinely absent, or flip core to true with a coreReason. Do not downgrade or drop anything the user declared critical.\n\nWhen AUTONOMA.md correctly reflects every declared critical flow, call finish.`;\n await runAgent(agentConfig, selfReviewPrompt, () => result);\n // If the agent didn't re-call finish (e.g. no changes needed), keep the prior result.\n if (!result) result = beforeSelfReview;\n }\n\n const reviewed = await reviewLoop(result, {\n agentId: \"kb-generator\",\n outputDir: input.outputDir,\n nonInteractive: input.nonInteractive,\n renderSummary: async () => {\n const flows = await parseCoreFlows(input.outputDir);\n return flows.length ? renderFlowsTable(flows) : undefined;\n },\n reviewGuidance:\n \"Check that every page/route in your app appears in core_flows.\\n\" +\n \"Verify that every flow the user named as critical in the Project Context appears in core_flows and is marked core: true with a coreReason.\\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 return reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"KB generator agent stopped without producing AUTONOMA.md\",\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport { z } from \"zod\";\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\nconst createdBySchema = z.object({\n owner: z.string(),\n via: z.string().optional(),\n why: z.string().optional(),\n});\n\nconst auditedModelSchema = z.object({\n name: z.string(),\n independently_created: z.coerce.boolean().default(false),\n creation_file: z.string().optional(),\n creation_function: z.string().optional(),\n side_effects: z.array(z.string()).optional(),\n // Tolerate a stray `created_by:` with no entries (parsed as null by YAML).\n created_by: z.array(createdBySchema).nullish().transform((v) => v ?? []),\n});\n\nconst frontmatterSchema = z.object({\n models: z.array(auditedModelSchema).nullish().transform((v) => v ?? []),\n});\n\n/**\n * Parse entity-audit.md into structured models. The frontmatter (`models:`) is\n * the contract every downstream step depends on, so this is deliberately\n * forgiving: it first parses real YAML frontmatter (validated with zod), and\n * only if that yields nothing does it fall back to scanning the document line\n * by line. A malformed audit should degrade to partial data, never hard-crash\n * the recipe builder — earlier versions threw \"no YAML frontmatter\" here and\n * took the whole run down.\n */\nexport async function parseEntityAudit(outputDir: string): Promise<AuditedModel[]> {\n const raw = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n\n try {\n const parsed = frontmatterSchema.safeParse(matter(raw).data);\n if (parsed.success && parsed.data.models.length > 0) {\n return parsed.data.models.map((m) => ({\n name: m.name,\n independently_created: m.independently_created,\n creation_file: m.creation_file,\n creation_function: m.creation_function,\n side_effects: m.side_effects,\n created_by: m.created_by,\n }));\n }\n } catch {\n // gray-matter/js-yaml choked on malformed YAML — fall through to the\n // line scanner below, which copes with partial or non-standard output.\n }\n\n return parseAuditByLineScan(raw);\n}\n\n/**\n * Last-resort parser: walk the document and reconstruct models from `- name:`\n * blocks. Works even when the content isn't valid YAML or has no `---` fence.\n */\nfunction parseAuditByLineScan(raw: string): AuditedModel[] {\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---/);\n // Prefer the fenced frontmatter when present, else scan the whole document.\n const yaml = fmMatch ? fmMatch[1]! : raw;\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\n/**\n * Resolve the order entities are processed in: a topological sort of the\n * `created_by` dependency graph (owners before the entities they spawn). Among\n * entities that are simultaneously available (no unmet dependency), ties are\n * broken by `importanceRank` (lower index = more important, surfaced first) when\n * provided, otherwise alphabetically.\n */\nexport function resolveEntityOrder(\n models: AuditedModel[],\n importanceRank?: Map<string, number>,\n): string[] {\n const rankOf = (name: string) => importanceRank?.get(name) ?? Number.MAX_SAFE_INTEGER;\n const compare = (a: string, b: string) => rankOf(a) - rankOf(b) || a.localeCompare(b);\n\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(compare);\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(compare);\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 { parseEntityAudit, type AuditedModel } from \"../04-recipe-builder/entity-order\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\n/** Parse the audited models from entity-audit.md (empty on any failure). */\nexport async function parseAuditedModels(outputDir: string): Promise<AuditedModel[]> {\n try {\n return await parseEntityAudit(outputDir);\n } catch {\n return [];\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1).trimEnd() + \"…\";\n}\n\nfunction pad(s: string, width: number): string {\n return s + \" \".repeat(Math.max(0, width - s.length));\n}\n\nfunction creationSource(m: AuditedModel): string {\n if (m.independently_created) {\n return m.creation_function ?? m.creation_file ?? \"(own creation API)\";\n }\n const parents = m.created_by.map((cb) => cb.owner).filter(Boolean);\n return parents.length ? `← ${parents.join(\", \")}` : \"(no known creator)\";\n}\n\n/**\n * Render the entity audit as an aligned terminal table, mirroring the KB flows\n * table. Standalone (independently-created) models are highlighted since those\n * are the ones that get their own factories.\n */\nexport function renderEntityAuditTable(models: AuditedModel[]): string {\n if (models.length === 0) return \"\";\n\n const NAME_MAX = 32;\n const SRC_MAX = 52;\n\n const rows = models.map((m, i) => ({\n num: String(i + 1),\n name: truncate(m.name, NAME_MAX),\n creation: m.independently_created ? \"standalone\" : \"side-effect\",\n source: truncate(creationSource(m).replace(/\\s+/g, \" \").trim(), SRC_MAX),\n }));\n\n const numW = Math.max(1, ...rows.map((r) => r.num.length));\n const nameW = Math.max(\"Entity\".length, ...rows.map((r) => r.name.length));\n const critW = Math.max(\"Creation\".length, ...rows.map((r) => r.creation.length));\n\n const standalone = models.filter((m) => m.independently_created).length;\n const header =\n `${BOLD}${pad(\"#\", numW)} ${pad(\"Entity\", nameW)} ${pad(\"Creation\", critW)} Created from${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + critW + SRC_MAX + 6)}${RESET}`;\n\n const body = rows\n .map((r) => {\n const line = `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.creation, critW)} ${r.source}`;\n // Highlight standalone models — those get their own factories.\n return r.creation === \"standalone\" ? `${YELLOW}${line}${RESET}` : line;\n })\n .join(\"\\n\");\n\n const caption = `${DIM}${models.length} models · ${standalone} standalone · ${models.length - standalone} side-effect-only${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\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, formatRetryGuidance, type AgentResult } from \"../../core/agent\";\nimport { formatException } from \"../../core/errors\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { getModel } from \"../../core/model\";\nimport { reviewLoop } from \"../../core/review\";\nimport { parseAuditedModels, renderEntityAuditTable } from \"./audit-table\";\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 retryGuidance?: string;\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 + formatRetryGuidance(input.retryGuidance);\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 let agentError: string | undefined;\n try {\n await runAgent(agentConfig, prompt, () => result);\n } catch (err) {\n agentError = err instanceof Error ? err.message : String(err);\n console.error(`Entity audit agent error:\\n${formatException(err)}`);\n }\n logger.summary();\n\n // The frontmatter in entity-audit.md is the contract every later step parses,\n // and the tracker holds the authoritative structured data (one entry per\n // mark_model_audited call). Always (re)write the file from the tracker so the\n // on-disk frontmatter is guaranteed well-formed — the agent's own write_file\n // occasionally emitted a file with missing or garbled frontmatter, which used\n // to crash the recipe builder downstream with \"no YAML frontmatter\".\n const writeCanonicalAudit = async (): Promise<string | null> => {\n if (tracker.auditedModels.size === 0) return null;\n const auditPath = join(input.outputDir, \"entity-audit.md\");\n await writeFile(auditPath, tracker.generateAuditMarkdown(), \"utf-8\");\n return auditPath;\n };\n\n const canonicalPath = await writeCanonicalAudit();\n if (!result && canonicalPath) {\n const cov = tracker.coverage();\n result = {\n success: true,\n artifacts: [canonicalPath],\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 renderSummary: async () => {\n const models = await parseAuditedModels(input.outputDir);\n return models.length ? renderEntityAuditTable(models) : undefined;\n },\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 // Re-canonicalize after the agent revised its answers, so the file stays\n // parseable regardless of how the agent rewrote it.\n await writeCanonicalAudit();\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: agentError\n ? `Entity audit failed: ${agentError}`\n : \"Entity audit agent stopped without producing entity-audit.md\",\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","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport matter from \"gray-matter\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BOLD = \"\\x1b[1m\";\n\nexport interface ScenarioEntityType {\n name: string;\n count: number;\n variableFields: string[];\n}\n\nexport interface ParsedScenario {\n scenarioNames: string[];\n entityTypes: ScenarioEntityType[];\n}\n\n/** Parse scenarios.md frontmatter into entity types + their variable fields. */\nexport async function parseScenario(outputDir: string): Promise<ParsedScenario> {\n let raw: string;\n try {\n raw = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch {\n return { scenarioNames: [], entityTypes: [] };\n }\n\n try {\n const data = matter(raw).data as {\n scenarios?: { name?: unknown }[];\n entity_types?: { name?: unknown; count?: unknown }[];\n variable_fields?: { entity?: unknown; field?: unknown }[];\n };\n\n // entity name -> [field names that vary]\n const varsByEntity = new Map<string, string[]>();\n for (const vf of data.variable_fields ?? []) {\n const entity = vf?.entity != null ? String(vf.entity) : \"\";\n const field = vf?.field != null ? String(vf.field) : \"\";\n if (!entity || !field) continue;\n const list = varsByEntity.get(entity) ?? [];\n list.push(field);\n varsByEntity.set(entity, list);\n }\n\n const entityTypes: ScenarioEntityType[] = (data.entity_types ?? [])\n .map((e) => {\n const name = e?.name != null ? String(e.name).trim() : \"\";\n const count = typeof e?.count === \"number\" ? e.count : Number(e?.count ?? 0) || 0;\n return { name, count, variableFields: varsByEntity.get(name) ?? [] };\n })\n .filter((e) => e.name.length > 0);\n\n const scenarioNames = (data.scenarios ?? [])\n .map((s) => (s?.name != null ? String(s.name).trim() : \"\"))\n .filter((n) => n.length > 0);\n\n return { scenarioNames, entityTypes };\n } catch {\n return { scenarioNames: [], entityTypes: [] };\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1).trimEnd() + \"…\";\n}\n\nfunction pad(s: string, width: number): string {\n return s + \" \".repeat(Math.max(0, width - s.length));\n}\n\n/**\n * Render the scenario as an aligned terminal table, mirroring the KB flows and\n * entity audit tables. Entities with variable fields (values that change\n * between runs) are highlighted.\n */\nexport function renderScenarioTable(parsed: ParsedScenario): string {\n if (parsed.entityTypes.length === 0) return \"\";\n\n const NAME_MAX = 32;\n const VARS_MAX = 40;\n\n const rows = parsed.entityTypes.map((e, i) => ({\n num: String(i + 1),\n name: truncate(e.name, NAME_MAX),\n count: String(e.count),\n vars: e.variableFields.length ? truncate(e.variableFields.join(\", \"), VARS_MAX) : \"—\",\n hasVars: e.variableFields.length > 0,\n }));\n\n const numW = Math.max(1, ...rows.map((r) => r.num.length));\n const nameW = Math.max(\"Entity\".length, ...rows.map((r) => r.name.length));\n const countW = Math.max(\"Count\".length, ...rows.map((r) => r.count.length));\n\n const totalRecords = parsed.entityTypes.reduce((sum, e) => sum + e.count, 0);\n const withVars = parsed.entityTypes.filter((e) => e.variableFields.length > 0).length;\n\n const header =\n `${BOLD}${pad(\"#\", numW)} ${pad(\"Entity\", nameW)} ${pad(\"Count\", countW)} Variable fields${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + countW + VARS_MAX + 6)}${RESET}`;\n\n const body = rows\n .map((r) => {\n const line = `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.count, countW)} ${r.vars}`;\n // Highlight entities with variable fields — those change between runs.\n return r.hasVars ? `${YELLOW}${line}${RESET}` : line;\n })\n .join(\"\\n\");\n\n const scenarioLabel = parsed.scenarioNames.length\n ? `scenario: ${parsed.scenarioNames.join(\", \")} · `\n : \"\";\n const caption = `${DIM}${scenarioLabel}${parsed.entityTypes.length} entity types · ${totalRecords} records · ${withVars} with variable fields${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\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, formatRetryGuidance, 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 { parseScenario, renderScenarioTable } from \"./scenario-table\";\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 retryGuidance?: string;\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 + formatRetryGuidance(input.retryGuidance);\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 renderSummary: async () => {\n const parsed = await parseScenario(input.outputDir);\n return parsed.entityTypes.length ? renderScenarioTable(parsed) : undefined;\n },\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 agent stopped without producing scenarios.md\",\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 { type LanguageModel, Output, generateText } from \"ai\";\nimport { z } from \"zod\";\nimport { formatException } from \"../../core/errors\";\nimport type { AuditedModel } from \"./entity-order\";\n\nconst rankedSchema = z.object({\n ranked: z\n .array(z.string())\n .describe(\"Every entity name, ordered most-important first.\"),\n});\n\nasync function callRanker(model: LanguageModel, prompt: string): Promise<string[]> {\n const result = await generateText({\n model,\n prompt,\n output: Output.object({ schema: rankedSchema }),\n });\n return result.output.ranked;\n}\n\nexport interface ReconcileResult {\n /** Canonical names in the final, reconciled order. */\n order: string[];\n /** Canonical names the AI omitted (appended to the end in original order). */\n missing: string[];\n /** Names the AI returned that aren't in the canonical set (dropped). */\n invented: string[];\n /** Names the AI returned more than once (later occurrences dropped). */\n duplicates: string[];\n}\n\n/**\n * Reconcile an AI-produced ordering against the canonical set of entity names.\n * Pure and deterministic so the validation logic is testable without a model.\n *\n * - Names not in the canonical set are dropped (recorded as `invented`).\n * - Repeated names keep their first occurrence (extras recorded as `duplicates`).\n * - Canonical names the AI omitted are appended at the end in their original\n * order (recorded as `missing`).\n */\nexport function reconcileRanking(\n canonicalInOrder: string[],\n aiRanked: string[],\n): ReconcileResult {\n const canonical = new Set(canonicalInOrder);\n const order: string[] = [];\n const seen = new Set<string>();\n const invented: string[] = [];\n const duplicates: string[] = [];\n\n for (const name of aiRanked) {\n if (!canonical.has(name)) {\n invented.push(name);\n continue;\n }\n if (seen.has(name)) {\n duplicates.push(name);\n continue;\n }\n seen.add(name);\n order.push(name);\n }\n\n const missing = canonicalInOrder.filter((name) => !seen.has(name));\n order.push(...missing);\n\n return { order, missing, invented, duplicates };\n}\n\nfunction buildPrompt(auditMarkdown: string, feedback?: string): string {\n return `You are ranking the database entities of an application by how foundational they are, so a user can configure them starting from the ones they understand best.\n\nRank from MOST important to LEAST important:\n- HIGH: entities that many others depend on, and entities representing the primary concepts of the domain — the accounts, users, workspaces/tenants, and core business objects a developer would name first when describing the product.\n- LOW: peripheral entities — feature-specific records, integration/audit/logging details, join tables, and narrow or client-specific tables a developer would not have top of mind.\n\nUse the audit below as your only source of truth. The \"created_by\" relationships and how often an entity owns/spawns others are strong signals of importance.\n\nReturn EVERY entity name from the audit, each exactly once, ordered most-important first. Use the names exactly as written in the audit. Do not invent, rename, merge, or omit any entity.${feedback ? `\\n\\n${feedback}` : \"\"}\n\n--- ENTITY AUDIT ---\n${auditMarkdown}`;\n}\n\n/**\n * Ask the model to rank the audited entities by perceived importance and return\n * a `name -> rank index` map (0 = most important) covering every model.\n *\n * Best-effort: on an unrecoverable failure (the call throws, or the result is\n * still broken after one feedback retry) it returns an empty map, signalling the\n * caller to fall back to the default alphabetical ordering. Importance ranking is\n * a UX nicety and must never block recipe building.\n */\nexport async function rankEntitiesByImportance(\n models: AuditedModel[],\n auditMarkdown: string,\n model: LanguageModel,\n): Promise<Map<string, number>> {\n const canonical = models.map((m) => m.name);\n if (canonical.length === 0) return new Map();\n\n // A result is acceptable if the AI named most entities itself; if it dropped\n // a large fraction we retry once with explicit feedback before giving up.\n const acceptableMissing = Math.floor(canonical.length / 2);\n\n try {\n let reconciled = reconcileRanking(canonical, await callRanker(model, buildPrompt(auditMarkdown)));\n\n if (\n reconciled.missing.length > acceptableMissing ||\n reconciled.invented.length > 0 ||\n reconciled.duplicates.length > 0\n ) {\n const feedbackParts: string[] = [\"Your previous response had problems. Fix them:\"];\n if (reconciled.missing.length > 0)\n feedbackParts.push(`- You omitted these entities, include them: ${reconciled.missing.join(\", \")}`);\n if (reconciled.invented.length > 0)\n feedbackParts.push(`- These names are not in the audit, do not use them: ${reconciled.invented.join(\", \")}`);\n if (reconciled.duplicates.length > 0)\n feedbackParts.push(`- These were listed more than once, list each exactly once: ${reconciled.duplicates.join(\", \")}`);\n\n const retry = reconcileRanking(\n canonical,\n await callRanker(model, buildPrompt(auditMarkdown, feedbackParts.join(\"\\n\"))),\n );\n // Keep the retry only if it's actually better than the first attempt.\n if (retry.missing.length <= reconciled.missing.length) reconciled = retry;\n }\n\n return new Map(reconciled.order.map((name, i) => [name, i]));\n } catch (err) {\n console.warn(\n `[recipe-builder] Importance ranking failed, falling back to alphabetical order:\\n${formatException(err)}`,\n );\n return new Map();\n }\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 type { AuditedModel } from \"./entity-order\";\n\nexport type RecipePayload = Record<string, Record<string, unknown>[]>;\n\n/** Recursively collect every alias referenced via `{ _ref: \"...\" }` in a value. */\nfunction collectRefs(value: unknown, out: Set<string>): void {\n if (Array.isArray(value)) {\n for (const v of value) collectRefs(v, out);\n } else if (value !== null && typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n if (typeof obj._ref === \"string\") out.add(obj._ref);\n for (const v of Object.values(obj)) collectRefs(v, out);\n }\n}\n\n/**\n * Build the payload for testing a single entity: that entity plus every other\n * entity it depends on, emitted in dependency order (parents before children).\n *\n * The SDK resolves `_ref`s WITHIN the request body, so any alias a record\n * references must be declared by a record in the same request. The recipe agent\n * is free to `_ref` any already-completed entity (not just the audit's\n * `created_by` parents), so we can't rely on the audit chain alone — a `_ref`\n * the audit never recorded as a dependency would otherwise be missing from the\n * payload and fail with \"references unknown alias(es)\". We therefore include the\n * transitive closure of BOTH the audit's `created_by` owners AND the entities\n * whose aliases actually appear in the recipe data.\n */\nexport function buildSingleEntityRecipe(\n entityName: string,\n models: AuditedModel[],\n entityOrder: string[],\n allEntities: Record<string, EntityProgress>,\n): RecipePayload {\n const modelMap = new Map(models.map((m) => [m.name, m]));\n\n // Which entity declares each alias, from the data we've accepted so far.\n const aliasOwner = new Map<string, string>();\n for (const [name, entity] of Object.entries(allEntities)) {\n for (const rec of entity?.recipeData ?? []) {\n if (typeof rec._alias === \"string\") aliasOwner.set(rec._alias, name);\n }\n }\n\n const recipe: RecipePayload = {};\n const done = new Set<string>();\n const onStack = new Set<string>();\n\n function include(name: string): void {\n if (done.has(name) || onStack.has(name)) return; // skip done + break cycles\n onStack.add(name);\n\n const records = allEntities[name]?.recipeData ?? [];\n\n // Dependencies must be created first: audit-declared owners…\n for (const dep of modelMap.get(name)?.created_by ?? []) {\n if (entityOrder.includes(dep.owner)) include(dep.owner);\n }\n // …plus every entity whose alias this one actually references.\n const refs = new Set<string>();\n collectRefs(records, refs);\n for (const alias of refs) {\n const owner = aliasOwner.get(alias);\n if (owner && owner !== name) include(owner);\n }\n\n onStack.delete(name);\n done.add(name);\n // Insertion order = dependency order, since deps are added above.\n if (records.length > 0) recipe[name] = records;\n }\n\n include(entityName);\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","/**\n * Live schema grounding for the recipe builder.\n *\n * The SDK's `discover` action returns the SOURCE OF TRUTH for what each\n * factory accepts: every registered model with its field names, coarse\n * types, and — critically — which fields are required. (See the SDK's\n * `buildSchemaFromFactories` / `schemaToWire`.)\n *\n * Until now the recipe builder never consumed this: it guessed field\n * names and shapes from the markdown entity audit, so a factory whose\n * `inputSchema` required a tenant FK (e.g. `clientId`) — which the SDK\n * does NOT auto-inject — would fail with an opaque HTTP 500 and the only\n * feedback into the fix loop was that raw error. Grounding propose/revise/\n * triage in this schema replaces guessing with fact.\n */\nimport type { RecipePayload } from \"./recipe\";\nimport * as sdk from \"./http-client\";\nimport type { SdkClientConfig } from \"./http-client\";\n\n/** One field as reported by the SDK's discover response. */\nexport interface DiscoverField {\n name: string;\n /** Coarse type string: string | number | integer | boolean | timestamp | json. */\n type: string;\n isRequired: boolean;\n isId: boolean;\n hasDefault: boolean;\n}\n\nexport interface DiscoverModel {\n name: string;\n tableName: string;\n fields: DiscoverField[];\n}\n\nexport interface DiscoverSchema {\n /** Keyed by model name (matches the factory registry / audit model names). */\n models: Map<string, DiscoverModel>;\n /** The tenant/scope field the dashboard isolates on, e.g. \"organizationId\".\n * The SDK does NOT auto-inject it — factories own the write and the recipe\n * must supply it explicitly wherever a model declares it. */\n scopeField: string | null;\n}\n\n/** Parse the wire JSON from a discover response into a typed schema. Returns\n * null when the body doesn't look like a discover schema (defensive). */\nexport function parseDiscoverBody(body: unknown): DiscoverSchema | null {\n if (!body || typeof body !== \"object\") return null;\n const schema = (body as Record<string, unknown>).schema as Record<string, unknown> | undefined;\n if (!schema || typeof schema !== \"object\") return null;\n\n const rawModels = schema.models;\n if (!Array.isArray(rawModels)) return null;\n\n const models = new Map<string, DiscoverModel>();\n for (const m of rawModels) {\n if (!m || typeof m !== \"object\") continue;\n const mm = m as Record<string, unknown>;\n if (typeof mm.name !== \"string\") continue;\n const rawFields = Array.isArray(mm.fields) ? mm.fields : [];\n const fields: DiscoverField[] = [];\n for (const f of rawFields) {\n if (!f || typeof f !== \"object\") continue;\n const ff = f as Record<string, unknown>;\n if (typeof ff.name !== \"string\") continue;\n fields.push({\n name: ff.name,\n type: typeof ff.type === \"string\" ? ff.type : \"string\",\n isRequired: ff.isRequired === true,\n isId: ff.isId === true,\n hasDefault: ff.hasDefault === true,\n });\n }\n models.set(mm.name, { name: mm.name, tableName: typeof mm.tableName === \"string\" ? mm.tableName : mm.name, fields });\n }\n\n const scopeField = typeof schema.scopeField === \"string\" && schema.scopeField.length > 0\n ? schema.scopeField\n : null;\n\n return { models, scopeField };\n}\n\n/**\n * Fetch the live schema from the SDK endpoint. Best-effort: returns null on\n * any network/HTTP/parse failure so it can never block the recipe builder.\n * Discover reflects only the factories CURRENTLY registered, so call it fresh\n * as the developer wires up more entities rather than caching it forever.\n */\nexport async function fetchDiscoverSchema(config: SdkClientConfig): Promise<DiscoverSchema | null> {\n try {\n const res = await sdk.discover(config);\n if (!res.ok) return null;\n return parseDiscoverBody(res.body);\n } catch {\n return null;\n }\n}\n\n/** True for a field the recipe MUST supply: required, not the synthetic id,\n * and without a factory-side default. */\nfunction isMandatory(field: DiscoverField): boolean {\n return field.isRequired && !field.isId && !field.hasDefault;\n}\n\n/**\n * Render a model's field spec for an LLM prompt. Returns null when the model\n * isn't in the live schema (factory not registered yet) so callers can fall\n * back to the audit-derived schema instead of asserting a wrong one.\n */\nexport function renderModelSchema(schema: DiscoverSchema, modelName: string): string | null {\n const m = schema.models.get(modelName);\n if (!m) return null;\n\n const lines = m.fields\n .filter((f) => !f.isId)\n .map((f) => {\n const req = isMandatory(f) ? \"REQUIRED\" : f.hasDefault ? \"optional (has default)\" : \"optional\";\n const scopeNote = schema.scopeField && f.name === schema.scopeField\n ? \" ← scope/tenant field — the SDK does NOT auto-fill it; set it explicitly (use a { \\\"_ref\\\": \\\"...\\\" } to the scope entity)\"\n : \"\";\n return ` - ${f.name}: ${f.type} (${req})${scopeNote}`;\n });\n\n return `Live schema for \"${modelName}\" (from the SDK /discover endpoint — this is the SOURCE OF TRUTH; it overrides the entity audit when they disagree):\n${lines.join(\"\\n\")}\n\nEvery REQUIRED field above must be present on every record. Do not send fields that are not listed.`;\n}\n\nexport interface RecipeValidationProblem {\n model: string;\n /** Index of the offending record within its model's array. */\n recordIndex: number;\n message: string;\n}\n\n/**\n * Validate an assembled create payload against the live schema BEFORE sending\n * it, turning blind HTTP 500s into precise, local diagnostics.\n *\n * Conservative by design — it only flags problems it is sure about:\n * - a model present in the payload AND in the live schema that omits a\n * mandatory field (required, no default, not the id);\n * - a `_ref` whose alias is declared by no record in the same payload (the\n * SDK resolves refs within the request body).\n *\n * Models absent from the live schema (factory not registered yet) are skipped\n * — we can't assert their shape — so this never produces false positives for\n * not-yet-implemented factories.\n */\nexport function validateRecipeAgainstSchema(\n recipe: RecipePayload,\n schema: DiscoverSchema,\n): RecipeValidationProblem[] {\n const problems: RecipeValidationProblem[] = [];\n\n // Collect every alias declared anywhere in the payload.\n const declaredAliases = new Set<string>();\n for (const records of Object.values(recipe)) {\n for (const rec of records) {\n if (typeof rec._alias === \"string\") declaredAliases.add(rec._alias);\n }\n }\n\n for (const [modelName, records] of Object.entries(recipe)) {\n const model = schema.models.get(modelName);\n records.forEach((record, recordIndex) => {\n // Required-field check (only when we know the model's real shape).\n if (model) {\n for (const field of model.fields) {\n if (!isMandatory(field)) continue;\n const value = record[field.name];\n if (value === undefined || value === null) {\n problems.push({\n model: modelName,\n recordIndex,\n message: `missing required field \"${field.name}\" (${field.type})`,\n });\n }\n }\n }\n // _ref resolvability check (independent of whether the model is known).\n const refs = new Set<string>();\n collectRefs(record, refs);\n for (const alias of refs) {\n if (!declaredAliases.has(alias)) {\n problems.push({\n model: modelName,\n recordIndex,\n message: `_ref points at \"${alias}\", which no record in this payload declares with an _alias`,\n });\n }\n }\n });\n }\n\n return problems;\n}\n\nfunction collectRefs(value: unknown, out: Set<string>): void {\n if (Array.isArray(value)) {\n for (const v of value) collectRefs(v, out);\n } else if (value !== null && typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n if (typeof obj._ref === \"string\") {\n out.add(obj._ref);\n return;\n }\n for (const v of Object.values(obj)) collectRefs(v, out);\n }\n}\n\n/** Format validation problems into a server-error-shaped string the fix loop\n * can consume, mirroring how a real HTTP error body reads. */\nexport function formatValidationProblems(problems: RecipeValidationProblem[]): string {\n const byModel = new Map<string, string[]>();\n for (const p of problems) {\n const key = `${p.model}[${p.recordIndex}]`;\n if (!byModel.has(key)) byModel.set(key, []);\n byModel.get(key)!.push(p.message);\n }\n return [...byModel.entries()]\n .map(([key, msgs]) => `${key}: ${msgs.join(\"; \")}`)\n .join(\"\\n\");\n}\n","import { type LanguageModel, Output, generateText } from \"ai\";\nimport { z } from \"zod\";\nimport { formatException } from \"../../../core/errors\";\n\n/**\n * Which side of the test a failure originates from.\n *\n * - `recipe` — the test DATA we sent is wrong (a _ref points at a\n * non-existent alias, a bad field value, a missing/extra\n * field, a type mismatch). Regenerating the data can fix it,\n * so autofix is worth running.\n * - `implementation` — the developer's HANDLER code is wrong (an unregistered\n * factory, a bug in their insert/delete logic, a wrong\n * column/table name, a server crash). No amount of data\n * regeneration fixes this — the user must change code.\n * - `unclear` — not confidently attributable to either side.\n */\nexport type FailureSide = \"recipe\" | \"implementation\" | \"unclear\";\n\n/** Which leg of the test failed: UP (create test data) or DOWN (tear it down). */\nexport type FailurePhase = \"create\" | \"teardown\";\n\nexport interface FailureClassification {\n side: FailureSide;\n /** One plain-language sentence the user sees explaining the verdict. */\n reason: string;\n}\n\nconst classificationSchema = z.object({\n side: z\n .enum([\"recipe\", \"implementation\", \"unclear\"])\n .describe(\n \"recipe = the test data we sent is wrong and regenerating it could fix the failure; \" +\n \"implementation = the developer's handler/factory code is wrong and only a code change fixes it; \" +\n \"unclear = cannot confidently attribute the failure to either side.\",\n ),\n reason: z\n .string()\n .describe(\"One short, plain-language sentence explaining the verdict for the user. No code, no jargon dumps.\"),\n});\n\nexport interface ClassifyArgs {\n entityName: string;\n /** UP (create) or DOWN (teardown) — teardown failures skew strongly implementation-side. */\n phase: FailurePhase;\n /** HTTP status of the failed response, when the request got one (5xx skews implementation-side). */\n httpStatus?: number;\n /** The raw server error body or formatted exception string. */\n error: unknown;\n /** The recipe payload that was sent (so the model can judge whether different data would help). */\n recipe: unknown;\n /** The _alias values declared by already-created parent entities — the ONLY valid _ref targets. */\n validRefAliases?: string;\n /** What the entity audit recorded about how this entity is created (factory existence, owners). */\n entityAudit?: string;\n /** The live field schema for this entity from the SDK /discover endpoint, if\n * available — the source of truth for required fields and types. */\n liveSchema?: string;\n}\n\n/**\n * A primer on the system under test. Without this the model has no idea what an\n * \"Environment Factory\", a recipe, a _ref, or an UP/DOWN request even is, and\n * can't reason about which side of the contract broke.\n */\nconst PRIMER = `## Background — what you are looking at\n\nThe Autonoma SDK lets a developer seed and tear down test data through a single HTTP endpoint on their own backend (the \"Environment Factory\"). For each database entity the developer registers a *factory* with two functions: a create() that inserts records, and a teardown() that deletes them. Their handler code calls into their app's real service/ORM layer.\n\nA separate tool (not the developer) generates the *recipe*: JSON test data, one array of records per entity. Each record may carry an \"_alias\" (a unique handle, e.g. \"account_1\") and \"_ref\" fields ({ \"_ref\": \"account_1\" }) that point at an alias declared by an already-created parent entity. The tool sends this recipe to the endpoint:\n- An **UP** request asks the factory to create the records (calls create()).\n- A **DOWN** request asks the factory to tear them down (calls teardown()).\n\nSo a failure has exactly two possible origins, and your only job is to tell them apart:`;\n\nexport function buildClassifierPrompt(args: ClassifyArgs): string {\n const errorText = typeof args.error === \"string\" ? args.error : JSON.stringify(args.error, null, 2);\n const phaseLine =\n args.phase === \"teardown\"\n ? `This was a DOWN (teardown) request. Teardown runs the developer's delete logic against data the create() step already accepted, so teardown failures are usually implementation-side (wrong delete order, foreign-key cleanup bugs) rather than caused by the recipe.`\n : `This was an UP (create) request — the factory tried to insert the recipe records.`;\n const statusLine =\n args.httpStatus != null\n ? `HTTP status: ${args.httpStatus}. (A 5xx usually means the handler threw; a 4xx is more often a rejected payload, but use the error text — status alone is not decisive.)`\n : `No HTTP status (the request threw before a response — often a network/server-process problem, lean implementation or unclear).`;\n\n return `${PRIMER}\n\n- RECIPE DATA is wrong — the JSON the tool sent doesn't fit the developer's (correct) schema. Examples of the *kind* of problem (not an exhaustive list): the request body references an alias (_ref) that no record in THIS SAME request declares with an _alias, a field holds a value the backend rejects, a required field is missing or an unknown field was sent, or a value has the wrong type. These are fixable by regenerating the data — the developer's code is fine. NOTE: an error like \"references unknown alias(es): X\" is recipe-side whenever X is not declared by an _alias in the test data shown below — the SDK resolves _refs WITHIN the request body, so it does not matter whether X appears in the \"valid targets\" list (that list is historical context about other entities' own runs, NOT the contents of this request).\n- IMPLEMENTATION is wrong — the developer's own handler/factory code is broken. Examples of the *kind* of problem: the factory for this entity is not registered, the handler references a column or table that does not exist (even though the recipe never mentioned it), the insert/delete logic has a bug, or the server threw an unhandled exception. No change to the test data can fix this; the developer must edit code.\n\n## How to decide\n\nAsk: \"Would sending DIFFERENT, corrected test data — still matching the intended schema — plausibly make this request succeed?\"\n- If yes → **recipe**.\n- If the data shown below looks valid and the error points at the server's own logic, a missing factory, or a column/table the recipe never referenced → **implementation**.\n- If you genuinely cannot tell from the evidence → **unclear**. Prefer \"unclear\" over a confident guess; a wrong confident answer is worse than admitting uncertainty.\n\nCross-check the error against the actual data sent below before deciding. For an \"unknown alias\" error, look at whether a record in the test data declares that alias with an _alias — NOT at the valid-targets list. If the alias the error names is missing from (or spelled differently in) the data we sent, it is recipe-side, even when that alias appears in the valid-targets list.\n\n## Evidence\n\n${phaseLine}\n${statusLine}\n\nEntity: \"${args.entityName}\"\n\nValid _ref targets (aliases declared by already-created parent entities):\n${args.validRefAliases?.trim() || \"(none — this is a root entity with no parents to reference)\"}\n\nWhat the entity audit recorded about how \"${args.entityName}\" is created:\n${args.entityAudit?.trim() || \"(not available)\"}\n\n${args.liveSchema?.trim() || \"(no live schema available — the /discover endpoint was unreachable)\"}\n\nTest data sent:\n${JSON.stringify(args.recipe, null, 2)}\n\nError:\n${errorText}`;\n}\n\n/**\n * Ask the model whether a failure is recipe-side or implementation-side.\n *\n * Best-effort: any failure of the classifier itself resolves to `unclear`, which\n * the caller treats as \"show the user the full menu and let them decide.\" The\n * classifier must never block or crash the failure-handling path.\n */\nexport async function classifyFailure(model: LanguageModel, args: ClassifyArgs): Promise<FailureClassification> {\n try {\n const result = await generateText({\n model,\n prompt: buildClassifierPrompt(args),\n output: Output.object({ schema: classificationSchema }),\n });\n return result.output;\n } catch (err) {\n return { side: \"unclear\", reason: `Could not auto-triage this error (${formatException(err)}).` };\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 \"cross-spawn\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { LanguageModel } from \"ai\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { formatException } from \"../../../core/errors\";\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, type RecipePayload } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\nimport {\n fetchDiscoverSchema,\n renderModelSchema,\n validateRecipeAgainstSchema,\n formatValidationProblems,\n type DiscoverSchema,\n} from \"../discover-schema\";\nimport { classifyFailure, type FailurePhase } from \"./failure-classifier\";\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\n/**\n * Summarize the _alias values declared by already-completed entities, so a\n * revise/propose agent knows exactly which aliases it can target with _ref.\n * Without this the agent is blind to other entities and produces broken refs.\n */\nfunction summarizeCompletedAliases(\n completedEntities: Record<string, EntityProgress>,\n excludeName?: string,\n): string {\n return Object.entries(completedEntities)\n .filter(([name, e]) => name !== excludeName && e.recipeData && e.recipeData.length > 0)\n .map(([name, e]) => `${name}: aliases ${e.recipeData!.map((r) => r._alias ?? \"?\").join(\", \")}`)\n .join(\"\\n\");\n}\n\n/** A one-line summary of how the audit says an entity is created, used to ground\n * the failure classifier (e.g. so a \"no factory registered\" error is judgeable). */\nfunction summarizeEntityAudit(model?: AuditedModel): string | undefined {\n if (!model) return undefined;\n const parts = [`independently_created: ${model.independently_created}`];\n if (model.creation_function) parts.push(`creation function: ${model.creation_function}`);\n if (model.created_by.length > 0) parts.push(`created by: ${model.created_by.map((c) => c.owner).join(\", \")}`);\n if (model.side_effects?.length) parts.push(`side effects: ${model.side_effects.join(\", \")}`);\n return parts.join(\"; \");\n}\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 schemaSpec?: string,\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 = summarizeCompletedAliases(completedEntities, entityName);\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${schemaSpec ? `${schemaSpec}\\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\nProduce records for \"${entityName}\" ONLY — one object per record. Do not include records for other models; the tool assembles parent entities automatically.\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 completedEntities: Record<string, EntityProgress>,\n schemaSpec?: 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 const completedAliases = summarizeCompletedAliases(completedEntities, entityName);\n const aliasBlock = completedAliases\n ? `Aliases declared by already-created parent entities (these are the ONLY valid _ref targets):\\n${completedAliases}\\n`\n : `This is a root entity — it has no parent entities to _ref.\\n`;\n\n await runAgent(\n {\n id: `fix-${entityName}`,\n systemPrompt: `You are fixing recipe data based on user feedback (or a validation failure). 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- Return records for \"${entityName}\" ONLY — a flat JSON array, one object per record. NEVER group records by model name or nest other models (Client/User/etc.) inside this array. The tool assembles parent entities into the request automatically; your job is only this one entity's rows.\n- _alias fields must be unique identifiers (e.g., \"card_1\", \"transaction_1\")\n- _ref fields must reference an alias that ALREADY EXISTS on a parent entity — see the list of valid targets below. Never invent a _ref to an alias that isn't listed.\n- If the error says \"references unknown alias(es): X\", a _ref points at \"X\" but nothing being created declares it. Correct that _ref to one of the valid targets listed below (it's usually a typo, e.g. \"users_1\" vs \"user_1\"), or drop the reference if the field is optional. Do NOT leave a _ref pointing at an alias that isn't in the valid targets list.\n- Read scenarios.md to verify you're using correct alias names from parent entities\n- Field names and required fields must match the live schema below when present (it is the source of truth), otherwise 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:\n${JSON.stringify(current, null, 2)}\n\nWhat's wrong / what to change:\n${feedback}\n\n${aliasBlock}\n${schemaSpec ? `${schemaSpec}\\n` : \"\"}\nRead scenarios.md and entity-audit.md to understand the correct aliases and schema. Apply the change 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 completedEntities: Record<string, EntityProgress>,\n schemaSpec?: 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 // cross-spawn resolves editor launchers across platforms; a failure to\n // spawn (e.g. no `$EDITOR` and no `vi` on Windows) is reported and the\n // edit is skipped rather than aborting the whole recipe review.\n const launched = await new Promise<boolean>((resolve) => {\n const proc = spawn(editor, [tmpPath], { stdio: \"inherit\" });\n proc.on(\"close\", () => resolve(true));\n proc.on(\"error\", (err: Error) => {\n p.log.error(\n `Couldn't open ${editor} (${err.message}). Edit this file manually, then choose \"edit\" again: ${tmpPath}`,\n );\n resolve(false);\n });\n });\n\n if (!launched) continue;\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 proposed = await reviseRecipeData(\n entityName, entityIndex, totalEntities, proposed, (feedback as string).trim(),\n model, outputDir, completedEntities, schemaSpec,\n );\n }\n }\n}\n\ntype TestResult = \"success\" | \"skip\" | { feedback: string };\n\nexport function formatErrorContext(errorBody: unknown): string {\n if (errorBody == null) return \"\";\n const rendered = typeof errorBody === \"string\" ? errorBody : JSON.stringify(errorBody);\n return `\\nServer error: ${rendered}`;\n}\n\n/**\n * The most times we'll route a failure into the recipe-fix agent before we stop\n * offering it and hand control back to the user. Autofix regenerates the test\n * data; if that many rounds haven't resolved the failure, the data was never the\n * cause — it's a handler/code issue the agent can't touch.\n */\nexport const MAX_AUTOFIX_ATTEMPTS = 2;\n\n/** Mutable per-entity counter, threaded through a whole test cycle so auto- and\n * manual autofix rounds share one budget. */\nexport interface AutofixBudget {\n attempts: number;\n}\n\nexport interface FailureContext {\n model: LanguageModel;\n /** The payload that was sent — context for the failure classifier. */\n recipe: unknown;\n budget: AutofixBudget;\n /** Aliases declared by already-created parents — the valid _ref targets. */\n validRefAliases?: string;\n /** What the entity audit recorded about how this entity is created. */\n entityAudit?: string;\n /** This entity's live field schema from /discover, rendered for prompts. */\n liveSchema?: string;\n}\n\nfunction seedFeedbackFromError(errorContext: string, reason?: string): { feedback: string } {\n const triage = reason ? ` (Auto-triage: ${reason})` : \"\";\n return { feedback: `The request failed — read the error and fix the recipe data.${triage}${errorContext}` };\n}\n\nexport async function promptOnFailure(\n entityName: string,\n errorBody: unknown,\n ctx: FailureContext,\n phase: FailurePhase,\n httpStatus?: number,\n): Promise<\"retry\" | \"skip\" | { feedback: string }> {\n notify(\"Autonoma\", `${entityName} — failed, action needed`);\n const errorContext = formatErrorContext(errorBody);\n\n // Classify the failure for CONTEXT only. The verdict is informational — we hand\n // it to the fix agent and show it to the user, but it never gates which actions\n // are available. (Letting `side` decide that is exactly what hid the autofix on\n // self-evident recipe errors like \"references unknown alias(es)\".)\n const { reason } = await classifyFailure(ctx.model, {\n entityName,\n phase,\n httpStatus,\n error: errorBody,\n recipe: ctx.recipe,\n validRefAliases: ctx.validRefAliases,\n entityAudit: ctx.entityAudit,\n liveSchema: ctx.liveSchema,\n });\n\n // While there's budget, always hand the raw failure (plus the triage note as\n // context) straight to the agent and let it decide whether and how to fix the\n // recipe. No \"is this recipe-side?\" gate in front of it.\n if (ctx.budget.attempts < MAX_AUTOFIX_ATTEMPTS) {\n ctx.budget.attempts++;\n p.log.info(`Triage: ${reason}`);\n p.log.info(\n `Handing the failure to the agent to fix from the error (attempt ${ctx.budget.attempts}/${MAX_AUTOFIX_ATTEMPTS})...`,\n );\n return seedFeedbackFromError(errorContext, reason);\n }\n\n // Budget spent — the agent's fixes didn't resolve it, so it's most likely your\n // handler code. Hand control back, with every option available (nothing hidden).\n p.log.warn(`The agent tried ${MAX_AUTOFIX_ATTEMPTS}× without resolving it. Latest triage: ${reason}`);\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 {\n value: \"autofix\",\n label: \"Let the agent try again from the error\",\n hint: \"Hand the raw error back to the agent, no typing\",\n },\n { value: \"feedback\", label: \"Let me explain what's wrong\", hint: \"Describe the change and the agent will apply it\" },\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 if (action === \"autofix\") {\n ctx.budget.attempts++;\n return seedFeedbackFromError(errorContext, reason);\n }\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 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: RecipePayload,\n grounding: Omit<FailureContext, \"recipe\">,\n discoverSchema?: DiscoverSchema,\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 const failureCtx: FailureContext = { ...grounding, recipe };\n\n // UP with retry loop\n while (true) {\n // Pre-flight: catch schema violations locally, before bothering the server,\n // so a missing required field surfaces as a precise diagnostic instead of an\n // opaque HTTP 500. Only validates models the live schema actually knows.\n if (discoverSchema) {\n const problems = validateRecipeAgainstSchema(recipe, discoverSchema);\n if (problems.length > 0) {\n const errorBody = `Recipe failed local schema validation against /discover (not sent to the server):\\n${formatValidationProblems(problems)}`;\n p.log.error(errorBody);\n const action = await promptOnFailure(entityName, errorBody, failureCtx, \"create\");\n if (action === \"skip\") return \"skip\";\n if (action === \"retry\") continue;\n return action;\n }\n }\n\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:\\n${formatException(err)}`);\n const action = await promptOnFailure(entityName, formatException(err), failureCtx, \"create\");\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, failureCtx, \"create\", upResult.status);\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:\\n${formatException(err)}`);\n const action = await promptOnFailure(entityName, formatException(err), failureCtx, \"teardown\");\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, failureCtx, \"teardown\", downResult.status);\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 // Best-effort live schema from the SDK's /discover endpoint. It is the source\n // of truth for each factory's required fields and types, so we use it to\n // ground recipe generation instead of guessing from the markdown audit.\n // Refetched per use rather than cached: discover only reflects the factories\n // registered SO FAR, and that set grows as the developer wires up entities.\n async function loadLiveSchema(name: string): Promise<{ schema: DiscoverSchema | null; spec?: string }> {\n if (!state.sdkEndpointUrl || !state.sharedSecret) return { schema: null };\n const schema = await fetchDiscoverSchema({\n endpointUrl: state.sdkEndpointUrl,\n sharedSecret: state.sharedSecret,\n });\n if (!schema) return { schema: null };\n return { schema, spec: renderModelSchema(schema, name) ?? undefined };\n }\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 // Live schema for grounding propose/review (null until the endpoint is\n // configured — i.e. from the second entity onward, or a resumed run).\n const { spec: recipeSchemaSpec } = await loadLiveSchema(entityName);\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, recipeSchemaSpec,\n );\n }\n\n // B. User review\n if (!nonInteractive) {\n recipeData = await reviewRecipeData(entityName, i, total, recipeData, model, outputDir, state.entities, recipeSchemaSpec);\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 const DOCS_BASE = \"https://docs.agent.autonoma.app\";\n\n p.log.info(\n `Next: implement the ${entityName} factory. The block below is a copy-paste guide —\\n` +\n ` paste it into Claude Code (or your AI assistant) and it will write the factory in your codebase.\\n` +\n ` A factory teaches the Autonoma SDK how to create and tear down ${entityName} records using your app's own code.\\n` +\n ` Keep it local for now: implement it, run your app on localhost, and we'll test it live here. You deploy later.`,\n );\n\n p.note(instructions, `Implementation guide for ${entityName} (paste into your AI assistant)`, { format: codeNoteFormat });\n\n p.log.info(`Autonoma SDK docs: ${DOCS_BASE}/sdk/environment-factory`);\n\n if (i === 0) {\n p.log.info(\"This is your first factory — the guide includes one-time SDK setup. Later entities 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 app running locally with the ${entityName} factory wired up?`,\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 // Now that the endpoint is configured, pull the live schema once for the\n // whole test cycle: it grounds the classifier, pre-flight validation, and\n // any recipe fixes the agent makes from a failure.\n const { schema: discoverSchema, spec: liveSchemaSpec } = await loadLiveSchema(entityName);\n\n // One autofix budget per entity test cycle — auto- and manual autofix\n // rounds share it, so a wrongly \"recipe\"-classified failure can't loop forever.\n const autofixBudget: AutofixBudget = { attempts: 0 };\n // Grounding for the failure classifier: which _ref targets are valid, what\n // the audit knows about how this entity is created, and the live schema.\n const grounding: Omit<FailureContext, \"recipe\"> = {\n model,\n budget: autofixBudget,\n validRefAliases: summarizeCompletedAliases(state.entities, entityName),\n entityAudit: summarizeEntityAudit(models.find((m) => m.name === entityName)),\n liveSchema: liveSchemaSpec,\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, grounding, discoverSchema ?? undefined);\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, state.entities, liveSchemaSpec,\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 { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { LanguageModel } from \"ai\";\nimport { notify } from \"../../../core/notify\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { formatException } from \"../../../core/errors\";\nimport { buildReadFileTool } from \"../../../tools\";\nimport { codeNoteFormat } from \"../../../core/highlight\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { saveRecipeState } from \"../state\";\nimport type { AuditedModel } from \"../entity-order\";\nimport { buildFullRecipe, type RecipePayload } from \"../recipe\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\nimport {\n fetchDiscoverSchema,\n renderModelSchema,\n validateRecipeAgainstSchema,\n formatValidationProblems,\n} from \"../discover-schema\";\n\n/**\n * Revise the entire recipe based on user feedback after they reviewed the app.\n * Unlike the per-entity revise, this agent sees the whole recipe so it can fix\n * issues that span entities (e.g. cross-references between records).\n */\nasync function reviseFullRecipe(\n current: RecipePayload,\n feedback: string,\n model: LanguageModel,\n outputDir: string,\n entityOrder: string[],\n schemaSpec?: string,\n): Promise<RecipePayload | undefined> {\n let revised: RecipePayload | undefined;\n\n const finishTool = tool({\n description: \"Submit the revised full recipe: an object mapping each entity name to its array of records.\",\n inputSchema: z.object({\n recipe: z.record(z.string(), z.array(z.record(z.string(), z.unknown()))),\n }),\n execute: async (input) => {\n revised = input.recipe;\n return { done: true };\n },\n });\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"revise:full-recipe\", 20);\n\n await runAgent(\n {\n id: \"revise-full-recipe\",\n systemPrompt: `You are revising a full test-data recipe based on user feedback after they reviewed the app populated with this data.\n\nThe recipe is an object mapping entity names to arrays of records. Records use:\n- _alias: a unique id for a record so other records can point to it\n- _ref: { \"_ref\": \"alias\" } points to a parent record's _alias\n\nRules:\n- Apply the user's feedback across whatever entities it touches.\n- Keep _ref values pointing to aliases that actually exist in the recipe. Never invent a _ref to a missing alias.\n- Entities are created in this order (parents first): ${entityOrder.join(\" → \")}. A record may only _ref an alias declared by an entity earlier in that order.\n- Field names, types, and required fields must match the live schema below when present (it is the source of truth), otherwise the schema in entity-audit.md.\n- Read scenarios.md and entity-audit.md from the output directory as needed.\n${schemaSpec ? `\\n${schemaSpec}\\n` : \"\"}\nReturn the COMPLETE revised recipe (all entities, not just the changed ones) via finish.`,\n model,\n maxSteps: 20,\n tools: (_heartbeat: () => void) => ({\n read_output: buildReadFileTool(outputDir),\n finish: finishTool,\n }),\n onStepFinish,\n },\n `The user reviewed the app with this test data and said it doesn't look right.\n\nCurrent full recipe:\n${JSON.stringify(current, null, 2)}\n\nUser feedback:\n\"${feedback}\"\n\nRevise the recipe to address the feedback, then call finish with the complete updated recipe.`,\n () => revised,\n );\n logger.summary();\n\n return revised;\n}\n\nasync function teardown(sdkConfig: SdkClientConfig, refsToken: string | undefined, successMessage: string): Promise<boolean> {\n if (!refsToken) return true;\n\n p.log.step(\"[Full validation] Tearing down all entities...\");\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:\\n${formatException(err)}`);\n return false;\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 p.log.success(successMessage);\n return true;\n}\n\nexport async function runFullValidation(\n state: RecipeBuilderState,\n _models: AuditedModel[],\n outputDir: string,\n model: LanguageModel,\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 // By this phase every factory is registered, so /discover returns the full\n // schema. Use it to ground revisions and to flag schema violations up front.\n const discoverSchema = await fetchDiscoverSchema(sdkConfig);\n const fullSchemaSpec = discoverSchema\n ? state.entityOrder.map((name) => renderModelSchema(discoverSchema, name)).filter(Boolean).join(\"\\n\\n\") || undefined\n : undefined;\n\n let fullRecipe = buildFullRecipe(state.entityOrder, state.entities);\n\n // UP → review → (teardown) → approve or revise-and-retry loop\n while (true) {\n if (discoverSchema) {\n const problems = validateRecipeAgainstSchema(fullRecipe, discoverSchema);\n if (problems.length > 0) {\n p.log.warn(\n `Heads up — the recipe has likely schema problems (from /discover); the full UP may fail:\\n${formatValidationProblems(problems)}`,\n );\n }\n }\n\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:\\n${formatException(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 if (p.isCancel(looksGood)) throw new Error(\"Cancelled\");\n\n // Always tear down the data we just created before deciding the next step.\n const torndown = await teardown(\n sdkConfig,\n refsToken,\n looksGood\n ? \"Full lifecycle works. All data was created and torn down cleanly.\"\n : \"Tore down the test data so we can regenerate it.\",\n );\n if (!torndown) return false;\n\n if (looksGood) return true;\n\n // Not right: collect feedback, revise the FULL recipe, and retry.\n const feedback = await p.text({\n message: \"What's wrong with the test data? Describe what to change.\",\n placeholder: \"e.g. accounts need realistic balances, transactions should reference the right account...\",\n });\n if (p.isCancel(feedback) || !(feedback as string).trim()) {\n p.log.info(\"No feedback given. You can edit recipe.json manually and re-run with --resume.\");\n return false;\n }\n\n p.log.info(\"Revising the full recipe based on your feedback...\");\n const revised = await reviseFullRecipe(fullRecipe, (feedback as string).trim(), model, outputDir, state.entityOrder, fullSchemaSpec);\n if (!revised) {\n p.log.warn(\"Couldn't revise automatically. Edit recipe.json manually and re-run with --resume.\");\n return false;\n }\n\n // Persist the revised records back into state, then rebuild and retry.\n for (const [name, records] of Object.entries(revised)) {\n if (state.entities[name]) {\n state.entities[name]!.recipeData = records;\n }\n }\n await saveRecipeState(outputDir, state);\n fullRecipe = buildFullRecipe(state.entityOrder, state.entities);\n\n p.note(JSON.stringify(fullRecipe, null, 2), \"Revised recipe — re-running full validation\", { format: codeNoteFormat });\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 { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport * 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 { rankEntitiesByImportance } from \"./entity-relevance\";\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 /** User guidance from a pipeline-level retry. The recipe builder has its own\n * per-entity recovery prompts, so this is accepted but currently unused. */\n retryGuidance?: string;\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 // Prefer the shared secret provided by onboarding (the application's secret\n // from the dashboard) so the deployment, dashboard, and CLI all sign with the\n // same key. The entity loop only generates a fresh one when none was provided.\n if (state.sharedSecret == null && input.config.sharedSecret != null) {\n state.sharedSecret = input.config.sharedSecret;\n await saveRecipeState(input.outputDir, state);\n }\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 let importanceRank: Map<string, number> | undefined;\n try {\n const auditMarkdown = await readFile(join(input.outputDir, \"entity-audit.md\"), \"utf-8\");\n importanceRank = await rankEntitiesByImportance(models, auditMarkdown, model);\n } catch {\n // Ranking is a UX nicety; on any failure fall back to alphabetical order.\n importanceRank = undefined;\n }\n\n const entityOrder = resolveEntityOrder(models, importanceRank);\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 core entities first, 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, model);\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, formatRetryGuidance, runAgent} from \"../../core/agent\";\nimport {formatException} from \"../../core/errors\";\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 retryGuidance?: 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 : \"\") + formatRetryGuidance(input.retryGuidance);\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 console.log(` [chunk] Agent error (will retry next chunk):\\n${formatException(err)}`);\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 console.error(`Journey generator error:\\n${formatException(err)}`);\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 { setGlobalEnv, getGlobalEnvPath } from \"./core/global-env\";\nimport { installInterruptHandler, restoreTerminal } from \"./core/interrupt\";\nimport { track, trackError, flushAnalytics } from \"./core/analytics\";\nimport { formatException, describeKnownError, supportReference, isUserCancellation } from \"./core/errors\";\n\n// tsup emits source maps; ask Node to apply them so any stack that does reach\n// our own code points at src/* instead of the bundled dist/index.js.\nprocess.setSourceMapsEnabled(true);\nimport { notify } from \"./core/notify\";\nimport { uploadArtifacts } from \"./core/upload\";\nimport { loadGitInfo, readGitInfo, saveGitInfo } from \"./core/git\";\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: \"Find your pages\",\n kb: \"Build a knowledge base\",\n entityAudit: \"Map your data models\",\n scenarioRecipe: \"Design test scenarios\",\n recipeBuilder: \"Set up test data\",\n testGenerator: \"Generate the tests\",\n};\n\n// One-line plain-language summary per step, used in the upfront overview and the\n// \"continue?\" prompts so it's always clear what's coming before it runs.\nconst STEP_SUMMARIES: Record<StepName, string> = {\n pagesFinder: \"Map every page and route in your app.\",\n kb: \"Learn your app's features, flows, and UI patterns.\",\n entityAudit: \"Find what your app stores (users, orgs, ...) and how each one is created.\",\n scenarioRecipe: \"Decide the realistic data each test will run against.\",\n recipeBuilder: \"Wire up small helpers that create and clean up that data in your database.\",\n testGenerator: \"Write the end-to-end tests, covering every page and feature.\",\n};\n\nconst STEP_INTROS: Record<StepName, string> = {\n pagesFinder:\n \"Scanning your codebase to find every page and route, so we know the full surface area that needs test coverage.\",\n kb: \"Reading those pages to learn your app's features, flows, and UI patterns - the context everything after this builds on.\",\n entityAudit:\n \"Finding the things your app stores (users, organizations, orders, ...) and how each one gets created, so we can generate realistic test data for them.\",\n scenarioRecipe:\n \"Designing the data each test will run against - concrete, realistic values that match how your app actually uses them.\",\n recipeBuilder:\n \"Helping you wire up small helpers that create and clean up test data in your own database. We give you a copy-paste guide for each one and test it live against your app running locally - you deploy later, once everything passes.\",\n testGenerator:\n \"Writing the actual end-to-end tests, covering every page and feature with depth 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 retryGuidance?: string,\n): Promise<PipelineState> {\n const label = STEP_LABELS[step];\n p.note(STEP_INTROS[step], `Step: ${label}`);\n\n const stepStartedAt = Date.now();\n track(\"cli_step_started\", { step });\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 retryGuidance,\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 retryGuidance,\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 retryGuidance,\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 retryGuidance,\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 retryGuidance,\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 trackError(new Error(result.summary), { step, source: \"step_result\" });\n }\n } else {\n state = await markStep(outputDir, state, step, \"done\");\n p.log.success(`Completed: ${label}`);\n }\n } catch (err) {\n // The user deliberately stopped (Ctrl+C / \"cancel\" at a prompt). That's not\n // a failure: let the run-level handler save progress and exit quietly, and\n // don't report it to error tracking, where it would look like a bug.\n if (isUserCancellation(err)) throw err;\n state = await markStep(outputDir, state, step, \"failed\");\n const known = describeKnownError(err);\n if (known) {\n // A recognized, actionable failure — the raw stack is library-internal\n // noise here, so we show the fix instead.\n p.log.error(`Failed: ${label} — ${known.title}`);\n p.log.info(known.hint);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n p.log.error(`Failed: ${label} — ${message}`);\n // Full stack so users can copy-paste it when reporting the issue.\n console.error(`\\x1b[2m${formatException(err)}\\x1b[0m`);\n // One short line that maps this failure to its analytics event(s).\n console.error(`\\x1b[2m${supportReference({ step })}\\x1b[0m`);\n p.log.info(\"If you report this, please include the error output above.\");\n }\n trackError(err, { step, source: \"step_exception\" });\n }\n\n track(\"cli_step_completed\", {\n step,\n status: state.steps[step],\n duration_ms: Date.now() - stepStartedAt,\n });\n\n return state;\n}\n\ntype FailureAction = { kind: \"retry\"; guidance?: string } | { kind: \"exit\" };\n\nasync function promptStepFailure(label: string): Promise<FailureAction> {\n notify(\"Autonoma\", `${label} failed — action needed`);\n\n const action = await p.select({\n message: \"This step failed. What would you like to do?\",\n options: [\n { value: \"retry\", label: \"Retry this step\", hint: \"Run it again from the top\" },\n { value: \"guidance\", label: \"Retry with guidance\", hint: \"Tell the agent what went wrong or what to focus on\" },\n { value: \"exit\", label: \"Stop here (progress saved)\", hint: \"Resume later with --resume\" },\n ],\n });\n\n if (p.isCancel(action) || action === \"exit\") return { kind: \"exit\" };\n if (action === \"retry\") return { kind: \"retry\" };\n\n const guidance = await p.text({\n message: \"What should the agent do differently?\",\n placeholder: \"e.g. the part that failed, or what to focus on\",\n });\n if (p.isCancel(guidance)) return { kind: \"exit\" };\n\n const trimmed = (guidance as string).trim();\n return { kind: \"retry\", guidance: trimmed || undefined };\n}\n\n// A failed step should never hard-stop an interactive run — the user gets to\n// retry (optionally steering the agent) until it passes or they bail out.\nasync function runStepWithRecovery(\n step: StepName,\n outputDir: string,\n state: PipelineState,\n config: ReturnType<typeof loadConfig>,\n projectContext?: ProjectContext,\n nonInteractive?: boolean,\n): Promise<PipelineState> {\n let guidance: string | undefined;\n\n while (true) {\n state = await runStep(step, outputDir, state, config, projectContext, nonInteractive, guidance);\n\n if (state.steps[step] !== \"failed\" || nonInteractive) return state;\n\n const action = await promptStepFailure(STEP_LABELS[step]);\n if (action.kind === \"exit\") return state;\n\n guidance = action.guidance;\n track(\"cli_step_retried\", { step, with_guidance: guidance != null });\n }\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\n/**\n * Make sure an OpenRouter API key is available before we ask anything else.\n * If it's already in the environment (shell, project .env, or global\n * ~/.autonoma/.env) we use it silently. Otherwise we prompt for it as the very\n * first input and persist it to the global env so it's reused on future runs.\n * Returns false if the user cancels.\n */\nasync function ensureOpenRouterKey(nonInteractive?: boolean): Promise<boolean> {\n if (process.env.OPENROUTER_API_KEY) return true;\n\n if (nonInteractive) {\n p.log.error(\n \"OPENROUTER_API_KEY is not set. Set it in your environment or run interactively once to save it.\",\n );\n return false;\n }\n\n p.log.info(\"You'll need an OpenRouter API key to run the planner. Get one at https://openrouter.ai/keys\");\n\n const key = await p.password({\n message: \"Paste your OpenRouter API key\",\n validate: (value) => ((value ?? \"\").trim().length === 0 ? \"API key cannot be empty\" : undefined),\n });\n\n if (p.isCancel(key)) return false;\n\n setGlobalEnv(\"OPENROUTER_API_KEY\", key.trim());\n p.log.success(`Saved your API key to ${getGlobalEnvPath()} — you won't be asked again.`);\n return true;\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 // ESC no longer exits; Ctrl+C twice (within 3s) does, with a resume hint.\n const resumeCommand =\n `autonoma-planner --resume` + (args.project ? ` --project ${args.project}` : \"\");\n installInterruptHandler({\n onExit: () => {\n track(\"cli_run_exited\");\n restoreTerminal();\n console.log(\"\");\n p.log.warn(`Your progress is saved. To resume, run:\\n ${resumeCommand}`);\n void flushAnalytics().finally(() => process.exit(0));\n },\n });\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 nonInteractive = !!args[\"non-interactive\"];\n if (!(await ensureOpenRouterKey(nonInteractive))) {\n p.log.warn(\"Cancelled.\");\n return;\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\n track(\"cli_run_started\", { model: modelName, non_interactive: nonInteractive });\n\n const outputDir = await ensureOutputDir(config.projectSlug);\n let state = await loadState(outputDir);\n\n // Record the commit the analysis is based on, once, on the first run - so a\n // --resume keeps the original commit and the upload can report it to Autonoma.\n if ((await loadGitInfo(outputDir)) == null) {\n const gitInfo = await readGitInfo(config.projectRoot);\n if (gitInfo != null) {\n await saveGitInfo(outputDir, gitInfo);\n p.log.info(`Git commit: ${gitInfo.sha.slice(0, 8)}${gitInfo.dirty ? \" (working tree dirty)\" : \"\"}`);\n }\n }\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.note(\n `${outputDir}\\n\\n` +\n `All generated files (knowledge base, scenarios, recipe, tests) live here.\\n` +\n `It's a hidden folder in your home directory — in Finder/Explorer use \"Go to folder\"\\n` +\n `or reveal hidden files (macOS: Cmd+Shift+. ) to see it.`,\n \"Output folder\",\n );\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 runStepWithRecovery(targetStep, outputDir, state, config, projectContext, nonInteractive);\n if (state.steps[targetStep] === \"failed\") {\n const retryCommand =\n `autonoma-planner --step ${targetStep}` + (args.project ? ` --project ${args.project}` : \"\");\n p.log.warn(`Your progress is saved. To retry this step, run:\\n ${retryCommand}`);\n process.exitCode = 1;\n }\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 // Up-front overview so it's clear what each step does before any of them run.\n p.note(\n steps.map((s, idx) => `${idx + 1}. ${STEP_LABELS[s]} - ${STEP_SUMMARIES[s]}`).join(\"\\n\"),\n \"Here's the plan\",\n );\n\n try {\n for (let i = startIdx; i < steps.length; i++) {\n const step = steps[i]!;\n state = await runStepWithRecovery(step, outputDir, state, config, projectContext, nonInteractive);\n\n if (state.steps[step] === \"paused\") {\n break;\n }\n\n // Only reached when the user chose to stop after a failure, or in\n // non-interactive mode where there's nobody to ask.\n if (state.steps[step] === \"failed\") {\n p.log.error(\"Pipeline stopped due to failure.\");\n p.log.warn(`Your progress is saved. To retry this step, run:\\n ${resumeCommand}`);\n process.exitCode = 1;\n break;\n }\n\n // Pages Finder runs silently and continues on its own — there's nothing\n // actionable to confirm at that point, so we skip the prompt after it.\n const skipConfirmAfter: StepName[] = [\"pagesFinder\"];\n\n if (i < steps.length - 1 && !nonInteractive && !skipConfirmAfter.includes(step)) {\n const nextStep = steps[i + 1]!;\n const shouldContinue = await p.confirm({\n message: `Next: ${STEP_LABELS[nextStep]} - ${STEP_SUMMARIES[nextStep]}\\nContinue?`,\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 (isUserCancellation(err)) {\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 const stepsDone = Object.values(state.steps).filter((s) => s === \"done\").length;\n track(\"cli_run_completed\", { steps_done: stepsDone });\n\n // Only upload once the whole pipeline finished — a paused/failed run has\n // incomplete artifacts and would publish a half-built test suite.\n const allStepsDone = Object.values(state.steps).every((s) => s === \"done\");\n if (allStepsDone) {\n try {\n await uploadArtifacts(config, outputDir);\n track(\"cli_artifacts_uploaded\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n p.log.error(`Failed to upload artifacts: ${message}`);\n console.error(`\\x1b[2m${formatException(err)}\\x1b[0m`);\n console.error(`\\x1b[2m${supportReference({ phase: \"artifact_upload\" })}\\x1b[0m`);\n p.log.info(`Your artifacts are saved in ${outputDir}. Re-run the CLI to retry the upload.`);\n track(\"cli_artifacts_upload_failed\", { message });\n trackError(err, { source: \"artifact_upload\" });\n }\n }\n\n p.outro(\"Done\");\n}\n\nmain()\n .then(() => flushAnalytics())\n .catch(async (err) => {\n // A cancellation that bubbled all the way up — exit quietly without a stack\n // or an error-tracking event; the user chose to stop.\n if (isUserCancellation(err)) {\n await flushAnalytics();\n process.exit(0);\n }\n const known = describeKnownError(err);\n if (known) {\n console.error(`\\x1b[31m${known.title}\\x1b[0m`);\n console.error(known.hint);\n } else {\n console.error(err);\n console.error(`\\x1b[2m${supportReference()}\\x1b[0m`);\n }\n trackError(err, { source: \"uncaught\" }, false);\n await flushAnalytics();\n process.exit(1);\n });\n","import { resolve, join } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport { loadGlobalEnv } from \"./core/global-env\";\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 // Precedence: real shell env > project .env > global ~/.autonoma/.env.\n // Each loader only sets a key if it isn't already present, so loading the\n // project env first lets it win over the global fallback.\n loadProjectEnv(projectRoot);\n loadGlobalEnv();\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 // Endpoint the CLI talks to. Defaults to production; override with\n // AUTONOMA_API_URL to point at an alpha/preview host (alpha-<sha>.autonoma.app, ...).\n autonomaApiUrl: process.env.AUTONOMA_API_URL ?? \"https://agent.autonoma.app\",\n autonomaApiToken: process.env.AUTONOMA_API_TOKEN,\n autonomaGenerationId: process.env.AUTONOMA_GENERATION_ID,\n };\n}\n","import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\nconst GLOBAL_ENV_PATH = join(AUTONOMA_HOME, \".env\");\n\nexport function getGlobalEnvPath(): string {\n return GLOBAL_ENV_PATH;\n}\n\nfunction parseEnvContent(content: string): Record<string, string> {\n const out: Record<string, string> = {};\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 (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[key] = value;\n }\n return out;\n}\n\n/**\n * Load `~/.autonoma/.env` into process.env as a fallback. Existing process.env\n * values (real shell env, project .env loaded earlier) always win.\n */\nexport function loadGlobalEnv(): void {\n let content: string;\n try {\n content = readFileSync(GLOBAL_ENV_PATH, \"utf-8\");\n } catch {\n return;\n }\n for (const [key, value] of Object.entries(parseEnvContent(content))) {\n if (!(key in process.env)) {\n process.env[key] = value;\n }\n }\n}\n\n/**\n * Upsert a key in `~/.autonoma/.env` and reflect it in process.env immediately.\n * Preserves other lines/comments in the file.\n */\nexport function setGlobalEnv(key: string, value: string): void {\n mkdirSync(AUTONOMA_HOME, { recursive: true });\n\n let lines: string[] = [];\n try {\n lines = readFileSync(GLOBAL_ENV_PATH, \"utf-8\").split(\"\\n\");\n } catch {\n lines = [];\n }\n\n const serialized = `${key}=${value}`;\n let replaced = false;\n lines = lines.map((line) => {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\") || !trimmed.includes(\"=\")) return line;\n const lineKey = trimmed.slice(0, trimmed.indexOf(\"=\")).trim();\n if (lineKey === key) {\n replaced = true;\n return serialized;\n }\n return line;\n });\n\n if (!replaced) {\n if (lines.length > 0 && lines[lines.length - 1]!.trim() === \"\") {\n lines.splice(lines.length - 1, 0, serialized);\n } else {\n lines.push(serialized);\n }\n }\n\n const output = lines.join(\"\\n\").replace(/\\n*$/, \"\\n\");\n writeFileSync(GLOBAL_ENV_PATH, output, { encoding: \"utf-8\", mode: 0o600 });\n\n process.env[key] = value;\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 readline from \"node:readline\";\nimport { settings } from \"@clack/core\";\n\nconst DIM = \"\\x1b[2m\";\nconst RESET = \"\\x1b[0m\";\nconst SHOW_CURSOR = \"\\x1b[?25h\";\n\nconst EXIT_HINT = `${DIM}(press Ctrl+C again to exit)${RESET}`;\nconst ARM_WINDOW_MS = 3000;\n// If the graceful exit (analytics flush -> process.exit) hasn't terminated the\n// process within this window, bail unconditionally. onExit defers the real\n// process.exit behind an async flush; if that chain ever fails to resolve, this\n// is what guarantees the CLI still closes on a plain double-tap.\nconst FORCE_EXIT_MS = 2500;\n\nlet installed = false;\nlet armed = false;\nlet armTimer: ReturnType<typeof setTimeout> | null = null;\nlet onExit: (() => void) | null = null;\nlet quitting = false;\n\nfunction disarm(): void {\n if (armTimer) clearTimeout(armTimer);\n armTimer = null;\n armed = false;\n}\n\n/** Last-resort synchronous exit. Never waits on a promise or the event loop. */\nfunction forceExit(): void {\n restoreTerminal();\n // 130 = 128 + SIGINT, the conventional code for \"terminated by Ctrl+C\".\n process.exit(130);\n}\n\nfunction handleInterrupt(): void {\n // A graceful exit is already underway. Don't just swallow the signal — if the\n // async flush in onExit stalled, the user is now stuck with no way out. Treat\n // any further press as \"get me out NOW\" and exit synchronously, bypassing the\n // flush entirely.\n if (quitting) {\n forceExit();\n return;\n }\n\n if (armed) {\n quitting = true;\n disarm();\n // Failsafe: onExit hands off the real exit to an async analytics flush. If\n // that never lands process.exit, force it. unref so the timer itself can't\n // keep the process alive past a clean exit.\n setTimeout(forceExit, FORCE_EXIT_MS).unref?.();\n onExit?.();\n return;\n }\n // First press: arm a short window and tell the user how to actually exit.\n // Claude Code-style: a second Ctrl+C within the window quits; otherwise it\n // disarms and the run continues untouched.\n armed = true;\n process.stderr.write(`\\n${EXIT_HINT}\\n`);\n armTimer = setTimeout(disarm, ARM_WINDOW_MS);\n}\n\n/**\n * Install Ctrl+C double-press handling and neuter ESC-as-exit.\n *\n * - ESC no longer cancels prompts (the alias is removed).\n * - Ctrl+C requires two presses within a 3s window to quit. The first press\n * shows a hint; if no second press lands, the run continues.\n *\n * Works both while a clack prompt owns stdin (via a SIGINT listener injected\n * onto each readline interface) and between prompts (via process SIGINT).\n */\nexport function installInterruptHandler(opts: { onExit: () => void }): void {\n onExit = opts.onExit;\n if (installed) return;\n installed = true;\n\n // ESC should do nothing. clack maps \"escape\" -> \"cancel\" by default and\n // updateSettings can't remove an existing alias, so delete it on the live map.\n settings.aliases.delete(\"escape\");\n\n // Between prompts (raw mode off), Ctrl+C arrives as a normal process signal.\n process.on(\"SIGINT\", handleInterrupt);\n\n // During a clack prompt, readline owns stdin in raw mode. Node's readline\n // closes the interface on Ctrl+C ONLY when it has no \"SIGINT\" listener; if a\n // listener exists it emits \"SIGINT\" and leaves the prompt running. So inject\n // one onto every interface clack creates.\n const original = readline.createInterface.bind(readline);\n readline.createInterface = ((...args: Parameters<typeof readline.createInterface>) => {\n const iface = original(...args);\n iface.on(\"SIGINT\", handleInterrupt);\n return iface;\n }) as typeof readline.createInterface;\n}\n\n/** Best-effort terminal restore before an abrupt exit. */\nexport function restoreTerminal(): void {\n try {\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n } catch {}\n process.stdout.write(SHOW_CURSOR);\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename, join, relative } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { glob } from \"glob\";\nimport type { AppConfig } from \"../config\";\nimport { loadGitInfo } from \"./git\";\n\ninterface UploadFile {\n name: string;\n content: string;\n folder?: string;\n}\n\n// Mirrors the artifacts the web UI used to accept when the user uploaded the\n// `~/.autonoma/<app>/` folder by hand. `recipe.json` is intentionally excluded:\n// it is submitted through the versioned scenario-recipe endpoint during the\n// recipe-builder step (see agents/04-recipe-builder/phases/submit.ts), and the\n// generic artifacts endpoint rejects it.\nconst ARTIFACT_FILES = [\"AUTONOMA.md\", \"scenarios.md\", \"entity-audit.md\"];\n\nasync function readArtifacts(outputDir: string): Promise<UploadFile[]> {\n const files: UploadFile[] = [];\n for (const name of ARTIFACT_FILES) {\n try {\n const content = await readFile(join(outputDir, name), \"utf-8\");\n files.push({ name, content });\n } catch {\n // Not every run produces every artifact (e.g. no entity audit); skip\n // the ones that aren't on disk.\n }\n }\n return files;\n}\n\nasync function readTestCases(outputDir: string): Promise<UploadFile[]> {\n const testsDir = join(outputDir, \"qa-tests\");\n const matches = await glob(\"**/*.md\", { cwd: testsDir, nodir: true });\n\n const files: UploadFile[] = [];\n for (const match of matches) {\n const name = basename(match);\n if (name === \"INDEX.md\") continue;\n\n const content = await readFile(join(testsDir, match), \"utf-8\");\n const folderPath = relative(\".\", match).split(\"/\").slice(0, -1).join(\"/\");\n files.push({ name, content, folder: folderPath.length > 0 ? folderPath : undefined });\n }\n return files;\n}\n\nasync function postJson(url: string, token: string, body: unknown): Promise<void> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Upload failed (HTTP ${res.status}): ${text}`);\n }\n}\n\nasync function patchJson(url: string, token: string, body: unknown): Promise<void> {\n const res = await fetch(url, {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Failed to mark setup complete (HTTP ${res.status}): ${text}`);\n }\n}\n\n/**\n * Uploads the generated artifacts (test cases + knowledge base + scenarios) to\n * the Autonoma backend at the end of a run, then marks the setup complete so\n * the onboarding UI auto-advances. The recipe is submitted separately during\n * the recipe-builder step.\n *\n * No-ops when the upload credentials are not configured, so the CLI still runs\n * standalone (outside onboarding) and just leaves the artifacts on disk.\n */\nexport async function uploadArtifacts(config: AppConfig, outputDir: string): Promise<void> {\n const { autonomaApiUrl, autonomaApiToken, autonomaGenerationId } = config;\n\n if (autonomaApiUrl == null || autonomaApiToken == null || autonomaGenerationId == null) {\n p.log.info(\n \"Autonoma upload credentials not configured — artifacts saved locally only. \" +\n `They live in ${outputDir}.`,\n );\n return;\n }\n\n const baseUrl = autonomaApiUrl.replace(/\\/+$/, \"\");\n const setupUrl = `${baseUrl}/v1/setup/setups/${autonomaGenerationId}`;\n\n p.log.step(\"Uploading artifacts to Autonoma...\");\n\n const [testCases, artifacts, gitInfo] = await Promise.all([\n readTestCases(outputDir),\n readArtifacts(outputDir),\n loadGitInfo(outputDir),\n ]);\n\n // commitSha lets the backend stamp the resulting snapshot (head_sha) and the\n // branch (last_handled_sha) with the commit the suite was generated from.\n await postJson(`${setupUrl}/artifacts`, autonomaApiToken, { testCases, artifacts, commitSha: gitInfo?.sha });\n await patchJson(setupUrl, autonomaApiToken, { status: \"completed\" });\n\n p.log.success(\n `Uploaded ${testCases.length} test case${testCases.length === 1 ? \"\" : \"s\"} and ` +\n `${artifacts.length} artifact${artifacts.length === 1 ? \"\" : \"s\"}. ` +\n \"Return to your browser to continue onboarding.\",\n );\n}\n","import { execFile } from \"node:child_process\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nconst GIT_INFO_FILE = \".git-info.json\";\n\nexport interface GitInfo {\n /** Full HEAD commit SHA at the time analysis started. */\n sha: string;\n /** Current branch name, or \"HEAD\" when detached. */\n branch?: string;\n /** True when the working tree had uncommitted changes (so the SHA doesn't fully represent the analyzed state). */\n dirty: boolean;\n}\n\nasync function git(projectRoot: string, args: string[]): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", args, { cwd: projectRoot });\n return stdout.trim();\n } catch {\n // Not a git repo, git not installed, or detached/empty - treat as \"no git\".\n return undefined;\n }\n}\n\n/**\n * Reads the current commit, branch, and dirty state of the project's git repo.\n * Returns undefined when the project is not a git repository (or git is\n * unavailable) - the caller should just skip recording commit info in that case.\n */\nexport async function readGitInfo(projectRoot: string): Promise<GitInfo | undefined> {\n const sha = await git(projectRoot, [\"rev-parse\", \"HEAD\"]);\n if (sha == null || sha.length === 0) return undefined;\n\n const branch = await git(projectRoot, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n const status = await git(projectRoot, [\"status\", \"--porcelain\"]);\n\n return {\n sha,\n branch: branch != null && branch.length > 0 ? branch : undefined,\n dirty: status != null && status.length > 0,\n };\n}\n\nexport async function saveGitInfo(outputDir: string, info: GitInfo): Promise<void> {\n await writeFile(join(outputDir, GIT_INFO_FILE), JSON.stringify(info, null, 2), \"utf-8\");\n}\n\nexport async function loadGitInfo(outputDir: string): Promise<GitInfo | undefined> {\n try {\n const raw = await readFile(join(outputDir, GIT_INFO_FILE), \"utf-8\");\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed === \"object\" && parsed != null && \"sha\" in parsed && typeof parsed.sha === \"string\") {\n const branch = \"branch\" in parsed && typeof parsed.branch === \"string\" ? parsed.branch : undefined;\n const dirty = \"dirty\" in parsed && typeof parsed.dirty === \"boolean\" ? parsed.dirty : false;\n return { sha: parsed.sha, branch, dirty };\n }\n return undefined;\n } catch {\n return undefined;\n }\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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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["join","p","readFileSync","fileURLToPath","join","readFileSync","writeFileSync","mkdirSync","join","homedir","AUTONOMA_HOME","resolve","resolve","path","DIM","RESET","log","summary","YELLOW","RESET","readFile","join","relative","glob","execFile","promisify","execFileAsync","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","dirname","relative","resolve","tool","z","inputSchema","p","tool","z","path","z","tool","input","p","join","path","resolve","CYAN","RESET","editor","GREEN","DIM","SYSTEM_PROMPT","readFile","join","BOLD","RESET","DIM","YELLOW","tool","z","readFile","join","p","SYSTEM_PROMPT","path","readFile","join","matter","z","truncate","pad","BOLD","RESET","DIM","YELLOW","SYSTEM_PROMPT","init_prompt","readFile","writeFile","join","tool","z","glob","buildFinishTool","SYSTEM_PROMPT","init_prompt","readFile","join","readFile","join","matter","truncate","pad","BOLD","RESET","DIM","YELLOW","init_prompt","readFile","join","tool","z","buildFinishTool","init_prompt","readFile","writeFile","join","STATE_FILE","z","p","tool","z","SYSTEM_PROMPT","existsSync","join","RESET","readFile","writeFile","join","text","collectRefs","p","Output","generateText","z","p","writeFile","readFile","join","spawn","tool","z","resolve","DOCS_BASE","p","tool","z","p","text","readFile","join","p","z","basename","tool","readFile","join","relative","basename","glob","init_review","readFile","writeFile","join","path","STATE_FILE","readFile","writeFile","join","z","tool","path","SYSTEM_PROMPT","matter","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","readFileSync","readFileSync","join","join","homedir","AUTONOMA_HOME","join","AUTONOMA_HOME","readFile","join","execFile","readFile","writeFile","join","readFile","join","text","readFile","writeFile","join","path","writeFile","join","readFile","runPageFinder","runKBGenerator","runEntityAudit","runScenarioRecipe","runRecipeBuilder","runTestGenerator","config","outputDir"]}
|