@autonoma-ai/planner 0.1.21 → 0.1.22-canary.422bbdc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_@swc+core@1.15.3_jiti@2.6.1_postcss@8.5.15_tsx@4.21.0_typescript@7.0.2_yaml@2.8.3/node_modules/tsup/assets/esm_shims.js","../src/core/to-record.ts","../src/agents/04-recipe-builder/recipe.ts","../src/agents/04-recipe-builder/phases/submit.ts","../src/env.ts","../src/core/debug.ts","../src/core/version.ts","../src/core/analytics.ts","../src/core/colors.ts","../src/core/context.ts","../src/core/errors.ts","../src/core/model.ts","../src/core/notify.ts","../src/core/project-map.ts","../src/core/display.ts","../src/core/agent.ts","../src/core/gitignore.ts","../src/core/exec-error.ts","../src/tools/bash.ts","../src/tools/glob.ts","../src/tools/grep.ts","../src/tools/list-directory.ts","../src/tools/read-file.ts","../src/core/pick-string.ts","../src/tools/subagent.ts","../src/tools/write-file.ts","../src/tools/ask-user.ts","../src/tools/index.ts","../src/agents/00-project-mapper/index.ts","../src/agents/00-pages-finder/index.ts","../src/core/review.ts","../src/agents/01-kb-generator/flows.ts","../src/agents/01-kb-generator/prompt.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/prompt.ts","../src/agents/03-scenario-recipe/scenario-table.ts","../src/agents/03-scenario-recipe/index.ts","../src/agents/04-recipe-builder/entity-relevance.ts","../src/core/detect-pkg-manager.ts","../src/core/highlight.ts","../src/agents/04-recipe-builder/http-client.ts","../src/agents/04-recipe-builder/discover-schema.ts","../src/agents/04-recipe-builder/state.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/tech-detect.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/00b-feature-discovery/index.ts","../src/agents/05-test-generator/graph.ts","../src/agents/05-test-generator/prompt.ts","../src/agents/05-test-generator/validation.ts","../src/agents/05-test-generator/tools.ts","../src/agents/05-test-generator/index.ts","../src/index.ts","../src/core/ensure-node.ts","../src/core/node-version.ts","../src/config.ts","../src/core/global-env.ts","../src/core/interrupt.ts","../src/core/output.ts","../src/core/git.ts","../src/core/state.ts","../src/core/upload.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","/**\n * Normalize an unknown value into a string-keyed record so its properties can\n * be read without a type assertion. Non-objects (and null) become an empty\n * record rather than throwing, which suits the defensive walking of external\n * JSON (HTTP responses, parsed front matter) where the shape isn't guaranteed.\n */\nexport function toRecord(value: unknown): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return {};\n const record: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n record[key] = entry;\n }\n return record;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { toRecord } from \"../../core/to-record\";\nimport type { AuditedModel } from \"./entity-order\";\nimport type { EntityProgress } from \"./state\";\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 = toRecord(value);\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(entityOrder: string[], allEntities: Record<string, EntityProgress>): 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 validation: {\n status: string;\n method: string;\n up_ms?: number;\n down_ms?: number;\n };\n }[];\n}\n\nexport function buildSubmittableRecipe(create: RecipePayload, description: string): 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 | undefined> {\n try {\n const raw = await readFile(join(outputDir, RECIPE_FILE), \"utf-8\");\n const parsed: FullRecipeJson = JSON.parse(raw);\n return parsed;\n } catch {\n return undefined;\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { type FullRecipeJson, buildFullRecipe, buildSubmittableRecipe, loadRecipe, saveRecipe } from \"../recipe\";\nimport type { RecipeBuilderState } from \"../state\";\n\nconst RECIPE_FILE = \"recipe.json\";\nconst UPLOAD_COMMAND = \"npx @autonoma-ai/planner@latest upload\";\n\nexport interface SubmitCredentials {\n apiUrl?: string;\n apiToken?: string;\n generationId?: string;\n}\n\nexport interface SubmitResult {\n /** Local path (relative to the output dir) the recipe was written to. */\n recipePath: string;\n /** True only when the recipe was accepted by Autonoma. */\n uploaded: boolean;\n}\n\n/**\n * Build the recipe from the recipe-builder state, save it to disk, and submit it.\n * Returns whether the upload actually succeeded so the caller can fail the step\n * instead of masking a rejected upload as success.\n */\nexport async function runSubmit(\n state: RecipeBuilderState,\n outputDir: string,\n autonomaApiUrl?: string,\n autonomaApiToken?: string,\n autonomaGenerationId?: string,\n): Promise<SubmitResult> {\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_FILE}`);\n\n const uploaded = await submitRecipe(recipe, {\n apiUrl: autonomaApiUrl,\n apiToken: autonomaApiToken,\n generationId: autonomaGenerationId,\n });\n\n return { recipePath: RECIPE_FILE, uploaded };\n}\n\n/**\n * Load a previously generated `recipe.json` from the output dir and submit it,\n * without re-running the whole planner. Backs the `upload` command so a\n * failed/lost upload can be retried on its own.\n */\nexport async function uploadRecipeFromDisk(outputDir: string, creds: SubmitCredentials): Promise<boolean> {\n const recipe = await loadRecipe(outputDir);\n if (recipe == null) {\n p.log.error(\n `No ${RECIPE_FILE} found in ${outputDir}. Run the planner's recipe step first to generate it, then retry.`,\n );\n return false;\n }\n return submitRecipe(recipe, creds);\n}\n\n/**\n * POST a recipe to Autonoma's versioned scenario-recipe endpoint. On any failure\n * (including missing credentials) the recipe is printed to stdout in full with a\n * re-upload instruction, so it is never lost - even when the CLI runs in an\n * ephemeral container whose `~/.autonoma` filesystem is discarded on exit.\n */\nexport async function submitRecipe(recipe: FullRecipeJson, creds: SubmitCredentials): Promise<boolean> {\n const { apiUrl, apiToken, generationId } = creds;\n\n if (!apiUrl || !apiToken || !generationId) {\n p.log.info(\n \"Autonoma API credentials not configured - recipe saved locally, not uploaded. Set AUTONOMA_API_URL, AUTONOMA_API_TOKEN and AUTONOMA_GENERATION_ID, then run `\" +\n UPLOAD_COMMAND +\n \"`.\",\n );\n return false;\n }\n\n const url = `${apiUrl.replace(/\\/+$/, \"\")}/v1/setup/setups/${generationId}/scenario-recipe-versions`;\n\n p.log.step(\"Submitting recipe to Autonoma...\");\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiToken}`,\n },\n body: JSON.stringify(recipe),\n });\n } catch (err) {\n p.log.error(`Recipe submission failed (network error): ${err instanceof Error ? err.message : String(err)}`);\n printRecipeForRecovery(recipe);\n return false;\n }\n\n if (res.ok) {\n p.log.success(`Recipe submitted successfully (HTTP ${res.status})`);\n return true;\n }\n\n const text = await res.text();\n p.log.error(`Recipe submission failed (HTTP ${res.status}): ${text}`);\n printRecipeForRecovery(recipe);\n return false;\n}\n\n/**\n * Print the full recipe JSON plus a copy-paste recovery command. Uses console.log\n * (not the prompt logger) so the block is clean and easy to pipe/save.\n */\nfunction printRecipeForRecovery(recipe: FullRecipeJson): void {\n console.log(\n [\n \"\",\n \"─\".repeat(72),\n \"RECIPE NOT UPLOADED - copy the JSON below into a recipe.json and re-upload with:\",\n ` ${UPLOAD_COMMAND}`,\n \"(with the same AUTONOMA_API_URL / AUTONOMA_API_TOKEN / AUTONOMA_GENERATION_ID env vars set)\",\n \"─\".repeat(72),\n JSON.stringify(recipe, null, 2),\n \"─\".repeat(72),\n \"\",\n ].join(\"\\n\"),\n );\n}\n","import { createEnv } from \"@t3-oss/env-core\";\nimport { z } from \"zod\";\n\n// Every environment variable the CLI reads. Defined once so it doubles as the\n// allowlist the .env loaders use - they only inject these keys from a project's\n// .env / the global ~/.autonoma/.env into process.env, never arbitrary keys\n// like PATH or NODE_OPTIONS that happen to live in the target project's .env.\nconst ENV_SCHEMA = {\n // Model id override (OpenRouter-style id, forwarded by the managed proxy).\n OPENROUTER_MODEL: z.string().optional(),\n DATABASE_URL: z.string().optional(),\n SDK_ENDPOINT_URL: z.string().optional(),\n AUTONOMA_SHARED_SECRET: z.string().optional(),\n AUTONOMA_SIGNING_SECRET: z.string().optional(),\n AUTONOMA_API_URL: z.string().optional(),\n AUTONOMA_API_TOKEN: z.string().optional(),\n AUTONOMA_GENERATION_ID: z.string().optional(),\n AUTONOMA_POSTHOG_KEY: z.string().optional(),\n AUTONOMA_POSTHOG_HOST: z.string().optional(),\n AUTONOMA_DISTINCT_ID: z.string().optional(),\n DONT_TRACK: z.string().optional(),\n AUTONOMA_DEBUG: z.string().optional(),\n EDITOR: z.string().optional(),\n VISUAL: z.string().optional(),\n} satisfies Record<string, z.ZodTypeAny>;\n\n/** Keys the CLI recognizes; the .env loaders inject only these into process.env. */\nexport const ENV_KEYS: readonly string[] = Object.keys(ENV_SCHEMA);\n\n/**\n * Single, validated entry point for the CLI's environment (AGENTS.md rule 25).\n *\n * Unlike a server app, the CLI populates process.env at RUNTIME - from the\n * target project's .env and the global ~/.autonoma/.env (see config.ts and\n * core/global-env.ts) - so the env is validated on demand through this accessor\n * rather than snapshotted once at import. Every key is optional; callers supply\n * defaults or error when a required value (e.g. AUTONOMA_API_TOKEN) is missing.\n * This is the only module that reads process.env for configuration.\n */\nexport function readEnv() {\n return createEnv({\n server: ENV_SCHEMA,\n runtimeEnv: process.env,\n emptyStringAsUndefined: true,\n });\n}\n\nexport type CliEnv = ReturnType<typeof readEnv>;\n","import { readEnv } from \"../env\";\n\n/**\n * Emit a diagnostic breadcrumb to stderr, gated behind AUTONOMA_DEBUG.\n *\n * The CLI drives its interactive UI on stderr, so benign swallowed errors (file\n * not found, optional cleanup, best-effort telemetry) are logged here rather\n * than polluting normal output or being silently discarded. Set AUTONOMA_DEBUG=1\n * to surface them when investigating.\n */\nexport function debugLog(message: string, context?: Record<string, unknown>): void {\n const flag = readEnv().AUTONOMA_DEBUG;\n if (flag !== \"1\" && flag !== \"true\") return;\n const suffix = context != null ? ` ${JSON.stringify(context, replaceErrors)}` : \"\";\n process.stderr.write(`[autonoma:debug] ${message}${suffix}\\n`);\n}\n\nfunction replaceErrors(_key: string, value: unknown): unknown {\n if (value instanceof Error) return { name: value.name, message: value.message, stack: value.stack };\n return value;\n}\n","import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\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 { randomUUID } from \"node:crypto\";\nimport { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { readEnv } from \"../env\";\nimport { debugLog } from \"./debug\";\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 (readEnv().AUTONOMA_POSTHOG_KEY ?? POSTHOG_PUBLIC_KEY).trim();\n}\n\nfunction resolveHost(): string {\n return (readEnv().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 = readEnv().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 = readEnv().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 | undefined;\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 (err) {\n debugLog(\"No cached device id found; generating a fresh one\", { err });\n }\n cachedDeviceId = randomUUID();\n try {\n mkdirSync(AUTONOMA_HOME, { recursive: true });\n writeFileSync(DEVICE_ID_PATH, cachedDeviceId, { encoding: \"utf-8\", mode: 0o600 });\n } catch (err) {\n debugLog(\"Could not persist device id; using an in-memory id for this run\", { err });\n }\n return cachedDeviceId;\n}\n\nlet enabled: boolean | undefined;\n\nfunction isEnabled(): boolean {\n if (enabled === undefined) {\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 // Runtime version - lets us confirm/monitor Node-version-specific\n // failures (e.g. the @clack `util.styleText` crash on Node < 22.13).\n node_version: process.versions.node,\n },\n });\n\n const promise = fetch(`${resolveHost()}/capture/`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n })\n .catch((err) => {\n debugLog(\"Analytics capture request failed (ignored)\", { err });\n })\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(error: unknown, properties: Record<string, unknown> = {}, handled = true): 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([Promise.allSettled([...pending]), new Promise((resolve) => setTimeout(resolve, timeoutMs))]);\n}\n","// Terminal color palette mirrored from @autonoma/blacklight (packages/blacklight/src/index.css).\n// blacklight's tokens are hex, so we render them with 24-bit truecolor ANSI escapes\n// (`\\x1b[38;2;R;G;Bm`) - every modern terminal supports it, and it lets the CLI match\n// the product's exact brand color instead of the nearest 16-color approximation.\n\nconst ESC = \"\\x1b[\";\nexport const RESET = `${ESC}0m`;\nexport const BOLD = `${ESC}1m`;\nexport const DIM = `${ESC}2m`;\n\nfunction fg(hex: string): string {\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n return `${ESC}38;2;${r};${g};${b}m`;\n}\n\n// --primary: #CCFF00 - blacklight's brand lime. This is the accent that carries\n// the CLI's identity: banner, subagent lines, checkpoints.\nexport const PRIMARY = fg(\"#CCFF00\");\n\n// Status colors: kept distinct from the primary accent so success/error/warning\n// still read semantically instead of collapsing into one lime tone.\nexport const SUCCESS = fg(\"#3FB950\");\nexport const ERROR = fg(\"#FF5C5C\");\nexport const WARNING = fg(\"#FFB020\");\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 | undefined> {\n try {\n const raw = await readFile(join(outputDir, CONTEXT_FILE), \"utf-8\");\n const parsed: ProjectContext = JSON.parse(raw);\n return parsed;\n } catch {\n return undefined;\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.map((p) => `- \\`${p.route}\\` - ${p.description} (\\`${p.path}\\`)`).join(\"\\n\");\n }\n\n return output;\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>(fn: () => Promise<T>, options: Partial<RetryOptions> = {}): 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(opts.baseDelayMs * 2 ** (attempt - 1) + Math.random() * 500, opts.maxDelayMs);\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 * Walk the cause chain to the first APICallError and return its HTTP status.\n * The agent layer wraps provider errors in an AgentError (and the AI SDK may\n * wrap them in a RetryError), so the status we key friendly messages off of is\n * almost never on the top-level error - we have to dig for it.\n */\nfunction apiStatusOf(err: unknown): number | undefined {\n let cur: unknown = err;\n for (let depth = 0; cur != null && depth < 10; depth++) {\n if (APICallError.isInstance(cur)) return cur.statusCode;\n if (RetryError.isInstance(cur)) {\n cur = cur.lastError;\n continue;\n }\n cur = cur instanceof Error ? cur.cause : undefined;\n }\n return undefined;\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 | undefined {\n const msg = chainMessages(err);\n const status = apiStatusOf(err);\n\n const looksLikeAuth =\n msg.includes(\"missing authentication header\") ||\n msg.includes(\"no auth credentials\") ||\n msg.includes(\"not authenticated\") ||\n msg.includes(\"unauthorized\") ||\n msg.includes(\"user not found\") ||\n status === 401 ||\n status === 403;\n if (looksLikeAuth) {\n return {\n title: \"Autonoma rejected the request - your API token looks missing or invalid.\",\n hint: \"Launch the planner from the Autonoma app, or set a valid AUTONOMA_API_TOKEN (create one at https://autonoma.app/settings/api-keys).\",\n };\n }\n\n // The managed proxy returns 402 (out_of_credits) once the org's credit\n // balance is exhausted. Point straight at billing.\n if (\n msg.includes(\"out_of_credits\") ||\n msg.includes(\"insufficient\") ||\n msg.includes(\"credits\") ||\n msg.includes(\"quota\") ||\n status === 402\n ) {\n return {\n title: \"You're out of Autonoma credits.\",\n hint: \"Top up your credits at https://autonoma.app, then re-run.\",\n };\n }\n\n if (\n NoSuchModelError.isInstance(err) ||\n msg.includes(\"model_not_allowed\") ||\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.\",\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: \"Autonoma is rate-limiting this account.\",\n hint: \"Wait a minute and re-run. If it persists, reach out to support.\",\n };\n }\n\n // A 404/502/503 reaching the CLI is a problem with the managed planner\n // service, not the user's input. A bare 404 means the proxy route wasn't\n // found at the API host - the proxy is disabled or undeployed, or a custom\n // AUTONOMA_API_URL points somewhere without it (the exact failure that once\n // surfaced as a raw \"Not Found\"). A 502/503 means the proxy is reachable but\n // its upstream or config is failing. Real bad-model/bad-request failures come\n // back as 400 and are handled above, so this family is always \"our side -\n // retry or contact support\", never something the user can fix by re-running.\n if (status === 404 || status === 502 || status === 503 || msg.includes(\"llm_proxy_unconfigured\")) {\n return {\n title: \"The Autonoma planner service is temporarily unavailable.\",\n hint: \"This is on our side, not your setup - retry in a minute, and contact support if it keeps happening. If you set a custom AUTONOMA_API_URL, confirm it points at a host running the planner.\",\n };\n }\n\n return undefined;\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\n// 402 is the managed proxy's hard stop (out of credits, or the free planner\n// usage cap reached). Retrying can't refill a balance mid-run, so fail fast and\n// let describeKnownError surface the billing hint instead of burning retries.\nconst FATAL_STATUS_CODES = new Set([400, 401, 402, 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 (LoadAPIKeyError.isInstance(err) || InvalidPromptError.isInstance(err) || NoSuchModelError.isInstance(err)) {\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 { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\nimport { readEnv } from \"../env\";\n\nexport const DEFAULT_MODEL = \"google/gemini-3-flash-preview\";\n\n// Passed as the AI SDK's `maxRetries` on every model call. The SDK default of 2 gave up on\n// transient provider blips after 3 attempts; 10 rides them out. The SDK handles the backoff and\n// only retries retryable (429/5xx/network) errors, failing fast on 4xx.\nexport const AI_MAX_RETRIES = 10;\n\n// Production API host. Overridable with AUTONOMA_API_URL to target an\n// alpha/preview host. Keep in sync with config.ts.\nconst DEFAULT_API_URL = \"https://autonoma.app\";\n\nlet provider: ReturnType<typeof createOpenRouter> | undefined;\n\n/**\n * Build the model provider against Autonoma's managed LLM proxy. The CLI no\n * longer needs an OpenRouter key: it authenticates with the Autonoma API token\n * (the same key the web app injects, or AUTONOMA_API_TOKEN), and our API\n * forwards to OpenRouter on our key, metering the org's credits. The OpenRouter\n * AI-SDK provider posts to `${baseURL}/chat/completions`, which the proxy serves.\n */\nfunction getProvider() {\n if (provider != null) return provider;\n\n const token = readEnv().AUTONOMA_API_TOKEN?.trim();\n if (!token) {\n throw new Error(\"Not authenticated - launch the planner from the Autonoma app, or set AUTONOMA_API_TOKEN.\");\n }\n\n const apiUrl = (readEnv().AUTONOMA_API_URL ?? DEFAULT_API_URL).replace(/\\/+$/, \"\");\n provider = createOpenRouter({ apiKey: token, baseURL: `${apiUrl}/v1/llm-proxy` });\n return provider;\n}\n\nexport function getModel(modelId?: string) {\n return getProvider().languageModel(modelId ?? readEnv().OPENROUTER_MODEL ?? DEFAULT_MODEL);\n}\n","import { execFile } from \"node:child_process\";\nimport { platform } from \"node:os\";\n\nexport function notify(title: string, message: string): void {\n process.stderr.write(\"\\x07\");\n\n const os = platform();\n if (os === \"darwin\") {\n execFile(\n \"osascript\",\n [\"-e\", `display notification \"${message.replace(/\"/g, '\\\\\"')}\" with title \"${title.replace(/\"/g, '\\\\\"')}\"`],\n () => {},\n );\n } else if (os === \"linux\") {\n execFile(\"notify-send\", [title, message], () => {});\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { debugLog } from \"./debug\";\n\n/**\n * A project map is the very first thing the planner establishes: a partition of the\n * codebase into the frontend app(s) whose pages we test, the backend(s) that own the\n * data we seed, and the directories that are irrelevant to either. Every later step\n * scopes itself to this map instead of re-discovering (and re-scanning) the whole\n * tree - which is what let a large monorepo drown the page/knowledge/audit agents.\n *\n * Deliberately framework-agnostic (see apps/cli CLAUDE.md): a repo may be a single\n * fullstack app (frontend and backend the SAME path), a monorepo with many apps, or a\n * codebase that only ships one half (frontend-only or backend-only). Multiple backends\n * are first-class.\n */\n\nconst FrontendEntry = z.object({\n path: z.string().min(1).describe(\"Repo-relative path to the frontend app/directory (the UI surface).\"),\n framework: z\n .string()\n .describe(\"Detected UI framework/stack, or 'unknown' if not obvious (e.g. next, react, vue, svelte).\"),\n dependsOn: z\n .array(z.string())\n .describe(\n \"Repo-relative paths (each matching a backend in this map) that THIS frontend needs in order to function - the \" +\n \"API/service(s) it calls and the data layer(s) that own the records it renders. These are pre-selected when the \" +\n \"user picks this frontend, so only list backends this frontend actually depends on. Empty if it needs none.\",\n ),\n why: z.string().min(1).describe(\"One line: the evidence that made you classify this as a frontend.\"),\n});\n\nconst BackendEntry = z.object({\n path: z\n .string()\n .min(1)\n .describe(\"Repo-relative path to the backend/API/service or the package that owns the data layer.\"),\n language: z.string().describe(\"Primary language, or 'unknown' (e.g. typescript, python, go, rust).\"),\n framework: z\n .string()\n .describe(\"Web/service framework or ORM stack, or 'unknown' (e.g. express, hono, fastapi, rails).\"),\n dataLayer: z\n .object({\n kind: z\n .string()\n .describe(\"How models are defined (e.g. prisma, drizzle, sqlalchemy, typeorm, raw-sql, unknown).\"),\n schemaPath: z.string().optional().describe(\"Repo-relative path to the schema/models definition, if found.\"),\n })\n .optional()\n .describe(\"Where this backend's database models live. Omit if this backend owns no data layer.\"),\n why: z.string().min(1).describe(\"One line: the evidence that made you classify this as a backend.\"),\n});\n\nconst IgnoreEntry = z.object({\n path: z.string().min(1).describe(\"Repo-relative path to a directory that is NOT relevant to testing this app.\"),\n why: z\n .string()\n .min(1)\n .describe(\"One line: why it is irrelevant (e.g. docs site, infra, tooling, examples, unrelated app).\"),\n});\n\nexport const ProjectMapSchema = z.object({\n frontends: z\n .array(FrontendEntry)\n .describe(\"The UI surface(s) whose pages/flows get tested. Usually 1; may be more.\"),\n backends: z\n .array(BackendEntry)\n .describe(\n \"The API/service(s) and data layer(s) that own the models we seed. May be 0 (frontend-only), 1, or many.\",\n ),\n ignore: z\n .array(IgnoreEntry)\n .describe(\"Directories judged irrelevant to this app's tests, so later steps skip them.\"),\n});\n\nexport type ProjectMap = z.infer<typeof ProjectMapSchema>;\n\nconst PROJECT_MAP_FILE = \"project-map.json\";\n\nexport async function saveProjectMap(outputDir: string, map: ProjectMap): Promise<void> {\n await writeFile(join(outputDir, PROJECT_MAP_FILE), JSON.stringify(map, null, 2), \"utf-8\");\n}\n\nexport async function loadProjectMap(outputDir: string): Promise<ProjectMap | undefined> {\n const path = join(outputDir, PROJECT_MAP_FILE);\n try {\n const raw = await readFile(path, \"utf-8\");\n const parsed = ProjectMapSchema.safeParse(JSON.parse(raw));\n if (parsed.success) return parsed.data;\n // A present-but-invalid map (e.g. a partial write after a crash) silently degrades\n // every downstream step to \"no scope\", so leave a breadcrumb rather than dropping it.\n debugLog(\"project-map.json failed schema validation, ignoring it\", { path, issues: parsed.error.issues });\n return undefined;\n } catch (err) {\n const isMissingFile = err instanceof Error && \"code\" in err && err.code === \"ENOENT\";\n if (!isMissingFile) debugLog(\"Failed to read project-map.json, ignoring it\", { path, err });\n return undefined;\n }\n}\n\n/** Human-readable rendering for the pipeline note / confirmation prompt. */\nexport function renderProjectMap(map: ProjectMap): string {\n const section = <T>(title: string, rows: T[], fmt: (row: T) => string): string => {\n if (rows.length === 0) return `${title}: (none)`;\n return `${title}:\\n` + rows.map((r) => ` - ${fmt(r)}`).join(\"\\n\");\n };\n return [\n section(\"Frontend(s)\", map.frontends, (f) => {\n const deps = f.dependsOn.length > 0 ? ` needs: ${f.dependsOn.join(\", \")}` : \"\";\n return `${f.path} [${f.framework}]${deps} - ${f.why}`;\n }),\n section(\"Backend(s)\", map.backends, (b) => {\n const dl =\n b.dataLayer != null\n ? ` data: ${b.dataLayer.kind}${b.dataLayer.schemaPath != null ? ` @ ${b.dataLayer.schemaPath}` : \"\"}`\n : \"\";\n return `${b.path} [${b.language}/${b.framework}]${dl} - ${b.why}`;\n }),\n section(\"Ignoring\", map.ignore, (i) => `${i.path} - ${i.why}`),\n ].join(\"\\n\\n\");\n}\n\n/**\n * The scope hint appended to a downstream agent's task prompt so it confines its work\n * to the mapped surface instead of walking the whole tree. Passed as an extra message,\n * NOT baked into any tuned system prompt.\n */\nexport function formatFrontendScope(map: ProjectMap): string | undefined {\n if (map.frontends.length === 0) return undefined;\n const fronts = map.frontends.map((f) => f.path).join(\", \");\n const ignore = map.ignore.map((i) => i.path);\n const ignoreLine =\n ignore.length > 0 ? ` Do NOT spend time in these irrelevant directories: ${ignore.join(\", \")}.` : \"\";\n return (\n `The project has already been mapped. The frontend surface to focus on is: ${fronts}. ` +\n `Confine your exploration to that surface.${ignoreLine}`\n );\n}\n\n/**\n * A user's choice of what to actually plan tests for: exactly ONE frontend root and\n * the subset of backends needed for it to work. The mapper discovers every candidate;\n * this narrows the candidate map down to a single testable surface. On the CLI this is\n * a radio (frontend) plus checkboxes (backends); when driven by Claude the caller just\n * asks the user in natural language and hands the answer back.\n */\nexport interface ScopeSelection {\n frontend: string;\n backends: string[];\n}\n\n/**\n * Match a requested path against the paths a mapper run actually emitted. The mapper\n * is non-deterministic about how deep it names a path (a fullstack app's backend may\n * come back as `apps/main-app` on one run and `apps/main-app/app/api` on the next), so\n * a caller-supplied selection (flags / harness config) can't rely on an exact string.\n * Prefer an exact hit, then accept an ancestor/descendant relationship either way.\n */\nfunction relatedPath(a: string, b: string): boolean {\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\nfunction matchMapPath(requested: string, candidates: string[]): string | undefined {\n if (candidates.includes(requested)) return requested;\n return candidates.find((c) => relatedPath(c, requested));\n}\n\n/**\n * Match a requested backend against the map, by path OR by the data layer it owns.\n * The schema path is far more stable across mapper runs than which backend the schema\n * gets attributed to: a shared data-layer package can come back attached to the\n * fullstack app, to the package itself, or to a sibling service that also reads it, on\n * different runs. So a caller that names the data-layer package (or its schema) still\n * resolves to whichever backend the mapper hung it on this time.\n */\nfunction matchBackend(requested: string, backends: ProjectMap[\"backends\"]): string | undefined {\n const byPath = backends.find((b) => relatedPath(b.path, requested));\n if (byPath != null) return byPath.path;\n const bySchema = backends.find(\n (b) => b.dataLayer?.schemaPath != null && relatedPath(b.dataLayer.schemaPath, requested),\n );\n return bySchema?.path;\n}\n\n/**\n * Resolve a caller-supplied selection to the exact paths present in the map, so a\n * hand-written `frontend`/`backends` still lines up after the mapper varied its path\n * depth or where it attributed a shared data layer. Frontends match by path; backends\n * match by path or by data-layer schema. Unmatched entries are passed through unchanged\n * so applySelection can throw a clear \"not in the map\" error listing the real candidates.\n */\nexport function resolveSelection(map: ProjectMap, requested: ScopeSelection): ScopeSelection {\n const frontendPaths = map.frontends.map((f) => f.path);\n return {\n frontend: matchMapPath(requested.frontend, frontendPaths) ?? requested.frontend,\n backends: requested.backends.map((b) => matchBackend(b, map.backends) ?? b),\n };\n}\n\n/**\n * The backends to seed for a frontend when the caller names none: its declared\n * dependencies, resolved to the real backend paths in this map with anything that does\n * not resolve dropped. dependsOn is LLM-emitted, so it can name a shared util or a path\n * no BackendEntry owns; keeping such an entry would make applySelection reject the whole\n * run. Resolution is tolerant (by path or data-layer schema, ancestor/descendant either\n * way) and de-duplicated, so the result is always exact backend paths applySelection accepts.\n */\nexport function defaultBackendsFor(map: ProjectMap, frontendPath: string): string[] {\n const declared = map.frontends.find((f) => f.path === frontendPath)?.dependsOn ?? [];\n const resolved = declared.map((dep) => matchBackend(dep, map.backends)).filter((p): p is string => p != null);\n return [...new Set(resolved)];\n}\n\n/**\n * When a candidate map has exactly one frontend, the choice is unambiguous: that\n * frontend plus the backends it declares it depends on. Returns undefined when the\n * user must pick (zero or multiple frontends), which is the \"return and ask\" path.\n */\nexport function pickDefaultSelection(map: ProjectMap): ScopeSelection | undefined {\n if (map.frontends.length !== 1) return undefined;\n const [only] = map.frontends;\n if (only == null) return undefined;\n return { frontend: only.path, backends: defaultBackendsFor(map, only.path) };\n}\n\n/**\n * Narrow a candidate map to the chosen frontend and backends. Every other frontend and\n * every unselected backend is folded into `ignore` so the downstream steps physically\n * skip them. Throws if the selection references paths the map does not contain, so a\n * bad hand-supplied choice fails loud instead of silently planning the wrong surface.\n */\nexport function applySelection(map: ProjectMap, selection: ScopeSelection): ProjectMap {\n const frontend = map.frontends.find((f) => f.path === selection.frontend);\n if (frontend == null) {\n const options = map.frontends.map((f) => f.path).join(\", \") || \"(none)\";\n throw new Error(`Selected frontend \"${selection.frontend}\" is not in the map. Candidates: ${options}`);\n }\n const chosenBackends = map.backends.filter((b) => selection.backends.includes(b.path));\n const missing = selection.backends.filter((p) => !map.backends.some((b) => b.path === p));\n if (missing.length > 0) {\n const options = map.backends.map((b) => b.path).join(\", \") || \"(none)\";\n throw new Error(`Selected backend(s) not in the map: ${missing.join(\", \")}. Candidates: ${options}`);\n }\n\n const droppedFrontends = map.frontends\n .filter((f) => f.path !== selection.frontend)\n .map((f) => ({ path: f.path, why: \"Another frontend in the monorepo; not the app under test.\" }));\n const droppedBackends = map.backends\n .filter((b) => !selection.backends.includes(b.path))\n .map((b) => ({ path: b.path, why: \"Backend not required by the selected frontend.\" }));\n\n return {\n frontends: [frontend],\n backends: chosenBackends,\n ignore: [...map.ignore, ...droppedFrontends, ...droppedBackends],\n };\n}\n\n/** The scope hint for backend/data-layer-oriented steps (entity audit, recipe). */\nexport function formatBackendScope(map: ProjectMap): string | undefined {\n if (map.backends.length === 0) return undefined;\n const backs = map.backends\n .map((b) => (b.dataLayer?.schemaPath != null ? `${b.path} (models @ ${b.dataLayer.schemaPath})` : b.path))\n .join(\", \");\n const ignore = map.ignore.map((i) => i.path);\n const ignoreLine = ignore.length > 0 ? ` Ignore these irrelevant directories: ${ignore.join(\", \")}.` : \"\";\n return (\n `The project has already been mapped. The backend(s)/data layer(s) that own the models to seed are: ${backs}. ` +\n `Scope your data-model work to those backend(s).${ignoreLine}`\n );\n}\n","import { BOLD, DIM, ERROR, PRIMARY, RESET, SUCCESS, WARNING } from \"./colors\";\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(input.filePath ?? input.path ?? input.file_path ?? \"\");\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(` ${SUCCESS}✎ write ${path}${RESET}`);\n break;\n }\n\n case \"write_test\":\n stats.filesWritten++;\n writePermanent(` ${SUCCESS}✎ 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(` ${SUCCESS}${BOLD}✓ done:${RESET} ${SUCCESS}${agentId}${RESET}`);\n break;\n\n case \"subagent\":\n case \"spawn_researcher\":\n writePermanent(` ${PRIMARY}⊕ 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(` ${ERROR}✗ ${te.name}: ${te.error}${RESET}`);\n }\n\n for (const f of info.writtenFiles) {\n writePermanent(` ${SUCCESS}📄 wrote: ${f}${RESET}`);\n }\n }\n\n function checkpoint(message: string) {\n writePermanent(` ${WARNING}▸ ${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(` ${DIM}files read: ${stats.filesRead} | files written: ${stats.filesWritten}${RESET}`);\n }\n }\n\n return { log, checkpoint, summary, stats };\n}\n","import { type LanguageModel, type ModelMessage, type ToolSet, ToolLoopAgent, hasToolCall, stepCountIs } from \"ai\";\nimport { track } from \"./analytics\";\nimport { createStepLogger, type StepInfo } from \"./display\";\nimport { AgentError, classifyAgentError, sleep } from \"./errors\";\nimport { AI_MAX_RETRIES } from \"./model\";\n\nconst MAX_RETRIES = 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.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: Record<string, unknown> }) => ({\n name: tc.toolName,\n input: tc.input,\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 model = config.model;\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): never => {\n const msg = err instanceof Error ? err.message : String(err);\n throw new AgentError(`agent \"${config.id}\" (model ${modelIdOf(model)}) failed: ${msg}`, config.id, err);\n };\n\n const YELLOW = \"\\x1b[33m\";\n const RESET = \"\\x1b[0m\";\n\n for (let retry = 0; retry < MAX_RETRIES; retry++) {\n const heartbeat = () => {};\n const tools = typeof config.tools === \"function\" ? await config.tools(heartbeat) : config.tools;\n\n const agent = new ToolLoopAgent({\n model,\n maxRetries: AI_MAX_RETRIES,\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);\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 < MAX_RETRIES - 1) {\n console.log(` ${YELLOW}[${config.id}] retrying (${retry + 1}/${MAX_RETRIES})...${RESET}`);\n if (errorClass === \"transient\") {\n await sleep(Math.min(2000 * 2 ** retry, 10_000));\n }\n continue;\n }\n\n fail(err);\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(projectRoot: string): 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","/**\n * The extra fields Node's `child_process` attaches to the error it throws when\n * a spawned command fails (non-zero exit, timeout, ...). The error is typed\n * `unknown` in a catch clause, so this reads each field defensively - no type\n * assertion, and any field whose runtime type doesn't match comes back as\n * undefined rather than a lie.\n */\nexport interface ExecErrorFields {\n code?: number;\n stdout?: string;\n stderr?: string;\n killed?: boolean;\n}\n\nexport function readExecError(error: unknown): ExecErrorFields {\n if (typeof error !== \"object\" || error === null) return {};\n const code = Reflect.get(error, \"code\");\n const stdout = Reflect.get(error, \"stdout\");\n const stderr = Reflect.get(error, \"stderr\");\n const killed = Reflect.get(error, \"killed\");\n return {\n code: typeof code === \"number\" ? code : undefined,\n stdout: typeof stdout === \"string\" ? stdout : undefined,\n stderr: typeof stderr === \"string\" ? stderr : undefined,\n killed: typeof killed === \"boolean\" ? killed : undefined,\n };\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { readExecError } from \"../core/exec-error\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CHAINING_OPERATORS = /;|&&|\\|\\||`|\\$\\(|>>|<<|&\\s*$/;\n\nconst DEFAULT_ALLOWED = new Set([\"git\", \"wc\", \"sort\", \"head\", \"tail\", \"cat\", \"ls\", \"find\", \"diff\", \"echo\"]);\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(command: string, allowed: Set<string>): 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(workingDirectory: string, allowedCommands?: Set<string>) {\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(\"sh\", [\"-c\", input.command], {\n cwd: workingDirectory,\n maxBuffer: MAX_OUTPUT_BYTES,\n timeout: TIMEOUT_MS,\n });\n return {\n exitCode: 0,\n stdout: stdout.trimEnd(),\n stderr: stderr.trimEnd(),\n };\n } catch (err) {\n const execErr = readExecError(err);\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: 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: \"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\";\nimport { readExecError } from \"../core/exec-error\";\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: \"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 = readExecError(error);\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 { minimatch } from \"minimatch\";\nimport { z } from \"zod\";\nimport { loadGitignorePatterns } from \"../core/gitignore\";\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 ? `${relativeBase}/${entry.name}` : 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(workingDirectory: string) {\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.string().default(\".\").describe(\"Directory path relative to project root. Defaults to root.\"),\n depth: z.number().min(1).max(15).default(10).describe(\"Max depth to traverse (1-15). Default 10.\"),\n gitignore: z\n .boolean()\n .describe(\n \"Whether to respect the gitignore or to ignore it. true will respect it. false \" +\n \"will ignore it. Default true\",\n )\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 === \".\" ? workingDirectory : 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 ? \"\" : 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.number().int().min(0).optional().describe(\"Line number to start reading from (0-based)\"),\n limit: z.number().int().min(1).optional().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.map((line, i) => `${offset + i + 1}\\t${line}`).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: \"Read file contents with line numbers. Use offset and limit for large files.\",\n inputSchema,\n execute: (input) => executeReadFile(workingDirectory, input.filePath, input.offset, input.limit),\n });\n}\n","/**\n * Read the first string-valued property among `keys` off an unknown value.\n *\n * Tool inputs come from the model and occasionally arrive under a synonym key\n * (`filePath` vs `path` vs `file_path`), so callers probe several names. This\n * does that probing without a type assertion and without throwing on shapes\n * that don't match - it simply returns undefined.\n */\nexport function pickString(source: unknown, keys: string[]): string | undefined {\n if (typeof source !== \"object\" || source === null) return undefined;\n for (const key of keys) {\n const value = Reflect.get(source, key);\n if (typeof value === \"string\") return value;\n }\n return undefined;\n}\n","import { type LanguageModel, ToolLoopAgent, hasToolCall, stepCountIs, tool } from \"ai\";\nimport { z } from \"zod\";\nimport { AI_MAX_RETRIES } from \"../core/model\";\nimport { pickString } from \"../core/pick-string\";\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 = pickString(input, [\"filePath\", \"path\", \"file_path\"]) ?? \"\";\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 maxRetries: AI_MAX_RETRIES,\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: () => {\n onHeartbeat?.();\n },\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: \"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\n .string()\n .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 // In non-interactive / no-TTY runs there is no human to answer, and\n // clack's prompt would block forever waiting on a TTY. Auto-skip so the\n // agent falls back to inferring the answer from the codebase.\n if (!process.stdin.isTTY) {\n return {\n answer: \"No interactive user is available (non-interactive run). Do not ask again - infer the answer by reading the relevant model/schema/service files in the codebase and proceed with your best judgment.\",\n };\n }\n const answer = await p.text({ message: input.question });\n if (p.isCancel(answer)) return { answer: \"User skipped this question\" };\n return { answer };\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 { tool } from \"ai\";\nimport { buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { type ProjectMap, ProjectMapSchema } from \"../../core/project-map\";\nimport { buildCodebaseTools } from \"../../tools\";\n\nexport interface ProjectMapperInput {\n projectRoot: string;\n modelId?: string;\n outputDir: string;\n nonInteractive?: boolean;\n}\n\nconst MAX_STEPS = 60;\n\nconst SYSTEM_PROMPT =\n \"You map a codebase into three groups so the rest of the test-planning pipeline knows exactly what to look at \" +\n \"and what to skip: FRONTENDS (the UI surfaces whose pages and flows could be tested), BACKENDS (the API/service \" +\n \"and the data layer that owns the database models we would seed test data into), and IGNORE (everything \" +\n \"irrelevant to testing this product).\\n\\n\" +\n \"You are a DISCOVERY step, not a decision step. The pipeline tests ONE frontend at a time, but YOU do not choose \" +\n \"which - a human (or the agent driving you) picks afterward from what you found. So enumerate EVERY candidate \" +\n \"frontend and EVERY candidate backend you can justify; do not prune down to a single app. Pruning happens at \" +\n \"selection, using the dependency edges you record.\\n\\n\" +\n \"Discover the structure - never assume it. Read package/dependency manifests, config files, and the directory \" +\n \"layout, then reason from evidence:\\n\" +\n \"- A FRONTEND renders a user interface (pages/routes/views, a UI framework or bundler, browser entry points).\\n\" +\n \"- A BACKEND serves an API and/or owns the data layer (a database schema, ORM models, migrations, server routes).\\n\" +\n \"- IGNORE is the rest: infra, build tooling, examples, generated code, and packages that are neither a UI nor a \" +\n \"service/data-layer.\\n\\n\" +\n \"For EACH frontend, record `dependsOn`: the repo-relative paths (each must be one of the backends you list) that \" +\n \"that frontend actually needs in order to work - the API/service(s) it calls and the data layer(s) that own the \" +\n \"records it renders. Infer these from evidence: the frontend's dependency manifest, the API clients/SDKs it \" +\n \"imports, GraphQL/REST endpoints or gateway URLs it points at, and shared data-layer packages it reads. When the \" +\n \"user selects that frontend, its `dependsOn` backends are pre-checked, so be accurate: list the backends it truly \" +\n \"needs, not every backend in the repo.\\n\\n\" +\n \"Handle every shape without special-casing any framework:\\n\" +\n \"- A single fullstack app can be BOTH a frontend and a backend at the SAME path - list that path under both, and \" +\n \"put its own path in its `dependsOn`.\\n\" +\n \"- A monorepo can hold many apps and packages - list every genuine frontend and backend; only truly irrelevant \" +\n \"directories go in IGNORE.\\n\" +\n \"- There may be MANY backends (a main API, separate services, a shared data-layer package, a gateway plus the \" +\n \"services behind it) - list each one, and wire each frontend's `dependsOn` to just the ones it uses.\\n\" +\n \"- The data layer a frontend uses may live in a sibling/shared package OUTSIDE the frontend's own folder - record \" +\n \"that package as a backend, point its dataLayer.schemaPath at the schema, and include it in the frontend's \" +\n \"`dependsOn`.\\n\" +\n \"- A codebase may ship only one half. If you find frontends but NO backend/data layer (or vice versa), still \" +\n \"record what you found and leave the other group empty - the caller will ask the user to supply the missing half.\\n\\n\" +\n \"Be thorough and evidence-based. When you have enumerated the candidates and their dependency edges, call \" +\n \"set_project_map, then call finish. Keep each `why` to a single concrete sentence citing what you saw.\";\n\n/**\n * Run the project-mapper agent: discover and propose the frontend/backend/ignore\n * partition of the codebase. Returns the captured map, or undefined if the agent\n * never produced one. Persistence and user/Claude confirmation happen in the caller.\n */\nexport async function runProjectMapper(input: ProjectMapperInput): Promise<ProjectMap | undefined> {\n const model = getModel(input.modelId);\n const { logger, onStepFinish } = buildDefaultStepLogger(\"project-map\", MAX_STEPS);\n\n let captured: ProjectMap | undefined;\n\n const prompt =\n `Map the codebase rooted at ${input.projectRoot}.\\n\\n` +\n \"Explore the layout and dependency manifests, then enumerate EVERY candidate frontend and EVERY candidate \" +\n \"backend/data-layer, and for each frontend record the backends it depends on. List everything genuinely \" +\n \"irrelevant under ignore. Do not prune to a single app - a human picks the one to test afterward. Then call \" +\n \"set_project_map and finish.\";\n\n const agentConfig = {\n id: \"project-mapper\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: MAX_STEPS,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n set_project_map: tool({\n description:\n \"Record the final project map: the frontend app(s), the backend(s)/data layer(s), and the \" +\n \"directories to ignore. Call this once you are confident in the partition, then call finish.\",\n inputSchema: ProjectMapSchema,\n execute: (map) => {\n captured = map;\n return (\n `Recorded: ${map.frontends.length} frontend(s), ${map.backends.length} backend(s), ` +\n `${map.ignore.length} ignored. Now call finish.`\n );\n },\n }),\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => captured);\n logger.summary();\n\n return captured;\n}\n","import { existsSync } from \"fs\";\nimport * as path from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { buildCodebaseTools } from \"../../tools\";\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(([, aValue], [, 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 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:\n \"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, () => undefined);\n logger.summary();\n\n return pageCollector.pages;\n}\n","import { access } from \"node:fs/promises\";\nimport { join, isAbsolute } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport spawn from \"cross-spawn\";\nimport which from \"which\";\nimport type { AgentResult } from \"./agent\";\nimport { debugLog } from \"./debug\";\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[] | undefined;\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 | undefined;\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(`Couldn't open ${editor.label} (${err.message}). Review the files manually:`);\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: [...options, { value: \"skip\", label: \"No, skip - I'll review later\" }],\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(result: AgentResult, options: ReviewLoopOptions): 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 (err) {\n debugLog(`Artifact ${f} not present; skipping`, { err });\n }\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.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","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.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 = `${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","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, resolve } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { type AgentResult, buildDefaultStepLogger, formatRetryGuidance, runAgent } from \"../../core/agent\";\nimport { formatContext, type ProjectContext } from \"../../core/context\";\nimport { debugLog } from \"../../core/debug\";\nimport { getModel } from \"../../core/model\";\nimport { pickString } from \"../../core/pick-string\";\nimport { reviewLoop } from \"../../core/review\";\nimport type { buildReadFileTool } from \"../../tools\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { parseCoreFlows, renderFlowsTable } from \"./flows\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\n\nexport interface KBGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n retryGuidance?: string;\n}\n\nclass PageTracker {\n registered = new Set<string>();\n read = new Set<string>();\n\n // Registered pages (from pages.json) are absolute paths, but the agent reads them\n // with paths relative to the working directory. Canonicalize both to an absolute\n // path against projectRoot so coverage matches regardless of how each side spelled\n // it - otherwise the finish gate never clears and the agent nudges out re-reading.\n constructor(private readonly projectRoot: string) {}\n\n private normalize(filePath: string): string {\n return resolve(this.projectRoot, filePath);\n }\n\n register(pages: string[]) {\n for (const p of pages) this.registered.add(this.normalize(p));\n }\n\n markRead(filePath: string) {\n const normalized = this.normalize(filePath);\n if (this.registered.has(normalized)) {\n this.read.add(normalized);\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\n// \"Small\" vs \"large\" app is decided purely by how many routes were registered - the one\n// number that drives the coverage problem. At or below this many routes the agent can\n// (and must) read every one, so the finish gate demands 100%. Above it, a single pass\n// samples the app rather than reading all routes, and an unreachable 100% gate makes the\n// agent nudge-thrash; there we let it finish once it has covered a solid floor instead.\nconst FULL_COVERAGE_MAX_ROUTES = 40;\nconst LARGE_APP_COVERAGE_FLOOR = 0.5;\n\n/** How many registered routes must be read before finish is allowed, given the total. */\nfunction requiredReads(total: number): number {\n if (total <= FULL_COVERAGE_MAX_ROUTES) return total;\n return Math.ceil(total * LARGE_APP_COVERAGE_FLOOR);\n}\n\nfunction buildFinishTool(tracker: PageTracker, onFinish: (result: AgentResult) => void) {\n return tool({\n description:\n \"Call when you have finished generating the knowledge base. \" +\n \"BLOCKED until you have read enough of the registered routes (every route on a small app; a strong \" +\n \"majority on a large one) - call page_coverage first to check how many remain.\",\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 const required = requiredReads(cov.total);\n if (cov.read < required) {\n const preview = cov.unread.slice(0, 40).join(\"\\n\");\n const more = cov.unread.length > 40 ? `\\n...and ${cov.unread.length - 40} more` : \"\";\n return {\n error:\n `Cannot finish: only ${cov.read}/${cov.total} routes read - read at least ${required - cov.read} ` +\n `more (target ${required} of ${cov.total}). Start with:\\n${preview}${more}`,\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(tracker: PageTracker, baseTool: ReturnType<typeof buildReadFileTool>) {\n return tool({\n description: baseTool.description,\n inputSchema: baseTool.inputSchema,\n execute: async (input, options) => {\n const filePath = pickString(input, [\"filePath\", \"path\", \"file_path\"]) ?? \"\";\n tracker.markRead(filePath);\n return baseTool.execute!(input, options);\n },\n });\n}\n\n/**\n * The KB agent config, parameterized by the page tracker so the main generation pass and\n * the finalization passes each get their own coverage gate. Keeping this in one place\n * means the tuned SYSTEM_PROMPT and tool wiring stay identical across every pass.\n */\nfunction buildKbAgentConfig(\n tracker: PageTracker,\n model: ReturnType<typeof getModel>,\n input: KBGeneratorInput,\n onStepFinish: ReturnType<typeof buildDefaultStepLogger>[\"onStepFinish\"],\n setResult: (r: AgentResult) => void,\n) {\n return {\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, setResult),\n };\n },\n onStepFinish,\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 setResult = (r: AgentResult) => {\n result = r;\n };\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"kb\", 150);\n\n const contextBlock =\n (input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\") +\n formatRetryGuidance(input.retryGuidance);\n\n const pages = input.projectContext?.pages;\n\n const tracker = new PageTracker(input.projectRoot);\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 you have not read enough of the registered routes\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 you have not read enough of the registered routes\n\nOutput files:\n1. AUTONOMA.md - with YAML frontmatter (app_name, app_description, core_flows, feature_count)`;\n\n const agentConfig = buildKbAgentConfig(tracker, model, input, onStepFinish, setResult);\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\")\n .then(() => true)\n .catch((err) => {\n debugLog(\"AUTONOMA.md not found while checking step completion\", { err });\n return false;\n });\n if (!result?.success && autonomaExists) {\n result = {\n success: true,\n artifacts: [\"AUTONOMA.md\"],\n summary: \"Knowledge base generated.\",\n };\n }\n\n // Config for the finalization passes (self-review + user review). AUTONOMA.md is\n // already written by now, so register every route as read - the coverage gate must\n // not block these passes from re-calling finish after edits.\n const finalTracker = new PageTracker(input.projectRoot);\n if (pages?.length) {\n const paths = pages.map((p) => p.path);\n finalTracker.register(paths);\n for (const path of paths) finalTracker.markRead(path);\n }\n const finalConfig = buildKbAgentConfig(finalTracker, model, input, onStepFinish, setResult);\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(finalConfig, 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(finalConfig, feedbackPrompt, () => result);\n return result;\n },\n });\n\n return (\n reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"KB generator agent stopped without producing AUTONOMA.md\",\n }\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\n .array(createdBySchema)\n .nullish()\n .transform((v) => v ?? []),\n});\n\nconst frontmatterSchema = z.object({\n models: z\n .array(auditedModelSchema)\n .nullish()\n .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> | undefined;\n let inCreatedBy = false;\n let currentCreatedBy: { owner: string; via?: string; why?: string } | undefined;\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 = undefined;\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 = undefined;\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\n .replace(/^\\s{6}-\\s*/, \"\")\n .replace(/^[\"']|[\"']$/g, \"\")\n .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(models: AuditedModel[], importanceRank?: Map<string, number>): 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.filter((m) => !result.includes(m.name)).map((m) => m.name);\n console.warn(\n `[recipe-builder] Circular dependency detected for: ${missing.join(\", \")}. Appending in original order.`,\n );\n for (const m of missing) result.push(m);\n }\n\n return result;\n}\n\nexport function getEntityDependencyChain(entityName: string, models: AuditedModel[], entityOrder: string[]): 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 = `${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 { glob } from \"glob\";\nimport { z } from \"zod\";\nimport { runAgent, buildDefaultStepLogger, formatRetryGuidance, type AgentResult } from \"../../core/agent\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { debugLog } from \"../../core/debug\";\nimport { formatException } from \"../../core/errors\";\nimport { getModel } from \"../../core/model\";\nimport { reviewLoop } from \"../../core/review\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { parseAuditedModels, renderEntityAuditTable } from \"./audit-table\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\n\n// Each model costs the agent ~2 steps (grep for its creation path, mark it audited), so a\n// large shared schema needs headroom well above a typical app's. At 200 the agent step-outs\n// mid-audit; 400 covers ~200 models with the safety net still catching anything larger.\nconst MAX_STEPS = 400;\n\nexport interface EntityAuditInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n retryGuidance?: string;\n /**\n * Optional scope hint from the project map: which backend(s)/data-layer(s) own the\n * models to audit, so a monorepo run stays on the selected schema instead of the\n * whole tree. Appended to the task prompt; never edits the tuned system prompt.\n */\n scopeHint?: 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;\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 } | undefined {\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 = undefined;\n return undefined;\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\n .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 })\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\n .string()\n .optional()\n .describe(\"Function/method name (e.g. 'UserService.create' or 'create_user')\"),\n side_effects: z\n .array(z.string())\n .optional()\n .describe(\"Side effects of creation (e.g. 'creates default Settings row', 'hashes password')\"),\n created_by: z\n .array(\n z.object({\n owner: z.string().describe(\"Owner model name\"),\n via: z\n .string()\n .optional()\n .describe(\"Function that creates this model (e.g. 'OrganizationService.create')\"),\n why: z\n .string()\n .optional()\n .describe(\"One sentence explaining why this model is created as a side effect\"),\n }),\n )\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(tracker: ModelTracker, onFinish: (result: AgentResult) => void) {\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 | undefined> {\n const candidates = await glob(\"**/schema.prisma\", {\n cwd: projectRoot,\n ignore: [\"**/node_modules/**\"],\n absolute: true,\n });\n return candidates[0] ?? undefined;\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(projectRoot: string): Promise<FrameworkDetection | undefined> {\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 undefined;\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\", MAX_STEPS);\n\n const scopeBlock = input.scopeHint != null ? `\\n${input.scopeHint}\\n` : \"\";\n const contextBlock =\n (input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\") +\n scopeBlock +\n formatRetryGuidance(input.retryGuidance);\n\n const preRegBlock =\n 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${\n preRegisteredCount === 0\n ? `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`\n : \"1. Call next_model\"\n} 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: MAX_STEPS,\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) => {\n result = r;\n }),\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 | undefined> => {\n if (tracker.auditedModels.size === 0) return undefined;\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:\n \"Entity audit generated (finish tool may not have captured the result, but entity-audit.md exists).\",\n };\n } catch (err) {\n debugLog(\"entity-audit.md not readable; falling back to reviewed result\", { err });\n }\n }\n\n return (\n 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}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function parseEntityNames(outputDir: string): Promise<string[]> {\n try {\n const content = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n const names: string[] = [];\n for (const line of content.split(\"\\n\")) {\n const match = line.match(/^\\s+-\\s+name:\\s+(.+)$/);\n if (match) names.push(match[1]!.trim());\n }\n return names;\n } catch {\n return [];\n }\n}\n","export const SCENARIO_DESIGN_PROMPT = `You are a scenario designer for E2E testing. You read an entity audit and design a single \"standard\" test data scenario.\n\n## Your input\n- entity-audit.md: models, creation paths, side effects\n- AUTONOMA.md: app context, core flows\n\n## Your output\nA scenarios.md file with YAML frontmatter describing a single \"standard\" scenario.\n\n## Scenario design rules\n\n1. ONE scenario: \"standard\" - represents a realistic working state of the application\n2. Realistic data volumes:\n - An email app gets 50+ emails, not 1\n - A payment app gets all payment method types\n - A project management tool gets multiple projects with tasks in various states\n3. Enum coverage: for every enum field, include at least one record per value\n4. The scenario must exercise all entity types from the audit\n5. Entity tables must be consistent - FK references must point to real records\n\n## Output format\n\n\\`\\`\\`yaml\n---\nscenario_count: 1\nscenarios:\n - name: standard\n description: \"Realistic working state with diverse data\"\nentity_types:\n - name: Organization\n count: 1\n - name: User\n count: 3\n - name: Project\n count: 5\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## Data values\nEvery value in the scenario is concrete and static - write the actual data the\nrecords should hold. Do NOT use placeholders, tokens, or templated/\"dynamic\"\nvalues; the recipe builder generates the exact records from what you write.`;\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 matter from \"gray-matter\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst BOLD = \"\\x1b[1m\";\n\nexport interface ScenarioEntityType {\n name: string;\n count: number;\n}\n\nexport interface ParsedScenario {\n scenarioNames: string[];\n entityTypes: ScenarioEntityType[];\n}\n\n/** Parse scenarios.md frontmatter into the scenario names and entity types. */\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: {\n scenarios?: { name?: unknown }[];\n entity_types?: { name?: unknown; count?: unknown }[];\n } = matter(raw).data;\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 };\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\n/**\n * Scenario data must be fully concrete - there is no variable mechanism. Catch\n * any placeholder, token, or leftover `variable_fields` block the design agent\n * might still emit, so it can be handed back for self-correction. This is a soft\n * check: it returns one human-readable error per problem (empty array = clean)\n * and never throws, so a stray placeholder is something the agent fixes, not a\n * fatal failure.\n */\nexport function validateScenarioIsConcrete(content: string): string[] {\n const errors: string[] = [];\n const checks: { pattern: RegExp; label: string }[] = [\n { pattern: /\\{\\{[a-zA-Z0-9_]+\\}\\}/g, label: \"{{token}} placeholder\" },\n { pattern: /(?<!\\{)\\{[a-z][a-zA-Z]*\\}(?!\\})/g, label: \"bare {variable} placeholder\" },\n { pattern: /^\\s*variable_fields\\s*:/m, label: \"variable_fields block\" },\n ];\n\n for (const { pattern, label } of checks) {\n const match = content.match(pattern);\n if (match && match.length > 0) {\n errors.push(\n `${label}: \"${match[0].trim()}\" - scenario values must be concrete. ` +\n `Replace it with the exact static value (there is no variable mechanism).`,\n );\n }\n }\n\n return errors;\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.\n */\nexport function renderScenarioTable(parsed: ParsedScenario): string {\n if (parsed.entityTypes.length === 0) return \"\";\n\n const NAME_MAX = 32;\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 }));\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\n const header = `${BOLD}${pad(\"#\", numW)} ${pad(\"Entity\", nameW)} ${pad(\"Count\", countW)}${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + countW + 4)}${RESET}`;\n\n const body = rows.map((r) => `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.count, countW)}`).join(\"\\n\");\n\n const scenarioLabel = parsed.scenarioNames.length ? `scenario: ${parsed.scenarioNames.join(\", \")} · ` : \"\";\n const caption = `${DIM}${scenarioLabel}${parsed.entityTypes.length} entity types · ${totalRecords} records${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\n}\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 { debugLog } from \"../../core/debug\";\nimport { getModel } from \"../../core/model\";\nimport { parseEntityNames } from \"../../core/parse-entity-audit\";\nimport { reviewLoop } from \"../../core/review\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { SCENARIO_DESIGN_PROMPT } from \"./prompt\";\nimport { parseScenario, renderScenarioTable, validateScenarioIsConcrete } from \"./scenario-table\";\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 /** Optional backend/data-layer scope hint from the project map (appended to the prompt). */\n scopeHint?: string;\n}\n\nexport function 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 // These checks return an error string back to the agent so it can fix the\n // scenario and call finish again - they must never throw / fail fatally.\n let content: string;\n try {\n content = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch {\n return { error: \"Cannot finish: scenarios.md not found. Write it first.\" };\n }\n\n if (requiredEntities.length > 0) {\n const missing = requiredEntities.filter((e) => !content.includes(e));\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 }\n\n const concretenessErrors = validateScenarioIsConcrete(content);\n if (concretenessErrors.length > 0) {\n return {\n error:\n `Cannot finish: scenario data must be fully concrete - no variables, tokens, or placeholders.\\n` +\n `Fix these before calling finish:\\n` +\n concretenessErrors.map((e) => ` - ${e}`).join(\"\\n\"),\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 scopeBlock = input.scopeHint != null ? `\\n${input.scopeHint}\\n` : \"\";\n const contextBlock =\n (input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\") +\n scopeBlock +\n formatRetryGuidance(input.retryGuidance);\n\n const requiredEntities = await parseEntityNames(input.outputDir);\n\n const entityListBlock =\n 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)\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 {\n ...tools,\n ask_user: buildAskUserTool(),\n finish: buildFinishTool(requiredEntities, input.outputDir, (r) => {\n result = r;\n }),\n };\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 \" - 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 (err) {\n debugLog(\"scenarios.md not readable; falling back to reviewed result\", { err });\n }\n }\n\n return (\n reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Scenario agent stopped without producing scenarios.md\",\n }\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 {\n ...tools,\n ask_user: buildAskUserTool(),\n finish: buildFinishTool(requiredEntities, input.outputDir, (r) => {\n result = r;\n }),\n };\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 { type LanguageModel, Output, generateText } from \"ai\";\nimport { z } from \"zod\";\nimport { formatException } from \"../../core/errors\";\nimport { AI_MAX_RETRIES } from \"../../core/model\";\nimport type { AuditedModel } from \"./entity-order\";\n\nconst rankedSchema = z.object({\n ranked: z.array(z.string()).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 maxRetries: AI_MAX_RETRIES,\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(canonicalInOrder: string[], aiRanked: string[]): 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(\n `- These names are not in the audit, do not use them: ${reconciled.invented.join(\", \")}`,\n );\n if (reconciled.duplicates.length > 0)\n feedbackParts.push(\n `- These were listed more than once, list each exactly once: ${reconciled.duplicates.join(\", \")}`,\n );\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 { 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\":\n return `bun add ${pkgs}`;\n case \"pnpm\":\n return `pnpm add ${pkgs}`;\n case \"yarn\":\n return `yarn add ${pkgs}`;\n case \"npm\":\n return `npm install ${pkgs}`;\n }\n}\n\nexport function runCommand(pm: PackageManager): string {\n switch (pm) {\n case \"bun\":\n return \"bun run\";\n case \"pnpm\":\n return \"pnpm run\";\n case \"yarn\":\n return \"yarn run\";\n case \"npm\":\n return \"npm run\";\n }\n}\n\nexport function execCommand(pm: PackageManager, file: string): string {\n switch (pm) {\n case \"bun\":\n return `bun ${file}`;\n case \"pnpm\":\n return `pnpm tsx ${file}`;\n case \"yarn\":\n return `yarn tsx ${file}`;\n case \"npm\":\n 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(/&#x27;/g, \"'\")\n .replace(/&amp;/g, \"&\")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/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 { 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(config: SdkClientConfig, refsToken: string): Promise<SdkResponse> {\n return sendRequest(config, {\n action: \"down\",\n refsToken,\n });\n}\n","import { toRecord } from \"../../core/to-record\";\nimport * as sdk from \"./http-client\";\nimport type { SdkClientConfig } from \"./http-client\";\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\";\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;\n}\n\n/** Parse the wire JSON from a discover response into a typed schema. Returns\n * undefined when the body doesn't look like a discover schema (defensive). */\nexport function parseDiscoverBody(body: unknown): DiscoverSchema | undefined {\n if (!body || typeof body !== \"object\") return undefined;\n const schema = toRecord(body).schema;\n if (!schema || typeof schema !== \"object\") return undefined;\n const schemaRecord = toRecord(schema);\n\n const rawModels = schemaRecord.models;\n if (!Array.isArray(rawModels)) return undefined;\n\n const models = new Map<string, DiscoverModel>();\n for (const m of rawModels) {\n if (!m || typeof m !== \"object\") continue;\n const mm = toRecord(m);\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 = toRecord(f);\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, {\n name: mm.name,\n tableName: typeof mm.tableName === \"string\" ? mm.tableName : mm.name,\n fields,\n });\n }\n\n const scopeField =\n typeof schemaRecord.scopeField === \"string\" && schemaRecord.scopeField.length > 0\n ? schemaRecord.scopeField\n : undefined;\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 | undefined> {\n try {\n const res = await sdk.discover(config);\n if (!res.ok) return undefined;\n return parseDiscoverBody(res.body);\n } catch {\n return undefined;\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 undefined 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 | undefined {\n const m = schema.models.get(modelName);\n if (!m) return undefined;\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 =\n 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(recipe: RecipePayload, schema: DiscoverSchema): 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 = toRecord(value);\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()].map(([key, msgs]) => `${key}: ${msgs.join(\"; \")}`).join(\"\\n\");\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type EntityStatus = \"pending\" | \"recipe-accepted\" | \"tested-up\" | \"tested-down\" | \"skipped\";\n\nexport interface EntityProgress {\n entityName: string;\n status: EntityStatus;\n recipeData?: Record<string, unknown>[];\n errorLog: string[];\n}\n\nexport type SdkAdapter =\n | {\n language: \"typescript\";\n framework: \"express\";\n sdkPackage: \"@autonoma-ai/sdk\";\n adapterPackage: \"@autonoma-ai/server-express\";\n }\n | {\n language: \"typescript\";\n framework: \"node\";\n sdkPackage: \"@autonoma-ai/sdk\";\n adapterPackage: \"@autonoma-ai/server-node\";\n }\n | {\n language: \"typescript\";\n framework: \"hono\";\n sdkPackage: \"@autonoma-ai/sdk\";\n adapterPackage: \"@autonoma-ai/server-hono\";\n }\n | {\n language: \"typescript\";\n framework: \"web\";\n sdkPackage: \"@autonoma-ai/sdk\";\n adapterPackage: \"@autonoma-ai/server-web\";\n }\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 | {\n language: \"go\";\n framework: \"gin\";\n sdkPackage: \"github.com/autonoma-ai/sdk-go\";\n adapterPackage: \"github.com/autonoma-ai/sdk-go\";\n }\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 {\n language: \"typescript\",\n framework: \"web\",\n sdkPackage: \"@autonoma-ai/sdk\",\n adapterPackage: \"@autonoma-ai/server-web\",\n },\n {\n language: \"typescript\",\n framework: \"express\",\n sdkPackage: \"@autonoma-ai/sdk\",\n adapterPackage: \"@autonoma-ai/server-express\",\n },\n {\n language: \"typescript\",\n framework: \"node\",\n sdkPackage: \"@autonoma-ai/sdk\",\n adapterPackage: \"@autonoma-ai/server-node\",\n },\n {\n language: \"typescript\",\n framework: \"hono\",\n sdkPackage: \"@autonoma-ai/sdk\",\n adapterPackage: \"@autonoma-ai/server-hono\",\n },\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 {\n language: \"go\",\n framework: \"gin\",\n sdkPackage: \"github.com/autonoma-ai/sdk-go\",\n adapterPackage: \"github.com/autonoma-ai/sdk-go\",\n },\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((a) => a.language === language.toLowerCase() && a.framework === framework.toLowerCase());\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;\n entityOrder: string[];\n entities: Record<string, EntityProgress>;\n currentEntityIndex: number;\n sdkEndpointUrl?: string;\n sharedSecret?: string;\n}\n\nconst STATE_FILE = \".recipe-builder-state.json\";\n\nexport function initialRecipeState(): RecipeBuilderState {\n return {\n phase: \"tech-detect\",\n entityOrder: [],\n entities: {},\n currentEntityIndex: 0,\n };\n}\n\nexport async function loadRecipeState(outputDir: string): Promise<RecipeBuilderState | undefined> {\n try {\n const raw = await readFile(join(outputDir, STATE_FILE), \"utf-8\");\n const parsed: RecipeBuilderState = JSON.parse(raw);\n return parsed;\n } catch {\n return undefined;\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 { AI_MAX_RETRIES } from \"../../../core/model\";\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 maxRetries: AI_MAX_RETRIES,\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 { writeFile, readFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { tool } from \"ai\";\nimport type { LanguageModel } from \"ai\";\nimport spawn from \"cross-spawn\";\nimport { z } from \"zod\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { detectPackageManager, installCommand } from \"../../../core/detect-pkg-manager\";\nimport { formatException } from \"../../../core/errors\";\nimport { loadGitignorePatterns } from \"../../../core/gitignore\";\nimport { codeNoteFormat } from \"../../../core/highlight\";\nimport { notify } from \"../../../core/notify\";\nimport { toRecord } from \"../../../core/to-record\";\nimport { readEnv } from \"../../../env\";\nimport { buildReadFileTool, buildGlobTool, buildGrepTool } from \"../../../tools\";\nimport { buildAskUserTool } from \"../../../tools/ask-user\";\nimport {\n fetchDiscoverSchema,\n renderModelSchema,\n validateRecipeAgainstSchema,\n formatValidationProblems,\n type DiscoverSchema,\n} from \"../discover-schema\";\nimport type { AuditedModel } from \"../entity-order\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\nimport { buildSingleEntityRecipe, type RecipePayload } from \"../recipe\";\nimport type { RecipeBuilderState, TechStack, EntityProgress } from \"../state\";\nimport { adapterLabel, saveRecipeState } from \"../state\";\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(completedEntities: Record<string, EntityProgress>, excludeName?: string): 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 =\n 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)`, {\n format: codeNoteFormat,\n });\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 env = readEnv();\n const editor = env.EDITOR ?? 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.trim()) continue;\n\n proposed = await reviseRecipeData(\n entityName,\n entityIndex,\n totalEntities,\n proposed,\n feedback.trim(),\n model,\n outputDir,\n completedEntities,\n 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 {\n value: \"feedback\",\n label: \"Let me explain what's wrong\",\n hint: \"Describe the change and the agent will apply it\",\n },\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.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(\n `Let's verify this factory works. We'll send a test request to create ${entityName}, then check the database.`,\n );\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 refsTokenValue = toRecord(upResult.body).refsToken;\n const refsToken = typeof refsTokenValue === \"string\" ? refsTokenValue : 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(\n entityName,\n downResult.body,\n failureCtx,\n \"teardown\",\n downResult.status,\n );\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; spec?: string }> {\n if (!state.sdkEndpointUrl || !state.sharedSecret) return {};\n const schema = await fetchDiscoverSchema({\n endpointUrl: state.sdkEndpointUrl,\n sharedSecret: state.sharedSecret,\n });\n if (!schema) return {};\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 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,\n i,\n total,\n model,\n outputDir,\n projectRoot,\n state.entities,\n recipeSchemaSpec,\n );\n }\n\n // B. User review\n if (!nonInteractive) {\n recipeData = await reviewRecipeData(\n entityName,\n i,\n total,\n recipeData,\n model,\n outputDir,\n state.entities,\n recipeSchemaSpec,\n );\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,\n i,\n total,\n i === 0,\n state.techStack!,\n auditModel,\n recipeData,\n model,\n projectRoot,\n outputDir,\n );\n const DOCS_BASE = \"https://docs.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)`, {\n format: codeNoteFormat,\n });\n\n p.log.info(`Autonoma SDK docs: ${DOCS_BASE}/sdk/environment-factory`);\n\n if (i === 0) {\n p.log.info(\n \"This is your first factory - the guide includes one-time SDK setup. Later entities only need the factory function.\",\n );\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.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(\n entityName,\n i,\n total,\n sdkConfig,\n singleRecipe,\n grounding,\n discoverSchema ?? undefined,\n );\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,\n i,\n total,\n state.entities[entityName]!.recipeData!,\n testResult.feedback,\n model,\n outputDir,\n state.entities,\n 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 type { LanguageModel } from \"ai\";\nimport { z } from \"zod\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { formatException } from \"../../../core/errors\";\nimport { codeNoteFormat } from \"../../../core/highlight\";\nimport { notify } from \"../../../core/notify\";\nimport { toRecord } from \"../../../core/to-record\";\nimport { buildReadFileTool } from \"../../../tools\";\nimport {\n fetchDiscoverSchema,\n renderModelSchema,\n validateRecipeAgainstSchema,\n formatValidationProblems,\n} from \"../discover-schema\";\nimport type { AuditedModel } from \"../entity-order\";\nimport * as sdk from \"../http-client\";\nimport type { SdkClientConfig } from \"../http-client\";\nimport { buildFullRecipe, type RecipePayload } from \"../recipe\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { saveRecipeState } from \"../state\";\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(\n sdkConfig: SdkClientConfig,\n refsToken: string | undefined,\n successMessage: string,\n): 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.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\n .map((name) => renderModelSchema(discoverSchema, name))\n .filter(Boolean)\n .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 = toRecord(upResult.body);\n const refsToken = typeof body.refsToken === \"string\" ? body.refsToken : undefined;\n\n const auth = body.auth != null && typeof body.auth === \"object\" ? toRecord(body.auth) : undefined;\n if (auth && Object.keys(auth).length > 0) {\n const authJson = JSON.stringify(auth, null, 2);\n const looksPlaceholder =\n authJson.includes(\"test-token\") || authJson.includes(\"placeholder\") || authJson.includes(\"todo\");\n\n p.note(\n authJson +\n \"\\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.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(\n fullRecipe,\n feedback.trim(),\n model,\n outputDir,\n state.entityOrder,\n fullSchemaSpec,\n );\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\", {\n format: codeNoteFormat,\n });\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { runAgent, buildDefaultStepLogger } from \"../../../core/agent\";\nimport { loadGitignorePatterns } from \"../../../core/gitignore\";\nimport { getModel } from \"../../../core/model\";\nimport { buildReadFileTool, buildGlobTool, buildGrepTool, buildBashTool } from \"../../../tools\";\nimport { ALL_ADAPTERS, ADAPTER_HINTS, adapterKey, adapterLabel, findAdapter, type TechStack } from \"../state\";\n\nconst DOCS_BASE = \"https://docs.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\n .string()\n .describe(\"Programming language: typescript, python, go, ruby, java, php, rust, elixir\"),\n framework: z\n .string()\n .describe(\n \"Web framework: express, node, hono, web, flask, fastapi, django, gin, rails, rack, spring, laravel, axum, actix, plug\",\n ),\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(\n \"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\n await runAgent(\n agentConfig,\n \"Detect the backend programming language and web framework for this project. Check dependency files and imports. Call finish with your findings.\",\n () => detected,\n );\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.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 { 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 { readEnv } from \"../../env\";\nimport { parseEntityAudit, resolveEntityOrder } from \"./entity-order\";\nimport { rankEntitiesByImportance } from \"./entity-relevance\";\nimport { runEntityLoop } from \"./phases/entity-loop\";\nimport { runFullValidation } from \"./phases/full-validation\";\nimport { runSubmit } from \"./phases/submit\";\nimport { detectTechStack } from \"./phases/tech-detect\";\nimport { initialRecipeState, loadRecipeState, saveRecipeState } from \"./state\";\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(input.projectRoot, input.modelId, input.nonInteractive);\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 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(\n `Found ${entityOrder.length} entities needing factories. Processing core entities first, in dependency order.`,\n );\n }\n\n // Phase 2: Entity-by-entity loop\n if (state.phase === \"entity-loop\") {\n await runEntityLoop(state, models, model, input.projectRoot, input.outputDir, input.nonInteractive);\n\n const allDone = state.entityOrder.every((name) => {\n const e = state.entities[name];\n return e?.status === \"tested-down\" || e?.status === \"skipped\";\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 env = readEnv();\n const { recipePath, uploaded } = await runSubmit(\n state,\n input.outputDir,\n env.AUTONOMA_API_URL,\n env.AUTONOMA_API_TOKEN,\n env.AUTONOMA_GENERATION_ID,\n );\n\n // Only advance past submit once the recipe is actually accepted; a rejected\n // upload must fail the step (not mark it done with no recipe on the server)\n // so `--resume` retries it.\n const uploadCredentialsPresent =\n env.AUTONOMA_API_URL != null && env.AUTONOMA_API_TOKEN != null && env.AUTONOMA_GENERATION_ID != null;\n if (uploadCredentialsPresent && !uploaded) {\n return {\n success: false,\n artifacts: [recipePath],\n summary: `Recipe was generated but not accepted by Autonoma. The recipe JSON was printed above - re-upload with \\`npx @autonoma-ai/planner@latest upload\\` (or run again with --resume).`,\n };\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// z.object() returns a schema typed by its exact shape; ReviewRubric.resultSchema\n// wants the general object-schema type. Funnelling each rubric's shape through\n// this typed parameter widens it without a per-rubric type assertion.\nfunction reviewResultSchema(shape: z.ZodRawShape): z.ZodObject<z.ZodRawShape> {\n return z.object(shape);\n}\n\n// The structured review payload: one DimensionResult per rubric dimension. Used\n// to validate (and type) the finish-tool input the review agent submits.\nexport const reviewResultRecordSchema = z.record(z.string(), 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: reviewResultSchema({\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 }),\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: reviewResultSchema({\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 }),\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: reviewResultSchema({\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 }),\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: reviewResultSchema({\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 }),\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 { reviewResultRecordSchema, type ReviewRubric, type 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> | undefined> {\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 // input already satisfied rubric.resultSchema upstream; re-parsing through\n // the concrete record schema recovers the precise type without an assertion.\n result = reviewResultRecordSchema.parse(input);\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 =\n 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 ?? undefined;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative, basename } from \"node:path\";\nimport { type LanguageModel } from \"ai\";\nimport { glob } from \"glob\";\nimport { createStepLogger } from \"../../core/display\";\nimport { runReviewPass } from \"./review-pass\";\nimport { ALL_RUBRICS, type DimensionResult } from \"./rubrics\";\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(\n ` [review] ${rubric.name} error on ${basename(testPath)}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return undefined;\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 {\n /* scenarios not available */\n }\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(\n test.content,\n test.relativePath,\n projectRoot,\n model,\n scenarioData,\n );\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\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { type AgentResult, buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { buildCodebaseTools } from \"../../tools\";\n\nconst FEATURES_FILE = \"features.json\";\n\nconst Feature = z.object({\n name: z\n .string()\n .min(1)\n .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\n .number()\n .int()\n .min(0)\n .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(\n ` - [${f.type}] ${f.name} (${f.interactiveElements} elements, ${f.sourceFiles.length} files)`,\n );\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> | undefined> {\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 undefined;\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 { 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;\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;\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;\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 } | undefined {\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\") continue;\n\n node.status = \"exploring\";\n this.currentNode = id;\n return { node, remaining: this.queue.length };\n }\n\n this.currentNode = undefined;\n return undefined;\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 = undefined;\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 ?? undefined;\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(outputDir: string, state: CoverageState): 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(outputDir: string): Promise<CoverageState | undefined> {\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 undefined;\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 the exact values from the scenario\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- Do NOT assert on values that are auto-generated or vary at runtime (like database IDs); assert on the stable scenario values instead\n- NEVER use \"Dynamic:\", \"{variableName}\", \"{{token}}\", 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 matter from \"gray-matter\";\n\nexport const VALID_VERBS = new Set([\"click\", \"type\", \"scroll\", \"assert\", \"hover\", \"drag\", \"read\", \"refresh\"]);\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(\n \"Missing or insufficient 'verification' field in frontmatter - must describe WHERE to navigate and WHAT to assert at the source of truth\",\n );\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 = 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 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 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 { AI_MAX_RETRIES } from \"../../core/model\";\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\n .string()\n .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\n .string()\n .min(\n 20,\n \"Verification must describe WHERE to navigate and WHAT to assert at the source of truth - not UI acknowledgments like toasts\",\n ),\n});\n\n/**\n * Test steps must use exact, concrete values from the scenario - no\n * placeholders, tokens, or examples. Scenario data is fully static (the planner\n * has no variable mechanism), so any `{{token}}`, bare `{variable}`, \"Dynamic:\",\n * or \"e.g.\" in the steps is a value the visual agent cannot resolve. Returns the\n * first offending placeholder found, or null when the steps are clean.\n */\nexport function findForbiddenPlaceholder(stepsSection: string): { name: string; match: string } | undefined {\n const placeholderPatterns = [\n { pattern: /Dynamic:\\s/gi, name: '\"Dynamic:\" placeholder' },\n { pattern: /\\{\\{[a-zA-Z0-9_]+\\}\\}/g, name: \"{{token}} 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 { name, match: matches[0] };\n }\n }\n\n return undefined;\n}\n\nexport function buildWriteTestTool(state: CoverageState, outputDir: string) {\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 {\n error: \"Test must include an **Intent**: section between Setup and Steps describing what behavior is being tested\",\n };\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 =\n 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:\n `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 placeholder = findForbiddenPlaceholder(stepsSection);\n if (placeholder) {\n return {\n error:\n `Test steps contain ${placeholder.name}: \"${placeholder.match}\". ` +\n `Use EXACT values from scenarios.md - not placeholders or examples.`,\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(model: LanguageModel, workingDirectory: string, onHeartbeat?: () => void) {\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 maxRetries: AI_MAX_RETRIES,\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) => {\n result = output;\n },\n }),\n },\n stopWhen: [stepCountIs(15), hasToolCall(\"finish\")],\n onStepFinish: () => {\n onHeartbeat?.();\n },\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> | undefined {\n try {\n const { data } = matter(content);\n return data && Object.keys(data).length > 0 ? data : undefined;\n } catch {\n return undefined;\n }\n}\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 { formatContext, type ProjectContext } from \"../../core/context\";\nimport { createStepLogger } from \"../../core/display\";\nimport { formatException } from \"../../core/errors\";\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 { glob } from \"glob\";\nimport { debugLog } from \"../../core/debug\";\nimport { buildBashTool, buildGlobTool, buildGrepTool, buildListDirectoryTool, buildReadFileTool } from \"../../tools\";\nimport { type DiscoveredFeature, loadFeatures, runFeatureDiscovery } from \"../00b-feature-discovery/index\";\nimport { CoverageState, type FeatureNode, loadBfsState } from \"./graph\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\nimport {\n buildCreateFolderTool,\n buildGetProgressTool,\n buildNextNodeTool,\n buildSpawnResearcherTool,\n buildWriteTestTool,\n} from \"./tools\";\nimport { validateTestContent } from \"./validation\";\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: undefined,\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) ?? undefined;\n const parentNode = parentId ? state.nodes.get(parentId) : undefined;\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(input: TestGeneratorInput): 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: \"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(join(input.outputDir, \"AUTONOMA.md\"), \"utf-8\");\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(join(input.outputDir, \"scenarios.md\"), \"utf-8\");\n kbContext += `\\n## Scenarios\\n\\n${scenariosMd}\\n`;\n } catch {\n /* scenarios not available */\n }\n\n let features: Map<string, DiscoveredFeature> | undefined;\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 =\n (input.projectContext ? \"\\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(model, input.projectRoot, heartbeat),\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(` [chunk] Queue empty after ${totalSteps} steps. Finishing.`);\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(input.outputDir, model, input.projectRoot);\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(input.outputDir, input.projectRoot, model);\n\n console.log(` Review: ${reviewResult.passed} passed, ${reviewResult.failed} failed`);\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 {\n /* already gone */\n }\n }\n\n // Fix in parallel - each test gets its own focused prompt\n console.log(` Feeding ${reviewResult.feedback.length} tests back to planner for fixes`);\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 try {\n await runAgent({ ...agentConfig, maxSteps: 30 }, fixPrompt, () => undefined);\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(join(input.outputDir, \"qa-tests\", \"**/*.md\"));\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(` ${markedInvalid} tests still invalid after review cycles - moved to _invalid/`);\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\n .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 })\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\nasync function generateIndex(outputDir: string, state: CoverageState): 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)) critCounts.set(critVal, (critCounts.get(critVal) ?? 0) + 1);\n const flowMatch = content.match(/flow:\\s*\"([^\"]+)\"/);\n const flowVal = flowMatch?.[1];\n if (flowVal) flowCounts.set(flowVal, (flowCounts.get(flowVal) ?? 0) + 1);\n const stepMatches = content.match(/^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm);\n if (stepMatches) totalSteps += stepMatches.length;\n const interactionMatches = content.match(/^\\d+\\.\\s+(click|type|drag):/gm);\n if (interactionMatches) totalInteractions += interactionMatches.length;\n } catch {\n /* file may not exist */\n }\n }\n }\n\n const avgSteps = 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()].flatMap(([_folder, tests]) => tests.map((t) => `- \\`${t}\\``)).join(\"\\n\")}\n`;\n\n await writeFile(join(outputDir, \"qa-tests\", \"INDEX.md\"), content, \"utf-8\");\n}\n\nasync function generateJourneyTests(outputDir: string, model: LanguageModel, projectRoot: string): 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 (err) {\n debugLog(\"AUTONOMA.md not present for journey generation\", { err });\n }\n try {\n scenariosMd = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch (err) {\n debugLog(\"scenarios.md not present for journey generation\", { err });\n }\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: undefined,\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","// MUST be first: guards the Node version before @clack/prompts (below) loads.\nimport \"./core/ensure-node\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { uploadRecipeFromDisk } from \"./agents/04-recipe-builder/phases/submit\";\nimport { loadConfig } from \"./config\";\nimport type { AgentResult } from \"./core/agent\";\nimport { track, trackError, flushAnalytics } from \"./core/analytics\";\nimport { BOLD, DIM, PRIMARY, RESET } from \"./core/colors\";\nimport { type ProjectContext, saveContext, loadContext } from \"./core/context\";\nimport { formatException, describeKnownError, supportReference, isUserCancellation } from \"./core/errors\";\nimport { installInterruptHandler, installTerminationDiagnostics, restoreTerminal } from \"./core/interrupt\";\nimport { DEFAULT_MODEL } from \"./core/model\";\nimport { ensureOutputDir } from \"./core/output\";\nimport { readEnv } from \"./env\";\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 { loadGitInfo, readGitInfo, saveGitInfo } from \"./core/git\";\nimport { notify } from \"./core/notify\";\nimport {\n applySelection,\n defaultBackendsFor,\n formatBackendScope,\n formatFrontendScope,\n loadProjectMap,\n type ProjectMap,\n pickDefaultSelection,\n renderProjectMap,\n resolveSelection,\n saveProjectMap,\n type ScopeSelection,\n} from \"./core/project-map\";\nimport { loadState, markStep, nextPendingStep, type StepName, type PipelineState } from \"./core/state\";\nimport { uploadArtifacts } from \"./core/upload\";\n\nconst PAGES_FILE = \"pages.json\";\n\nasync function savePages(\n outputDir: string,\n pages: Map<string, { route: string; path: string; description: string }>,\n): 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(\n outputDir: string,\n): 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\n// Pull a flag's value only when it was given as `--key value` (a string), not\n// as a bare boolean flag or absent. Keeps callers from having to narrow the\n// `string | boolean | undefined` index type by hand.\nfunction strArg(args: Record<string, string | boolean>, key: string): string | undefined {\n const value = args[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nconst STEP_LABELS: Record<StepName, string> = {\n projectMapper: \"Map your project structure\",\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\nfunction isStepName(value: string): value is StepName {\n return value in STEP_LABELS;\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 projectMapper: \"Identify your frontend(s), backend(s), and which folders to ignore.\",\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 projectMapper:\n \"Looking at how your codebase is laid out - which folder(s) are the frontend, which are the backend/data layer, and which are unrelated - so every later step scans only what matters instead of the whole repo.\",\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\n/**\n * Turn the mapper's candidate map into a single testable surface. Precedence:\n * (1) an explicit selection supplied by the caller (flags / harness) always wins;\n * (2) interactively, ask via a radio (frontend) + checkbox (backends) picker;\n * (3) non-interactively with no explicit choice, only proceed if unambiguous\n * (exactly one frontend), otherwise return undefined so the caller pauses.\n */\nasync function resolveScopeSelection(\n map: ProjectMap,\n config: ReturnType<typeof loadConfig>,\n nonInteractive?: boolean,\n): Promise<ScopeSelection | undefined> {\n if (config.frontend != null) {\n // Resolve tolerantly first: a fullstack app's own backend may be named at the\n // app root or a nested api dir depending on the run, so match the requested\n // path against what this map actually produced before defaulting the backends.\n const requestedFrontend = resolveSelection(map, { frontend: config.frontend, backends: [] }).frontend;\n // An explicit --backends is validated loudly by applySelection; a defaulted set\n // comes from the LLM's dependsOn, so drop entries that map to no real backend\n // instead of letting them reach applySelection and hard-fail the whole run.\n const backends = config.backends ?? defaultBackendsFor(map, requestedFrontend);\n return resolveSelection(map, { frontend: config.frontend, backends });\n }\n\n if (!nonInteractive) return promptScopeSelection(map);\n\n return pickDefaultSelection(map);\n}\n\n/** Interactive radio (frontend) + checkbox (backends, pre-checked to the frontend's dependencies). */\nasync function promptScopeSelection(map: ProjectMap): Promise<ScopeSelection> {\n const frontend = await p.select({\n message: \"Which frontend do you want to plan tests for?\",\n options: map.frontends.map((f) => ({ value: f.path, label: `${f.path} [${f.framework}]`, hint: f.why })),\n });\n if (p.isCancel(frontend)) throw new Error(\"Cancelled\");\n\n if (map.backends.length === 0) return { frontend, backends: [] };\n\n // Resolve dependsOn through the same tolerant matcher the non-interactive path uses, so a\n // dependency named by its data-layer schema path still pre-checks its owning backend option\n // (whose value is the backend's own path) instead of silently going un-checked.\n const needed = defaultBackendsFor(map, frontend);\n const backends = await p.multiselect({\n message: \"Which backends does it need? (pre-checked: the ones it depends on)\",\n options: map.backends.map((b) => ({ value: b.path, label: `${b.path} [${b.framework}]`, hint: b.why })),\n initialValues: needed,\n required: false,\n });\n if (p.isCancel(backends)) throw new Error(\"Cancelled\");\n\n return { frontend, backends };\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 \"projectMapper\": {\n const { runProjectMapper } = await import(\"./agents/00-project-mapper/index\");\n const map = await runProjectMapper({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n nonInteractive,\n });\n if (map == null) {\n result = { success: false, artifacts: [], summary: \"Project mapper did not produce a map.\" };\n break;\n }\n if (map.frontends.length === 0) {\n result = {\n success: false,\n artifacts: [],\n summary: \"Project mapper found no frontend to test. Point --project at a codebase with a UI.\",\n };\n break;\n }\n\n // The mapper only DISCOVERS candidates. Narrow to the one frontend we test\n // (radio) plus the backends it needs (checkbox). When non-interactive and\n // ambiguous, persist the candidates and pause so the caller (Claude / CI)\n // can resume with --frontend/--backends.\n const selection = await resolveScopeSelection(map, config, nonInteractive);\n if (selection == null) {\n await saveProjectMap(outputDir, map);\n p.note(renderProjectMap(map), \"Project map - candidates (pick one frontend + its backends)\");\n result = {\n success: false,\n paused: true,\n artifacts: [],\n summary:\n `Found ${map.frontends.length} candidate frontends. Choose one and its backends, then ` +\n \"resume with --frontend <path> --backends <path,path>.\",\n };\n break;\n }\n\n const scoped = applySelection(map, selection);\n await saveProjectMap(outputDir, scoped);\n p.note(renderProjectMap(scoped), \"Project map\");\n break;\n }\n case \"pagesFinder\": {\n const { runPageFinder } = await import(\"./agents/00-pages-finder/index\");\n const projectMap = await loadProjectMap(outputDir);\n const pages = await runPageFinder({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n nonInteractive,\n extraMessage: projectMap != null ? formatFrontendScope(projectMap) : undefined,\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 const auditMap = await loadProjectMap(outputDir);\n result = await runEntityAudit({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n projectContext,\n nonInteractive,\n retryGuidance,\n scopeHint: auditMap != null ? formatBackendScope(auditMap) : undefined,\n });\n break;\n }\n case \"scenarioRecipe\": {\n const { runScenarioRecipe } = await import(\"./agents/03-scenario-recipe/index\");\n const recipeMap = await loadProjectMap(outputDir);\n result = await runScenarioRecipe({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n retryGuidance,\n scopeHint: recipeMap != null ? formatBackendScope(recipeMap) : undefined,\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 {\n value: \"guidance\",\n label: \"Retry with guidance\",\n hint: \"Tell the agent what went wrong or what to focus on\",\n },\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.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 ? \"+\"\n : status === \"running\"\n ? \"~\"\n : status === \"paused\"\n ? \"‖\"\n : status === \"failed\"\n ? \"x\"\n : \" \";\n const label = isStepName(step) ? STEP_LABELS[step] : step;\n console.log(` [${icon}] ${label}: ${status}`);\n }\n}\n\nconst BANNER = `\n${PRIMARY}${BOLD} █████╗ ██╗ ██╗████████╗ ██████╗ ███╗ ██╗ ██████╗ ███╗ ███╗ █████╗\n██╔══██╗██║ ██║╚══██╔══╝██╔═══██╗████╗ ██║██╔═══██╗████╗ ████║██╔══██╗\n███████║██║ ██║ ██║ ██║ ██║██╔██╗ ██║██║ ██║██╔████╔██║███████║\n██╔══██║██║ ██║ ██║ ██║ ██║██║╚██╗██║██║ ██║██║╚██╔╝██║██╔══██║\n██║ ██║╚██████╔╝ ██║ ╚██████╔╝██║ ╚████║╚██████╔╝██║ ╚═╝ ██║██║ ██║\n╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n${RESET}\n${DIM} E2E Test Planner - Generate exhaustive test suites from your codebase${RESET}\n`;\n\n/**\n * Make sure the CLI is authenticated before doing anything else. The planner\n * runs on managed Autonoma credits via the Autonoma API token (AUTONOMA_API_TOKEN),\n * which the web app injects when it launches the CLI. There's no LLM key to\n * paste anymore - if the token is missing we error with instructions rather than\n * prompting. Returns false when unauthenticated.\n */\nfunction ensureAutonomaAuth(): boolean {\n if (readEnv().AUTONOMA_API_TOKEN?.trim()) return true;\n\n p.log.error(\n \"Not authenticated. Launch the planner from the Autonoma app, or set AUTONOMA_API_TOKEN (create a key at https://autonoma.app/settings/api-keys).\",\n );\n return false;\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,\n testingGoal,\n criticalFlows,\n };\n}\n\nasync function main() {\n // Before anything else, arm diagnostics so a SIGTERM/SIGHUP or a swallowed async\n // error leaves a greppable breadcrumb instead of the run just vanishing.\n installTerminationDiagnostics();\n\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: strArg(args, \"project\"),\n slug: strArg(args, \"slug\"),\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 === \"upload\") {\n const config = loadConfig({\n project: strArg(args, \"project\"),\n slug: strArg(args, \"slug\"),\n });\n const outputDir = await ensureOutputDir(config.projectSlug);\n // Re-upload everything already generated in `~/.autonoma/<app>/`: the recipe\n // first (so scenarios exist before tests reference them), then the artifacts\n // (tests/kb/scenarios), which also marks the setup completed. Both endpoints\n // are idempotent, so this is safe to run repeatedly to recover a failed run.\n const recipeUploaded = await uploadRecipeFromDisk(outputDir, {\n apiUrl: config.autonomaApiUrl,\n apiToken: config.autonomaApiToken,\n generationId: config.autonomaGenerationId,\n });\n await uploadArtifacts(config, outputDir);\n await flushAnalytics();\n process.exit(recipeUploaded ? 0 : 1);\n }\n\n if (command === \"help\" || args.help) {\n console.log(\"Usage:\");\n console.log(\n \" test-planner [run] [--project <path>] [--frontend <path>] [--backends <path,path>] [--model <id>] [--step <name>] [--resume] [--non-interactive]\",\n );\n console.log(\" test-planner status [--project <path>]\");\n console.log(\" test-planner upload [--project <path>] # re-upload already-generated recipe + artifacts\");\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 = `autonoma-planner --resume` + (args.project ? ` --project ${args.project}` : \"\");\n installInterruptHandler({\n // exitCode defaults to 0 for a user-initiated Ctrl+C (progress saved, a clean stop);\n // an external SIGTERM/SIGHUP passes the conventional 143/129 so the flushed exit still\n // carries the signal code a reaper/CI reads, not a 0 that looks like normal completion.\n onExit: (exitCode = 0) => {\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(exitCode));\n },\n });\n\n const backendsArg = strArg(args, \"backends\");\n const config = loadConfig({\n project: strArg(args, \"project\"),\n model: strArg(args, \"model\"),\n slug: strArg(args, \"slug\"),\n frontend: strArg(args, \"frontend\"),\n backends:\n backendsArg != null\n ? backendsArg\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n : undefined,\n });\n\n if (!ensureAutonomaAuth()) {\n return;\n }\n\n const nonInteractive = !!args[\"non-interactive\"];\n\n const modelName = config.modelId ?? readEnv().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((s) => s === \"done\" || s === \"running\");\n\n if (!isResuming && !nonInteractive && hasProgress) {\n const completedSteps = Object.entries(state.steps)\n .filter(([, s]) => s === \"done\")\n .map(([name]) => (isStepName(name) ? STEP_LABELS[name] : name))\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(\n \"Non-interactive mode requires saved project context. Run interactively first, or create .project-context.json manually.\",\n );\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(`Got it. I'll focus on: ${projectContext.criticalFlows}\\n` + ` Starting the pipeline now.`);\n console.log(\"\");\n\n const stepArg = strArg(args, \"step\");\n const targetStep: StepName | undefined = stepArg != null && isStepName(stepArg) ? stepArg : undefined;\n if (stepArg != null && targetStep == null) {\n p.log.error(`Unknown --step \"${stepArg}\". Valid steps: ${Object.keys(STEP_LABELS).join(\", \")}`);\n return;\n }\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) : \"projectMapper\";\n if (!startStep) {\n p.log.success(\"All steps complete.\");\n return;\n }\n\n const steps: StepName[] = [\n \"projectMapper\",\n \"pagesFinder\",\n \"kb\",\n \"entityAudit\",\n \"scenarioRecipe\",\n \"recipeBuilder\",\n \"testGenerator\",\n ];\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(steps.map((s, idx) => `${idx + 1}. ${STEP_LABELS[s]} - ${STEP_SUMMARIES[s]}`).join(\"\\n\"), \"Here's the plan\");\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","// Side-effect entry guard: verify the Node runtime before anything else loads.\n// This module is imported first in index.ts (ahead of @clack/prompts) so the\n// version check runs before any dependency can touch `util.styleText`. ESM\n// evaluates imports in order and before the module body, so a bare\n// `ensureSupportedNode()` call in the entry body would still run AFTER @clack's\n// import side-effects - defeating the fail-fast guarantee if a future @clack (or\n// other dep) ever touched `styleText` at import time.\nimport { ensureSupportedNode } from \"./node-version\";\n\nensureSupportedNode();\n","// Minimum Node.js the planner supports. Not arbitrary: @clack/prompts (our\n// interactive UI) calls `util.styleText([\"inverse\", \"hidden\"], ...)`, and the\n// array form of `styleText` only exists on Node >= 22.13 (and 23+). On older\n// Node the first prompt render throws a cryptic `The argument 'format' must be\n// one of: ...` error, so we fail fast here with an actionable message instead.\nexport const MIN_NODE = { major: 22, minor: 13 };\n\n/**\n * Whether a `major.minor.patch` version string clears the minimum. Malformed\n * input (missing/non-numeric major or minor) is treated as unsupported so we\n * fail closed rather than let a prompt crash slip through.\n */\nexport function isSupportedNodeVersion(raw: string): boolean {\n const parts = raw.split(\".\");\n const major = Number.parseInt(parts[0] ?? \"\", 10);\n const minor = Number.parseInt(parts[1] ?? \"\", 10);\n if (!Number.isFinite(major) || !Number.isFinite(minor)) return false;\n return major > MIN_NODE.major || (major === MIN_NODE.major && minor >= MIN_NODE.minor);\n}\n\n/**\n * Exit early with a clear message when the runtime is too old for the CLI's\n * dependencies. Uses plain `console` (not @clack) on purpose: @clack is exactly\n * what breaks on the unsupported versions, so it can't be trusted to render the\n * warning. Called as the very first thing the process does.\n */\nexport function ensureSupportedNode(): void {\n const raw = process.versions.node;\n if (isSupportedNodeVersion(raw)) return;\n\n console.error(\n `\\x1b[31mAutonoma Planner requires Node.js >= ${MIN_NODE.major}.${MIN_NODE.minor} - you're running v${raw}.\\x1b[0m`,\n );\n console.error(\"Please upgrade Node.js and re-run. See https://nodejs.org/en/download\");\n process.exit(1);\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { loadGlobalEnv } from \"./core/global-env\";\nimport { ENV_KEYS, readEnv } from \"./env\";\n\nexport interface AppConfig {\n projectRoot: string;\n projectSlug: string;\n modelId?: string;\n // Pre-supplied project-map selection (skips the interactive frontend/backend\n // picker): the single frontend to test and the backends it needs. Used by CI,\n // the eval harness, and any caller that already knows the target surface.\n frontend?: string;\n backends?: 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 // Only inject keys the CLI actually reads - never arbitrary project keys\n // (PATH, NODE_OPTIONS, ...) that happen to be in the target project's .env.\n if (ENV_KEYS.includes(key) && !(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 frontend?: string;\n backends?: 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 // Read AFTER the loaders so the validated env reflects the project/global\n // .env files just merged into process.env.\n const env = readEnv();\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 ?? env.OPENROUTER_MODEL,\n frontend: args.frontend,\n backends: args.backends,\n databaseUrl: env.DATABASE_URL,\n sdkEndpointUrl: env.SDK_ENDPOINT_URL,\n sharedSecret: env.AUTONOMA_SHARED_SECRET,\n signingSecret: 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: env.AUTONOMA_API_URL ?? \"https://autonoma.app\",\n autonomaApiToken: env.AUTONOMA_API_TOKEN,\n autonomaGenerationId: env.AUTONOMA_GENERATION_ID,\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { ENV_KEYS } from \"../env\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\nconst GLOBAL_ENV_PATH = join(AUTONOMA_HOME, \".env\");\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 ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\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 (ENV_KEYS.includes(key) && !(key in process.env)) {\n process.env[key] = value;\n }\n }\n}\n","import readline from \"node:readline\";\nimport { settings } from \"@clack/core\";\nimport { debugLog } from \"./debug\";\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> | undefined;\nlet onExit: ((exitCode?: number) => void) | undefined;\nlet quitting = false;\n\nfunction disarm(): void {\n if (armTimer) clearTimeout(armTimer);\n armTimer = undefined;\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: (exitCode?: number) => 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 // The one unavoidable assertion in this package: readline.createInterface is\n // an overloaded builtin, and a single-signature wrapper is not structurally\n // assignable to its overload set without bridging the type here.\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/**\n * Surface *why* the process ends when it isn't a clean Ctrl+C: an external\n * SIGTERM/SIGHUP (a task reaper, a parent shell going away, an OOM-adjacent kill),\n * or a crash from an unhandled exception/rejection that would otherwise die with no\n * breadcrumb. Each writes one greppable `[diagnostics]` line - including memory stats,\n * which hint at pressure-related kills - before letting the process go. SIGKILL cannot\n * be caught and leaves no trace by design; if a run vanishes with none of these lines,\n * it was SIGKILL (or the host pulled the whole environment).\n */\nexport function installTerminationDiagnostics(): void {\n const memSnapshot = (): string => {\n const m = process.memoryUsage();\n const mb = (n: number): number => Math.round(n / 1024 / 1024);\n return `rss=${mb(m.rss)}MB heapUsed=${mb(m.heapUsed)}MB heapTotal=${mb(m.heapTotal)}MB`;\n };\n\n for (const signal of [\"SIGTERM\", \"SIGHUP\"] as const) {\n // 128 + signal number (SIGTERM=15, SIGHUP=1), the conventional exit codes.\n const forcedCode = signal === \"SIGTERM\" ? 143 : 129;\n process.on(signal, () => {\n process.stderr.write(`\\n[diagnostics] received ${signal} - external termination (${memSnapshot()})\\n`);\n terminateGracefully(forcedCode);\n });\n }\n\n process.on(\"uncaughtException\", (err) => {\n const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);\n process.stderr.write(`\\n[diagnostics] uncaughtException (${memSnapshot()}): ${detail}\\n`);\n restoreTerminal();\n process.exit(1);\n });\n\n // An unhandled rejection is an un-awaited promise that failed - a real bug. Node's default\n // is to terminate the process; a listener that only logged would silently override that and\n // let the pipeline continue in a corrupted state (emitting a bad plan/factory from a\n // half-finished step). Surface the breadcrumb, then honor the crash instead of swallowing it.\n process.on(\"unhandledRejection\", (reason) => {\n const detail = reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);\n process.stderr.write(`\\n[diagnostics] unhandledRejection (${memSnapshot()}): ${detail}\\n`);\n restoreTerminal();\n process.exit(1);\n });\n}\n\n/**\n * Terminate in response to an external signal, but let the graceful shutdown hook run first so\n * buffered analytics are flushed and the resume hint is printed. The hook is handed `forcedCode`\n * so its own exit carries the conventional signal code (143/129) instead of a clean 0 - otherwise\n * a reaper/CI reading the exit code couldn't tell an external kill from normal completion. A\n * FORCE_EXIT_MS failsafe guarantees the process still closes with that code if the async flush\n * ever stalls; with no hook wired (or a graceful exit already in flight) we exit immediately.\n */\nfunction terminateGracefully(forcedCode: number): void {\n if (quitting || onExit == null) {\n restoreTerminal();\n process.exit(forcedCode);\n }\n quitting = true;\n setTimeout(() => {\n restoreTerminal();\n process.exit(forcedCode);\n }, FORCE_EXIT_MS).unref?.();\n onExit(forcedCode);\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 (err) {\n debugLog(\"Could not restore terminal raw mode\", { err });\n }\n process.stdout.write(SHOW_CURSOR);\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\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 { 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\";\nimport { z } from \"zod\";\nimport { debugLog } from \"./debug\";\n\nconst StepStatusSchema = z.enum([\"pending\", \"running\", \"done\", \"failed\", \"paused\"]);\n\nexport type StepStatus = z.infer<typeof StepStatusSchema>;\n\n// A step key absent from an existing state file predates that step's introduction, so an\n// older run never had a chance to run it. Default missing keys to \"done\" on load so adding a\n// new pipeline step never silently re-triggers work an already-completed run considers finished.\nconst PipelineStateSchema = z.object({\n steps: z.object({\n projectMapper: StepStatusSchema.default(\"done\"),\n pagesFinder: StepStatusSchema.default(\"done\"),\n kb: StepStatusSchema.default(\"done\"),\n entityAudit: StepStatusSchema.default(\"done\"),\n scenarioRecipe: StepStatusSchema.default(\"done\"),\n recipeBuilder: StepStatusSchema.default(\"done\"),\n testGenerator: StepStatusSchema.default(\"done\"),\n }),\n});\n\nexport type PipelineState = z.infer<typeof PipelineStateSchema>;\n\nconst STATE_FILE = \".pipeline-state.json\";\n\nexport function initialState(): PipelineState {\n return {\n steps: {\n projectMapper: \"pending\",\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 PipelineStateSchema.parse(JSON.parse(raw));\n } catch (err) {\n // Missing file is the expected first-run path; a present-but-unreadable/invalid file\n // means we are silently discarding prior progress, so leave a breadcrumb for that case.\n const isMissingFile = err instanceof Error && \"code\" in err && err.code === \"ENOENT\";\n if (!isMissingFile) debugLog(\"Failed to load pipeline state, starting fresh\", { path, err });\n return initialState();\n }\n}\n\nexport async function saveState(outputDir: string, state: PipelineState): 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 | undefined {\n const order: StepName[] = [\n \"projectMapper\",\n \"pagesFinder\",\n \"kb\",\n \"entityAudit\",\n \"scenarioRecipe\",\n \"recipeBuilder\",\n \"testGenerator\",\n ];\n return order.find((s) => state.steps[s] !== \"done\") ?? undefined;\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 { debugLog } from \"./debug\";\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 (err) {\n // Not every run produces every artifact (e.g. no entity audit); skip\n // the ones that aren't on disk.\n debugLog(`Artifact ${name} not on disk; skipping upload`, { err });\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"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["RECIPE_FILE","text","readFileSync","join","fileURLToPath","readFileSync","homedir","join","AUTONOMA_HOME","resolve","readFile","writeFile","join","p","resolve","execFile","readFile","writeFile","join","z","path","p","path","log","summary","YELLOW","RESET","readFile","join","relative","glob","execFile","promisify","z","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","tool","SYSTEM_PROMPT","path","tool","z","input","join","p","path","resolve","RESET","editor","DIM","readFile","join","BOLD","RESET","DIM","SYSTEM_PROMPT","readFile","join","resolve","tool","z","SYSTEM_PROMPT","path","p","readFile","join","matter","z","truncate","pad","BOLD","RESET","DIM","YELLOW","SYSTEM_PROMPT","init_prompt","readFile","writeFile","join","tool","glob","z","buildFinishTool","MAX_STEPS","SYSTEM_PROMPT","init_prompt","readFile","join","init_prompt","readFile","join","matter","truncate","pad","BOLD","RESET","DIM","buildFinishTool","readFile","join","tool","z","init_prompt","z","existsSync","join","RESET","text","collectRefs","p","readFile","writeFile","join","STATE_FILE","Output","generateText","z","writeFile","readFile","join","p","tool","spawn","z","resolve","DOCS_BASE","p","tool","z","p","tool","z","SYSTEM_PROMPT","readFile","join","p","z","basename","tool","readFile","join","relative","basename","glob","init_review","readFile","writeFile","join","tool","z","path","SYSTEM_PROMPT","readFile","writeFile","join","path","STATE_FILE","SYSTEM_PROMPT","init_prompt","matter","mkdir","writeFile","dirname","join","hasToolCall","stepCountIs","tool","ToolLoopAgent","matter","z","resultSchema","init_tools","mkdir","readFile","writeFile","basename","join","tool","z","glob","SYSTEM_PROMPT","p","content","init_review","init_prompt","init_tools","readFile","writeFile","join","p","readFileSync","join","join","readFileSync","join","DIM","RESET","homedir","join","AUTONOMA_HOME","join","AUTONOMA_HOME","readFile","writeFile","join","readFile","writeFile","join","z","path","readFile","join","p","readFile","join","text","writeFile","join","readFile","runProjectMapper","runPageFinder","runKBGenerator","runEntityAudit","runScenarioRecipe","runRecipeBuilder","runTestGenerator","config","outputDir"]}
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_@swc+core@1.15.3_jiti@2.6.1_postcss@8.5.15_tsx@4.21.0_typescript@7.0.2_yaml@2.8.3/node_modules/tsup/assets/esm_shims.js","../src/ui/artifacts/registry.ts","../src/env.ts","../src/core/debug.ts","../src/ui/theme.ts","../src/ui/components/render-content.ts","../src/core/state.ts","../src/ui/steps.ts","../src/ui/eta.ts","../src/ui/nav.ts","../src/ui/prompt.ts","../src/ui/store.ts","../src/ui/prompts.ts","../src/agents/04-recipe-builder/recipe.ts","../src/agents/04-recipe-builder/phases/submit.ts","../src/core/version.ts","../src/core/analytics.ts","../src/core/colors.ts","../src/core/context.ts","../src/core/errors.ts","../src/core/ui-lifecycle.ts","../src/core/interrupt.ts","../src/core/model.ts","../src/core/notify.ts","../src/core/project-map.ts","../src/core/display.ts","../src/core/agent.ts","../src/core/gitignore.ts","../src/core/exec-error.ts","../src/tools/bash.ts","../src/tools/glob.ts","../src/tools/grep.ts","../src/tools/list-directory.ts","../src/tools/read-file.ts","../src/core/pick-string.ts","../src/tools/subagent.ts","../src/tools/write-file.ts","../src/tools/ask-user.ts","../src/tools/index.ts","../src/agents/00-project-mapper/coverage.ts","../src/agents/00-project-mapper/index.ts","../src/agents/00-pages-finder/index.ts","../src/core/progress.ts","../src/agents/01-kb-generator/prompt.ts","../src/agents/01-kb-generator/index.ts","../src/agents/02-entity-audit/prompt.ts","../src/agents/02-entity-audit/index.ts","../src/core/parse-entity-audit.ts","../src/agents/03-scenario-recipe/prompt.ts","../src/agents/03-scenario-recipe/scenario-table.ts","../src/agents/03-scenario-recipe/index.ts","../src/agents/04-recipe-builder/entity-order.ts","../src/agents/04-recipe-builder/completion.ts","../src/agents/04-recipe-builder/launcher.ts","../src/agents/04-recipe-builder/integration-prompt.ts","../src/agents/04-recipe-builder/state.ts","../src/agents/04-recipe-builder/phases/handoff.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/00b-feature-discovery/index.ts","../src/agents/05-test-generator/graph.ts","../src/agents/05-test-generator/prompt.ts","../src/agents/05-test-generator/validation.ts","../src/agents/05-test-generator/tools.ts","../src/agents/05-test-generator/index.ts","../src/ui/artifacts/reader.ts","../src/ui/artifacts/watcher.ts","../src/ui/draw/chrome.ts","../src/ui/draw/wrap.ts","../src/ui/draw/countdown.ts","../src/ui/draw/help.ts","../src/ui/draw/prompt.ts","../src/ui/draw/dashboard.ts","../src/ui/hooks/useTerminalSize.ts","../src/ui/grid.ts","../src/ui/screens/Dashboard.tsx","../src/ui/App.tsx","../src/ui/hooks/useStore.ts","../src/ui/Live.tsx","../src/ui/mount.tsx","../src/index.ts","../src/core/ensure-node.ts","../src/core/node-version.ts","../src/agents/04-recipe-builder/sdk-command.ts","../src/agents/04-recipe-builder/http-client.ts","../src/config.ts","../src/core/global-env.ts","../src/core/output.ts","../src/core/git.ts","../src/core/upload.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 type { Artifact, ContentKind } from \"../types\";\n\n/**\n * The well-known pipeline artifacts: human title (the primary label in the\n * FILES list and hero header) plus a friendly one-liner. Display-only: the\n * on-disk names are contracts (downstream agents and the handoff prompt\n * reference them) and must never change. Test files aren't listed; their\n * kebab names are already self-describing.\n */\nconst KNOWN_FILES: Record<string, { title: string; description?: string }> = {\n \"project-map.json\": { title: \"Project Map\", description: \"Your repo's frontend + backend layout\" },\n \"pages.json\": { title: \"Page Inventory\", description: \"Every route in the app\" },\n \"AUTONOMA.md\": { title: \"Knowledge Base\", description: \"What your app does\" },\n \"entity-audit.md\": { title: \"Database Entity Analysis\", description: \"What your app stores\" },\n \"scenarios.md\": { title: \"Test Data Scenarios\", description: \"The data your tests run against\" },\n \"recipe.json\": { title: \"Test Data Recipe\", description: \"How test data is created\" },\n \"IMPLEMENTATION.md\": { title: \"SDK Integration Checklist\", description: \"SDK integration progress notes\" },\n \"INDEX.md\": { title: \"Test Suite Index\", description: \"Every test in the suite\" },\n \"integration-prompt.md\": { title: \"Integration Instructions\", description: \"The coding agent's spec\" },\n \"autonoma-config.json\": { title: \"Planner Config\", description: \"How the planner runs on this repo\" },\n};\n\nexport function basename(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\nexport function kindOf(path: string): ContentKind {\n if (path.endsWith(\".json\")) return \"json\";\n if (path.endsWith(\".md\") || path.endsWith(\".markdown\")) return \"markdown\";\n return \"plain\";\n}\n\n/** Whether a path is a generated test file (they sort alphabetically in the FILES list). */\nexport function isTestArtifact(relPath: string): boolean {\n return relPath.includes(\"qa-tests/\") || relPath.includes(\"tests/\");\n}\n\nexport function iconOf(relPath: string): Artifact[\"icon\"] {\n if (relPath.endsWith(\".json\")) return \"json\";\n if (isTestArtifact(relPath)) return \"test\";\n return \"doc\";\n}\n\n/** Human title for a well-known artifact; undefined for tests/unknown files. */\nexport function titleOf(relPath: string): string | undefined {\n return KNOWN_FILES[basename(relPath)]?.title;\n}\n\n/** Human description for an artifact given its path relative to the output dir. */\nexport function describeArtifact(relPath: string): string | undefined {\n const name = basename(relPath);\n const known = KNOWN_FILES[name]?.description;\n if (known != null) return known;\n // Tests nest arbitrarily deep (qa-tests/<area>/<sub>/...); the folder path\n // is what distinguishes same-named tests, so show it under the name.\n if (iconOf(relPath) === \"test\") {\n const dir = relPath.split(\"/\").slice(0, -1).join(\"/\");\n return dir === \"\" ? \"natural-language test\" : `${dir}/`;\n }\n return undefined;\n}\n","import { createEnv } from \"@t3-oss/env-core\";\nimport { z } from \"zod\";\n\n// Every environment variable the CLI reads. Defined once so it doubles as the\n// allowlist the .env loaders use - they only inject these keys from a project's\n// .env / the global ~/.autonoma/.env into process.env, never arbitrary keys\n// like PATH or NODE_OPTIONS that happen to live in the target project's .env.\nconst ENV_SCHEMA = {\n // Model id override (OpenRouter-style id, forwarded by the managed proxy).\n OPENROUTER_MODEL: z.string().optional(),\n DATABASE_URL: z.string().optional(),\n AUTONOMA_SHARED_SECRET: z.string().optional(),\n AUTONOMA_SIGNING_SECRET: z.string().optional(),\n AUTONOMA_API_URL: z.string().optional(),\n AUTONOMA_API_TOKEN: z.string().optional(),\n AUTONOMA_GENERATION_ID: z.string().optional(),\n AUTONOMA_POSTHOG_KEY: z.string().optional(),\n AUTONOMA_POSTHOG_HOST: z.string().optional(),\n AUTONOMA_DISTINCT_ID: z.string().optional(),\n DONT_TRACK: z.string().optional(),\n AUTONOMA_DEBUG: z.string().optional(),\n EDITOR: z.string().optional(),\n VISUAL: z.string().optional(),\n} satisfies Record<string, z.ZodTypeAny>;\n\n/** Keys the CLI recognizes; the .env loaders inject only these into process.env. */\nexport const ENV_KEYS: readonly string[] = Object.keys(ENV_SCHEMA);\n\n/**\n * Single, validated entry point for the CLI's environment (AGENTS.md rule 25).\n *\n * Unlike a server app, the CLI populates process.env at RUNTIME - from the\n * target project's .env and the global ~/.autonoma/.env (see config.ts and\n * core/global-env.ts) - so the env is validated on demand through this accessor\n * rather than snapshotted once at import. Every key is optional; callers supply\n * defaults or error when a required value (e.g. AUTONOMA_API_TOKEN) is missing.\n * This is the only module that reads process.env for configuration.\n */\nexport function readEnv() {\n return createEnv({\n server: ENV_SCHEMA,\n runtimeEnv: process.env,\n emptyStringAsUndefined: true,\n });\n}\n\nexport type CliEnv = ReturnType<typeof readEnv>;\n","import { readEnv } from \"../env\";\n\n/**\n * Emit a diagnostic breadcrumb to stderr, gated behind AUTONOMA_DEBUG.\n *\n * The CLI drives its interactive UI on stderr, so benign swallowed errors (file\n * not found, optional cleanup, best-effort telemetry) are logged here rather\n * than polluting normal output or being silently discarded. Set AUTONOMA_DEBUG=1\n * to surface them when investigating.\n */\nexport function debugLog(message: string, context?: Record<string, unknown>): void {\n const flag = readEnv().AUTONOMA_DEBUG;\n if (flag !== \"1\" && flag !== \"true\") return;\n const suffix = context != null ? ` ${JSON.stringify(context, replaceErrors)}` : \"\";\n process.stderr.write(`[autonoma:debug] ${message}${suffix}\\n`);\n}\n\nfunction replaceErrors(_key: string, value: unknown): unknown {\n if (value instanceof Error) return { name: value.name, message: value.message, stack: value.stack };\n return value;\n}\n","/**\n * Design tokens for the TUI (see docs/ui-design-brief.md). The accent is\n * blacklight's brand lime, matching src/core/colors.ts. Hierarchy comes from\n * color tier + bold + background fills + spacing - never font size.\n */\nexport const theme = {\n /** Primary accent: active step, progress, primary action, brand. */\n accent: \"#CCFF00\",\n /** Body text. */\n text: \"#EDEDED\",\n /** The \"why\" lines, descriptions. */\n secondary: \"#898989\",\n /** Eyebrows, timestamps, dim labels. */\n tertiary: \"#707070\",\n /** Queued / inert. */\n faint: \"#444444\",\n\n sky: \"#38BDF8\", // WRITING / live / read calls\n violet: \"#8B5CF6\", // search / propose calls\n green: \"#3FB950\", // validation passed, success\n amber: \"#FFB020\", // paused / awaiting review\n orange: \"#FF8800\", // teardown / delete calls\n red: \"#FF5C5C\", // failures only\n\n /** Lime-tinted active-row / focus fill (solid approximation of rgba lime). */\n activeBg: \"#1a2004\",\n /** Neutral fill for the keyboard-selection cursor row. */\n selectionBg: \"#2a2a2a\",\n /** Black-on-lime text for primary buttons / pills. */\n onAccent: \"#050505\",\n\n border: \"#333333\", // panel hairlines\n borderChrome: \"#454545\", // chrome dividers (column separators)\n cardEdge: \"#4a4a4a\", // card border edges (corners use accent)\n} as const;\n\n/** Step status -> color for pipeline rendering. */\nexport const statusColor = {\n pending: theme.faint,\n running: theme.accent,\n done: theme.accent,\n failed: theme.red,\n paused: theme.amber,\n} as const;\n","import matter from \"gray-matter\";\nimport { z } from \"zod\";\nimport { debugLog } from \"../../core/debug\";\nimport { theme } from \"../theme\";\nimport type { ContentKind } from \"../types\";\n\nexport interface Span {\n text: string;\n color?: string;\n bold?: boolean;\n dim?: boolean;\n}\n\nexport type StyledLine = Span[];\n\n/** Widest first column in frontmatter/pages tables before truncation. */\nconst TABLE_KEY_MAX = 34;\n\n/**\n * Turn a file's contents into styled lines for the hero panel. Line-oriented on\n * purpose: it lets the panel slice to its viewport and only ever render ~40\n * lines regardless of file size.\n *\n * Known pipeline documents get document-aware rendering: markdown frontmatter\n * becomes a readable info card (scalars as key/value, arrays as tables) and\n * pages.json becomes a route table.\n *\n * Memoized on (text, kind, name): the dashboard repaints on every store change\n * and clock tick, and re-parsing a large document each frame is what makes the\n * UI crawl.\n */\nexport function renderContent(text: string, kind: ContentKind, name?: string): StyledLine[] {\n if (memo != null && memo.text === text && memo.kind === kind && memo.name === name) return memo.lines;\n const lines = renderUncached(text, kind, name);\n memo = { text, kind, name, lines };\n return lines;\n}\n\nlet memo: { text: string; kind: ContentKind; name?: string; lines: StyledLine[] } | undefined;\n\n/**\n * Wrapped variant for the viewer: long lines fold at `width` (word-aware,\n * falling back to a hard cut for unbroken runs). Separately memoized - the\n * viewer calls this every repaint.\n */\nexport function renderContentWrapped(\n text: string,\n kind: ContentKind,\n name: string | undefined,\n width: number,\n): StyledLine[] {\n if (\n wrapMemo != null &&\n wrapMemo.text === text &&\n wrapMemo.kind === kind &&\n wrapMemo.name === name &&\n wrapMemo.width === width\n ) {\n return wrapMemo.lines;\n }\n const lines = wrapStyledLines(renderContent(text, kind, name), width);\n wrapMemo = { text, kind, name, width, lines };\n return lines;\n}\n\nlet wrapMemo: { text: string; kind: ContentKind; name?: string; width: number; lines: StyledLine[] } | undefined;\n\n/** Leading space count of a styled line (across spans). */\nfunction leadingSpaces(line: StyledLine): number {\n let n = 0;\n for (const span of line) {\n for (const ch of span.text) {\n if (ch !== \" \") return n;\n n++;\n }\n }\n return n;\n}\n\n/**\n * Fold styled lines at `width`, preserving span styles across the fold.\n * Indented lines get a hanging indent: continuations align under the line's\n * first non-space column, so a wrapped detail line (a table's dim note, a\n * nested path) reads as one block instead of snapping back to column 0.\n */\nexport function wrapStyledLines(lines: StyledLine[], width: number): StyledLine[] {\n if (width < 8) return lines;\n const out: StyledLine[] = [];\n for (const line of lines) {\n const total = line.reduce((n, s) => n + s.text.length, 0);\n if (total <= width) {\n out.push(line);\n continue;\n }\n const leading = leadingSpaces(line);\n const indent = leading > 0 && leading <= Math.floor(width / 2) ? leading : 0;\n // Flatten to a char stream so folds can cross span boundaries.\n const chars: { ch: string; span: Span }[] = [];\n for (const span of line) for (const ch of span.text) chars.push({ ch, span });\n let start = 0;\n let first = true;\n while (start < chars.length) {\n const avail = first ? width : width - indent;\n let end = Math.min(start + avail, chars.length);\n if (end < chars.length) {\n // Prefer breaking at the last space, unless it is too far back.\n let back = end;\n while (back > start && chars[back - 1]!.ch !== \" \") back--;\n if (back > start + Math.floor(avail / 2)) end = back;\n }\n const folded: StyledLine = [];\n for (let i = start; i < end; i++) {\n const { ch, span } = chars[i]!;\n const last = folded[folded.length - 1];\n if (last != null && chars[i - 1]?.span === span && i > start) last.text += ch;\n else folded.push({ text: ch, color: span.color, bold: span.bold, dim: span.dim });\n }\n if (!first && indent > 0) folded.unshift({ text: \" \".repeat(indent) });\n out.push(folded.length ? folded : [{ text: \"\" }]);\n start = end;\n while (start < chars.length && chars[start]!.ch === \" \") start++;\n first = false;\n }\n }\n return out;\n}\n\nfunction renderUncached(text: string, kind: ContentKind, name?: string): StyledLine[] {\n if (name === \"pages.json\") {\n const table = renderPagesJson(text);\n if (table != null) return table;\n }\n if (name === \"project-map.json\") {\n const sections = renderStructuredJson(text);\n if (sections != null) return sections;\n }\n if (name === \"entity-audit.md\") {\n const audit = renderEntityAudit(text);\n if (audit != null) return audit;\n }\n switch (kind) {\n case \"json\":\n return text.split(\"\\n\").map(jsonLine);\n case \"markdown\":\n return markdownDocument(text);\n default:\n return text.split(\"\\n\").map((l) => [{ text: l }]);\n }\n}\n\n/* ------------------------------------------------------------- frontmatter -- */\n\n/**\n * Markdown with YAML frontmatter renders as an info card (the parsed data,\n * readable) followed by the styled body. Raw YAML - especially AUTONOMA.md's\n * pages/core_flows arrays - is noise when shown verbatim.\n */\nfunction markdownDocument(text: string): StyledLine[] {\n if (!text.startsWith(\"---\\n\")) return markdownLines(text.split(\"\\n\"));\n\n let parsed: { data: Record<string, unknown>; content: string };\n try {\n parsed = matter(text);\n } catch (err) {\n debugLog(\"Frontmatter parse failed, rendering raw markdown\", { err });\n return markdownLines(text.split(\"\\n\"));\n }\n\n const entries = Object.entries(parsed.data);\n if (entries.length === 0) return markdownLines(parsed.content.split(\"\\n\"));\n\n const out: StyledLine[] = [];\n const scalars = entries.filter(([, v]) => !Array.isArray(v));\n const arrays = entries.filter((e): e is [string, unknown[]] => Array.isArray(e[1]));\n\n for (const [key, value] of scalars) {\n out.push([{ text: `${key} `, color: theme.accent }, { text: formatScalar(value) }]);\n }\n for (const [key, items] of arrays) {\n out.push([{ text: \"\" }]);\n out.push([\n { text: key, color: theme.accent, bold: true },\n { text: ` ${items.length} ${items.length === 1 ? \"entry\" : \"entries\"}`, color: theme.tertiary },\n ]);\n out.push(...renderArrayTable(items));\n }\n\n if (parsed.content.trim() !== \"\") {\n out.push([{ text: \"\" }]);\n out.push([{ text: \"─\".repeat(40), color: theme.border }]);\n out.push([{ text: \"\" }]);\n out.push(...markdownLines(parsed.content.replace(/^\\n+/, \"\").split(\"\\n\")));\n }\n return out;\n}\n\nfunction formatScalar(value: unknown): string {\n if (value == null) return \"\";\n if (Array.isArray(value)) return value.map((v) => formatScalar(v)).join(\", \");\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n}\n\n/**\n * An array of objects renders as a two-column table: the identifying field\n * (page/feature/route/name/...) then the description; remaining fields become\n * a dim annotation line. Arrays of scalars render as a plain list.\n */\nfunction renderArrayTable(items: unknown[]): StyledLine[] {\n const out: StyledLine[] = [];\n const KEY_FIELDS = [\"page\", \"feature\", \"route\", \"path\", \"name\", \"model\", \"flow\"];\n const TEXT_FIELDS = [\"description\", \"mission\", \"summary\", \"why\"];\n\n const keyWidth = Math.min(\n TABLE_KEY_MAX,\n Math.max(...items.map((item) => keyFieldOf(item, KEY_FIELDS)?.length ?? 0), 4),\n );\n\n for (const item of items) {\n if (item == null || typeof item !== \"object\") {\n out.push([{ text: \" - \", color: theme.secondary }, { text: formatScalar(item) }]);\n continue;\n }\n const record: Record<string, unknown> = { ...item };\n const key = keyFieldOf(item, KEY_FIELDS) ?? \"\";\n const textField = TEXT_FIELDS.find((f) => typeof record[f] === \"string\");\n const description = textField != null ? String(record[textField]) : \"\";\n const consumed = new Set([...KEY_FIELDS, ...(textField != null ? [textField] : [])]);\n const rest = Object.entries(record).filter(([k, v]) => !consumed.has(k) && v != null && v !== false);\n\n out.push([\n { text: \" \", color: theme.secondary },\n { text: pad(key, keyWidth), color: theme.sky },\n { text: \" \" },\n { text: description, color: theme.text },\n ]);\n if (rest.length > 0) {\n const note = rest.map(([k, v]) => (v === true ? k : `${k}: ${formatScalar(v)}`)).join(\" · \");\n out.push([{ text: \" \".repeat(keyWidth + 4) }, { text: note, color: theme.tertiary }]);\n }\n }\n return out;\n}\n\nfunction keyFieldOf(item: unknown, fields: string[]): string | undefined {\n if (item == null || typeof item !== \"object\") return undefined;\n const record: Record<string, unknown> = { ...item };\n for (const f of fields) {\n if (typeof record[f] === \"string\") return String(record[f]);\n }\n return undefined;\n}\n\nfunction pad(s: string, w: number): string {\n if (s.length > w) return s.slice(0, w - 1) + \"…\";\n return s.padEnd(w, \" \");\n}\n\n/**\n * A JSON document whose top-level values are arrays of objects (project-map:\n * frontends / backends / ignore) renders as labeled sections of the same\n * two-column tables the frontmatter card uses.\n */\nfunction renderStructuredJson(text: string): StyledLine[] | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (err) {\n debugLog(\"Structured JSON parse failed, falling back to raw view\", { err });\n return undefined;\n }\n if (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) return undefined;\n\n const record: Record<string, unknown> = { ...parsed };\n const sections = Object.entries(record).filter((e): e is [string, unknown[]] => Array.isArray(e[1]));\n if (sections.length === 0) return undefined;\n\n const out: StyledLine[] = [];\n for (const [key, items] of sections) {\n if (out.length > 0) out.push([{ text: \"\" }]);\n out.push([\n { text: key, color: theme.accent, bold: true },\n { text: ` ${items.length} ${items.length === 1 ? \"entry\" : \"entries\"}`, color: theme.tertiary },\n ]);\n out.push(...renderArrayTable(items));\n }\n return out;\n}\n\n/* ---------------------------------------------------------- entity-audit.md -- */\n\nconst CreatedBySchema = z.object({\n owner: z.string(),\n via: z.string().optional(),\n why: z.string().optional(),\n});\n\nconst AuditModelSchema = z.object({\n name: z.string(),\n independently_created: z.boolean().optional(),\n creation_file: z.string().optional(),\n creation_function: z.string().optional(),\n side_effects: z.array(z.string()).optional(),\n created_by: z.array(CreatedBySchema).optional(),\n});\n\ntype AuditModel = z.infer<typeof AuditModelSchema>;\n\n/** Column reserved for the FACTORY / via-owner badge. */\nconst AUDIT_BADGE_W = 12;\n\n/**\n * entity-audit.md's frontmatter is one huge `models:` array - unreadable as raw\n * YAML and noisy through the generic card. Render it as a model table instead:\n * name, how the model comes into existence (own factory vs via an owner), and\n * where in the code that happens.\n */\nfunction renderEntityAudit(text: string): StyledLine[] | undefined {\n if (!text.startsWith(\"---\\n\")) return undefined;\n let parsed: { data: Record<string, unknown>; content: string };\n try {\n parsed = matter(text);\n } catch (err) {\n debugLog(\"entity-audit.md frontmatter parse failed, falling back\", { err });\n return undefined;\n }\n const raw = parsed.data.models;\n if (!Array.isArray(raw)) return undefined;\n\n const models: AuditModel[] = [];\n for (const item of raw) {\n const result = AuditModelSchema.safeParse(item);\n if (result.success) models.push(result.data);\n }\n if (models.length === 0) return undefined;\n\n const factories = models.filter((m) => m.independently_created === true).length;\n const out: StyledLine[] = [];\n out.push([\n { text: \"models\", color: theme.accent, bold: true },\n { text: ` ${models.length} total`, color: theme.tertiary },\n { text: \" \", color: theme.faint },\n { text: `● ${factories} with a factory`, color: theme.accent },\n { text: \" \", color: theme.faint },\n { text: `○ ${models.length - factories} created via owners`, color: theme.violet },\n ]);\n out.push([{ text: \"\" }]);\n\n const nameW = Math.min(TABLE_KEY_MAX, Math.max(...models.map((m) => m.name.length), 4));\n for (const m of models) {\n out.push(auditRow(m, nameW));\n const note = auditNote(m);\n if (note != null) out.push([{ text: \" \".repeat(nameW + AUDIT_BADGE_W + 4) }, note]);\n }\n\n if (parsed.content.trim() !== \"\") {\n out.push([{ text: \"\" }]);\n out.push([{ text: \"─\".repeat(40), color: theme.border }]);\n out.push([{ text: \"\" }]);\n out.push(...markdownLines(parsed.content.replace(/^\\n+/, \"\").split(\"\\n\")));\n }\n return out;\n}\n\nfunction auditRow(m: AuditModel, nameW: number): StyledLine {\n const root = m.independently_created === true;\n const badge = root ? \"● factory\" : \"○ via\";\n const owners = [...new Set((m.created_by ?? []).map((c) => c.owner))];\n const how = root ? (m.creation_function ?? m.creation_file ?? \"\") : owners.length > 0 ? owners.join(\", \") : \"-\";\n return [\n { text: \" \" },\n { text: pad(m.name, nameW), color: theme.sky },\n { text: \" \" },\n { text: pad(badge, AUDIT_BADGE_W), color: root ? theme.accent : theme.violet },\n { text: how, color: root ? theme.text : theme.secondary },\n ];\n}\n\n/** The dim second line: where creation happens, its side effects, or the why. */\nfunction auditNote(m: AuditModel): Span | undefined {\n const parts: string[] = [];\n if (m.independently_created === true) {\n if (m.creation_file != null && m.creation_function != null) parts.push(m.creation_file);\n if (m.side_effects != null && m.side_effects.length > 0) {\n parts.push(`side effects: ${m.side_effects.join(\", \")}`);\n }\n const owners = [...new Set((m.created_by ?? []).map((c) => c.owner))];\n if (owners.length > 0) parts.push(`also created by ${owners.join(\", \")}`);\n } else {\n const why = m.created_by?.find((c) => c.why != null)?.why;\n const via = m.created_by?.find((c) => c.via != null)?.via;\n if (why != null) parts.push(why);\n else if (via != null) parts.push(`via ${via}`);\n }\n if (parts.length === 0) return undefined;\n return { text: parts.join(\" · \"), color: theme.tertiary };\n}\n\n/* --------------------------------------------------------------- pages.json -- */\n\n/** pages.json is a record of { route, path, description } - render a route table. */\nfunction renderPagesJson(text: string): StyledLine[] | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (err) {\n debugLog(\"pages.json parse failed, falling back to raw JSON view\", { err });\n return undefined;\n }\n if (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) return undefined;\n\n const record: Record<string, unknown> = { ...parsed };\n const pages = Object.values(record).filter(\n (p): p is { route?: string; path?: string; description?: string } => p != null && typeof p === \"object\",\n );\n if (pages.length === 0) return undefined;\n\n const out: StyledLine[] = [];\n out.push([\n { text: \"pages\", color: theme.accent, bold: true },\n { text: ` ${pages.length} routes`, color: theme.tertiary },\n ]);\n out.push([{ text: \"\" }]);\n\n const routeWidth = Math.min(TABLE_KEY_MAX, Math.max(...pages.map((p) => p.route?.length ?? 0), 5));\n for (const page of pages) {\n out.push([\n { text: \" \" },\n { text: pad(page.route ?? \"\", routeWidth), color: theme.sky },\n { text: \" \" },\n { text: page.description ?? \"\", color: theme.text },\n ]);\n if (page.path != null && page.path !== \"\") {\n out.push([{ text: \" \".repeat(routeWidth + 4) }, { text: page.path, color: theme.tertiary }]);\n }\n }\n return out;\n}\n\n/* ----------------------------------------------------------------- markdown -- */\n\nfunction markdownLines(lines: string[]): StyledLine[] {\n const out: StyledLine[] = [];\n let inCode = false;\n\n lines.forEach((line) => {\n const trimmed = line.trimStart();\n\n // Fenced code blocks.\n if (trimmed.startsWith(\"```\")) {\n inCode = !inCode;\n out.push([{ text: line, color: theme.faint }]);\n return;\n }\n if (inCode) {\n out.push([{ text: line, color: theme.sky }]);\n return;\n }\n\n // Headings.\n const heading = /^(#{1,6})\\s/.exec(trimmed);\n if (heading) {\n out.push([{ text: line, color: theme.accent, bold: true }]);\n return;\n }\n\n // Blockquote.\n if (trimmed.startsWith(\">\")) {\n out.push([{ text: line, dim: true }]);\n return;\n }\n\n // List items: dim the marker, inline-style the rest.\n const list = /^(\\s*(?:[-*+]|\\d+\\.)\\s)(.*)$/.exec(line);\n if (list) {\n out.push([{ text: list[1]!, color: theme.secondary }, ...inlineSpans(list[2]!)]);\n return;\n }\n\n out.push(inlineSpans(line));\n });\n\n return out;\n}\n\n/** Inline `**bold**` and `` `code` ``; everything else is plain text. */\nfunction inlineSpans(text: string): StyledLine {\n if (text === \"\") return [{ text: \"\" }];\n const spans: Span[] = [];\n const re = /\\*\\*([^*]+)\\*\\*|`([^`]+)`/g;\n let last = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text))) {\n if (m.index > last) spans.push({ text: text.slice(last, m.index) });\n if (m[1] != null) spans.push({ text: m[1], bold: true });\n else if (m[2] != null) spans.push({ text: m[2], color: theme.sky });\n last = m.index + m[0].length;\n }\n if (last < text.length) spans.push({ text: text.slice(last) });\n return spans.length ? spans : [{ text }];\n}\n\n/* --------------------------------------------------------------------- json -- */\n\nfunction jsonLine(line: string): StyledLine {\n const spans: Span[] = [];\n const re =\n /(\"(?:[^\"\\\\]|\\\\.)*\"\\s*:)|(\"(?:[^\"\\\\]|\\\\.)*\")|(\\b(?:true|false|null)\\b)|(-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)|([{}[\\],])/g;\n let last = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(line))) {\n if (m.index > last) spans.push({ text: line.slice(last, m.index), color: theme.secondary });\n if (m[1] != null) spans.push({ text: m[1], color: theme.accent });\n else if (m[2] != null) spans.push({ text: m[2], color: theme.green });\n else if (m[3] != null) spans.push({ text: m[3], color: theme.amber });\n else if (m[4] != null) spans.push({ text: m[4], color: theme.sky });\n else if (m[5] != null) spans.push({ text: m[5], color: theme.secondary });\n last = m.index + m[0].length;\n }\n if (last < line.length) spans.push({ text: line.slice(last), color: theme.secondary });\n return spans.length ? spans : [{ text: \"\" }];\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { debugLog } from \"./debug\";\n\nconst StepStatusSchema = z.enum([\"pending\", \"running\", \"done\", \"failed\", \"paused\"]);\n\nexport type StepStatus = z.infer<typeof StepStatusSchema>;\n\n// A step key absent from an existing state file predates that step's introduction, so an\n// older run never had a chance to run it. Default missing keys to \"done\" on load so adding a\n// new pipeline step never silently re-triggers work an already-completed run considers finished.\nconst PipelineStateSchema = z.object({\n steps: z.object({\n projectMapper: StepStatusSchema.default(\"done\"),\n pagesFinder: StepStatusSchema.default(\"done\"),\n kb: StepStatusSchema.default(\"done\"),\n entityAudit: StepStatusSchema.default(\"done\"),\n scenarioRecipe: StepStatusSchema.default(\"done\"),\n recipeBuilder: StepStatusSchema.default(\"done\"),\n testGenerator: StepStatusSchema.default(\"done\"),\n }),\n});\n\nexport type PipelineState = z.infer<typeof PipelineStateSchema>;\n\nconst STATE_FILE = \".pipeline-state.json\";\n\nexport function initialState(): PipelineState {\n return {\n steps: {\n projectMapper: \"pending\",\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 PipelineStateSchema.parse(JSON.parse(raw));\n } catch (err) {\n // Missing file is the expected first-run path; a present-but-unreadable/invalid file\n // means we are silently discarding prior progress, so leave a breadcrumb for that case.\n const isMissingFile = err instanceof Error && \"code\" in err && err.code === \"ENOENT\";\n if (!isMissingFile) debugLog(\"Failed to load pipeline state, starting fresh\", { path, err });\n return initialState();\n }\n}\n\nexport async function saveState(outputDir: string, state: PipelineState): 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\n/** Canonical pipeline order - the one list every consumer derives from. */\nexport const STEP_ORDER: StepName[] = [\n \"projectMapper\",\n \"pagesFinder\",\n \"kb\",\n \"entityAudit\",\n \"scenarioRecipe\",\n \"recipeBuilder\",\n \"testGenerator\",\n];\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 | undefined {\n return STEP_ORDER.find((s) => state.steps[s] !== \"done\") ?? undefined;\n}\n","import type { StepName } from \"../core/state\";\n\n// Re-exported so UI modules keep one import site for step metadata.\nexport { STEP_ORDER } from \"../core/state\";\n\nconst MIN = 60_000;\n\n/** Short, skimmable labels for the pipeline column. */\nexport const UI_STEP_LABELS: Record<StepName, string> = {\n projectMapper: \"Map project\",\n pagesFinder: \"Map pages\",\n kb: \"Build knowledge base\",\n entityAudit: \"Model data\",\n scenarioRecipe: \"Design scenarios\",\n recipeBuilder: \"Set up test data\",\n testGenerator: \"Write E2E tests\",\n};\n\n/** Dim one-liner under each step label - the \"why this step exists\". */\nexport const UI_STEP_WHY: Record<StepName, string> = {\n projectMapper: \"find the frontend + backend\",\n pagesFinder: \"find every route\",\n kb: \"learn the app\",\n entityAudit: \"what the app stores\",\n scenarioRecipe: \"realistic data\",\n recipeBuilder: \"your coding agent wires the SDK\",\n testGenerator: \"page-by-page\",\n};\n\n/**\n * One-line plain-language summary per step, used in the upfront overview, the\n * \"continue?\" prompts, and the help modal.\n */\nexport const STEP_SUMMARIES: Record<StepName, string> = {\n projectMapper: \"Identify your frontend(s), backend(s), and which folders to ignore.\",\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\n/** The longer \"what is happening and why\" intro per step. */\nexport const STEP_INTROS: Record<StepName, string> = {\n projectMapper:\n \"Looking at how your codebase is laid out - which folder(s) are the frontend, which are the backend/data layer, and which are unrelated - so every later step scans only what matters instead of the whole repo.\",\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 \"Handing off to your local coding agent to wire up small helpers that create and clean up test data in your own database. It implements them, generates the recipe, and validates each one live against your app running locally - you watch it work, then we continue.\",\n testGenerator:\n \"Writing the actual end-to-end tests, covering every page and feature with depth proportional to its complexity.\",\n};\n\n/** What each step leaves behind - shown in the hero while it runs. */\nexport const STEP_OUTPUTS: Record<StepName, string> = {\n projectMapper: \"project-map.json - which folders are the frontend and backend\",\n pagesFinder: \"pages.json - every route in your app\",\n kb: \"AUTONOMA.md - what your app does, feature by feature\",\n entityAudit: \"entity-audit.md - what your app stores and how it's created\",\n scenarioRecipe: \"scenarios.md - the realistic data your tests will run against\",\n recipeBuilder: \"recipe.json - validated test-data factories wired into your app\",\n testGenerator: \"qa-tests/ - one natural-language test per flow\",\n};\n\n/**\n * Docs pages explaining what a step is doing, shown while it runs. Only steps\n * with a real, dedicated page get one - never link to a generic index.\n */\nexport const STEP_DOCS: Partial<Record<StepName, string>> = {\n recipeBuilder: \"https://docs.autonoma.app/environment-factory/\",\n testGenerator: \"https://docs.autonoma.app/test-planner/\",\n};\n\n/**\n * ETA budgets per step (ms). Most are flat; the recipe builder hands off to the\n * user's own coding agent so it is user-paced and carries a max bound.\n */\n// Budgets come from measured medians in PostHog (cli_step_completed,\n// status=done, 90 days to 2026-07-21; ~40-140 completions per step), rounded\n// up toward p60 since the distributions are heavily right-skewed with repo\n// size. recipeBuilder keeps a wide user-paced budget: the historical data\n// predates the coding-agent handoff.\nexport const STEP_BUDGET: Record<StepName, { ms: number; maxMs?: number }> = {\n projectMapper: { ms: 3 * MIN },\n pagesFinder: { ms: 3 * MIN },\n kb: { ms: 12 * MIN },\n entityAudit: { ms: 10 * MIN },\n scenarioRecipe: { ms: 3 * MIN },\n recipeBuilder: { ms: 45 * MIN, maxMs: 120 * MIN },\n testGenerator: { ms: 30 * MIN, maxMs: 60 * MIN },\n};\n\n/**\n * Per-page budget rates for the steps whose duration scales with the page\n * count, which is known once the pages step completes. Only pages qualify as\n * a predictor today: the other size signals (entities, tests) are produced BY\n * their own steps, so they can't size those budgets ahead of time - the live\n * in-run rate (eta.ts) covers them instead.\n *\n * Measured from cli_step_completed events carrying size telemetry (PostHog,\n * status=done, to 2026-07-23). Small sample (a handful of runs), so these are\n * priors leaning toward the p75, not a regression - refine as data accrues.\n * kb: 14-25s/page observed; testGenerator: ~3 tests/page x ~105s/test.\n */\nexport const STEP_MS_PER_PAGE: Partial<Record<StepName, number>> = {\n kb: 25_000,\n testGenerator: 300_000,\n};\n","import { STEP_MS_PER_PAGE } from \"./steps\";\nimport type { ProjectSizes, RunState, StepNode } from \"./types\";\n\nexport interface EtaResult {\n elapsedMs: number;\n /** Remaining time using the lower budget bound. */\n etaMs: number;\n /** 0-100, budget-weighted completion. */\n pct: number;\n complete: boolean;\n}\n\n/** Floors so a user-paced step never collapses the ETA to \"0 min left\" mid-step. */\nconst USER_PACED_MIN_REMAINING_MS = 30_000;\n/** A sized budget never drops below this, however small the project reads. */\nconst SIZED_BUDGET_FLOOR_MS = 90_000;\n/** Trust the running step's own pace once this much of it is observed. */\nconst LIVE_RATE_MIN_DONE = 3;\nconst LIVE_RATE_MIN_ELAPSED_MS = 60_000;\n/** Bounds on the completed-steps pace ratio applied to pending budgets. */\nconst PACE_RATIO_MIN = 0.5;\nconst PACE_RATIO_MAX = 2;\n/** Below this much completed budget, the pace ratio is noise - use 1. */\nconst PACE_RATIO_MIN_SIGNAL_MS = 120_000;\n\n/**\n * The run's clock excluding time spent blocked on user questions: while a\n * prompt is up (and for all past prompts) the elapsed/ETA hold still.\n */\nexport function agentNow(state: RunState): number {\n const waitingNow =\n state.prompt.current != null && state.prompt.waitingSince != null\n ? Math.max(0, state.now - state.prompt.waitingSince)\n : 0;\n return state.now - state.waitedMs - waitingNow;\n}\n\nfunction clamp01(n: number): number {\n if (Number.isNaN(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\n/** A step's budget: sized by the known page count where duration scales with\n * it, the flat measured median otherwise. */\nfunction budgetFor(step: StepNode, sizes: ProjectSizes): number {\n const msPerPage = STEP_MS_PER_PAGE[step.name];\n if (msPerPage != null && sizes.pages != null && sizes.pages > 0) {\n return Math.max(SIZED_BUDGET_FLOOR_MS, sizes.pages * msPerPage);\n }\n return step.budgetMs;\n}\n\n/** How \"done\" a running step is: real sub-progress when we have it, else time. */\nfunction runningFraction(step: StepNode, now: number, budget: number): number {\n if (step.sub && step.sub.total > 0) {\n return clamp01(step.sub.done / step.sub.total);\n }\n if (step.startedAt != null) {\n return clamp01((now - step.startedAt) / budget);\n }\n return 0;\n}\n\n/**\n * The running step's own observed pace: elapsed / units-done projects the\n * remaining units. The strongest signal there is - it prices THIS repo on\n * THIS machine - so once enough of the step is observed it overrides the\n * budget-based remainder.\n */\nfunction liveRemainingMs(step: StepNode, now: number): number | undefined {\n if (step.sub == null || step.sub.total <= 0 || step.startedAt == null) return undefined;\n const elapsed = now - step.startedAt;\n if (step.sub.done < LIVE_RATE_MIN_DONE || elapsed < LIVE_RATE_MIN_ELAPSED_MS) return undefined;\n return (elapsed / step.sub.done) * Math.max(0, step.sub.total - step.sub.done);\n}\n\n/**\n * How this run is pacing against its budgets, from the steps already\n * completed - a slow machine or a heavyweight repo shows up here. Applied to\n * pending agent-paced budgets; user-paced steps are excluded on both sides\n * (their duration reflects the human/coding agent, not this run's pace).\n */\nfunction paceRatio(state: RunState): number {\n let actual = 0;\n let budgeted = 0;\n for (const name of state.stepOrder) {\n const step = state.steps[name];\n if (step.status !== \"done\" || step.budgetMaxMs != null) continue;\n if (step.startedAt == null || step.endedAt == null) continue;\n actual += Math.max(0, step.endedAt - step.startedAt);\n budgeted += budgetFor(step, state.sizes);\n }\n if (budgeted < PACE_RATIO_MIN_SIGNAL_MS) return 1;\n return Math.max(PACE_RATIO_MIN, Math.min(PACE_RATIO_MAX, actual / budgeted));\n}\n\n/**\n * ETA = sum of remaining step budgets, where a budget is sized by the page\n * count once known, the running step is projected from its own observed pace,\n * and pending steps are scaled by how the run is pacing so far. A single\n * value - no ranges (design decision).\n */\nexport function computeEta(state: RunState): EtaResult {\n const nowAgent = agentNow(state);\n const elapsedMs = Math.max(0, nowAgent - state.startedAt);\n\n // Only a successful finish is \"complete\": a failed or paused run keeps its\n // real budget-weighted percentage instead of jumping to a green 100%.\n if (state.finished && (state.outcome?.kind ?? \"complete\") === \"complete\") {\n return { elapsedMs, etaMs: 0, pct: 100, complete: true };\n }\n\n const ratio = paceRatio(state);\n let consumedBudget = 0;\n let totalBudget = 0;\n let remaining = 0;\n\n for (const name of state.stepOrder) {\n const step = state.steps[name];\n const budget = budgetFor(step, state.sizes);\n totalBudget += budget;\n\n if (step.status === \"done\") {\n consumedBudget += budget;\n continue;\n }\n\n if (step.status === \"running\") {\n const frac = runningFraction(step, nowAgent, budget);\n consumedBudget += budget * frac;\n let rem = liveRemainingMs(step, nowAgent) ?? budget * (1 - frac);\n if (step.budgetMaxMs != null) rem = Math.max(rem, USER_PACED_MIN_REMAINING_MS);\n remaining += rem;\n continue;\n }\n\n // pending / failed / paused - full budget still ahead, scaled by the\n // run's observed pace (user-paced steps keep their flat budget).\n remaining += step.budgetMaxMs != null ? budget : budget * ratio;\n }\n\n const pct = totalBudget > 0 ? clamp01(consumedBudget / totalBudget) * 100 : 0;\n\n return { elapsedMs, etaMs: remaining, pct, complete: false };\n}\n\n/** mm:ss, or h:mm:ss past an hour. */\nexport function formatClock(ms: number): string {\n const total = Math.max(0, Math.floor(ms / 1000));\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${pad(m)}:${pad(s)}`;\n}\n\n/** Human \"~39 min left\" / \"~1h 5m left\". A single value - no range. */\nexport function formatEtaLabel(eta: EtaResult): string {\n if (eta.complete) return \"complete\";\n return `~${phrase(Math.max(1, Math.round(eta.etaMs / 60_000)))} left`;\n}\n\nfunction phrase(min: number): string {\n if (min < 60) return `${min} min`;\n const h = Math.floor(min / 60);\n const m = min % 60;\n return m > 0 ? `${h}h ${m}m` : `${h}h`;\n}\n","import type { Artifact, RunState } from \"./types\";\n\nexport type NavAction =\n | { type: \"moveUp\" }\n | { type: \"moveDown\" }\n | { type: \"focusLeft\" }\n | { type: \"focusRight\" }\n | { type: \"enter\" }\n | { type: \"pageUp\" }\n | { type: \"pageDown\" }\n | { type: \"scrollTop\" }\n | { type: \"scrollBottom\" }\n | { type: \"toggleFollow\" }\n | { type: \"closeDocument\" }\n | { type: \"setViewport\"; rows: number; cols: number };\n\nconst PAGE_LINES = 10;\n\n/** All artifacts, newest first - the flat FILES column. */\nexport function allArtifacts(state: RunState): Artifact[] {\n return state.artifactOrder.map((id) => state.artifacts[id]).filter((a): a is Artifact => a != null);\n}\n\nexport function selectedArtifact(state: RunState): Artifact | undefined {\n return allArtifacts(state)[state.nav.selectedArtifactIdx];\n}\n\nfunction clamp(n: number, max: number): number {\n return Math.max(0, Math.min(max, n));\n}\n\n/** The furthest scroll-top: with a known viewport it's exact, else approximate. */\nfunction maxTopOf(state: RunState): number {\n if (state.nav.viewportRows != null) return Math.max(0, state.live.lineCount - state.nav.viewportRows);\n return state.nav.maxScroll;\n}\n\n/**\n * Scroll the document. While following, the view sits at the tail even though\n * mainScrollTop was never set - so the first manual scroll starts FROM the\n * tail position, not from wherever the counter was left.\n */\nfunction scroll(state: RunState, delta: number): RunState {\n const maxTop = maxTopOf(state);\n const from = state.live.following ? maxTop : state.nav.mainScrollTop;\n const top = clamp(from + delta, maxTop);\n return { ...state, nav: { ...state.nav, mainScrollTop: top }, live: { ...state.live, following: false } };\n}\n\n/** Open the selected file in the viewer: pin it and move focus there. */\nfunction openSelected(state: RunState): RunState {\n const art = selectedArtifact(state);\n if (art == null) return state;\n return {\n ...state,\n nav: { ...state.nav, focus: \"main\", mainScrollTop: 0 },\n live: { ...state.live, following: false, artifactId: art.id, path: art.path, name: art.name },\n };\n}\n\n/**\n * Keyboard navigation over the two panels. Left/Right (h/l) move between the\n * file list and the viewer - moving right from the list opens the selected\n * file, Finder-style. Up/Down (k/j) move the cursor or scroll the document.\n * Default focus is the viewer so the document scrolls immediately.\n */\nexport function navReducer(state: RunState, action: NavAction): RunState {\n const nav = state.nav;\n\n switch (action.type) {\n case \"focusLeft\": {\n if (nav.focus === \"main\") {\n // Land the cursor on the file that's open in the viewer.\n const idx = state.live.artifactId != null ? state.artifactOrder.indexOf(state.live.artifactId) : -1;\n return {\n ...state,\n nav: { ...nav, focus: \"artifacts\", selectedArtifactIdx: idx >= 0 ? idx : nav.selectedArtifactIdx },\n };\n }\n return state;\n }\n case \"focusRight\": {\n // From the file list, \"going right\" means going INTO the file.\n if (nav.focus === \"artifacts\") return openSelected(state);\n return state;\n }\n\n case \"moveUp\":\n case \"moveDown\": {\n const delta = action.type === \"moveUp\" ? -1 : 1;\n if (nav.focus === \"artifacts\") {\n // Moving the cursor is browsing: stop the list/hero jumping to\n // every new write until `f` re-follows.\n const idx = clamp(nav.selectedArtifactIdx + delta, Math.max(0, allArtifacts(state).length - 1));\n return {\n ...state,\n nav: { ...nav, selectedArtifactIdx: idx },\n live: { ...state.live, following: false },\n };\n }\n return scroll(state, delta);\n }\n\n case \"enter\": {\n if (nav.focus === \"artifacts\") return openSelected(state);\n return state;\n }\n\n case \"pageUp\":\n return scroll(state, -PAGE_LINES);\n case \"pageDown\":\n return scroll(state, PAGE_LINES);\n case \"scrollTop\":\n return { ...state, nav: { ...nav, mainScrollTop: 0 }, live: { ...state.live, following: false } };\n case \"scrollBottom\":\n return { ...state, nav: { ...nav, mainScrollTop: maxTopOf(state) } };\n\n case \"toggleFollow\": {\n if (state.live.following) {\n // Turning OFF freezes the view exactly where the tail was -\n // the stale scroll offset would otherwise snap to the top.\n return {\n ...state,\n nav: { ...state.nav, mainScrollTop: maxTopOf(state) },\n live: { ...state.live, following: false },\n };\n }\n return { ...state, live: { ...state.live, following: true } };\n }\n\n case \"closeDocument\": {\n // Back to the DEFAULT state: the step explainer, with follow-latest\n // re-armed - the next write brings the hero back live. Browsing and\n // pinning are the exceptions; esc always returns to the living view.\n return {\n ...state,\n nav: { ...state.nav, mainScrollTop: 0 },\n live: {\n ...state.live,\n artifactId: undefined,\n path: undefined,\n name: undefined,\n text: \"\",\n lineCount: 0,\n writingLive: false,\n following: true,\n },\n };\n }\n\n case \"setViewport\": {\n if (nav.viewportRows === action.rows && nav.viewportCols === action.cols) return state;\n return { ...state, nav: { ...nav, viewportRows: action.rows, viewportCols: action.cols } };\n }\n }\n}\n","import type { PromptAnswer, PromptDraft, PromptRequest } from \"./types\";\n\n/**\n * Pure editing logic for the docked prompt panel: how a fresh draft looks for\n * each prompt kind, how key actions mutate it, and how a draft becomes the\n * final answer on submit. The store owns the promise bridge; App routes keys.\n */\n\nexport type PromptAction =\n | { type: \"up\" }\n | { type: \"down\" }\n | { type: \"setIndex\"; index: number }\n | { type: \"toggle\" }\n | { type: \"input\"; text: string }\n | { type: \"backspace\" }\n | { type: \"delete\" }\n | { type: \"left\" }\n | { type: \"right\" }\n | { type: \"home\" }\n | { type: \"end\" };\n\nexport function initialDraft(req: PromptRequest): PromptDraft {\n switch (req.kind) {\n case \"confirm\":\n // Index 0 = yes, 1 = no.\n return { index: (req.initialValue ?? true) ? 0 : 1, text: \"\", cursor: 0, checked: [] };\n case \"select\": {\n const initial = req.options.findIndex((o) => o.value === req.initialValue);\n return { index: Math.max(0, initial), text: \"\", cursor: 0, checked: [] };\n }\n case \"multiselect\":\n return { index: 0, text: \"\", cursor: 0, checked: [...(req.initialValues ?? [])] };\n case \"text\": {\n const text = req.defaultValue ?? \"\";\n return { index: 0, text, cursor: text.length, checked: [] };\n }\n }\n}\n\nfunction clamp(n: number, max: number): number {\n return Math.max(0, Math.min(max, n));\n}\n\nexport function promptReducer(req: PromptRequest, draft: PromptDraft, action: PromptAction): PromptDraft {\n // Any edit clears a previous submit error.\n const d: PromptDraft = { ...draft, error: undefined };\n\n switch (action.type) {\n case \"up\":\n case \"down\": {\n const delta = action.type === \"up\" ? -1 : 1;\n if (req.kind === \"confirm\") return { ...d, index: d.index === 0 ? 1 : 0 };\n if (req.kind === \"select\" || req.kind === \"multiselect\") {\n return { ...d, index: clamp(d.index + delta, req.options.length - 1) };\n }\n return d;\n }\n case \"setIndex\": {\n if (req.kind === \"confirm\") return { ...d, index: clamp(action.index, 1) };\n if (req.kind === \"select\" || req.kind === \"multiselect\") {\n return { ...d, index: clamp(action.index, req.options.length - 1) };\n }\n return d;\n }\n case \"toggle\": {\n if (req.kind !== \"multiselect\") return d;\n const value = req.options[d.index]?.value;\n if (value == null) return d;\n const checked = d.checked.includes(value) ? d.checked.filter((v) => v !== value) : [...d.checked, value];\n return { ...d, checked };\n }\n case \"input\": {\n if (req.kind !== \"text\") return d;\n const text = d.text.slice(0, d.cursor) + action.text + d.text.slice(d.cursor);\n return { ...d, text, cursor: d.cursor + action.text.length };\n }\n case \"backspace\": {\n if (req.kind !== \"text\" || d.cursor === 0) return d;\n return { ...d, text: d.text.slice(0, d.cursor - 1) + d.text.slice(d.cursor), cursor: d.cursor - 1 };\n }\n case \"delete\": {\n if (req.kind !== \"text\" || d.cursor >= d.text.length) return d;\n return { ...d, text: d.text.slice(0, d.cursor) + d.text.slice(d.cursor + 1) };\n }\n case \"left\":\n return req.kind === \"text\" ? { ...d, cursor: clamp(d.cursor - 1, d.text.length) } : d;\n case \"right\":\n return req.kind === \"text\" ? { ...d, cursor: clamp(d.cursor + 1, d.text.length) } : d;\n case \"home\":\n return req.kind === \"text\" ? { ...d, cursor: 0 } : d;\n case \"end\":\n return req.kind === \"text\" ? { ...d, cursor: d.text.length } : d;\n }\n}\n\n/**\n * Turn the draft into the submitted answer, or return an error string when\n * the draft can't be submitted yet (shown in the panel).\n */\nexport function answerFor(req: PromptRequest, draft: PromptDraft): PromptAnswer | { error: string } {\n switch (req.kind) {\n case \"confirm\":\n return { kind: \"confirm\", value: draft.index === 0 };\n case \"select\": {\n const option = req.options[draft.index];\n if (option == null) return { error: \"Nothing selected\" };\n return { kind: \"select\", value: option.value };\n }\n case \"multiselect\": {\n if (req.required !== false && draft.checked.length === 0) {\n return { error: \"Select at least one (space toggles)\" };\n }\n return { kind: \"multiselect\", values: draft.checked };\n }\n case \"text\":\n return { kind: \"text\", value: draft.text };\n }\n}\n","import { join } from \"node:path\";\nimport { basename, describeArtifact, iconOf, isTestArtifact, kindOf, titleOf } from \"./artifacts/registry\";\nimport { renderContentWrapped } from \"./components/render-content\";\nimport { agentNow, formatClock } from \"./eta\";\nimport { navReducer, type NavAction } from \"./nav\";\nimport { answerFor, initialDraft, promptReducer, type PromptAction } from \"./prompt\";\nimport { STEP_BUDGET, STEP_ORDER, UI_STEP_LABELS, UI_STEP_WHY } from \"./steps\";\nimport type {\n Artifact,\n ArtifactStatus,\n ContentKind,\n LogEntry,\n LogLevel,\n MetaInfo,\n ProjectSizes,\n PromptAnswer,\n PromptRequest,\n RunOutcome,\n RunState,\n StepName,\n StepNode,\n StepStatus,\n SubProgress,\n} from \"./types\";\n\nexport type LiveReader = (absPath: string) => Promise<{ text: string; kind: ContentKind } | undefined>;\n\nexport interface StoreOptions {\n outputDir: string;\n meta: MetaInfo;\n /** Injected disk reader for the hero panel; omitted in tests (refresh is a no-op). */\n reader?: LiveReader;\n}\n\nexport interface ActivityInput {\n call: string;\n arg: string;\n metric?: string;\n failed?: boolean;\n}\n\nexport interface RunStore {\n getState(): RunState;\n subscribe(listener: () => void): () => void;\n\n // step lifecycle\n startStep(name: StepName): void;\n endStep(name: StepName, status: StepStatus): void;\n setSubProgress(name: StepName, sub: SubProgress | undefined): void;\n setMeta(patch: Partial<MetaInfo>): void;\n /** Record a learned project-size signal (drives sized ETA budgets). */\n setSizes(patch: ProjectSizes): void;\n\n // activity + logs\n setActivity(text: string): void;\n pushActivity(entry: ActivityInput): void;\n appendLog(entry: { level: LogLevel; text: string; title?: string }): void;\n\n // artifacts + hero\n noteWrite(relPath: string): void;\n handleFsChange(relPath: string): void;\n setLiveFile(relPath: string, text: string, kind: ContentKind): void;\n\n // run end\n finish(outcome: RunOutcome): void;\n\n // nav + clock\n dispatchNav(action: NavAction): void;\n startClock(): void;\n stopClock(): void;\n\n /** Reflect the Ctrl+C double-press arm state in the controls bar. */\n setCtrlCArmed(armed: boolean): void;\n\n /** Show/hide the \"?\" help modal. */\n setHelpOpen(open: boolean): void;\n\n /**\n * Ask the user a blocking question, rendered as the docked ACTION\n * REQUIRED panel. Resolves when they submit (or cancel). Questions queue;\n * one shows at a time.\n */\n requestPrompt(req: PromptRequest): Promise<PromptAnswer>;\n /** Route an editing key action into the active prompt's draft. */\n dispatchPrompt(action: PromptAction): void;\n /** Submit the active prompt's draft (no-op if invalid; error shows inline). */\n submitPrompt(): void;\n /** Cancel the active prompt (esc). */\n cancelPrompt(): void;\n\n /**\n * Show a blocking countdown overlay (the pre-handoff explainer). Resolves\n * when the countdown reaches zero or the user presses enter to start now.\n */\n runCountdown(opts: { title: string; lines: string[]; seconds: number }): Promise<void>;\n /** Enter on the countdown: dismiss it and resolve immediately. */\n skipCountdown(): void;\n}\n\nconst LOG_CAP = 500;\nconst ACTIVITY_CAP = 200;\n/** Coalesce listener notifications so bursts of events repaint once per frame. */\nconst EMIT_COALESCE_MS = 16;\n/** How long after the last write a file keeps its \"writing live\" indicator. */\nconst WRITE_SETTLE_MS = 900;\n/** Scroll headroom kept below the last line when computing scroll bounds. */\nconst SCROLL_TAIL_LINES = 5;\n// 100ms: the WRITING spinner in the FILES list runs at 200ms/frame (5fps) and\n// the strip spinner at 250ms - the clock must tick at least as fast as the\n// fastest spinner or frames skip. Ink only rewrites the lines that changed,\n// so the cost per tick is a few spinner cells.\nconst CLOCK_TICK_MS = 100;\n/** Terminal bell, rung when a blocking question appears. */\nconst BELL = \"\\x07\";\n\nfunction initialSteps(): Record<StepName, StepNode> {\n const make = (name: StepName): StepNode => ({\n name,\n label: UI_STEP_LABELS[name],\n status: \"pending\",\n budgetMs: STEP_BUDGET[name].ms,\n budgetMaxMs: STEP_BUDGET[name].maxMs,\n artifactIds: [],\n why: UI_STEP_WHY[name],\n });\n // Keyed explicitly (not derived from STEP_ORDER) so the compiler enforces\n // that every StepName is present; a new step fails typecheck here.\n return {\n projectMapper: make(\"projectMapper\"),\n pagesFinder: make(\"pagesFinder\"),\n kb: make(\"kb\"),\n entityAudit: make(\"entityAudit\"),\n scenarioRecipe: make(\"scenarioRecipe\"),\n recipeBuilder: make(\"recipeBuilder\"),\n testGenerator: make(\"testGenerator\"),\n };\n}\n\n/**\n * Paths that should never appear as artifacts: dotfiles/state files, anything\n * without a file extension (directories, coarse fs.watch noise), and\n * atomic-write droppings (recipe.json.tmp.<pid>.<hash> - renamed away moments\n * after the watcher sees them, so they'd linger as ghosts in the list).\n */\nfunction isInternal(relPath: string): boolean {\n const name = basename(relPath);\n if (name.startsWith(\".\") || relPath.startsWith(\".\")) return true;\n if (!name.includes(\".\")) return true;\n if (name.includes(\".tmp.\") || name.endsWith(\".tmp\")) return true;\n return false;\n}\n\n/**\n * Where a new artifact lands in the FILES list. Test files form an\n * alphabetical block (by path, so folders group together) at the top - dozens\n * stream in during the last step and a stable, scannable order beats recency.\n * Everything else stays newest-first below them.\n */\nfunction insertIntoOrder(order: string[], id: string): string[] {\n const tests = order.filter((x) => isTestArtifact(x));\n const others = order.filter((x) => !isTestArtifact(x));\n if (!isTestArtifact(id)) return [...tests, id, ...others];\n const at = tests.findIndex((t) => t.localeCompare(id) > 0);\n if (at === -1) tests.push(id);\n else tests.splice(at, 0, id);\n return [...tests, ...others];\n}\n\nexport function createStore(opts: StoreOptions): RunStore {\n const now0 = Date.now();\n let state: RunState = {\n startedAt: now0,\n now: now0,\n meta: opts.meta,\n steps: initialSteps(),\n stepOrder: STEP_ORDER,\n activity: \"\",\n activityFeed: [],\n artifacts: {},\n artifactOrder: [],\n log: [],\n live: {\n kind: \"plain\",\n text: \"\",\n lineCount: 0,\n revision: 0,\n writingLive: false,\n following: true,\n },\n nav: {\n // The file list is the natural landing spot: arrows give visible\n // feedback immediately (the document may not even exist yet).\n focus: \"artifacts\",\n selectedArtifactIdx: 0,\n mainScrollTop: 0,\n maxScroll: 0,\n },\n finished: false,\n ctrlCArmed: false,\n helpOpen: false,\n prompt: { queued: 0, draft: { index: 0, text: \"\", cursor: 0, checked: [] } },\n waitedMs: 0,\n sizes: {},\n };\n\n const listeners = new Set<() => void>();\n const promptQueue: { req: PromptRequest; resolve: (a: PromptAnswer) => void }[] = [];\n const settleTimers = new Map<string, ReturnType<typeof setTimeout>>();\n let countdownTimer: ReturnType<typeof setTimeout> | undefined;\n let countdownResolve: (() => void) | undefined;\n let clock: ReturnType<typeof setInterval> | undefined;\n let logSeq = 0;\n let activitySeq = 0;\n\n // Notifications are coalesced: a burst of store updates (a busy agent step\n // registers many tool calls and file writes back to back) triggers one\n // repaint per frame, not one per event. Reads via getState() stay live.\n let emitTimer: ReturnType<typeof setTimeout> | undefined;\n const emit = () => {\n if (emitTimer != null) return;\n emitTimer = setTimeout(() => {\n emitTimer = undefined;\n for (const l of listeners) l();\n }, EMIT_COALESCE_MS);\n };\n const set = (next: RunState) => {\n if (next === state) return;\n state = next;\n emit();\n };\n\n function absOf(relPath: string): string {\n return join(opts.outputDir, relPath);\n }\n\n /** Tool events sometimes carry absolute paths; artifacts key on output-relative ones. */\n function relOf(path: string): string {\n if (!path.startsWith(opts.outputDir)) return path;\n return path.slice(opts.outputDir.length).replace(/^\\/+/, \"\");\n }\n\n function ensureArtifact(relPath: string, status: ArtifactStatus): RunState {\n const id = relPath;\n if (state.artifacts[id]) return state;\n const step = state.currentStep ?? state.stepOrder[0]!;\n // A registration that lands after its step settled (the fs watcher\n // debounces past endStep) must not show as WRITING forever.\n const stepDone = state.steps[step].status === \"done\";\n const art: Artifact = {\n id,\n path: relPath,\n name: basename(relPath),\n title: titleOf(relPath),\n description: describeArtifact(relPath),\n status: stepDone && status === \"WRITING\" ? \"DONE\" : status,\n step,\n updatedAt: state.now,\n icon: iconOf(relPath),\n };\n return {\n ...state,\n artifacts: { ...state.artifacts, [id]: art },\n artifactOrder: insertIntoOrder(state.artifactOrder, id),\n steps: {\n ...state.steps,\n [step]: { ...state.steps[step], artifactIds: [...state.steps[step].artifactIds, id] },\n },\n };\n }\n\n async function refresh(relPath: string) {\n if (opts.reader == null) return;\n const content = await opts.reader(absOf(relPath));\n if (content == null) return;\n // Only repaint the hero if this file is the one being shown.\n if (state.live.artifactId === relPath) {\n setLiveText(relPath, content.text, content.kind);\n }\n }\n\n function setLiveText(relPath: string, text: string, kind: ContentKind) {\n // Wrap-aware when the layout has reported its measure - scroll bounds\n // must count folded lines, not raw ones.\n const cols = state.nav.viewportCols;\n const lineCount =\n cols != null ? renderContentWrapped(text, kind, basename(relPath), cols).length : text.split(\"\\n\").length;\n set({\n ...state,\n live: {\n ...state.live,\n artifactId: relPath,\n path: relPath,\n name: basename(relPath),\n kind,\n text,\n lineCount,\n revision: state.live.revision + 1,\n },\n nav: { ...state.nav, maxScroll: Math.max(0, lineCount - SCROLL_TAIL_LINES) },\n });\n }\n\n function scheduleSettle(relPath: string) {\n const prev = settleTimers.get(relPath);\n if (prev) clearTimeout(prev);\n settleTimers.set(\n relPath,\n setTimeout(() => {\n settleTimers.delete(relPath);\n let next = state;\n // WRITING means \"being written right now\": once the write\n // quiets down the file is DONE, even mid-step - a step that\n // writes dozens of files (tests) must not leave them all\n // glowing WRITING for an hour. A later update flips it back.\n const art = next.artifacts[relPath];\n if (art != null && art.status === \"WRITING\") {\n next = { ...next, artifacts: { ...next.artifacts, [relPath]: { ...art, status: \"DONE\" } } };\n }\n if (next.live.artifactId === relPath && next.live.writingLive) {\n next = { ...next, live: { ...next.live, writingLive: false } };\n }\n set(next);\n }, WRITE_SETTLE_MS),\n );\n }\n\n const store: RunStore = {\n getState: () => state,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n\n startStep(name) {\n set({\n ...state,\n currentStep: name,\n // Agent-time, not wall time: waiting on a question must not\n // count against the step's budget.\n steps: {\n ...state.steps,\n [name]: { ...state.steps[name], status: \"running\", startedAt: agentNow(state) },\n },\n });\n },\n\n endStep(name, status) {\n // Settle the step's artifacts to DONE when it completes successfully.\n const artifacts = { ...state.artifacts };\n if (status === \"done\") {\n for (const id of state.steps[name].artifactIds) {\n const art = artifacts[id];\n if (art) artifacts[id] = { ...art, status: \"DONE\" };\n }\n }\n set({\n ...state,\n artifacts,\n steps: { ...state.steps, [name]: { ...state.steps[name], status, endedAt: agentNow(state) } },\n });\n },\n\n setSubProgress(name, sub) {\n set({ ...state, steps: { ...state.steps, [name]: { ...state.steps[name], sub } } });\n },\n\n setMeta(patch) {\n set({ ...state, meta: { ...state.meta, ...patch } });\n },\n\n setSizes(patch) {\n set({ ...state, sizes: { ...state.sizes, ...patch } });\n },\n\n setActivity(text) {\n if (text === state.activity) return;\n set({ ...state, activity: text });\n },\n\n pushActivity(entry) {\n const e = {\n id: activitySeq++,\n time: formatClock(state.now - state.startedAt),\n call: entry.call,\n arg: entry.arg,\n metric: entry.metric,\n failed: entry.failed,\n };\n const feed =\n state.activityFeed.length >= ACTIVITY_CAP\n ? [...state.activityFeed.slice(1), e]\n : [...state.activityFeed, e];\n set({ ...state, activityFeed: feed });\n },\n\n appendLog(entry) {\n const e: LogEntry = {\n id: logSeq++,\n level: entry.level,\n text: entry.text,\n title: entry.title,\n at: state.now,\n };\n const log = state.log.length >= LOG_CAP ? [...state.log.slice(1), e] : [...state.log, e];\n set({ ...state, log });\n // The dashboard has no raw-log panel; surface the levels a user must\n // not miss as activity rows so they show up in the ACTIVITY feed.\n const surfaced: LogLevel[] = [\"success\", \"warn\", \"error\", \"checkpoint\"];\n if (surfaced.includes(entry.level)) {\n store.pushActivity({ call: entry.level, arg: entry.text, failed: entry.level === \"error\" });\n }\n },\n\n noteWrite(path) {\n const relPath = relOf(path);\n if (isInternal(relPath)) return;\n let next = ensureArtifact(relPath, \"WRITING\");\n const art = next.artifacts[relPath]!;\n next = {\n ...next,\n artifacts: { ...next.artifacts, [relPath]: { ...art, status: \"WRITING\", updatedAt: next.now } },\n };\n // Follow the newest file in the hero unless the user pinned one.\n // The list cursor rides along so browsing starts from the newest.\n if (next.live.following) {\n next = {\n ...next,\n live: {\n ...next.live,\n artifactId: relPath,\n path: relPath,\n name: basename(relPath),\n kind: kindOf(relPath),\n writingLive: true,\n },\n nav: { ...next.nav, selectedArtifactIdx: Math.max(0, next.artifactOrder.indexOf(relPath)) },\n };\n } else if (next.live.artifactId === relPath) {\n next = { ...next, live: { ...next.live, writingLive: true } };\n }\n set(next);\n void refresh(relPath);\n scheduleSettle(relPath);\n },\n\n handleFsChange(relPath) {\n // A change on disk IS a write, wherever it came from - a custom\n // tool (register_pages), the coding agent, anything. Route it\n // through noteWrite so WRITING status, the settle timer, and\n // follow-the-newest behave identically to tool-driven writes.\n store.noteWrite(relPath);\n },\n\n setLiveFile(relPath, text, kind) {\n setLiveText(relPath, text, kind);\n },\n\n finish(outcome) {\n store.stopClock();\n set({\n ...state,\n finished: true,\n outcome,\n currentStep: undefined,\n live: { ...state.live, writingLive: false },\n });\n },\n\n dispatchNav(action) {\n const before = state.live.artifactId;\n set(navReducer(state, action));\n const after = state.live.artifactId;\n if (after != null && after !== before) void refresh(after);\n if (action.type === \"toggleFollow\" && state.live.following) {\n // \"Newest\" is by write time, not list position - tests sort\n // alphabetically, so the latest write can sit mid-list.\n const arts = state.artifactOrder\n .map((id) => state.artifacts[id])\n .filter((a): a is Artifact => a != null);\n const newest = arts.reduce<Artifact | undefined>(\n (a, b) => (a == null || b.updatedAt > a.updatedAt ? b : a),\n undefined,\n );\n if (newest != null && newest.id !== state.live.artifactId) {\n set({\n ...state,\n live: {\n ...state.live,\n artifactId: newest.id,\n path: newest.path,\n name: newest.name,\n kind: kindOf(newest.path),\n },\n nav: { ...state.nav, selectedArtifactIdx: state.artifactOrder.indexOf(newest.id) },\n });\n void refresh(newest.id);\n }\n }\n },\n\n startClock() {\n if (clock != null) return;\n clock = setInterval(() => set({ ...state, now: Date.now() }), CLOCK_TICK_MS);\n },\n stopClock() {\n if (clock != null) clearInterval(clock);\n clock = undefined;\n },\n\n setCtrlCArmed(isArmed) {\n if (isArmed === state.ctrlCArmed) return;\n set({ ...state, ctrlCArmed: isArmed });\n },\n\n setHelpOpen(open) {\n if (open === state.helpOpen) return;\n set({ ...state, helpOpen: open });\n },\n\n requestPrompt(req) {\n return new Promise<PromptAnswer>((resolve) => {\n promptQueue.push({ req, resolve });\n if (state.prompt.current == null) activateNextPrompt();\n else set({ ...state, prompt: { ...state.prompt, queued: promptQueue.length - 1 } });\n });\n },\n\n dispatchPrompt(action) {\n const current = state.prompt.current;\n if (current == null) return;\n set({ ...state, prompt: { ...state.prompt, draft: promptReducer(current, state.prompt.draft, action) } });\n },\n\n submitPrompt() {\n const current = state.prompt.current;\n if (current == null) return;\n const result = answerFor(current, state.prompt.draft);\n if (\"error\" in result) {\n set({ ...state, prompt: { ...state.prompt, draft: { ...state.prompt.draft, error: result.error } } });\n return;\n }\n settlePrompt(result);\n },\n\n cancelPrompt() {\n const current = state.prompt.current;\n if (current == null) return;\n if (current.cancelable !== true) {\n // Esc must never silently kill the run; tell the user how to leave.\n set({\n ...state,\n prompt: {\n ...state.prompt,\n draft: { ...state.prompt.draft, error: \"This question needs an answer - Ctrl+C twice quits\" },\n },\n });\n return;\n }\n settlePrompt({ kind: \"cancel\" });\n },\n\n runCountdown({ title, lines, seconds }) {\n return new Promise<void>((resolve) => {\n countdownResolve = resolve;\n if (process.stdout.isTTY) process.stdout.write(BELL);\n set({ ...state, countdown: { title, lines, endsAt: state.now + seconds * 1000 } });\n countdownTimer = setTimeout(() => store.skipCountdown(), seconds * 1000);\n });\n },\n\n skipCountdown() {\n if (countdownTimer != null) clearTimeout(countdownTimer);\n countdownTimer = undefined;\n const resolve = countdownResolve;\n countdownResolve = undefined;\n if (state.countdown != null) set({ ...state, countdown: undefined });\n resolve?.();\n },\n };\n\n function activateNextPrompt(): void {\n const next = promptQueue[0];\n if (next == null) {\n set({ ...state, prompt: { ...state.prompt, current: undefined, queued: 0, waitingSince: undefined } });\n return;\n }\n // An audible nudge: the run blocks until the user answers.\n if (process.stdout.isTTY) process.stdout.write(BELL);\n set({\n ...state,\n prompt: {\n current: next.req,\n queued: promptQueue.length - 1,\n draft: initialDraft(next.req),\n waitingSince: state.prompt.waitingSince ?? state.now,\n },\n });\n }\n\n function settlePrompt(answer: PromptAnswer): void {\n const head = promptQueue.shift();\n if (head == null) return;\n // Bank the time this question was on screen - elapsed/ETA exclude it.\n const since = state.prompt.waitingSince;\n if (since != null) {\n state = {\n ...state,\n waitedMs: state.waitedMs + Math.max(0, state.now - since),\n prompt: { ...state.prompt, waitingSince: undefined },\n };\n }\n activateNextPrompt();\n head.resolve(answer);\n }\n\n return store;\n}\n\n/* --------------------------------------------------------------- singleton -- */\n\nlet active: RunStore | undefined;\n\n/**\n * The store the orchestrator/agents/loggers push into. Set only while the\n * interactive TUI is mounted - headless runs keep it unset so every consumer\n * falls back to plain line output.\n */\nexport function setActiveStore(store: RunStore | undefined): void {\n active = store;\n}\n\nexport function getActiveStore(): RunStore | undefined {\n return active;\n}\n","import { getActiveStore } from \"./store\";\nimport type { LogLevel } from \"./types\";\n\n/**\n * The pipeline's one interaction surface. With the TUI mounted, non-blocking\n * output (log/note/intro/outro) feeds the run store and blocking prompts\n * render as the docked ACTION REQUIRED panel via the store's prompt bridge.\n * Without a store (non-TTY, --non-interactive), output falls back to plain\n * console lines and blocking prompts resolve to their safe default - or\n * cancel when there is none - since there is nobody to ask.\n *\n * Cancellation is the CANCEL sentinel - check with isCancel().\n */\n\nexport const CANCEL: unique symbol = Symbol(\"prompt-cancelled\");\n\nexport function isCancel(value: unknown): value is typeof CANCEL {\n return value === CANCEL;\n}\n\nconst MARKERS: Record<LogLevel, string> = {\n info: \"·\",\n success: \"✓\",\n warn: \"!\",\n error: \"✗\",\n note: \"·\",\n checkpoint: \"▸\",\n intro: \"◆\",\n outro: \"◆\",\n};\n\nfunction emit(level: LogLevel, text: string, title?: string): void {\n const store = getActiveStore();\n if (store != null) {\n store.appendLog({ level, text, title });\n return;\n }\n const line = title != null ? `${title}\\n${text}` : text;\n console.log(`${MARKERS[level]} ${line}`);\n}\n\nexport const log = {\n info(message: string): void {\n emit(\"info\", message);\n },\n success(message: string): void {\n emit(\"success\", message);\n },\n step(message: string): void {\n emit(\"info\", message);\n },\n warn(message: string): void {\n emit(\"warn\", message);\n },\n error(message: string): void {\n emit(\"error\", message);\n },\n};\n\nexport function intro(message: string): void {\n emit(\"intro\", message);\n}\n\nexport function outro(message: string): void {\n emit(\"outro\", message);\n}\n\nexport function note(message: string, title?: string): void {\n emit(\"note\", message, title);\n}\n\n/**\n * A blocking countdown overlay explaining what happens next; resolves when it\n * runs out or the user presses enter to continue immediately. Headless runs\n * print the explanation and continue - a delay with nobody watching is waste.\n */\nexport async function countdown(opts: { title: string; lines: string[]; seconds: number }): Promise<void> {\n const store = getActiveStore();\n if (store == null) {\n console.log(`◆ ${opts.title}\\n${opts.lines.map((l) => ` ${l}`).join(\"\\n\")}`);\n return;\n }\n await store.runCountdown(opts);\n}\n\n/* ----------------------------------------------------------------- blocking -- */\n\nexport interface PromptExtras {\n /** Extra explainer line under the question. */\n detail?: string;\n /** Esc means \"go back\" and resolves CANCEL; off by default. */\n cancelable?: boolean;\n}\n\nexport async function confirm(\n opts: { message: string; initialValue?: boolean } & PromptExtras,\n): Promise<boolean | typeof CANCEL> {\n const store = getActiveStore();\n if (store == null) return opts.initialValue ?? true;\n const answer = await store.requestPrompt({\n kind: \"confirm\",\n message: opts.message,\n initialValue: opts.initialValue,\n detail: opts.detail,\n cancelable: opts.cancelable,\n });\n return answer.kind === \"confirm\" ? answer.value : CANCEL;\n}\n\nexport async function text(\n opts: { message: string; placeholder?: string; defaultValue?: string; initialValue?: string } & PromptExtras,\n): Promise<string | typeof CANCEL> {\n const store = getActiveStore();\n const defaultValue = opts.defaultValue ?? opts.initialValue;\n if (store == null) return defaultValue ?? CANCEL;\n const answer = await store.requestPrompt({\n kind: \"text\",\n message: opts.message,\n placeholder: opts.placeholder,\n defaultValue,\n detail: opts.detail,\n cancelable: opts.cancelable,\n });\n return answer.kind === \"text\" ? answer.value : CANCEL;\n}\n\ninterface TypedOption<V extends string> {\n value: V;\n label: string;\n hint?: string;\n}\n\nexport async function select<V extends string>(\n opts: { message: string; options: TypedOption<V>[]; initialValue?: V } & PromptExtras,\n): Promise<V | typeof CANCEL> {\n const store = getActiveStore();\n if (store == null) return opts.initialValue ?? CANCEL;\n const answer = await store.requestPrompt({\n kind: \"select\",\n message: opts.message,\n options: opts.options,\n initialValue: opts.initialValue,\n detail: opts.detail,\n cancelable: opts.cancelable,\n });\n if (answer.kind !== \"select\") return CANCEL;\n const match = opts.options.find((o) => o.value === answer.value);\n return match != null ? match.value : CANCEL;\n}\n\nexport async function multiselect<V extends string>(\n opts: { message: string; options: TypedOption<V>[]; initialValues?: V[]; required?: boolean } & PromptExtras,\n): Promise<V[] | typeof CANCEL> {\n const store = getActiveStore();\n if (store == null) return opts.initialValues ?? CANCEL;\n const answer = await store.requestPrompt({\n kind: \"multiselect\",\n message: opts.message,\n options: opts.options,\n initialValues: opts.initialValues,\n required: opts.required,\n detail: opts.detail,\n cancelable: opts.cancelable,\n });\n if (answer.kind !== \"multiselect\") return CANCEL;\n const allowed = new Set<string>(opts.options.map((o) => o.value));\n return opts.options.map((o) => o.value).filter((v) => allowed.has(v) && answer.values.includes(v));\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { debugLog } from \"../../core/debug\";\n\nconst recipePayloadSchema = z.record(z.string(), z.array(z.record(z.string(), z.unknown())));\n\n/** The recipe the agent generates and the CLI submits. Validated on read (below):\n * it comes from the agent, so we don't blindly trust its shape before uploading. */\nconst fullRecipeSchema = z.object({\n version: z.number(),\n source: z.object({ discoverPath: z.string(), scenariosPath: z.string() }),\n validationMode: z.string(),\n recipes: z\n .array(\n z.object({\n name: z.string(),\n description: z.string(),\n create: recipePayloadSchema,\n validation: z.object({\n status: z.string(),\n method: z.string(),\n up_ms: z.number().optional(),\n down_ms: z.number().optional(),\n }),\n }),\n )\n .min(1),\n});\n\nexport type RecipePayload = z.infer<typeof recipePayloadSchema>;\nexport type FullRecipeJson = z.infer<typeof fullRecipeSchema>;\n\nexport const RECIPE_FILE = \"recipe.json\";\n\n/**\n * Read and validate the recipe the agent generated from the output dir. Returns\n * undefined when it's absent, unparseable, or malformed - callers treat any of\n * those as \"not ready\" - so a broken recipe is never submitted as if it were real.\n */\nexport async function loadRecipe(outputDir: string): Promise<FullRecipeJson | undefined> {\n const path = join(outputDir, RECIPE_FILE);\n\n let raw: string;\n try {\n raw = await readFile(path, \"utf-8\");\n } catch (err) {\n debugLog(\"No recipe.json yet\", { path, err });\n return undefined;\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (err) {\n debugLog(\"recipe.json is not valid JSON\", { path, err });\n return undefined;\n }\n\n const parsed = fullRecipeSchema.safeParse(json);\n if (!parsed.success) {\n debugLog(\"recipe.json failed schema validation\", { path, issues: parsed.error.issues });\n return undefined;\n }\n return parsed.data;\n}\n","import * as p from \"../../../ui/prompts\";\nimport { type FullRecipeJson, RECIPE_FILE, loadRecipe } from \"../recipe\";\n\nconst UPLOAD_COMMAND = \"npx @autonoma-ai/planner@latest upload\";\n\nexport interface SubmitCredentials {\n apiUrl?: string;\n apiToken?: string;\n generationId?: string;\n}\n\nexport interface SubmitResult {\n /** Local path (relative to the output dir) the recipe was read from. */\n recipePath: string;\n /** True only when the recipe was accepted by Autonoma. */\n uploaded: boolean;\n}\n\n/**\n * Submit the recipe that already sits on disk - the one the agent generated and\n * validated (or, non-interactively, the drafted one). The CLI never rebuilds the\n * recipe from its own state here: the agent may have written `recipe.json` directly\n * during handoff, and that on-disk file is the source of truth. Returns whether the\n * upload actually succeeded so the caller can fail the step instead of masking a\n * rejected upload as success.\n */\nexport async function runSubmit(\n outputDir: string,\n autonomaApiUrl?: string,\n autonomaApiToken?: string,\n autonomaGenerationId?: string,\n): Promise<SubmitResult> {\n const recipe = await loadRecipe(outputDir);\n if (recipe == null) {\n p.log.error(`No ${RECIPE_FILE} found in ${outputDir} to submit.`);\n return { recipePath: RECIPE_FILE, uploaded: false };\n }\n\n const uploaded = await submitRecipe(recipe, {\n apiUrl: autonomaApiUrl,\n apiToken: autonomaApiToken,\n generationId: autonomaGenerationId,\n });\n\n return { recipePath: RECIPE_FILE, uploaded };\n}\n\n/**\n * Load a previously generated `recipe.json` from the output dir and submit it,\n * without re-running the whole planner. Backs the `upload` command so a\n * failed/lost upload can be retried on its own.\n */\nexport async function uploadRecipeFromDisk(outputDir: string, creds: SubmitCredentials): Promise<boolean> {\n const recipe = await loadRecipe(outputDir);\n if (recipe == null) {\n p.log.error(\n `No ${RECIPE_FILE} found in ${outputDir}. Run the planner's recipe step first to generate it, then retry.`,\n );\n return false;\n }\n return submitRecipe(recipe, creds);\n}\n\n/**\n * POST a recipe to Autonoma's versioned scenario-recipe endpoint. On any failure\n * (including missing credentials) the recipe is printed to stdout in full with a\n * re-upload instruction, so it is never lost - even when the CLI runs in an\n * ephemeral container whose `~/.autonoma` filesystem is discarded on exit.\n */\nexport async function submitRecipe(recipe: FullRecipeJson, creds: SubmitCredentials): Promise<boolean> {\n const { apiUrl, apiToken, generationId } = creds;\n\n if (!apiUrl || !apiToken || !generationId) {\n p.log.info(\n \"Autonoma API credentials not configured - recipe saved locally, not uploaded. Set AUTONOMA_API_URL, AUTONOMA_API_TOKEN and AUTONOMA_GENERATION_ID, then run `\" +\n UPLOAD_COMMAND +\n \"`.\",\n );\n return false;\n }\n\n const url = `${apiUrl.replace(/\\/+$/, \"\")}/v1/setup/setups/${generationId}/scenario-recipe-versions`;\n\n p.log.step(\"Submitting recipe to Autonoma...\");\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiToken}`,\n },\n body: JSON.stringify(recipe),\n });\n } catch (err) {\n p.log.error(`Recipe submission failed (network error): ${err instanceof Error ? err.message : String(err)}`);\n printRecipeForRecovery(recipe);\n return false;\n }\n\n if (res.ok) {\n p.log.success(`Recipe submitted successfully (HTTP ${res.status})`);\n return true;\n }\n\n const text = await res.text();\n p.log.error(`Recipe submission failed (HTTP ${res.status}): ${text}`);\n printRecipeForRecovery(recipe);\n return false;\n}\n\n/**\n * Print the full recipe JSON plus a copy-paste recovery command. Uses console.log\n * (not the prompt logger) so the block is clean and easy to pipe/save.\n */\nfunction printRecipeForRecovery(recipe: FullRecipeJson): void {\n console.log(\n [\n \"\",\n \"─\".repeat(72),\n \"RECIPE NOT UPLOADED - copy the JSON below into a recipe.json and re-upload with:\",\n ` ${UPLOAD_COMMAND}`,\n \"(with the same AUTONOMA_API_URL / AUTONOMA_API_TOKEN / AUTONOMA_GENERATION_ID env vars set)\",\n \"─\".repeat(72),\n JSON.stringify(recipe, null, 2),\n \"─\".repeat(72),\n \"\",\n ].join(\"\\n\"),\n );\n}\n","import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\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 { randomUUID } from \"node:crypto\";\nimport { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { readEnv } from \"../env\";\nimport { debugLog } from \"./debug\";\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 (readEnv().AUTONOMA_POSTHOG_KEY ?? POSTHOG_PUBLIC_KEY).trim();\n}\n\nfunction resolveHost(): string {\n return (readEnv().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 = readEnv().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 = readEnv().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 | undefined;\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 (err) {\n debugLog(\"No cached device id found; generating a fresh one\", { err });\n }\n cachedDeviceId = randomUUID();\n try {\n mkdirSync(AUTONOMA_HOME, { recursive: true });\n writeFileSync(DEVICE_ID_PATH, cachedDeviceId, { encoding: \"utf-8\", mode: 0o600 });\n } catch (err) {\n debugLog(\"Could not persist device id; using an in-memory id for this run\", { err });\n }\n return cachedDeviceId;\n}\n\nlet enabled: boolean | undefined;\n\nfunction isEnabled(): boolean {\n if (enabled === undefined) {\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 // Runtime version - lets us confirm/monitor Node-version-specific\n // failures (e.g. a `util.styleText` crash on Node < 22.13 in old deps).\n node_version: process.versions.node,\n },\n });\n\n const promise = fetch(`${resolveHost()}/capture/`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n })\n .catch((err) => {\n debugLog(\"Analytics capture request failed (ignored)\", { err });\n })\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(error: unknown, properties: Record<string, unknown> = {}, handled = true): 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([Promise.allSettled([...pending]), new Promise((resolve) => setTimeout(resolve, timeoutMs))]);\n}\n","// Terminal color palette mirrored from @autonoma/blacklight (packages/blacklight/src/index.css).\n// blacklight's tokens are hex, so we render them with 24-bit truecolor ANSI escapes\n// (`\\x1b[38;2;R;G;Bm`) - every modern terminal supports it, and it lets the CLI match\n// the product's exact brand color instead of the nearest 16-color approximation.\n\nconst ESC = \"\\x1b[\";\nexport const RESET = `${ESC}0m`;\nexport const BOLD = `${ESC}1m`;\nexport const DIM = `${ESC}2m`;\n\nfunction fg(hex: string): string {\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n return `${ESC}38;2;${r};${g};${b}m`;\n}\n\n// --primary: #CCFF00 - blacklight's brand lime. This is the accent that carries\n// the CLI's identity: banner, subagent lines, checkpoints.\nexport const PRIMARY = fg(\"#CCFF00\");\n\n// Status colors: kept distinct from the primary accent so success/error/warning\n// still read semantically instead of collapsing into one lime tone.\nexport const SUCCESS = fg(\"#3FB950\");\nexport const ERROR = fg(\"#FF5C5C\");\nexport const WARNING = fg(\"#FFB020\");\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 | undefined> {\n try {\n const raw = await readFile(join(outputDir, CONTEXT_FILE), \"utf-8\");\n const parsed: ProjectContext = JSON.parse(raw);\n return parsed;\n } catch {\n return undefined;\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.map((p) => `- \\`${p.route}\\` - ${p.description} (\\`${p.path}\\`)`).join(\"\\n\");\n }\n\n return output;\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>(fn: () => Promise<T>, options: Partial<RetryOptions> = {}): 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(opts.baseDelayMs * 2 ** (attempt - 1) + Math.random() * 500, opts.maxDelayMs);\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 (the prompt 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 * Walk the cause chain to the first APICallError and return its HTTP status.\n * The agent layer wraps provider errors in an AgentError (and the AI SDK may\n * wrap them in a RetryError), so the status we key friendly messages off of is\n * almost never on the top-level error - we have to dig for it.\n */\nfunction apiStatusOf(err: unknown): number | undefined {\n let cur: unknown = err;\n for (let depth = 0; cur != null && depth < 10; depth++) {\n if (APICallError.isInstance(cur)) return cur.statusCode;\n if (RetryError.isInstance(cur)) {\n cur = cur.lastError;\n continue;\n }\n cur = cur instanceof Error ? cur.cause : undefined;\n }\n return undefined;\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 | undefined {\n const msg = chainMessages(err);\n const status = apiStatusOf(err);\n\n const looksLikeAuth =\n msg.includes(\"missing authentication header\") ||\n msg.includes(\"no auth credentials\") ||\n msg.includes(\"not authenticated\") ||\n msg.includes(\"unauthorized\") ||\n msg.includes(\"user not found\") ||\n status === 401 ||\n status === 403;\n if (looksLikeAuth) {\n return {\n title: \"Autonoma rejected the request - your API token looks missing or invalid.\",\n hint: \"Launch the planner from the Autonoma app, or set a valid AUTONOMA_API_TOKEN (create one at https://autonoma.app/settings/api-keys).\",\n };\n }\n\n // The managed proxy returns 402 (out_of_credits) once the org's credit\n // balance is exhausted. Point straight at billing.\n if (\n msg.includes(\"out_of_credits\") ||\n msg.includes(\"insufficient\") ||\n msg.includes(\"credits\") ||\n msg.includes(\"quota\") ||\n status === 402\n ) {\n return {\n title: \"You're out of Autonoma credits.\",\n hint: \"Top up your credits at https://autonoma.app, then re-run.\",\n };\n }\n\n if (\n NoSuchModelError.isInstance(err) ||\n msg.includes(\"model_not_allowed\") ||\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.\",\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: \"Autonoma is rate-limiting this account.\",\n hint: \"Wait a minute and re-run. If it persists, reach out to support.\",\n };\n }\n\n // A 404/502/503 reaching the CLI is a problem with the managed planner\n // service, not the user's input. A bare 404 means the proxy route wasn't\n // found at the API host - the proxy is disabled or undeployed, or a custom\n // AUTONOMA_API_URL points somewhere without it (the exact failure that once\n // surfaced as a raw \"Not Found\"). A 502/503 means the proxy is reachable but\n // its upstream or config is failing. Real bad-model/bad-request failures come\n // back as 400 and are handled above, so this family is always \"our side -\n // retry or contact support\", never something the user can fix by re-running.\n if (status === 404 || status === 502 || status === 503 || msg.includes(\"llm_proxy_unconfigured\")) {\n return {\n title: \"The Autonoma planner service is temporarily unavailable.\",\n hint: \"This is on our side, not your setup - retry in a minute, and contact support if it keeps happening. If you set a custom AUTONOMA_API_URL, confirm it points at a host running the planner.\",\n };\n }\n\n return undefined;\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\n// 402 is the managed proxy's hard stop (out of credits, or the free planner\n// usage cap reached). Retrying can't refill a balance mid-run, so fail fast and\n// let describeKnownError surface the billing hint instead of burning retries.\nconst FATAL_STATUS_CODES = new Set([400, 401, 402, 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 (LoadAPIKeyError.isInstance(err) || InvalidPromptError.isInstance(err) || NoSuchModelError.isInstance(err)) {\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 { debugLog } from \"./debug\";\n\n/**\n * Registry decoupling the TUI's mount/unmount from the code that needs to\n * yield the terminal (the coding-agent handoff). The TUI\n * registers pause/resume at mount; core code calls pauseUi()/resumeUi()\n * without importing Ink. Headless runs never register, so both are no-ops.\n *\n * Pauses nest: only the 0 -> 1 transition pauses and the 1 -> 0 transition\n * resumes, so a suspend() inside an already-paused prompt is safe.\n */\nexport interface UiLifecycle {\n pause(): void;\n resume(): void;\n}\n\nlet lifecycle: UiLifecycle | undefined;\nlet pauseDepth = 0;\n\nexport function registerUiLifecycle(l: UiLifecycle | undefined): void {\n lifecycle = l;\n pauseDepth = 0;\n}\n\nexport function isUiActive(): boolean {\n return lifecycle != null;\n}\n\nexport function pauseUi(): void {\n if (lifecycle == null) return;\n pauseDepth++;\n if (pauseDepth === 1) lifecycle.pause();\n}\n\nexport function resumeUi(): void {\n if (lifecycle == null) return;\n if (pauseDepth === 0) {\n debugLog(\"resumeUi called with no matching pauseUi\");\n return;\n }\n pauseDepth--;\n if (pauseDepth === 0) lifecycle.resume();\n}\n\n/** Run `fn` with the TUI paused (terminal handed back to cooked output). */\nexport async function withUiPaused<T>(fn: () => Promise<T>): Promise<T> {\n pauseUi();\n try {\n return await fn();\n } finally {\n resumeUi();\n }\n}\n\n/* ------------------------------------------------------- emergency teardown -- */\n\nlet teardown: (() => void) | undefined;\n\n/** Registered by the TUI at mount so fatal paths can kill the frame. */\nexport function registerUiTeardown(fn: (() => void) | undefined): void {\n teardown = fn;\n}\n\n/**\n * Tear the TUI down NOW - for fatal error paths about to print and exit.\n * Restores the real console so the error is actually visible instead of\n * vanishing into the unmounted frame's captured log. Idempotent; a no-op\n * when nothing is mounted.\n */\nexport function teardownUi(): void {\n const fn = teardown;\n teardown = undefined;\n fn?.();\n}\n","import { debugLog } from \"./debug\";\nimport { pauseUi, resumeUi, teardownUi } from \"./ui-lifecycle\";\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> | undefined;\nlet onExit: ((exitCode?: number) => void) | undefined;\nlet quitting = false;\n\n// While the Ink TUI is mounted, the arm hint must render inside the frame\n// instead of scribbling on stderr. The TUI registers a display callback; when\n// unset, the hint falls back to a plain stderr line.\nlet armDisplay: ((armed: boolean) => void) | undefined;\n\nexport function setInterruptArmDisplay(cb: ((armed: boolean) => void) | undefined): void {\n armDisplay = cb;\n}\n\nfunction showArmed(isArmed: boolean): void {\n if (armDisplay != null) {\n armDisplay(isArmed);\n return;\n }\n if (isArmed) process.stderr.write(`\\n${EXIT_HINT}\\n`);\n}\n\nfunction disarm(): void {\n if (armTimer) clearTimeout(armTimer);\n armTimer = undefined;\n armed = false;\n showArmed(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 showArmed(true);\n armTimer = setTimeout(disarm, ARM_WINDOW_MS);\n}\n\n/**\n * Feed a Ctrl+C press from the Ink TUI (mounted with exitOnCtrlC: false, so\n * raw-mode presses arrive as input, never as SIGINT). Applies the exact same\n * double-press policy as the signal path.\n */\nexport function interruptPress(): void {\n handleInterrupt();\n}\n\n/**\n * Install Ctrl+C double-press handling.\n *\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. While the Ink\n * TUI owns stdin (raw mode) presses arrive via interruptPress(); everywhere\n * else Ctrl+C arrives as a normal process SIGINT.\n */\nexport function installInterruptHandler(opts: { onExit: (exitCode?: number) => void }): void {\n onExit = opts.onExit;\n if (installed) return;\n installed = true;\n\n process.on(\"SIGINT\", handleInterrupt);\n}\n\n/**\n * Hand the terminal to a spawned interactive child (e.g. a local agent).\n * Unmounts the TUI, detaches the CLI's SIGINT double-tap handler, and restores\n * cooked mode, so Ctrl+C behaves the way the developer expects INSIDE the\n * child - interrupting it, not killing the whole CLI. Idempotent; a no-op if\n * the handler was never installed.\n */\nexport function suspend(): void {\n if (!installed) return;\n // The Ink frame must be gone before the child owns the terminal.\n pauseUi();\n disarm();\n process.removeListener(\"SIGINT\", handleInterrupt);\n restoreTerminal();\n}\n\n/** Re-arm the CLI's Ctrl+C handling after a suspended child exits. Idempotent. */\nexport function resume(): void {\n if (!installed) return;\n if (!process.listeners(\"SIGINT\").includes(handleInterrupt)) {\n process.on(\"SIGINT\", handleInterrupt);\n }\n resumeUi();\n}\n\n/**\n * Surface *why* the process ends when it isn't a clean Ctrl+C: an external\n * SIGTERM/SIGHUP (a task reaper, a parent shell going away, an OOM-adjacent kill),\n * or a crash from an unhandled exception/rejection that would otherwise die with no\n * breadcrumb. Each writes one greppable `[diagnostics]` line - including memory stats,\n * which hint at pressure-related kills - before letting the process go. SIGKILL cannot\n * be caught and leaves no trace by design; if a run vanishes with none of these lines,\n * it was SIGKILL (or the host pulled the whole environment).\n */\nexport function installTerminationDiagnostics(): void {\n const memSnapshot = (): string => {\n const m = process.memoryUsage();\n const mb = (n: number): number => Math.round(n / 1024 / 1024);\n return `rss=${mb(m.rss)}MB heapUsed=${mb(m.heapUsed)}MB heapTotal=${mb(m.heapTotal)}MB`;\n };\n\n for (const signal of [\"SIGTERM\", \"SIGHUP\"] as const) {\n // 128 + signal number (SIGTERM=15, SIGHUP=1), the conventional exit codes.\n const forcedCode = signal === \"SIGTERM\" ? 143 : 129;\n process.on(signal, () => {\n process.stderr.write(`\\n[diagnostics] received ${signal} - external termination (${memSnapshot()})\\n`);\n terminateGracefully(forcedCode);\n });\n }\n\n process.on(\"uncaughtException\", (err) => {\n teardownUi();\n const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);\n process.stderr.write(`\\n[diagnostics] uncaughtException (${memSnapshot()}): ${detail}\\n`);\n restoreTerminal();\n process.exit(1);\n });\n\n // An unhandled rejection is an un-awaited promise that failed - a real bug. Node's default\n // is to terminate the process; a listener that only logged would silently override that and\n // let the pipeline continue in a corrupted state (emitting a bad plan/factory from a\n // half-finished step). Surface the breadcrumb, then honor the crash instead of swallowing it.\n process.on(\"unhandledRejection\", (reason) => {\n teardownUi();\n const detail = reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);\n process.stderr.write(`\\n[diagnostics] unhandledRejection (${memSnapshot()}): ${detail}\\n`);\n restoreTerminal();\n process.exit(1);\n });\n}\n\n/**\n * Terminate in response to an external signal, but let the graceful shutdown hook run first so\n * buffered analytics are flushed and the resume hint is printed. The hook is handed `forcedCode`\n * so its own exit carries the conventional signal code (143/129) instead of a clean 0 - otherwise\n * a reaper/CI reading the exit code couldn't tell an external kill from normal completion. A\n * FORCE_EXIT_MS failsafe guarantees the process still closes with that code if the async flush\n * ever stalls; with no hook wired (or a graceful exit already in flight) we exit immediately.\n */\nfunction terminateGracefully(forcedCode: number): void {\n if (quitting || onExit == null) {\n restoreTerminal();\n process.exit(forcedCode);\n }\n quitting = true;\n setTimeout(() => {\n restoreTerminal();\n process.exit(forcedCode);\n }, FORCE_EXIT_MS).unref?.();\n onExit(forcedCode);\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 (err) {\n debugLog(\"Could not restore terminal raw mode\", { err });\n }\n process.stdout.write(SHOW_CURSOR);\n}\n","import { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\nimport { readEnv } from \"../env\";\n\nexport const DEFAULT_MODEL = \"google/gemini-3-flash-preview\";\n\n// Passed as the AI SDK's `maxRetries` on every model call. The SDK default of 2 gave up on\n// transient provider blips after 3 attempts; 10 rides them out. The SDK handles the backoff and\n// only retries retryable (429/5xx/network) errors, failing fast on 4xx.\nexport const AI_MAX_RETRIES = 10;\n\n// Production API host. Overridable with AUTONOMA_API_URL to target an\n// alpha/preview host. Keep in sync with config.ts.\nconst DEFAULT_API_URL = \"https://autonoma.app\";\n\nlet provider: ReturnType<typeof createOpenRouter> | undefined;\n\n/**\n * Build the model provider against Autonoma's managed LLM proxy. The CLI no\n * longer needs an OpenRouter key: it authenticates with the Autonoma API token\n * (the same key the web app injects, or AUTONOMA_API_TOKEN), and our API\n * forwards to OpenRouter on our key, metering the org's credits. The OpenRouter\n * AI-SDK provider posts to `${baseURL}/chat/completions`, which the proxy serves.\n */\nfunction getProvider() {\n if (provider != null) return provider;\n\n const token = readEnv().AUTONOMA_API_TOKEN?.trim();\n if (!token) {\n throw new Error(\"Not authenticated - launch the planner from the Autonoma app, or set AUTONOMA_API_TOKEN.\");\n }\n\n const apiUrl = (readEnv().AUTONOMA_API_URL ?? DEFAULT_API_URL).replace(/\\/+$/, \"\");\n provider = createOpenRouter({ apiKey: token, baseURL: `${apiUrl}/v1/llm-proxy` });\n return provider;\n}\n\nexport function getModel(modelId?: string) {\n return getProvider().languageModel(modelId ?? readEnv().OPENROUTER_MODEL ?? DEFAULT_MODEL);\n}\n","import { execFile } from \"node:child_process\";\nimport { platform } from \"node:os\";\n\nexport function notify(title: string, message: string): void {\n process.stderr.write(\"\\x07\");\n\n const os = platform();\n if (os === \"darwin\") {\n execFile(\n \"osascript\",\n [\"-e\", `display notification \"${message.replace(/\"/g, '\\\\\"')}\" with title \"${title.replace(/\"/g, '\\\\\"')}\"`],\n () => {},\n );\n } else if (os === \"linux\") {\n execFile(\"notify-send\", [title, message], () => {});\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { debugLog } from \"./debug\";\n\n/**\n * A project map is the very first thing the planner establishes: a partition of the\n * codebase into the frontend app(s) whose pages we test, the backend(s) that own the\n * data we seed, and the directories that are irrelevant to either. Every later step\n * scopes itself to this map instead of re-discovering (and re-scanning) the whole\n * tree - which is what let a large monorepo drown the page/knowledge/audit agents.\n *\n * Deliberately framework-agnostic (see apps/cli CLAUDE.md): a repo may be a single\n * fullstack app (frontend and backend the SAME path), a monorepo with many apps, or a\n * codebase that only ships one half (frontend-only or backend-only). Multiple backends\n * are first-class.\n */\n\nconst FrontendEntry = z.object({\n path: z.string().min(1).describe(\"Repo-relative path to the frontend app/directory (the UI surface).\"),\n framework: z\n .string()\n .describe(\"Detected UI framework/stack, or 'unknown' if not obvious (e.g. next, react, vue, svelte).\"),\n dependsOn: z\n .array(z.string())\n .describe(\n \"Repo-relative paths (each matching a backend in this map) that THIS frontend needs in order to function - the \" +\n \"API/service(s) it calls and the data layer(s) that own the records it renders. These are pre-selected when the \" +\n \"user picks this frontend, so only list backends this frontend actually depends on. Empty if it needs none.\",\n ),\n why: z.string().min(1).describe(\"One line: the evidence that made you classify this as a frontend.\"),\n});\n\nconst BackendEntry = z.object({\n path: z\n .string()\n .min(1)\n .describe(\"Repo-relative path to the backend/API/service or the package that owns the data layer.\"),\n language: z.string().describe(\"Primary language, or 'unknown' (e.g. typescript, python, go, rust).\"),\n framework: z\n .string()\n .describe(\"Web/service framework or ORM stack, or 'unknown' (e.g. express, hono, fastapi, rails).\"),\n dataLayer: z\n .object({\n kind: z\n .string()\n .describe(\"How models are defined (e.g. prisma, drizzle, sqlalchemy, typeorm, raw-sql, unknown).\"),\n schemaPath: z.string().optional().describe(\"Repo-relative path to the schema/models definition, if found.\"),\n })\n .optional()\n .describe(\"Where this backend's database models live. Omit if this backend owns no data layer.\"),\n why: z.string().min(1).describe(\"One line: the evidence that made you classify this as a backend.\"),\n});\n\nconst IgnoreEntry = z.object({\n path: z.string().min(1).describe(\"Repo-relative path to a directory that is NOT relevant to testing this app.\"),\n why: z\n .string()\n .min(1)\n .describe(\"One line: why it is irrelevant (e.g. docs site, infra, tooling, examples, unrelated app).\"),\n});\n\nexport const ProjectMapSchema = z.object({\n frontends: z\n .array(FrontendEntry)\n .describe(\"The UI surface(s) whose pages/flows get tested. Usually 1; may be more.\"),\n backends: z\n .array(BackendEntry)\n .describe(\n \"The API/service(s) and data layer(s) that own the models we seed. May be 0 (frontend-only), 1, or many.\",\n ),\n ignore: z\n .array(IgnoreEntry)\n .describe(\"Directories judged irrelevant to this app's tests, so later steps skip them.\"),\n});\n\nexport type ProjectMap = z.infer<typeof ProjectMapSchema>;\n\nconst PROJECT_MAP_FILE = \"project-map.json\";\n\nexport async function saveProjectMap(outputDir: string, map: ProjectMap): Promise<void> {\n await writeFile(join(outputDir, PROJECT_MAP_FILE), JSON.stringify(map, null, 2), \"utf-8\");\n}\n\nexport async function loadProjectMap(outputDir: string): Promise<ProjectMap | undefined> {\n const path = join(outputDir, PROJECT_MAP_FILE);\n try {\n const raw = await readFile(path, \"utf-8\");\n const parsed = ProjectMapSchema.safeParse(JSON.parse(raw));\n if (parsed.success) return parsed.data;\n // A present-but-invalid map (e.g. a partial write after a crash) silently degrades\n // every downstream step to \"no scope\", so leave a breadcrumb rather than dropping it.\n debugLog(\"project-map.json failed schema validation, ignoring it\", { path, issues: parsed.error.issues });\n return undefined;\n } catch (err) {\n const isMissingFile = err instanceof Error && \"code\" in err && err.code === \"ENOENT\";\n if (!isMissingFile) debugLog(\"Failed to read project-map.json, ignoring it\", { path, err });\n return undefined;\n }\n}\n\n/** Human-readable rendering for the pipeline note / confirmation prompt. */\nexport function renderProjectMap(map: ProjectMap): string {\n const section = <T>(title: string, rows: T[], fmt: (row: T) => string): string => {\n if (rows.length === 0) return `${title}: (none)`;\n return `${title}:\\n` + rows.map((r) => ` - ${fmt(r)}`).join(\"\\n\");\n };\n return [\n section(\"Frontend(s)\", map.frontends, (f) => {\n const deps = f.dependsOn.length > 0 ? ` needs: ${f.dependsOn.join(\", \")}` : \"\";\n return `${f.path} [${f.framework}]${deps} - ${f.why}`;\n }),\n section(\"Backend(s)\", map.backends, (b) => {\n const dl =\n b.dataLayer != null\n ? ` data: ${b.dataLayer.kind}${b.dataLayer.schemaPath != null ? ` @ ${b.dataLayer.schemaPath}` : \"\"}`\n : \"\";\n return `${b.path} [${b.language}/${b.framework}]${dl} - ${b.why}`;\n }),\n section(\"Ignoring\", map.ignore, (i) => `${i.path} - ${i.why}`),\n ].join(\"\\n\\n\");\n}\n\n/**\n * The scope hint appended to a downstream agent's task prompt so it confines its work\n * to the mapped surface instead of walking the whole tree. Passed as an extra message,\n * NOT baked into any tuned system prompt.\n */\nexport function formatFrontendScope(map: ProjectMap): string | undefined {\n if (map.frontends.length === 0) return undefined;\n const fronts = map.frontends.map((f) => f.path).join(\", \");\n const ignore = map.ignore.map((i) => i.path);\n const ignoreLine =\n ignore.length > 0 ? ` Do NOT spend time in these irrelevant directories: ${ignore.join(\", \")}.` : \"\";\n return (\n `The project has already been mapped. The frontend surface to focus on is: ${fronts}. ` +\n `Confine your exploration to that surface.${ignoreLine}`\n );\n}\n\n/**\n * A user's choice of what to actually plan tests for: exactly ONE frontend root and\n * the subset of backends needed for it to work. The mapper discovers every candidate;\n * this narrows the candidate map down to a single testable surface. On the CLI this is\n * a radio (frontend) plus checkboxes (backends); when driven by Claude the caller just\n * asks the user in natural language and hands the answer back.\n */\nexport interface ScopeSelection {\n frontend: string;\n backends: string[];\n}\n\n/**\n * Match a requested path against the paths a mapper run actually emitted. The mapper\n * is non-deterministic about how deep it names a path (a fullstack app's backend may\n * come back as `apps/main-app` on one run and `apps/main-app/app/api` on the next), so\n * a caller-supplied selection (flags / harness config) can't rely on an exact string.\n * Prefer an exact hit, then accept an ancestor/descendant relationship either way.\n */\nfunction relatedPath(a: string, b: string): boolean {\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\nfunction matchMapPath(requested: string, candidates: string[]): string | undefined {\n if (candidates.includes(requested)) return requested;\n return candidates.find((c) => relatedPath(c, requested));\n}\n\n/**\n * Match a requested backend against the map, by path OR by the data layer it owns.\n * The schema path is far more stable across mapper runs than which backend the schema\n * gets attributed to: a shared data-layer package can come back attached to the\n * fullstack app, to the package itself, or to a sibling service that also reads it, on\n * different runs. So a caller that names the data-layer package (or its schema) still\n * resolves to whichever backend the mapper hung it on this time.\n */\nfunction matchBackend(requested: string, backends: ProjectMap[\"backends\"]): string | undefined {\n const byPath = backends.find((b) => relatedPath(b.path, requested));\n if (byPath != null) return byPath.path;\n const bySchema = backends.find(\n (b) => b.dataLayer?.schemaPath != null && relatedPath(b.dataLayer.schemaPath, requested),\n );\n return bySchema?.path;\n}\n\n/**\n * Resolve a caller-supplied selection to the exact paths present in the map, so a\n * hand-written `frontend`/`backends` still lines up after the mapper varied its path\n * depth or where it attributed a shared data layer. Frontends match by path; backends\n * match by path or by data-layer schema. Unmatched entries are passed through unchanged\n * so applySelection can throw a clear \"not in the map\" error listing the real candidates.\n */\nexport function resolveSelection(map: ProjectMap, requested: ScopeSelection): ScopeSelection {\n const frontendPaths = map.frontends.map((f) => f.path);\n return {\n frontend: matchMapPath(requested.frontend, frontendPaths) ?? requested.frontend,\n backends: requested.backends.map((b) => matchBackend(b, map.backends) ?? b),\n };\n}\n\n/**\n * The backends to seed for a frontend when the caller names none: its declared\n * dependencies, resolved to the real backend paths in this map with anything that does\n * not resolve dropped. dependsOn is LLM-emitted, so it can name a shared util or a path\n * no BackendEntry owns; keeping such an entry would make applySelection reject the whole\n * run. Resolution is tolerant (by path or data-layer schema, ancestor/descendant either\n * way) and de-duplicated, so the result is always exact backend paths applySelection accepts.\n */\nexport function defaultBackendsFor(map: ProjectMap, frontendPath: string): string[] {\n const declared = map.frontends.find((f) => f.path === frontendPath)?.dependsOn ?? [];\n const resolved = declared.map((dep) => matchBackend(dep, map.backends)).filter((p): p is string => p != null);\n return [...new Set(resolved)];\n}\n\n/**\n * When a candidate map has exactly one frontend, the choice is unambiguous: that\n * frontend plus the backends it declares it depends on. Returns undefined when the\n * user must pick (zero or multiple frontends), which is the \"return and ask\" path.\n */\nexport function pickDefaultSelection(map: ProjectMap): ScopeSelection | undefined {\n if (map.frontends.length !== 1) return undefined;\n const [only] = map.frontends;\n if (only == null) return undefined;\n return { frontend: only.path, backends: defaultBackendsFor(map, only.path) };\n}\n\n/**\n * Narrow a candidate map to the chosen frontend and backends. Every other frontend and\n * every unselected backend is folded into `ignore` so the downstream steps physically\n * skip them. Throws if the selection references paths the map does not contain, so a\n * bad hand-supplied choice fails loud instead of silently planning the wrong surface.\n */\nexport function applySelection(map: ProjectMap, selection: ScopeSelection): ProjectMap {\n const frontend = map.frontends.find((f) => f.path === selection.frontend);\n if (frontend == null) {\n const options = map.frontends.map((f) => f.path).join(\", \") || \"(none)\";\n throw new Error(`Selected frontend \"${selection.frontend}\" is not in the map. Candidates: ${options}`);\n }\n const chosenBackends = map.backends.filter((b) => selection.backends.includes(b.path));\n const missing = selection.backends.filter((p) => !map.backends.some((b) => b.path === p));\n if (missing.length > 0) {\n const options = map.backends.map((b) => b.path).join(\", \") || \"(none)\";\n throw new Error(`Selected backend(s) not in the map: ${missing.join(\", \")}. Candidates: ${options}`);\n }\n\n const droppedFrontends = map.frontends\n .filter((f) => f.path !== selection.frontend)\n .map((f) => ({ path: f.path, why: \"Another frontend in the monorepo; not the app under test.\" }));\n const droppedBackends = map.backends\n .filter((b) => !selection.backends.includes(b.path))\n .map((b) => ({ path: b.path, why: \"Backend not required by the selected frontend.\" }));\n\n return {\n frontends: [frontend],\n backends: chosenBackends,\n ignore: [...map.ignore, ...droppedFrontends, ...droppedBackends],\n };\n}\n\n/** The scope hint for backend/data-layer-oriented steps (entity audit, recipe). */\nexport function formatBackendScope(map: ProjectMap): string | undefined {\n if (map.backends.length === 0) return undefined;\n const backs = map.backends\n .map((b) => (b.dataLayer?.schemaPath != null ? `${b.path} (models @ ${b.dataLayer.schemaPath})` : b.path))\n .join(\", \");\n const ignore = map.ignore.map((i) => i.path);\n const ignoreLine = ignore.length > 0 ? ` Ignore these irrelevant directories: ${ignore.join(\", \")}.` : \"\";\n return (\n `The project has already been mapped. The backend(s)/data layer(s) that own the models to seed are: ${backs}. ` +\n `Scope your data-model work to those backend(s).${ignoreLine}`\n );\n}\n","import { join } from \"node:path\";\nimport { getActiveStore, type RunStore } from \"../ui/store\";\nimport { BOLD, DIM, ERROR, PRIMARY, RESET, SUCCESS, WARNING } from \"./colors\";\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(input.filePath ?? input.path ?? input.file_path ?? \"\");\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\n/** Map a tool call to the short verb the ACTIVITY panel colors by. */\nfunction activityCall(toolName: string): string {\n switch (toolName) {\n case \"read_file\":\n case \"read_output\":\n return \"read\";\n case \"glob\":\n case \"grep\":\n return toolName;\n case \"list_directory\":\n return \"glob\";\n case \"bash\":\n return \"bash\";\n case \"write_file\":\n return \"write\";\n case \"write_test\":\n return \"test\";\n case \"subagent\":\n case \"spawn_researcher\":\n return \"subagent\";\n case \"finish\":\n return \"done\";\n default:\n return toolName;\n }\n}\n\n/**\n * `toolChoice: \"required\"` forces the model to emit a tool call every turn, so\n * when it only wants to say something it wraps the text in `bash echo ...`.\n * Show those as what they are - the agent's own commentary - instead of a\n * wall of meaningless bash rows.\n */\nfunction echoPayload(command: string): string | undefined {\n const m = /^echo\\s+(?:-n\\s+)?[\"']?(.*?)[\"']?\\s*$/.exec(command.trim());\n if (m == null) return undefined;\n return m[1] ?? \"\";\n}\n\n/**\n * Feed one agent step into the TUI store: activity rows for every tool call,\n * artifact/hero updates for written files, and the one-line \"doing X now\".\n */\nfunction logToStore(store: RunStore, agentId: string, info: StepInfo, stats: ProgressStats): void {\n for (const tc of info.toolCalls) {\n const summary = toolCallSummary(tc.name, tc.input);\n const call = activityCall(tc.name);\n\n if (tc.name === \"read_file\" || tc.name === \"read_output\") stats.filesRead++;\n\n if (tc.name === \"write_file\") {\n stats.filesWritten++;\n store.noteWrite(String(tc.input.path ?? tc.input.file_path ?? \"\"));\n }\n if (tc.name === \"write_test\") {\n stats.filesWritten++;\n // Mirrors the write_test tool: qa-tests/{folder}/{filename}.\n const folder = String(tc.input.folder ?? \"\");\n const filename = String(tc.input.filename ?? \"\");\n if (folder && filename) store.noteWrite(join(\"qa-tests\", folder, filename));\n }\n\n if (tc.name === \"bash\") {\n const echoed = echoPayload(String(tc.input.command ?? \"\"));\n if (echoed != null) {\n // The model narrating between real actions - dim note, not noise.\n if (echoed.trim() !== \"\") store.pushActivity({ call: \"agent\", arg: echoed.replace(/\\s+/g, \" \") });\n continue;\n }\n }\n const flat = summary.replace(/\\s+/g, \" \").trim();\n store.pushActivity({ call, arg: tc.name === \"finish\" ? agentId : flat });\n store.setActivity(`${call} ${flat}`.trim());\n }\n\n for (const te of info.toolErrors) {\n store.pushActivity({ call: te.name, arg: String(te.error).slice(0, 120), failed: true });\n }\n\n for (const f of info.writtenFiles) {\n store.noteWrite(f);\n }\n}\n\nexport function createStepLogger(agentId: string, _maxSteps: number) {\n const stats: ProgressStats = {\n filesRead: 0,\n filesWritten: 0,\n };\n let frameIdx = 0;\n let lastSpinnerLine = false;\n\n function clearSpinner() {\n if (lastSpinnerLine) {\n process.stderr.write(CLEAR_LINE);\n lastSpinnerLine = false;\n }\n }\n\n function writeSpinner(message: string) {\n const frame = SPINNER_FRAMES[frameIdx % SPINNER_FRAMES.length];\n frameIdx++;\n process.stderr.write(`${CLEAR_LINE} ${DIM}${frame} ${message}${RESET}`);\n lastSpinnerLine = true;\n }\n\n function writePermanent(message: string) {\n clearSpinner();\n console.log(message);\n }\n\n function log(info: StepInfo) {\n const store = getActiveStore();\n if (store != null) {\n logToStore(store, agentId, info, stats);\n return;\n }\n\n for (const tc of info.toolCalls) {\n const summary = toolCallSummary(tc.name, tc.input);\n\n switch (tc.name) {\n case \"read_file\":\n case \"read_output\":\n stats.filesRead++;\n writeSpinner(`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(` ${SUCCESS}✎ write ${path}${RESET}`);\n break;\n }\n\n case \"write_test\":\n stats.filesWritten++;\n writePermanent(` ${SUCCESS}✎ 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(` ${SUCCESS}${BOLD}✓ done:${RESET} ${SUCCESS}${agentId}${RESET}`);\n break;\n\n case \"subagent\":\n case \"spawn_researcher\":\n writePermanent(` ${PRIMARY}⊕ 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(` ${ERROR}✗ ${te.name}: ${te.error}${RESET}`);\n }\n\n for (const f of info.writtenFiles) {\n writePermanent(` ${SUCCESS}📄 wrote: ${f}${RESET}`);\n }\n }\n\n function checkpoint(message: string) {\n const store = getActiveStore();\n if (store != null) {\n store.appendLog({ level: \"checkpoint\", text: message });\n return;\n }\n writePermanent(` ${WARNING}▸ ${message}${RESET}`);\n }\n\n function summary() {\n if (getActiveStore() != null) return;\n clearSpinner();\n if (stats.filesRead > 0 || stats.filesWritten > 0) {\n console.log(` ${DIM}────────────────────────────────${RESET}`);\n console.log(` ${DIM}files read: ${stats.filesRead} | files written: ${stats.filesWritten}${RESET}`);\n }\n }\n\n return { log, checkpoint, summary, stats };\n}\n","import { type LanguageModel, type ModelMessage, type ToolSet, ToolLoopAgent, hasToolCall, stepCountIs } from \"ai\";\nimport { track } from \"./analytics\";\nimport { createStepLogger, type StepInfo } from \"./display\";\nimport { AgentError, classifyAgentError, sleep } from \"./errors\";\nimport { AI_MAX_RETRIES } from \"./model\";\n\nconst MAX_RETRIES = 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.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: Record<string, unknown> }) => ({\n name: tc.toolName,\n input: tc.input,\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 model = config.model;\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): never => {\n const msg = err instanceof Error ? err.message : String(err);\n throw new AgentError(`agent \"${config.id}\" (model ${modelIdOf(model)}) failed: ${msg}`, config.id, err);\n };\n\n const YELLOW = \"\\x1b[33m\";\n const RESET = \"\\x1b[0m\";\n\n for (let retry = 0; retry < MAX_RETRIES; retry++) {\n const heartbeat = () => {};\n const tools = typeof config.tools === \"function\" ? await config.tools(heartbeat) : config.tools;\n\n const agent = new ToolLoopAgent({\n model,\n maxRetries: AI_MAX_RETRIES,\n instructions: config.systemPrompt,\n tools,\n temperature: config.temperature,\n // Force a structured tool call on every step. Without this, the AI SDK ends the loop as\n // soon as a step returns finishReason !== \"tool-calls\" - and weaker models (e.g.\n // gemini-3-flash) intermittently end a turn with prose, an empty turn, or a tool call typed\n // as text, which then surfaces as an empty \"provider error\"/no-result instead of finishing.\n // \"required\" keeps the model emitting real tool calls until it calls `finish`.\n toolChoice: \"required\",\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);\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 < MAX_RETRIES - 1) {\n console.log(` ${YELLOW}[${config.id}] retrying (${retry + 1}/${MAX_RETRIES})...${RESET}`);\n if (errorClass === \"transient\") {\n await sleep(Math.min(2000 * 2 ** retry, 10_000));\n }\n continue;\n }\n\n fail(err);\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(projectRoot: string): 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","/**\n * The extra fields Node's `child_process` attaches to the error it throws when\n * a spawned command fails (non-zero exit, timeout, ...). The error is typed\n * `unknown` in a catch clause, so this reads each field defensively - no type\n * assertion, and any field whose runtime type doesn't match comes back as\n * undefined rather than a lie.\n */\nexport interface ExecErrorFields {\n code?: number;\n stdout?: string;\n stderr?: string;\n killed?: boolean;\n}\n\nexport function readExecError(error: unknown): ExecErrorFields {\n if (typeof error !== \"object\" || error === null) return {};\n const code = Reflect.get(error, \"code\");\n const stdout = Reflect.get(error, \"stdout\");\n const stderr = Reflect.get(error, \"stderr\");\n const killed = Reflect.get(error, \"killed\");\n return {\n code: typeof code === \"number\" ? code : undefined,\n stdout: typeof stdout === \"string\" ? stdout : undefined,\n stderr: typeof stderr === \"string\" ? stderr : undefined,\n killed: typeof killed === \"boolean\" ? killed : undefined,\n };\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { readExecError } from \"../core/exec-error\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CHAINING_OPERATORS = /;|&&|\\|\\||`|\\$\\(|>>|<<|&\\s*$/;\n\nconst DEFAULT_ALLOWED = new Set([\"git\", \"wc\", \"sort\", \"head\", \"tail\", \"cat\", \"ls\", \"find\", \"diff\", \"echo\"]);\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(command: string, allowed: Set<string>): 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(workingDirectory: string, allowedCommands?: Set<string>) {\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(\"sh\", [\"-c\", input.command], {\n cwd: workingDirectory,\n maxBuffer: MAX_OUTPUT_BYTES,\n timeout: TIMEOUT_MS,\n });\n return {\n exitCode: 0,\n stdout: stdout.trimEnd(),\n stderr: stderr.trimEnd(),\n };\n } catch (err) {\n const execErr = readExecError(err);\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: 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 = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.git/**\",\n \"**/.next/**\",\n \"**/build/**\",\n \"**/coverage/**\",\n];\n/** Results live in the agent's conversation until the step ends - cap them. */\nconst MAX_MATCHES = 500;\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 if (matches.length > MAX_MATCHES) {\n return {\n matches: matches.slice(0, MAX_MATCHES),\n count: matches.length,\n error: `${matches.length} matches - showing the first ${MAX_MATCHES}. Narrow the pattern.`,\n };\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: \"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\";\nimport { readExecError } from \"../core/exec-error\";\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: \"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 = readExecError(error);\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 { minimatch } from \"minimatch\";\nimport { z } from \"zod\";\nimport { loadGitignorePatterns } from \"../core/gitignore\";\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 ? `${relativeBase}/${entry.name}` : 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(workingDirectory: string) {\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.string().default(\".\").describe(\"Directory path relative to project root. Defaults to root.\"),\n depth: z.number().min(1).max(15).default(10).describe(\"Max depth to traverse (1-15). Default 10.\"),\n gitignore: z\n .boolean()\n .describe(\n \"Whether to respect the gitignore or to ignore it. true will respect it. false \" +\n \"will ignore it. Default true\",\n )\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 === \".\" ? workingDirectory : 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 ? \"\" : relative(workingDirectory, targetDir);\n const maybeIgnored = input.gitignore ? isIgnored : undefined;\n\n const tree = await buildTree(targetDir, input.depth, 0, maybeIgnored, relBase || undefined);\n let rendered = renderTree(tree);\n // The tree is retained in the conversation until the step ends;\n // an uncapped listing of a big repo is a heap-exhaustion vector.\n const MAX_TREE_BYTES = 128 * 1024;\n if (rendered.length > MAX_TREE_BYTES) {\n rendered =\n rendered.slice(0, MAX_TREE_BYTES) + \"\\n... [tree truncated - list a subdirectory or reduce depth]\";\n }\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// A line cap alone is useless against minified bundles or lockfiles (megabytes\n// on one line). Every result is retained in the agent's conversation for the\n// whole step, so an uncapped read is a straight path to heap exhaustion.\nconst MAX_OUTPUT_BYTES = 256 * 1024;\n\nconst inputSchema = z.object({\n filePath: z.string().describe(\"Path to the file (absolute or relative to working directory)\"),\n offset: z.number().int().min(0).optional().describe(\"Line number to start reading from (0-based)\"),\n limit: z.number().int().min(1).optional().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.map((line, i) => `${offset + i + 1}\\t${line}`).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 if (sliced.numbered.length > MAX_OUTPUT_BYTES) {\n sliced.numbered =\n sliced.numbered.slice(0, MAX_OUTPUT_BYTES) +\n `\\n... [output truncated at ${Math.round(MAX_OUTPUT_BYTES / 1024)}KB - request a smaller offset/limit range]`;\n }\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: \"Read file contents with line numbers. Use offset and limit for large files.\",\n inputSchema,\n execute: (input) => executeReadFile(workingDirectory, input.filePath, input.offset, input.limit),\n });\n}\n","/**\n * Read the first string-valued property among `keys` off an unknown value.\n *\n * Tool inputs come from the model and occasionally arrive under a synonym key\n * (`filePath` vs `path` vs `file_path`), so callers probe several names. This\n * does that probing without a type assertion and without throwing on shapes\n * that don't match - it simply returns undefined.\n */\nexport function pickString(source: unknown, keys: string[]): string | undefined {\n if (typeof source !== \"object\" || source === null) return undefined;\n for (const key of keys) {\n const value = Reflect.get(source, key);\n if (typeof value === \"string\") return value;\n }\n return undefined;\n}\n","import { type LanguageModel, ToolLoopAgent, hasToolCall, stepCountIs, tool } from \"ai\";\nimport { z } from \"zod\";\nimport { AI_MAX_RETRIES } from \"../core/model\";\nimport { pickString } from \"../core/pick-string\";\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 = pickString(input, [\"filePath\", \"path\", \"file_path\"]) ?? \"\";\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 maxRetries: AI_MAX_RETRIES,\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 // Force a structured tool call on every step. Without this the AI SDK ends the loop as\n // soon as a step returns finishReason !== \"tool-calls\" - a weaker model that replies with\n // prose, an empty turn, or a tool call typed as text then surfaces as an empty\n // \"provider error\"/no-result instead of finishing. \"required\" keeps it emitting real tool\n // calls until it calls `finish`.\n toolChoice: \"required\",\n stopWhen: [stepCountIs(50), hasToolCall(\"finish\")],\n onStepFinish: () => {\n onHeartbeat?.();\n },\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: \"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 { tool } from \"ai\";\nimport { z } from \"zod\";\nimport * as p from \"../ui/prompts\";\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\n .string()\n .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 // In non-interactive / no-TTY runs there is no human to answer, and\n // a prompt would block forever with nobody to answer. Auto-skip so the\n // agent falls back to inferring the answer from the codebase.\n if (!process.stdin.isTTY) {\n return {\n answer: \"No interactive user is available (non-interactive run). Do not ask again - infer the answer by reading the relevant model/schema/service files in the codebase and proceed with your best judgment.\",\n };\n }\n const answer = await p.text({\n message: input.question,\n detail: \"The agent needs this to continue - esc skips the question.\",\n cancelable: true,\n });\n if (p.isCancel(answer)) return { answer: \"User skipped this question\" };\n return { answer };\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 { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { debugLog } from \"../../core/debug\";\nimport type { ProjectMap } from \"../../core/project-map\";\n\n/** Dependency/build artifacts - never part of the app's structure. */\nconst SKIP_DIRS = new Set([\"node_modules\", \"dist\", \"build\", \"coverage\", \"out\", \"target\", \"vendor\"]);\n/** How deep to look for an uncovered directory before giving up on precision. */\nconst MAX_DEPTH = 2;\n/** Cap the report so a pathological tree doesn't flood the agent's context. */\nconst MAX_REPORTED = 12;\n\n/**\n * Directories the map does not account for. The mapper is an LLM and samples\n * the tree differently on every run - this is the mechanical backstop that\n * makes its output consistent: every directory must be inside some entry\n * (frontend, backend, or ignore), or it comes back here and the agent must\n * classify it explicitly. Recurses into partially-covered parents (an `apps/`\n * with two of three children mapped reports exactly the third child).\n */\nexport async function findUncoveredDirs(projectRoot: string, map: ProjectMap): Promise<string[]> {\n const entries = [...map.frontends, ...map.backends, ...map.ignore].map((e) =>\n e.path.replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\"),\n );\n // An entry for the repo root covers everything (single fullstack app).\n if (entries.some((e) => e === \".\" || e === \"\")) return [];\n\n const underEntry = (rel: string): boolean => entries.some((e) => e === rel || rel.startsWith(`${e}/`));\n const hasEntryWithin = (rel: string): boolean => entries.some((e) => e.startsWith(`${rel}/`));\n\n const out: string[] = [];\n\n async function walk(abs: string, rel: string, depth: number): Promise<void> {\n let children: Dirent[];\n try {\n children = await readdir(abs, { withFileTypes: true });\n } catch (err) {\n debugLog(\"Coverage walk could not read a directory, skipping it\", { abs, err });\n return;\n }\n for (const child of children) {\n if (out.length >= MAX_REPORTED) return;\n if (!child.isDirectory()) continue;\n if (child.name.startsWith(\".\") || SKIP_DIRS.has(child.name)) continue;\n const childRel = rel === \"\" ? child.name : `${rel}/${child.name}`;\n if (underEntry(childRel)) continue;\n if (hasEntryWithin(childRel)) {\n // Partially covered (e.g. apps/ with some children mapped):\n // descend to name exactly what is missing; past the depth cap,\n // let it pass rather than report a parent that is mostly mapped.\n if (depth + 1 < MAX_DEPTH) await walk(join(abs, child.name), childRel, depth + 1);\n } else {\n out.push(childRel);\n }\n }\n }\n\n await walk(projectRoot, \"\", 0);\n return out;\n}\n","import { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { type ProjectMap, ProjectMapSchema } from \"../../core/project-map\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { findUncoveredDirs } from \"./coverage\";\n\nexport interface ProjectMapperInput {\n projectRoot: string;\n modelId?: string;\n outputDir: string;\n nonInteractive?: boolean;\n}\n\nconst MAX_STEPS = 60;\n\nconst SYSTEM_PROMPT =\n \"You map a codebase into three groups so the rest of the test-planning pipeline knows exactly what to look at \" +\n \"and what to skip: FRONTENDS (the UI surfaces whose pages and flows could be tested), BACKENDS (the API/service \" +\n \"and the data layer that owns the database models we would seed test data into), and IGNORE (everything \" +\n \"irrelevant to testing this product).\\n\\n\" +\n \"You are a DISCOVERY step, not a decision step. The pipeline tests ONE frontend at a time, but YOU do not choose \" +\n \"which - a human (or the agent driving you) picks afterward from what you found. So enumerate EVERY candidate \" +\n \"frontend and EVERY candidate backend you can justify; do not prune down to a single app. Pruning happens at \" +\n \"selection, using the dependency edges you record.\\n\\n\" +\n \"Work as INVENTORY -> CLASSIFY, in that order:\\n\" +\n \"1. INVENTORY: build the complete list of candidate units MECHANICALLY before classifying anything. Read however \" +\n \"this repo declares its members - workspace/package manifests, build orchestration configs - and list the \" +\n \"top-level directories. That inventory, not your intuition while exploring, is the checklist you work through.\\n\" +\n \"2. CLASSIFY every inventory entry by reading its manifest/entry points - frontend, backend, both, or ignore. \" +\n \"Every entry ends up in the map somewhere; NEVER drop one silently. Two runs over the same codebase must produce \" +\n \"the same map, because both derive it from the same inventory.\\n\\n\" +\n \"What each group means:\\n\" +\n \"- A FRONTEND renders a user interface (pages/routes/views, a UI framework or bundler, browser entry points).\\n\" +\n \"- A BACKEND serves an API and/or owns the data layer (a database schema, ORM models, migrations, server routes). \" +\n \"Backend shapes that are easy to miss - include ALL of them: a service that only exposes an API (no data layer of \" +\n \"its own), a background worker / queue or job consumer that reads or writes the same database, a shared data-layer \" +\n \"package, and a gateway plus the services behind it.\\n\" +\n \"- IGNORE is the rest: infra, build tooling, examples, generated code, and packages that are neither a UI nor a \" +\n \"service/data-layer. Ignoring is an explicit decision with a why - not the absence of an entry.\\n\\n\" +\n \"For EACH frontend, record `dependsOn`: the repo-relative paths (each must be one of the backends you list) that \" +\n \"that frontend actually needs in order to work - the API/service(s) it calls and the data layer(s) that own the \" +\n \"records it renders. Infer these from evidence: the frontend's dependency manifest, the API clients/SDKs it \" +\n \"imports, GraphQL/REST endpoints or gateway URLs it points at, and shared data-layer packages it reads. When the \" +\n \"user selects that frontend, its `dependsOn` backends are pre-checked, so be accurate: list the backends it truly \" +\n \"needs, not every backend in the repo.\\n\\n\" +\n \"Handle every shape without special-casing any framework:\\n\" +\n \"- A single fullstack app can be BOTH a frontend and a backend at the SAME path - list that path under both, and \" +\n \"put its own path in its `dependsOn`.\\n\" +\n \"- A monorepo can hold many apps and packages - list every genuine frontend and backend; only truly irrelevant \" +\n \"directories go in IGNORE.\\n\" +\n \"- There may be MANY backends (a main API, separate services, a shared data-layer package, a gateway plus the \" +\n \"services behind it) - list each one, and wire each frontend's `dependsOn` to just the ones it uses.\\n\" +\n \"- The data layer a frontend uses may live in a sibling/shared package OUTSIDE the frontend's own folder - record \" +\n \"that package as a backend, point its dataLayer.schemaPath at the schema, and include it in the frontend's \" +\n \"`dependsOn`.\\n\" +\n \"- A codebase may ship only one half. If you find frontends but NO backend/data layer (or vice versa), still \" +\n \"record what you found and leave the other group empty - the caller will ask the user to supply the missing half.\\n\\n\" +\n \"Be thorough and evidence-based. When you have enumerated the candidates and their dependency edges, call \" +\n \"set_project_map, then call finish. Keep each `why` to a single concrete sentence citing what you saw.\";\n\n/**\n * Run the project-mapper agent: discover and propose the frontend/backend/ignore\n * partition of the codebase. Returns the captured map, or undefined if the agent\n * never produced one. Persistence and user/Claude confirmation happen in the caller.\n */\nexport async function runProjectMapper(input: ProjectMapperInput): Promise<ProjectMap | undefined> {\n const model = getModel(input.modelId);\n const { logger, onStepFinish } = buildDefaultStepLogger(\"project-map\", MAX_STEPS);\n\n let captured: ProjectMap | undefined;\n let uncoveredAtCapture: string[] = [];\n\n const prompt =\n `Map the codebase rooted at ${input.projectRoot}.\\n\\n` +\n \"First build the full inventory (workspace/package manifests + top-level directories), then classify EVERY \" +\n \"inventory entry: every candidate frontend, every candidate backend/data-layer (including API-only services \" +\n \"and background workers), and everything genuinely irrelevant under ignore. For each frontend record the \" +\n \"backends it depends on. Do not prune to a single app - a human picks the one to test afterward. Then call \" +\n \"set_project_map (it verifies nothing was missed) and finish.\";\n\n const agentConfig = {\n id: \"project-mapper\",\n systemPrompt: SYSTEM_PROMPT,\n model,\n maxSteps: MAX_STEPS,\n tools: async (heartbeat: () => void) => {\n const tools = await buildCodebaseTools(model, input.projectRoot, input.outputDir, heartbeat);\n return {\n ...tools,\n set_project_map: tool({\n description:\n \"Record the final project map: the frontend app(s), the backend(s)/data layer(s), and the \" +\n \"directories to ignore. Call this once you are confident in the partition, then call finish. \" +\n \"The map must account for every directory in the repo - unaccounted ones are returned so you \" +\n \"can classify them and call this again.\",\n inputSchema: ProjectMapSchema,\n execute: async (map) => {\n captured = map;\n const recorded =\n `Recorded: ${map.frontends.length} frontend(s), ${map.backends.length} backend(s), ` +\n `${map.ignore.length} ignored.`;\n const uncovered = await findUncoveredDirs(input.projectRoot, map);\n uncoveredAtCapture = uncovered;\n if (uncovered.length > 0) {\n return (\n `${recorded} BUT these directories are not covered by any entry: ` +\n `${uncovered.join(\", \")}. Check each one - if it holds a frontend or a ` +\n \"backend/data layer (including API-only services and background workers), add it; \" +\n \"otherwise add it to ignore with a why. Then call set_project_map again with the \" +\n \"complete map.\"\n );\n }\n return `${recorded} Every directory is accounted for. Now call finish.`;\n },\n }),\n finish: tool({\n description: \"End this step. Call once set_project_map has recorded a complete map.\",\n inputSchema: z.object({}),\n execute: () => {\n if (captured == null) {\n return { error: \"Cannot finish: no map recorded - call set_project_map first.\" };\n }\n if (uncoveredAtCapture.length > 0) {\n return {\n error:\n \"Cannot finish: the recorded map leaves directories unaccounted for: \" +\n `${uncoveredAtCapture.join(\", \")}. Classify each (frontend, backend, or ` +\n \"ignore with a why) and call set_project_map again.\",\n };\n }\n return \"Done.\";\n },\n }),\n };\n },\n onStepFinish,\n };\n\n // Incomplete coverage keeps the nudge loop alive (the agent is told which\n // directories it missed); after the nudge budget we still return whatever\n // map was captured - a map with holes beats no map.\n await runAgent(agentConfig, prompt, () => (uncoveredAtCapture.length === 0 ? captured : undefined));\n logger.summary();\n\n return captured;\n}\n","import { existsSync } from \"fs\";\nimport * as path from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { buildCodebaseTools } from \"../../tools\";\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(([, aValue], [, bValue]) => aValue.path.localeCompare(bValue.path))\n .join(\"\\n\");\n }\n\n static from(obj: unknown, projectRoot: string): Page | Error {\n const result = Page.safeParse(obj);\n if (!result.success) return result.error;\n\n const data = result.data;\n\n // Resolve against the TARGET PROJECT, never the CLI's own cwd - the\n // old cwd-relative resolve rejected honest project-relative paths,\n // which trained the model into ../-chain brute force until it escaped\n // to filesystem root, storing garbage paths in pages.json.\n const abs = path.isAbsolute(data.path) ? data.path : path.resolve(projectRoot, data.path);\n if (!existsSync(abs)) {\n return new Error(`path ${data.path} does not exist under ${projectRoot}`);\n }\n\n return { ...data, path: path.relative(projectRoot, abs) };\n }\n}\n\nexport async function runPageFinder(input: PageFinderGeneratorInput): Promise<Map<string, Page>> {\n const model = getModel(input.modelId);\n\n const pageCollector = new PageCollector();\n const projectRoot = input.projectRoot;\n let finished = false;\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:\n \"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 \"When every page has been added, call the finish tool to end the step.\\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 \"list_directory truncates at its depth limit; if a directory goes deeper, narrow the path or use glob \" +\n \"to reach the rest - do not re-list a path you have already seen.\",\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, projectRoot);\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 finish: tool({\n description: \"End this step. Call once every page in the codebase has been added via add_page.\",\n inputSchema: z.object({}),\n execute: () => {\n if (pageCollector.pages.size === 0) {\n return {\n error: \"Cannot finish: no pages added yet - explore the codebase and add_page each one.\",\n };\n }\n finished = true;\n return `Done - ${pageCollector.pages.size} pages recorded.`;\n },\n }),\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => (finished ? pageCollector.pages : undefined));\n logger.summary();\n\n return pageCollector.pages;\n}\n","import { getActiveStore } from \"../ui/store\";\nimport type { StepName } from \"./state\";\n\n/**\n * Report a step's real done/total to the dashboard strip and the ETA model's\n * live-pace layer. The agents' own trackers (pages read, models audited,\n * nodes tested) are the source of truth; this is a no-op headless.\n */\nexport function reportSubProgress(step: StepName, done: number, total: number, unit: string, note?: string): void {\n if (total <= 0) return;\n getActiveStore()?.setSubProgress(step, { done: Math.min(done, total), total, unit, note });\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, resolve } from \"node:path\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { type AgentResult, buildDefaultStepLogger, formatRetryGuidance, runAgent } from \"../../core/agent\";\nimport { formatContext, type ProjectContext } from \"../../core/context\";\nimport { debugLog } from \"../../core/debug\";\nimport { getModel } from \"../../core/model\";\nimport { pickString } from \"../../core/pick-string\";\nimport { reportSubProgress } from \"../../core/progress\";\nimport type { buildReadFileTool } from \"../../tools\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\n\nexport interface KBGeneratorInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n retryGuidance?: string;\n}\n\nclass PageTracker {\n registered = new Set<string>();\n read = new Set<string>();\n\n // Registered pages (from pages.json) are absolute paths, but the agent reads them\n // with paths relative to the working directory. Canonicalize both to an absolute\n // path against projectRoot so coverage matches regardless of how each side spelled\n // it - otherwise the finish gate never clears and the agent nudges out re-reading.\n constructor(private readonly projectRoot: string) {}\n\n private normalize(filePath: string): string {\n return resolve(this.projectRoot, filePath);\n }\n\n register(pages: string[]) {\n for (const p of pages) this.registered.add(this.normalize(p));\n reportSubProgress(\"kb\", this.read.size, this.registered.size, \"pages\");\n }\n\n markRead(filePath: string) {\n const normalized = this.normalize(filePath);\n if (this.registered.has(normalized)) {\n this.read.add(normalized);\n reportSubProgress(\"kb\", this.read.size, this.registered.size, \"pages\");\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\n// \"Small\" vs \"large\" app is decided purely by how many routes were registered - the one\n// number that drives the coverage problem. At or below this many routes the agent can\n// (and must) read every one, so the finish gate demands 100%. Above it, a single pass\n// samples the app rather than reading all routes, and an unreachable 100% gate makes the\n// agent nudge-thrash; there we let it finish once it has covered a solid floor instead.\nconst FULL_COVERAGE_MAX_ROUTES = 40;\nconst LARGE_APP_COVERAGE_FLOOR = 0.5;\n\n/** How many registered routes must be read before finish is allowed, given the total. */\nfunction requiredReads(total: number): number {\n if (total <= FULL_COVERAGE_MAX_ROUTES) return total;\n return Math.ceil(total * LARGE_APP_COVERAGE_FLOOR);\n}\n\nfunction buildFinishTool(tracker: PageTracker, onFinish: (result: AgentResult) => void) {\n return tool({\n description:\n \"Call when you have finished generating the knowledge base. \" +\n \"BLOCKED until you have read enough of the registered routes (every route on a small app; a strong \" +\n \"majority on a large one) - call page_coverage first to check how many remain.\",\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 const required = requiredReads(cov.total);\n if (cov.read < required) {\n const preview = cov.unread.slice(0, 40).join(\"\\n\");\n const more = cov.unread.length > 40 ? `\\n...and ${cov.unread.length - 40} more` : \"\";\n return {\n error:\n `Cannot finish: only ${cov.read}/${cov.total} routes read - read at least ${required - cov.read} ` +\n `more (target ${required} of ${cov.total}). Start with:\\n${preview}${more}`,\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(tracker: PageTracker, baseTool: ReturnType<typeof buildReadFileTool>) {\n return tool({\n description: baseTool.description,\n inputSchema: baseTool.inputSchema,\n execute: async (input, options) => {\n const filePath = pickString(input, [\"filePath\", \"path\", \"file_path\"]) ?? \"\";\n tracker.markRead(filePath);\n return baseTool.execute!(input, options);\n },\n });\n}\n\n/**\n * The KB agent config, parameterized by the page tracker so the main generation pass and\n * the finalization passes each get their own coverage gate. Keeping this in one place\n * means the tuned SYSTEM_PROMPT and tool wiring stay identical across every pass.\n */\nfunction buildKbAgentConfig(\n tracker: PageTracker,\n model: ReturnType<typeof getModel>,\n input: KBGeneratorInput,\n onStepFinish: ReturnType<typeof buildDefaultStepLogger>[\"onStepFinish\"],\n setResult: (r: AgentResult) => void,\n) {\n return {\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, setResult),\n };\n },\n onStepFinish,\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 setResult = (r: AgentResult) => {\n result = r;\n };\n\n const { logger, onStepFinish } = buildDefaultStepLogger(\"kb\", 150);\n\n const contextBlock =\n (input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\") +\n formatRetryGuidance(input.retryGuidance);\n\n const pages = input.projectContext?.pages;\n\n const tracker = new PageTracker(input.projectRoot);\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 you have not read enough of the registered routes\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 you have not read enough of the registered routes\n\nOutput files:\n1. AUTONOMA.md - with YAML frontmatter (app_name, app_description, core_flows, feature_count)`;\n\n const agentConfig = buildKbAgentConfig(tracker, model, input, onStepFinish, setResult);\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\")\n .then(() => true)\n .catch((err) => {\n debugLog(\"AUTONOMA.md not found while checking step completion\", { err });\n return false;\n });\n if (!result?.success && autonomaExists) {\n result = {\n success: true,\n artifacts: [\"AUTONOMA.md\"],\n summary: \"Knowledge base generated.\",\n };\n }\n\n // Config for the finalization passes (self-review + user review). AUTONOMA.md is\n // already written by now, so register every route as read - the coverage gate must\n // not block these passes from re-calling finish after edits.\n const finalTracker = new PageTracker(input.projectRoot);\n if (pages?.length) {\n const paths = pages.map((p) => p.path);\n finalTracker.register(paths);\n for (const path of paths) finalTracker.markRead(path);\n }\n const finalConfig = buildKbAgentConfig(finalTracker, model, input, onStepFinish, setResult);\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(finalConfig, 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 // Output review happens live in the TUI - the run no longer stops to ask.\n const reviewed = result;\n\n return (\n reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"KB generator agent stopped without producing AUTONOMA.md\",\n }\n );\n}\n","export const SYSTEM_PROMPT = `You audit a codebase to discover EVERY database model and every way each is created. You must find ALL models - missing one means the test data layer has a gap. This audit drives factory generation and scenario planning.\n\n## The two orthogonal questions\n\nFor every model, answer BOTH independently:\n\n1. **independently_created** - Does the codebase have an exported function/method that creates this model on its own? Boolean.\n2. **created_by** - When you trace every other model's creation function, does any of them produce this model as a side effect? List of {owner, via, why} entries; empty if none.\n\nThese are NOT mutually exclusive. A model can be both. Do not collapse the two.\n\n## The four states a model can be in\n\n| independently_created | created_by | Interpretation |\n|---|---|---|\n| true | [] | Pure root - only standalone creation exists |\n| true | non-empty | Dual - has standalone path AND is produced by owners |\n| false | non-empty | Pure dependent - only reachable via owner's creation |\n| false | [] | INVALID - unreachable model, fix before writing |\n\n## MANDATORY DISCOVERY PROCESS\n\n### Step 0: Identify the database framework\nDetermine which ORM/database tool the project uses. Explore the project structure - read config files, schema definitions, and imports to identify the data layer. Every project is different; use your tools (grep, glob, read_file) to discover the patterns.\n\n### Step 1: Find ALL model definitions and register them\nBased on the framework you identified, use grep and glob to find ALL model/table/entity definitions. Call register_models with the complete list. Real applications typically have 30-150 models - if you found fewer than 20, search harder before registering.\n\n### Step 2: Process models using the queue\nAfter registering, call next_model to get the first model. For each model:\n\n1. grep for creation patterns (e.g. \"ModelName.create\", \"new ModelName\", \"insert into model\") - 1 to 3 greps MAX\n2. If you find a creation path: read the file, call mark_model_audited with the details\n3. If you can't find it after 2-3 greps: call next_model to skip and move on\n\nIMPORTANT: Do NOT spend more than 3-4 steps per model. The queue ensures you process every model. If a model has no obvious creation path, skipping it is valid - it gets marked as \"no creation path found.\"\n\nWhen you call mark_model_audited, also note side effects you see in the creation function (other models created as part of the same operation). Record these in the created_by field of those other models when you reach them.\n\n### Step 3: Write output and finish\nWhen next_model returns done, write entity-audit.md and call finish.\n\n## Output file\n\nYou produce ONE file: entity-audit.md. It is the complete spec a developer (or\ncoding agent) later implements factories from, so creation_file, creation_function,\nand side_effects must be precise enough to write the factory without re-auditing.\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## 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 { glob } from \"glob\";\nimport { z } from \"zod\";\nimport { runAgent, buildDefaultStepLogger, formatRetryGuidance, type AgentResult } from \"../../core/agent\";\nimport { type ProjectContext, formatContext } from \"../../core/context\";\nimport { debugLog } from \"../../core/debug\";\nimport { formatException } from \"../../core/errors\";\nimport { getModel } from \"../../core/model\";\nimport { reportSubProgress } from \"../../core/progress\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\n\n// Each model costs the agent ~2 steps (grep for its creation path, mark it audited), so a\n// large shared schema needs headroom well above a typical app's. At 200 the agent step-outs\n// mid-audit; 400 covers ~200 models with the safety net still catching anything larger.\nconst MAX_STEPS = 400;\n\nexport interface EntityAuditInput {\n projectRoot: string;\n outputDir: string;\n modelId?: string;\n projectContext?: ProjectContext;\n nonInteractive?: boolean;\n retryGuidance?: string;\n /**\n * Optional scope hint from the project map: which backend(s)/data-layer(s) own the\n * models to audit, so a monorepo run stays on the selected schema instead of the\n * whole tree. Appended to the task prompt; never edits the tuned system prompt.\n */\n scopeHint?: 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;\n\n register(models: string[]) {\n for (const m of models) this.registered.add(m);\n reportSubProgress(\"entityAudit\", this.auditedModels.size, this.registered.size, \"models\");\n }\n\n initQueue() {\n this.queue = [...this.registered].filter((m) => !this.auditedModels.has(m));\n }\n\n nextModel(): { model: string; remaining: number } | undefined {\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 = undefined;\n return undefined;\n }\n\n markAudited(model: AuditedModel) {\n this.auditedModels.set(model.name, model);\n reportSubProgress(\"entityAudit\", this.auditedModels.size, this.registered.size, \"models\");\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\n .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 })\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\n .string()\n .optional()\n .describe(\"Function/method name (e.g. 'UserService.create' or 'create_user')\"),\n side_effects: z\n .array(z.string())\n .optional()\n .describe(\"Side effects of creation (e.g. 'creates default Settings row', 'hashes password')\"),\n created_by: z\n .array(\n z.object({\n owner: z.string().describe(\"Owner model name\"),\n via: z\n .string()\n .optional()\n .describe(\"Function that creates this model (e.g. 'OrganizationService.create')\"),\n why: z\n .string()\n .optional()\n .describe(\"One sentence explaining why this model is created as a side effect\"),\n }),\n )\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(tracker: ModelTracker, onFinish: (result: AgentResult) => void) {\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 | undefined> {\n const candidates = await glob(\"**/schema.prisma\", {\n cwd: projectRoot,\n ignore: [\"**/node_modules/**\"],\n absolute: true,\n });\n return candidates[0] ?? undefined;\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(projectRoot: string): Promise<FrameworkDetection | undefined> {\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 undefined;\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\", MAX_STEPS);\n\n const scopeBlock = input.scopeHint != null ? `\\n${input.scopeHint}\\n` : \"\";\n const contextBlock =\n (input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\") +\n scopeBlock +\n formatRetryGuidance(input.retryGuidance);\n\n const preRegBlock =\n 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${\n preRegisteredCount === 0\n ? `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`\n : \"1. Call next_model\"\n} 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: MAX_STEPS,\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) => {\n result = r;\n }),\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 | undefined> => {\n if (tracker.auditedModels.size === 0) return undefined;\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 // Output review happens live in the TUI - the run no longer stops to ask.\n const reviewed = result;\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:\n \"Entity audit generated (finish tool may not have captured the result, but entity-audit.md exists).\",\n };\n } catch (err) {\n debugLog(\"entity-audit.md not readable; falling back to reviewed result\", { err });\n }\n }\n\n return (\n 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}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function parseEntityNames(outputDir: string): Promise<string[]> {\n try {\n const content = await readFile(join(outputDir, \"entity-audit.md\"), \"utf-8\");\n const names: string[] = [];\n for (const line of content.split(\"\\n\")) {\n const match = line.match(/^\\s+-\\s+name:\\s+(.+)$/);\n if (match) names.push(match[1]!.trim());\n }\n return names;\n } catch {\n return [];\n }\n}\n","export const SCENARIO_DESIGN_PROMPT = `You are a scenario designer for E2E testing. You read an entity audit and design a single \"standard\" test data scenario.\n\n## Your input\n- entity-audit.md: models, creation paths, side effects\n- AUTONOMA.md: app context, core flows\n\n## Your output\nA scenarios.md file with YAML frontmatter describing a single \"standard\" scenario.\n\n## Scenario design rules\n\n1. ONE scenario: \"standard\" - represents a realistic working state of the application\n2. Realistic data volumes:\n - An email app gets 50+ emails, not 1\n - A payment app gets all payment method types\n - A project management tool gets multiple projects with tasks in various states\n3. Enum coverage: for every enum field, include at least one record per value\n4. The scenario must exercise all entity types from the audit\n5. Entity tables must be consistent - FK references must point to real records\n\n## Output format\n\n\\`\\`\\`yaml\n---\nscenario_count: 1\nscenarios:\n - name: standard\n description: \"Realistic working state with diverse data\"\nentity_types:\n - name: Organization\n count: 1\n - name: User\n count: 3\n - name: Project\n count: 5\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## Data values\nEvery value in the scenario is concrete and static - write the actual data the\nrecords should hold. Do NOT use placeholders, tokens, or templated/\"dynamic\"\nvalues; the recipe builder generates the exact records from what you write.`;\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 matter from \"gray-matter\";\n\nconst RESET = \"\\x1b[0m\";\nconst DIM = \"\\x1b[2m\";\nconst BOLD = \"\\x1b[1m\";\n\nexport interface ScenarioEntityType {\n name: string;\n count: number;\n}\n\nexport interface ParsedScenario {\n scenarioNames: string[];\n entityTypes: ScenarioEntityType[];\n}\n\n/** Parse scenarios.md frontmatter into the scenario names and entity types. */\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: {\n scenarios?: { name?: unknown }[];\n entity_types?: { name?: unknown; count?: unknown }[];\n } = matter(raw).data;\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 };\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\n/**\n * Scenario data must be fully concrete - there is no variable mechanism. Catch\n * any placeholder, token, or leftover `variable_fields` block the design agent\n * might still emit, so it can be handed back for self-correction. This is a soft\n * check: it returns one human-readable error per problem (empty array = clean)\n * and never throws, so a stray placeholder is something the agent fixes, not a\n * fatal failure.\n */\nexport function validateScenarioIsConcrete(content: string): string[] {\n const errors: string[] = [];\n const checks: { pattern: RegExp; label: string }[] = [\n { pattern: /\\{\\{[a-zA-Z0-9_]+\\}\\}/g, label: \"{{token}} placeholder\" },\n { pattern: /(?<!\\{)\\{[a-z][a-zA-Z]*\\}(?!\\})/g, label: \"bare {variable} placeholder\" },\n { pattern: /^\\s*variable_fields\\s*:/m, label: \"variable_fields block\" },\n ];\n\n for (const { pattern, label } of checks) {\n const match = content.match(pattern);\n if (match && match.length > 0) {\n errors.push(\n `${label}: \"${match[0].trim()}\" - scenario values must be concrete. ` +\n `Replace it with the exact static value (there is no variable mechanism).`,\n );\n }\n }\n\n return errors;\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.\n */\nexport function renderScenarioTable(parsed: ParsedScenario): string {\n if (parsed.entityTypes.length === 0) return \"\";\n\n const NAME_MAX = 32;\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 }));\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\n const header = `${BOLD}${pad(\"#\", numW)} ${pad(\"Entity\", nameW)} ${pad(\"Count\", countW)}${RESET}`;\n const sep = `${DIM}${\"─\".repeat(numW + nameW + countW + 4)}${RESET}`;\n\n const body = rows.map((r) => `${pad(r.num, numW)} ${pad(r.name, nameW)} ${pad(r.count, countW)}`).join(\"\\n\");\n\n const scenarioLabel = parsed.scenarioNames.length ? `scenario: ${parsed.scenarioNames.join(\", \")} · ` : \"\";\n const caption = `${DIM}${scenarioLabel}${parsed.entityTypes.length} entity types · ${totalRecords} records${RESET}`;\n\n return `${header}\\n${sep}\\n${body}\\n${caption}`;\n}\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 { debugLog } from \"../../core/debug\";\nimport { getModel } from \"../../core/model\";\nimport { parseEntityNames } from \"../../core/parse-entity-audit\";\nimport { buildCodebaseTools } from \"../../tools\";\nimport { buildAskUserTool } from \"../../tools/ask-user\";\nimport { SCENARIO_DESIGN_PROMPT } from \"./prompt\";\nimport { validateScenarioIsConcrete } from \"./scenario-table\";\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 /** Optional backend/data-layer scope hint from the project map (appended to the prompt). */\n scopeHint?: string;\n}\n\nexport function 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 // These checks return an error string back to the agent so it can fix the\n // scenario and call finish again - they must never throw / fail fatally.\n let content: string;\n try {\n content = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch {\n return { error: \"Cannot finish: scenarios.md not found. Write it first.\" };\n }\n\n if (requiredEntities.length > 0) {\n const missing = requiredEntities.filter((e) => !content.includes(e));\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 }\n\n const concretenessErrors = validateScenarioIsConcrete(content);\n if (concretenessErrors.length > 0) {\n return {\n error:\n `Cannot finish: scenario data must be fully concrete - no variables, tokens, or placeholders.\\n` +\n `Fix these before calling finish:\\n` +\n concretenessErrors.map((e) => ` - ${e}`).join(\"\\n\"),\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 scopeBlock = input.scopeHint != null ? `\\n${input.scopeHint}\\n` : \"\";\n const contextBlock =\n (input.projectContext ? \"\\n\" + formatContext(input.projectContext) + \"\\n\" : \"\") +\n scopeBlock +\n formatRetryGuidance(input.retryGuidance);\n\n const requiredEntities = await parseEntityNames(input.outputDir);\n\n const entityListBlock =\n 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)\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 {\n ...tools,\n ask_user: buildAskUserTool(),\n finish: buildFinishTool(requiredEntities, input.outputDir, (r) => {\n result = r;\n }),\n };\n },\n onStepFinish,\n };\n\n await runAgent(agentConfig, prompt, () => result);\n logger.summary();\n\n // Output review happens live in the TUI - the run no longer stops to ask.\n const reviewed = result;\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 (err) {\n debugLog(\"scenarios.md not readable; falling back to reviewed result\", { err });\n }\n }\n\n return (\n reviewed ?? {\n success: false,\n artifacts: [],\n summary: \"Scenario agent stopped without producing scenarios.md\",\n }\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 {\n ...tools,\n ask_user: buildAskUserTool(),\n finish: buildFinishTool(requiredEntities, input.outputDir, (r) => {\n result = r;\n }),\n };\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 } 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\n .array(createdBySchema)\n .nullish()\n .transform((v) => v ?? []),\n});\n\nconst frontmatterSchema = z.object({\n models: z\n .array(auditedModelSchema)\n .nullish()\n .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> | undefined;\n let inCreatedBy = false;\n let currentCreatedBy: { owner: string; via?: string; why?: string } | undefined;\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 = undefined;\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 = undefined;\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\n .replace(/^\\s{6}-\\s*/, \"\")\n .replace(/^[\"']|[\"']$/g, \"\")\n .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(models: AuditedModel[], importanceRank?: Map<string, number>): 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.filter((m) => !result.includes(m.name)).map((m) => m.name);\n console.warn(\n `[recipe-builder] Circular dependency detected for: ${missing.join(\", \")}. Appending in original order.`,\n );\n for (const m of missing) result.push(m);\n }\n\n return result;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { debugLog } from \"../../core/debug\";\n\n/**\n * Marker the interactive agent writes as its last act, once every entity and the\n * full-recipe pass have validated. The agent owns all validation (per entity:\n * up -> DB check -> down -> DB check); this marker is how it reports the whole\n * session done, and its presence (with `complete: true`) is what the CLI submits on.\n */\nexport const COMPLETION_MARKER_FILE = \".sdk-integration-complete\";\n\nconst completionSchema = z.object({ complete: z.literal(true) });\n\n/**\n * Whether the agent reported the integration complete. Returns false (not a throw)\n * when the marker is missing or malformed, so a bailed/incomplete session degrades\n * to a bounded re-launch instead of crashing.\n */\nexport async function readCompletion(outputDir: string): Promise<boolean> {\n let raw: string;\n try {\n raw = await readFile(join(outputDir, COMPLETION_MARKER_FILE), \"utf-8\");\n } catch (err) {\n debugLog(\"No completion marker yet\", { err });\n return false;\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (err) {\n debugLog(\"Completion marker is not valid JSON\", { err });\n return false;\n }\n\n const parsed = completionSchema.safeParse(json);\n if (!parsed.success) {\n debugLog(\"Completion marker failed schema validation\", { issues: parsed.error.issues });\n return false;\n }\n return true;\n}\n","import type { StdioOptions } from \"node:child_process\";\nimport { dirname } from \"node:path\";\nimport spawn from \"cross-spawn\";\nimport which from \"which\";\nimport { debugLog } from \"../../core/debug\";\nimport * as p from \"../../ui/prompts\";\nimport { readCompletion } from \"./completion\";\n\n/** How often to check for the completion marker while the agent runs. */\nconst MARKER_POLL_MS = 2000;\n/** Marker seen -> let the agent finish streaming its summary before reclaiming. */\nconst MARKER_EXIT_GRACE_MS = 30_000;\n/** SIGTERM ignored -> force-kill after this long. */\nconst KILL_ESCALATION_MS = 10_000;\n\n/**\n * The autonomy the interactive agent runs with, in plain-language labels that map\n * to Claude's `--permission-mode`. `plan` (read-only) is intentionally excluded -\n * it can't implement anything, so it's irrelevant to a handoff whose whole job is\n * to write code.\n */\nexport type PermissionMode = \"default\" | \"acceptEdits\" | \"bypassPermissions\";\n\nexport const DEFAULT_PERMISSION_MODE: PermissionMode = \"bypassPermissions\";\n\nexport const PERMISSION_MODE_LABELS: Record<PermissionMode, string> = {\n default: \"Approve each command\",\n acceptEdits: \"Auto-edit files, approve commands\",\n bypassPermissions: \"Fully autonomous\",\n};\n\n/**\n * The one injection seam for the handoff. A launcher knows how to detect its\n * agent on the machine and how to run it, attached to the terminal, over a\n * rendered prompt file. Codex (and other agents) slot in later by implementing\n * this interface; the handoff flow never changes.\n */\nexport interface AgentLauncher {\n /** Stable id persisted in state and matched by the `--agent` flag (e.g. \"claude\"). */\n readonly id: string;\n /** Human label for prompts and announcements (e.g. \"Claude Code\"). */\n readonly label: string;\n /** Whether the agent's binary is on PATH. */\n isAvailable(): Promise<boolean>;\n /**\n * Run the agent over the rendered prompt file, inheriting the env the CLI spawns\n * it with (so the canonical shared secret flows through to the app). When\n * `interactive`, it attaches this process's stdio so the developer watches and\n * drives it (and the agent can surface its own login); otherwise it runs headless\n * and autonomous (`-p`), its output piped to the CLI's stdout/stderr. Resolves\n * with the agent's exit code once it exits.\n */\n launch(promptFile: string, permissionMode: PermissionMode, interactive: boolean): Promise<number | undefined>;\n}\n\nexport interface ClaudeLauncherOptions {\n /** Directory the agent runs in - the developer's repo. */\n cwd: string;\n /** Env the agent (and any app it boots) inherits, including AUTONOMA_SHARED_SECRET. */\n env: NodeJS.ProcessEnv;\n}\n\nconst CLAUDE_ID = \"claude\";\n\n/** Points the agent at the rendered prompt file it must read and follow. */\nfunction launchMessage(promptFile: string): string {\n return (\n `Read the file ${promptFile} and follow its instructions exactly to integrate ` +\n `Autonoma into this application. It is your complete spec. Do not stop until every ` +\n `item in it is done and you have written the completion marker it describes.`\n );\n}\n\n/** Claude Code launcher. Authentication is Claude's own concern - it surfaces its\n * login flow live in the attached terminal. */\nexport class ClaudeLauncher implements AgentLauncher {\n readonly id = CLAUDE_ID;\n readonly label = \"Claude Code\";\n\n constructor(private readonly opts: ClaudeLauncherOptions) {}\n\n async isAvailable(): Promise<boolean> {\n const resolved = await which(CLAUDE_ID, { nothrow: true });\n debugLog(\"Probed for claude on PATH\", { found: resolved != null });\n return resolved != null;\n }\n\n launch(promptFile: string, permissionMode: PermissionMode, interactive: boolean): Promise<number | undefined> {\n debugLog(\"Launching Claude Code\", { promptFile, permissionMode, interactive });\n const message = launchMessage(promptFile);\n // Interactive: attach the terminal so the developer watches/steers and Claude\n // can surface its login. Headless (`-p`): autonomous print mode for\n // --non-interactive runs, with output piped to our stdout/stderr for the logs.\n const args = interactive\n ? [\"--permission-mode\", permissionMode, message]\n : [\"-p\", message, \"--permission-mode\", permissionMode, \"--verbose\"];\n const stdio: StdioOptions = interactive ? \"inherit\" : [\"ignore\", \"inherit\", \"inherit\"];\n\n return new Promise<number | undefined>((resolve) => {\n // env carries the canonical shared secret through to the app and the `sdk` calls.\n const proc = spawn(CLAUDE_ID, args, {\n cwd: this.opts.cwd,\n env: this.opts.env,\n stdio,\n });\n // An interactive session never exits on its own - after the final\n // message it sits at its REPL. The completion marker is the real\n // \"done\" signal, so watch for it and reclaim the terminal.\n const stopWatching = interactive ? watchForCompletion(dirname(promptFile), proc) : () => {};\n proc.on(\"error\", (err: Error) => {\n debugLog(\"Claude Code failed to spawn\", { err });\n p.log.error(`Couldn't launch Claude Code: ${err.message}`);\n stopWatching();\n resolve(undefined);\n });\n proc.on(\"close\", (code) => {\n debugLog(\"Claude Code exited\", { code });\n stopWatching();\n resolve(code ?? undefined);\n });\n });\n }\n}\n\nexport interface CompletionWatchTiming {\n pollMs: number;\n graceMs: number;\n killMs: number;\n}\n\nconst DEFAULT_WATCH_TIMING: CompletionWatchTiming = {\n pollMs: MARKER_POLL_MS,\n graceMs: MARKER_EXIT_GRACE_MS,\n killMs: KILL_ESCALATION_MS,\n};\n\n/**\n * Poll for the completion marker while the interactive agent runs; once it\n * appears, give the agent a beat to finish streaming its summary, then\n * terminate it so control returns to the planner. Returns a cleanup fn.\n */\nexport function watchForCompletion(\n outputDir: string,\n proc: { kill(signal: NodeJS.Signals): boolean },\n timing: CompletionWatchTiming = DEFAULT_WATCH_TIMING,\n): () => void {\n let graceTimer: ReturnType<typeof setTimeout> | undefined;\n let killTimer: ReturnType<typeof setTimeout> | undefined;\n\n const poll = setInterval(() => {\n void readCompletion(outputDir).then((complete) => {\n if (!complete || graceTimer != null) return;\n debugLog(\"Completion marker detected while the agent runs; scheduling terminal reclaim\");\n clearInterval(poll);\n graceTimer = setTimeout(() => {\n debugLog(\"Reclaiming the terminal from the interactive agent (SIGTERM)\");\n proc.kill(\"SIGTERM\");\n killTimer = setTimeout(() => {\n debugLog(\"Agent ignored SIGTERM; escalating to SIGKILL\");\n proc.kill(\"SIGKILL\");\n }, timing.killMs);\n }, timing.graceMs);\n });\n }, timing.pollMs);\n\n return () => {\n clearInterval(poll);\n if (graceTimer != null) clearTimeout(graceTimer);\n if (killTimer != null) clearTimeout(killTimer);\n };\n}\n\n/** Every launcher this CLI knows how to build. Claude only, for now. */\nexport function buildAllLaunchers(opts: ClaudeLauncherOptions): AgentLauncher[] {\n return [new ClaudeLauncher(opts)];\n}\n\n/**\n * Probe PATH and pick the launcher to hand off to. Zero available -> undefined\n * (the caller decides: manual fallback interactively, hard error otherwise);\n * exactly one -> use it (announce, don't prompt for a choice of one); multiple ->\n * prompt to pick when interactive, else undefined (can't disambiguate headlessly -\n * name one with `--agent`). A preset id (from `--agent`) short-circuits detection\n * when that agent is available.\n */\nexport async function selectLauncher(\n launchers: AgentLauncher[],\n presetId?: string,\n interactive = true,\n): Promise<AgentLauncher | undefined> {\n const availability = await Promise.all(launchers.map((l) => l.isAvailable()));\n const available = launchers.filter((_, i) => availability[i]);\n debugLog(\"Detected available agents\", { available: available.map((l) => l.id), presetId, interactive });\n\n if (presetId != null) {\n const preset = available.find((l) => l.id === presetId);\n if (preset != null) return preset;\n p.log.warn(`Requested agent \"${presetId}\" is not installed or not supported.`);\n }\n\n if (available.length === 0) return undefined;\n\n if (available.length === 1) {\n const only = available[0]!;\n p.log.info(`Found ${only.label} - will use it for the integration.`);\n return only;\n }\n\n // Multiple agents and no usable preset: can't prompt headlessly.\n if (!interactive) return undefined;\n\n const selected = await p.select({\n message: \"Which agent should implement the integration?\",\n options: available.map((l) => ({ value: l.id, label: l.label })),\n });\n if (p.isCancel(selected)) throw new Error(\"Agent selection cancelled\");\n return available.find((l) => l.id === selected);\n}\n\n/**\n * Resolve the permission mode: a preset from the `--permission-mode` flag wins;\n * otherwise offer a select prompt defaulting to fully autonomous.\n */\nexport async function selectPermissionMode(preset?: PermissionMode): Promise<PermissionMode> {\n if (preset != null) return preset;\n\n const selected = await p.select<PermissionMode>({\n message: \"How much autonomy should the agent have?\",\n options: [\n { value: \"bypassPermissions\", label: PERMISSION_MODE_LABELS.bypassPermissions },\n { value: \"acceptEdits\", label: PERMISSION_MODE_LABELS.acceptEdits },\n { value: \"default\", label: PERMISSION_MODE_LABELS.default },\n ],\n initialValue: DEFAULT_PERMISSION_MODE,\n });\n if (p.isCancel(selected)) throw new Error(\"Permission mode selection cancelled\");\n return selected;\n}\n\n/** Validate a raw `--permission-mode` flag value, returning undefined if unset/invalid. */\nexport function parsePermissionMode(value?: string): PermissionMode | undefined {\n if (value === \"default\" || value === \"acceptEdits\" || value === \"bypassPermissions\") return value;\n return undefined;\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { COMPLETION_MARKER_FILE } from \"./completion\";\n\n/**\n * The integration recipe, rendered to a durable file. This single versioned\n * artifact drives the automated run, the manual fallback, and any debugging. It\n * must work on ANY project: it never assumes a framework, file extension,\n * directory convention, or routing scheme. It tells the agent WHAT to achieve and\n * lets it DISCOVER the stack - including how to run the app - with its own tools.\n *\n * The agent does ALL validation itself, per entity, driving the endpoint through\n * the CLI's own `sdk` commands and inspecting the database directly, then reports\n * the whole session done by writing a completion marker.\n */\n\n/** Bump when the prompt's contract changes; surfaced in the file header. */\nexport const INTEGRATION_PROMPT_VERSION = 5;\n\n/** The rendered prompt lives here in the app's planner output dir. */\nexport const INTEGRATION_PROMPT_FILE = \"integration-prompt.md\";\n\n/** Preferred endpoint path unless the repo has a clearly better convention. */\nconst DEFAULT_ENDPOINT_PATH = \"/api/autonoma\";\n\nexport interface IntegrationPromptParams {\n /** The planner output dir holding the frozen artifacts (KB, audit, scenarios). */\n outputDir: string;\n /** Where the agent writes the recipe it generates and validates against. */\n recipePath: string;\n /** How the agent invokes this CLI's endpoint tool, e.g. `node /path/dist/index.js`.\n * Used as `<cliCommand> sdk discover|up|down ...`. */\n cliCommand: string;\n /**\n * A note about why a prior session didn't complete, present only on a\n * re-launch, so the agent resumes rather than repeating finished work.\n */\n priorFailure?: string;\n}\n\nexport function renderIntegrationPrompt(params: IntegrationPromptParams): string {\n const priorFailureSection =\n params.priorFailure != null\n ? `\n═══ A PRIOR SESSION DID NOT COMPLETE - READ THIS FIRST ═══\n${params.priorFailure}\nRe-read your IMPLEMENTATION.md checklist, pick up at the first unfinished entity,\nand do NOT redo entities already validated. Finish every remaining item, then write\nthe completion marker.\n`\n : \"\";\n\n return `<!-- Autonoma integration prompt v${INTEGRATION_PROMPT_VERSION} -->\nYou are integrating Autonoma into THIS application, working in a LOCAL checkout of\nthe repo. The Autonoma planner has ALREADY run locally and produced its artifacts\n(knowledge base, entity audit, scenarios) at:\n ${params.outputDir}\nYou are the developer picking up exactly where the planner hands off: implement the\ntest-data layer (the SDK integration), GENERATE the test-data recipe, and validate\nit. Do NOT re-run the planner; read its artifacts as your spec.\n${priorFailureSection}\nWork without asking questions. Make reasonable, codebase-grounded decisions. Only\nstop for missing secrets, credentials, or external services that genuinely cannot\nbe mocked or run locally - and when you do, say exactly what you need and why.\n\n═══ DISCOVER FIRST (never assume) ═══\nBefore writing anything, investigate this specific app with your tools. Determine,\nfrom the actual source, every one of:\n • language, package manager, and how to install/build/typecheck/lint/test\n • backend framework and how routes/handlers are declared\n • the auth system (sessions, JWT, cookies, a third-party provider) and how a\n request is authenticated end to end\n • the data layer (ORM/query builder/raw SQL), the models, and the REAL creation\n path for each model (services, repositories, invariants, required relations,\n enum values, defaults, side effects)\n • how the app is started and served locally, AND how to connect to its database\n to inspect rows (you will query the DB directly to verify each factory)\nDo not pattern-match on file names or directory layouts. Read the code. The right\nconventions are whatever THIS repo already uses - mirror them.\n\n═══ GET THE APP RUNNING LOCALLY ═══\nYou need the app running to validate your integration. Bring it up locally the way\nthe repo documents: install dependencies, start whatever backing services it needs\n(a database, a gateway, etc.), and start the server. Read the repo's own\nREADME/scripts to learn how - do not assume. Note the URL your SDK endpoint answers\non; you pass it to the validation commands below.\n\n═══ PREREQUISITES - STOP IF MISSING ═══\nAutonoma generates END-TO-END tests that drive a real USER INTERFACE backed by its\nAPIs. This only works when BOTH a frontend/UI to exercise AND every backend service\nthat UI depends on are present and runnable. Before any integration work, confirm\nboth are here. If the UI is absent, or a backend the UI needs cannot be run locally,\nSTOP immediately and say EXACTLY what is missing and why you can't proceed.\n\n═══ OBJECTIVE ═══\n0. Read the planner's artifacts (knowledge base, entity audit, scenarios) in the\n output directory above. They are your spec for what entities and scenarios must\n exist. The planner is done; do not re-run it, and do NOT delete or modify anything\n already in that directory - you only ADD your recipe.json and the completion marker.\n1. Install the Autonoma SDK and the backend adapter for THIS repo's language. The SDK\n is published for many languages under different package names and registries (npm,\n PyPI, Go modules, RubyGems, ...), so DISCOVER the correct package + adapter for this\n stack from the SDK docs (https://docs.autonoma.app/sdk) - do NOT assume the\n JavaScript/npm package.\n2. Implement ONE endpoint (prefer \"${DEFAULT_ENDPOINT_PATH}\" unless the repo has a\n clearly better convention) that handles the discover / up / down protocol through\n the SDK handler. The signing secret AUTONOMA_SHARED_SECRET is ALREADY provisioned\n in the app's environment - verify the x-signature HMAC against that env value (the\n SDK reads it for you). Do NOT hardcode a secret or overwrite the env value.\n3. Implement a real factory for EVERY entity the entity audit says needs one:\n • CREATE THROUGH THE APP'S OWN CODE, NOT RAW DB WRITES. The entity audit names a\n creation_function (and its side_effects) for each entity - call THAT function\n (inject or instantiate the service the app itself uses) so its real business\n logic and side effects actually run. A raw insert silently skips validation,\n hashing, derived fields, relation/permission wiring - exactly what this\n integration exists to avoid. The audit has no line numbers, so VERIFY each named\n creation_function actually exists in its creation_file; if the entry is stale,\n DISCOVER the real creation path yourself before wiring the factory. Fall back to\n a raw write ONLY when the real creation function genuinely cannot run locally.\n Even then, TRY it first and fall back only on an ACTUAL failure. When you fall\n back, say so for that entity and note which side_effects you reproduced by hand.\n • Some models have NO reusable creation function - the app writes them with an\n inline data-layer insert inside a request handler. For these, COPY that insert\n into your factory (open the named creation_file, replicate the exact insert, and\n DROP the handler's request/auth/external-service side effects), then give it a\n scoped-delete teardown. NEVER satisfy such a factory by calling the handler over\n HTTP. (Trace one level in first: if the handler delegates to a reusable function,\n call that instead; only copy the insert when the write is genuinely inlined.)\n • preserve invariants, relations, enums, defaults, and side effects\n • support recipe references (an _alias to name a created row, an _ref to point at\n another alias); create parents before children\n • return created refs in the shape the SDK expects\n4. Implement teardown. PREFER deleting by the scoping root: if the app scopes data by\n a tenant (an organization / workspace / account - most do), tear down by deleting\n that scope and letting cascades remove everything under it. This is simpler AND it\n also removes rows a test created that were never in \"up\" (e.g. an invoice created\n mid-test), which per-record teardown would leak. Only when there is no such scope,\n fall back to deleting each created record in reverse dependency order. Either way,\n be idempotent where practical, and NEVER delete non-test data - scope strictly by\n the seeded tenant / the test run / a unique marker.\n5. Implement the auth callback so the test runner gets REAL, usable credentials for\n the seeded user (valid cookies / a valid Authorization header / real login\n credentials) - never a placeholder token.\n6. Leave a maintenance note so the integration stays in sync as the schema evolves.\n Find the repo's agent-instructions file (AGENTS.md or CLAUDE.md; check the app\n directory and repo root, or create AGENTS.md at the repo root). Append a short\n \"Autonoma test data\" section that (a) explains in 2-3 sentences what Autonoma is\n and that it seeds realistic test data through this endpoint's factories via the\n app's own creation paths, and (b) instructs the reader to add/update the matching\n factory whenever they add or change models or the code that creates them. Keep it\n brief and match the file's tone; don't duplicate an equivalent existing note.\n\n═══ YOU GENERATE THE RECIPE ═══\nThere is no pre-written recipe. YOU build it at:\n ${params.recipePath}\nIt is a JSON file of the form:\n {\n \"version\": 1,\n \"source\": { \"discoverPath\": \"discover.json\", \"scenariosPath\": \"scenarios.md\" },\n \"validationMode\": \"endpoint-lifecycle\",\n \"recipes\": [\n { \"name\": \"standard\", \"description\": \"<short>\",\n \"create\": { \"<EntityName>\": [ { \"_alias\": \"x_1\", ...fields }, ... ] },\n \"validation\": { \"status\": \"validated\", \"method\": \"endpoint-up-down\" } }\n ]\n }\nThe \"create\" object maps each entity name to an array of records. Records use _alias\n(to name a created row) and _ref (to point at a parent's alias). Populate it from\nscenarios.md so the data realizes those scenarios. Build it up entity by entity as\nyou go (see the loop below) and keep the envelope intact.\n\n═══ TRACK YOUR WORK - DO NOT STOP UNTIL IT IS COMPLETE ═══\nBefore implementing, write a checklist file inside the app (e.g. IMPLEMENTATION.md)\nand keep it updated. It must enumerate, as explicit checkboxes: EVERY entity the\nentity audit says needs a factory (by name, copied from the audit), plus the\nendpoint, teardown, the auth callback, the maintenance note, and the full-recipe\npass. Check items off only when actually done and verified. The single most common\nfailure is stopping with entities left uncovered.\n\n═══ VALIDATE - ENTITY BY ENTITY, THEN THE WHOLE RECIPE ═══\nYou validate your own work by driving the endpoint through THIS CLI's signed client\nand inspecting the database. The CLI signs every request with the canonical secret\nfrom the environment, so you never construct signatures yourself. The commands:\n • ${params.cliCommand} sdk discover --url <endpoint-url>\n • ${params.cliCommand} sdk up --url <endpoint-url> --recipe <file> [--timeout <seconds>]\n (prints JSON; the response body includes a \"refsToken\")\n • ${params.cliCommand} sdk down --url <endpoint-url> --refs-token <token-from-up>\nThe --recipe file may be your full recipe.json or a slice containing just the\nentities under test. Each request times out after 120s by default; a cold\nfull-recipe up (first compile + many real-service inserts) can exceed that, so\npass --timeout <seconds> to raise it rather than falling back to smaller slices.\n\nWork through the entities in dependency order (parents before children). For EACH\nentity:\n 1. Implement or fix that entity's factory.\n 2. Add/fix that entity's records in the recipe (with its required parents present -\n the single-entity dependency chain; an Order needs its Customer).\n 3. Write a slice file with just this entity (and its parents) and run:\n ${params.cliCommand} sdk up --url <url> --recipe <slice>\n 4. Query the DATABASE directly and confirm the expected rows were created (right\n table, right values, relations wired) - not just that up returned 200.\n 5. Run: ${params.cliCommand} sdk down --url <url> --refs-token <token-from-up>\n 6. Query the DATABASE again and confirm those rows are GONE.\n 7. If any check failed, fix the right thing - the FACTORY CODE or the RECIPE DATA,\n whichever the failure points to - and repeat from step 3. Loop until green.\n\nOnce every entity passes independently, run the FULL recipe as one pass:\n • ${params.cliCommand} sdk up --url <url> --recipe ${params.recipePath} -> succeeds\n • confirm all rows created (DB), then down with the refsToken -> succeeds, rows gone (DB)\n • confirm a WRONG signature is rejected (the SDK does this for you - do not disable it)\n • confirm the up response's auth payload contains real credentials, not a placeholder\n\n═══ FINISH - THE LAST THING YOU DO ═══\nOnly after every entity and the full-recipe pass are green, and ${params.recipePath}\nholds the recipe you validated, write the completion marker so the CLI knows the\nsession is done and can upload the recipe:\n ${join(params.outputDir, COMPLETION_MARKER_FILE)}\nIts contents MUST be exactly:\n { \"complete\": true }\nDo NOT write this marker while any checklist item is unfinished. It is how control\nreturns to the CLI - it is not optional. The planner watches for this marker and\ntakes the terminal back shortly after it appears. After writing it, end with ONE\nshort closing message telling the developer:\n \"The integration is done. The Autonoma planner takes this terminal back in a\n few seconds to continue the setup - or exit now to continue immediately.\"\nNothing after that message - no further questions, summaries, or work.`;\n}\n\n/** Render the integration prompt to its durable file and return the file path. */\nexport async function writeIntegrationPrompt(params: IntegrationPromptParams): Promise<string> {\n const path = join(params.outputDir, INTEGRATION_PROMPT_FILE);\n await writeFile(path, renderIntegrationPrompt(params), \"utf-8\");\n return path;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { PermissionMode } from \"./launcher\";\n\nexport type EntityStatus = \"pending\" | \"recipe-accepted\" | \"tested-up\" | \"tested-down\" | \"skipped\";\n\nexport interface EntityProgress {\n entityName: string;\n status: EntityStatus;\n recipeData?: Record<string, unknown>[];\n errorLog: string[];\n}\n\n/**\n * Step-04 is a small state machine, each phase persisted so `--resume` continues\n * mid-flow. `tech-detect` seeds the entity order; the local agent implements the\n * integration, generates the recipe, and validates it entirely itself (`handoff`);\n * the CLI confirms the agent reported done (`completion`) and uploads the recipe\n * (`submit`). Interactive and `--non-interactive` runs take the same path - the\n * latter just drives the agent headlessly.\n */\nexport type RecipePhase = \"tech-detect\" | \"handoff\" | \"completion\" | \"submit\" | \"done\";\n\nexport interface RecipeBuilderState {\n phase: RecipePhase;\n entityOrder: string[];\n entities: Record<string, EntityProgress>;\n sharedSecret?: string;\n /** Which agent launcher the developer chose (e.g. \"claude\"); persisted so a\n * `--resume` reuses it without re-detecting/re-prompting. */\n agentId?: string;\n /** The Claude permission mode the developer chose; persisted for `--resume`. */\n permissionMode?: PermissionMode;\n /** How many times the interactive agent has been launched for this handoff.\n * Bounds the re-launch to finish an incomplete session. */\n launchAttempts?: number;\n /** Why a prior session didn't complete, carried into the re-launch so the agent\n * resumes at the first unfinished item instead of redoing finished work. */\n priorFailure?: string;\n /** Path to the recipe the agent generates and validates against, then submitted. */\n recipePath?: string;\n}\n\nconst STATE_FILE = \".recipe-builder-state.json\";\n\nexport function initialRecipeState(): RecipeBuilderState {\n return {\n phase: \"tech-detect\",\n entityOrder: [],\n entities: {},\n };\n}\n\nexport async function loadRecipeState(outputDir: string): Promise<RecipeBuilderState | undefined> {\n try {\n const raw = await readFile(join(outputDir, STATE_FILE), \"utf-8\");\n const parsed: RecipeBuilderState = JSON.parse(raw);\n return parsed;\n } catch {\n return undefined;\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 { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { debugLog } from \"../../../core/debug\";\nimport { suspend, resume } from \"../../../core/interrupt\";\nimport { notify } from \"../../../core/notify\";\nimport * as p from \"../../../ui/prompts\";\nimport { COMPLETION_MARKER_FILE, readCompletion } from \"../completion\";\nimport { INTEGRATION_PROMPT_FILE, writeIntegrationPrompt } from \"../integration-prompt\";\nimport type { AgentLauncher, PermissionMode } from \"../launcher\";\nimport { DEFAULT_PERMISSION_MODE, selectLauncher, selectPermissionMode } from \"../launcher\";\nimport { loadRecipe, RECIPE_FILE } from \"../recipe\";\nimport type { RecipeBuilderState } from \"../state\";\nimport { saveRecipeState } from \"../state\";\n\n/** Total interactive launches allowed: the first, plus one re-launch to finish. */\nexport const MAX_LAUNCH_ATTEMPTS = 2;\n\n/** Breathing room before the terminal switches to the coding agent. */\nconst HANDOFF_COUNTDOWN_SECONDS = 10;\n\nexport interface HandoffDeps {\n /** Launchers to detect/select over. Injected in tests; built from the repo in prod. */\n launchers: AgentLauncher[];\n /** Preset agent id from `--agent`. */\n presetAgentId?: string;\n /** Preset permission mode from `--permission-mode`. */\n presetPermissionMode?: PermissionMode;\n /** How the agent invokes the CLI's endpoint tool: `<cliCommand> sdk up|down|discover`. */\n cliCommand: string;\n /** Interactive run: prompt + attach the agent to the TTY. Otherwise run headless,\n * autonomous, no prompts, and hard-error (not manual-fallback) when no agent exists. */\n interactive: boolean;\n}\n\n/** What a phase run tells the orchestrator to do next. */\nexport type PhaseOutcome =\n | { kind: \"advance\" }\n | { kind: \"pause\"; summary: string }\n | { kind: \"handback\"; summary: string };\n\n/**\n * Hand the whole integration to the developer's own coding agent (e.g. Claude Code).\n * Interactive: ask to launch (Enter = go), pick an autonomy level, and attach it to\n * the terminal. Headless (--non-interactive): run it autonomously with no prompts and\n * hard-error when no agent is available (no manual fallback without a TTY).\n * Interactively, a missing agent or a decline drops to printing the instructions to\n * run by hand.\n */\nexport async function runHandoffPhase(\n state: RecipeBuilderState,\n deps: HandoffDeps,\n outputDir: string,\n): Promise<PhaseOutcome> {\n const recipePath = state.recipePath ?? join(outputDir, RECIPE_FILE);\n state.recipePath = recipePath;\n\n const launcher = await selectLauncher(deps.launchers, state.agentId ?? deps.presetAgentId, deps.interactive);\n if (launcher == null) {\n // Non-interactive requires an agent - there is no manual fallback without a TTY.\n if (!deps.interactive) {\n return {\n kind: \"handback\",\n summary:\n \"--non-interactive SDK implementation requires an installed, supported coding agent, but none was resolved on your PATH (name one with --agent if more than one is present). Install one, or run interactively.\",\n };\n }\n return manualFallback(outputDir, recipePath, deps.cliCommand, \"No supported agent found on your PATH.\");\n }\n\n if (deps.interactive) {\n const proceed = await p.confirm({\n message: `Implement the SDK integration now with your local ${launcher.label}?`,\n initialValue: true, // Enter = launch\n });\n if (p.isCancel(proceed)) throw new Error(\"Handoff cancelled\");\n if (!proceed) {\n return manualFallback(outputDir, recipePath, deps.cliCommand, `You chose not to launch ${launcher.label}.`);\n }\n }\n\n const permissionMode = deps.interactive\n ? await selectPermissionMode(state.permissionMode ?? deps.presetPermissionMode)\n : (state.permissionMode ?? deps.presetPermissionMode ?? DEFAULT_PERMISSION_MODE);\n state.agentId = launcher.id;\n state.permissionMode = permissionMode;\n await saveRecipeState(outputDir, state);\n\n await launchAgent(launcher, permissionMode, {\n outputDir,\n recipePath,\n cliCommand: deps.cliCommand,\n interactive: deps.interactive,\n });\n state.launchAttempts = (state.launchAttempts ?? 0) + 1;\n await saveRecipeState(outputDir, state);\n\n // launchAgent awaited the coding agent's exit, so control is back here; the\n // completion phase (next) decides success from the marker + recipe, not the exit code.\n return { kind: \"advance\" };\n}\n\n/**\n * CLI-side orchestration - the coding agent is a separate, already-exited process and\n * never runs this code. Confirm it finished and left a recipe to submit: the agent\n * owns all validation (per entity: up -> DB -> down -> DB), so \"done\" here is just the\n * completion marker it wrote plus a present recipe.json.\n *\n * The loop is the CLI's bounded re-launch. On the AUTOMATED path (an agent ran) an\n * incomplete session re-launches the agent ONCE, then re-checks. On the MANUAL path\n * (interactive, no agent ran) we ask the developer whether they've implemented it.\n * Either way an unresolved case hands control back with a clear explanation.\n */\nexport async function runCompletionPhase(\n state: RecipeBuilderState,\n deps: HandoffDeps,\n outputDir: string,\n): Promise<PhaseOutcome> {\n const recipePath = state.recipePath ?? join(outputDir, RECIPE_FILE);\n const automated = (state.launchAttempts ?? 0) >= 1;\n\n while (true) {\n const complete = await readCompletion(outputDir);\n const recipeReady = (await loadRecipe(outputDir)) != null;\n\n if (complete && recipeReady) {\n p.log.success(\"The agent reported the integration complete and validated.\");\n return { kind: \"advance\" };\n }\n\n const failure = !recipeReady\n ? \"No completed recipe.json was produced, so there is nothing validated to submit.\"\n : \"The agent exited without marking the integration complete (see its IMPLEMENTATION.md for what's left).\";\n\n if (automated) {\n const launcher = await launcherFor(state, deps);\n if (launcher != null && (state.launchAttempts ?? 0) < MAX_LAUNCH_ATTEMPTS) {\n p.log.warn(\"The integration isn't complete yet. Re-launching the agent once to finish it...\");\n state.priorFailure = failure;\n await saveRecipeState(outputDir, state);\n\n await launchAgent(launcher, state.permissionMode ?? \"bypassPermissions\", {\n outputDir,\n recipePath,\n cliCommand: deps.cliCommand,\n interactive: deps.interactive,\n priorFailure: failure,\n });\n state.launchAttempts = (state.launchAttempts ?? 0) + 1;\n await saveRecipeState(outputDir, state);\n continue;\n }\n return { kind: \"handback\", summary: handbackSummary(failure, outputDir) };\n }\n\n // Manual path is interactive-only; a non-interactive run can't ask, so it hands back.\n if (!deps.interactive) return { kind: \"handback\", summary: handbackSummary(failure, outputDir) };\n\n // No agent ran. If the developer's assistant wrote the marker we would have\n // advanced above; otherwise ask whether they've finished.\n const done = await p.confirm({\n message: \"Have you implemented the integration and is the recipe complete?\",\n initialValue: true,\n });\n if (p.isCancel(done)) throw new Error(\"Completion check cancelled\");\n if (done && recipeReady) return { kind: \"advance\" };\n if (done && !recipeReady) {\n p.log.warn(\n `I couldn't find a completed ${RECIPE_FILE} in ${outputDir}. Make sure it's written before you resume.`,\n );\n }\n return { kind: \"pause\", summary: \"Resume when the integration is implemented and the recipe is written.\" };\n }\n}\n\nfunction handbackSummary(failure: string, outputDir: string): string {\n return (\n `${failure}\\n\\n` +\n `Finish the integration (see the prompt at ${join(outputDir, INTEGRATION_PROMPT_FILE)}), ` +\n `then re-run with --resume.`\n );\n}\n\ninterface LaunchTarget {\n outputDir: string;\n recipePath: string;\n cliCommand: string;\n interactive: boolean;\n priorFailure?: string;\n}\n\n/** Render the prompt file and run the agent with the terminal handed over to it. */\nasync function launchAgent(\n launcher: AgentLauncher,\n permissionMode: PermissionMode,\n target: LaunchTarget,\n): Promise<void> {\n const promptFile = await writeIntegrationPrompt({\n outputDir: target.outputDir,\n recipePath: target.recipePath,\n cliCommand: target.cliCommand,\n priorFailure: target.priorFailure,\n });\n\n // A stale marker from an earlier session would make the completion watcher\n // reclaim the terminal seconds after launch - the agent must write it fresh.\n await rm(join(target.outputDir, COMPLETION_MARKER_FILE), { force: true }).catch((err) => {\n debugLog(\"Could not clear a stale completion marker\", { err });\n });\n\n p.log.info(`Launching ${launcher.label}. It will implement the integration - watch and steer it as it works.`);\n notify(\"Autonoma\", \"Handing off to your local agent\");\n\n if (target.interactive) {\n await p.countdown({\n title: `Handing off to ${launcher.label}`,\n lines: [\n `Your terminal is about to switch to ${launcher.label}. It will implement the ` +\n `Autonoma SDK integration inside your repo: install the SDK, wire the endpoint, ` +\n `and write a real factory for every entity in the audit, validating each one ` +\n `against your locally running app.`,\n `This dashboard disappears while it works - that's expected. Watch and steer it ` +\n `like any ${launcher.label} session; this usually takes a while.`,\n `When it finishes and exits, you come straight back here and the planner continues ` +\n `where it left off: submitting the validated recipe, then generating your test suite.`,\n ],\n seconds: HANDOFF_COUNTDOWN_SECONDS,\n });\n }\n\n // Hand the terminal (SIGINT + raw mode) to the agent, then take it back.\n suspend();\n try {\n const exitCode = await launcher.launch(promptFile, permissionMode, target.interactive);\n p.log.info(`${launcher.label} exited (code ${exitCode ?? \"unknown\"}). Back to the planner.`);\n } finally {\n resume();\n }\n}\n\n/** Rebuild the chosen launcher from persisted state, without re-prompting. */\nasync function launcherFor(state: RecipeBuilderState, deps: HandoffDeps): Promise<AgentLauncher | undefined> {\n const id = state.agentId;\n if (id == null) return undefined;\n const match = deps.launchers.find((l) => l.id === id);\n if (match == null) return undefined;\n return (await match.isAvailable()) ? match : undefined;\n}\n\n/**\n * Manual fallback: no automated run. Point the developer at the rendered prompt so\n * they can implement it in whatever assistant they have, then pause so a later\n * `--resume` confirms completion and continues to test generation.\n */\nasync function manualFallback(\n outputDir: string,\n recipePath: string,\n cliCommand: string,\n why: string,\n): Promise<PhaseOutcome> {\n const promptFile = await writeIntegrationPrompt({ outputDir, recipePath, cliCommand });\n p.note(\n `${why}\\n\\n` +\n `The full integration instructions have been written to:\\n ${promptFile}\\n\\n` +\n `Implement them with your AI assistant (or by hand), get your app running locally, then\\n` +\n `re-run with --resume. The CLI will continue to test generation.`,\n \"Implement the integration yourself\",\n );\n return { kind: \"pause\", summary: \"Integration handed off for manual implementation - resume when it's ready.\" };\n}\n","import { randomBytes } from \"node:crypto\";\nimport type { AppConfig } from \"../../config\";\nimport type { AgentResult } from \"../../core/agent\";\nimport type { ProjectContext } from \"../../core/context\";\nimport { readEnv } from \"../../env\";\nimport * as p from \"../../ui/prompts\";\nimport { parseEntityAudit, resolveEntityOrder } from \"./entity-order\";\nimport { buildAllLaunchers, type AgentLauncher, type PermissionMode } from \"./launcher\";\nimport { runCompletionPhase, runHandoffPhase, type HandoffDeps, type PhaseOutcome } from \"./phases/handoff\";\nimport { runSubmit } from \"./phases/submit\";\nimport { initialRecipeState, loadRecipeState, saveRecipeState } from \"./state\";\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. Step-04 has its own recovery, so\n * this is accepted but currently unused. */\n retryGuidance?: string;\n /** Preset agent id from the `--agent` flag. */\n agent?: string;\n /** Preset permission mode from the `--permission-mode` flag. */\n permissionMode?: PermissionMode;\n /** Test seam: inject the AgentLauncher(s) instead of building the real Claude one. */\n launchers?: AgentLauncher[];\n /** Override how the agent invokes this CLI's `sdk` tool (defaults to this process). */\n cliCommand?: string;\n}\n\nfunction generateSharedSecret(): string {\n return randomBytes(32).toString(\"hex\");\n}\n\n/** Turn a phase outcome into the AgentResult the pipeline expects, or undefined to continue. */\nfunction outcomeToResult(outcome: PhaseOutcome): AgentResult | undefined {\n if (outcome.kind === \"advance\") return undefined;\n if (outcome.kind === \"pause\") {\n return { success: false, paused: true, artifacts: [], summary: outcome.summary };\n }\n return { success: false, artifacts: [], summary: outcome.summary };\n}\n\nexport async function runRecipeBuilder(input: RecipeBuilderInput): Promise<AgentResult> {\n const { outputDir } = input;\n\n const state = (await loadRecipeState(outputDir)) ?? initialRecipeState();\n\n // Canonical shared secret: the app's onboarding secret when present, else a\n // CLI-generated one persisted for the run. It flows CLI -> agent -> app via env\n // inheritance, so the app and the agent's signed `sdk` calls use the same value.\n if (state.sharedSecret == null) {\n state.sharedSecret = input.config.sharedSecret ?? generateSharedSecret();\n await saveRecipeState(outputDir, state);\n }\n\n const models = await parseEntityAudit(outputDir);\n\n // Phase 1: resolve a dependency order + seed state. The agent discovers the stack\n // and generates the recipe itself, so this needs no LLM.\n if (state.phase === \"tech-detect\") {\n state.entityOrder = resolveEntityOrder(models);\n state.entities = {};\n for (const name of state.entityOrder) {\n state.entities[name] = { entityName: name, status: \"pending\", errorLog: [] };\n }\n state.phase = \"handoff\";\n await saveRecipeState(outputDir, state);\n p.log.info(`Found ${state.entityOrder.length} entities needing factories.`);\n }\n\n const handoffDeps = buildHandoffDeps(input, state.sharedSecret);\n\n // Phase 2: Hand off to the developer's local agent - interactive (attached to the\n // TTY) or, under --non-interactive, headless and autonomous.\n if (state.phase === \"handoff\") {\n const outcome = await runHandoffPhase(state, handoffDeps, outputDir);\n // Completion is always next: on advance we fall through to it in the same run;\n // on a manual fallback we pause here and a later --resume enters completion.\n state.phase = \"completion\";\n await saveRecipeState(outputDir, state);\n const result = outcomeToResult(outcome);\n if (result != null) return result;\n }\n\n // Phase 3: Confirm the agent reported done (with a bounded re-launch to finish).\n if (state.phase === \"completion\") {\n const outcome = await runCompletionPhase(state, handoffDeps, outputDir);\n if (outcome.kind !== \"advance\") {\n const result = outcomeToResult(outcome);\n if (result != null) return result;\n }\n state.phase = \"submit\";\n await saveRecipeState(outputDir, state);\n }\n\n // Phase 4: Submit the agent-validated recipe.\n if (state.phase === \"submit\") {\n const env = readEnv();\n const { recipePath, uploaded } = await runSubmit(\n outputDir,\n env.AUTONOMA_API_URL,\n env.AUTONOMA_API_TOKEN,\n env.AUTONOMA_GENERATION_ID,\n );\n\n const uploadCredentialsPresent =\n env.AUTONOMA_API_URL != null && env.AUTONOMA_API_TOKEN != null && env.AUTONOMA_GENERATION_ID != null;\n if (uploadCredentialsPresent && !uploaded) {\n return {\n success: false,\n artifacts: [recipePath],\n summary: `Recipe was generated but not accepted by Autonoma. The recipe JSON was printed above - re-upload with \\`npx @autonoma-ai/planner@latest upload\\` (or run again with --resume).`,\n };\n }\n\n state.phase = \"done\";\n await saveRecipeState(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 { success: true, artifacts: [], summary: \"Recipe builder already complete.\" };\n}\n\n/**\n * Assemble the handoff dependencies. The canonical shared secret is placed in the\n * env the agent (and the app it boots, and the `sdk` commands it runs) inherit, and\n * `cliCommand` is how the agent invokes this CLI's endpoint tool.\n */\nfunction buildHandoffDeps(input: RecipeBuilderInput, sharedSecret: string): HandoffDeps {\n const agentEnv: NodeJS.ProcessEnv = { ...process.env, AUTONOMA_SHARED_SECRET: sharedSecret };\n const launchers = input.launchers ?? buildAllLaunchers({ cwd: input.projectRoot, env: agentEnv });\n const cliCommand = input.cliCommand ?? `${process.execPath} ${process.argv[1] ?? \"\"}`;\n\n return {\n launchers,\n presetAgentId: input.agent,\n presetPermissionMode: input.permissionMode,\n cliCommand,\n interactive: !input.nonInteractive,\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// z.object() returns a schema typed by its exact shape; ReviewRubric.resultSchema\n// wants the general object-schema type. Funnelling each rubric's shape through\n// this typed parameter widens it without a per-rubric type assertion.\nfunction reviewResultSchema(shape: z.ZodRawShape): z.ZodObject<z.ZodRawShape> {\n return z.object(shape);\n}\n\n// The structured review payload: one DimensionResult per rubric dimension. Used\n// to validate (and type) the finish-tool input the review agent submits.\nexport const reviewResultRecordSchema = z.record(z.string(), 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: reviewResultSchema({\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 }),\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: reviewResultSchema({\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 }),\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: reviewResultSchema({\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 }),\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: reviewResultSchema({\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 }),\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 { reviewResultRecordSchema, type ReviewRubric, type 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> | undefined> {\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 // input already satisfied rubric.resultSchema upstream; re-parsing through\n // the concrete record schema recovers the precise type without an assertion.\n result = reviewResultRecordSchema.parse(input);\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 =\n 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 ?? undefined;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative, basename } from \"node:path\";\nimport { type LanguageModel } from \"ai\";\nimport { glob } from \"glob\";\nimport { createStepLogger } from \"../../core/display\";\nimport { runReviewPass } from \"./review-pass\";\nimport { ALL_RUBRICS, type DimensionResult } from \"./rubrics\";\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(\n ` [review] ${rubric.name} error on ${basename(testPath)}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return undefined;\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 {\n /* scenarios not available */\n }\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(\n test.content,\n test.relativePath,\n projectRoot,\n model,\n scenarioData,\n );\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\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { type AgentResult, buildDefaultStepLogger, runAgent } from \"../../core/agent\";\nimport { getModel } from \"../../core/model\";\nimport { buildCodebaseTools } from \"../../tools\";\n\nconst FEATURES_FILE = \"features.json\";\n\nconst Feature = z.object({\n name: z\n .string()\n .min(1)\n .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\n .number()\n .int()\n .min(0)\n .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(\n ` - [${f.type}] ${f.name} (${f.interactiveElements} elements, ${f.sourceFiles.length} files)`,\n );\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> | undefined> {\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 undefined;\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 { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { reportSubProgress } from \"../../core/progress\";\n\n/** Prior tests-per-node until the run has enough real data to measure its own. */\nconst TESTS_PER_NODE_PRIOR = 3;\n/** Processed nodes needed before trusting the run's own tests/node ratio. */\nconst LIVE_RATE_MIN_PROCESSED = 3;\n\n/**\n * Estimate the final test count. The total isn't known upfront - each node's\n * test count is only decided as its source is read - so project from the run's\n * own tests/node ratio once a few nodes are done, a prior before that. Never\n * below what's already written.\n */\nexport function estimateExpectedTests(written: number, processed: number, totalNodes: number): number {\n if (totalNodes <= 0) return written;\n const rate = written > 0 && processed >= LIVE_RATE_MIN_PROCESSED ? written / processed : TESTS_PER_NODE_PRIOR;\n return Math.max(written, Math.round(rate * totalNodes));\n}\n\nexport interface FeatureNode {\n id: string;\n name: string;\n routePath?: string;\n sourceFiles: string[];\n parentId?: string;\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;\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;\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 this.reportProgress();\n return true;\n }\n\n nextNode(): { node: FeatureNode; remaining: number } | undefined {\n if (this.currentNode) {\n const current = this.nodes.get(this.currentNode);\n if (current && current.status !== \"tested\") {\n current.status = \"skipped\";\n this.reportProgress();\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\") continue;\n\n node.status = \"exploring\";\n this.currentNode = id;\n return { node, remaining: this.queue.length };\n }\n\n this.currentNode = undefined;\n return undefined;\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 = undefined;\n const existing = this.testsWritten.get(nodeId) ?? [];\n this.testsWritten.set(nodeId, [...existing, ...testPaths]);\n this.reportProgress();\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 /** Processed nodes (tested or skipped) over the known graph size, plus a\n * live estimate of the final test count - which isn't known upfront (each\n * node's test count is decided as its source is read). */\n private reportProgress(): void {\n const stats = this.summary();\n const processed = stats.tested + stats.skipped;\n const expected = estimateExpectedTests(stats.totalTests, processed, stats.totalNodes);\n reportSubProgress(\"testGenerator\", processed, stats.totalNodes, \"nodes\", `~${expected} tests`);\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 ?? undefined;\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(outputDir: string, state: CoverageState): 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(outputDir: string): Promise<CoverageState | undefined> {\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 undefined;\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 the exact values from the scenario\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- Do NOT assert on values that are auto-generated or vary at runtime (like database IDs); assert on the stable scenario values instead\n- NEVER use \"Dynamic:\", \"{variableName}\", \"{{token}}\", 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 matter from \"gray-matter\";\n\nexport const VALID_VERBS = new Set([\"click\", \"type\", \"scroll\", \"assert\", \"hover\", \"drag\", \"read\", \"refresh\"]);\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(\n \"Missing or insufficient 'verification' field in frontmatter - must describe WHERE to navigate and WHAT to assert at the source of truth\",\n );\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 = 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 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 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 { AI_MAX_RETRIES } from \"../../core/model\";\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\n .string()\n .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\n .string()\n .min(\n 20,\n \"Verification must describe WHERE to navigate and WHAT to assert at the source of truth - not UI acknowledgments like toasts\",\n ),\n});\n\n/**\n * Test steps must use exact, concrete values from the scenario - no\n * placeholders, tokens, or examples. Scenario data is fully static (the planner\n * has no variable mechanism), so any `{{token}}`, bare `{variable}`, \"Dynamic:\",\n * or \"e.g.\" in the steps is a value the visual agent cannot resolve. Returns the\n * first offending placeholder found, or null when the steps are clean.\n */\nexport function findForbiddenPlaceholder(stepsSection: string): { name: string; match: string } | undefined {\n const placeholderPatterns = [\n { pattern: /Dynamic:\\s/gi, name: '\"Dynamic:\" placeholder' },\n { pattern: /\\{\\{[a-zA-Z0-9_]+\\}\\}/g, name: \"{{token}} 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 { name, match: matches[0] };\n }\n }\n\n return undefined;\n}\n\nexport function buildWriteTestTool(state: CoverageState, outputDir: string) {\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 {\n error: \"Test must include an **Intent**: section between Setup and Steps describing what behavior is being tested\",\n };\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 =\n 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:\n `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 placeholder = findForbiddenPlaceholder(stepsSection);\n if (placeholder) {\n return {\n error:\n `Test steps contain ${placeholder.name}: \"${placeholder.match}\". ` +\n `Use EXACT values from scenarios.md - not placeholders or examples.`,\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(model: LanguageModel, workingDirectory: string, onHeartbeat?: () => void) {\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 maxRetries: AI_MAX_RETRIES,\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) => {\n result = output;\n },\n }),\n },\n stopWhen: [stepCountIs(15), hasToolCall(\"finish\")],\n onStepFinish: () => {\n onHeartbeat?.();\n },\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> | undefined {\n try {\n const { data } = matter(content);\n return data && Object.keys(data).length > 0 ? data : undefined;\n } catch {\n return undefined;\n }\n}\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 { formatContext, type ProjectContext } from \"../../core/context\";\nimport { createStepLogger } from \"../../core/display\";\nimport { formatException } from \"../../core/errors\";\nimport { loadGitignorePatterns } from \"../../core/gitignore\";\nimport { getModel } from \"../../core/model\";\nimport { runConsolidatedReview, type TestReviewFeedback } from \"./review\";\n\nconst MAX_CONCURRENCY = 8;\nimport { glob } from \"glob\";\nimport { debugLog } from \"../../core/debug\";\nimport { buildBashTool, buildGlobTool, buildGrepTool, buildListDirectoryTool, buildReadFileTool } from \"../../tools\";\nimport { type DiscoveredFeature, loadFeatures, runFeatureDiscovery } from \"../00b-feature-discovery/index\";\nimport { CoverageState, type FeatureNode, loadBfsState } from \"./graph\";\nimport { SYSTEM_PROMPT } from \"./prompt\";\nimport {\n buildCreateFolderTool,\n buildGetProgressTool,\n buildNextNodeTool,\n buildSpawnResearcherTool,\n buildWriteTestTool,\n} from \"./tools\";\nimport { validateTestContent } from \"./validation\";\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: undefined,\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) ?? undefined;\n const parentNode = parentId ? state.nodes.get(parentId) : undefined;\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(input: TestGeneratorInput): 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: \"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(join(input.outputDir, \"AUTONOMA.md\"), \"utf-8\");\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(join(input.outputDir, \"scenarios.md\"), \"utf-8\");\n kbContext += `\\n## Scenarios\\n\\n${scenariosMd}\\n`;\n } catch {\n /* scenarios not available */\n }\n\n let features: Map<string, DiscoveredFeature> | undefined;\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 =\n (input.projectContext ? \"\\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(model, input.projectRoot, heartbeat),\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(` [chunk] Queue empty after ${totalSteps} steps. Finishing.`);\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(input.outputDir, model, input.projectRoot);\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(input.outputDir, input.projectRoot, model);\n\n console.log(` Review: ${reviewResult.passed} passed, ${reviewResult.failed} failed`);\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 {\n /* already gone */\n }\n }\n\n // Fix in parallel - each test gets its own focused prompt\n console.log(` Feeding ${reviewResult.feedback.length} tests back to planner for fixes`);\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 try {\n // `result` is already set by the generation phase, so the nudge loop is\n // skipped: the fix agent runs one pass and stops on finish instead of\n // being force-nudged MAX_NUDGES times after every clean pass.\n await runAgent({ ...agentConfig, maxSteps: 30 }, fixPrompt, () => result);\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(join(input.outputDir, \"qa-tests\", \"**/*.md\"));\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(` ${markedInvalid} tests still invalid after review cycles - moved to _invalid/`);\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 // Output review happens live in the TUI - the run no longer stops to ask.\n const reviewed = result;\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\n .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 })\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\nasync function generateIndex(outputDir: string, state: CoverageState): 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)) critCounts.set(critVal, (critCounts.get(critVal) ?? 0) + 1);\n const flowMatch = content.match(/flow:\\s*\"([^\"]+)\"/);\n const flowVal = flowMatch?.[1];\n if (flowVal) flowCounts.set(flowVal, (flowCounts.get(flowVal) ?? 0) + 1);\n const stepMatches = content.match(/^\\d+\\.\\s+(click|type|scroll|assert|hover|drag|read|refresh):/gm);\n if (stepMatches) totalSteps += stepMatches.length;\n const interactionMatches = content.match(/^\\d+\\.\\s+(click|type|drag):/gm);\n if (interactionMatches) totalInteractions += interactionMatches.length;\n } catch {\n /* file may not exist */\n }\n }\n }\n\n const avgSteps = 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()].flatMap(([_folder, tests]) => tests.map((t) => `- \\`${t}\\``)).join(\"\\n\")}\n`;\n\n await writeFile(join(outputDir, \"qa-tests\", \"INDEX.md\"), content, \"utf-8\");\n}\n\nasync function generateJourneyTests(outputDir: string, model: LanguageModel, projectRoot: string): 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 (err) {\n debugLog(\"AUTONOMA.md not present for journey generation\", { err });\n }\n try {\n scenariosMd = await readFile(join(outputDir, \"scenarios.md\"), \"utf-8\");\n } catch (err) {\n debugLog(\"scenarios.md not present for journey generation\", { err });\n }\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: undefined,\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 { open, readFile, stat } from \"node:fs/promises\";\nimport { debugLog } from \"../../core/debug\";\nimport type { ContentKind } from \"../types\";\nimport { kindOf } from \"./registry\";\n\n/** Above this, only the tail is read so the hero never blocks on a huge file. */\nconst LARGE_BYTES = 256 * 1024;\nconst TAIL_BYTES = 64 * 1024;\n\nexport interface LiveContent {\n text: string;\n kind: ContentKind;\n truncated: boolean;\n}\n\n/**\n * Refresh-from-disk for the hero panel. Reads the whole file, or just its tail\n * when it's large. Returns undefined if the file can't be read (e.g. deleted\n * between the watch event and the read).\n */\nexport async function readForLive(absPath: string): Promise<LiveContent | undefined> {\n try {\n const info = await stat(absPath);\n if (!info.isFile()) return undefined;\n const kind = kindOf(absPath);\n\n if (info.size <= LARGE_BYTES) {\n const text = await readFile(absPath, \"utf-8\");\n return { text, kind, truncated: false };\n }\n\n // Tail-read large files: open and read the last TAIL_BYTES.\n const fh = await open(absPath, \"r\");\n try {\n const start = Math.max(0, info.size - TAIL_BYTES);\n const buf = Buffer.alloc(info.size - start);\n await fh.read(buf, 0, buf.length, start);\n // Drop the partial first line so we start clean.\n const raw = buf.toString(\"utf-8\");\n const nl = raw.indexOf(\"\\n\");\n const text = nl >= 0 ? raw.slice(nl + 1) : raw;\n return { text, kind, truncated: true };\n } finally {\n await fh.close();\n }\n } catch (err) {\n debugLog(\"Hero panel could not read file\", { absPath, err });\n return undefined;\n }\n}\n","import { watch, type FSWatcher } from \"node:fs\";\nimport { debugLog } from \"../../core/debug\";\n\nconst DEBOUNCE_MS = 120;\n\n/**\n * Watch the output directory and report changed paths (relative to it),\n * debounced per path. This is the backstop that catches files written outside\n * the agent tool loop (savePages, recipe submit, INDEX.md). The primary trigger\n * is still the write_file/write_test events the store gets from onStepFinish.\n *\n * Falls back to a non-recursive watch where recursive isn't supported.\n */\nexport function watchOutputDir(outputDir: string, onChange: (relPath: string) => void): () => void {\n const watchers: FSWatcher[] = [];\n const timers = new Map<string, ReturnType<typeof setTimeout>>();\n\n const fire = (rel: string) => {\n const prev = timers.get(rel);\n if (prev) clearTimeout(prev);\n timers.set(\n rel,\n setTimeout(() => {\n timers.delete(rel);\n onChange(rel);\n }, DEBOUNCE_MS),\n );\n };\n\n const handler = (_event: string, filename: string | Buffer | null) => {\n if (filename == null) return;\n fire(typeof filename === \"string\" ? filename : filename.toString());\n };\n\n try {\n watchers.push(watch(outputDir, { recursive: true }, handler));\n } catch (err) {\n debugLog(\"Recursive fs.watch unavailable, falling back to flat watch\", { outputDir, err });\n try {\n watchers.push(watch(outputDir, handler));\n } catch (err2) {\n debugLog(\"No fs.watch available; write events alone drive the UI\", { outputDir, err: err2 });\n }\n }\n\n return () => {\n for (const w of watchers) {\n try {\n w.close();\n } catch (err) {\n debugLog(\"Failed to close fs watcher\", { outputDir, err });\n }\n }\n for (const t of timers.values()) clearTimeout(t);\n timers.clear();\n };\n}\n","import type { StyledLine } from \"../components/render-content\";\nimport { computeEta, formatClock, formatEtaLabel } from \"../eta\";\nimport type { Grid, Style } from \"../grid\";\nimport { theme } from \"../theme\";\nimport type { RunState } from \"../types\";\n\nconst BRAND = \"◆ autonoma\";\n\n/** Draw pre-styled spans (from renderContent) into the grid, truncated to maxW. */\nexport function drawSpans(g: Grid, x: number, y: number, spans: StyledLine, maxW: number): void {\n let cx = x;\n for (const s of spans) {\n for (const ch of s.text) {\n if (cx >= x + maxW) return;\n const st: Style = { color: s.dim ? theme.tertiary : s.color, bold: s.bold };\n g.set(cx, y, ch, st);\n cx++;\n }\n }\n}\n\n/** Top bar: brand + title, right metrics, subtitle, progress underline (rows 0-2). */\nexport function drawTopBar(g: Grid, state: RunState): void {\n const W = g.w;\n const eta = computeEta(state);\n const { meta } = state;\n const elapsed = formatClock(eta.elapsedMs);\n const outcome = state.finished ? (state.outcome?.kind ?? \"complete\") : undefined;\n const etaText = outcome === \"failed\" ? \"stopped\" : outcome === \"paused\" ? \"paused\" : formatEtaLabel(eta);\n const etaColor =\n outcome === \"failed\"\n ? theme.red\n : outcome === \"paused\"\n ? theme.amber\n : eta.complete\n ? theme.green\n : theme.accent;\n const pct = Math.round(eta.pct);\n\n g.text(0, 0, BRAND, { color: theme.accent, bold: true });\n g.text(BRAND.length + 1, 0, \"│\", { color: theme.cardEdge });\n g.text(BRAND.length + 3, 0, meta.title, { color: theme.text, bold: true });\n\n // right metrics, right-aligned\n const segs: { t: string; st: Style }[] = [\n { t: \"ELAPSED \", st: { color: theme.tertiary } },\n { t: elapsed, st: { color: theme.text, bold: true } },\n { t: \" ETA \", st: { color: theme.tertiary } },\n { t: etaText, st: { color: etaColor, bold: true } },\n { t: \" \", st: {} },\n { t: `${pct}%`, st: { color: theme.accent, bold: true } },\n ];\n const total = segs.reduce((n, s) => n + s.t.length, 0);\n let x = W - total;\n for (const s of segs) {\n g.text(x, 0, s.t, s.st);\n x += s.t.length;\n }\n\n // subtitle\n const sub = [meta.project, `planner v${meta.version}`].join(\" · \");\n g.text(0, 1, sub, { color: theme.tertiary });\n if (meta.stepNote != null) g.text(sub.length + 3, 1, meta.stepNote, { color: theme.amber });\n\n // progress underline\n const filled = Math.max(0, Math.min(W, Math.round((W * pct) / 100)));\n g.hline(0, 2, filled, \"━\", theme.accent);\n g.hline(filled, 2, W - filled, \"━\", theme.faint);\n}\n\n/** A full-width controls line at row y: left hints + right hints. */\nexport interface Hint {\n k: string;\n label: string;\n color?: string;\n}\n\nexport function drawHints(g: Grid, y: number, left: Hint[], right: Hint[]): void {\n let x = 0;\n for (let i = 0; i < left.length; i++) {\n if (i > 0) x += 3;\n const h = left[i]!;\n g.text(x, y, h.k, { color: h.color ?? theme.accent, bold: true });\n x += h.k.length;\n g.text(x, y, \" \" + h.label, { color: theme.secondary });\n x += h.label.length + 1;\n }\n // right group, right-aligned\n const rlen = right.reduce((n, h) => n + h.k.length + 1 + h.label.length, 0) + (right.length - 1) * 3;\n let rx = g.w - rlen;\n for (let i = 0; i < right.length; i++) {\n if (i > 0) rx += 3;\n const h = right[i]!;\n g.text(rx, y, h.k, { color: h.color ?? theme.accent, bold: true });\n rx += h.k.length;\n g.text(rx, y, \" \" + h.label, { color: theme.secondary });\n rx += h.label.length + 1;\n }\n}\n","/** Word-wrap plain `text` to `maxW`, greedy; words longer than the measure land on their own line. */\nexport function wrapPlain(text: string, maxW: number): string[] {\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let cur = \"\";\n for (const word of words) {\n if (cur !== \"\" && (cur + \" \" + word).length > maxW) {\n lines.push(cur);\n cur = word;\n } else {\n cur = cur === \"\" ? word : `${cur} ${word}`;\n }\n }\n if (cur !== \"\") lines.push(cur);\n return lines;\n}\n","import type { Grid } from \"../grid\";\nimport { theme } from \"../theme\";\nimport type { RunState } from \"../types\";\nimport { wrapPlain } from \"./wrap\";\n\nconst MODAL_MAX_W = 96;\nconst MODAL_FILL = \"#141414\";\n\n/**\n * The pre-handoff countdown: a centered modal explaining what is about to\n * happen to the terminal, with the seconds remaining until it happens. Enter\n * continues immediately; the store dismisses it automatically at zero.\n */\nexport function drawCountdownModal(g: Grid, state: RunState): void {\n const c = state.countdown;\n if (c == null) return;\n const W = g.w;\n const H = g.h;\n\n const w = Math.min(MODAL_MAX_W, W - 6);\n const innerW = w - 6;\n\n const titleLines = wrapPlain(c.title, innerW);\n const bodyLines = c.lines.flatMap((line, i) => {\n const wrapped = wrapPlain(line, innerW);\n return i === 0 ? wrapped : [\"\", ...wrapped];\n });\n\n const h = 2 + 1 + titleLines.length + 1 + bodyLines.length + 2 + 2;\n const x = Math.floor((W - w) / 2);\n const y = Math.max(2, Math.floor((H - h) / 2));\n\n // Blank the area, border it, and re-tint so the border sits on the fill.\n g.clearRect(x, y, w, h, MODAL_FILL);\n g.rect(x, y, w, h, { edge: theme.cardEdge, corner: theme.accent });\n for (let yy = y; yy < y + h; yy++) g.fillBg(x, yy, w, MODAL_FILL);\n const bg = MODAL_FILL;\n\n let cy = y + 1;\n g.text(x + 3, cy, \" UP NEXT \", { bg: theme.accent, color: theme.onAccent, bold: true });\n cy += 2;\n\n for (const line of titleLines) {\n g.text(x + 3, cy, line, { color: theme.text, bold: true, bg });\n cy++;\n }\n cy++;\n for (const line of bodyLines) {\n g.text(x + 3, cy, line, { color: theme.secondary, bg });\n cy++;\n }\n\n const remaining = Math.max(0, Math.ceil((c.endsAt - state.now) / 1000));\n const label = `Continuing in ${remaining}s`;\n const ly = y + h - 2;\n g.text(x + 3, ly, label, { color: theme.accent, bold: true, bg });\n g.text(x + 3 + label.length + 3, ly, \"enter\", { color: theme.accent, bold: true, bg });\n g.text(x + 3 + label.length + 3 + 6, ly, \"continue now\", { color: theme.secondary, bg });\n}\n","import type { Grid } from \"../grid\";\nimport { STEP_DOCS, STEP_INTROS, STEP_SUMMARIES, UI_STEP_LABELS } from \"../steps\";\nimport { theme } from \"../theme\";\nimport type { RunState } from \"../types\";\n\nconst MODAL_MAX_W = 78;\nconst MODAL_FILL = \"#141414\";\n/** How many recent warn/error lines the modal keeps reviewable. */\nconst RECENT_PROBLEMS = 4;\n\n/** Word-wrap `text` to `maxW`, greedy. */\nfunction wrap(text: string, maxW: number): string[] {\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let cur = \"\";\n for (const word of words) {\n if (cur !== \"\" && (cur + \" \" + word).length > maxW) {\n lines.push(cur);\n cur = word;\n } else {\n cur = cur === \"\" ? word : `${cur} ${word}`;\n }\n }\n if (cur !== \"\") lines.push(cur);\n return lines;\n}\n\n/**\n * The \"?\" modal: what the current step is doing and why, where to read more,\n * and the key reference. Drawn over the dashboard as the last layer.\n */\nexport function drawHelpModal(g: Grid, state: RunState): void {\n const W = g.w;\n const H = g.h;\n const w = Math.min(MODAL_MAX_W, W - 8);\n const innerW = w - 6;\n\n const step = state.currentStep;\n const intro = step != null ? STEP_INTROS[step] : \"The run has no active step right now.\";\n const introLines = wrap(intro, innerW);\n const docsUrl = step != null ? STEP_DOCS[step] : undefined;\n\n // Body: intro + optional docs + pipeline list + keys block.\n const pipelineLines = state.stepOrder.length;\n const keys: [string, string][] = [\n [\"←→ / h l\", \"switch between the file list and the document\"],\n [\"↑↓ / j k\", \"move the file cursor, or scroll the document\"],\n [\"enter / →\", \"open the selected file\"],\n [\"esc\", \"back to the file list\"],\n [\"f\", \"follow the newest file again\"],\n [\"g / G\", \"jump to top / bottom\"],\n [\"?\", \"toggle this help\"],\n [\"Ctrl+C twice\", \"exit - progress is saved, --resume continues\"],\n ];\n\n // Errors scroll out of the activity feed; keep the recent ones reviewable.\n const problems = state.log.filter((e) => e.level === \"error\" || e.level === \"warn\").slice(-RECENT_PROBLEMS);\n\n const h =\n 4 +\n introLines.length +\n (docsUrl != null ? 2 : 0) +\n 2 +\n pipelineLines +\n 2 +\n keys.length +\n (problems.length > 0 ? 2 + problems.length : 0) +\n 2;\n const x = Math.floor((W - w) / 2);\n const y = Math.max(1, Math.floor((H - h) / 2));\n\n // Blank the whole area first - the dashboard is still painted underneath -\n // then draw the border and re-tint every row so the border sits on the\n // modal fill instead of punching holes to the terminal background.\n g.clearRect(x, y, w, h, MODAL_FILL);\n g.rect(x, y, w, h, { edge: theme.cardEdge, corner: theme.accent });\n for (let yy = y; yy < y + h; yy++) g.fillBg(x, yy, w, MODAL_FILL);\n const bg = MODAL_FILL;\n\n let cy = y + 1;\n const title = step != null ? `What's happening - ${UI_STEP_LABELS[step]}` : \"What's happening\";\n g.text(x + 3, cy, title, { color: theme.accent, bold: true, bg });\n cy += 2;\n\n for (const line of introLines) {\n g.text(x + 3, cy, line, { color: theme.text, bg });\n cy++;\n }\n if (docsUrl != null) {\n cy++;\n g.text(x + 3, cy, `read more ${docsUrl}`, { color: theme.sky, bg });\n cy++;\n }\n\n cy++;\n g.text(x + 3, cy, \"THE PIPELINE\", { color: theme.tertiary, bg });\n cy++;\n state.stepOrder.forEach((name) => {\n const s = state.steps[name];\n const glyph = s.status === \"done\" ? \"✓\" : s.status === \"running\" ? \"◐\" : \"○\";\n const color = s.status === \"done\" || s.status === \"running\" ? theme.accent : theme.faint;\n g.text(x + 3, cy, glyph, { color, bg });\n g.text(x + 5, cy, UI_STEP_LABELS[name].padEnd(22), {\n color: s.status === \"pending\" ? theme.secondary : theme.text,\n bold: s.status === \"running\",\n bg,\n });\n g.text(x + 28, cy, STEP_SUMMARIES[name].slice(0, w - 31), { color: theme.tertiary, bg });\n cy++;\n });\n\n cy++;\n g.text(x + 3, cy, \"KEYS\", { color: theme.tertiary, bg });\n cy++;\n for (const [key, label] of keys) {\n g.text(x + 3, cy, key.padEnd(14), { color: theme.accent, bold: true, bg });\n g.text(x + 18, cy, label.slice(0, w - 21), { color: theme.secondary, bg });\n cy++;\n }\n\n if (problems.length > 0) {\n cy++;\n g.text(x + 3, cy, \"RECENT PROBLEMS\", { color: theme.tertiary, bg });\n cy++;\n for (const problem of problems) {\n const mark = problem.level === \"error\" ? \"✗\" : \"!\";\n const color = problem.level === \"error\" ? theme.red : theme.amber;\n g.text(x + 3, cy, mark, { color, bold: true, bg });\n g.text(x + 5, cy, problem.text.replace(/\\s+/g, \" \").slice(0, w - 8), { color: theme.secondary, bg });\n cy++;\n }\n }\n\n g.textRight(x + w - 3, y + h - 1, \" ? or esc to close \", { color: theme.tertiary });\n}\n","import type { Grid } from \"../grid\";\nimport { theme } from \"../theme\";\nimport type { PromptState, RunState } from \"../types\";\nimport { wrapPlain } from \"./wrap\";\n\nconst MODAL_MAX_W = 96;\nconst MODAL_FILL = \"#141414\";\n/** Visible option rows before the list windows around the highlight. */\nconst MAX_OPTION_ROWS = 8;\n\n/**\n * A blocking question as a big centered modal over the dashboard - impossible\n * to miss. The run does not move until it's answered; esc means \"go back\"\n * only where the flow allows it (request.cancelable).\n */\nexport function drawPromptModal(g: Grid, state: RunState): void {\n const W = g.w;\n const H = g.h;\n const prompt = state.prompt;\n const req = prompt.current;\n if (req == null) return;\n\n const w = Math.min(MODAL_MAX_W, W - 6);\n const innerW = w - 6;\n\n const messageLines = wrapPlain(req.message, innerW);\n const detailLines = req.detail != null ? wrapPlain(req.detail, innerW) : [];\n\n let bodyRows = 1;\n if (req.kind === \"select\" || req.kind === \"multiselect\") {\n bodyRows = Math.min(req.options.length, MAX_OPTION_ROWS);\n }\n\n const h = 2 + messageLines.length + detailLines.length + (detailLines.length > 0 ? 1 : 0) + 1 + bodyRows + 2 + 2;\n const x = Math.floor((W - w) / 2);\n const y = Math.max(2, Math.floor((H - h) / 2));\n\n // Blank the area, border it, and re-tint so the border sits on the fill.\n g.clearRect(x, y, w, h, MODAL_FILL);\n g.rect(x, y, w, h, { edge: theme.cardEdge, corner: theme.accent });\n for (let yy = y; yy < y + h; yy++) g.fillBg(x, yy, w, MODAL_FILL);\n const bg = MODAL_FILL;\n\n let cy = y + 1;\n g.text(x + 3, cy, \" ACTION REQUIRED \", { bg: theme.accent, color: theme.onAccent, bold: true });\n if (prompt.queued > 0) {\n g.textRight(x + w - 3, cy, `+${prompt.queued} more after this`, { color: theme.tertiary, bg });\n }\n cy += 2;\n\n for (const line of messageLines) {\n g.text(x + 3, cy, line, { color: theme.text, bold: true, bg });\n cy++;\n }\n for (const line of detailLines) {\n g.text(x + 3, cy, line, { color: theme.secondary, bg });\n cy++;\n }\n if (detailLines.length > 0) cy++;\n cy++;\n\n switch (req.kind) {\n case \"confirm\":\n drawConfirm(g, prompt, x + 3, cy, bg);\n break;\n case \"select\":\n case \"multiselect\":\n drawOptions(g, prompt, x, cy, w, bodyRows, bg);\n break;\n case \"text\":\n drawTextInput(g, prompt, x + 3, cy, innerW, bg);\n break;\n }\n cy += bodyRows + 1;\n\n const error = prompt.draft.error;\n if (error != null) {\n g.text(x + 3, y + h - 2, `! ${error}`, { color: theme.red, bold: true, bg });\n } else {\n drawKeysLine(g, state, x + 3, y + h - 2, bg);\n }\n}\n\nfunction drawKeysLine(g: Grid, state: RunState, x0: number, y: number, bg: string): void {\n const req = state.prompt.current;\n if (req == null) return;\n const parts: [string, string][] = [];\n if (req.kind === \"confirm\") parts.push([\"←→ / y n\", \"choose\"], [\"enter\", \"confirm\"]);\n if (req.kind === \"select\") parts.push([\"↑↓\", \"choose\"], [\"enter\", \"confirm\"]);\n if (req.kind === \"multiselect\") {\n parts.push([\"↑↓\", \"move\"], [\"space\", \"toggle on/off\"], [\"enter\", \"confirm selection\"]);\n }\n if (req.kind === \"text\") parts.push([\"type your answer\", \"\"], [\"enter\", \"submit\"]);\n if (req.cancelable === true) parts.push([\"esc\", \"go back\"]);\n\n let x = x0;\n for (const [k, label] of parts) {\n g.text(x, y, k, { color: theme.accent, bold: true, bg });\n x += k.length;\n if (label !== \"\") {\n g.text(x + 1, y, label, { color: theme.secondary, bg });\n x += label.length + 1;\n }\n x += 3;\n }\n}\n\nfunction drawConfirm(g: Grid, prompt: PromptState, x0: number, y: number, bg: string): void {\n const yes = prompt.draft.index === 0;\n const chip = (x: number, label: string, active: boolean): number => {\n const text = ` ${label} `;\n if (active) g.text(x, y, text, { bg: theme.accent, color: theme.onAccent, bold: true });\n else g.text(x, y, text, { color: theme.secondary, bg });\n return text.length;\n };\n let x = x0;\n x += chip(x, \"Yes\", yes) + 4;\n chip(x, \"No\", !yes);\n}\n\nfunction drawOptions(g: Grid, prompt: PromptState, x0: number, y: number, w: number, rows: number, bg: string): void {\n const req = prompt.current;\n if (req == null || (req.kind !== \"select\" && req.kind !== \"multiselect\")) return;\n const multi = req.kind === \"multiselect\";\n const options = req.options;\n\n // Window around the highlighted option.\n let start = 0;\n if (options.length > rows) {\n start = Math.max(0, Math.min(prompt.draft.index - Math.floor(rows / 2), options.length - rows));\n }\n\n for (let i = 0; i < rows; i++) {\n const idx = start + i;\n const option = options[idx];\n if (option == null) break;\n const active = idx === prompt.draft.index;\n const rowY = y + i;\n if (active) g.fillBg(x0 + 1, rowY, w - 2, theme.selectionBg);\n const rowBg = active ? theme.selectionBg : bg;\n if (active) g.set(x0 + 2, rowY, \"›\", { color: theme.accent, bold: true, bg: rowBg });\n let x = x0 + 4;\n if (multi) {\n const checked = prompt.draft.checked.includes(option.value);\n g.text(x, rowY, checked ? \"[x]\" : \"[ ]\", {\n color: checked ? theme.accent : theme.faint,\n bold: checked,\n bg: rowBg,\n });\n x += 4;\n }\n g.text(x, rowY, option.label, { color: active ? theme.text : theme.secondary, bold: active, bg: rowBg });\n x += option.label.length;\n if (option.hint != null) {\n g.text(x + 2, rowY, option.hint.slice(0, Math.max(0, x0 + w - 3 - (x + 2))), {\n color: theme.tertiary,\n bg: rowBg,\n });\n }\n }\n if (options.length > rows) {\n g.textRight(x0 + w - 3, y + rows - 1, `${prompt.draft.index + 1}/${options.length}`, {\n color: theme.tertiary,\n bg,\n });\n }\n}\n\nfunction drawTextInput(g: Grid, prompt: PromptState, x0: number, y: number, maxW: number, bg: string): void {\n const { text, cursor } = prompt.draft;\n const req = prompt.current;\n const placeholder = req?.kind === \"text\" ? (req.placeholder ?? \"\") : \"\";\n\n g.text(x0, y, \"> \", { color: theme.accent, bold: true, bg });\n const inputW = maxW - 3;\n if (text === \"\") {\n // Caret block first, dim placeholder after it - never under the caret.\n g.text(x0 + 2, y, \" \", { bg: theme.accent });\n g.text(x0 + 4, y, placeholder.slice(0, inputW - 2), { color: theme.faint, bg });\n return;\n }\n // Keep the caret visible on long input by sliding the window.\n const from = Math.max(0, cursor - inputW + 1);\n const visible = text.slice(from, from + inputW);\n g.text(x0 + 2, y, visible, { color: theme.text, bg });\n const caretX = x0 + 2 + (cursor - from);\n const under = text.slice(cursor, cursor + 1) || \" \";\n g.text(caretX, y, under, { bg: theme.accent, color: theme.onAccent });\n}\n","import { titleOf } from \"../artifacts/registry\";\nimport { renderContentWrapped } from \"../components/render-content\";\nimport { agentNow } from \"../eta\";\nimport type { Grid } from \"../grid\";\nimport { allArtifacts } from \"../nav\";\nimport { STEP_DOCS, STEP_INTROS, STEP_OUTPUTS } from \"../steps\";\nimport { theme } from \"../theme\";\nimport type { ActivityEntry, Artifact, RunState, StepNode } from \"../types\";\nimport { drawHints, drawSpans, drawTopBar, type Hint } from \"./chrome\";\nimport { drawCountdownModal } from \"./countdown\";\nimport { drawHelpModal } from \"./help\";\nimport { drawPromptModal } from \"./prompt\";\nimport { wrapPlain } from \"./wrap\";\n\n/**\n * Layout, top to bottom: top bar (rows 0-2), the horizontal pipeline strip\n * (status display only - not focusable), then two interactive panels side by\n * side (file list | document viewer), the ACTIVITY feed, and the controls bar.\n */\nconst STRIP_Y = 3;\nconst PANEL_TOP = 6;\nconst ACTIVITY_ROWS = 11;\nconst HINTS_ROWS = 2;\n\n/** File-list column: matches the old artifacts column's size. */\nconst FILES_MIN_W = 41;\nconst FILES_FRACTION = 0.27;\n\n/** Readable measure for centered empty-state copy. */\nconst EMPTY_BODY_MAX_W = 72;\n\n/** Longest status cell (\"● WRITING\"); reserves the gap between name and status. */\nconst STATUS_CELL_W = 11;\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n/** Both must be multiples of the store clock tick (100ms) so frames only ever\n * advance forward - a mismatched period makes a spinner crawl or run backwards. */\nconst SPINNER_STEP_MS = 250;\n/** The WRITING spinner in the FILES list - deliberately faster (5fps): it marks\n * the file being produced right now. */\nconst WRITING_SPINNER_MS = 200;\n\ninterface Geometry {\n /** x of the vertical divider between the file list and the viewer. */\n div: number;\n heroX: number;\n heroW: number;\n}\n\nfunction computeGeometry(w: number): Geometry {\n const div = Math.max(FILES_MIN_W, Math.round(w * FILES_FRACTION));\n const heroX = div + 2;\n return { div, heroX, heroW: w - heroX - 2 };\n}\n\nfunction activityRowsFor(h: number): number {\n return Math.max(4, Math.min(ACTIVITY_ROWS, h - HINTS_ROWS - PANEL_TOP - 10));\n}\n\n/**\n * How many document lines the viewer shows at a grid size. The nav reducer\n * needs this so unfollowing starts scrolling from the tail actually on screen.\n */\nexport function heroViewportRows(_width: number, height: number): number {\n const panelBottom = height - HINTS_ROWS - activityRowsFor(height);\n return Math.max(1, panelBottom - 1 - (PANEL_TOP + 2));\n}\n\n/** Hero text width at a grid width - the wrap measure the store needs for\n * exact scroll bounds. */\nexport function heroViewportCols(width: number): number {\n return computeGeometry(width).heroW;\n}\n\n/* ---------------------------------------------------------- pipeline strip -- */\n\n/** The strip's sub-progress label: \"28/41 nodes · ~120 tests\". */\nfunction subLabel(sub: StepNode[\"sub\"]): string | undefined {\n if (sub == null) return undefined;\n const base = `${sub.done}/${sub.total} ${sub.unit}`;\n return sub.note != null ? `${base} · ${sub.note}` : base;\n}\n\nfunction stepGlyph(step: StepNode, now: number): { ch: string; color: string } {\n if (step.status === \"done\") return { ch: \"✓\", color: theme.accent };\n if (step.status === \"running\") {\n const frame = SPINNER_FRAMES[Math.floor(now / SPINNER_STEP_MS) % SPINNER_FRAMES.length]!;\n return { ch: frame, color: theme.accent };\n }\n if (step.status === \"failed\") return { ch: \"✗\", color: theme.red };\n if (step.status === \"paused\") return { ch: \"‖\", color: theme.amber };\n return { ch: \"○\", color: theme.tertiary };\n}\n\n/**\n * The pipeline as one horizontal row of steps. Labels shrink (longest first)\n * until the strip fits the terminal width.\n */\nfunction drawPipelineStrip(g: Grid, state: RunState, y: number): void {\n const W = g.w;\n const GAP = 3;\n\n const items = state.stepOrder.map((name) => {\n const step = state.steps[name];\n return {\n step,\n label: step.label,\n // The unit matters: the tests step counts NODES (pages/features),\n // not tests - the test count per node is only decided as each one\n // is read, so a bare 28/41 would read as the wrong thing. An\n // optional note carries the estimated final count (~120 tests).\n sub: subLabel(step.sub),\n };\n });\n\n const itemWidth = (item: (typeof items)[number]) =>\n 2 + item.label.length + (item.sub != null ? item.sub.length + 1 : 0);\n const totalWidth = () => items.reduce((n, item) => n + itemWidth(item), 0) + GAP * (items.length - 1) + 2;\n\n while (totalWidth() > W) {\n const longest = items.reduce((a, b) => (a.label.length >= b.label.length ? a : b));\n if (longest.label.length <= 7) break;\n longest.label = longest.label.slice(0, longest.label.length - 2).trimEnd() + \"…\";\n }\n\n let x = 1;\n items.forEach((item, i) => {\n const active = item.step.status === \"running\";\n const w = itemWidth(item);\n if (active) g.fillBg(x - 1, y, w + 2, theme.activeBg);\n const bg = active ? theme.activeBg : undefined;\n const gl = stepGlyph(item.step, agentNow(state));\n g.text(x, y, gl.ch, { color: gl.color, bg });\n const labelColor = active\n ? theme.accent\n : item.step.status === \"pending\"\n ? theme.secondary\n : item.step.status === \"failed\"\n ? theme.red\n : theme.text;\n g.text(x + 2, y, item.label, { color: labelColor, bold: active, bg });\n if (item.sub != null) {\n g.text(x + 2 + item.label.length + 1, y, item.sub, {\n color: active ? theme.accent : theme.tertiary,\n bg,\n });\n }\n x += w + GAP;\n if (i < items.length - 1) g.text(x - 2, y, \"›\", { color: theme.faint });\n });\n\n g.hline(0, y + 1, W, \"─\", theme.borderChrome);\n}\n\n/* ---------------------------------------------------------------- file list -- */\n\nfunction artifactStatusCell(a: Artifact, now: number): { t: string; color: string } {\n switch (a.status) {\n case \"DONE\":\n return { t: \"DONE\", color: theme.tertiary };\n case \"WRITING\": {\n const frame = SPINNER_FRAMES[Math.floor(now / WRITING_SPINNER_MS) % SPINNER_FRAMES.length]!;\n return { t: `${frame} WRITING`, color: theme.sky };\n }\n default:\n return { t: \"PENDING\", color: theme.faint };\n }\n}\n\nfunction drawFiles(g: Grid, geo: Geometry, state: RunState, base: number, bottom: number): void {\n const list = allArtifacts(state);\n const focused = state.nav.focus === \"artifacts\";\n\n g.text(1, base - 2, \"FILES\", { color: focused ? theme.accent : theme.tertiary });\n // Just the count: files only enter this list once written, so any\n // done-of-total form here reads N of N forever. Real progress toward a\n // planned total lives in the pipeline strip's sub-progress.\n g.textRight(geo.div - 2, base - 2, `${list.length} ${list.length === 1 ? \"file\" : \"files\"}`, {\n color: theme.tertiary,\n });\n\n const maxRows = Math.max(1, Math.floor((bottom - base) / 3));\n\n // Keep the SELECTION in view. While following, the cursor rides the\n // newest write (which sits mid-list once tests sort alphabetically);\n // while browsing, it's wherever the user put it. Either way the list\n // never jumps away from the row that matters.\n const showCursor = focused || !state.live.following;\n let start = 0;\n const sel = state.nav.selectedArtifactIdx;\n if (sel < start) start = sel;\n else if (sel >= start + maxRows) start = sel - maxRows + 1;\n const visible = list.slice(start, start + maxRows);\n\n visible.forEach((a, i) => {\n const row = base + i * 3;\n const active = a.status === \"WRITING\";\n const selected = showCursor && start + i === state.nav.selectedArtifactIdx;\n // ONE background per row: the fill and every text span must use the\n // same value, or the row renders as mismatched patches behind the\n // text. Selection wins over the writing tint.\n const rowBg = selected ? theme.selectionBg : active ? theme.activeBg : undefined;\n if (rowBg != null) {\n for (let y = row - 1; y <= row + 1; y++) g.fillBg(0, y, geo.div, rowBg);\n }\n const bg = rowBg;\n if (selected) g.set(0, row, \"›\", { color: theme.accent, bold: true, bg });\n const icon = a.icon === \"json\" ? \"{}\" : \"▤\";\n g.text(2, row, icon, { color: theme.tertiary, bg });\n // Well-known files show their human title as the primary label with\n // the on-disk name demoted to the detail line; tests keep their\n // (already descriptive) file name up top.\n const label = a.title ?? a.name;\n const detail = a.title != null ? [a.name, a.description].filter((s) => s != null).join(\" · \") : a.description;\n const nameColor = active || a.status === \"DONE\" ? theme.text : theme.secondary;\n const nameMax = geo.div - 2 - STATUS_CELL_W - 2 - 5;\n const shown = label.length > nameMax ? label.slice(0, Math.max(1, nameMax - 1)) + \"…\" : label;\n g.text(5, row, shown, { color: nameColor, bold: active || selected, bg });\n const st = artifactStatusCell(a, agentNow(state));\n g.textRight(geo.div - 2, row, st.t, { color: st.color, bg });\n if (detail != null && detail !== \"\") {\n g.text(5, row + 1, detail.slice(0, geo.div - 6), {\n color: active || selected ? theme.secondary : theme.tertiary,\n bg,\n });\n }\n });\n}\n\n/* ------------------------------------------------------------------- viewer -- */\n\nfunction drawHeroHeader(g: Grid, geo: Geometry, state: RunState, y: number): void {\n const { live } = state;\n let x = geo.heroX;\n if (live.path == null) {\n g.text(x, y, \"▤ no document yet\", { color: theme.tertiary });\n return;\n }\n if (live.writingLive) {\n g.text(x, y, \"● \", { color: theme.accent });\n x += 2;\n }\n g.text(x, y, live.kind === \"json\" ? \"{} \" : \"▤ \", { color: theme.tertiary });\n x += 3;\n // Human title first; the on-disk name follows dim so the file stays findable.\n const title = live.path != null ? titleOf(live.path) : undefined;\n g.text(x, y, title ?? live.name ?? \"\", { color: theme.text, bold: true });\n x += (title ?? live.name ?? \"\").length;\n if (title != null && live.name != null) {\n g.text(x + 2, y, live.name, { color: theme.tertiary });\n x += live.name.length + 2;\n }\n if (live.writingLive) g.text(x + 3, y, \"● WRITING LIVE\", { color: theme.sky });\n else g.text(x + 3, y, \"✓ COMPLETE\", { color: theme.green });\n\n const kb = `${(live.text.length / 1024).toFixed(1)} KB`;\n const right = live.writingLive\n ? live.following\n ? { t: \"↓ FOLLOWING LATEST\", c: theme.accent }\n : { t: \"PAUSED · press f to follow\", c: theme.tertiary }\n : live.following\n ? { t: `scroll to read · ${kb}`, c: theme.tertiary }\n : { t: `pinned · f follows latest · ${kb}`, c: theme.sky };\n g.textRight(geo.heroX + geo.heroW - 1, y, right.t, { color: right.c });\n}\n\n/**\n * While a step runs but no document is showing, the viewer explains the step:\n * where we are in the pipeline, what is happening and why, what file it will\n * produce, and where to read more. Left-aligned in a centered block - this is\n * a paragraph, not a caption.\n */\nfunction drawHeroEmpty(g: Grid, geo: Geometry, state: RunState, y0: number, bottom: number): void {\n const name = state.currentStep;\n const step = name != null ? state.steps[name] : undefined;\n const blockW = Math.min(EMPTY_BODY_MAX_W, geo.heroW - 4);\n const x0 = geo.heroX + Math.max(1, Math.floor((geo.heroW - blockW) / 2));\n const clip = (t: string) => (t.length > blockW ? t.slice(0, blockW - 1) + \"…\" : t);\n\n if (name == null || step == null) {\n const y = Math.floor((y0 + bottom) / 2);\n g.text(x0, y, \"Starting up...\", { color: theme.secondary });\n return;\n }\n\n const stepIdx = state.stepOrder.indexOf(name);\n const introLines = wrapPlain(STEP_INTROS[name], blockW);\n const outputLines = wrapPlain(STEP_OUTPUTS[name], blockW - 11);\n const docsUrl = STEP_DOCS[name];\n\n const hasFiles = state.artifactOrder.length > 0;\n const blockH =\n 2 + 2 + introLines.length + 1 + outputLines.length + (docsUrl != null ? 1 : 0) + 2 + (hasFiles ? 1 : 0);\n let y = Math.max(y0, Math.floor((y0 + bottom - blockH) / 2));\n\n g.text(x0, y, `STEP ${stepIdx + 1} OF ${state.stepOrder.length}`, { color: theme.tertiary });\n y += 1;\n g.text(x0, y, clip(step.label), { color: theme.text, bold: true });\n y += 2;\n for (const line of introLines) {\n g.text(x0, y, line, { color: theme.secondary });\n y++;\n }\n y++;\n g.text(x0, y, \"Produces\", { color: theme.accent, bold: true });\n outputLines.forEach((line, i) => {\n g.text(x0 + 11, y + i, line, { color: theme.text });\n });\n y += outputLines.length;\n if (docsUrl != null) {\n g.text(x0, y, \"Read more\", { color: theme.accent, bold: true });\n g.text(x0 + 11, y, clip(docsUrl.replace(/^https?:\\/\\//, \"\")), { color: theme.sky });\n y++;\n }\n // The follow state, impossible to miss: either we're live-tailing (the\n // next write opens here) or a prominent hint says how to turn that on.\n y++;\n if (state.live.following) {\n g.text(x0, y, \"●\", { color: theme.accent });\n g.text(x0 + 2, y, clip(\"following - the newest file opens here as it's written\"), {\n color: theme.accent,\n bold: true,\n });\n } else {\n g.text(x0, y, \" f \", { bg: theme.accent, color: theme.onAccent, bold: true });\n g.text(x0 + 4, y, clip(\"follow the newest file as it's written\"), { color: theme.text, bold: true });\n }\n if (hasFiles) {\n y++;\n g.text(x0, y, clip(\"enter or → on a file in the list to read it here\"), { color: theme.tertiary });\n }\n}\n\nfunction drawHeroBody(g: Grid, geo: Geometry, state: RunState, y0: number, bottom: number): void {\n const { live } = state;\n if (live.path == null) {\n drawHeroEmpty(g, geo, state, y0, bottom);\n return;\n }\n const reserve = live.writingLive ? 1 : 0;\n const rows = Math.max(1, bottom - y0 - reserve);\n const lines = renderContentWrapped(live.text, live.kind, live.name, geo.heroW);\n const maxTop = Math.max(0, lines.length - rows);\n const top = live.following ? maxTop : Math.max(0, Math.min(state.nav.mainScrollTop, maxTop));\n const visible = lines.slice(top, top + rows);\n visible.forEach((spans, i) => drawSpans(g, geo.heroX, y0 + i, spans, geo.heroW));\n if (live.writingLive) {\n const cy = y0 + rows;\n g.text(geo.heroX, cy, \"▍ \", { color: theme.sky });\n const act = (state.activity || \"writing...\").slice(0, geo.heroW - 4);\n g.text(geo.heroX + 2, cy, act, { color: theme.secondary });\n g.set(geo.heroX + 2 + act.length + 1, cy, \"█\", { color: theme.accent });\n }\n}\n\n/* ----------------------------------------------------------------- activity -- */\n\nfunction callColor(call: string): string {\n if (call === \"read\") return theme.sky;\n if (call === \"glob\" || call === \"grep\" || call === \"search\") return theme.violet;\n if (call === \"write\" || call === \"test\") return theme.accent;\n if (call === \"bash\") return theme.orange;\n if (call === \"subagent\") return theme.violet;\n if (call === \"agent\") return theme.tertiary;\n if (call === \"done\" || call === \"success\") return theme.green;\n if (call === \"warn\" || call === \"checkpoint\") return theme.amber;\n if (call === \"error\") return theme.red;\n return theme.secondary;\n}\n\nfunction drawActivity(g: Grid, state: RunState, top: number, h: number): void {\n const W = g.w;\n g.hline(0, top, W, \"─\", theme.borderChrome);\n g.text(0, top + 1, \"● \", { color: theme.accent });\n g.text(2, top + 1, \"ACTIVITY\", { color: theme.tertiary });\n g.text(11, top + 1, \"live agent calls\", { color: theme.secondary });\n const stateLabel = state.finished\n ? \"idle\"\n : state.prompt.current != null\n ? \"waiting for you\"\n : state.currentStep != null\n ? \"streaming\"\n : \"waiting\";\n g.textRight(W - 1, top + 1, stateLabel, { color: theme.tertiary });\n\n const rows = Math.max(1, h - 2);\n const entries = state.activityFeed.slice(-rows);\n entries.forEach((e: ActivityEntry, i) => {\n const y = top + 2 + i;\n const newest = i === entries.length - 1 && !state.finished;\n if (newest) g.fillBg(0, y, W, theme.activeBg);\n const bg = newest ? theme.activeBg : undefined;\n g.text(0, y, e.time, { color: theme.tertiary, bg });\n g.text(10, y, e.call.slice(0, 11), { color: callColor(e.call), bold: true, bg });\n g.text(22, y, e.arg.slice(0, Math.max(0, W - 40)), { color: theme.text, bg });\n if (e.failed) g.textRight(W - 1, y, \"✗ failed\", { color: theme.red, bg });\n else if (e.metric != null) g.textRight(W - 1, y, e.metric, { color: theme.tertiary, bg });\n });\n}\n\n/* ---------------------------------------------------------------- dashboard -- */\n\nexport function drawDashboard(g: Grid, state: RunState): void {\n const W = g.w;\n const H = g.h;\n drawTopBar(g, state);\n const geo = computeGeometry(W);\n\n drawPipelineStrip(g, state, STRIP_Y + 1);\n\n const activityRows = activityRowsFor(H);\n const panelBottom = H - HINTS_ROWS - activityRows; // first row of the bottom region\n\n g.vline(geo.div, PANEL_TOP, panelBottom - PANEL_TOP, \"│\", theme.borderChrome);\n\n drawHeroHeader(g, geo, state, PANEL_TOP);\n g.hline(geo.heroX, PANEL_TOP + 1, geo.heroW, \"─\", theme.border);\n\n drawFiles(g, geo, state, PANEL_TOP + 2, panelBottom - 1);\n drawHeroBody(g, geo, state, PANEL_TOP + 2, panelBottom - 1);\n\n const promptActive = state.prompt.current != null;\n drawActivity(g, state, panelBottom, activityRows);\n\n // Ctrl+C routes to interruptPress in every mode (modal or not), so the\n // armed state must show everywhere - a press whose feedback never appears\n // reads as a dead key.\n const exitHint: Hint = state.ctrlCArmed\n ? { k: \"Ctrl+C\", label: \"again to exit (progress saved)\", color: theme.red }\n : { k: \"^C ^C\", label: \"exit\", color: theme.red };\n\n if (state.countdown != null) {\n drawHints(g, H - 1, [{ k: \"enter\", label: \"continue now\", color: theme.sky }], [exitHint]);\n drawCountdownModal(g, state);\n if (state.helpOpen) drawHelpModal(g, state);\n return;\n }\n if (promptActive) {\n // The modal carries its own key line; the nav hints would contradict it.\n drawHints(g, H - 1, [], [exitHint]);\n drawPromptModal(g, state);\n if (state.helpOpen) drawHelpModal(g, state);\n return;\n }\n drawHints(\n g,\n H - 2,\n [\n { k: \"↑↓ / j k\", label: \"scroll document\" },\n { k: \"f\", label: \"follow latest\" },\n { k: \"g / G\", label: \"top / bottom\" },\n ],\n [\n { k: \"?\", label: \"help\", color: theme.sky },\n { k: \"enter\", label: \"open selected\", color: theme.sky },\n ],\n );\n const focusHints: Hint[] = [{ k: \"←→ / h l\", label: \"files / document\", color: theme.sky }];\n if (state.nav.focus === \"main\") focusHints.push({ k: \"esc\", label: \"back to files\", color: theme.sky });\n drawHints(g, H - 1, focusHints, [exitHint]);\n\n if (state.helpOpen) drawHelpModal(g, state);\n}\n","import { useEffect, useState } from \"react\";\n\nconst FALLBACK_COLUMNS = 100;\nconst FALLBACK_ROWS = 32;\n\nexport interface TermSize {\n columns: number;\n rows: number;\n}\n\nfunction current(): TermSize {\n return {\n columns: process.stdout.columns || FALLBACK_COLUMNS,\n rows: process.stdout.rows || FALLBACK_ROWS,\n };\n}\n\n/** Reactive terminal dimensions; re-renders on resize. */\nexport function useTerminalSize(): TermSize {\n const [size, setSize] = useState<TermSize>(current);\n useEffect(() => {\n const onResize = () => setSize(current());\n process.stdout.on(\"resize\", onResize);\n return () => {\n process.stdout.off(\"resize\", onResize);\n };\n }, []);\n return size;\n}\n","import { theme } from \"./theme\";\n\nconst rgbCache = new Map<string, string>();\n\nfunction rgbOf(hex: string): string {\n const cached = rgbCache.get(hex);\n if (cached != null) return cached;\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n const rgb = `${r};${g};${b}`;\n rgbCache.set(hex, rgb);\n return rgb;\n}\n\nfunction fgCode(hex: string): string {\n return `38;2;${rgbOf(hex)}`;\n}\n\nfunction bgCode(hex: string): string {\n return `48;2;${rgbOf(hex)}`;\n}\n\nexport interface Cell {\n ch: string;\n color?: string;\n bg?: string;\n bold?: boolean;\n}\nexport interface Seg {\n text: string;\n color?: string;\n bg?: string;\n bold?: boolean;\n}\nexport interface Style {\n color?: string;\n bg?: string;\n bold?: boolean;\n}\n\n/**\n * A fixed character-cell framebuffer. Screens draw boxes, tables, highlights\n * and text at exact (x,y) coordinates, then `rows()` flattens into styled spans\n * for Ink. This is deterministic - every border edge, corner and column lines\n * up by construction - which Ink's flexbox + borderStyle could not deliver.\n */\nexport class Grid {\n readonly w: number;\n readonly h: number;\n cells: Cell[][];\n\n constructor(w: number, h: number) {\n this.w = w;\n this.h = h;\n this.cells = Array.from({ length: h }, () => Array.from({ length: w }, (): Cell => ({ ch: \" \" })));\n }\n\n set(x: number, y: number, ch: string, st: Style = {}): void {\n if (y < 0 || y >= this.h || x < 0 || x >= this.w) return;\n // A control char (\\n, \\t, ...) inside a cell breaks the emitted row\n // string and shifts every following terminal line - never store one.\n const safe = ch < \" \" ? \" \" : ch;\n this.cells[y]![x] = { ch: safe, color: st.color, bg: st.bg, bold: st.bold };\n }\n\n /** Draw a string starting at (x,y); truncates at the right edge. */\n text(x: number, y: number, s: string, st: Style = {}): void {\n for (let i = 0; i < s.length; i++) this.set(x + i, y, s[i]!, st);\n }\n\n /** Right-align a string ending at (xEnd, y) (xEnd inclusive). */\n textRight(xEnd: number, y: number, s: string, st: Style = {}): void {\n this.text(xEnd - s.length + 1, y, s, st);\n }\n\n hline(x: number, y: number, len: number, ch: string, color?: string): void {\n for (let i = 0; i < len; i++) this.set(x + i, y, ch, { color });\n }\n\n vline(x: number, y: number, len: number, ch: string, color?: string): void {\n for (let i = 0; i < len; i++) this.set(x, y + i, ch, { color });\n }\n\n /** Blank a rectangle: every cell becomes a space on `bg`. For overlays/modals. */\n clearRect(x: number, y: number, w: number, h: number, bg?: string): void {\n for (let yy = y; yy < y + h; yy++) {\n for (let xx = x; xx < x + w; xx++) this.set(xx, yy, \" \", { bg });\n }\n }\n\n /** Set a background colour across a span, preserving the chars already there. */\n fillBg(x: number, y: number, len: number, bg: string): void {\n const row = this.cells[y];\n if (row == null) return;\n for (let i = 0; i < len; i++) {\n const c = row[x + i];\n if (c) c.bg = bg;\n }\n }\n\n /**\n * A box with box-drawing borders. Corners use `corner` (lime by default),\n * edges use `edge` (gray). Optional `fill` paints the interior background.\n */\n rect(\n x: number,\n y: number,\n w: number,\n h: number,\n opts: { edge?: string; corner?: string; fill?: string } = {},\n ): void {\n const edge = opts.edge ?? theme.cardEdge;\n const corner = opts.corner ?? theme.accent;\n this.set(x, y, \"┌\", { color: corner });\n this.set(x + w - 1, y, \"┐\", { color: corner });\n this.set(x, y + h - 1, \"└\", { color: corner });\n this.set(x + w - 1, y + h - 1, \"┘\", { color: corner });\n this.hline(x + 1, y, w - 2, \"─\", edge);\n this.hline(x + 1, y + h - 1, w - 2, \"─\", edge);\n this.vline(x, y + 1, h - 2, \"│\", edge);\n this.vline(x + w - 1, y + 1, h - 2, \"│\", edge);\n if (opts.fill != null) for (let yy = y + 1; yy < y + h - 1; yy++) this.fillBg(x + 1, yy, w - 2, opts.fill);\n }\n\n /**\n * Flatten into per-row ANSI strings (24-bit color escapes). One string per\n * row keeps the Ink tree tiny - rendering thousands of nested <Text> spans\n * per frame is what makes large dashboards crawl.\n */\n ansiRows(): string[] {\n return this.rows().map((segs) => {\n let out = \"\";\n for (const s of segs) {\n const codes: string[] = [];\n if (s.bold) codes.push(\"1\");\n if (s.color != null) codes.push(fgCode(s.color));\n if (s.bg != null) codes.push(bgCode(s.bg));\n if (codes.length === 0) {\n out += s.text;\n } else {\n out += `\\x1b[${codes.join(\";\")}m${s.text}\\x1b[0m`;\n }\n }\n return out;\n });\n }\n\n /** Flatten into per-row spans, merging adjacent cells with identical style. */\n rows(): Seg[][] {\n const out: Seg[][] = [];\n for (let y = 0; y < this.h; y++) {\n const row = this.cells[y]!;\n const segs: Seg[] = [];\n let cur: Seg | undefined;\n for (let x = 0; x < this.w; x++) {\n const c = row[x]!;\n if (cur && cur.color === c.color && cur.bg === c.bg && cur.bold === !!c.bold) {\n cur.text += c.ch;\n } else {\n cur = { text: c.ch, color: c.color, bg: c.bg, bold: c.bold };\n segs.push(cur);\n }\n }\n out.push(segs);\n }\n return out;\n }\n}\n","import { Box, Text } from \"ink\";\nimport { drawDashboard } from \"../draw/dashboard\";\nimport { Grid } from \"../grid\";\nimport type { RunState } from \"../types\";\n\n/**\n * Paint the frame and emit it as one Text per row, all inline. The Grid must\n * NEVER be passed as a prop to a child component: React retains prop objects\n * per render, and a ~2MB grid retained at repaint rate leaks hundreds of\n * MB/min (measured - this exact shape OOMed real runs).\n */\nexport function Dashboard({ state, width, rows }: { state: RunState; width: number; rows: number }) {\n const g = new Grid(width, rows);\n drawDashboard(g, state);\n return (\n <Box flexDirection=\"column\" width={width} height={rows}>\n {g.ansiRows().map((row, y) => (\n <Text key={y}>{row}</Text>\n ))}\n </Box>\n );\n}\n","import { useInput, type Key } from \"ink\";\nimport { useEffect } from \"react\";\nimport { heroViewportCols, heroViewportRows } from \"./draw/dashboard\";\nimport { useTerminalSize, type TermSize } from \"./hooks/useTerminalSize\";\nimport type { NavAction } from \"./nav\";\nimport type { PromptAction } from \"./prompt\";\nimport { Dashboard } from \"./screens/Dashboard\";\nimport type { PromptRequest, RunState } from \"./types\";\n\n/** Everything a prompt needs from the outside: draft edits, submit, cancel. */\nexport interface PromptHandlers {\n onAction: (a: PromptAction) => void;\n onSubmit: () => void;\n onCancel: () => void;\n}\n\n/**\n * The presentational shell: terminal-size-aware, key handling, and the screen\n * switch. Pure projection of RunState - all state lives in the store.\n */\nexport function App({\n state,\n onNav,\n onHelp,\n prompt,\n onSkipCountdown,\n size,\n}: {\n state: RunState;\n onNav: (a: NavAction) => void;\n /** Show/hide the help modal; omitted in static renders. */\n onHelp?: (open: boolean) => void;\n /** Answering machinery for the docked prompt panel; omitted in static renders. */\n prompt?: PromptHandlers;\n /** Enter on the pre-handoff countdown: continue immediately. */\n onSkipCountdown?: () => void;\n size?: TermSize;\n}) {\n const measured = useTerminalSize();\n const { rows, columns } = size ?? measured;\n const gridRows = Math.max(10, rows - 1);\n\n // Tell the nav reducer how tall the viewer is, so unfollowing starts\n // scrolling from the tail position that's actually on screen.\n useEffect(() => {\n onNav({ type: \"setViewport\", rows: heroViewportRows(columns, gridRows), cols: heroViewportCols(columns) });\n }, [columns, gridRows, onNav]);\n\n useInput((input, key) => {\n // While help is open it swallows the keyboard: ? / esc / q close it.\n if (state.helpOpen) {\n if (input === \"?\" || key.escape || input === \"q\") onHelp?.(false);\n return;\n }\n\n // The pre-handoff countdown: enter continues immediately, nothing else.\n if (state.countdown != null) {\n if (key.return) onSkipCountdown?.();\n return;\n }\n\n // A blocking question owns the keyboard until answered.\n const activePrompt = state.prompt.current;\n if (activePrompt != null && prompt != null) {\n handlePromptKey(activePrompt, input, key, prompt);\n return;\n }\n\n if (input === \"?\") onHelp?.(true);\n else if (key.escape) {\n if (state.nav.focus === \"main\") onNav({ type: \"focusLeft\" });\n else onNav({ type: \"closeDocument\" });\n } else if (key.leftArrow || input === \"h\") onNav({ type: \"focusLeft\" });\n else if (key.rightArrow || input === \"l\") onNav({ type: \"focusRight\" });\n else if (key.upArrow || input === \"k\") onNav({ type: \"moveUp\" });\n else if (key.downArrow || input === \"j\") onNav({ type: \"moveDown\" });\n else if (key.return) onNav({ type: \"enter\" });\n else if (key.pageUp) onNav({ type: \"pageUp\" });\n else if (key.pageDown) onNav({ type: \"pageDown\" });\n else if (input === \"f\") onNav({ type: \"toggleFollow\" });\n else if (input === \"g\") onNav({ type: \"scrollTop\" });\n else if (input === \"G\") onNav({ type: \"scrollBottom\" });\n });\n\n // Leave one terminal row free: rendering exactly `rows` lines makes the\n // terminal scroll and the frame walks off-screen (inline rendering).\n return <Dashboard state={state} width={columns} rows={gridRows} />;\n}\n\nfunction handlePromptKey(req: PromptRequest, input: string, key: Key, handlers: PromptHandlers): void {\n if (key.escape) {\n handlers.onCancel();\n return;\n }\n if (key.return) {\n handlers.onSubmit();\n return;\n }\n\n if (req.kind === \"text\") {\n // Free typing: every printable character is input, never a hotkey.\n if (key.leftArrow) handlers.onAction({ type: \"left\" });\n else if (key.rightArrow) handlers.onAction({ type: \"right\" });\n else if (key.upArrow) handlers.onAction({ type: \"home\" });\n else if (key.downArrow) handlers.onAction({ type: \"end\" });\n else if (key.backspace) handlers.onAction({ type: \"backspace\" });\n else if (key.delete) handlers.onAction({ type: \"delete\" });\n else if (input !== \"\" && !key.ctrl && !key.meta) handlers.onAction({ type: \"input\", text: input });\n return;\n }\n\n if (req.kind === \"confirm\") {\n if (input === \"y\" || input === \"Y\") {\n handlers.onAction({ type: \"setIndex\", index: 0 });\n handlers.onSubmit();\n return;\n }\n if (input === \"n\" || input === \"N\") {\n handlers.onAction({ type: \"setIndex\", index: 1 });\n handlers.onSubmit();\n return;\n }\n }\n\n if (key.upArrow || input === \"k\" || key.leftArrow || input === \"h\") handlers.onAction({ type: \"up\" });\n else if (key.downArrow || input === \"j\" || key.rightArrow || input === \"l\") handlers.onAction({ type: \"down\" });\n else if (input === \" \") handlers.onAction({ type: \"toggle\" });\n}\n","import { useSyncExternalStore } from \"react\";\nimport type { RunStore } from \"../store\";\nimport type { RunState } from \"../types\";\n\n/** Subscribe an Ink component tree to the run store. */\nexport function useStore(store: RunStore): RunState {\n return useSyncExternalStore(store.subscribe, store.getState, store.getState);\n}\n","import { useInput } from \"ink\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { interruptPress } from \"../core/interrupt\";\nimport { App } from \"./App\";\nimport { useStore } from \"./hooks/useStore\";\nimport type { RunStore } from \"./store\";\n\n/**\n * Binds the live run store to the presentational <App> and owns Ctrl+C.\n *\n * Ink is mounted with exitOnCtrlC: false, so Ctrl+C arrives here as raw input.\n * Presses are fed to the shared interrupt policy (double-press to exit); the\n * arm state comes back into the store via setInterruptArmDisplay so the\n * controls bar can show \"again to exit\".\n */\nexport function Live({ store }: { store: RunStore }) {\n const state = useStore(store);\n\n useEffect(() => {\n store.startClock();\n return () => store.stopClock();\n }, [store]);\n\n useInput((input, key) => {\n if (key.ctrl && input === \"c\") interruptPress();\n });\n\n const onNav = useCallback((a: Parameters<RunStore[\"dispatchNav\"]>[0]) => store.dispatchNav(a), [store]);\n const onHelp = useCallback((open: boolean) => store.setHelpOpen(open), [store]);\n const onSkipCountdown = useCallback(() => store.skipCountdown(), [store]);\n const prompt = useMemo(\n () => ({\n onAction: (a: Parameters<RunStore[\"dispatchPrompt\"]>[0]) => store.dispatchPrompt(a),\n onSubmit: () => store.submitPrompt(),\n onCancel: () => store.cancelPrompt(),\n }),\n [store],\n );\n\n return <App state={state} onNav={onNav} onHelp={onHelp} prompt={prompt} onSkipCountdown={onSkipCountdown} />;\n}\n","import { render, type Instance } from \"ink\";\nimport { setInterruptArmDisplay } from \"../core/interrupt\";\nimport { registerUiLifecycle, registerUiTeardown } from \"../core/ui-lifecycle\";\nimport { readForLive } from \"./artifacts/reader\";\nimport { watchOutputDir } from \"./artifacts/watcher\";\nimport { Live } from \"./Live\";\nimport { createStore, setActiveStore, type RunStore } from \"./store\";\nimport type { MetaInfo } from \"./types\";\n\nexport interface MountOptions {\n outputDir: string;\n meta: MetaInfo;\n}\n\nexport interface MountedUi {\n store: RunStore;\n /** Tear everything down and restore plain terminal output. */\n unmount: () => void;\n}\n\ninterface ConsolePatch {\n restore: () => void;\n}\n\n/**\n * Route stray console.* from deep in the pipeline into the run log - direct\n * writes would scribble over the Ink frame.\n */\nfunction patchConsole(store: RunStore): ConsolePatch {\n const orig = { log: console.log, error: console.error, warn: console.warn };\n const toLog =\n (level: \"info\" | \"warn\" | \"error\") =>\n (...args: unknown[]) =>\n store.appendLog({ level, text: args.map((a) => String(a)).join(\" \") });\n console.log = toLog(\"info\");\n console.error = toLog(\"error\");\n console.warn = toLog(\"warn\");\n return {\n restore: () => {\n console.log = orig.log;\n console.error = orig.error;\n console.warn = orig.warn;\n },\n };\n}\n\n/**\n * Mount the interactive Ink dashboard. Only called on a TTY (the caller\n * decides); headless runs never touch this module, so every store consumer\n * falls back to plain output.\n *\n * Registers a pause/resume lifecycle so the coding-agent handoff can take\n * the terminal: pause unmounts the Ink frame and restores console patching;\n * resume re-renders against the same store.\n */\nexport function mountUi(opts: MountOptions): MountedUi {\n const store = createStore({ outputDir: opts.outputDir, meta: opts.meta, reader: readForLive });\n setActiveStore(store);\n\n const stopWatch = watchOutputDir(opts.outputDir, (rel) => store.handleFsChange(rel));\n\n let ink: Instance | undefined;\n let consolePatch: ConsolePatch | undefined;\n\n const show = () => {\n consolePatch = patchConsole(store);\n // The arm hint renders in the controls bar only while the frame is up; a\n // stale arm state from before a pause must not survive the remount.\n store.setCtrlCArmed(false);\n setInterruptArmDisplay((armed) => store.setCtrlCArmed(armed));\n // patchConsole: false - our own console capture (above) already routes\n // stray logs into the store; Ink's would print them above the frame.\n ink = render(<Live store={store} />, { exitOnCtrlC: false, patchConsole: false });\n };\n\n const hide = () => {\n // While the TUI is down (the coding-agent handoff), the\n // Ctrl+C arm hint must fall back to stderr - routing it into an unmounted\n // tree would swallow the \"press again to exit\" feedback entirely.\n setInterruptArmDisplay(undefined);\n consolePatch?.restore();\n consolePatch = undefined;\n // Always clear the frame: whatever takes the terminal next (the user's\n // coding agent, the exit hint, the final outro) starts\n // on a clean region instead of under a stale dashboard.\n ink?.clear();\n ink?.unmount();\n ink = undefined;\n };\n\n const unmount = () => {\n registerUiTeardown(undefined);\n registerUiLifecycle(undefined);\n setInterruptArmDisplay(undefined);\n stopWatch();\n store.stopClock();\n hide();\n setActiveStore(undefined);\n };\n\n show();\n registerUiLifecycle({ pause: hide, resume: show });\n // Fatal paths (uncaught errors about to print + exit) can kill the frame\n // without holding a reference to this mount.\n registerUiTeardown(unmount);\n\n return { store, unmount };\n}\n","// MUST be first: guards the Node version before ink/react (below) load.\nimport \"./core/ensure-node\";\n\n// Before react/ink load: without this the published CLI runs React's\n// development build - slower renders and far heavier memory retention.\nprocess.env.NODE_ENV ??= \"production\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { uploadRecipeFromDisk } from \"./agents/04-recipe-builder/phases/submit\";\nimport { runSdkCommand } from \"./agents/04-recipe-builder/sdk-command\";\nimport { loadConfig } from \"./config\";\nimport type { AgentResult } from \"./core/agent\";\nimport { track, trackError, flushAnalytics } from \"./core/analytics\";\nimport { BOLD, DIM, PRIMARY, RESET } from \"./core/colors\";\nimport { type ProjectContext, loadContext } from \"./core/context\";\nimport { formatException, describeKnownError, supportReference, isUserCancellation } from \"./core/errors\";\nimport { installInterruptHandler, installTerminationDiagnostics, restoreTerminal } from \"./core/interrupt\";\nimport { DEFAULT_MODEL } from \"./core/model\";\nimport { ensureOutputDir } from \"./core/output\";\nimport { teardownUi } from \"./core/ui-lifecycle\";\nimport { readEnv } from \"./env\";\nimport * as p from \"./ui/prompts\";\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 { loadGitInfo, readGitInfo, saveGitInfo } from \"./core/git\";\nimport { notify } from \"./core/notify\";\nimport {\n applySelection,\n defaultBackendsFor,\n formatBackendScope,\n formatFrontendScope,\n loadProjectMap,\n type ProjectMap,\n pickDefaultSelection,\n renderProjectMap,\n resolveSelection,\n saveProjectMap,\n type ScopeSelection,\n} from \"./core/project-map\";\nimport {\n initialState,\n loadState,\n markStep,\n nextPendingStep,\n saveState,\n STEP_ORDER,\n type StepName,\n type PipelineState,\n} from \"./core/state\";\nimport { uploadArtifacts } from \"./core/upload\";\nimport { CLI_VERSION } from \"./core/version\";\nimport { STEP_INTROS, STEP_SUMMARIES } from \"./ui/steps\";\nimport { getActiveStore, type RunStore } from \"./ui/store\";\n\nconst PAGES_FILE = \"pages.json\";\n\nasync function savePages(\n outputDir: string,\n pages: Map<string, { route: string; path: string; description: string }>,\n): 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(\n outputDir: string,\n): 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\n// Pull a flag's value only when it was given as `--key value` (a string), not\n// as a bare boolean flag or absent. Keeps callers from having to narrow the\n// `string | boolean | undefined` index type by hand.\nfunction strArg(args: Record<string, string | boolean>, key: string): string | undefined {\n const value = args[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nconst STEP_LABELS: Record<StepName, string> = {\n projectMapper: \"Map your project structure\",\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\nfunction isStepName(value: string): value is StepName {\n return value in STEP_LABELS;\n}\n\n// Step summaries and intros live in ui/steps.ts so the dashboard's help modal\n// shares the exact copy the prompts use.\n\n/**\n * Turn the mapper's candidate map into a single testable surface. Precedence:\n * (1) an explicit selection supplied by the caller (flags / harness) always wins;\n * (2) interactively, ask via a radio (frontend) + checkbox (backends) picker;\n * (3) non-interactively with no explicit choice, only proceed if unambiguous\n * (exactly one frontend), otherwise return undefined so the caller pauses.\n */\nasync function resolveScopeSelection(\n map: ProjectMap,\n config: ReturnType<typeof loadConfig>,\n nonInteractive?: boolean,\n): Promise<ScopeSelection | undefined> {\n if (config.frontend != null) {\n // Resolve tolerantly first: a fullstack app's own backend may be named at the\n // app root or a nested api dir depending on the run, so match the requested\n // path against what this map actually produced before defaulting the backends.\n const requestedFrontend = resolveSelection(map, { frontend: config.frontend, backends: [] }).frontend;\n // An explicit --backends is validated loudly by applySelection; a defaulted set\n // comes from the LLM's dependsOn, so drop entries that map to no real backend\n // instead of letting them reach applySelection and hard-fail the whole run.\n const backends = config.backends ?? defaultBackendsFor(map, requestedFrontend);\n return resolveSelection(map, { frontend: config.frontend, backends });\n }\n\n if (!nonInteractive) return promptScopeSelection(map);\n\n return pickDefaultSelection(map);\n}\n\n/**\n * Interactive radio (frontend) + checkbox (backends, pre-checked to the\n * frontend's dependencies). Esc on the backends question goes BACK to the\n * frontend pick; the flow can only move forward or back, never abort the run.\n */\nasync function promptScopeSelection(map: ProjectMap): Promise<ScopeSelection> {\n while (true) {\n const frontend = await p.select({\n message: \"Which frontend do you want to plan tests for?\",\n detail: \"One frontend per run - the whole test suite is planned against it.\",\n options: map.frontends.map((f) => ({ value: f.path, label: `${f.path} [${f.framework}]`, hint: f.why })),\n });\n if (p.isCancel(frontend)) continue;\n\n if (map.backends.length === 0) return { frontend, backends: [] };\n\n // Resolve dependsOn through the same tolerant matcher the non-interactive path uses, so a\n // dependency named by its data-layer schema path still pre-checks its owning backend option\n // (whose value is the backend's own path) instead of silently going un-checked.\n const needed = defaultBackendsFor(map, frontend);\n const backends = await p.multiselect({\n message: \"Which backends does this frontend talk to?\",\n detail:\n \"Pick EVERY backend and data layer it depends on - you can select several. \" +\n \"The ones the mapper detected are pre-checked.\",\n options: map.backends.map((b) => ({ value: b.path, label: `${b.path} [${b.framework}]`, hint: b.why })),\n initialValues: needed,\n required: false,\n cancelable: true,\n });\n if (p.isCancel(backends)) continue; // esc: back to the frontend pick\n\n return { frontend, backends };\n }\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 getActiveStore()?.startStep(step);\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 // Page count sizes the page-scaled ETA budgets (kb, test generation).\n const knownPages = projectContext?.pages?.length ?? 0;\n if (knownPages > 0) getActiveStore()?.setSizes({ pages: knownPages });\n\n // Size signals for the analytics event - the measured-duration data shows\n // repo size dominates step time, so future ETA heuristics need these.\n let stepMetrics: Record<string, number> = {};\n\n try {\n let result: AgentResult | undefined;\n\n switch (step) {\n case \"projectMapper\": {\n const { runProjectMapper } = await import(\"./agents/00-project-mapper/index\");\n const map = await runProjectMapper({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n nonInteractive,\n });\n if (map == null) {\n result = { success: false, artifacts: [], summary: \"Project mapper did not produce a map.\" };\n break;\n }\n if (map.frontends.length === 0) {\n result = {\n success: false,\n artifacts: [],\n summary: \"Project mapper found no frontend to test. Point --project at a codebase with a UI.\",\n };\n break;\n }\n\n // The mapper only DISCOVERS candidates. Narrow to the one frontend we test\n // (radio) plus the backends it needs (checkbox). When non-interactive and\n // ambiguous, persist the candidates and pause so the caller (Claude / CI)\n // can resume with --frontend/--backends.\n const selection = await resolveScopeSelection(map, config, nonInteractive);\n if (selection == null) {\n await saveProjectMap(outputDir, map);\n p.note(renderProjectMap(map), \"Project map - candidates (pick one frontend + its backends)\");\n result = {\n success: false,\n paused: true,\n artifacts: [],\n summary:\n `Found ${map.frontends.length} candidate frontends. Choose one and its backends, then ` +\n \"resume with --frontend <path> --backends <path,path>.\",\n };\n break;\n }\n\n const scoped = applySelection(map, selection);\n stepMetrics = {\n frontend_count: map.frontends.length,\n backend_count: map.backends.length,\n ignored_count: map.ignore.length,\n };\n await saveProjectMap(outputDir, scoped);\n p.note(renderProjectMap(scoped), \"Project map\");\n break;\n }\n case \"pagesFinder\": {\n const { runPageFinder } = await import(\"./agents/00-pages-finder/index\");\n const projectMap = await loadProjectMap(outputDir);\n const pages = await runPageFinder({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n nonInteractive,\n extraMessage: projectMap != null ? formatFrontendScope(projectMap) : undefined,\n });\n await savePages(outputDir, pages);\n stepMetrics = { page_count: pages.size };\n if (pages.size > 0) getActiveStore()?.setSizes({ pages: pages.size });\n break;\n }\n case \"kb\": {\n const { runKBGenerator } = await import(\"./agents/01-kb-generator/index\");\n stepMetrics = { page_count: projectContext?.pages?.length ?? 0 };\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 const auditMap = await loadProjectMap(outputDir);\n result = await runEntityAudit({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n projectContext,\n nonInteractive,\n retryGuidance,\n scopeHint: auditMap != null ? formatBackendScope(auditMap) : undefined,\n });\n break;\n }\n case \"scenarioRecipe\": {\n const { runScenarioRecipe } = await import(\"./agents/03-scenario-recipe/index\");\n const recipeMap = await loadProjectMap(outputDir);\n result = await runScenarioRecipe({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n retryGuidance,\n scopeHint: recipeMap != null ? formatBackendScope(recipeMap) : undefined,\n });\n break;\n }\n case \"recipeBuilder\": {\n const { runRecipeBuilder } = await import(\"./agents/04-recipe-builder/index\");\n const { parsePermissionMode } = await import(\"./agents/04-recipe-builder/launcher\");\n result = await runRecipeBuilder({\n projectRoot: config.projectRoot,\n outputDir,\n modelId: config.modelId,\n config,\n projectContext,\n nonInteractive,\n retryGuidance,\n agent: config.agent,\n permissionMode: parsePermissionMode(config.permissionMode),\n });\n break;\n }\n case \"testGenerator\": {\n const { runTestGenerator } = await import(\"./agents/05-test-generator/index\");\n const pages = await loadPages(outputDir);\n stepMetrics = { page_count: pages.size };\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 getActiveStore()?.endStep(step, state.steps[step]);\n\n if (step === \"entityAudit\") {\n const { parseEntityNames } = await import(\"./core/parse-entity-audit\");\n stepMetrics = { ...stepMetrics, entity_count: (await parseEntityNames(outputDir)).length };\n }\n if (step === \"testGenerator\") {\n const { readdir } = await import(\"node:fs/promises\");\n const entries = await readdir(join(outputDir, \"qa-tests\"), { recursive: true }).catch(() => []);\n stepMetrics = {\n ...stepMetrics,\n test_count: entries.map((e) => String(e)).filter((e) => e.endsWith(\".md\")).length,\n };\n }\n\n track(\"cli_step_completed\", {\n step,\n status: state.steps[step],\n duration_ms: Date.now() - stepStartedAt,\n ...stepMetrics,\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 while (true) {\n const action = await p.select({\n message: `${label} failed. What would you like to do?`,\n options: [\n { value: \"retry\", label: \"Retry this step\", hint: \"Run it again from the top\" },\n {\n value: \"guidance\",\n label: \"Retry with guidance\",\n hint: \"Tell the agent what went wrong or what to focus on\",\n },\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 cancelable: true,\n });\n if (p.isCancel(guidance)) continue; // esc: back to the retry choices\n\n const trimmed = guidance.trim();\n return { kind: \"retry\", guidance: trimmed || undefined };\n }\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 ? \"+\"\n : status === \"running\"\n ? \"~\"\n : status === \"paused\"\n ? \"‖\"\n : status === \"failed\"\n ? \"x\"\n : \" \";\n const label = isStepName(step) ? STEP_LABELS[step] : step;\n console.log(` [${icon}] ${label}: ${status}`);\n }\n}\n\ninterface MountedDashboard {\n store: RunStore;\n unmount: () => void;\n}\n\n/**\n * Mount the Ink dashboard - interactive TTY only. Mounted before the setup\n * questions so every prompt (resume, project context, scope selection, step\n * failure) renders as the docked ACTION REQUIRED panel; there is no separate\n * terminal-mode prompt path anymore.\n */\nasync function mountDashboard(outputDir: string, projectSlug: string): Promise<MountedDashboard | undefined> {\n const isTTY = !!process.stdout.isTTY && !!process.stdin.isTTY;\n if (!isTTY) return undefined;\n\n const { mountUi } = await import(\"./ui/mount\");\n return mountUi({\n outputDir,\n meta: { title: \"Generating your test suite\", project: projectSlug, version: CLI_VERSION },\n });\n}\n\n/**\n * Reflect an existing run's settled steps in the dashboard (resume). A stale\n * \"running\" from an interrupted session is skipped - that step will re-run,\n * and seeding it would show a spinner nothing is driving.\n */\nfunction seedDashboard(ui: MountedDashboard | undefined, state: PipelineState): void {\n if (ui == null) return;\n for (const [step, status] of Object.entries(state.steps)) {\n if (isStepName(step) && (status === \"done\" || status === \"failed\" || status === \"paused\")) {\n ui.store.endStep(step, status);\n }\n }\n}\n\nconst BANNER = `\n${PRIMARY}${BOLD} █████╗ ██╗ ██╗████████╗ ██████╗ ███╗ ██╗ ██████╗ ███╗ ███╗ █████╗\n██╔══██╗██║ ██║╚══██╔══╝██╔═══██╗████╗ ██║██╔═══██╗████╗ ████║██╔══██╗\n███████║██║ ██║ ██║ ██║ ██║██╔██╗ ██║██║ ██║██╔████╔██║███████║\n██╔══██║██║ ██║ ██║ ██║ ██║██║╚██╗██║██║ ██║██║╚██╔╝██║██╔══██║\n██║ ██║╚██████╔╝ ██║ ╚██████╔╝██║ ╚████║╚██████╔╝██║ ╚═╝ ██║██║ ██║\n╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n${RESET}\n${DIM} E2E Test Planner - Generate exhaustive test suites from your codebase${RESET}\n`;\n\n/**\n * Make sure the CLI is authenticated before doing anything else. The planner\n * runs on managed Autonoma credits via the Autonoma API token (AUTONOMA_API_TOKEN),\n * which the web app injects when it launches the CLI. There's no LLM key to\n * paste anymore - if the token is missing we error with instructions rather than\n * prompting. Returns false when unauthenticated.\n */\nfunction ensureAutonomaAuth(): boolean {\n if (readEnv().AUTONOMA_API_TOKEN?.trim()) return true;\n\n p.log.error(\n \"Not authenticated. Launch the planner from the Autonoma app, or set AUTONOMA_API_TOKEN (create a key at https://autonoma.app/settings/api-keys).\",\n );\n return false;\n}\n\nasync function main() {\n // Before anything else, arm diagnostics so a SIGTERM/SIGHUP or a swallowed async\n // error leaves a greppable breadcrumb instead of the run just vanishing.\n installTerminationDiagnostics();\n\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: strArg(args, \"project\"),\n slug: strArg(args, \"slug\"),\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 === \"upload\") {\n const config = loadConfig({\n project: strArg(args, \"project\"),\n slug: strArg(args, \"slug\"),\n });\n const outputDir = await ensureOutputDir(config.projectSlug);\n // Re-upload everything already generated in `~/.autonoma/<app>/`: the recipe\n // first (so scenarios exist before tests reference them), then the artifacts\n // (tests/kb/scenarios), which also marks the setup completed. Both endpoints\n // are idempotent, so this is safe to run repeatedly to recover a failed run.\n const recipeUploaded = await uploadRecipeFromDisk(outputDir, {\n apiUrl: config.autonomaApiUrl,\n apiToken: config.autonomaApiToken,\n generationId: config.autonomaGenerationId,\n });\n await uploadArtifacts(config, outputDir);\n await flushAnalytics();\n process.exit(recipeUploaded ? 0 : 1);\n }\n\n // `sdk <discover|up|down>` is the interactive agent's endpoint tool, not a\n // developer-facing command: it's non-interactive, prints JSON, and its exit code\n // signals HTTP success. It shells out from inside the handoff session.\n if (command === \"sdk\") {\n const exitCode = await runSdkCommand(process.argv.slice(3), {\n env: process.env,\n stdout: (text) => process.stdout.write(text),\n stderr: (text) => process.stderr.write(text),\n });\n process.exit(exitCode);\n }\n\n if (command === \"help\" || args.help) {\n console.log(\"Usage:\");\n console.log(\n \" test-planner [run] [--project <path>] [--frontend <path>] [--backends <path,path>] [--model <id>] [--step <name>] [--resume] [--non-interactive] [--agent <name>] [--permission-mode <default|acceptEdits|bypassPermissions>]\",\n );\n console.log(\" test-planner status [--project <path>]\");\n console.log(\" test-planner upload [--project <path>] # re-upload already-generated recipe + artifacts\");\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 = `autonoma-planner --resume` + (args.project ? ` --project ${args.project}` : \"\");\n let mountedUi: MountedDashboard | undefined;\n installInterruptHandler({\n // exitCode defaults to 0 for a user-initiated Ctrl+C (progress saved, a clean stop);\n // an external SIGTERM/SIGHUP passes the conventional 143/129 so the flushed exit still\n // carries the signal code a reaper/CI reads, not a 0 that looks like normal completion.\n onExit: (exitCode = 0) => {\n track(\"cli_run_exited\");\n mountedUi?.unmount();\n mountedUi = undefined;\n restoreTerminal();\n console.log(\"\");\n p.log.warn(`Your progress is saved. To resume, run:\\n ${resumeCommand}`);\n void flushAnalytics().finally(() => process.exit(exitCode));\n },\n });\n\n const backendsArg = strArg(args, \"backends\");\n const config = loadConfig({\n project: strArg(args, \"project\"),\n model: strArg(args, \"model\"),\n slug: strArg(args, \"slug\"),\n frontend: strArg(args, \"frontend\"),\n backends:\n backendsArg != null\n ? backendsArg\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n : undefined,\n agent: strArg(args, \"agent\"),\n permissionMode: strArg(args, \"permission-mode\"),\n });\n\n if (!ensureAutonomaAuth()) {\n return;\n }\n\n const nonInteractive = !!args[\"non-interactive\"];\n\n const modelName = config.modelId ?? readEnv().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 // Mount the dashboard BEFORE the setup questions: every prompt from here\n // on renders as the docked ACTION REQUIRED panel inside the TUI.\n if (!nonInteractive) mountedUi = await mountDashboard(outputDir, config.projectSlug);\n\n let isResuming = !!(args.resume || args.step);\n let projectContext: ProjectContext | undefined;\n\n const hasProgress = Object.values(state.steps).some((s) => s === \"done\" || s === \"running\");\n\n if (!isResuming && !nonInteractive && hasProgress) {\n const completedSteps = Object.entries(state.steps)\n .filter(([, s]) => s === \"done\")\n .map(([name]) => (isStepName(name) ? STEP_LABELS[name] : name))\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 mountedUi?.unmount();\n mountedUi = undefined;\n p.log.warn(\"Cancelled.\");\n return;\n }\n\n if (resume) {\n isResuming = true;\n } else {\n // Starting over: drop the old run's step marks, or the fresh run\n // inherits stale \"done\" states the moment it saves progress.\n state = initialState();\n await saveState(outputDir, state);\n }\n }\n\n if (isResuming) seedDashboard(mountedUi, state);\n\n // Project context is optional: the agents discover the codebase themselves.\n // A .project-context.json (from an older run, or hand-written to steer the\n // agents) is still honored when present.\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 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 const stepArg = strArg(args, \"step\");\n const targetStep: StepName | undefined = stepArg != null && isStepName(stepArg) ? stepArg : undefined;\n if (stepArg != null && targetStep == null) {\n mountedUi?.unmount();\n mountedUi = undefined;\n p.log.error(`Unknown --step \"${stepArg}\". Valid steps: ${Object.keys(STEP_LABELS).join(\", \")}`);\n return;\n }\n\n if (targetStep) {\n if (targetStep === \"testGenerator\" && state.steps.scenarioRecipe !== \"done\") {\n mountedUi?.unmount();\n mountedUi = undefined;\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 mountedUi?.unmount();\n mountedUi = undefined;\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) : \"projectMapper\";\n if (!startStep) {\n mountedUi?.unmount();\n mountedUi = undefined;\n p.log.success(\"All steps complete.\");\n return;\n }\n\n const steps = STEP_ORDER;\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(steps.map((s, idx) => `${idx + 1}. ${STEP_LABELS[s]} - ${STEP_SUMMARIES[s]}`).join(\"\\n\"), \"Here's the plan\");\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 } catch (err) {\n mountedUi?.unmount();\n mountedUi = undefined;\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 const anyFailed = Object.values(state.steps).some((s) => s === \"failed\");\n getActiveStore()?.finish({ kind: allStepsDone ? \"complete\" : anyFailed ? \"failed\" : \"paused\" });\n mountedUi?.unmount();\n mountedUi = undefined;\n\n // The dashboard frame is cleared on unmount; leave a durable plain-text\n // summary and the next step in the scrollback instead.\n if (allStepsDone) {\n p.log.success(\"Your test suite is ready.\");\n p.log.info(`Artifacts: ${outputDir}`);\n p.log.info(\"Next: connect a preview environment and run it -> https://autonoma.app\");\n }\n p.outro(\"Done\");\n}\n\nmain()\n .then(() => flushAnalytics())\n .catch(async (err) => {\n // The dashboard may still be up; kill it first so the console is real\n // again - otherwise the error prints into the dead frame's captured\n // log and the user sees nothing.\n teardownUi();\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","// Side-effect entry guard: verify the Node runtime before anything else loads.\n// This module is imported first in index.ts (ahead of ink/react) so the\n// version check runs before any dependency can touch `util.styleText`. ESM\n// evaluates imports in order and before the module body, so a bare\n// `ensureSupportedNode()` call in the entry body would still run AFTER their\n// import side-effects - defeating the fail-fast guarantee if a future dependency (or\n// other dep) ever touched `styleText` at import time.\nimport { ensureSupportedNode } from \"./node-version\";\n\nensureSupportedNode();\n","// Minimum Node.js the planner supports. Not arbitrary: ink and react (our\n// interactive UI) calls `util.styleText([\"inverse\", \"hidden\"], ...)`, and the\n// array form of `styleText` only exists on Node >= 22.13 (and 23+). On older\n// Node the first prompt render throws a cryptic `The argument 'format' must be\n// one of: ...` error, so we fail fast here with an actionable message instead.\nexport const MIN_NODE = { major: 22, minor: 13 };\n\n/**\n * Whether a `major.minor.patch` version string clears the minimum. Malformed\n * input (missing/non-numeric major or minor) is treated as unsupported so we\n * fail closed rather than let a prompt crash slip through.\n */\nexport function isSupportedNodeVersion(raw: string): boolean {\n const parts = raw.split(\".\");\n const major = Number.parseInt(parts[0] ?? \"\", 10);\n const minor = Number.parseInt(parts[1] ?? \"\", 10);\n if (!Number.isFinite(major) || !Number.isFinite(minor)) return false;\n return major > MIN_NODE.major || (major === MIN_NODE.major && minor >= MIN_NODE.minor);\n}\n\n/**\n * Exit early with a clear message when the runtime is too old for the CLI's\n * dependencies. Uses plain `console` (not the TUI) on purpose: the TUI stack is exactly\n * what breaks on the unsupported versions, so it can't be trusted to render the\n * warning. Called as the very first thing the process does.\n */\nexport function ensureSupportedNode(): void {\n const raw = process.versions.node;\n if (isSupportedNodeVersion(raw)) return;\n\n console.error(\n `\\x1b[31mAutonoma Planner requires Node.js >= ${MIN_NODE.major}.${MIN_NODE.minor} - you're running v${raw}.\\x1b[0m`,\n );\n console.error(\"Please upgrade Node.js and re-run. See https://nodejs.org/en/download\");\n process.exit(1);\n}\n","import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport * as sdk from \"./http-client\";\n\n/**\n * The `autonoma-planner sdk <action>` command group - the interactive coding\n * agent's endpoint client. The agent shells out to it to exercise its own\n * integration: `discover`, `up` (returns a refsToken), and `down` (takes that\n * token). The CLI owns request signing (HMAC over the raw body with the canonical\n * AUTONOMA_SHARED_SECRET from the env) and the request shape, so the agent\n * validates against the exact client the platform's test runner uses instead of\n * hand-rolling signatures.\n *\n * Output contract (so the agent can parse it): a single JSON object\n * `{ ok, status, body }` on stdout, and an exit code - 0 on a 2xx, 1 on a non-2xx\n * or request error, 2 on a usage error (missing secret/url/args).\n */\n\n/**\n * Per-request abort so a hung handler can't stall the agent's shell forever.\n * A cold full-recipe `up` (first compile + many sequential real-service inserts)\n * can be slow, so the default is generous and `--timeout <seconds>` raises it.\n */\nconst DEFAULT_REQUEST_TIMEOUT_MS = 120_000;\n\nexport interface SdkCommandIo {\n env: NodeJS.ProcessEnv;\n stdout: (text: string) => void;\n stderr: (text: string) => void;\n}\n\nconst createSchema = z.record(z.string(), z.array(z.unknown()));\nconst envelopeSchema = z.object({ recipes: z.array(z.object({ create: createSchema })).min(1) });\nconst bareCreateWrapperSchema = z.object({ create: createSchema });\n\n/**\n * The flags any `sdk` subcommand accepts. `.strict()` so a typo'd flag is a hard\n * error instead of being silently dropped; `timeout` is coerced from its string\n * token and validated as positive seconds. Which flags are *required* is\n * action-specific and checked below.\n */\nconst flagsSchema = z\n .object({\n url: z.string().min(1).optional(),\n recipe: z.string().min(1).optional(),\n \"refs-token\": z.string().min(1).optional(),\n \"test-run-id\": z.string().min(1).optional(),\n timeout: z.coerce.number().int().positive().optional(),\n })\n .strict();\n\n/** Run one `sdk` subcommand. `argv` is everything after `sdk` (e.g. `[\"up\", \"--url\", ...]`). */\nexport async function runSdkCommand(argv: string[], io: SdkCommandIo): Promise<number> {\n const action = argv[0];\n\n const sharedSecret = io.env.AUTONOMA_SHARED_SECRET;\n if (sharedSecret == null || sharedSecret === \"\") {\n io.stderr(\"AUTONOMA_SHARED_SECRET is not set in the environment.\\n\");\n return 2;\n }\n\n const parsedFlags = flagsSchema.safeParse(tokenizeFlags(argv.slice(1)));\n if (!parsedFlags.success) {\n io.stderr(`Invalid flags: ${formatIssues(parsedFlags.error)}\\n`);\n return 2;\n }\n const flags = parsedFlags.data;\n\n if (flags.url == null) {\n io.stderr(\"--url <endpoint-url> is required.\\n\");\n return 2;\n }\n\n const timeoutMs = flags.timeout != null ? flags.timeout * 1000 : DEFAULT_REQUEST_TIMEOUT_MS;\n const config: sdk.SdkClientConfig = { endpointUrl: flags.url, sharedSecret, timeoutMs };\n\n try {\n if (action === \"discover\") return emit(io, await sdk.discover(config));\n\n if (action === \"up\") {\n if (flags.recipe == null) {\n io.stderr(\"--recipe <file> is required for `up`.\\n\");\n return 2;\n }\n const create = await loadCreatePayload(flags.recipe);\n return emit(io, await sdk.up(config, create, flags[\"test-run-id\"] ?? `cli-${Date.now()}`));\n }\n\n if (action === \"down\") {\n if (flags[\"refs-token\"] == null) {\n io.stderr(\"--refs-token <token> is required for `down` (use the refsToken returned by `up`).\\n\");\n return 2;\n }\n return emit(io, await sdk.down(config, flags[\"refs-token\"]));\n }\n\n io.stderr(`Unknown sdk action \"${action ?? \"\"}\". Use one of: discover | up | down.\\n`);\n return 2;\n } catch (err) {\n // AbortSignal.timeout rejects with a TimeoutError/AbortError - name it explicitly\n // rather than surfacing the opaque \"operation was aborted\".\n const timedOut = err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n const detail = err instanceof Error ? err.message : String(err);\n const suffix = timedOut ? ` (request timed out after ${timeoutMs / 1000}s; raise --timeout)` : \"\";\n io.stderr(`sdk ${action ?? \"\"} failed${suffix}: ${detail}\\n`);\n return 1;\n }\n}\n\n/** Emit the response as JSON and map HTTP success to the process exit code. */\nfunction emit(io: SdkCommandIo, res: sdk.SdkResponse): number {\n io.stdout(JSON.stringify({ ok: res.ok, status: res.status, body: res.body }, null, 2) + \"\\n\");\n return res.ok ? 0 : 1;\n}\n\n/**\n * Read the `create` payload (entity -> records) from a recipe file. Accepts a full\n * recipe envelope (`{ recipes: [{ create }] }`), a `{ create }` wrapper, or a bare\n * `create` map - so the agent can point at the whole recipe.json or a single-entity\n * slice it wrote. Validated with zod (no casts) at this file boundary.\n */\nasync function loadCreatePayload(file: string): Promise<Record<string, unknown[]>> {\n const raw = await readFile(file, \"utf-8\");\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (err) {\n throw new Error(`${file} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const envelope = envelopeSchema.safeParse(json);\n if (envelope.success) return envelope.data.recipes[0]!.create;\n\n const wrapped = bareCreateWrapperSchema.safeParse(json);\n if (wrapped.success) return wrapped.data.create;\n\n const bare = createSchema.safeParse(json);\n if (bare.success) return bare.data;\n\n throw new Error(\n `${file} is not a valid recipe: expected a full recipe envelope, a { create } object, or a bare { Entity: [records] } map.`,\n );\n}\n\n/** Tokenize `--key value`, `--key=value`, and bare `--flag` (-> \"true\") into a map. */\nfunction tokenizeFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (!arg.startsWith(\"--\")) continue;\n const body = arg.slice(2);\n const eq = body.indexOf(\"=\");\n if (eq !== -1) {\n flags[body.slice(0, eq)] = body.slice(eq + 1);\n continue;\n }\n const next = argv[i + 1];\n if (next != null && !next.startsWith(\"--\")) {\n flags[body] = next;\n i++;\n } else {\n flags[body] = \"true\";\n }\n }\n return flags;\n}\n\n/** Render zod flag issues as `--flag: message` (the `--` so the fix is obvious). */\nfunction formatIssues(error: z.ZodError): string {\n return error.issues.map((i) => (i.path.length > 0 ? `--${i.path.join(\".\")}: ${i.message}` : i.message)).join(\"; \");\n}\n","import { createHmac } from \"node:crypto\";\n\nexport interface SdkClientConfig {\n endpointUrl: string;\n sharedSecret: string;\n /** Abort the request after this many ms so a hung handler can't stall the caller. */\n timeoutMs?: number;\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 signal: config.timeoutMs != null ? AbortSignal.timeout(config.timeoutMs) : undefined,\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(config: SdkClientConfig, refsToken: string): Promise<SdkResponse> {\n return sendRequest(config, {\n action: \"down\",\n refsToken,\n });\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { loadGlobalEnv } from \"./core/global-env\";\nimport { ENV_KEYS, readEnv } from \"./env\";\n\nexport interface AppConfig {\n projectRoot: string;\n projectSlug: string;\n modelId?: string;\n // Pre-supplied project-map selection (skips the interactive frontend/backend\n // picker): the single frontend to test and the backends it needs. Used by CI,\n // the eval harness, and any caller that already knows the target surface.\n frontend?: string;\n backends?: string[];\n databaseUrl?: string;\n sharedSecret?: string;\n signingSecret?: string;\n autonomaApiUrl?: string;\n autonomaApiToken?: string;\n autonomaGenerationId?: string;\n // Step-04 handoff presets. `agent` picks the interactive agent (e.g. \"claude\");\n // `permissionMode` presets its autonomy. Both come from CLI flags.\n agent?: string;\n permissionMode?: 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 // Only inject keys the CLI actually reads - never arbitrary project keys\n // (PATH, NODE_OPTIONS, ...) that happen to be in the target project's .env.\n if (ENV_KEYS.includes(key) && !(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 frontend?: string;\n backends?: string[];\n agent?: string;\n permissionMode?: 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 // Read AFTER the loaders so the validated env reflects the project/global\n // .env files just merged into process.env.\n const env = readEnv();\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 ?? env.OPENROUTER_MODEL,\n frontend: args.frontend,\n backends: args.backends,\n databaseUrl: env.DATABASE_URL,\n sharedSecret: env.AUTONOMA_SHARED_SECRET,\n signingSecret: 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: env.AUTONOMA_API_URL ?? \"https://autonoma.app\",\n autonomaApiToken: env.AUTONOMA_API_TOKEN,\n autonomaGenerationId: env.AUTONOMA_GENERATION_ID,\n agent: args.agent,\n permissionMode: args.permissionMode,\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { ENV_KEYS } from \"../env\";\n\nconst AUTONOMA_HOME = join(homedir(), \".autonoma\");\nconst GLOBAL_ENV_PATH = join(AUTONOMA_HOME, \".env\");\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 ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\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 (ENV_KEYS.includes(key) && !(key in process.env)) {\n process.env[key] = value;\n }\n }\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\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 { 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 } from \"node:fs/promises\";\nimport { basename, join, relative } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { AppConfig } from \"../config\";\nimport * as p from \"../ui/prompts\";\nimport { debugLog } from \"./debug\";\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 (err) {\n // Not every run produces every artifact (e.g. no entity audit); skip\n // the ones that aren't on disk.\n debugLog(`Artifact ${name} not on disk; skipping upload`, { err });\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"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["path","z","text","note","z","path","pad","text","clamp","join","emit","path","text","log","open","resolve","current","text","readFile","join","z","path","text","readFileSync","join","fileURLToPath","readFileSync","homedir","join","AUTONOMA_HOME","resolve","readFile","writeFile","join","resolve","DIM","RESET","execFile","readFile","writeFile","join","z","path","join","path","log","summary","RESET","readFile","join","relative","glob","execFile","promisify","z","execFileAsync","tool","glob","z","inputSchema","execFile","promisify","tool","z","inputSchema","execFileAsync","join","relative","tool","z","path","readFile","relative","resolve","tool","z","MAX_OUTPUT_BYTES","inputSchema","ToolLoopAgent","hasToolCall","stepCountIs","tool","z","readFile","inputSchema","writeFile","mkdir","dirname","relative","resolve","tool","z","inputSchema","tool","z","readdir","join","tool","z","SYSTEM_PROMPT","path","tool","z","input","note","SYSTEM_PROMPT","init_prompt","readFile","join","resolve","tool","z","SYSTEM_PROMPT","path","init_prompt","SYSTEM_PROMPT","init_prompt","readFile","writeFile","join","tool","glob","z","buildFinishTool","MAX_STEPS","SYSTEM_PROMPT","init_prompt","readFile","join","init_prompt","readFile","join","matter","buildFinishTool","readFile","join","tool","z","init_prompt","readFile","join","matter","z","current","readFile","join","z","dirname","resolve","writeFile","join","path","readFile","writeFile","join","STATE_FILE","init_state","join","init_state","init_state","z","basename","tool","readFile","join","relative","basename","glob","readFile","writeFile","join","tool","z","path","SYSTEM_PROMPT","readFile","writeFile","join","path","STATE_FILE","current","SYSTEM_PROMPT","init_prompt","matter","mkdir","writeFile","dirname","join","hasToolCall","stepCountIs","tool","ToolLoopAgent","matter","z","resultSchema","init_tools","mkdir","readFile","writeFile","basename","join","tool","z","glob","SYSTEM_PROMPT","content","init_prompt","init_tools","readFile","stat","text","text","text","MODAL_MAX_W","intro","MODAL_FILL","MODAL_MAX_W","MODAL_FILL","x","active","text","init_prompt","SPINNER_FRAMES","active","y","init_prompt","useEffect","jsx","useInput","useEffect","jsx","open","jsx","armed","readFile","writeFile","join","readFile","z","text","z","emit","readFile","readFileSync","join","join","readFileSync","join","homedir","join","AUTONOMA_HOME","join","AUTONOMA_HOME","readFile","writeFile","join","readFile","basename","join","readFile","join","basename","text","writeFile","join","readFile","runProjectMapper","runPageFinder","runKBGenerator","runEntityAudit","runScenarioRecipe","runRecipeBuilder","parsePermissionMode","runTestGenerator","parseEntityNames","readdir","mountUi","config","outputDir","text","resume"]}