@appilots/cli 0.1.0
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/LICENSE +21 -0
- package/README.md +96 -0
- package/dist/cli/index.js +4178 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.mts +891 -0
- package/dist/index.d.ts +891 -0
- package/dist/index.js +3109 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3070 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/config/index.ts","../../src/cli/utils/logger.ts","../../src/cli/commands/init.ts","../../src/services/api-client.ts","../../src/cli/commands/sync.ts","../../src/generators/MCPGenerator.ts","../../src/analyzers/ScreenAnalyzer.ts","../../src/ast/parse.ts","../../src/ast/jsx/attributes.ts","../../src/ast/jsx/classify.ts","../../src/ast/functions/collect.ts","../../src/ast/functions/analyze-async.ts","../../src/ast/navigation/calls.ts","../../src/extractors/appilots/jsdoc.ts","../../src/analyzers/NavigationAnalyzer.ts","../../src/analyzers/ComponentAnalyzer.ts","../../src/analyzers/FormAnalyzer.ts","../../src/pipeline/enrichment.ts","../../src/pipeline/metadata-lint.ts","../../src/cli/utils/metadata-report.ts","../../src/cli/commands/watch.ts","../../src/cli/commands/generate.ts","../../src/cli/commands/status.ts","../../src/cli/commands/eval.ts","../../src/eval/scenario-loader.ts","../../src/eval/matcher.ts","../../src/eval/baseline.ts","../../src/eval/scaffold.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { loadConfig } from '../config/index';\nimport { banner, error, info } from './utils/logger';\nimport { initCommand } from './commands/init';\nimport { syncCommand } from './commands/sync';\nimport { watchCommand } from './commands/watch';\nimport { generateCommand } from './commands/generate';\nimport { statusCommand } from './commands/status';\nimport { evalCommand } from './commands/eval';\n\nasync function main() {\n const program = new Command();\n\n program\n .name('appilots')\n .description(\n 'Analyze your React Native app and generate MCP documents for AI-powered navigation.\\n\\n' +\n 'Quick start:\\n' +\n ' $ appilots init --api-key ak_xxx\\n' +\n ' $ appilots sync\\n' +\n ' $ appilots watch',\n )\n .version('0.1.0')\n .option('--verbose', 'Enable verbose logging');\n\n // Register all commands\n program.addCommand(initCommand());\n program.addCommand(syncCommand());\n program.addCommand(watchCommand());\n program.addCommand(generateCommand());\n program.addCommand(statusCommand());\n program.addCommand(evalCommand());\n\n // If no arguments, check for config and default to sync\n const args = process.argv.slice(2);\n const firstArg = args[0];\n const hasCommand = firstArg !== undefined && args.length > 0 && !firstArg.startsWith('-');\n\n if (args.length === 0) {\n const config = loadConfig();\n if (config) {\n // Default to sync when config exists\n process.argv.push('sync');\n } else {\n banner();\n info('Welcome to Appilots! Get started with:');\n info(' appilots init --api-key <your-ak_key>');\n console.log('');\n program.outputHelp();\n return;\n }\n }\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err) => {\n error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n","import { readFileSync, writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport { existsSync, statSync } from 'fs';\n\n/**\n * Appilots configuration interface\n */\nexport interface AppilotsConfig {\n /** API key for authenticating with Appilots backend */\n apiKey: string;\n /**\n * Project ID on Appilots dashboard. Optional at load time — the API key\n * already identifies the project server-side (env-only CI workflows run\n * without a .appilotsrc), so commands must not assume it is present.\n */\n projectId?: string;\n /** Server URL for Appilots API */\n serverUrl: string;\n /** Output directory for generated files */\n outputDir?: string;\n /** Glob patterns to include in analysis */\n include?: string[];\n /** Glob patterns to exclude from analysis */\n exclude?: string[];\n /** Automatically activate generated MCP on sync */\n autoActivate?: boolean;\n /**\n * Strict screen filtering (§1).\n * When true, only files with registerScreen() calls or matching\n * screenPatterns are included as screens in the MCP document.\n * Default: true (exclude components/hooks/config files from the MCP screen map)\n */\n strictScreens?: boolean;\n /**\n * Glob patterns that identify screen files (used with strictScreens).\n * Default: ['**\\/*Screen.{ts,tsx}', '**\\/screens/**\\/*.{ts,tsx}']\n */\n screenPatterns?: string[];\n /**\n * Additional glob patterns for navigation file discovery (§5).\n * These are ADDED to the default patterns, not replacing them.\n */\n navigationInclude?: string[];\n /**\n * Glob patterns to exclude from navigation analysis (§5).\n */\n navigationExclude?: string[];\n /** `appilots eval` settings — see docs: Testing your agent between releases. */\n eval?: EvalConfig;\n}\n\nexport interface EvalConfig {\n /** Directory of `*.json` scenario files. Default: `<outputDir>/scenarios`. */\n scenariosDir?: string;\n /** Committed baseline file. Default: `<outputDir>/eval-baseline.json`. */\n baselinePath?: string;\n /** Minimum fraction of scenarios that must pass (0-1). Default: 0.95. */\n minPassRate?: number;\n /** Max fractional token increase vs baseline before it's flagged as a\n * regression on an otherwise-passing scenario. Default: 0.25 (+25%). */\n maxTokenRegression?: number;\n}\n\n/**\n * Validation result type\n */\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Environment overrides recognized by the CLI. Precedence when loading:\n * command-line flags (applied by each command) > env vars > .appilotsrc.\n */\nexport interface EnvOverrides {\n apiKey?: string;\n projectId?: string;\n serverUrl?: string;\n}\n\n/**\n * Reads APPILOTS_* environment variables, treating blank values as unset.\n */\nexport function getEnvOverrides(env: NodeJS.ProcessEnv = process.env): EnvOverrides {\n const clean = (value: string | undefined): string | undefined => {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n };\n return {\n apiKey: clean(env.APPILOTS_API_KEY),\n projectId: clean(env.APPILOTS_PROJECT_ID),\n serverUrl: clean(env.APPILOTS_SERVER_URL),\n };\n}\n\n/**\n * Loads configuration from the nearest .appilotsrc merged with APPILOTS_*\n * environment variables (env wins). Works without a .appilotsrc when\n * APPILOTS_API_KEY is set, so CI can run `appilots sync` with env vars only.\n *\n * @returns AppilotsConfig if a file or APPILOTS_API_KEY exists, null otherwise\n * @throws when the file is unparseable or the merged config fails validation\n */\nexport function loadConfig(): AppilotsConfig | null {\n const configPath = getConfigPath();\n const env = getEnvOverrides();\n\n let fileConfig: Record<string, unknown> = {};\n if (configPath) {\n try {\n fileConfig = JSON.parse(readFileSync(configPath, 'utf-8'));\n } catch (error) {\n throw new Error(`Failed to parse .appilotsrc at ${configPath}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n } else if (!env.apiKey) {\n return null;\n }\n\n const merged = {\n serverUrl: 'http://localhost:4000',\n outputDir: '.appilots',\n autoActivate: true,\n strictScreens: true,\n ...fileConfig,\n ...(env.apiKey ? { apiKey: env.apiKey } : {}),\n ...(env.projectId ? { projectId: env.projectId } : {}),\n ...(env.serverUrl ? { serverUrl: env.serverUrl } : {}),\n } as AppilotsConfig;\n\n const validation = validateConfig(merged);\n if (!validation.valid) {\n const source = configPath ?? 'environment variables';\n throw new Error(\n `Invalid Appilots configuration (${source}):\\n` +\n validation.errors.map((e) => ` - ${e}`).join('\\n') +\n '\\nFix .appilotsrc or set APPILOTS_API_KEY / APPILOTS_SERVER_URL.'\n );\n }\n\n return merged;\n}\n\n/**\n * Saves configuration to .appilotsrc in the given directory\n *\n * @param dir Directory to write .appilotsrc to\n * @param config Partial config to merge with defaults\n */\nexport function saveConfig(dir: string, config: Partial<AppilotsConfig>): void {\n const configPath = join(dir, '.appilotsrc');\n const existingConfig = getConfigPath() ? loadConfig() : null;\n\n const mergedConfig: AppilotsConfig = {\n apiKey: config.apiKey || existingConfig?.apiKey || '',\n projectId: config.projectId || existingConfig?.projectId || '',\n serverUrl: config.serverUrl || existingConfig?.serverUrl || 'http://localhost:4000',\n outputDir: config.outputDir || existingConfig?.outputDir || '.appilots',\n autoActivate: config.autoActivate !== undefined ? config.autoActivate : (existingConfig?.autoActivate ?? true),\n include: config.include || existingConfig?.include,\n exclude: config.exclude || existingConfig?.exclude,\n strictScreens: config.strictScreens ?? existingConfig?.strictScreens ?? true,\n screenPatterns: config.screenPatterns || existingConfig?.screenPatterns,\n navigationInclude: config.navigationInclude || existingConfig?.navigationInclude,\n navigationExclude: config.navigationExclude || existingConfig?.navigationExclude,\n eval: config.eval || existingConfig?.eval,\n };\n\n try {\n writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2), 'utf-8');\n } catch (error) {\n throw new Error(`Failed to write .appilotsrc to ${configPath}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\n/**\n * Finds and returns the path to the nearest .appilotsrc file by walking up\n * the directory tree from cwd. Follows the same logic as .npmrc lookup.\n *\n * @returns Path to .appilotsrc if found, null otherwise\n */\nexport function getConfigPath(): string | null {\n let currentDir = resolve(process.cwd());\n const root = resolve('/');\n\n while (currentDir !== root) {\n const configPath = join(currentDir, '.appilotsrc');\n try {\n if (existsSync(configPath) && statSync(configPath).isFile()) {\n return configPath;\n }\n } catch {\n // Continue searching if we can't access the file\n }\n currentDir = resolve(currentDir, '..');\n }\n\n // Check root level as last resort\n const rootConfigPath = join(root, '.appilotsrc');\n try {\n if (existsSync(rootConfigPath) && statSync(rootConfigPath).isFile()) {\n return rootConfigPath;\n }\n } catch {\n // Ignore\n }\n\n return null;\n}\n\n/**\n * Validates an Appilots configuration object for required fields and types\n *\n * @param config Configuration object to validate\n * @returns ValidationResult with valid flag and array of error messages\n */\nexport function validateConfig(config: any): ValidationResult {\n const errors: string[] = [];\n\n if (!config || typeof config !== 'object') {\n return {\n valid: false,\n errors: ['Configuration must be an object'],\n };\n }\n\n // Check required fields\n if (!config.apiKey || typeof config.apiKey !== 'string') {\n errors.push('apiKey is required and must be a string (set it in .appilotsrc or via APPILOTS_API_KEY)');\n } else if (!config.apiKey.startsWith('ak_')) {\n errors.push('apiKey must start with \"ak_\"');\n }\n\n // projectId is optional (the API key identifies the project), but when\n // present it must be a non-empty string\n if (config.projectId !== undefined && config.projectId !== '' && typeof config.projectId !== 'string') {\n errors.push('projectId must be a string');\n }\n\n // Check optional fields types\n if (config.serverUrl !== undefined && typeof config.serverUrl !== 'string') {\n errors.push('serverUrl must be a string');\n }\n\n if (config.outputDir !== undefined && typeof config.outputDir !== 'string') {\n errors.push('outputDir must be a string');\n }\n\n if (config.include !== undefined && !Array.isArray(config.include)) {\n errors.push('include must be an array of strings');\n } else if (Array.isArray(config.include) && !config.include.every((item: unknown) => typeof item === 'string')) {\n errors.push('include must be an array of strings');\n }\n\n if (config.exclude !== undefined && !Array.isArray(config.exclude)) {\n errors.push('exclude must be an array of strings');\n } else if (Array.isArray(config.exclude) && !config.exclude.every((item: unknown) => typeof item === 'string')) {\n errors.push('exclude must be an array of strings');\n }\n\n if (config.autoActivate !== undefined && typeof config.autoActivate !== 'boolean') {\n errors.push('autoActivate must be a boolean');\n }\n\n if (config.strictScreens !== undefined && typeof config.strictScreens !== 'boolean') {\n errors.push('strictScreens must be a boolean');\n }\n\n for (const field of ['screenPatterns', 'navigationInclude', 'navigationExclude'] as const) {\n const value = config[field];\n if (value !== undefined && (!Array.isArray(value) || !value.every((item: unknown) => typeof item === 'string'))) {\n errors.push(`${field} must be an array of strings`);\n }\n }\n\n if (config.eval !== undefined) {\n if (typeof config.eval !== 'object' || config.eval === null || Array.isArray(config.eval)) {\n errors.push('eval must be an object');\n } else {\n const evalConfig = config.eval as Record<string, unknown>;\n if (evalConfig.scenariosDir !== undefined && typeof evalConfig.scenariosDir !== 'string') {\n errors.push('eval.scenariosDir must be a string');\n }\n if (evalConfig.baselinePath !== undefined && typeof evalConfig.baselinePath !== 'string') {\n errors.push('eval.baselinePath must be a string');\n }\n if (\n evalConfig.minPassRate !== undefined &&\n (typeof evalConfig.minPassRate !== 'number' ||\n evalConfig.minPassRate < 0 ||\n evalConfig.minPassRate > 1)\n ) {\n errors.push('eval.minPassRate must be a number between 0 and 1');\n }\n if (\n evalConfig.maxTokenRegression !== undefined &&\n (typeof evalConfig.maxTokenRegression !== 'number' || evalConfig.maxTokenRegression < 0)\n ) {\n errors.push('eval.maxTokenRegression must be a non-negative number');\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\n\n/**\n * Pretty CLI logger using chalk and ora\n */\n\nexport type LogMode = 'pretty' | 'quiet' | 'json';\n\n/**\n * Global output mode. 'quiet' silences decorative output (banner, info,\n * success, dim) keeping warnings/errors; 'json' silences everything on\n * stdout except the final JSON payload (errors go to stderr) so CI can\n * pipe the output straight into a parser.\n */\nlet mode: LogMode = 'pretty';\n\nexport function setLogMode(next: LogMode): void {\n mode = next;\n}\n\nexport function getLogMode(): LogMode {\n return mode;\n}\n\n/**\n * Prints the machine-readable result of a command. Only mode 'json'\n * emits it — pretty/quiet runs already communicated via the logger.\n */\nexport function jsonOutput(payload: unknown): void {\n if (mode === 'json') {\n console.log(JSON.stringify(payload, null, 2));\n }\n}\n\n/**\n * Creates and returns an ora spinner instance. Silent in quiet/json mode\n * (spinner control sequences would corrupt piped output).\n *\n * @param text Text to display while spinning\n * @returns Ora spinner instance\n */\nexport function createSpinner(text: string) {\n return ora({ text, isSilent: mode !== 'pretty' });\n}\n\n/**\n * Prints a success message with a green checkmark\n *\n * @param msg Message to display\n */\nexport function success(msg: string): void {\n if (mode !== 'pretty') return;\n console.log(chalk.green.bold('✓'), msg);\n}\n\n/**\n * Prints an error message with a red X. Always emitted — on stderr in\n * json mode so stdout stays parseable.\n *\n * @param msg Message to display\n */\nexport function error(msg: string): void {\n if (mode === 'json') {\n console.error(chalk.red.bold('✗'), msg);\n return;\n }\n console.log(chalk.red.bold('✗'), msg);\n}\n\n/**\n * Prints a warning message with a yellow warning symbol. Kept in quiet\n * mode; routed to stderr in json mode.\n *\n * @param msg Message to display\n */\nexport function warn(msg: string): void {\n if (mode === 'json') {\n console.error(chalk.yellow.bold('⚠'), msg);\n return;\n }\n console.log(chalk.yellow.bold('⚠'), msg);\n}\n\n/**\n * Prints an informational message with a blue info icon\n *\n * @param msg Message to display\n */\nexport function info(msg: string): void {\n if (mode !== 'pretty') return;\n console.log(chalk.blue.bold('ℹ'), msg);\n}\n\n/**\n * Prints dimmed/gray text\n *\n * @param msg Message to display\n */\nexport function dim(msg: string): void {\n if (mode !== 'pretty') return;\n console.log(chalk.dim(msg));\n}\n\n/**\n * Prints the Appilots ASCII logo and header with version\n */\nexport function banner(): void {\n if (mode !== 'pretty') return;\n const logo = `\n ${chalk.cyan('╔═══════════════════════════════════════╗')}\n ${chalk.cyan('║')} ${chalk.bold.cyan('Appilots MCP Generator')} ${chalk.cyan('║')}\n ${chalk.cyan('║')} ${chalk.dim('v0.1.0')} ${chalk.cyan('║')}\n ${chalk.cyan('╚═══════════════════════════════════════╝')}\n `;\n console.log(logo);\n}\n\n/**\n * Prints a section heading (plain line). Suppressed outside pretty mode.\n */\nexport function heading(msg: string): void {\n if (mode !== 'pretty') return;\n console.log(msg);\n}\n\n/**\n * Prints a simple two-column aligned table\n *\n * @param rows Array of [key, value] pairs to display\n */\nexport function table(rows: [string, string][]): void {\n if (mode !== 'pretty' || rows.length === 0) {\n return;\n }\n\n // Calculate the maximum key length for alignment\n const maxKeyLength = Math.max(...rows.map(([key]) => key.length));\n\n rows.forEach(([key, value]) => {\n const padding = ' '.repeat(maxKeyLength - key.length + 2);\n console.log(` ${chalk.bold(key)}${padding}${value}`);\n });\n}\n","import { Command } from 'commander';\nimport { AppilotsAPIClient } from '../../services/api-client';\nimport { saveConfig, getConfigPath, getEnvOverrides } from '../../config/index';\nimport { banner, success, error, warn, info, dim } from '../utils/logger';\nimport { existsSync, readFileSync, appendFileSync } from 'fs';\nimport { join } from 'path';\n\ninterface InitOptions {\n apiKey?: string;\n server?: string;\n}\n\n/**\n * .appilotsrc stores the API key in plain text, so it must never be\n * committed. Appends it to the project's .gitignore when missing;\n * returns what happened so the command can phrase the warning.\n */\nfunction ensureConfigIgnored(dir: string): 'already-ignored' | 'added' | 'no-gitignore' {\n const gitignorePath = join(dir, '.gitignore');\n if (!existsSync(gitignorePath)) {\n return 'no-gitignore';\n }\n\n const lines = readFileSync(gitignorePath, 'utf-8').split(/\\r?\\n/);\n const ignored = lines.some((line) => {\n const entry = line.trim();\n return entry === '.appilotsrc' || entry === '/.appilotsrc' || entry === '.appilotsrc/';\n });\n if (ignored) {\n return 'already-ignored';\n }\n\n appendFileSync(gitignorePath, '\\n# Appilots CLI config (contains your API key — do not commit)\\n.appilotsrc\\n');\n return 'added';\n}\n\nexport function initCommand(): Command {\n return new Command('init')\n .description('Set up Appilots configuration interactively')\n .option('--api-key <key>', 'Appilots API key (ak_... format)')\n .option('--server <url>', 'Appilots server URL')\n .action(async (options: InitOptions) => {\n try {\n banner();\n\n // Check if config already exists\n const configPath = getConfigPath();\n if (configPath) {\n warn(`Found existing .appilotsrc at ${configPath}`);\n warn('Use --api-key and --server to override settings');\n }\n\n // Flag wins over environment variable\n const env = getEnvOverrides();\n const apiKey = options.apiKey || env.apiKey;\n if (!apiKey) {\n error('API key is required');\n info('Provide it with: --api-key <your-ak_...key>');\n info('Or set APPILOTS_API_KEY environment variable');\n process.exit(1);\n }\n if (!options.apiKey && env.apiKey) {\n info('Using API key from APPILOTS_API_KEY environment variable');\n }\n\n // Use provided server, then env, then default\n const serverUrl = options.server || env.serverUrl || 'http://localhost:4000';\n\n // Validate API key format\n if (!apiKey.startsWith('ak_')) {\n error('Invalid API key format. Must start with ak_');\n process.exit(1);\n }\n\n info('Validating API key...');\n const apiClient = new AppilotsAPIClient({\n serverUrl,\n apiKey,\n });\n\n // Check health\n const isHealthy = await apiClient.health();\n if (!isHealthy) {\n error(`Cannot reach Appilots server at ${serverUrl}`);\n info('Make sure the server is running and the URL is correct');\n process.exit(1);\n }\n\n // Get status to validate credentials and get project info\n const status = await apiClient.status();\n if (status.error) {\n error(`Failed to validate API key: ${status.error}`);\n process.exit(1);\n }\n\n if (!status.project) {\n error('Could not retrieve project information');\n process.exit(1);\n }\n\n success(`✓ Successfully connected to ${status.project.name}`);\n success(`✓ Project ID: ${status.project.id}`);\n\n // Save configuration\n const config = {\n apiKey,\n projectId: status.project.id,\n serverUrl,\n outputDir: '.appilots',\n autoActivate: true,\n };\n\n saveConfig(process.cwd(), config);\n\n success('Configuration saved to .appilotsrc');\n\n switch (ensureConfigIgnored(process.cwd())) {\n case 'added':\n success('Added .appilotsrc to .gitignore (it contains your API key)');\n break;\n case 'no-gitignore':\n warn('.appilotsrc contains your API key — make sure it is NOT committed');\n info('Add \".appilotsrc\" to your .gitignore');\n break;\n case 'already-ignored':\n break;\n }\n\n info('Next steps:');\n dim(' $ appilots sync - Analyze and upload your project');\n dim(' $ appilots watch - Watch for changes and auto-sync');\n } catch (err) {\n error(`Initialization failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n });\n}\n","/**\n * HTTP client for communicating with the Appilots API backend\n */\n\n/**\n * Result from a sync operation\n */\nexport interface SyncResult {\n success: boolean;\n unchanged: boolean;\n id?: string;\n checksum?: string;\n screensCount?: number;\n formsCount?: number;\n actionsCount?: number;\n error?: string;\n}\n\n/**\n * One eval scenario as sent to `POST /cli/eval/run`. Shape mirrors the\n * server's `evalScenarioRequestSchema` — kept as a plain interface here\n * (no @appilots/shared import) since this package publishes standalone.\n */\nexport interface EvalScenarioRequest {\n id: string;\n screen?: string;\n observation?: unknown;\n prompt: string;\n modelOverride?: string;\n}\n\nexport interface EvalScenarioResult {\n id: string;\n content: string;\n actions: Array<{ id: string; type: string; payload: Record<string, unknown> }>;\n totalTokens: number;\n totalCostUsd: number;\n totalLatencyMs: number;\n modelUsed: string;\n}\n\n/**\n * Result from an eval run\n */\nexport interface EvalRunResult {\n results?: EvalScenarioResult[];\n error?: string;\n}\n\n/**\n * Result from a status query\n */\nexport interface StatusResult {\n project?: {\n id: string;\n name: string;\n };\n activeMcp?: {\n id: string;\n version: string;\n screensCount: number;\n formsCount: number;\n actionsCount: number;\n };\n error?: string;\n}\n\n/**\n * Appilots API client configuration\n */\ninterface APIClientConfig {\n serverUrl: string;\n apiKey: string;\n /** Per-request timeout in ms (default 30s) */\n timeoutMs?: number;\n /** Retries on network errors / 5xx (default 2) */\n maxRetries?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst RETRY_BASE_DELAY_MS = 500;\n\n/**\n * HTTP client for communicating with Appilots API\n */\nexport class AppilotsAPIClient {\n private serverUrl: string;\n private apiKey: string;\n private timeoutMs: number;\n private maxRetries: number;\n\n constructor(config: APIClientConfig) {\n this.serverUrl = config.serverUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.apiKey = config.apiKey;\n this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n }\n\n /**\n * fetch with a hard timeout and exponential-backoff retries. Retries\n * only on network failures and 5xx responses — 4xx are the caller's\n * problem and retrying them would just spam the server.\n */\n private async request(url: string, init: RequestInit): Promise<Response> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n await new Promise((r) => setTimeout(r, RETRY_BASE_DELAY_MS * 2 ** (attempt - 1)));\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const response = await fetch(url, { ...init, signal: controller.signal });\n if (response.status >= 500 && attempt < this.maxRetries) {\n lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);\n continue;\n }\n return response;\n } catch (err) {\n lastError = controller.signal.aborted\n ? new Error(`Request timed out after ${this.timeoutMs}ms: ${url}`)\n : err;\n } finally {\n clearTimeout(timer);\n }\n }\n throw lastError instanceof Error ? lastError : new Error(String(lastError));\n }\n\n /**\n * Syncs content with the Appilots backend\n *\n * @param content The MCP content object to sync\n * @param version Version string for the content\n * @param appVersion Host app version (package.json) — sent as\n * X-App-Version so the backend can associate the MCP\n * document with the app build that produced it\n * @returns SyncResult with success status and metadata\n */\n async sync(content: object, version: string, appVersion?: string): Promise<SyncResult> {\n try {\n const response = await this.request(`${this.serverUrl}/api/v1/cli/sync`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n ...(appVersion ? { 'X-App-Version': appVersion } : {}),\n },\n body: JSON.stringify({ content, version }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n return {\n success: false,\n unchanged: false,\n error: (errorData?.error as string) || `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n const json = (await response.json()) as Record<string, unknown>;\n const inner = (json.data ?? json) as Record<string, unknown>;\n return {\n success: true,\n ...inner,\n } as SyncResult;\n } catch (error) {\n return {\n success: false,\n unchanged: false,\n error: error instanceof Error ? error.message : 'Failed to sync with Appilots API',\n };\n }\n }\n\n /**\n * Gets the status of the Appilots project and active MCP\n *\n * @returns StatusResult with project and active MCP information\n */\n async status(): Promise<StatusResult> {\n try {\n const response = await this.request(`${this.serverUrl}/api/v1/cli/status`, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n return {\n error: (errorData?.error as string) || `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n const json = (await response.json()) as Record<string, unknown>;\n const inner = (json.data ?? json) as StatusResult;\n return inner;\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : 'Failed to fetch status from Appilots API',\n };\n }\n }\n\n /**\n * Runs a batch of eval scenarios against the project's MCP document in\n * decision/dry-run mode — no side effects, same relay path as the\n * dashboard's sandbox, authenticated with this client's API key.\n *\n * @param scenarios Scenarios to run, capped server-side at\n * EVAL_MAX_SCENARIOS_PER_RUN (currently 20) as a cost guard.\n */\n async evalRun(scenarios: EvalScenarioRequest[]): Promise<EvalRunResult> {\n try {\n const response = await this.request(`${this.serverUrl}/api/v1/cli/eval/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({ scenarios }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const errObj = errorData?.error as Record<string, unknown> | undefined;\n return {\n error:\n (errObj?.message as string | undefined) ||\n `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n const json = (await response.json()) as Record<string, unknown>;\n const inner = (json.data ?? json) as { results?: EvalScenarioResult[] };\n return { results: inner.results ?? [] };\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : 'Failed to run eval against Appilots API',\n };\n }\n }\n\n /**\n * Checks if the Appilots API server is healthy\n *\n * @returns true if server is healthy, false otherwise\n */\n async health(): Promise<boolean> {\n try {\n const response = await this.request(`${this.serverUrl}/api/v1/health`, {\n method: 'GET',\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n","import { Command } from 'commander';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { MCPGenerator } from '../../generators/MCPGenerator';\nimport { AppilotsAPIClient } from '../../services/api-client';\nimport { loadConfig } from '../../config/index';\nimport { banner, success, error, info, createSpinner, warn, table, heading, setLogMode, jsonOutput } from '../utils/logger';\nimport { reportMetadataLint } from '../utils/metadata-report';\n\ninterface SyncOptions {\n verbose?: boolean;\n force?: boolean;\n apiKey?: string;\n projectId?: string;\n server?: string;\n json?: boolean;\n quiet?: boolean;\n strictMetadata?: boolean;\n}\n\nexport function syncCommand(): Command {\n return new Command('sync')\n .description('Analyze project and sync MCP documents with Appilots')\n .option('--verbose', 'Enable verbose logging', false)\n .option('--force', 'Force upload even if nothing changed', false)\n .option('--api-key <key>', 'Appilots API key (overrides .appilotsrc and APPILOTS_API_KEY)')\n .option('--project-id <id>', 'Project ID (overrides .appilotsrc and APPILOTS_PROJECT_ID)')\n .option('--server <url>', 'Appilots server URL (overrides .appilotsrc and APPILOTS_SERVER_URL)')\n .option('--json', 'Output a machine-readable JSON result (implies --quiet)', false)\n .option('--quiet', 'Suppress banner and informational output', false)\n .option('--strict-metadata', 'Fail when mutating actions are missing effect/riskLevel metadata', false)\n .action(async (options: SyncOptions) => {\n if (options.json) setLogMode('json');\n else if (options.quiet) setLogMode('quiet');\n try {\n banner();\n\n // Load configuration (.appilotsrc merged with APPILOTS_* env vars),\n // then let explicit flags win — CI can run without any .appilotsrc.\n const loaded = loadConfig();\n const apiKey = options.apiKey || loaded?.apiKey;\n if (!apiKey) {\n error('No .appilotsrc configuration found');\n info('Run: appilots init --api-key <your-key>');\n info('Or set APPILOTS_API_KEY, or pass --api-key');\n jsonOutput({ success: false, error: 'No configuration found (missing API key)' });\n process.exit(1);\n return;\n }\n const config = {\n serverUrl: 'http://localhost:4000',\n outputDir: '.appilots',\n ...loaded,\n apiKey,\n ...(options.projectId ? { projectId: options.projectId } : {}),\n ...(options.server ? { serverUrl: options.server } : {}),\n };\n\n // Initialize API client\n const apiClient = new AppilotsAPIClient({\n serverUrl: config.serverUrl,\n apiKey: config.apiKey,\n });\n\n const outputDir = config.outputDir || '.appilots';\n\n // §3 fix: Read previous checksum BEFORE generating\n let previousChecksum = '';\n try {\n const checksumPath = join(outputDir, '.appilots-checksum');\n previousChecksum = (await readFile(checksumPath, 'utf-8')).trim();\n } catch {\n // No previous checksum — first run\n }\n\n // Generate MCP document\n let spinner = createSpinner('Analyzing project...');\n spinner.start();\n\n const generator = new MCPGenerator({\n rootDir: process.cwd(),\n outputDir,\n format: 'json',\n strictScreens: config.strictScreens,\n screenPatterns: config.screenPatterns,\n include: config.include,\n exclude: config.exclude,\n navigationInclude: config.navigationInclude,\n navigationExclude: config.navigationExclude,\n });\n\n const output = await generator.generate();\n spinner.stop();\n\n success(\n `Found ${output.document.metadata.totalScreens} screens, ` +\n `${output.document.metadata.totalForms} forms, ${output.document.metadata.totalActions} actions`\n );\n\n // OKR-005 KR4: surface mutating actions missing effect/riskLevel\n // before upload; fatal only with --strict-metadata\n reportMetadataLint(output.document, Boolean(options.strictMetadata));\n\n // §3 fix: Compare previous checksum with newly generated one\n if (!options.force && previousChecksum && previousChecksum === output.checksum) {\n // Local content hasn't changed — check remote to confirm\n spinner = createSpinner('Checking remote status...');\n spinner.start();\n\n const status = await apiClient.status();\n spinner.stop();\n\n if (status.error) {\n warn(`Could not verify remote: ${status.error}`);\n info('Uploading anyway...');\n } else if (status.activeMcp) {\n success('Already up to date (no local or remote changes)');\n jsonOutput({ success: true, unchanged: true, checksum: output.checksum });\n return;\n }\n // No active MCP on server? Fall through to upload\n }\n\n // Upload to server\n spinner = createSpinner('Uploading to Appilots...');\n spinner.start();\n\n const syncResult = await apiClient.sync(\n output.document,\n output.document.version,\n output.document.metadata.appVersion,\n );\n spinner.stop();\n\n if (!syncResult.success) {\n error(`Sync failed: ${syncResult.error}`);\n jsonOutput({ success: false, error: syncResult.error });\n process.exit(1);\n }\n\n if (syncResult.unchanged && !options.force) {\n success('Already up to date on server');\n } else {\n success('Successfully synced MCP document');\n info(`Document ID: ${syncResult.id}`);\n info(`Checksum: ${syncResult.checksum}`);\n\n if (config.projectId) {\n const dashboardUrl = `${config.serverUrl}/dashboard/projects/${config.projectId}`;\n info(`View on dashboard: ${dashboardUrl}`);\n }\n }\n\n if (options.verbose) {\n heading('\\nSync Details:');\n table([\n ['Screens', String(syncResult.screensCount || 0)],\n ['Forms', String(syncResult.formsCount || 0)],\n ['Actions', String(syncResult.actionsCount || 0)],\n ['Document ID', syncResult.id || 'N/A'],\n ['Previous checksum', previousChecksum || '(first run)'],\n ['New checksum', output.checksum],\n ['Changed', String(previousChecksum !== output.checksum)],\n ]);\n }\n\n jsonOutput({\n success: true,\n unchanged: Boolean(syncResult.unchanged),\n id: syncResult.id,\n checksum: syncResult.checksum ?? output.checksum,\n screensCount: syncResult.screensCount ?? output.document.metadata.totalScreens,\n formsCount: syncResult.formsCount ?? output.document.metadata.totalForms,\n actionsCount: syncResult.actionsCount ?? output.document.metadata.totalActions,\n });\n } catch (err) {\n error(`Sync failed: ${err instanceof Error ? err.message : String(err)}`);\n jsonOutput({ success: false, error: err instanceof Error ? err.message : String(err) });\n if (options.verbose) {\n console.error(err);\n }\n process.exit(1);\n }\n });\n}\n","import { mkdir, writeFile, readFile } from 'node:fs/promises';\nimport { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport type { MCPGeneratorOptions, MCPDocument, MCPOutput } from './types';\nimport type { AnalyzerConfig, FormDescriptor, FormFieldDescriptor, ScreenDescriptor } from '../types';\nimport { ScreenAnalyzer } from '../analyzers/ScreenAnalyzer';\nimport { NavigationAnalyzer } from '../analyzers/NavigationAnalyzer';\nimport { ComponentAnalyzer } from '../analyzers/ComponentAnalyzer';\nimport { FormAnalyzer } from '../analyzers/FormAnalyzer';\nimport { enrichScreenForAgent } from '../pipeline/enrichment';\nimport glob from 'fast-glob';\n\n/**\n * Main generator that orchestrates analyzers and produces MCP documents.\n *\n * @example\n * ```ts\n * const generator = new MCPGenerator({\n * rootDir: './my-rn-app',\n * outputDir: '.appilots',\n * format: 'json',\n * });\n *\n * const output = await generator.generate();\n * console.log(`Generated MCP at: ${output.filePath}`);\n * ```\n */\nexport interface MCPGeneratorConfig {\n rootDir: string;\n outputDir?: string;\n format?: 'json';\n version?: string;\n includeSourcePaths?: boolean;\n splitOutput?: boolean;\n /** §1: Only include files with registerScreen() or matching screen patterns */\n strictScreens?: boolean;\n /** §1: Custom glob patterns for screen file detection */\n screenPatterns?: string[];\n /** §5: Additional navigation file patterns (added to defaults) */\n navigationInclude?: string[];\n /** §5: Exclude patterns for navigation analysis */\n navigationExclude?: string[];\n /** Source include patterns */\n include?: string[];\n /** Source exclude patterns */\n exclude?: string[];\n}\n\nexport class MCPGenerator {\n private analyzerConfig: AnalyzerConfig;\n private options: MCPGeneratorOptions;\n private generatorConfig: MCPGeneratorConfig;\n\n constructor(config: MCPGeneratorConfig) {\n this.generatorConfig = config;\n\n this.analyzerConfig = {\n rootDir: config.rootDir,\n include: config.include ?? ['**/*.tsx', '**/*.ts', '**/*.jsx', '**/*.js'],\n exclude: config.exclude ?? ['**/node_modules/**', '**/__tests__/**', '**/dist/**'],\n };\n\n this.options = {\n format: config.format ?? 'json',\n outputDir: config.outputDir ?? '.appilots',\n includeSourcePaths: config.includeSourcePaths ?? false,\n splitOutput: config.splitOutput ?? false,\n version: config.version ?? '1.0',\n };\n }\n\n /** Generate MCP documents from the project */\n async generate(): Promise<MCPOutput> {\n console.log('[MCPGenerator] Starting generation...');\n\n // Create output directory if it doesn't exist\n const outputDir = this.options.outputDir || '.appilots';\n await mkdir(outputDir, { recursive: true });\n console.log(`[MCPGenerator] Output directory ensured: ${outputDir}`);\n\n // Run all analyzers in parallel\n const screenAnalyzer = new ScreenAnalyzer(this.analyzerConfig, {\n strictScreens: this.generatorConfig.strictScreens ?? true,\n screenPatterns: this.generatorConfig.screenPatterns,\n });\n const navigationAnalyzer = new NavigationAnalyzer(this.analyzerConfig, {\n navigationInclude: this.generatorConfig.navigationInclude,\n navigationExclude: this.generatorConfig.navigationExclude,\n });\n const componentAnalyzer = new ComponentAnalyzer(this.analyzerConfig);\n const formAnalyzer = new FormAnalyzer(this.analyzerConfig);\n\n console.log('[MCPGenerator] Running analyzers...');\n const [screens, navigation] = await Promise.all([\n screenAnalyzer.analyze(),\n navigationAnalyzer.analyze(),\n ]);\n\n console.log(\n `[MCPGenerator] Screen and navigation analysis complete. Found ${screens.length} screens`\n );\n\n // Find all screen files to run ComponentAnalyzer and FormAnalyzer on each\n const screenFiles = await glob(\n this.analyzerConfig.include || ['**/*.tsx', '**/*.ts'],\n {\n cwd: this.analyzerConfig.rootDir,\n ignore: this.analyzerConfig.exclude || ['**/node_modules/**'],\n }\n );\n\n console.log(`[MCPGenerator] Analyzing components and forms from ${screenFiles.length} files...`);\n\n // Run ComponentAnalyzer and FormAnalyzer on each screen file\n const enrichmentPromises = screenFiles.map(async (file: string) => {\n const filePath = path.resolve(this.analyzerConfig.rootDir, file);\n try {\n const [components, forms] = await Promise.all([\n componentAnalyzer.analyzeFile(filePath),\n formAnalyzer.analyzeFile(filePath),\n ]);\n return { filePath, components, forms };\n } catch (error) {\n console.warn(`[MCPGenerator] Failed to analyze ${file}:`, error);\n return { filePath, components: [], forms: [] };\n }\n });\n\n const enrichmentResults = await Promise.all(enrichmentPromises);\n\n // Create a map of file path to enrichment data\n const enrichmentMap = new Map<\n string,\n { components: any[]; forms: any[] }\n >();\n for (const result of enrichmentResults) {\n enrichmentMap.set(result.filePath, {\n components: result.components,\n forms: result.forms,\n });\n }\n\n // Enrich screens with components and forms from analyzers\n const enrichedScreens = screens.map((screen) => {\n const enrichment = enrichmentMap.get(screen.filePath);\n if (enrichment) {\n // Merge components (avoid duplicates)\n const existingComponentNames = new Set(screen.components.map((c) => c.name));\n const newComponents = enrichment.components.filter(\n (c: any) => !existingComponentNames.has(c.name)\n );\n\n // Merge forms. registerScreen/ScreenAnalyzer forms are the primary\n // contract; FormAnalyzer enriches them with submit/validation data.\n const mergedForms: FormDescriptor[] = screen.forms.map((form) => ({\n ...form,\n fields: [...form.fields],\n }));\n for (const newForm of enrichment.forms) {\n const existingForm =\n mergedForms.find((form) => form.id === newForm.id) ??\n this.findFormWithSharedFields(mergedForms, newForm);\n if (existingForm) {\n this.mergeForm(existingForm, newForm);\n } else {\n mergedForms.push({\n ...newForm,\n fields: [...newForm.fields],\n submitAction: this.namedSubmitAction(newForm.submitAction),\n });\n }\n }\n\n return {\n ...screen,\n components: [...screen.components, ...newComponents],\n forms: mergedForms,\n } as ScreenDescriptor;\n }\n return screen;\n });\n\n const agentReadyScreens = enrichedScreens.map(enrichScreenForAgent);\n\n // Get project name and app version from package.json\n const projectInfo = await this.getProjectInfo();\n const projectName = projectInfo.name;\n\n console.log(`[MCPGenerator] Project name: ${projectName}`);\n\n // Build the MCPDocument\n const document: MCPDocument = {\n version: this.options.version!,\n generatedAt: new Date().toISOString(),\n projectName,\n screens: agentReadyScreens,\n navigation,\n metadata: {\n generatorVersion: '0.1.0',\n ...(projectInfo.version ? { appVersion: projectInfo.version } : {}),\n totalScreens: agentReadyScreens.length,\n totalForms: agentReadyScreens.reduce((acc, s) => acc + s.forms.length, 0),\n totalActions: agentReadyScreens.reduce((acc, s) => acc + s.actions.length, 0),\n analyzedFiles: screenFiles.length,\n // §D: Only set when strict mode filters out screens\n ...(screenAnalyzer.screensFilteredOut > 0\n ? { screensFilteredOut: screenAnalyzer.screensFilteredOut }\n : {}),\n },\n };\n\n // Serialize document to JSON\n const serialized = JSON.stringify(document, null, 2);\n\n // Calculate SHA-256 checksum\n const checksum = this.calculateChecksum(serialized);\n\n // Write the document file\n const filePath = path.resolve(\n outputDir,\n `mcp-document.${this.options.format}`\n );\n await writeFile(filePath, serialized, 'utf-8');\n console.log(`[MCPGenerator] Document written to: ${filePath}`);\n\n // Write checksum file\n const checksumFilePath = path.resolve(outputDir, '.appilots-checksum');\n await writeFile(checksumFilePath, checksum, 'utf-8');\n console.log(`[MCPGenerator] Checksum written to: ${checksumFilePath}`);\n\n console.log('[MCPGenerator] Generation complete!');\n\n return {\n document,\n filePath,\n format: this.options.format,\n checksum,\n };\n }\n\n /**\n * Read the previously stored checksum from disk.\n * Returns null if no checksum file exists (first run).\n *\n * §4: This replaces the incomplete `hasChanged` static method.\n * To detect actual changes, compare this value with `output.checksum`\n * after calling `generate()`.\n */\n static async readPreviousChecksum(outputDir: string): Promise<string | null> {\n const checksumFilePath = path.resolve(outputDir, '.appilots-checksum');\n try {\n const content = await readFile(checksumFilePath, 'utf-8');\n return content.trim() || null;\n } catch {\n return null;\n }\n }\n\n /**\n * Calculate SHA-256 checksum of content\n */\n private calculateChecksum(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n }\n\n private mergeForm(target: FormDescriptor, source: FormDescriptor): void {\n for (const field of source.fields) {\n const existingField = this.findEquivalentField(target.fields, field);\n if (existingField) {\n this.mergeField(existingField, field);\n } else {\n target.fields.push(field);\n }\n }\n target.submitAction = target.submitAction ?? this.namedSubmitAction(source.submitAction);\n target.validationRules = source.validationRules\n ? { ...source.validationRules, ...(target.validationRules ?? {}) }\n : target.validationRules;\n }\n\n private findEquivalentField(\n fields: FormFieldDescriptor[],\n incoming: FormFieldDescriptor,\n ): FormFieldDescriptor | undefined {\n return fields.find((field) => {\n if (field.name && incoming.name && field.name === incoming.name) return true;\n if (field.valueBinding && incoming.valueBinding && field.valueBinding === incoming.valueBinding) return true;\n if (field.locator?.id && incoming.locator?.id && field.locator.id === incoming.locator.id) return true;\n if (field.placeholder && incoming.placeholder && field.placeholder === incoming.placeholder) return true;\n if (\n field.locator?.accessibilityLabel &&\n incoming.locator?.accessibilityLabel &&\n field.locator.accessibilityLabel === incoming.locator.accessibilityLabel\n ) {\n return true;\n }\n return false;\n });\n }\n\n private mergeField(target: FormFieldDescriptor, source: FormFieldDescriptor): void {\n if (this.isWeakInferredFieldName(target.name) && !this.isWeakInferredFieldName(source.name)) {\n target.name = source.name;\n }\n target.label = target.label ?? source.label;\n target.placeholder = target.placeholder ?? source.placeholder;\n target.options = target.options ?? source.options;\n target.locator = target.locator ?? source.locator;\n target.sourceComponent = target.sourceComponent ?? source.sourceComponent;\n target.valueBinding = target.valueBinding ?? source.valueBinding;\n target.errorBinding = target.errorBinding ?? source.errorBinding;\n target.required = target.required || source.required;\n if (target.type === 'text' && source.type !== 'text') {\n target.type = source.type;\n }\n }\n\n private namedSubmitAction(submitAction: string | undefined): string | undefined {\n return submitAction && submitAction !== 'anonymous' ? submitAction : undefined;\n }\n\n private isWeakInferredFieldName(name: string): boolean {\n return /^(text|value|input|query|search|selected|checked)$/i.test(name);\n }\n\n private findFormWithSharedFields(\n forms: FormDescriptor[],\n incoming: FormDescriptor,\n ): FormDescriptor | undefined {\n if (incoming.fields.length === 0) return undefined;\n\n let best: { form: FormDescriptor; overlap: number } | undefined;\n for (const form of forms) {\n const overlap = incoming.fields.filter((field) => this.findEquivalentField(form.fields, field)).length;\n if (overlap > 0 && (!best || overlap > best.overlap)) {\n best = { form, overlap };\n }\n }\n\n return best?.form;\n }\n\n /**\n * Get project name and version from package.json in rootDir\n */\n private async getProjectInfo(): Promise<{ name: string; version?: string }> {\n try {\n const packageJsonPath = path.resolve(this.analyzerConfig.rootDir, 'package.json');\n const packageJsonContent = await readFile(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(packageJsonContent);\n return {\n name: packageJson.name || 'Unknown Project',\n version: typeof packageJson.version === 'string' ? packageJson.version : undefined,\n };\n } catch (error) {\n console.warn('[MCPGenerator] Failed to read package.json, using default project name');\n return { name: 'Unknown Project' };\n }\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport traverse from '@babel/traverse';\nimport * as BabelTypes from '@babel/types';\nimport glob from 'fast-glob';\nimport { parseSource } from '../ast/parse';\nimport { classifyJsxComponent } from '../ast/jsx/classify';\nimport { collectFunctions } from '../ast/functions/collect';\nimport { analyzeFunctionBehavior } from '../ast/functions/analyze-async';\nimport { extractNavigationCalls } from '../ast/navigation/calls';\nimport {\n extractDestructiveJsDocTargets,\n extractPermissionsFromJsDoc,\n} from '../extractors/appilots/jsdoc';\nimport type {\n AnalyzerConfig,\n ScreenDescriptor,\n FormDescriptor,\n FormFieldDescriptor,\n ActionDescriptor,\n ComponentDescriptor,\n CollectionDescriptor,\n RowActionDescriptor,\n AppilotsInferredAction,\n LocatorDescriptor,\n} from '../types';\n\nexport { extractDestructiveJsDocTargets, extractPermissionsFromJsDoc } from '../extractors/appilots/jsdoc';\n\n/**\n * Analyzes React Native source files to extract screen definitions,\n * their components, forms, and available actions.\n *\n * The analyzer uses Babel AST to:\n * 1. Extract optional registerScreen() calls (developer-provided metadata)\n * 2. Detect exported component names\n * 3. Find navigation patterns (navigation.navigate calls)\n * 4. Identify form inputs (TextInput, Input components)\n * 5. Extract button/action handlers\n *\n * §1 Strict mode: when `strictScreens` is enabled in config, only files\n * containing a `registerScreen()` call or matching `screenPatterns` globs\n * are included in the output. This avoids components/hooks/utils being\n * listed as screens.\n */\nexport class ScreenAnalyzer {\n private config: AnalyzerConfig;\n private verbose = process.env.VERBOSE === 'true';\n /** When true, only files with registerScreen or matching screen patterns are included */\n private strictScreens: boolean;\n /** Glob patterns that identify screen files in strict mode */\n private screenPatterns: string[];\n /** §D: Count of screens filtered out in strict mode (available after analyze()) */\n public screensFilteredOut = 0;\n\n constructor(\n config: AnalyzerConfig,\n options?: { strictScreens?: boolean; screenPatterns?: string[] },\n ) {\n this.config = config;\n this.strictScreens = options?.strictScreens ?? false;\n this.screenPatterns = options?.screenPatterns ?? [\n '**/*Screen.{ts,tsx}',\n '**/screens/**/*.{ts,tsx}',\n ];\n }\n\n /** Analyze all screens in the project */\n async analyze(): Promise<ScreenDescriptor[]> {\n const { include = ['src/**/*Screen.{ts,tsx}'], exclude = ['node_modules/**'] } = this.config;\n\n if (this.verbose) {\n console.log(`[ScreenAnalyzer] Searching with patterns:`, include);\n if (this.strictScreens) {\n console.log(`[ScreenAnalyzer] Strict mode ON — screen patterns:`, this.screenPatterns);\n }\n }\n\n // Find all matching files\n const files = await glob(include, {\n cwd: this.config.rootDir,\n ignore: exclude,\n });\n\n if (this.verbose) {\n console.log(`[ScreenAnalyzer] Found ${files.length} files`);\n }\n\n // In strict mode, pre-compute which files match screen patterns\n let screenPatternFiles: Set<string> | null = null;\n if (this.strictScreens) {\n const matched = await glob(this.screenPatterns, {\n cwd: this.config.rootDir,\n ignore: exclude,\n });\n screenPatternFiles = new Set(matched.map((f) => path.resolve(this.config.rootDir, f)));\n }\n\n const screens: ScreenDescriptor[] = [];\n this.screensFilteredOut = 0;\n\n for (const file of files) {\n const filePath = path.resolve(this.config.rootDir, file);\n try {\n const descriptor = await this.analyzeFile(filePath);\n if (!descriptor) continue;\n\n // §1+§B: In strict mode, filter out non-screen files\n // Uses actual registerScreen() call detection, not optional metadata fields\n if (this.strictScreens) {\n const hasRegisterScreen = (descriptor as any).__hasRegisterScreen === true;\n const matchesPattern = screenPatternFiles?.has(filePath) ?? false;\n\n if (!hasRegisterScreen && !matchesPattern) {\n this.screensFilteredOut++;\n if (this.verbose) {\n console.log(`[ScreenAnalyzer] ✗ Filtered (strict): ${file}`);\n }\n continue;\n }\n }\n\n screens.push(descriptor);\n if (this.verbose) {\n console.log(`[ScreenAnalyzer] ✓ Analyzed: ${descriptor.name} (${file})`);\n }\n } catch (error) {\n if (this.verbose) {\n console.warn(`[ScreenAnalyzer] Failed to parse ${file}:`, error instanceof Error ? error.message : error);\n }\n // Skip files that fail to parse\n }\n }\n\n if (this.verbose && this.strictScreens) {\n console.log(`[ScreenAnalyzer] Strict mode: ${screens.length} included, ${this.screensFilteredOut} filtered out`);\n }\n\n return screens;\n }\n\n /** Analyze a single file. Returns descriptor + whether registerScreen was found. */\n async analyzeFile(filePath: string): Promise<ScreenDescriptor | null> {\n const source = await fs.readFile(filePath, 'utf-8');\n const name = this.extractScreenName(filePath);\n\n // Parse the file with the shared parser so every extractor sees\n // the same syntax support and parser changes stay centralized.\n const ast = parseSource(source, this.config.parserPlugins as any);\n\n // Extract metadata from registerScreen call\n const registerScreenMeta = this.extractRegisterScreenMetadata(ast);\n\n // §B: Track whether registerScreen() was actually called in this file\n const hasRegisterScreenCall = this.detectRegisterScreenCall(ast);\n\n // Extract component name (default export)\n const componentName = this.extractDefaultComponentName(ast);\n\n // Extract navigation targets from AST\n const navigationTargets = this.extractNavigationTargets(ast);\n\n // Extract forms and fields. registerScreen metadata is the app\n // author's explicit contract, so keep it ahead of JSX inference.\n const forms = this.mergeForms(registerScreenMeta?.forms ?? [], this.extractForms(ast));\n\n // Extract components\n const components = this.extractComponents(ast);\n\n // Extract actions\n const actions = this.extractActions(ast, registerScreenMeta);\n\n // Extract list/collection semantics. This is the static complement\n // to the SDK's runtime list snapshot: it tells the agent what a row\n // represents and what pressing that row is expected to do.\n const collections = this.extractCollections(ast);\n\n // Extract @appilots-permissions / @appilots-pii JSDoc metadata\n // (BACKLOG 2.1). Reads source comments — runs against the raw\n // file text to keep the implementation simple (Babel comment\n // tokens differ between configurations).\n const permissionsFromJsDoc = extractPermissionsFromJsDoc(source);\n\n // BACKLOG 2.2 — `@appilots-destructive <action-id>[, <id>...]`\n // marks specific extracted actions as destructive. Without an\n // arg, marks ALL actions on the screen as destructive (rare,\n // but supported for screens like \"DeleteAccount\").\n const destructiveTags = extractDestructiveJsDocTargets(source);\n if (destructiveTags) {\n for (const action of actions) {\n if (destructiveTags === '*' || destructiveTags.has(action.id)) {\n action.destructive = true;\n }\n }\n }\n\n // Merge registerScreen metadata with AST analysis\n const descriptor: ScreenDescriptor = {\n name: registerScreenMeta?.name || name,\n filePath,\n title: registerScreenMeta?.title,\n description: registerScreenMeta?.description,\n components,\n forms,\n actions,\n navigationTargets,\n ...(collections.length > 0 ? { collections } : {}),\n ...(registerScreenMeta?.suggestedPrompts && registerScreenMeta.suggestedPrompts.length > 0\n ? { suggestedPrompts: registerScreenMeta.suggestedPrompts }\n : {}),\n ...(permissionsFromJsDoc\n ? {\n permissions: permissionsFromJsDoc,\n ...(permissionsFromJsDoc.isPii ? { isPii: true } : {}),\n }\n : {}),\n };\n\n // Attach flag for strict mode filtering (not part of the public type)\n (descriptor as any).__hasRegisterScreen = hasRegisterScreenCall;\n\n return descriptor;\n }\n\n /**\n * §B: Detect actual presence of registerScreen() call in the AST.\n * This is more reliable than checking for title/description which are optional.\n */\n private detectRegisterScreenCall(ast: BabelTypes.File): boolean {\n let found = false;\n\n traverse(ast, {\n CallExpression: (nodePath) => {\n if (found) return;\n const callee = nodePath.node.callee;\n\n if (\n (BabelTypes.isIdentifier(callee) && callee.name === 'registerScreen') ||\n (BabelTypes.isMemberExpression(callee) &&\n BabelTypes.isIdentifier(callee.property) &&\n callee.property.name === 'registerScreen')\n ) {\n found = true;\n nodePath.stop();\n }\n },\n });\n\n return found;\n }\n\n /**\n * Extract metadata from registerScreen() call\n */\n private extractRegisterScreenMetadata(\n ast: BabelTypes.File\n ): Partial<ScreenDescriptor> & { name: string } | null {\n let metadata: Partial<ScreenDescriptor> & { name: string } | null = null;\n\n traverse(ast, {\n CallExpression: (nodePath) => {\n const callee = nodePath.node.callee;\n\n // Check if this is a registerScreen call\n if (\n (BabelTypes.isIdentifier(callee) && callee.name === 'registerScreen') ||\n (BabelTypes.isMemberExpression(callee) &&\n BabelTypes.isIdentifier(callee.property) &&\n callee.property.name === 'registerScreen')\n ) {\n // First argument should be an object expression\n const arg = nodePath.node.arguments[0];\n if (BabelTypes.isObjectExpression(arg)) {\n metadata = this.parseRegisterScreenObject(arg);\n }\n }\n },\n });\n\n return metadata;\n }\n\n /**\n * Parse the object passed to registerScreen()\n */\n private parseRegisterScreenObject(\n objExpr: BabelTypes.ObjectExpression\n ): Partial<ScreenDescriptor> & { name: string } {\n const result: Partial<ScreenDescriptor> & { name: string } = {\n name: '',\n actions: [],\n forms: [],\n navigationTargets: [],\n components: [],\n };\n\n for (const prop of objExpr.properties) {\n if (!BabelTypes.isObjectProperty(prop) && !BabelTypes.isObjectMethod(prop)) {\n continue;\n }\n\n const key = BabelTypes.isIdentifier(prop.key) ? prop.key.name : null;\n if (!key) continue;\n\n if (BabelTypes.isObjectProperty(prop)) {\n const value = prop.value;\n\n if (key === 'name' && BabelTypes.isStringLiteral(value)) {\n result.name = value.value;\n } else if (key === 'title' && BabelTypes.isStringLiteral(value)) {\n result.title = value.value;\n } else if (key === 'description' && BabelTypes.isStringLiteral(value)) {\n result.description = value.value;\n } else if (key === 'actions' && BabelTypes.isArrayExpression(value)) {\n result.actions = this.parseActionsArray(value);\n } else if (key === 'fields' && BabelTypes.isArrayExpression(value)) {\n // Convert fields to forms\n const fields = this.parseFieldsArray(value);\n if (fields.length > 0) {\n result.forms = [\n {\n id: 'default',\n fields,\n },\n ];\n }\n } else if (key === 'suggestedPrompts' && BabelTypes.isArrayExpression(value)) {\n // Each entry must be a static string literal — dynamic values can't\n // be safely inlined into the MCP doc, so they're silently skipped.\n const prompts: string[] = [];\n for (const element of value.elements) {\n if (BabelTypes.isStringLiteral(element)) {\n const trimmed = element.value.trim();\n if (trimmed.length > 0) prompts.push(trimmed);\n }\n }\n if (prompts.length > 0) {\n result.suggestedPrompts = prompts;\n }\n }\n }\n }\n\n return result;\n }\n\n /**\n * Parse actions array from registerScreen\n */\n private parseActionsArray(arr: BabelTypes.ArrayExpression): ActionDescriptor[] {\n const actions: ActionDescriptor[] = [];\n\n for (const element of arr.elements) {\n if (BabelTypes.isObjectExpression(element)) {\n const action = this.parseActionObject(element);\n if (action.id) {\n actions.push(action);\n }\n }\n }\n\n return actions;\n }\n\n /**\n * Parse a single action object\n */\n private parseActionObject(obj: BabelTypes.ObjectExpression): ActionDescriptor {\n const action: ActionDescriptor = {\n id: '',\n type: 'custom',\n };\n\n for (const prop of obj.properties) {\n if (!BabelTypes.isObjectProperty(prop)) continue;\n\n const key = BabelTypes.isIdentifier(prop.key) ? prop.key.name : null;\n if (!key) continue;\n\n const value = prop.value;\n\n if (key === 'id' && BabelTypes.isStringLiteral(value)) {\n action.id = value.value;\n } else if (key === 'label' && BabelTypes.isStringLiteral(value)) {\n action.label = value.value;\n } else if (key === 'type' && BabelTypes.isStringLiteral(value)) {\n action.type = (value.value as any) || 'custom';\n } else if (key === 'targetScreen' && BabelTypes.isStringLiteral(value)) {\n action.targetScreen = value.value;\n } else if (key === 'description' && BabelTypes.isStringLiteral(value)) {\n action.description = value.value;\n } else if (key === 'handler' && BabelTypes.isStringLiteral(value)) {\n action.handler = value.value;\n } else if (key === 'requiresConfirmation' && BabelTypes.isBooleanLiteral(value)) {\n action.requiresConfirmation = value.value;\n } else if (key === 'destructive' && BabelTypes.isBooleanLiteral(value)) {\n action.destructive = value.value;\n } else if (key === 'effect' && BabelTypes.isStringLiteral(value)) {\n action.effect = value.value;\n } else if (key === 'riskLevel' && BabelTypes.isStringLiteral(value)) {\n action.riskLevel = value.value;\n } else if (key === 'nativeConfirmationExpected' && BabelTypes.isBooleanLiteral(value)) {\n action.nativeConfirmationExpected = value.value;\n } else if (key === 'appilotsInferred' && BabelTypes.isObjectExpression(value)) {\n action.appilotsInferred = this.parseAppilotsInferredObject(value);\n }\n }\n\n return action;\n }\n\n private parseAppilotsInferredObject(obj: BabelTypes.ObjectExpression): AppilotsInferredAction {\n const out: AppilotsInferredAction = {};\n for (const prop of obj.properties) {\n if (!BabelTypes.isObjectProperty(prop)) continue;\n const key = BabelTypes.isIdentifier(prop.key) ? prop.key.name : null;\n if (!key) continue;\n const value = prop.value;\n if (key === 'isAsyncTrigger' && BabelTypes.isBooleanLiteral(value)) {\n out.isAsyncTrigger = value.value;\n } else if (key === 'expectedOutcome' && BabelTypes.isStringLiteral(value)) {\n out.expectedOutcome = value.value as AppilotsInferredAction['expectedOutcome'];\n } else if (key === 'loadingStateBindings' && BabelTypes.isArrayExpression(value)) {\n out.loadingStateBindings = value.elements\n .filter((el): el is BabelTypes.StringLiteral => BabelTypes.isStringLiteral(el))\n .map((el) => el.value);\n }\n }\n return out;\n }\n\n /**\n * Parse fields array from registerScreen\n */\n private parseFieldsArray(arr: BabelTypes.ArrayExpression): FormFieldDescriptor[] {\n const fields: FormFieldDescriptor[] = [];\n\n for (const element of arr.elements) {\n if (BabelTypes.isObjectExpression(element)) {\n const field = this.parseFieldObject(element);\n if (field.name) {\n fields.push(field);\n }\n }\n }\n\n return fields;\n }\n\n /**\n * Parse a single field object\n */\n private parseFieldObject(obj: BabelTypes.ObjectExpression): FormFieldDescriptor {\n const field: FormFieldDescriptor = {\n name: '',\n type: 'text',\n required: false,\n };\n\n for (const prop of obj.properties) {\n if (!BabelTypes.isObjectProperty(prop)) continue;\n\n const key = BabelTypes.isIdentifier(prop.key) ? prop.key.name : null;\n if (!key) continue;\n\n const value = prop.value;\n\n if (key === 'id' && BabelTypes.isStringLiteral(value)) {\n field.name = value.value;\n } else if (key === 'label' && BabelTypes.isStringLiteral(value)) {\n field.label = value.value;\n } else if (key === 'type' && BabelTypes.isStringLiteral(value)) {\n field.type = (value.value as any) || 'text';\n } else if (key === 'required' && BabelTypes.isBooleanLiteral(value)) {\n field.required = value.value;\n } else if (key === 'placeholder' && BabelTypes.isStringLiteral(value)) {\n field.placeholder = value.value;\n } else if (key === 'defaultValue' && BabelTypes.isExpression(value)) {\n field.defaultValue = this.extractLiteralValue(value);\n } else if (key === 'options' && BabelTypes.isArrayExpression(value)) {\n field.options = this.parseOptionsArray(value);\n }\n }\n\n return field;\n }\n\n /**\n * Parse options array for select fields\n */\n private parseOptionsArray(arr: BabelTypes.ArrayExpression): { label: string; value: string }[] {\n const options: { label: string; value: string }[] = [];\n\n for (const element of arr.elements) {\n if (BabelTypes.isObjectExpression(element)) {\n let label = '';\n let value = '';\n\n for (const prop of element.properties) {\n if (!BabelTypes.isObjectProperty(prop)) continue;\n\n const key = BabelTypes.isIdentifier(prop.key) ? prop.key.name : null;\n if (!key) continue;\n\n if (key === 'label' && BabelTypes.isStringLiteral(prop.value)) {\n label = prop.value.value;\n } else if (key === 'value' && BabelTypes.isStringLiteral(prop.value)) {\n value = prop.value.value;\n }\n }\n\n if (label && value) {\n options.push({ label, value });\n }\n }\n }\n\n return options;\n }\n\n private mergeForms(primary: FormDescriptor[], secondary: FormDescriptor[]): FormDescriptor[] {\n const out: FormDescriptor[] = primary.map((form) => ({\n ...form,\n fields: [...form.fields],\n }));\n\n for (const form of secondary) {\n const existing =\n out.find((candidate) => candidate.id === form.id) ??\n this.findFormWithSharedFields(out, form);\n if (!existing) {\n out.push({ ...form, fields: [...form.fields], submitAction: this.namedSubmitAction(form.submitAction) });\n continue;\n }\n\n for (const field of form.fields) {\n const existingField = this.findEquivalentField(existing.fields, field);\n if (existingField) {\n this.mergeFieldMetadata(existingField, field);\n } else {\n existing.fields.push(field);\n }\n }\n existing.submitAction = existing.submitAction ?? this.namedSubmitAction(form.submitAction);\n existing.validationRules = form.validationRules\n ? { ...form.validationRules, ...(existing.validationRules ?? {}) }\n : existing.validationRules;\n }\n\n return out;\n }\n\n private findEquivalentField(\n fields: FormFieldDescriptor[],\n incoming: FormFieldDescriptor,\n ): FormFieldDescriptor | undefined {\n return fields.find((field) => {\n if (field.name && incoming.name && field.name === incoming.name) return true;\n if (field.valueBinding && incoming.valueBinding && field.valueBinding === incoming.valueBinding) return true;\n if (field.locator?.id && incoming.locator?.id && field.locator.id === incoming.locator.id) return true;\n if (field.placeholder && incoming.placeholder && field.placeholder === incoming.placeholder) return true;\n if (\n field.locator?.accessibilityLabel &&\n incoming.locator?.accessibilityLabel &&\n field.locator.accessibilityLabel === incoming.locator.accessibilityLabel\n ) {\n return true;\n }\n return false;\n });\n }\n\n private namedSubmitAction(submitAction: string | undefined): string | undefined {\n return submitAction && submitAction !== 'anonymous' ? submitAction : undefined;\n }\n\n private mergeFieldMetadata(target: FormFieldDescriptor, source: FormFieldDescriptor): void {\n if (this.isWeakInferredFieldName(target.name) && !this.isWeakInferredFieldName(source.name)) {\n target.name = source.name;\n }\n target.label = target.label ?? source.label;\n target.placeholder = target.placeholder ?? source.placeholder;\n target.options = target.options ?? source.options;\n target.locator = target.locator ?? source.locator;\n if (target.locator && source.locator) {\n target.locator = this.mergeLocator(source.locator, target.locator);\n }\n target.sourceComponent = target.sourceComponent ?? source.sourceComponent;\n target.valueBinding = target.valueBinding ?? source.valueBinding;\n target.errorBinding = target.errorBinding ?? source.errorBinding;\n target.required = target.required || source.required;\n if (target.type === 'text' && source.type !== 'text') {\n target.type = source.type;\n }\n }\n\n private findFormWithSharedFields(\n forms: FormDescriptor[],\n incoming: FormDescriptor,\n ): FormDescriptor | undefined {\n if (incoming.fields.length === 0) return undefined;\n\n let best: { form: FormDescriptor; overlap: number } | undefined;\n for (const form of forms) {\n const overlap = incoming.fields.filter((field) =>\n this.findEquivalentField(form.fields, field),\n ).length;\n if (overlap > 0 && (!best || overlap > best.overlap)) {\n best = { form, overlap };\n }\n }\n\n return best?.form;\n }\n\n /**\n * Extract the name of the default exported component\n */\n private extractDefaultComponentName(ast: BabelTypes.File): string {\n let componentName = '';\n\n traverse(ast, {\n ExportDefaultDeclaration: (nodePath) => {\n const declaration = nodePath.node.declaration;\n\n if (BabelTypes.isFunctionDeclaration(declaration) && declaration.id?.name) {\n componentName = declaration.id.name;\n } else if (BabelTypes.isArrowFunctionExpression(declaration)) {\n // Arrow function export - try to get from parent variable declaration\n componentName = 'Component';\n }\n },\n VariableDeclarator: (nodePath) => {\n if (\n BabelTypes.isIdentifier(nodePath.node.id) &&\n (BabelTypes.isArrowFunctionExpression(nodePath.node.init) ||\n BabelTypes.isFunctionExpression(nodePath.node.init))\n ) {\n // Check if this is exported\n const parent = nodePath.parent;\n if (\n BabelTypes.isVariableDeclaration(parent) &&\n parent.declare === true\n ) {\n componentName = nodePath.node.id.name;\n }\n }\n },\n });\n\n return componentName;\n }\n\n /**\n * Extract navigation targets from navigation.navigate() calls\n */\n private extractNavigationTargets(ast: BabelTypes.File): string[] {\n const targets = new Set<string>();\n\n traverse(ast, {\n CallExpression: (nodePath) => {\n const callee = nodePath.node.callee;\n\n // Match navigation.navigate('ScreenName') pattern\n if (\n BabelTypes.isMemberExpression(callee) &&\n BabelTypes.isIdentifier(callee.object) &&\n callee.object.name === 'navigation' &&\n BabelTypes.isIdentifier(callee.property) &&\n callee.property.name === 'navigate'\n ) {\n const arg = nodePath.node.arguments[0];\n if (BabelTypes.isStringLiteral(arg)) {\n targets.add(arg.value);\n }\n }\n },\n });\n\n return Array.from(targets).sort();\n }\n\n /**\n * Extract form information from JSX\n */\n private extractForms(ast: BabelTypes.File): FormDescriptor[] {\n const forms: FormDescriptor[] = [];\n const fields = new Map<string, FormFieldDescriptor>();\n\n traverse(ast, {\n JSXOpeningElement: (nodePath) => {\n const element = nodePath.node;\n\n if (BabelTypes.isJSXIdentifier(element.name)) {\n const componentName = element.name.name;\n\n // Detect native inputs and custom form controls by their prop\n // contract, not by app-specific component names.\n const role = classifyJsxComponent(componentName, element);\n if (['input', 'select', 'toggle', 'date'].includes(role)) {\n const field = this.extractFieldFromInputElement(element);\n if (field.name) {\n fields.set(field.name, field);\n }\n }\n }\n },\n });\n\n // Create a default form if we found any fields\n if (fields.size > 0) {\n forms.push({\n id: 'default',\n fields: Array.from(fields.values()),\n });\n }\n\n return forms;\n }\n\n /**\n * Extract field metadata from a TextInput/Input element\n */\n private extractFieldFromInputElement(element: BabelTypes.JSXOpeningElement): FormFieldDescriptor {\n const field: FormFieldDescriptor = {\n name: '',\n type: 'text',\n required: false,\n };\n const componentName = BabelTypes.isJSXIdentifier(element.name) ? element.name.name : '';\n const role = componentName ? classifyJsxComponent(componentName, element) : 'custom';\n field.sourceComponent = componentName || undefined;\n\n for (const attr of element.attributes) {\n if (!BabelTypes.isJSXAttribute(attr)) continue;\n\n const attrName = BabelTypes.isJSXIdentifier(attr.name) ? attr.name.name : null;\n if (!attrName) continue;\n\n if (attr.value) {\n if (BabelTypes.isStringLiteral(attr.value)) {\n if (attrName === 'placeholder') {\n field.placeholder = attr.value.value;\n } else if (attrName === 'appilotsId') {\n field.name = attr.value.value;\n field.locator = this.mergeLocator(field.locator, {\n id: attr.value.value,\n appilotsId: attr.value.value,\n source: 'appilotsId',\n });\n } else if (attrName === 'testID') {\n // Use testID to derive field name if not set\n if (!field.name) {\n field.name = attr.value.value.replace(/^(input-|field-|txt-)/, '');\n }\n field.locator = this.mergeLocator(field.locator, {\n id: field.name || attr.value.value,\n testID: attr.value.value,\n source: 'testID',\n });\n } else if (attrName === 'label') {\n field.label = attr.value.value;\n } else if (attrName === 'accessibilityLabel') {\n if (!field.label) field.label = attr.value.value;\n field.locator = this.mergeLocator(field.locator, {\n ...(field.locator?.id ? {} : { id: this.slugifyActionId(attr.value.value) }),\n accessibilityLabel: attr.value.value,\n source: field.locator?.source ?? 'accessibilityLabel',\n });\n } else if (attrName === 'keyboardType') {\n if (attr.value.value === 'email-address' || attr.value.value === 'email') field.type = 'email';\n if (attr.value.value === 'phone-pad') field.type = 'phone';\n if (attr.value.value === 'numeric' || attr.value.value === 'number-pad') field.type = 'number';\n }\n } else if (BabelTypes.isJSXExpressionContainer(attr.value)) {\n // Handle dynamic attributes\n if (attrName === 'value' && BabelTypes.isIdentifier(attr.value.expression)) {\n // Try to infer field name from variable name\n if (!field.name) {\n field.name = attr.value.expression.name;\n }\n field.valueBinding = attr.value.expression.name;\n } else if (attrName === 'checked' && BabelTypes.isIdentifier(attr.value.expression)) {\n if (!field.name) field.name = attr.value.expression.name;\n field.valueBinding = attr.value.expression.name;\n } else if (attrName === 'error') {\n field.errorBinding = this.expressionToBinding(attr.value.expression);\n } else if (attrName === 'required' && BabelTypes.isBooleanLiteral(attr.value.expression)) {\n field.required = attr.value.expression.value;\n }\n }\n } else if (attrName === 'required') {\n field.required = true;\n }\n }\n\n if (role === 'select') field.type = 'select';\n if (role === 'toggle') field.type = 'toggle';\n if (role === 'date') field.type = 'date';\n if (!field.name || this.isWeakInferredFieldName(field.name)) {\n const label = field.locator?.accessibilityLabel ?? field.label ?? field.placeholder;\n if (label) field.name = this.slugifyActionId(label);\n }\n if (!field.locator && field.name) {\n field.locator = { id: field.name, label: field.label, source: 'inferred' };\n } else if (field.locator && !field.locator.id && field.name) {\n field.locator = this.mergeLocator(field.locator, {\n id: field.name,\n label: field.label,\n source: field.locator.source ?? 'inferred',\n });\n }\n\n return field;\n }\n\n private isWeakInferredFieldName(name: string): boolean {\n return /^(text|value|input|query|search|selected|checked)$/i.test(name);\n }\n\n /**\n * Extract component structure from JSX\n */\n private extractComponents(ast: BabelTypes.File): ComponentDescriptor[] {\n const components: ComponentDescriptor[] = [];\n const seen = new Set<string>();\n\n traverse(ast, {\n JSXOpeningElement: (nodePath) => {\n const element = nodePath.node;\n\n if (BabelTypes.isJSXIdentifier(element.name)) {\n const componentName = element.name.name;\n\n if (seen.has(componentName)) return;\n seen.add(componentName);\n\n const type = this.inferComponentType(componentName);\n const component: ComponentDescriptor = {\n name: componentName,\n type,\n };\n\n // Extract testID and accessibilityLabel\n for (const attr of element.attributes) {\n if (!BabelTypes.isJSXAttribute(attr)) continue;\n\n const attrName = BabelTypes.isJSXIdentifier(attr.name) ? attr.name.name : null;\n if (!attrName) continue;\n\n if (attr.value && BabelTypes.isStringLiteral(attr.value)) {\n if (attrName === 'testID') {\n component.testID = attr.value.value;\n } else if (attrName === 'accessibilityLabel') {\n component.accessibilityLabel = attr.value.value;\n }\n }\n }\n\n components.push(component);\n }\n },\n });\n\n return components;\n }\n\n /**\n * Infer component type from component name\n */\n private inferComponentType(name: string): ComponentDescriptor['type'] {\n const role = classifyJsxComponent(name);\n if (role === 'select' || role === 'toggle' || role === 'date') {\n return 'input';\n }\n if (role === 'input') {\n return 'input';\n }\n if (role === 'button') {\n return 'button';\n }\n if (role === 'list') {\n return 'list';\n }\n if (role === 'modal') {\n return 'modal';\n }\n if (role === 'view') {\n return 'view';\n }\n return 'custom';\n }\n\n /**\n * Extract actions from button/touchable elements\n */\n private extractActions(\n ast: BabelTypes.File,\n registerScreenMeta: Partial<ScreenDescriptor> & { name: string } | null\n ): ActionDescriptor[] {\n // Start with actions from registerScreen if available\n const actions = [...(registerScreenMeta?.actions || [])];\n const actionIds = new Set(actions.map((a) => a.id));\n const actionLabels = new Map(\n actions\n .filter((a) => a.label)\n .map((a) => [this.normalizeLabel(a.label!), a] as const),\n );\n\n // Extract additional actions from JSX buttons/touchables\n traverse(ast, {\n JSXOpeningElement: (nodePath) => {\n const element = nodePath.node;\n\n if (BabelTypes.isJSXIdentifier(element.name)) {\n const componentName = element.name.name;\n\n if (classifyJsxComponent(componentName, element) === 'button') {\n const action = this.extractActionFromButton(element);\n const existingByLabel = action.label\n ? actionLabels.get(this.normalizeLabel(action.label))\n : undefined;\n if (existingByLabel) {\n this.mergeActionMetadata(existingByLabel, action);\n return;\n }\n if (action.id && !actionIds.has(action.id)) {\n actions.push(action);\n actionIds.add(action.id);\n if (action.label) actionLabels.set(this.normalizeLabel(action.label), action);\n }\n }\n }\n },\n });\n\n this.enrichActionsFromHandlers(ast, actions);\n\n return actions;\n }\n\n private normalizeLabel(label: string): string {\n return label\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '');\n }\n\n private mergeActionMetadata(target: ActionDescriptor, source: ActionDescriptor): void {\n target.handler = target.handler ?? source.handler;\n target.targetScreen = target.targetScreen ?? source.targetScreen;\n target.description = target.description ?? source.description;\n target.nativeConfirmationExpected =\n target.nativeConfirmationExpected || source.nativeConfirmationExpected || undefined;\n target.requiresConfirmation =\n target.requiresConfirmation || source.requiresConfirmation || undefined;\n target.destructive = target.destructive || source.destructive || undefined;\n target.effect = target.effect ?? source.effect;\n target.riskLevel = target.riskLevel ?? source.riskLevel;\n target.appilotsInferred = target.appilotsInferred ?? source.appilotsInferred;\n }\n\n private enrichActionsFromHandlers(ast: BabelTypes.File, actions: ActionDescriptor[]): void {\n const handlerMap = this.collectHandlerInfo(ast);\n const labelToHandler = this.collectButtonHandlersByLabel(ast);\n\n for (const action of actions) {\n if (!action.handler && action.label) {\n const handler = labelToHandler.get(action.label);\n if (handler) action.handler = handler;\n }\n\n const handler = action.handler ? handlerMap.get(action.handler) : undefined;\n if (!handler) continue;\n\n action.appilotsInferred = {\n ...(action.appilotsInferred ?? {}),\n ...handler.appilotsInferred,\n };\n if (handler.nativeConfirmationExpected) action.nativeConfirmationExpected = true;\n if (handler.targetScreen && !action.targetScreen) action.targetScreen = handler.targetScreen;\n if (handler.successSignal && !action.successSignal) action.successSignal = handler.successSignal;\n if (handler.failureSignal && !action.failureSignal) action.failureSignal = handler.failureSignal;\n if (handler.opensModal && !action.opensModal) action.opensModal = handler.opensModal;\n if (\n handler.destructive ||\n action.destructive === true ||\n action.requiresConfirmation === true ||\n action.effect === 'destructive' ||\n action.riskLevel === 'high'\n ) {\n action.destructive = true;\n action.effect = action.effect ?? 'destructive';\n action.riskLevel = action.riskLevel ?? 'high';\n action.requiresConfirmation = action.requiresConfirmation ?? true;\n }\n }\n }\n\n private collectButtonHandlersByLabel(ast: BabelTypes.File): Map<string, string> {\n const out = new Map<string, string>();\n traverse(ast, {\n JSXOpeningElement: (nodePath) => {\n const element = nodePath.node;\n if (!BabelTypes.isJSXIdentifier(element.name)) return;\n const componentName = element.name.name;\n if (classifyJsxComponent(componentName, element) !== 'button') return;\n\n let label: string | undefined;\n let handler: string | undefined;\n for (const attr of element.attributes) {\n if (!BabelTypes.isJSXAttribute(attr)) continue;\n const attrName = BabelTypes.isJSXIdentifier(attr.name) ? attr.name.name : null;\n if (!attrName || !attr.value) continue;\n if (\n (attrName === 'title' || attrName === 'accessibilityLabel' || attrName === 'label') &&\n BabelTypes.isStringLiteral(attr.value)\n ) {\n label = attr.value.value;\n }\n if (\n attrName === 'onPress' &&\n BabelTypes.isJSXExpressionContainer(attr.value) &&\n BabelTypes.isIdentifier(attr.value.expression)\n ) {\n handler = attr.value.expression.name;\n }\n }\n if (label && handler) out.set(label, handler);\n },\n });\n return out;\n }\n\n private collectHandlerInfo(ast: BabelTypes.File): Map<string, {\n appilotsInferred: AppilotsInferredAction;\n destructive: boolean;\n nativeConfirmationExpected: boolean;\n targetScreen?: string;\n successSignal?: import('../types').SignalDescriptor;\n failureSignal?: import('../types').SignalDescriptor;\n opensModal?: string;\n }> {\n const handlers = collectFunctions(ast);\n\n const out = new Map<string, {\n appilotsInferred: AppilotsInferredAction;\n destructive: boolean;\n nativeConfirmationExpected: boolean;\n targetScreen?: string;\n successSignal?: import('../types').SignalDescriptor;\n failureSignal?: import('../types').SignalDescriptor;\n opensModal?: string;\n }>();\n\n for (const [name, fn] of handlers) {\n const info = analyzeFunctionBehavior(name, fn, handlers);\n out.set(name, info);\n }\n\n return out;\n }\n\n private analyzeHandlerFunction(\n name: string,\n fn: BabelTypes.Function,\n handlers: Map<string, BabelTypes.Function>,\n seen = new Set<string>(),\n ): {\n appilotsInferred: AppilotsInferredAction;\n destructive: boolean;\n nativeConfirmationExpected: boolean;\n targetScreen?: string;\n } {\n if (seen.has(name)) {\n return {\n appilotsInferred: { expectedOutcome: 'none' },\n destructive: false,\n nativeConfirmationExpected: false,\n };\n }\n seen.add(name);\n\n let hasAwait = fn.async === true;\n let hasThen = false;\n let hasStateSetter = false;\n let nativeConfirmationExpected = false;\n let targetScreen: string | undefined;\n let destructive = /(delete|destroy|remove|discard|wipe|drop|terminate)/i.test(name);\n\n const inspectNode = (node: BabelTypes.Node) => {\n if (BabelTypes.isAwaitExpression(node)) hasAwait = true;\n if (\n BabelTypes.isCallExpression(node) &&\n BabelTypes.isMemberExpression(node.callee) &&\n BabelTypes.isIdentifier(node.callee.property)\n ) {\n const method = node.callee.property.name;\n if (method === 'then' || method === 'catch' || method === 'finally') hasThen = true;\n if (\n BabelTypes.isIdentifier(node.callee.object) &&\n node.callee.object.name === 'navigation' &&\n ['navigate', 'push', 'replace'].includes(method)\n ) {\n const firstArg = node.arguments[0];\n if (BabelTypes.isStringLiteral(firstArg)) targetScreen = firstArg.value;\n }\n if (\n BabelTypes.isIdentifier(node.callee.object) &&\n node.callee.object.name === 'Alert' &&\n method === 'alert'\n ) {\n nativeConfirmationExpected = true;\n }\n }\n if (BabelTypes.isCallExpression(node) && BabelTypes.isIdentifier(node.callee)) {\n const calleeName = node.callee.name;\n if (/^set[A-Z]/.test(calleeName)) hasStateSetter = true;\n if (/(delete|destroy|remove|discard|wipe|drop|terminate)/i.test(calleeName)) {\n destructive = true;\n }\n const nested = handlers.get(calleeName);\n if (nested) {\n const nestedInfo = this.analyzeHandlerFunction(calleeName, nested, handlers, seen);\n hasAwait = hasAwait || nestedInfo.appilotsInferred.isAsyncTrigger === true;\n nativeConfirmationExpected ||= nestedInfo.nativeConfirmationExpected;\n destructive ||= nestedInfo.destructive;\n targetScreen = targetScreen ?? nestedInfo.targetScreen;\n }\n }\n if (\n BabelTypes.isMemberExpression(node) &&\n BabelTypes.isIdentifier(node.property) &&\n /(delete|destroy|remove|discard|wipe|drop|terminate)/i.test(node.property.name)\n ) {\n destructive = true;\n }\n };\n\n if (fn.body) {\n traverse(fn.body as any, {\n noScope: true,\n enter: (nodePath: any) => inspectNode(nodePath.node),\n } as any);\n }\n\n const expectedOutcome: AppilotsInferredAction['expectedOutcome'] = targetScreen\n ? 'navigation'\n : hasStateSetter\n ? 'inline-feedback'\n : hasAwait || hasThen\n ? 'mixed'\n : 'none';\n\n return {\n appilotsInferred: {\n isAsyncTrigger: hasAwait || hasThen || undefined,\n expectedOutcome,\n },\n destructive,\n nativeConfirmationExpected,\n targetScreen,\n };\n }\n\n /**\n * BACKLOG 2.2 — heuristic destructive detection.\n *\n * Combines several signals:\n * - JSX `destructive` boolean prop (`<Pressable destructive />`)\n * - JSX `aria-destructive` attribute\n * - Handler name contains a generic destructive verb\n * (delete/destroy/remove/discard/wipe/revoke/etc.). `cancel` is intentionally excluded —\n * too many \"Cancelar\" buttons that just dismiss modals.\n * - testID / id contains a destructive verb\n *\n * Default-allow with explicit opt-out via `@appilots-non-destructive`\n * is more dangerous than the inverse, so we default-deny: the\n * heuristic must hit OR the JSDoc tag must be present.\n */\n private isElementDestructive(\n element: BabelTypes.JSXOpeningElement,\n handlerName: string | undefined,\n actionId: string | undefined,\n ): boolean {\n const DESTRUCTIVE_VERB =\n /(delete|destroy|remove|discard|wipe|erase|drop|terminate|revoke|deactivate|disable)/i;\n\n // Explicit JSX prop wins.\n for (const attr of element.attributes) {\n if (!BabelTypes.isJSXAttribute(attr)) continue;\n const attrName = BabelTypes.isJSXIdentifier(attr.name) ? attr.name.name : null;\n if (attrName === 'destructive' || attrName === 'aria-destructive') {\n // <Btn destructive /> (no value) is true; <Btn destructive={false} />\n // turns it off.\n if (attr.value === null) return true;\n if (BabelTypes.isJSXExpressionContainer(attr.value)) {\n const expr = attr.value.expression;\n if (BabelTypes.isBooleanLiteral(expr)) return expr.value;\n }\n if (BabelTypes.isStringLiteral(attr.value)) {\n return attr.value.value === 'true';\n }\n }\n }\n\n if (handlerName && DESTRUCTIVE_VERB.test(handlerName)) return true;\n if (actionId && DESTRUCTIVE_VERB.test(actionId)) return true;\n\n return false;\n }\n\n /**\n * Extract action metadata from a button element\n */\n private extractActionFromButton(element: BabelTypes.JSXOpeningElement): ActionDescriptor {\n const action: ActionDescriptor = {\n id: '',\n type: 'custom',\n };\n const componentName = BabelTypes.isJSXIdentifier(element.name) ? element.name.name : undefined;\n action.sourceComponent = componentName;\n let handlerName: string | undefined;\n\n for (const attr of element.attributes) {\n if (!BabelTypes.isJSXAttribute(attr)) continue;\n\n const attrName = BabelTypes.isJSXIdentifier(attr.name) ? attr.name.name : null;\n if (!attrName) continue;\n\n if (attr.value) {\n if (BabelTypes.isStringLiteral(attr.value)) {\n if (attrName === 'appilotsId') {\n action.id = attr.value.value;\n action.locator = this.mergeLocator(action.locator, {\n id: attr.value.value,\n appilotsId: attr.value.value,\n source: 'appilotsId',\n });\n } else if (attrName === 'testID') {\n action.id = attr.value.value;\n action.locator = this.mergeLocator(action.locator, {\n id: attr.value.value,\n testID: attr.value.value,\n source: 'testID',\n });\n } else if (attrName === 'title' || attrName === 'label' || attrName === 'accessibilityLabel') {\n action.label = attr.value.value;\n if (attrName === 'accessibilityLabel') {\n action.locator = this.mergeLocator(action.locator, {\n accessibilityLabel: attr.value.value,\n source: 'accessibilityLabel',\n });\n }\n if (!action.id) {\n action.id = this.slugifyActionId(attr.value.value);\n }\n }\n } else if (BabelTypes.isJSXExpressionContainer(attr.value)) {\n if (attrName === 'onPress' && BabelTypes.isIdentifier(attr.value.expression)) {\n // Infer action type from handler name\n handlerName = attr.value.expression.name.toLowerCase();\n action.handler = attr.value.expression.name;\n if (handlerName.includes('submit')) {\n action.type = 'submit';\n } else if (handlerName.includes('navigate')) {\n action.type = 'navigation';\n }\n } else if (attrName === 'onPress') {\n const inline = this.extractInlineOnPressMetadata(attr.value.expression);\n if (inline.handler) {\n handlerName = inline.handler.toLowerCase();\n action.handler = inline.handler;\n if (handlerName.includes('submit')) action.type = 'submit';\n }\n if (inline.targetScreen) {\n action.type = 'navigation';\n action.targetScreen = inline.targetScreen;\n }\n } else if (attrName === 'loading' && BabelTypes.isIdentifier(attr.value.expression)) {\n action.appilotsInferred = {\n ...(action.appilotsInferred ?? {}),\n isAsyncTrigger: true,\n loadingStateBindings: [attr.value.expression.name],\n };\n }\n }\n } else if (attrName === 'destructive') {\n action.destructive = true;\n }\n }\n\n if (!action.locator && action.id) {\n action.locator = { id: action.id, label: action.label, source: action.label ? 'label' : 'inferred' };\n }\n\n // BACKLOG 2.2 — flag the action as destructive if the heuristic\n // detects it. Persists into the MCP doc so the runtime doesn't\n // need to re-derive on every request.\n if (this.isElementDestructive(element, handlerName, action.id)) {\n action.destructive = true;\n }\n\n return action;\n }\n\n private extractInlineOnPressMetadata(\n expr: BabelTypes.Expression | BabelTypes.JSXEmptyExpression,\n ): Pick<ActionDescriptor, 'handler' | 'targetScreen'> {\n if (BabelTypes.isJSXEmptyExpression(expr)) return {};\n const navCall = extractNavigationCalls(expr).find((call) => call.targetScreen);\n const handler = this.extractFirstHandlerName(expr);\n return {\n ...(handler ? { handler } : {}),\n ...(navCall?.targetScreen ? { targetScreen: navCall.targetScreen } : {}),\n };\n }\n\n private extractFirstHandlerName(node: BabelTypes.Node): string | undefined {\n if (BabelTypes.isIdentifier(node)) return node.name;\n if (BabelTypes.isArrowFunctionExpression(node) || BabelTypes.isFunctionExpression(node)) {\n return this.extractFirstHandlerName(node.body);\n }\n if (BabelTypes.isBlockStatement(node)) {\n for (const statement of node.body) {\n const handler = this.extractFirstHandlerName(statement);\n if (handler) return handler;\n }\n return undefined;\n }\n if (BabelTypes.isExpressionStatement(node)) {\n return this.extractFirstHandlerName(node.expression);\n }\n if (BabelTypes.isReturnStatement(node)) {\n return node.argument ? this.extractFirstHandlerName(node.argument) : undefined;\n }\n if (BabelTypes.isUnaryExpression(node)) {\n return this.extractFirstHandlerName(node.argument);\n }\n if (BabelTypes.isAwaitExpression(node)) {\n return this.extractFirstHandlerName(node.argument);\n }\n if (BabelTypes.isCallExpression(node)) {\n if (BabelTypes.isIdentifier(node.callee)) return node.callee.name;\n return undefined;\n }\n return undefined;\n }\n\n private mergeLocator(\n current: LocatorDescriptor | undefined,\n next: LocatorDescriptor,\n ): LocatorDescriptor {\n return { ...(current ?? {}), ...next };\n }\n\n private expressionToBinding(expr: BabelTypes.Expression | BabelTypes.JSXEmptyExpression): string | undefined {\n if (BabelTypes.isIdentifier(expr)) return expr.name;\n if (\n BabelTypes.isMemberExpression(expr) &&\n BabelTypes.isIdentifier(expr.object) &&\n BabelTypes.isIdentifier(expr.property)\n ) {\n return `${expr.object.name}.${expr.property.name}`;\n }\n return undefined;\n }\n\n private slugifyActionId(label: string): string {\n return label\n .toLowerCase()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n }\n\n private extractCollections(ast: BabelTypes.File): CollectionDescriptor[] {\n const renderItemFns = this.collectRenderItemFunctions(ast);\n const collections: CollectionDescriptor[] = [];\n\n traverse(ast, {\n JSXOpeningElement: (nodePath) => {\n const element = nodePath.node;\n if (!BabelTypes.isJSXIdentifier(element.name)) return;\n const component = element.name.name;\n if (!['FlatList', 'SectionList', 'VirtualizedList', 'FlashList'].includes(component)) {\n return;\n }\n\n const dataSource = this.jsxExpressionIdentifier(element, 'data');\n const renderItem = this.jsxExpressionIdentifier(element, 'renderItem');\n const keyField = this.extractKeyField(element);\n const renderFn = renderItem ? renderItemFns.get(renderItem) : undefined;\n const rowAction = renderFn ? this.extractRowAction(renderFn) : undefined;\n const displayFields = renderFn ? this.extractItemFields(renderFn) : [];\n const itemType = this.inferItemType(dataSource, renderItem, displayFields);\n const identityFields = this.inferIdentityFields(keyField, displayFields);\n const searchField = this.inferSearchField(ast, dataSource);\n\n const id = dataSource ?? renderItem ?? `${component.toLowerCase()}-${collections.length + 1}`;\n collections.push({\n id,\n component,\n ...(itemType ? { itemType } : {}),\n ...(dataSource ? { dataSource } : {}),\n ...(keyField ? { keyField } : {}),\n ...(renderItem ? { renderItem } : {}),\n ...(displayFields.length > 0 ? { displayFields } : {}),\n ...(rowAction ? { rowAction } : {}),\n ...(rowAction ? { rowActions: [rowAction] } : {}),\n ...(identityFields.length > 0 ? { identityFields } : {}),\n ...(searchField ? { searchField } : {}),\n });\n },\n });\n\n return collections;\n }\n\n private collectRenderItemFunctions(ast: BabelTypes.File): Map<string, BabelTypes.Function> {\n const out = new Map<string, BabelTypes.Function>();\n traverse(ast, {\n VariableDeclarator: (nodePath) => {\n if (!BabelTypes.isIdentifier(nodePath.node.id)) return;\n const init = nodePath.node.init;\n if (\n BabelTypes.isArrowFunctionExpression(init) ||\n BabelTypes.isFunctionExpression(init)\n ) {\n out.set(nodePath.node.id.name, init);\n }\n },\n FunctionDeclaration: (nodePath) => {\n if (nodePath.node.id?.name) out.set(nodePath.node.id.name, nodePath.node);\n },\n });\n return out;\n }\n\n private jsxExpressionIdentifier(\n element: BabelTypes.JSXOpeningElement,\n attrName: string,\n ): string | undefined {\n const attr = element.attributes.find((candidate) =>\n BabelTypes.isJSXAttribute(candidate) &&\n BabelTypes.isJSXIdentifier(candidate.name) &&\n candidate.name.name === attrName,\n );\n if (!BabelTypes.isJSXAttribute(attr) || !attr.value) return undefined;\n if (\n BabelTypes.isJSXExpressionContainer(attr.value) &&\n BabelTypes.isIdentifier(attr.value.expression)\n ) {\n return attr.value.expression.name;\n }\n if (BabelTypes.isStringLiteral(attr.value)) return attr.value.value;\n return undefined;\n }\n\n private extractKeyField(element: BabelTypes.JSXOpeningElement): string | undefined {\n const attr = element.attributes.find((candidate) =>\n BabelTypes.isJSXAttribute(candidate) &&\n BabelTypes.isJSXIdentifier(candidate.name) &&\n candidate.name.name === 'keyExtractor',\n );\n if (\n !BabelTypes.isJSXAttribute(attr) ||\n !attr.value ||\n !BabelTypes.isJSXExpressionContainer(attr.value)\n ) {\n return undefined;\n }\n const expr = attr.value.expression;\n if (!BabelTypes.isArrowFunctionExpression(expr)) return undefined;\n const param = expr.params[0];\n if (!BabelTypes.isIdentifier(param)) return undefined;\n if (\n BabelTypes.isMemberExpression(expr.body) &&\n BabelTypes.isIdentifier(expr.body.object) &&\n expr.body.object.name === param.name &&\n BabelTypes.isIdentifier(expr.body.property)\n ) {\n return expr.body.property.name;\n }\n return undefined;\n }\n\n private extractRowAction(fn: BabelTypes.Function): RowActionDescriptor | undefined {\n let action: RowActionDescriptor | undefined;\n traverse(fn.body as any, {\n noScope: true,\n CallExpression: (nodePath: any) => {\n const node = nodePath.node as BabelTypes.CallExpression;\n if (\n !BabelTypes.isMemberExpression(node.callee) ||\n !BabelTypes.isIdentifier(node.callee.object) ||\n node.callee.object.name !== 'navigation' ||\n !BabelTypes.isIdentifier(node.callee.property) ||\n !['navigate', 'push', 'replace'].includes(node.callee.property.name)\n ) {\n return;\n }\n const firstArg = node.arguments[0];\n if (!BabelTypes.isStringLiteral(firstArg)) return;\n const params = this.extractNavigationParams(node.arguments[1]);\n action = {\n type: 'navigation',\n targetScreen: firstArg.value,\n ...(Object.keys(params).length > 0 ? { params } : {}),\n description: `Pressing a row opens ${firstArg.value}`,\n };\n },\n } as any);\n return action;\n }\n\n private extractNavigationParams(arg: BabelTypes.Node | undefined | null): Record<string, string> {\n const params: Record<string, string> = {};\n if (!arg || !BabelTypes.isObjectExpression(arg)) return params;\n for (const prop of arg.properties) {\n if (!BabelTypes.isObjectProperty(prop)) continue;\n const key = BabelTypes.isIdentifier(prop.key)\n ? prop.key.name\n : BabelTypes.isStringLiteral(prop.key)\n ? prop.key.value\n : undefined;\n if (!key) continue;\n if (\n BabelTypes.isMemberExpression(prop.value) &&\n BabelTypes.isIdentifier(prop.value.object) &&\n BabelTypes.isIdentifier(prop.value.property)\n ) {\n params[key] = `${prop.value.object.name}.${prop.value.property.name}`;\n } else if (BabelTypes.isIdentifier(prop.value)) {\n params[key] = prop.value.name;\n } else if (BabelTypes.isStringLiteral(prop.value)) {\n params[key] = prop.value.value;\n }\n }\n return params;\n }\n\n private extractItemFields(fn: BabelTypes.Function): string[] {\n const fields = new Set<string>();\n const itemNames = new Set<string>(['item']);\n const firstParam = fn.params[0];\n if (BabelTypes.isObjectPattern(firstParam)) {\n for (const prop of firstParam.properties) {\n if (\n BabelTypes.isObjectProperty(prop) &&\n BabelTypes.isIdentifier(prop.key) &&\n prop.key.name === 'item' &&\n BabelTypes.isIdentifier(prop.value)\n ) {\n itemNames.add(prop.value.name);\n }\n }\n } else if (BabelTypes.isIdentifier(firstParam)) {\n itemNames.add(firstParam.name);\n }\n\n traverse(fn.body as any, {\n noScope: true,\n MemberExpression: (nodePath: any) => {\n const node = nodePath.node as BabelTypes.MemberExpression;\n if (\n BabelTypes.isIdentifier(node.object) &&\n itemNames.has(node.object.name) &&\n BabelTypes.isIdentifier(node.property)\n ) {\n fields.add(node.property.name);\n }\n },\n } as any);\n\n return Array.from(fields).sort();\n }\n\n private inferItemType(\n dataSource: string | undefined,\n renderItem: string | undefined,\n displayFields: string[],\n ): string | undefined {\n const source = dataSource ?? renderItem;\n if (!source) return undefined;\n const singular = source\n .replace(/^render/i, '')\n .replace(/(List|Items|Data|Rows|Sections)$/i, '')\n .replace(/s$/i, '');\n const candidate = singular.charAt(0).toUpperCase() + singular.slice(1);\n if (candidate.length > 1) return candidate;\n if (displayFields.length > 0) return 'Item';\n return undefined;\n }\n\n private inferIdentityFields(\n keyField: string | undefined,\n displayFields: string[],\n ): string[] {\n const out = new Set<string>();\n if (keyField) out.add(keyField);\n for (const field of displayFields) {\n if (/^(id|uuid|key|name|title|plate|email|slug)$/i.test(field)) out.add(field);\n }\n return Array.from(out);\n }\n\n private inferSearchField(ast: BabelTypes.File, dataSource: string | undefined): string | undefined {\n if (!dataSource) return undefined;\n let queryBinding: string | undefined;\n traverse(ast, {\n CallExpression: (nodePath) => {\n const node = nodePath.node;\n if (!BabelTypes.isMemberExpression(node.callee)) return;\n if (!BabelTypes.isIdentifier(node.callee.property) || node.callee.property.name !== 'filter') return;\n if (!BabelTypes.isIdentifier(node.callee.object) || node.callee.object.name !== dataSource) return;\n const fn = node.arguments[0];\n if (!BabelTypes.isArrowFunctionExpression(fn) && !BabelTypes.isFunctionExpression(fn)) return;\n traverse(fn.body as any, {\n noScope: true,\n Identifier: (innerPath: any) => {\n const name = innerPath.node.name;\n if (/query|search|filter/i.test(name)) queryBinding = queryBinding ?? name;\n },\n } as any);\n },\n });\n return queryBinding;\n }\n\n /**\n * Extract literal values from AST nodes\n */\n private extractLiteralValue(node: BabelTypes.Expression): unknown {\n if (BabelTypes.isStringLiteral(node)) {\n return node.value;\n }\n if (BabelTypes.isNumericLiteral(node)) {\n return node.value;\n }\n if (BabelTypes.isBooleanLiteral(node)) {\n return node.value;\n }\n if (BabelTypes.isNullLiteral(node)) {\n return null;\n }\n return undefined;\n }\n\n /**\n * Extract screen name from file path\n * E.g., /src/screens/ItemListScreen.tsx -> ItemListScreen\n */\n private extractScreenName(filePath: string): string {\n const basename = path.basename(filePath);\n return basename.replace(/\\.(tsx?|jsx?)$/, '');\n }\n}\n\n","import { parse, type ParserPlugin } from '@babel/parser';\nimport type * as t from '@babel/types';\n\nexport const DEFAULT_PARSER_PLUGINS: ParserPlugin[] = [\n 'jsx',\n 'typescript',\n ['decorators', { decoratorsBeforeExport: true }],\n 'asyncGenerators',\n ['pipelineOperator', { proposal: 'minimal' }],\n 'partialApplication',\n 'logicalAssignment',\n 'classPrivateProperties',\n 'classPrivateMethods',\n ['recordAndTuple', { syntaxType: 'hash' }],\n];\n\nexport function parseSource(source: string, parserPlugins: ParserPlugin[] = []): t.File {\n return parse(source, {\n sourceType: 'module',\n plugins: [...DEFAULT_PARSER_PLUGINS, ...parserPlugins],\n }) as t.File;\n}\n","import * as t from '@babel/types';\n\nexport function findJsxAttribute(\n element: t.JSXOpeningElement,\n name: string,\n): t.JSXAttribute | undefined {\n return element.attributes.find(\n (attr): attr is t.JSXAttribute =>\n t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === name,\n );\n}\n\nexport function getStringAttr(\n element: t.JSXOpeningElement,\n name: string,\n): string | undefined {\n const attr = findJsxAttribute(element, name);\n if (!attr || !attr.value) return undefined;\n if (t.isStringLiteral(attr.value)) return attr.value.value;\n if (t.isJSXExpressionContainer(attr.value) && t.isStringLiteral(attr.value.expression)) {\n return attr.value.expression.value;\n }\n return undefined;\n}\n\nexport function getBooleanAttr(\n element: t.JSXOpeningElement,\n name: string,\n): boolean | undefined {\n const attr = findJsxAttribute(element, name);\n if (!attr) return undefined;\n if (attr.value === null) return true;\n if (t.isStringLiteral(attr.value)) {\n if (attr.value.value === 'true') return true;\n if (attr.value.value === 'false') return false;\n }\n if (t.isJSXExpressionContainer(attr.value) && t.isBooleanLiteral(attr.value.expression)) {\n return attr.value.expression.value;\n }\n return undefined;\n}\n\nexport function getExpressionIdentifierAttr(\n element: t.JSXOpeningElement,\n name: string,\n): string | undefined {\n const attr = findJsxAttribute(element, name);\n if (!attr?.value || !t.isJSXExpressionContainer(attr.value)) return undefined;\n return t.isIdentifier(attr.value.expression) ? attr.value.expression.name : undefined;\n}\n\nexport function getMemberExpressionAttr(\n element: t.JSXOpeningElement,\n name: string,\n): string | undefined {\n const attr = findJsxAttribute(element, name);\n if (!attr?.value || !t.isJSXExpressionContainer(attr.value)) return undefined;\n const expr = attr.value.expression;\n if (t.isIdentifier(expr)) return expr.name;\n if (\n t.isMemberExpression(expr) &&\n t.isIdentifier(expr.object) &&\n t.isIdentifier(expr.property)\n ) {\n return `${expr.object.name}.${expr.property.name}`;\n }\n return undefined;\n}\n\nexport function hasJsxAttribute(element: t.JSXOpeningElement, name: string): boolean {\n return Boolean(findJsxAttribute(element, name));\n}\n\nexport function firstStringAttr(\n element: t.JSXOpeningElement,\n names: string[],\n): { name: string; value: string } | undefined {\n for (const name of names) {\n const value = getStringAttr(element, name);\n if (value) return { name, value };\n }\n return undefined;\n}\n","import type * as t from '@babel/types';\nimport {\n getExpressionIdentifierAttr,\n getStringAttr,\n hasJsxAttribute,\n} from './attributes';\n\nexport type SemanticComponentRole =\n | 'view'\n | 'input'\n | 'button'\n | 'list'\n | 'modal'\n | 'select'\n | 'toggle'\n | 'date'\n | 'custom';\n\nconst VIEW_COMPONENTS = new Set(['View', 'ScrollView', 'SafeAreaView', 'KeyboardAvoidingView']);\nconst INPUT_COMPONENTS = new Set(['TextInput', 'Input', 'HocInput']);\nconst BUTTON_COMPONENTS = new Set(['TouchableOpacity', 'Pressable', 'Button']);\nconst LIST_COMPONENTS = new Set(['FlatList', 'SectionList', 'VirtualizedList', 'FlashList']);\nconst MODAL_COMPONENTS = new Set(['Modal', 'BottomSheet']);\n\nexport function classifyJsxComponent(\n name: string,\n element?: t.JSXOpeningElement,\n): SemanticComponentRole {\n if (LIST_COMPONENTS.has(name)) return 'list';\n if (MODAL_COMPONENTS.has(name)) return 'modal';\n if (/date/i.test(name)) return 'date';\n if (/(select|picker|dropdown|radio)/i.test(name)) return 'select';\n if (/(checkbox|switch|toggle)/i.test(name)) return 'toggle';\n if (INPUT_COMPONENTS.has(name)) return 'input';\n if (BUTTON_COMPONENTS.has(name)) return 'button';\n\n if (element) {\n const hasOptions = hasJsxAttribute(element, 'options');\n const hasValue = hasJsxAttribute(element, 'value');\n const hasChecked = hasJsxAttribute(element, 'checked') || hasJsxAttribute(element, 'selected');\n const hasOnChange =\n hasJsxAttribute(element, 'onChange') ||\n hasJsxAttribute(element, 'onValueChange') ||\n hasJsxAttribute(element, 'onChangeText');\n const hasOnPress = hasJsxAttribute(element, 'onPress');\n\n if (hasOptions && (hasValue || hasOnChange)) return 'select';\n if (hasChecked && hasOnChange) return 'toggle';\n if (hasOnChange && (hasJsxAttribute(element, 'label') || hasJsxAttribute(element, 'placeholder'))) {\n return 'input';\n }\n if (hasOnPress) return 'button';\n if (getStringAttr(element, 'visible') || getExpressionIdentifierAttr(element, 'visible')) {\n return 'modal';\n }\n }\n\n if (VIEW_COMPONENTS.has(name)) return 'view';\n return 'custom';\n}\n","import traverse from '@babel/traverse';\nimport * as t from '@babel/types';\n\nexport function collectFunctions(ast: t.File): Map<string, t.Function> {\n const handlers = new Map<string, t.Function>();\n\n traverse(ast, {\n FunctionDeclaration: (nodePath) => {\n if (nodePath.node.id?.name) handlers.set(nodePath.node.id.name, nodePath.node);\n },\n VariableDeclarator: (nodePath) => {\n if (!t.isIdentifier(nodePath.node.id)) return;\n const init = nodePath.node.init;\n if (t.isArrowFunctionExpression(init) || t.isFunctionExpression(init)) {\n handlers.set(nodePath.node.id.name, init);\n }\n },\n });\n\n return handlers;\n}\n","import traverse from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { AppilotsInferredAction, SignalDescriptor } from '../../types';\n\nexport interface FunctionBehavior {\n appilotsInferred: AppilotsInferredAction;\n destructive: boolean;\n nativeConfirmationExpected: boolean;\n targetScreen?: string;\n successSignal?: SignalDescriptor;\n failureSignal?: SignalDescriptor;\n opensModal?: string;\n loadingStateBindings?: string[];\n}\n\nconst DESTRUCTIVE_VERB =\n /(delete|destroy|remove|discard|wipe|erase|drop|terminate|revoke|deactivate|disable)/i;\n\nexport function analyzeFunctionBehavior(\n name: string,\n fn: t.Function,\n handlers: Map<string, t.Function>,\n seen = new Set<string>(),\n): FunctionBehavior {\n if (seen.has(name)) {\n return {\n appilotsInferred: { expectedOutcome: 'none' },\n destructive: false,\n nativeConfirmationExpected: false,\n };\n }\n seen.add(name);\n\n let hasAwait = fn.async === true;\n let hasThen = false;\n let hasStateSetter = false;\n let nativeConfirmationExpected = false;\n let targetScreen: string | undefined;\n let successSignal: SignalDescriptor | undefined;\n let failureSignal: SignalDescriptor | undefined;\n let opensModal: string | undefined;\n let destructive = DESTRUCTIVE_VERB.test(name);\n const loadingStateBindings = new Set<string>();\n\n const inspectCall = (node: t.CallExpression) => {\n if (t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.property)) {\n const method = node.callee.property.name;\n if (method === 'then' || method === 'catch' || method === 'finally') hasThen = true;\n if (\n t.isIdentifier(node.callee.object) &&\n node.callee.object.name === 'navigation' &&\n ['navigate', 'push', 'replace'].includes(method)\n ) {\n const firstArg = node.arguments[0];\n if (t.isStringLiteral(firstArg)) {\n targetScreen = firstArg.value;\n successSignal = { type: 'navigation', target: firstArg.value };\n }\n }\n if (\n t.isIdentifier(node.callee.object) &&\n node.callee.object.name === 'navigation' &&\n method === 'goBack'\n ) {\n successSignal = { type: 'goBack', description: 'Action returns to the previous screen' };\n }\n if (t.isIdentifier(node.callee.object) && node.callee.object.name === 'Alert' && method === 'alert') {\n nativeConfirmationExpected = true;\n }\n if (\n t.isIdentifier(node.callee.object) &&\n /(toast|notification|snackbar)/i.test(node.callee.object.name)\n ) {\n const firstArg = node.arguments[0];\n const secondArg = node.arguments[1];\n const text = t.isStringLiteral(secondArg)\n ? secondArg.value\n : t.isStringLiteral(firstArg)\n ? firstArg.value\n : undefined;\n const signal: SignalDescriptor = { type: 'toast', description: text };\n if (/(error|danger|fail)/i.test(method) || (t.isStringLiteral(firstArg) && /error/i.test(firstArg.value))) {\n failureSignal = signal;\n } else {\n successSignal = successSignal ?? signal;\n }\n }\n }\n\n if (t.isIdentifier(node.callee)) {\n const calleeName = node.callee.name;\n if (/^set[A-Z]/.test(calleeName)) {\n hasStateSetter = true;\n const stateName = setterToStateName(calleeName);\n const firstArg = node.arguments[0];\n if (stateName && t.isBooleanLiteral(firstArg)) {\n if (/loading|submitting|saving|fetching|refreshing/i.test(stateName)) {\n loadingStateBindings.add(stateName);\n }\n if (firstArg.value === true && !/loading|submitting|saving|fetching|refreshing/i.test(stateName)) {\n opensModal = opensModal ?? stateName;\n }\n }\n }\n if (DESTRUCTIVE_VERB.test(calleeName)) destructive = true;\n\n const nested = handlers.get(calleeName);\n if (nested) {\n const nestedInfo = analyzeFunctionBehavior(calleeName, nested, handlers, seen);\n hasAwait = hasAwait || nestedInfo.appilotsInferred.isAsyncTrigger === true;\n nativeConfirmationExpected ||= nestedInfo.nativeConfirmationExpected;\n destructive ||= nestedInfo.destructive;\n targetScreen = targetScreen ?? nestedInfo.targetScreen;\n successSignal = successSignal ?? nestedInfo.successSignal;\n failureSignal = failureSignal ?? nestedInfo.failureSignal;\n opensModal = opensModal ?? nestedInfo.opensModal;\n for (const binding of nestedInfo.loadingStateBindings ?? []) {\n loadingStateBindings.add(binding);\n }\n }\n }\n };\n\n const inspectNode = (node: t.Node) => {\n if (t.isAwaitExpression(node)) hasAwait = true;\n if (t.isCallExpression(node)) inspectCall(node);\n if (t.isMemberExpression(node) && t.isIdentifier(node.property) && DESTRUCTIVE_VERB.test(node.property.name)) {\n destructive = true;\n }\n };\n\n if (fn.body) {\n traverse(fn.body as any, {\n noScope: true,\n enter: (nodePath: any) => inspectNode(nodePath.node),\n } as any);\n }\n\n const expectedOutcome: AppilotsInferredAction['expectedOutcome'] = targetScreen\n ? 'navigation'\n : successSignal?.type === 'goBack'\n ? 'navigation'\n : hasStateSetter || successSignal?.type === 'toast' || opensModal\n ? 'inline-feedback'\n : hasAwait || hasThen\n ? 'mixed'\n : 'none';\n\n return {\n appilotsInferred: {\n isAsyncTrigger: hasAwait || hasThen || undefined,\n expectedOutcome,\n ...(loadingStateBindings.size > 0\n ? { loadingStateBindings: Array.from(loadingStateBindings).sort() }\n : {}),\n },\n destructive,\n nativeConfirmationExpected,\n targetScreen,\n successSignal,\n failureSignal,\n opensModal,\n loadingStateBindings: Array.from(loadingStateBindings).sort(),\n };\n}\n\nfunction setterToStateName(setterName: string): string | undefined {\n const raw = setterName.replace(/^set/, '');\n if (!raw) return undefined;\n return raw.charAt(0).toLowerCase() + raw.slice(1);\n}\n","import traverse from '@babel/traverse';\nimport * as t from '@babel/types';\n\nexport interface NavigationCall {\n method: 'navigate' | 'push' | 'replace' | 'goBack';\n targetScreen?: string;\n params?: Record<string, string>;\n}\n\nexport function extractNavigationCalls(ast: t.File | t.Node): NavigationCall[] {\n const calls: NavigationCall[] = [];\n traverse(ast as any, {\n noScope: !t.isFile(ast),\n CallExpression: (nodePath: any) => {\n const node = nodePath.node as t.CallExpression;\n if (\n !t.isMemberExpression(node.callee) ||\n !t.isIdentifier(node.callee.object) ||\n node.callee.object.name !== 'navigation' ||\n !t.isIdentifier(node.callee.property)\n ) {\n return;\n }\n const method = node.callee.property.name;\n if (!['navigate', 'push', 'replace', 'goBack'].includes(method)) return;\n const firstArg = node.arguments[0];\n const targetScreen = t.isStringLiteral(firstArg) ? firstArg.value : undefined;\n calls.push({\n method: method as NavigationCall['method'],\n ...(targetScreen ? { targetScreen } : {}),\n params: extractNavigationParams(node.arguments[1]),\n });\n },\n } as any);\n return calls;\n}\n\nexport function extractNavigationParams(arg: t.Node | undefined | null): Record<string, string> {\n const params: Record<string, string> = {};\n if (!arg || !t.isObjectExpression(arg)) return params;\n for (const prop of arg.properties) {\n if (!t.isObjectProperty(prop)) continue;\n const key = t.isIdentifier(prop.key)\n ? prop.key.name\n : t.isStringLiteral(prop.key)\n ? prop.key.value\n : undefined;\n if (!key) continue;\n if (\n t.isMemberExpression(prop.value) &&\n t.isIdentifier(prop.value.object) &&\n t.isIdentifier(prop.value.property)\n ) {\n params[key] = `${prop.value.object.name}.${prop.value.property.name}`;\n } else if (t.isIdentifier(prop.value)) {\n params[key] = prop.value.name;\n } else if (t.isStringLiteral(prop.value)) {\n params[key] = prop.value.value;\n }\n }\n return params;\n}\n","import type { ScreenPermissionDescriptor } from '../../types';\n\nexport function extractPermissionsFromJsDoc(\n source: string,\n): ScreenPermissionDescriptor | undefined {\n if (!source.includes('@appilots-')) return undefined;\n\n const result: ScreenPermissionDescriptor = {};\n let touched = false;\n\n const permRe = /@appilots-permissions\\s+([^\\n]+)/g;\n let m: RegExpExecArray | null;\n while ((m = permRe.exec(source))) {\n const rawLine = (m[1] ?? '').replace(/\\*\\/?\\s*$/, '').trim();\n const parsed = parsePermissionLine(rawLine);\n if (parsed) {\n Object.assign(result, parsed);\n touched = true;\n break;\n }\n }\n\n if (/@appilots-pii\\b/.test(source)) {\n result.isPii = true;\n touched = true;\n }\n\n const blockedRe = /@appilots-blocked-actions\\s+([^\\n]+)/;\n const blockedMatch = blockedRe.exec(source);\n if (blockedMatch && blockedMatch[1]) {\n const ids = blockedMatch[1]\n .replace(/\\*\\/?\\s*$/, '')\n .split(/[,\\s]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n if (ids.length > 0) {\n result.blockedActions = ids;\n touched = true;\n }\n }\n\n return touched ? result : undefined;\n}\n\nexport function extractDestructiveJsDocTargets(\n source: string,\n): Set<string> | '*' | undefined {\n if (!/@appilots-destructive\\b/.test(source)) return undefined;\n\n const out = new Set<string>();\n const re = /@appilots-destructive\\s*([^\\n]*)/g;\n let bareSeen = false;\n let m: RegExpExecArray | null;\n while ((m = re.exec(source))) {\n const rest = (m[1] ?? '').replace(/\\*\\/?\\s*$/, '').trim();\n if (!rest) {\n bareSeen = true;\n continue;\n }\n for (const id of rest.split(/[,\\s]+/).map((s) => s.trim()).filter(Boolean)) {\n out.add(id);\n }\n }\n\n if (out.size === 0) return bareSeen ? '*' : undefined;\n return out;\n}\n\nfunction parsePermissionLine(line: string): ScreenPermissionDescriptor | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n if (trimmed.startsWith('{')) {\n const candidate = trimmed.replace(/'/g, '\"');\n try {\n const obj = JSON.parse(candidate);\n if (obj && typeof obj === 'object') {\n return sanitisePermissionsObject(obj as Record<string, unknown>);\n }\n } catch {\n // Fall through to key=value parsing.\n }\n }\n\n const out: Record<string, unknown> = {};\n for (const pair of trimmed.split(/[,\\s]+/)) {\n const [k, v] = pair.split('=');\n if (!k || v === undefined) continue;\n const key = k.trim();\n const value = v.trim().replace(/^['\"]|['\"]$/g, '');\n if (value === 'true') out[key] = true;\n else if (value === 'false') out[key] = false;\n else out[key] = value;\n }\n return Object.keys(out).length > 0 ? sanitisePermissionsObject(out) : null;\n}\n\nfunction sanitisePermissionsObject(\n obj: Record<string, unknown>,\n): ScreenPermissionDescriptor {\n const out: ScreenPermissionDescriptor = {};\n if (\n typeof obj.agentAccess === 'string' &&\n (obj.agentAccess === 'read' || obj.agentAccess === 'write' || obj.agentAccess === 'none')\n ) {\n out.agentAccess = obj.agentAccess;\n }\n if (typeof obj.requiresConfirmation === 'boolean') {\n out.requiresConfirmation = obj.requiresConfirmation;\n }\n if (typeof obj.isPii === 'boolean') {\n out.isPii = obj.isPii;\n }\n if (Array.isArray(obj.blockedActions)) {\n const ids = obj.blockedActions.filter((x): x is string => typeof x === 'string' && !!x);\n if (ids.length > 0) out.blockedActions = ids;\n }\n return out;\n}\n","import { promises as fs } from 'fs';\nimport path from 'path';\nimport glob from 'fast-glob';\nimport * as parser from '@babel/parser';\nimport traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type {\n AnalyzerConfig,\n NavigationGraph,\n NavigationNode,\n NavigatorDescriptor,\n ParamDescriptor,\n} from '../types';\n\ninterface ParsedNavigator {\n name: string;\n type: 'stack' | 'tab' | 'drawer';\n screens: ParsedScreen[];\n initialRouteName?: string;\n parentNavigator?: string;\n}\n\ninterface ParsedScreen {\n name: string;\n navigatorName: string;\n navigatorType: 'stack' | 'tab' | 'drawer';\n params?: ParamDescriptor[];\n parentNavigator?: string;\n}\n\ninterface TypeExport {\n name: string;\n type: 'stack' | 'tab' | 'drawer';\n paramEntries: Map<string, ParamDescriptor[]>;\n}\n\n/**\n * Analyzes React Navigation configuration to build a navigation graph.\n */\nexport class NavigationAnalyzer {\n private config: AnalyzerConfig;\n /** Extra glob patterns for navigation file discovery (added to defaults) */\n private navigationInclude: string[];\n /** Extra glob patterns to exclude from navigation analysis */\n private navigationExclude: string[];\n\n constructor(\n config: AnalyzerConfig,\n options?: { navigationInclude?: string[]; navigationExclude?: string[] },\n ) {\n this.config = config;\n this.navigationInclude = options?.navigationInclude ?? [];\n this.navigationExclude = options?.navigationExclude ?? [];\n }\n\n /** Build the full navigation graph */\n async analyze(): Promise<NavigationGraph> {\n const navigationFiles = await this.findNavigationFiles();\n const parsedNavigators: ParsedNavigator[] = [];\n const typeExports: TypeExport[] = [];\n\n // Parse all navigation files\n for (const filePath of navigationFiles) {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n const navigators = this.parseNavigators(content, filePath);\n const types = this.parseParamTypes(content, filePath);\n\n parsedNavigators.push(...navigators);\n typeExports.push(...types);\n } catch (error) {\n console.warn(`Failed to parse ${filePath}:`, error);\n }\n }\n\n // Match type exports to navigators\n this.attachParamsToNavigators(parsedNavigators, typeExports);\n\n // Build the navigation graph\n return this.buildNavigationGraph(parsedNavigators);\n }\n\n /** Find all navigation-related files */\n private async findNavigationFiles(): Promise<string[]> {\n const patterns = [\n '**/navigation/**/*.{ts,tsx}',\n '**/navigator*.{ts,tsx}',\n '**/routes*.{ts,tsx}',\n // §5: Add user-configured navigation patterns (additive, not replacing)\n ...this.navigationInclude,\n ];\n\n const excludePatterns = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n ...(this.config.exclude || []),\n // §5: Add user-configured navigation excludes\n ...this.navigationExclude,\n ];\n\n const files = await glob(patterns, {\n cwd: this.config.rootDir,\n ignore: excludePatterns,\n });\n\n return files.map((file) => path.join(this.config.rootDir, file));\n }\n\n /** Parse navigator definitions from a file */\n private parseNavigators(content: string, filePath: string): ParsedNavigator[] {\n const navigators: ParsedNavigator[] = [];\n\n try {\n const ast = parser.parse(content, {\n sourceType: 'module',\n plugins: [\n 'jsx',\n 'typescript',\n ...((this.config.parserPlugins || []) as parser.ParserPlugin[]),\n ] as parser.ParserPlugin[],\n });\n\n const navigatorCalls: Map<string, ParsedNavigator> = new Map();\n const screensByNavigator: Map<string, ParsedScreen[]> = new Map();\n\n traverse(ast, {\n // Detect createStackNavigator / createTabNavigator / createDrawerNavigator calls\n CallExpression: (nodePath) => {\n const { node } = nodePath;\n const callee = node.callee;\n\n let navigatorType: 'stack' | 'tab' | 'drawer' | null = null;\n\n if (\n t.isIdentifier(callee) &&\n callee.name === 'createNativeStackNavigator'\n ) {\n navigatorType = 'stack';\n } else if (\n t.isIdentifier(callee) &&\n callee.name === 'createStackNavigator'\n ) {\n navigatorType = 'stack';\n } else if (\n t.isIdentifier(callee) &&\n callee.name === 'createBottomTabNavigator'\n ) {\n navigatorType = 'tab';\n } else if (\n t.isIdentifier(callee) &&\n callee.name === 'createTabNavigator'\n ) {\n navigatorType = 'tab';\n } else if (\n t.isIdentifier(callee) &&\n callee.name === 'createDrawerNavigator'\n ) {\n navigatorType = 'drawer';\n }\n\n if (navigatorType) {\n // Extract variable assignment\n const parent = nodePath.parent;\n if (\n t.isVariableDeclarator(parent) &&\n t.isIdentifier(parent.id)\n ) {\n const varName = parent.id.name;\n navigatorCalls.set(varName, {\n name: varName,\n type: navigatorType,\n screens: [],\n });\n }\n }\n },\n\n // Detect Stack.Navigator / Tab.Navigator JSX elements\n JSXElement: (nodePath) => {\n const { node } = nodePath;\n const openingElement = node.openingElement;\n\n if (\n t.isJSXMemberExpression(openingElement.name) &&\n t.isJSXIdentifier(openingElement.name.object)\n ) {\n const objectName = openingElement.name.object.name;\n const propertyName = t.isJSXIdentifier(openingElement.name.property)\n ? openingElement.name.property.name\n : null;\n\n if (propertyName === 'Navigator') {\n const navigator = navigatorCalls.get(objectName);\n if (navigator) {\n // Extract initialRouteName\n const initialRouteAttr = openingElement.attributes.find(\n (attr) =>\n t.isJSXAttribute(attr) &&\n t.isJSXIdentifier(attr.name) &&\n attr.name.name === 'initialRouteName'\n );\n\n if (\n t.isJSXAttribute(initialRouteAttr) &&\n t.isStringLiteral(initialRouteAttr.value)\n ) {\n navigator.initialRouteName = initialRouteAttr.value.value;\n }\n\n // Extract screens from children\n const screens = this.extractScreensFromNavigator(\n node,\n objectName,\n navigator.type\n );\n screensByNavigator.set(objectName, screens);\n }\n }\n }\n },\n });\n\n // Build final navigator list with screens\n navigatorCalls.forEach((navigator) => {\n const screens = screensByNavigator.get(navigator.name) || [];\n navigator.screens = screens;\n navigators.push(navigator);\n });\n } catch (error) {\n console.warn(`Failed to parse navigators in ${filePath}:`, error);\n }\n\n return navigators;\n }\n\n /** Extract screens from a navigator JSX element */\n private extractScreensFromNavigator(\n navigatorElement: t.JSXElement,\n navigatorVarName: string,\n navigatorType: 'stack' | 'tab' | 'drawer'\n ): ParsedScreen[] {\n const screens: ParsedScreen[] = [];\n\n if (!navigatorElement.children) return screens;\n\n for (const child of navigatorElement.children) {\n if (\n t.isJSXElement(child) &&\n t.isJSXMemberExpression(child.openingElement.name)\n ) {\n const memberExpr = child.openingElement.name;\n if (\n t.isJSXIdentifier(memberExpr.object) &&\n memberExpr.object.name === navigatorVarName &&\n t.isJSXIdentifier(memberExpr.property) &&\n memberExpr.property.name === 'Screen'\n ) {\n const screenName = this.extractAttributeValue(\n child.openingElement.attributes,\n 'name'\n );\n\n if (screenName) {\n screens.push({\n name: screenName,\n navigatorName: navigatorVarName,\n navigatorType,\n });\n }\n }\n }\n }\n\n return screens;\n }\n\n /** Extract string attribute value from JSX attributes */\n private extractAttributeValue(\n attributes: (t.JSXAttribute | t.JSXSpreadAttribute)[],\n attrName: string\n ): string | null {\n const attr = attributes.find(\n (a) => t.isJSXAttribute(a) && t.isJSXIdentifier(a.name) && a.name.name === attrName\n );\n\n if (\n t.isJSXAttribute(attr) &&\n t.isStringLiteral(attr.value)\n ) {\n return attr.value.value;\n }\n\n return null;\n }\n\n /** Parse TypeScript type exports (ParamList types) */\n private parseParamTypes(content: string, filePath: string): TypeExport[] {\n const types: TypeExport[] = [];\n\n try {\n const ast = parser.parse(content, {\n sourceType: 'module',\n plugins: [\n 'jsx',\n 'typescript',\n ...((this.config.parserPlugins || []) as parser.ParserPlugin[]),\n ] as parser.ParserPlugin[],\n });\n\n traverse(ast, {\n TSTypeAliasDeclaration: (nodePath) => {\n const { node } = nodePath;\n const typeName = node.id.name;\n\n // Match React Navigation param-list aliases such as\n // RootStackParamList, MainTabParamList, SettingsDrawerParamList,\n // or a project-specific FooParamList.\n const typeMatch = /^[A-Za-z0-9_]*(Stack|Tab|Drawer)?ParamList$/i.test(typeName);\n\n if (typeMatch && node.typeAnnotation?.type === 'TSTypeLiteral') {\n const paramEntries = this.extractParamListEntries(\n node.typeAnnotation as t.TSTypeLiteral,\n typeName\n );\n\n const navType = this.inferTypeFromName(typeName);\n if (navType) {\n types.push({\n name: typeName,\n type: navType.type,\n paramEntries,\n });\n }\n }\n },\n });\n } catch (error) {\n console.warn(`Failed to parse types in ${filePath}:`, error);\n }\n\n return types;\n }\n\n /** Extract param entries from a TypeScript type literal */\n private extractParamListEntries(\n typeLiteral: t.TSTypeLiteral,\n typeName: string\n ): Map<string, ParamDescriptor[]> {\n const entries = new Map<string, ParamDescriptor[]>();\n\n for (const member of typeLiteral.members) {\n if (member.type === 'TSPropertySignature' && member.key) {\n const keyName =\n member.key.type === 'Identifier' ? member.key.name : null;\n\n if (keyName && member.typeAnnotation) {\n const params = this.extractParamsFromType(\n member.typeAnnotation.typeAnnotation\n );\n entries.set(keyName, params);\n }\n }\n }\n\n return entries;\n }\n\n /** Extract param descriptors from a TypeScript type */\n private extractParamsFromType(typeAnnotation: t.TypeAnnotation | t.TSType): ParamDescriptor[] {\n const params: ParamDescriptor[] = [];\n\n if (\n typeAnnotation.type === 'TSUndefinedKeyword' ||\n typeAnnotation.type === 'TSNullKeyword'\n ) {\n return params;\n }\n\n if (typeAnnotation.type === 'TSTypeLiteral') {\n const typeLiteral = typeAnnotation as t.TSTypeLiteral;\n for (const member of typeLiteral.members) {\n if (member.type === 'TSPropertySignature' && member.key) {\n const keyName =\n member.key.type === 'Identifier' ? member.key.name : null;\n\n if (keyName) {\n const typeStr = member.typeAnnotation\n ? this.typeToString(member.typeAnnotation.typeAnnotation)\n : 'unknown';\n const required = !member.optional;\n\n params.push({\n name: keyName,\n type: typeStr,\n required,\n });\n }\n }\n }\n }\n\n return params;\n }\n\n /** Convert TypeScript type annotation to string */\n private typeToString(type: t.TypeAnnotation | t.TSType): string {\n if (type.type === 'TSStringKeyword') return 'string';\n if (type.type === 'TSNumberKeyword') return 'number';\n if (type.type === 'TSBooleanKeyword') return 'boolean';\n if (type.type === 'TSUndefinedKeyword') return 'undefined';\n if (type.type === 'TSNullKeyword') return 'null';\n\n if (type.type === 'TSUnionType') {\n return (type as t.TSUnionType).types.map((t) => this.typeToString(t)).join(' | ');\n }\n\n if (type.type === 'TSTypeLiteral') {\n return 'object';\n }\n\n if (type.type === 'TSTypeReference' && (type as t.TSTypeReference).typeName) {\n const name = (type as t.TSTypeReference).typeName;\n return name.type === 'Identifier' ? name.name : 'unknown';\n }\n\n return 'unknown';\n }\n\n /** Infer navigator type from type name */\n private inferTypeFromName(\n typeName: string\n ): { type: 'stack' | 'tab' | 'drawer' } | null {\n if (/stack/i.test(typeName)) return { type: 'stack' };\n if (/tab/i.test(typeName)) return { type: 'tab' };\n if (/drawer/i.test(typeName)) return { type: 'drawer' };\n return null;\n }\n\n /** Attach parsed type params to navigator screens */\n private attachParamsToNavigators(\n navigators: ParsedNavigator[],\n types: TypeExport[]\n ): void {\n for (const navigator of navigators) {\n // Try to find a matching type export\n const matchingType = types.find((t) => t.type === navigator.type);\n\n if (matchingType) {\n for (const screen of navigator.screens) {\n const screenParams = matchingType.paramEntries.get(screen.name);\n if (screenParams) {\n screen.params = screenParams;\n }\n }\n }\n }\n }\n\n /** Build the complete navigation graph */\n private buildNavigationGraph(\n parsedNavigators: ParsedNavigator[]\n ): NavigationGraph {\n const screens: Record<string, NavigationNode> = {};\n const navigators: NavigatorDescriptor[] = [];\n let initialScreen = '';\n\n // First pass: create navigator descriptors and identify root navigator\n for (const navigator of parsedNavigators) {\n const screenNames = navigator.screens.map((s) => s.name);\n\n navigators.push({\n name: navigator.name,\n type: navigator.type,\n screens: screenNames,\n parentNavigator: navigator.parentNavigator,\n });\n\n // Root navigator is likely the one that contains 'Auth' or 'Main' screens\n // or the first navigator with an initialRouteName\n if (\n !initialScreen &&\n navigator.initialRouteName &&\n (navigator.name.includes('Root') ||\n screenNames.some((s) => s === 'Auth' || s === 'Main'))\n ) {\n initialScreen = navigator.initialRouteName;\n }\n }\n\n // Second pass: create navigation nodes with reachability\n for (const navigator of parsedNavigators) {\n for (const screen of navigator.screens) {\n const screenKey = screen.name;\n\n // Calculate reachable screens\n const reachableTo: string[] = [];\n const reachableFrom: string[] = [];\n\n // For screens in the same navigator\n for (const otherScreen of navigator.screens) {\n if (otherScreen.name !== screen.name) {\n if (navigator.type === 'tab') {\n // Tab screens can reach all other screens in the same tab\n reachableTo.push(otherScreen.name);\n reachableFrom.push(otherScreen.name);\n } else {\n // Stack screens can reach other screens via navigation\n reachableTo.push(otherScreen.name);\n }\n }\n }\n\n screens[screenKey] = {\n screenName: screen.name,\n navigatorType: navigator.type,\n parentNavigator: navigator.name,\n reachableFrom,\n reachableTo,\n params: screen.params,\n };\n }\n }\n\n // If no initial screen identified, use the first screen from the root navigator\n if (!initialScreen && parsedNavigators.length > 0) {\n const firstNavigator = parsedNavigators[0];\n const rootNavigator = parsedNavigators.find(\n (n) => n.name.includes('Root') || (firstNavigator && n.name === firstNavigator.name)\n );\n if (rootNavigator && rootNavigator.screens && rootNavigator.screens.length > 0) {\n const firstScreen = rootNavigator.screens[0];\n initialScreen = firstScreen?.name || '';\n }\n }\n\n return {\n screens,\n initialScreen,\n navigators,\n };\n }\n}\n","import type { AnalyzerConfig, ComponentDescriptor } from '../types';\nimport { readFileSync } from 'fs';\nimport * as parser from '@babel/parser';\nimport traverse from '@babel/traverse';\nimport * as t from '@babel/types';\n\n/**\n * Analyzes React Native components to extract their semantic meaning,\n * props, and interaction points.\n */\nexport class ComponentAnalyzer {\n private config: AnalyzerConfig;\n\n constructor(config: AnalyzerConfig) {\n this.config = config;\n }\n\n /** Analyze components in a file */\n async analyzeFile(filePath: string): Promise<ComponentDescriptor[]> {\n try {\n const code = readFileSync(filePath, 'utf-8');\n const ast = parser.parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript', ['decorators', { decoratorsBeforeExport: true }]],\n });\n\n const components: ComponentDescriptor[] = [];\n\n traverse(ast, {\n JSXElement: (path) => {\n const component = this.extractComponentFromJSXElement(path.node);\n if (component) {\n components.push(component);\n }\n },\n });\n\n return components;\n } catch (error) {\n console.error(`Failed to analyze file ${filePath}:`, error);\n return [];\n }\n }\n\n private extractComponentFromJSXElement(\n element: t.JSXElement\n ): ComponentDescriptor | null {\n const elementName = this.getElementName(element.openingElement);\n if (!elementName) return null;\n\n const type = this.determineComponentType(elementName);\n const props = this.extractProps(element.openingElement);\n const { testID, accessibilityLabel } = this.extractAccessibilityProps(element.openingElement);\n const children = this.extractChildren(element.children);\n\n return {\n name: elementName,\n type,\n props: Object.keys(props).length > 0 ? props : undefined,\n children: children.length > 0 ? children : undefined,\n testID,\n accessibilityLabel,\n };\n }\n\n private getElementName(openingElement: t.JSXOpeningElement): string | null {\n if (t.isJSXIdentifier(openingElement.name)) {\n return openingElement.name.name;\n }\n if (t.isJSXMemberExpression(openingElement.name)) {\n const parts: string[] = [];\n let current: t.JSXNamespacedName | t.JSXMemberExpression | t.JSXIdentifier =\n openingElement.name;\n while (t.isJSXMemberExpression(current)) {\n if (t.isJSXIdentifier(current.property)) {\n parts.unshift(current.property.name);\n }\n current = current.object as t.JSXNamespacedName | t.JSXMemberExpression | t.JSXIdentifier;\n }\n if (t.isJSXIdentifier(current)) {\n parts.unshift(current.name);\n }\n return parts.join('.');\n }\n return null;\n }\n\n private determineComponentType(\n name: string\n ): 'view' | 'input' | 'button' | 'list' | 'modal' | 'custom' {\n const viewComponents = ['View', 'ScrollView', 'SafeAreaView', 'KeyboardAvoidingView'];\n const inputComponents = ['TextInput', 'Input'];\n const buttonComponents = ['TouchableOpacity', 'Pressable', 'Button'];\n const listComponents = ['FlatList', 'SectionList'];\n const modalComponents = ['Modal', 'BottomSheet'];\n\n if (viewComponents.includes(name)) return 'view';\n if (inputComponents.includes(name)) return 'input';\n if (buttonComponents.includes(name)) return 'button';\n if (listComponents.includes(name)) return 'list';\n if (modalComponents.includes(name)) return 'modal';\n\n return 'custom';\n }\n\n private extractProps(openingElement: t.JSXOpeningElement): Record<string, string> {\n const props: Record<string, string> = {};\n\n for (const attr of openingElement.attributes) {\n if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {\n const propName = attr.name.name;\n\n if (attr.value === null) {\n // Boolean prop\n props[propName] = 'true';\n } else if (t.isStringLiteral(attr.value)) {\n props[propName] = attr.value.value;\n } else if (t.isJSXExpressionContainer(attr.value) && t.isStringLiteral(attr.value.expression)) {\n props[propName] = attr.value.expression.value;\n }\n }\n }\n\n return props;\n }\n\n private extractAccessibilityProps(openingElement: t.JSXOpeningElement): {\n testID?: string;\n accessibilityLabel?: string;\n } {\n const result: { testID?: string; accessibilityLabel?: string } = {};\n\n for (const attr of openingElement.attributes) {\n if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {\n const propName = attr.name.name;\n\n if ((propName === 'testID' || propName === 'accessibilityLabel') && attr.value) {\n if (t.isStringLiteral(attr.value)) {\n result[propName as keyof typeof result] = attr.value.value;\n } else if (t.isJSXExpressionContainer(attr.value) && t.isStringLiteral(attr.value.expression)) {\n result[propName as keyof typeof result] = attr.value.expression.value;\n }\n }\n }\n }\n\n return result;\n }\n\n private extractChildren(\n children: Array<t.JSXElement[\"children\"][number]>,\n depth: number = 0,\n maxDepth: number = 3\n ): ComponentDescriptor[] {\n if (depth >= maxDepth) return [];\n\n const extracted: ComponentDescriptor[] = [];\n\n for (const child of children) {\n if (t.isJSXElement(child)) {\n const component = this.extractComponentFromJSXElement(child);\n if (component) {\n extracted.push(component);\n }\n }\n }\n\n return extracted;\n }\n}\n","import type { AnalyzerConfig, FormDescriptor, FormFieldDescriptor } from '../types';\nimport { readFileSync } from 'fs';\nimport * as parser from '@babel/parser';\nimport traverse from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as path from 'path';\n\n/**\n * Analyzes form structures in React Native screens, extracting\n * field definitions, validation rules, and submit actions.\n */\nexport class FormAnalyzer {\n private config: AnalyzerConfig;\n private stateVariables: Map<string, { varName: string; type: string }> = new Map();\n private inputElements: Array<{\n varName: string;\n appilotsId?: string;\n label?: string;\n placeholder?: string;\n keyboardType?: string;\n testID?: string;\n }> = [];\n private submitButtons: Array<{ label?: string; handler?: string }> = [];\n\n constructor(config: AnalyzerConfig) {\n this.config = config;\n }\n\n /** Analyze forms in a file */\n async analyzeFile(filePath: string): Promise<FormDescriptor[]> {\n try {\n const code = readFileSync(filePath, 'utf-8');\n const ast = parser.parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript', ['decorators', { decoratorsBeforeExport: true }]],\n });\n\n this.stateVariables.clear();\n this.inputElements = [];\n this.submitButtons = [];\n\n // First pass: extract state variables\n traverse(ast, {\n CallExpression: (path) => {\n this.extractStateVariables(path.node);\n },\n });\n\n // Second pass: extract input elements and buttons\n traverse(ast, {\n JSXElement: (path) => {\n this.extractFormElements(path.node);\n },\n });\n\n // Third pass: extract validation rules\n const validationRules = this.extractValidationRules(ast);\n\n // Build forms from extracted data\n return this.buildForms(filePath, validationRules);\n } catch (error) {\n console.error(`Failed to analyze forms in file ${filePath}:`, error);\n return [];\n }\n }\n\n private extractStateVariables(node: t.CallExpression): void {\n if (\n t.isIdentifier(node.callee) &&\n node.callee.name === 'useState' &&\n node.arguments.length > 0\n ) {\n // Try to find the assignment: const [varName, setVarName] = useState(...)\n // This is found in VariableDeclarator context\n return;\n }\n }\n\n private extractFormElements(element: t.JSXElement): void {\n const elementName = this.getElementName(element.openingElement);\n\n if (!elementName) return;\n\n // Detect input elements\n if (elementName === 'TextInput' || elementName === 'Input') {\n const inputInfo = this.extractInputInfo(element.openingElement);\n this.inputElements.push(inputInfo);\n }\n\n // Detect submit buttons (TouchableOpacity, Pressable, Button with onPress at end)\n if (['TouchableOpacity', 'Pressable', 'Button'].includes(elementName)) {\n const buttonInfo = this.extractButtonInfo(element.openingElement);\n if (buttonInfo) {\n this.submitButtons.push(buttonInfo);\n }\n }\n }\n\n private extractInputInfo(\n openingElement: t.JSXOpeningElement\n ): {\n varName: string;\n label?: string;\n placeholder?: string;\n keyboardType?: string;\n testID?: string;\n appilotsId?: string;\n } {\n const info: {\n varName: string;\n label?: string;\n placeholder?: string;\n keyboardType?: string;\n testID?: string;\n appilotsId?: string;\n } = { varName: '' };\n\n for (const attr of openingElement.attributes) {\n if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {\n const propName = attr.name.name;\n const propValue = this.extractAttributeValue(attr.value);\n\n switch (propName) {\n case 'label':\n info.label = propValue;\n break;\n case 'placeholder':\n info.placeholder = propValue;\n break;\n case 'keyboardType':\n info.keyboardType = propValue;\n break;\n case 'testID':\n info.testID = propValue;\n break;\n case 'appilotsId':\n info.appilotsId = propValue;\n if (propValue) info.varName = propValue;\n break;\n case 'value':\n // Try to extract variable name from value binding\n if (attr.value && t.isJSXExpressionContainer(attr.value) && t.isIdentifier(attr.value.expression)) {\n info.varName = attr.value.expression.name;\n }\n break;\n }\n }\n }\n\n return info;\n }\n\n private extractButtonInfo(\n openingElement: t.JSXOpeningElement\n ): { label?: string; handler?: string } | null {\n const info: { label?: string; handler?: string } = {};\n\n for (const attr of openingElement.attributes) {\n if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {\n const propName = attr.name.name;\n\n if (propName === 'title' || propName === 'label') {\n info.label = this.extractAttributeValue(attr.value);\n }\n\n if (propName === 'onPress') {\n if (attr.value && t.isJSXExpressionContainer(attr.value)) {\n if (t.isIdentifier(attr.value.expression)) {\n info.handler = attr.value.expression.name;\n } else if (t.isArrowFunctionExpression(attr.value.expression) || t.isFunctionExpression(attr.value.expression)) {\n info.handler = 'anonymous';\n }\n }\n }\n }\n }\n\n return Object.keys(info).length > 0 ? info : null;\n }\n\n private extractAttributeValue(value: t.JSXAttribute['value']): string | undefined {\n if (value === null) return undefined;\n if (t.isStringLiteral(value)) return value.value;\n if (t.isJSXExpressionContainer(value) && t.isStringLiteral(value.expression)) {\n return value.expression.value;\n }\n return undefined;\n }\n\n private getElementName(openingElement: t.JSXOpeningElement): string | null {\n if (t.isJSXIdentifier(openingElement.name)) {\n return openingElement.name.name;\n }\n return null;\n }\n\n private extractValidationRules(ast: t.File): Record<string, string> {\n const rules: Record<string, string> = {};\n\n traverse(ast, {\n IfStatement: (path) => {\n const test = path.node.test;\n const rule = this.extractRuleFromCondition(test);\n if (rule) {\n const { field, description } = rule;\n if (field && description) {\n rules[field] = description;\n }\n }\n },\n });\n\n return rules;\n }\n\n private extractRuleFromCondition(\n test: t.Expression\n ): { field: string; description: string } | null {\n let fieldName = '';\n let description = '';\n\n // Pattern: !varName.trim() or varName.length < N\n if (t.isUnaryExpression(test) && test.operator === '!') {\n if (t.isCallExpression(test.argument)) {\n const callExpr = test.argument;\n if (t.isMemberExpression(callExpr.callee)) {\n const memberExpr = callExpr.callee;\n if (t.isIdentifier(memberExpr.object)) {\n fieldName = memberExpr.object.name;\n description = `${fieldName} is required`;\n }\n }\n } else if (t.isIdentifier(test.argument)) {\n fieldName = test.argument.name;\n description = `${fieldName} is required`;\n }\n }\n\n // Pattern: varName.length < N\n if (t.isBinaryExpression(test) && (test.operator === '<' || test.operator === '<=')) {\n if (t.isMemberExpression(test.left)) {\n const memberExpr = test.left;\n if (t.isIdentifier(memberExpr.object)) {\n fieldName = memberExpr.object.name;\n if (t.isNumericLiteral(test.right)) {\n description = `${fieldName} must be at least ${test.right.value} characters`;\n }\n }\n }\n }\n\n // Pattern: !varName.includes('@')\n if (t.isUnaryExpression(test) && test.operator === '!') {\n if (t.isCallExpression(test.argument) && t.isMemberExpression(test.argument.callee)) {\n const methodName = t.isIdentifier(test.argument.callee.property)\n ? test.argument.callee.property.name\n : null;\n if (methodName === 'includes' && t.isIdentifier(test.argument.callee.object)) {\n fieldName = test.argument.callee.object.name;\n description = `${fieldName} format is invalid`;\n }\n }\n }\n\n return fieldName && description ? { field: fieldName, description } : null;\n }\n\n private buildForms(filePath: string, validationRules: Record<string, string>): FormDescriptor[] {\n if (this.inputElements.length === 0) return [];\n\n const fileName = path.basename(filePath, path.extname(filePath));\n const formId = `${fileName}Form`.replace(/Screen$/, '').toLowerCase();\n\n const fields: FormFieldDescriptor[] = this.inputElements.map((input) => {\n const fieldType = this.inferFieldType(input);\n const required = this.isFieldRequired(input.varName, validationRules);\n\n return {\n name: input.appilotsId || input.varName || input.testID || 'field',\n label: input.label,\n type: fieldType,\n required,\n placeholder: input.placeholder,\n };\n });\n\n const lastButton = this.submitButtons[this.submitButtons.length - 1];\n const submitAction = lastButton?.handler;\n\n return [\n {\n id: formId,\n fields,\n submitAction,\n validationRules: Object.keys(validationRules).length > 0 ? validationRules : undefined,\n },\n ];\n }\n\n private inferFieldType(input: {\n varName: string;\n label?: string;\n placeholder?: string;\n keyboardType?: string;\n testID?: string;\n appilotsId?: string;\n }): FormFieldDescriptor['type'] {\n const lowerVarName = input.varName.toLowerCase();\n const lowerLabel = input.label?.toLowerCase() || '';\n const lowerPlaceholder = input.placeholder?.toLowerCase() || '';\n const combined = `${lowerVarName} ${lowerLabel} ${lowerPlaceholder}`;\n\n // Check keyboardType first\n if (input.keyboardType === 'email-address' || input.keyboardType === 'email') {\n return 'email';\n }\n if (input.keyboardType === 'phone-pad' || input.keyboardType === 'numeric') {\n return input.keyboardType === 'numeric' ? 'number' : 'phone';\n }\n\n // Check variable/label/placeholder names\n if (combined.includes('email')) return 'email';\n if (combined.includes('phone') || combined.includes('tel')) return 'phone';\n if (combined.includes('password')) return 'text';\n if (combined.includes('number') || combined.includes('numeric')) return 'number';\n if (combined.includes('date')) return 'date';\n if (combined.includes('toggle') || combined.includes('check')) return 'toggle';\n if (combined.includes('select') || combined.includes('choice')) return 'select';\n\n return 'text';\n }\n\n private isFieldRequired(fieldName: string, rules: Record<string, string>): boolean {\n const rule = rules[fieldName];\n return rule !== undefined && rule.includes('required');\n }\n}\n","import type {\n ActionDescriptor,\n CollectionDescriptor,\n FlowDescriptor,\n FormDescriptor,\n FormFieldDescriptor,\n ScreenAgentHints,\n ScreenDescriptor,\n TargetDescriptor,\n WaitPolicyDescriptor,\n} from '../types';\n\nexport function enrichScreenForAgent(screen: ScreenDescriptor): ScreenDescriptor {\n const targets = mergeTargets([\n ...targetsFromForms(screen.forms),\n ...targetsFromActions(screen.actions),\n ...targetsFromCollections(screen.collections ?? []),\n ]);\n const flows = synthesizeFlows(screen, targets);\n const agentHints = synthesizeAgentHints(screen, targets, flows);\n\n return {\n ...screen,\n ...(targets.length > 0 ? { targets } : {}),\n ...(flows.length > 0 ? { flows } : {}),\n ...(agentHints ? { agentHints } : {}),\n };\n}\n\nfunction targetsFromForms(forms: FormDescriptor[]): TargetDescriptor[] {\n const targets: TargetDescriptor[] = [];\n for (const form of forms) {\n for (const field of form.fields) {\n targets.push({\n id: field.locator?.id ?? field.name,\n role: fieldToRole(field),\n label: field.label,\n fieldName: field.name,\n locator: field.locator ?? { id: field.name, source: 'inferred' },\n sourceComponent: field.sourceComponent,\n });\n }\n if (form.submitAction && form.submitAction !== 'anonymous') {\n targets.push({\n id: form.submitAction,\n role: 'submit',\n actionId: form.submitAction,\n label: form.submitAction,\n });\n }\n }\n return targets;\n}\n\nfunction fieldToRole(field: FormFieldDescriptor): TargetDescriptor['role'] {\n if (field.type === 'toggle') return 'toggle';\n if (field.type === 'select') return 'select';\n if (field.type === 'date') return 'date';\n return 'input';\n}\n\nfunction targetsFromActions(actions: ActionDescriptor[]): TargetDescriptor[] {\n return actions\n .filter((action) => action.id)\n .map((action) => ({\n id: action.locator?.id ?? action.id,\n role: action.type === 'submit' ? 'submit' : 'button',\n label: action.label,\n locator: action.locator ?? { id: action.id, label: action.label, source: 'inferred' },\n actionId: action.id,\n handler: action.handler,\n targetScreen: action.targetScreen,\n destructive: action.destructive,\n requiresConfirmation: action.requiresConfirmation,\n opensModal: action.opensModal,\n opensBottomSheet: action.opensBottomSheet,\n sourceComponent: action.sourceComponent,\n }));\n}\n\nfunction targetsFromCollections(collections: CollectionDescriptor[]): TargetDescriptor[] {\n return collections.map((collection) => ({\n id: collection.id,\n role: 'list',\n label: collection.itemType ?? collection.dataSource ?? collection.id,\n locator: { id: collection.id, testID: collection.id, source: 'testID' },\n sourceComponent: collection.component,\n }));\n}\n\nfunction mergeTargets(targets: TargetDescriptor[]): TargetDescriptor[] {\n const byId = new Map<string, TargetDescriptor>();\n for (const target of targets) {\n if (!target.id) continue;\n const existing = byId.get(target.id);\n byId.set(target.id, existing ? { ...target, ...existing, locator: existing.locator ?? target.locator } : target);\n }\n return Array.from(byId.values()).sort((a, b) => a.id.localeCompare(b.id));\n}\n\nfunction synthesizeFlows(screen: ScreenDescriptor, targets: TargetDescriptor[]): FlowDescriptor[] {\n const flows: FlowDescriptor[] = [];\n\n for (const form of screen.forms) {\n const submitAction = screen.actions.find((action) => action.id === form.submitAction)\n ?? screen.actions.find((action) => action.type === 'submit');\n if (!submitAction) continue;\n\n flows.push({\n id: `submit-${form.id}`,\n title: submitAction.label ? `Submit ${submitAction.label}` : `Submit ${form.id}`,\n intent: 'form_submit',\n steps: [\n ...form.fields.map((field) => ({\n type: field.type === 'select' ? 'select' : field.type === 'toggle' ? 'toggle' : 'fill',\n target: field.name,\n label: field.label,\n required: field.required,\n description: field.placeholder,\n })),\n { type: 'press', target: submitAction.id, label: submitAction.label },\n { type: 'wait', description: describeWait(submitAction) },\n ],\n waitPolicy: waitPolicyForAction(submitAction),\n safetyNotes: submitAction.requiresConfirmation || submitAction.destructive\n ? ['Requires confirmation before execution']\n : undefined,\n });\n }\n\n for (const action of screen.actions) {\n if (action.type === 'submit') continue;\n if (action.targetScreen) {\n flows.push({\n id: `navigate-${action.id}`,\n title: action.label ? `Open ${action.label}` : `Navigate to ${action.targetScreen}`,\n intent: 'navigate',\n steps: [{ type: 'press', target: action.id, label: action.label }],\n waitPolicy: waitPolicyForAction(action),\n });\n } else if (action.destructive || action.requiresConfirmation) {\n flows.push({\n id: `confirm-${action.id}`,\n title: action.label ? `Confirm ${action.label}` : `Confirm ${action.id}`,\n intent: 'destructive_action',\n steps: [\n { type: 'press', target: action.id, label: action.label },\n { type: 'confirm', description: 'Wait for native or custom confirmation before continuing' },\n { type: 'wait', description: describeWait(action) },\n ],\n waitPolicy: waitPolicyForAction(action),\n safetyNotes: ['Destructive or high-risk action'],\n });\n }\n }\n\n for (const collection of screen.collections ?? []) {\n if (collection.rowAction || (collection.rowActions && collection.rowActions.length > 0)) {\n flows.push({\n id: `list-${collection.id}`,\n title: `Act on an item in ${collection.id}`,\n intent: 'list_action',\n steps: [\n { type: 'choose-list-item', target: collection.id, description: 'Resolve the user reference to a visible or searchable row' },\n { type: 'press', description: collection.rowAction?.description ?? 'Open the row action' },\n ],\n waitPolicy: { expectedOutcome: collection.rowAction?.targetScreen ? 'navigation' : 'inline-feedback' },\n });\n }\n }\n\n return flows.sort((a, b) => a.id.localeCompare(b.id));\n}\n\nfunction waitPolicyForAction(action: ActionDescriptor): WaitPolicyDescriptor {\n const expectedOutcome = action.successSignal?.type === 'goBack'\n ? 'goBack'\n : action.appilotsInferred?.expectedOutcome ?? (action.targetScreen ? 'navigation' : undefined);\n const signals = [action.successSignal, action.failureSignal].filter(Boolean) as WaitPolicyDescriptor['signals'];\n return {\n ...(expectedOutcome ? { expectedOutcome } : {}),\n ...(signals && signals.length > 0 ? { signals } : {}),\n ...(action.appilotsInferred?.isAsyncTrigger ? { maxMs: 10000 } : {}),\n };\n}\n\nfunction describeWait(action: ActionDescriptor): string {\n if (action.successSignal?.description) return action.successSignal.description;\n if (action.successSignal?.type === 'goBack') return 'Wait for the app to return to the previous screen';\n if (action.targetScreen) return `Wait for navigation to ${action.targetScreen}`;\n if (action.appilotsInferred?.expectedOutcome) return `Wait for ${action.appilotsInferred.expectedOutcome}`;\n return 'Wait for the UI to settle';\n}\n\nfunction synthesizeAgentHints(\n screen: ScreenDescriptor,\n targets: TargetDescriptor[],\n flows: FlowDescriptor[],\n): ScreenAgentHints | undefined {\n const preferredTargets = targets\n .filter((target) => ['submit', 'button', 'list'].includes(target.role))\n .slice(0, 8)\n .map((target) => target.id);\n const commonTasks = flows.slice(0, 6).map((flow) => flow.title);\n const safetyNotes = screen.actions\n .filter((action) => action.destructive || action.requiresConfirmation)\n .map((action) => `${action.id} requires confirmation`);\n const firstAsyncAction = screen.actions.find((action) => action.appilotsInferred?.isAsyncTrigger);\n\n const hints: ScreenAgentHints = {\n primaryGoal: synthesizePrimaryGoal(screen),\n commonTasks,\n preferredTargets,\n ...(firstAsyncAction ? { waitPolicy: waitPolicyForAction(firstAsyncAction) } : {}),\n ...(safetyNotes.length > 0 ? { safetyNotes } : {}),\n };\n\n return hints.primaryGoal || commonTasks.length > 0 || preferredTargets.length > 0\n ? hints\n : undefined;\n}\n\nfunction synthesizePrimaryGoal(screen: ScreenDescriptor): string | undefined {\n const goals: string[] = [];\n const collections = screen.collections ?? [];\n\n if (collections.length > 0) {\n const collectionNames = collections\n .map((collection) => collection.itemType ?? collection.dataSource ?? collection.id)\n .filter(Boolean)\n .slice(0, 3);\n goals.push(\n collectionNames.length > 0\n ? `Browse and act on ${collectionNames.join(', ')} list data`\n : 'Browse and act on list data',\n );\n }\n\n const uniqueFields = new Map<string, FormFieldDescriptor>();\n for (const form of screen.forms) {\n for (const field of form.fields) {\n uniqueFields.set(field.name, field);\n }\n }\n const fieldCount = uniqueFields.size;\n if (fieldCount > 0) {\n const requiredCount = Array.from(uniqueFields.values()).filter((field) => field.required).length;\n const fieldLabel = fieldCount === 1 ? 'field' : 'fields';\n goals.push(\n requiredCount > 0\n ? `Complete a form with ${fieldCount} ${fieldLabel} (${requiredCount} required)`\n : `Complete a form with ${fieldCount} ${fieldLabel}`,\n );\n }\n\n const navigationCount = screen.actions.filter((action) => action.targetScreen).length;\n if (navigationCount > 0) {\n goals.push(`Open ${navigationCount} related screen${navigationCount === 1 ? '' : 's'}`);\n }\n\n const submitCount = screen.actions.filter((action) => action.type === 'submit').length;\n if (submitCount > 0) {\n goals.push(`Submit ${submitCount === 1 ? 'the primary form' : `${submitCount} forms/actions`}`);\n }\n\n const asyncCount = screen.actions.filter((action) => action.appilotsInferred?.isAsyncTrigger).length;\n if (asyncCount > 0) {\n goals.push(`Wait for ${asyncCount === 1 ? 'async feedback' : 'async action feedback'}`);\n }\n\n if (goals.length > 0) return goals.join('; ');\n if (screen.title) return `Screen labeled \"${screen.title}\"`;\n return undefined;\n}\n","import type { MCPDocument } from '../generators/types';\nimport type { ActionDescriptor } from '../types/index';\n\n/**\n * Metadata lint (OKR-005 KR4) — every mutating action registered in the\n * MCP document should declare `effect` and `riskLevel` so the runtime can\n * enforce safety policy without parsing labels. The generator extracts\n * these fields when declared in registerScreen(); this lint surfaces the\n * ones that were not, instead of letting them pass silently.\n */\n\nexport interface MetadataLintWarning {\n screen: string;\n actionId: string;\n actionType: ActionDescriptor['type'];\n missing: ('effect' | 'riskLevel')[];\n reason: string;\n}\n\n/**\n * Verbs that indicate an action changes state even when its `type` alone\n * doesn't say so (custom handlers, api_call wrappers, etc.). Mirrors the\n * destructive-verb heuristic used by ScreenAnalyzer for the\n * `destructive` flag, plus non-destructive mutation verbs.\n */\nconst MUTATION_VERB_RE =\n /\\b(delete|destroy|remove|discard|wipe|revoke|cancel|reset|clear|create|add|register|save|submit|update|edit|change|toggle|pay|send|confirm|subscribe|unsubscribe|renew|downgrade|upgrade|transfer)\\w*/i;\n\nfunction isMutating(action: ActionDescriptor): { mutating: boolean; reason: string } {\n if (action.destructive || action.effect === 'destructive') {\n return { mutating: true, reason: 'flagged destructive' };\n }\n if (action.type === 'submit' || action.type === 'state_change') {\n return { mutating: true, reason: `type \"${action.type}\"` };\n }\n const haystack = `${action.id} ${action.label ?? ''} ${action.handler ?? ''}`;\n if ((action.type === 'api_call' || action.type === 'custom') && MUTATION_VERB_RE.test(haystack)) {\n return { mutating: true, reason: 'mutation verb in id/label/handler' };\n }\n return { mutating: false, reason: '' };\n}\n\n/**\n * Scans every screen action and returns one warning per mutating action\n * that is missing `effect` and/or `riskLevel`.\n */\nexport function lintActionMetadata(document: MCPDocument): MetadataLintWarning[] {\n const warnings: MetadataLintWarning[] = [];\n\n for (const screen of document.screens) {\n for (const action of screen.actions ?? []) {\n const { mutating, reason } = isMutating(action);\n if (!mutating) continue;\n\n const missing: MetadataLintWarning['missing'] = [];\n if (!action.effect) missing.push('effect');\n if (!action.riskLevel) missing.push('riskLevel');\n if (missing.length === 0) continue;\n\n warnings.push({\n screen: screen.name,\n actionId: action.id,\n actionType: action.type,\n missing,\n reason,\n });\n }\n }\n\n return warnings;\n}\n\n/**\n * Formats lint warnings for terminal output: one line per action plus an\n * aggregate line, e.g.\n * VehicleDetails.deleteVehicle (submit): missing effect, riskLevel\n */\nexport function formatMetadataWarnings(warnings: MetadataLintWarning[]): string[] {\n return warnings.map(\n (w) => `${w.screen}.${w.actionId} (${w.actionType}, ${w.reason}): missing ${w.missing.join(', ')}`\n );\n}\n","import type { MCPDocument } from '../../generators/types';\nimport { lintActionMetadata, formatMetadataWarnings } from '../../pipeline/metadata-lint';\nimport { warn, dim, error, success } from './logger';\n\n/**\n * Prints the metadata lint result for a generated document. In strict\n * mode (--strict-metadata) any warning is fatal so CI can gate on full\n * effect/riskLevel coverage (OKR-005 KR4).\n */\nexport function reportMetadataLint(document: MCPDocument, strict: boolean): void {\n const warnings = lintActionMetadata(document);\n\n if (warnings.length === 0) {\n success('Metadata lint: all mutating actions declare effect + riskLevel');\n return;\n }\n\n warn(`Metadata lint: ${warnings.length} mutating action(s) missing effect/riskLevel`);\n for (const line of formatMetadataWarnings(warnings)) {\n dim(` ${line}`);\n }\n dim(' Declare them in registerScreen(): actions: [{ id, effect: \"write\" | \"destructive\", riskLevel: \"low\" | \"medium\" | \"high\" }]');\n\n if (strict) {\n error('--strict-metadata: failing due to missing action metadata');\n process.exit(1);\n }\n}\n","import { Command } from 'commander';\nimport { watch } from 'node:fs';\nimport { join } from 'node:path';\nimport { MCPGenerator } from '../../generators/MCPGenerator';\nimport { AppilotsAPIClient } from '../../services/api-client';\nimport { loadConfig } from '../../config/index';\nimport { banner, success, error, info, createSpinner, dim } from '../utils/logger';\n\ninterface WatchOptions {\n verbose?: boolean;\n}\n\nexport function watchCommand(): Command {\n return new Command('watch')\n .description('Watch project for changes and auto-sync MCP documents')\n .option('--verbose', 'Enable verbose logging', false)\n .action(async (options: WatchOptions) => {\n try {\n banner();\n\n // Load configuration\n const config = loadConfig();\n if (!config) {\n error('No .appilotsrc configuration found');\n info('Run: appilots init --api-key <your-key>');\n process.exit(1);\n }\n\n // Initialize API client\n const apiClient = new AppilotsAPIClient({\n serverUrl: config.serverUrl,\n apiKey: config.apiKey,\n });\n\n // Do initial sync\n info('Performing initial sync...');\n const generatorConfig = {\n rootDir: process.cwd(),\n outputDir: config.outputDir || '.appilots',\n format: 'json' as const,\n strictScreens: config.strictScreens,\n screenPatterns: config.screenPatterns,\n include: config.include,\n exclude: config.exclude,\n navigationInclude: config.navigationInclude,\n navigationExclude: config.navigationExclude,\n };\n\n const generator = new MCPGenerator(generatorConfig);\n\n const initialOutput = await generator.generate();\n const initialSync = await apiClient.sync(initialOutput.document, initialOutput.document.version);\n\n if (!initialSync.success) {\n error(`Initial sync failed: ${initialSync.error}`);\n process.exit(1);\n }\n\n success('Initial sync completed');\n info(`Watching for changes in ${config.outputDir || '.appilots'}...`);\n dim('Press Ctrl+C to stop\\n');\n\n // Set up file watcher\n let debounceTimer: NodeJS.Timeout | null = null;\n const DEBOUNCE_MS = 500;\n\n const watcher = watch(\n process.cwd(),\n { recursive: true },\n async (eventType, filename) => {\n if (!filename) return;\n\n // Skip hidden files, node_modules, and output directory\n if (\n filename.startsWith('.') ||\n filename.includes('node_modules') ||\n filename.includes(config.outputDir || '.appilots')\n ) {\n return;\n }\n\n // Debounce rapid changes\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n\n debounceTimer = setTimeout(async () => {\n try {\n if (options.verbose) {\n info(`Change detected: ${filename}`);\n }\n\n const spinner = createSpinner('Re-analyzing project...');\n spinner.start();\n\n const newGenerator = new MCPGenerator(generatorConfig);\n\n const output = await newGenerator.generate();\n spinner.text = 'Uploading changes...';\n\n const syncResult = await apiClient.sync(output.document, output.document.version);\n spinner.stop();\n\n if (!syncResult.success) {\n error(`Sync failed: ${syncResult.error}`);\n } else if (syncResult.unchanged) {\n info('Changes synced (no content changes detected)');\n } else {\n success('Changes synced successfully');\n info(\n `${output.document.metadata.totalScreens} screens, ` +\n `${output.document.metadata.totalForms} forms, ` +\n `${output.document.metadata.totalActions} actions`\n );\n }\n } catch (err) {\n error(`Watch sync failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }, DEBOUNCE_MS);\n }\n );\n\n // Handle graceful shutdown\n process.on('SIGINT', () => {\n info('Stopping watcher...');\n watcher.close();\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n process.exit(0);\n });\n } catch (err) {\n error(`Watch failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { MCPGenerator } from '../../generators/MCPGenerator';\nimport { banner, success, error, info, createSpinner } from '../utils/logger';\nimport { reportMetadataLint } from '../utils/metadata-report';\n\ninterface GenerateOptions {\n output?: string;\n format?: string;\n strictMetadata?: boolean;\n}\n\nexport function generateCommand(): Command {\n return new Command('generate')\n .description('Generate MCP documents from project source (local only)')\n .option('-o, --output <path>', 'Output directory for MCP documents', '.appilots')\n .option('-f, --format <format>', 'Output format (only json supported)', 'json')\n .option('--strict-metadata', 'Fail when mutating actions are missing effect/riskLevel metadata', false)\n .action(async (options: GenerateOptions) => {\n try {\n banner();\n\n // §2: Reject unsupported formats explicitly\n if (options.format && options.format !== 'json') {\n error(`Format \"${options.format}\" is not supported yet. Only \"json\" is available.`);\n process.exit(1);\n }\n\n const spinner = createSpinner('Analyzing project...');\n spinner.start();\n\n const generator = new MCPGenerator({\n rootDir: process.cwd(),\n outputDir: options.output || '.appilots',\n format: 'json',\n });\n\n const output = await generator.generate();\n spinner.stop();\n\n success(\n `Generated MCP document with ${output.document.metadata.totalScreens} screens, ` +\n `${output.document.metadata.totalForms} forms, ${output.document.metadata.totalActions} actions`\n );\n info(`Written to: ${output.filePath}`);\n info(`Checksum: ${output.checksum}`);\n\n reportMetadataLint(output.document, Boolean(options.strictMetadata));\n } catch (err) {\n error(`Generation failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { AppilotsAPIClient } from '../../services/api-client';\nimport { loadConfig } from '../../config/index';\nimport { banner, success, error, info, table, warn, heading, setLogMode, jsonOutput } from '../utils/logger';\n\ninterface StatusOptions {\n json?: boolean;\n quiet?: boolean;\n}\n\nexport function statusCommand(): Command {\n return new Command('status')\n .description('Show current project and MCP document status')\n .option('--json', 'Output a machine-readable JSON result (implies --quiet)', false)\n .option('--quiet', 'Suppress banner and informational output', false)\n .action(async (options: StatusOptions) => {\n if (options.json) setLogMode('json');\n else if (options.quiet) setLogMode('quiet');\n try {\n banner();\n\n // Load configuration\n const config = loadConfig();\n if (!config) {\n error('No .appilotsrc configuration found');\n info('Run: appilots init --api-key <your-key>');\n jsonOutput({ success: false, error: 'No .appilotsrc configuration found' });\n process.exit(1);\n return;\n }\n\n // Initialize API client\n const apiClient = new AppilotsAPIClient({\n serverUrl: config.serverUrl,\n apiKey: config.apiKey,\n });\n\n // Get status from server\n const status = await apiClient.status();\n\n if (status.error) {\n error(`Failed to fetch status: ${status.error}`);\n jsonOutput({ success: false, error: status.error });\n process.exit(1);\n }\n\n // Display local configuration\n heading('\\n📋 Local Configuration:');\n table([\n ['API Server', config.serverUrl],\n ['Project ID', config.projectId || '(resolved from API key)'],\n ['Output Directory', config.outputDir || '.appilots'],\n ['Auto Activate', String(config.autoActivate ?? true)],\n ]);\n\n // Display project info\n if (status.project) {\n heading('\\n📌 Project Info:');\n table([['Name', status.project.name], ['ID', status.project.id]]);\n }\n\n // Display active MCP info\n if (status.activeMcp) {\n heading('\\n✅ Active MCP Document:');\n table([\n ['Document ID', status.activeMcp.id],\n ['Version', status.activeMcp.version],\n ['Screens', String(status.activeMcp.screensCount)],\n ['Forms', String(status.activeMcp.formsCount)],\n ['Actions', String(status.activeMcp.actionsCount)],\n ]);\n } else {\n heading('\\n⚠️ No active MCP document');\n info('Run: appilots sync');\n }\n\n success('Status retrieved successfully');\n jsonOutput({\n success: true,\n local: {\n serverUrl: config.serverUrl,\n projectId: config.projectId || null,\n outputDir: config.outputDir || '.appilots',\n },\n project: status.project ?? null,\n activeMcp: status.activeMcp ?? null,\n });\n } catch (err) {\n error(`Status check failed: ${err instanceof Error ? err.message : String(err)}`);\n jsonOutput({ success: false, error: err instanceof Error ? err.message : String(err) });\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { AppilotsAPIClient, type EvalScenarioRequest } from '../../services/api-client';\nimport { loadConfig } from '../../config/index';\nimport {\n banner,\n success,\n error,\n info,\n warn,\n dim,\n table,\n heading,\n createSpinner,\n setLogMode,\n jsonOutput,\n} from '../utils/logger';\nimport { loadScenarios } from '../../eval/scenario-loader';\nimport { matchActions } from '../../eval/matcher';\nimport { loadBaseline, saveBaseline, buildBaseline, diffAgainstBaseline } from '../../eval/baseline';\nimport { EXAMPLE_SCENARIO } from '../../eval/scaffold';\n\nconst DEFAULT_MIN_PASS_RATE = 0.95;\nconst DEFAULT_MAX_TOKEN_REGRESSION = 0.25;\n\ninterface EvalOptions {\n init?: boolean;\n force?: boolean;\n dir?: string;\n baseline?: string;\n updateBaseline?: boolean;\n minPassRate?: string;\n maxTokenRegression?: string;\n model?: string;\n apiKey?: string;\n projectId?: string;\n server?: string;\n json?: boolean;\n quiet?: boolean;\n}\n\n/** Parses a numeric CLI flag, falling back (with a warning) on garbage input\n * instead of silently comparing against NaN. */\nfunction parseRate(raw: string | undefined, fallback: number, flagName: string): number {\n if (raw === undefined) return fallback;\n const n = Number(raw);\n if (Number.isNaN(n)) {\n warn(`Ignoring invalid ${flagName} value \"${raw}\" — using ${fallback}`);\n return fallback;\n }\n return n;\n}\n\nexport function evalCommand(): Command {\n return new Command('eval')\n .description(\n 'Run agent eval scenarios against the current MCP document in dry-run mode and check for regressions vs a committed baseline',\n )\n .option('--init', 'Scaffold an example scenario in the scenarios directory', false)\n .option('--force', 'With --init, overwrite an existing example scenario', false)\n .option('--dir <path>', 'Scenarios directory (default: <outputDir>/scenarios)')\n .option('--baseline <path>', 'Baseline file path (default: <outputDir>/eval-baseline.json)')\n .option(\n '--update-baseline',\n 'Record this run as the new baseline (refuses if pass rate is below the threshold)',\n false,\n )\n .option('--min-pass-rate <n>', 'Minimum fraction of scenarios that must pass, 0-1 (default: 0.95)')\n .option(\n '--max-token-regression <n>',\n 'Max fractional token increase before a passing scenario is flagged, e.g. 0.25 for +25% (default: 0.25)',\n )\n .option('--model <id>', 'Model override for scenarios that do not set their own modelOverride')\n .option('--api-key <key>', 'Appilots API key (overrides .appilotsrc and APPILOTS_API_KEY)')\n .option('--project-id <id>', 'Project ID (overrides .appilotsrc and APPILOTS_PROJECT_ID)')\n .option('--server <url>', 'Appilots server URL (overrides .appilotsrc and APPILOTS_SERVER_URL)')\n .option('--json', 'Output a machine-readable JSON result (implies --quiet)', false)\n .option('--quiet', 'Suppress banner and informational output', false)\n .action(async (options: EvalOptions) => {\n if (options.json) setLogMode('json');\n else if (options.quiet) setLogMode('quiet');\n try {\n banner();\n\n const loaded = loadConfig();\n const outputDir = loaded?.outputDir || '.appilots';\n const scenariosDir = options.dir || loaded?.eval?.scenariosDir || join(outputDir, 'scenarios');\n\n if (options.init) {\n mkdirSync(scenariosDir, { recursive: true });\n const examplePath = join(scenariosDir, 'example.json');\n if (existsSync(examplePath) && !options.force) {\n warn(`${examplePath} already exists — pass --force to overwrite`);\n } else {\n writeFileSync(examplePath, `${JSON.stringify(EXAMPLE_SCENARIO, null, 2)}\\n`, 'utf-8');\n success(`Wrote example scenario to ${examplePath}`);\n }\n info('Edit it to match a real screen in your app, then:');\n dim(' $ appilots eval --update-baseline # capture the current (good) behavior');\n dim(' $ appilots eval # check for regressions on future runs');\n jsonOutput({ success: true, scenariosDir, examplePath });\n return;\n }\n\n const apiKey = options.apiKey || loaded?.apiKey;\n if (!apiKey) {\n error('No .appilotsrc configuration found');\n info('Run: appilots init --api-key <your-key>');\n info('Or set APPILOTS_API_KEY, or pass --api-key');\n jsonOutput({ success: false, error: 'No configuration found (missing API key)' });\n process.exit(1);\n return;\n }\n const config = {\n serverUrl: 'http://localhost:4000',\n ...loaded,\n apiKey,\n ...(options.projectId ? { projectId: options.projectId } : {}),\n ...(options.server ? { serverUrl: options.server } : {}),\n };\n\n const baselinePath =\n options.baseline || loaded?.eval?.baselinePath || join(outputDir, 'eval-baseline.json');\n const minPassRate = parseRate(\n options.minPassRate,\n loaded?.eval?.minPassRate ?? DEFAULT_MIN_PASS_RATE,\n '--min-pass-rate',\n );\n const maxTokenRegression = parseRate(\n options.maxTokenRegression,\n loaded?.eval?.maxTokenRegression ?? DEFAULT_MAX_TOKEN_REGRESSION,\n '--max-token-regression',\n );\n\n const loadedScenarios = loadScenarios(scenariosDir);\n if (loadedScenarios.errors.length > 0) {\n for (const scenarioError of loadedScenarios.errors) {\n error(`${scenarioError.file}: ${scenarioError.error}`);\n }\n jsonOutput({\n success: false,\n error: 'One or more scenario files failed to load',\n details: loadedScenarios.errors,\n });\n process.exit(1);\n return;\n }\n if (loadedScenarios.scenarios.length === 0) {\n error(`No scenarios found in ${scenariosDir}`);\n info('Run: appilots eval --init');\n jsonOutput({ success: false, error: `No scenarios found in ${scenariosDir}` });\n process.exit(1);\n return;\n }\n\n const nameCounts = new Map<string, number>();\n for (const { scenario } of loadedScenarios.scenarios) {\n nameCounts.set(scenario.name, (nameCounts.get(scenario.name) ?? 0) + 1);\n }\n const duplicates = [...nameCounts.entries()]\n .filter(([, count]) => count > 1)\n .map(([name]) => name);\n if (duplicates.length > 0) {\n error(\n `Duplicate scenario name(s) — \"name\" must be unique across all scenario files: ${duplicates.join(', ')}`,\n );\n jsonOutput({ success: false, error: `Duplicate scenario names: ${duplicates.join(', ')}` });\n process.exit(1);\n return;\n }\n\n const apiClient = new AppilotsAPIClient({ serverUrl: config.serverUrl, apiKey: config.apiKey });\n\n const requests: EvalScenarioRequest[] = loadedScenarios.scenarios.map(({ scenario }) => ({\n id: scenario.name,\n screen: scenario.given?.screen,\n observation: scenario.given?.observation,\n prompt: scenario.when,\n modelOverride: scenario.modelOverride || options.model,\n }));\n\n const spinner = createSpinner(`Running ${requests.length} scenario(s)...`);\n spinner.start();\n const runResult = await apiClient.evalRun(requests);\n spinner.stop();\n\n if (runResult.error) {\n error(`Eval run failed: ${runResult.error}`);\n jsonOutput({ success: false, error: runResult.error });\n process.exit(1);\n return;\n }\n\n const resultsById = new Map((runResult.results ?? []).map((r) => [r.id, r]));\n const outcomes = loadedScenarios.scenarios.map(({ scenario }) => {\n const result = resultsById.get(scenario.name);\n if (!result) {\n return {\n name: scenario.name,\n status: 'failed' as const,\n totalTokens: 0,\n failureReason: 'no result returned by the API for this scenario',\n };\n }\n const match = matchActions(scenario.expect, result.actions, result.content);\n return {\n name: scenario.name,\n status: (match.ok ? 'passed' : 'failed') as 'passed' | 'failed',\n totalTokens: result.totalTokens,\n failureReason: match.ok ? undefined : match.reason,\n };\n });\n\n const passed = outcomes.filter((o) => o.status === 'passed').length;\n const total = outcomes.length;\n const passRate = total > 0 ? passed / total : 1;\n\n heading('\\nResults:');\n table(\n outcomes.map((o) => [\n o.status === 'passed' ? `✓ ${o.name}` : `✗ ${o.name}`,\n o.status === 'passed' ? `${o.totalTokens} tokens` : o.failureReason || 'failed',\n ]),\n );\n\n const baseline = loadBaseline(baselinePath);\n let regressions: ReturnType<typeof diffAgainstBaseline> = [];\n if (!options.updateBaseline) {\n regressions = diffAgainstBaseline(outcomes, baseline, maxTokenRegression);\n if (regressions.length > 0) {\n heading('\\nRegressions vs baseline:');\n table(regressions.map((r) => [r.name, `${r.kind}: ${r.detail}`]));\n }\n }\n\n const passRatePct = Math.round(passRate * 1000) / 10;\n const minPassRatePct = Math.round(minPassRate * 1000) / 10;\n heading(`\\nPass rate: ${passed}/${total} (${passRatePct}%) — threshold ${minPassRatePct}%`);\n\n if (options.updateBaseline) {\n if (passRate < minPassRate) {\n error(\n `Refusing to update baseline: pass rate ${passRatePct}% is below the ${minPassRatePct}% threshold`,\n );\n info('Fix the failing scenario(s) first, then re-run with --update-baseline.');\n jsonOutput({ success: false, passRate, minPassRate, total, passed, results: outcomes });\n process.exit(1);\n return;\n }\n const newBaseline = buildBaseline(outcomes, {\n generatedAt: new Date().toISOString(),\n gitSha: process.env.GIT_SHA ?? null,\n });\n saveBaseline(baselinePath, newBaseline);\n success(`Updated baseline at ${baselinePath}`);\n jsonOutput({ success: true, passRate, minPassRate, total, passed, results: outcomes });\n return;\n }\n\n const ok = passRate >= minPassRate && regressions.length === 0;\n jsonOutput({\n success: ok,\n passRate,\n minPassRate,\n total,\n passed,\n failed: total - passed,\n regressions,\n results: outcomes,\n });\n\n if (!ok) {\n if (passRate < minPassRate) {\n error(`Pass rate ${passRatePct}% is below the ${minPassRatePct}% threshold`);\n }\n if (regressions.length > 0) {\n error(`${regressions.length} regression(s) vs baseline`);\n }\n process.exit(1);\n } else {\n success('Eval passed');\n }\n } catch (err) {\n error(`Eval failed: ${err instanceof Error ? err.message : String(err)}`);\n jsonOutput({ success: false, error: err instanceof Error ? err.message : String(err) });\n process.exit(1);\n }\n });\n}\n","import { readdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport type { EvalScenario } from './types';\n\nexport interface LoadedScenario {\n file: string;\n scenario: EvalScenario;\n}\n\nexport interface ScenarioLoadError {\n file: string;\n error: string;\n}\n\nexport interface ScenarioLoadResult {\n scenarios: LoadedScenario[];\n errors: ScenarioLoadError[];\n}\n\n/**\n * Minimal shape validation — enough to give the dev a precise error\n * pointing at the offending file, without pulling in a full JSON-schema\n * validator for a handful of required fields.\n */\nfunction validateScenarioShape(raw: unknown): string | null {\n if (!raw || typeof raw !== 'object') return 'scenario must be a JSON object';\n const s = raw as Record<string, unknown>;\n if (typeof s.name !== 'string' || !s.name.trim()) {\n return '\"name\" is required and must be a non-empty string';\n }\n if (typeof s.when !== 'string' || !s.when.trim()) {\n return '\"when\" is required and must be a non-empty string (the user prompt)';\n }\n if (!s.expect || typeof s.expect !== 'object') {\n return '\"expect\" is required and must be an object (see docs: Testing your agent between releases)';\n }\n return null;\n}\n\n/**\n * Loads every `*.json` scenario file from `dir`, sorted by filename for a\n * stable run order. Returns an empty result (no error) when `dir` doesn't\n * exist yet — the caller decides whether that's fatal.\n */\nexport function loadScenarios(dir: string): ScenarioLoadResult {\n const scenarios: LoadedScenario[] = [];\n const errors: ScenarioLoadError[] = [];\n\n let files: string[];\n try {\n files = readdirSync(dir)\n .filter((f) => f.endsWith('.json'))\n .sort();\n } catch {\n return { scenarios, errors };\n }\n\n for (const file of files) {\n const full = join(dir, file);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(full, 'utf-8'));\n } catch (err) {\n errors.push({ file, error: `invalid JSON: ${err instanceof Error ? err.message : String(err)}` });\n continue;\n }\n const shapeError = validateScenarioShape(raw);\n if (shapeError) {\n errors.push({ file, error: shapeError });\n continue;\n }\n scenarios.push({ file, scenario: raw as EvalScenario });\n }\n\n return { scenarios, errors };\n}\n","/**\n * Action matchers — tolerate LLM variability while still asserting on\n * structurally meaningful behavior.\n *\n * Ported from the monorepo's internal tests/agentic/fixtures/matchers.ts\n * (same semantics) so the published @appilots/cli package doesn't take a\n * dependency on the private @appilots/shared workspace package.\n *\n * Match modes:\n * - \"any\" — every expected action appears somewhere in the actual\n * actions (default; most lenient)\n * - \"first\" — the first actual action matches the first expected one;\n * remaining expected actions just need to appear somewhere\n * - \"exact\" — actual.length === expected.length AND each pair matches\n * in order\n * - \"none\" — zero actions emitted (security / clarification probes)\n *\n * Payload constraints are matched as PARTIAL: every key in the expected\n * payload must equal the actual, but the actual can have extra keys.\n * Form-fill fields are matched by `fieldId` regardless of order, and only\n * the listed fields are required (extras are allowed).\n */\nimport type { EvalActualAction, EvalExpectedAction, EvalExpectedActions } from './types';\n\nexport interface MatchResult {\n ok: boolean;\n reason?: string;\n}\n\nfunction normalizeReply(text: string): string {\n return text\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase();\n}\n\nfunction partialMatch(\n expected: Record<string, unknown> | undefined,\n actual: Record<string, unknown> | undefined,\n): boolean {\n if (!expected) return true;\n if (!actual) return false;\n\n for (const key of Object.keys(expected)) {\n const exp = expected[key];\n const act = actual[key];\n\n // Special case: form_fill.fields — array of { fieldId, value }.\n // Each expected field must appear in actual; order not required.\n if (key === 'fields' && Array.isArray(exp) && Array.isArray(act)) {\n for (const expField of exp as Array<Record<string, unknown>>) {\n const fieldId = expField.fieldId;\n const matched = (act as Array<Record<string, unknown>>).find(\n (f) => f.fieldId === fieldId,\n );\n if (!matched) return false;\n if (expField.value !== undefined && matched.value !== expField.value) {\n return false;\n }\n }\n continue;\n }\n\n if (typeof exp === 'object' && exp !== null && !Array.isArray(exp)) {\n if (typeof act !== 'object' || act === null) return false;\n if (!partialMatch(exp as Record<string, unknown>, act as Record<string, unknown>)) {\n return false;\n }\n continue;\n }\n\n if (exp !== act) return false;\n }\n return true;\n}\n\nfunction matchesOne(expected: EvalExpectedAction, actual: EvalActualAction): boolean {\n if (expected.type !== actual.type) return false;\n return partialMatch(expected.payload, actual.payload);\n}\n\nexport function matchActions(\n expected: EvalExpectedActions,\n actual: EvalActualAction[],\n /** Assistant's visible reply — required by `replyMustContain` blocks. */\n reply = '',\n): MatchResult {\n if (expected.anyOf && expected.anyOf.length > 0) {\n const reasons: string[] = [];\n for (const branch of expected.anyOf) {\n const res = matchActions(branch, actual, reply);\n if (res.ok) return res;\n reasons.push(res.reason ?? 'no reason');\n }\n return {\n ok: false,\n reason: `anyOf: no branch matched — ${reasons.map((r, i) => `[${i}] ${r}`).join(' · ')}`,\n };\n }\n\n if (expected.forbidActionTypes && expected.forbidActionTypes.length > 0) {\n const forbidden = actual.find((a) => expected.forbidActionTypes!.includes(a.type));\n if (forbidden) {\n return {\n ok: false,\n reason: `forbidActionTypes: action of type=${forbidden.type} was emitted`,\n };\n }\n }\n\n if (expected.replyMustNotContain && expected.replyMustNotContain.length > 0) {\n const hay = normalizeReply(reply);\n const leaked = expected.replyMustNotContain.find((needle) =>\n hay.includes(normalizeReply(needle)),\n );\n if (leaked) {\n return {\n ok: false,\n reason: `replyMustNotContain: \"${leaked}\" was echoed in the reply \"${reply.slice(0, 120)}\"`,\n };\n }\n }\n\n if (expected.replyMustContain && expected.replyMustContain.length > 0) {\n const hay = normalizeReply(reply);\n const hit = expected.replyMustContain.some((needle) => hay.includes(normalizeReply(needle)));\n if (!hit) {\n return {\n ok: false,\n reason: `replyMustContain: none of [${expected.replyMustContain.join(', ')}] found in reply \"${reply.slice(0, 120)}\"`,\n };\n }\n }\n\n const mode = expected.mode ?? 'any';\n const expectedActions = expected.actions ?? [];\n\n if (mode === 'none') {\n if (actual.length === 0) return { ok: true };\n return {\n ok: false,\n reason: `none mode: expected 0 actions, got ${actual.length} (${actual.map((a) => a.type).join(', ')})`,\n };\n }\n\n if (mode === 'exact') {\n if (actual.length !== expectedActions.length) {\n return {\n ok: false,\n reason: `exact mode: expected ${expectedActions.length} action(s), got ${actual.length}`,\n };\n }\n for (let i = 0; i < expectedActions.length; i++) {\n if (!matchesOne(expectedActions[i]!, actual[i]!)) {\n return {\n ok: false,\n reason: `exact mode: action[${i}] mismatch — expected type=${expectedActions[i]!.type}, got type=${actual[i]!.type}`,\n };\n }\n }\n return { ok: true };\n }\n\n if (mode === 'first') {\n const first = actual[0];\n if (!first) {\n return { ok: false, reason: 'first mode: no actions emitted' };\n }\n if (!expectedActions[0] || !matchesOne(expectedActions[0], first)) {\n return {\n ok: false,\n reason: `first mode: first action did not match — expected type=${expectedActions[0]?.type}, got type=${first.type}`,\n };\n }\n for (const exp of expectedActions.slice(1)) {\n if (!actual.some((a) => matchesOne(exp, a))) {\n return {\n ok: false,\n reason: `first mode: expected action of type=${exp.type} not found in remaining actions`,\n };\n }\n }\n return { ok: true };\n }\n\n // any: every expected action appears somewhere in actual\n for (const exp of expectedActions) {\n if (!actual.some((a) => matchesOne(exp, a))) {\n return {\n ok: false,\n reason: `any mode: expected action of type=${exp.type} not found`,\n };\n }\n }\n return { ok: true };\n}\n\nexport function summarizeActions(actions: EvalActualAction[]): string {\n if (actions.length === 0) return '<no actions>';\n return actions\n .map((a, i) => {\n const summary = JSON.stringify(a.payload).slice(0, 200);\n return ` [${i}] ${a.type} ${summary}`;\n })\n .join('\\n');\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname } from 'path';\n\nexport interface BaselineScenarioResult {\n status: 'passed' | 'failed';\n totalTokens: number;\n failureReason?: string;\n}\n\nexport interface EvalBaseline {\n generatedAt: string | null;\n gitSha?: string | null;\n perScenario: Record<string, BaselineScenarioResult>;\n}\n\nconst EMPTY_BASELINE: EvalBaseline = { generatedAt: null, gitSha: null, perScenario: {} };\n\n/** Returns an empty baseline (not an error) when the file doesn't exist\n * yet — that's the expected state before the first `--update-baseline`. */\nexport function loadBaseline(path: string): EvalBaseline {\n if (!existsSync(path)) return { ...EMPTY_BASELINE, perScenario: {} };\n try {\n const raw = JSON.parse(readFileSync(path, 'utf-8')) as Partial<EvalBaseline>;\n return {\n generatedAt: raw.generatedAt ?? null,\n gitSha: raw.gitSha ?? null,\n perScenario: raw.perScenario ?? {},\n };\n } catch {\n return { ...EMPTY_BASELINE, perScenario: {} };\n }\n}\n\nexport function saveBaseline(path: string, baseline: EvalBaseline): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(baseline, null, 2)}\\n`, 'utf-8');\n}\n\nexport interface ScenarioRunOutcome {\n name: string;\n status: 'passed' | 'failed';\n totalTokens: number;\n failureReason?: string;\n}\n\nexport function buildBaseline(\n outcomes: ScenarioRunOutcome[],\n meta: { generatedAt: string; gitSha?: string | null },\n): EvalBaseline {\n const perScenario: Record<string, BaselineScenarioResult> = {};\n for (const o of outcomes) {\n perScenario[o.name] = {\n status: o.status,\n totalTokens: o.totalTokens,\n ...(o.failureReason ? { failureReason: o.failureReason } : {}),\n };\n }\n return { generatedAt: meta.generatedAt, gitSha: meta.gitSha ?? null, perScenario };\n}\n\nexport type RegressionKind = 'newly-failing' | 'token-regression';\n\nexport interface RegressionEntry {\n name: string;\n kind: RegressionKind;\n detail: string;\n}\n\n/**\n * Two regression signals, mirroring the internal\n * scripts/qa/eval-baseline-compare.ts logic at a scenario level:\n * - a scenario that passed on the baseline now fails\n * - a scenario that still passes but costs meaningfully more tokens\n * than it used to (>`maxTokenRegression` fractional increase)\n *\n * A scenario with no baseline entry (new scenario, or first run) never\n * regresses — there's nothing to compare against yet.\n */\nexport function diffAgainstBaseline(\n outcomes: ScenarioRunOutcome[],\n baseline: EvalBaseline,\n maxTokenRegression: number,\n): RegressionEntry[] {\n const regressions: RegressionEntry[] = [];\n\n for (const outcome of outcomes) {\n const prior = baseline.perScenario[outcome.name];\n if (!prior) continue;\n\n if (outcome.status === 'failed' && prior.status === 'passed') {\n regressions.push({\n name: outcome.name,\n kind: 'newly-failing',\n detail: outcome.failureReason ?? 'scenario now fails (previously passed)',\n });\n continue;\n }\n\n if (\n outcome.status === 'passed' &&\n prior.status === 'passed' &&\n prior.totalTokens > 0 &&\n outcome.totalTokens > prior.totalTokens * (1 + maxTokenRegression)\n ) {\n const pct = Math.round(((outcome.totalTokens - prior.totalTokens) / prior.totalTokens) * 100);\n regressions.push({\n name: outcome.name,\n kind: 'token-regression',\n detail: `tokens ${prior.totalTokens} → ${outcome.totalTokens} (+${pct}%, threshold +${Math.round(maxTokenRegression * 100)}%)`,\n });\n }\n }\n\n return regressions;\n}\n","/**\n * Example scenario written by `appilots eval --init`. Deliberately small\n * and heavily commented via the `description` field rather than JSON\n * comments (JSON has none) — see docs: \"Testing your agent between\n * releases\" for the full field reference.\n */\nexport const EXAMPLE_SCENARIO = {\n name: 'agent-fills-signup-form',\n description:\n 'The agent should fill the visible signup form fields from a single spoken instruction. Edit `given.observation` to match a real screen in your app, and `when` to a prompt your users would actually say.',\n given: {\n screen: 'SignupScreen',\n observation: {\n route: 'SignupScreen',\n texts: ['Create your account'],\n inputs: [\n { id: 'email', label: 'Email', required: true },\n { id: 'name', label: 'Full name', required: true },\n ],\n buttons: [{ id: 'btn-submit-signup', label: 'Sign up' }],\n },\n },\n when: 'My name is Jane Doe and my email is jane@example.com',\n expect: {\n mode: 'any',\n actions: [\n {\n type: 'form_fill',\n payload: {\n fields: [{ fieldId: 'name' }, { fieldId: 'email' }],\n },\n },\n ],\n },\n};\n"],"mappings":"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","names":["import_commander","import_fs","error","ora","chalk","error","import_fs","import_path","import_commander","import_promises","import_node_path","import_promises","import_path","import_traverse","t","traverse","import_traverse","t","traverse","import_traverse","t","traverse","glob","path","error","fs","traverse","handler","info","DESTRUCTIVE_VERB","basename","import_fs","import_path","import_fast_glob","import_traverse","t","fs","error","glob","path","traverse","import_fs","parser","import_traverse","t","traverse","path","error","import_fs","parser","import_traverse","t","path","traverse","error","info","import_fast_glob","glob","filePath","path","error","import_commander","import_commander","import_commander","import_commander","import_fs","import_path","import_fs","import_path","mode","import_fs","import_path","path"]}
|