@vostride/agent-qa-dashboard 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-BL7OautO.d.cts → index-ygQLgXzT.d.cts} +6 -1
- package/dist/{index-BL7OautO.d.ts → index-ygQLgXzT.d.ts} +6 -1
- package/dist/index.cjs +201 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +204 -21
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +200 -21
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +202 -19
- package/dist/server/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/schema.ts","../src/db/database.ts","../src/db/run-id-migration.ts","../src/db/runtime-db-path.ts","../src/reporter/dashboard-reporter.ts","../src/server/server.ts","../src/server/routes.ts","../src/memory/memory-catalog-manager.ts","../src/tests/test-file-manager.ts","../src/hooks/hook-registry-manager.ts","../src/hooks/hook-reference-scan.ts","../src/server/body-parser.ts","../src/execution/test-runner.ts","../src/queue/job-queue.ts","../src/tests/suite-file-manager.ts","../src/config/config-manager.ts","../src/execution/appium-manager.ts","../src/live-editor/session-manager.ts","../src/live-editor/live-session.ts","../src/live-editor/mobile-bootstrap.ts","../src/live-editor/ws-handler.ts"],"sourcesContent":["export const SCHEMA_VERSION = 1\n\nexport interface DashboardMigration {\n version: number\n sql: string[]\n}\n\nexport const MIGRATIONS: DashboardMigration[] = [\n {\n version: 1,\n sql: [\n `CREATE TABLE IF NOT EXISTS runs (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n file_path TEXT,\n status TEXT NOT NULL CHECK(status IN ('passed','failed','skipped','running','cancelled','pending','flaky')),\n priority INTEGER NOT NULL DEFAULT 0,\n duration INTEGER NOT NULL DEFAULT 0,\n attributes TEXT NOT NULL DEFAULT '{}',\n environment TEXT,\n metadata TEXT,\n started_at TEXT,\n ended_at TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n video_path TEXT,\n failure_summary TEXT,\n platform TEXT DEFAULT 'web',\n test_file_content TEXT,\n model_name TEXT,\n llm_provider TEXT,\n parallel INTEGER DEFAULT 0,\n parent_run_id TEXT,\n attempt_number INTEGER DEFAULT 0,\n retry_count INTEGER DEFAULT 0,\n max_retries INTEGER DEFAULT 0,\n error_log TEXT,\n memory_log TEXT,\n test_id TEXT,\n suite_id TEXT\n )`,\n `CREATE TABLE IF NOT EXISTS steps (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES runs(id),\n name TEXT NOT NULL,\n status TEXT NOT NULL CHECK(status IN ('passed','failed','healed','skipped','cancelled')),\n duration INTEGER NOT NULL DEFAULT 0,\n action TEXT,\n observation TEXT,\n reasoning TEXT,\n planned_action TEXT,\n result TEXT CHECK(result IN ('success','failure')),\n error TEXT,\n screenshot_path TEXT,\n screenshot_before_path TEXT,\n healing_attempts TEXT,\n retry_count INTEGER DEFAULT 0,\n captured_variables TEXT,\n step_order INTEGER NOT NULL DEFAULT 0,\n annotation_data TEXT,\n healing_screenshot_paths TEXT,\n accessibility_violations TEXT,\n confidence REAL,\n prompt_tokens INTEGER DEFAULT 0,\n completion_tokens INTEGER DEFAULT 0,\n total_tokens INTEGER DEFAULT 0,\n sub_actions_data TEXT,\n console_logs TEXT,\n network_logs TEXT,\n variable_snapshot TEXT,\n original_step_name TEXT,\n screen_context_before TEXT,\n screen_context_after TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n `CREATE TABLE IF NOT EXISTS reasoning_traces (\n id TEXT PRIMARY KEY,\n step_id TEXT NOT NULL REFERENCES steps(id),\n observe_text TEXT,\n observe_duration INTEGER,\n plan_reasoning TEXT,\n plan_confidence REAL,\n plan_action TEXT,\n plan_duration INTEGER,\n execute_action TEXT,\n execute_duration INTEGER,\n verify_reasoning TEXT,\n verify_success INTEGER,\n verify_duration INTEGER,\n heal_attempts TEXT,\n total_duration INTEGER,\n screen_state_before TEXT,\n screen_state_after TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n `CREATE TABLE IF NOT EXISTS logs (\n id TEXT PRIMARY KEY,\n step_id TEXT REFERENCES steps(id) ON DELETE CASCADE,\n run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,\n level TEXT NOT NULL CHECK(level IN ('debug','info','warn','error')),\n source TEXT NOT NULL CHECK(source IN ('agent','adapter','cache','planner','healer','hook','runner')),\n message TEXT NOT NULL,\n data TEXT,\n timestamp TEXT NOT NULL\n )`,\n `CREATE TABLE IF NOT EXISTS execution_logs (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,\n step_id TEXT,\n type TEXT NOT NULL CHECK(type IN ('hook', 'appium-script', 'runjs')),\n name TEXT NOT NULL,\n phase TEXT NOT NULL CHECK(phase IN ('setup', 'teardown', 'inline')),\n status TEXT NOT NULL CHECK(status IN ('passed', 'failed')),\n duration INTEGER NOT NULL DEFAULT 0,\n stdout TEXT,\n stderr TEXT,\n return_data TEXT,\n variables TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n hook_id TEXT\n )`,\n `CREATE TABLE IF NOT EXISTS token_events (\n id TEXT PRIMARY KEY,\n model_name TEXT NOT NULL,\n prompt_tokens INTEGER NOT NULL DEFAULT 0,\n completion_tokens INTEGER NOT NULL DEFAULT 0,\n source TEXT NOT NULL CHECK(source IN ('test-run', 'live-editor')),\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n `CREATE TABLE IF NOT EXISTS run_artifacts (\n run_id TEXT PRIMARY KEY REFERENCES runs(id) ON DELETE CASCADE,\n kind TEXT NOT NULL CHECK(kind IN ('test', 'suite-parent', 'suite-child', 'unknown')),\n schema_version INTEGER NOT NULL,\n payload TEXT NOT NULL DEFAULT '{}',\n finalized_at TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n 'CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_started_at ON runs(started_at)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_name ON runs(name)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_queue ON runs(status, priority, created_at)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_parent ON runs(parent_run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_steps_run_id ON steps(run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_reasoning_traces_step_id ON reasoning_traces(step_id)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_step_id ON logs(step_id)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_run_id ON logs(run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_level ON logs(level)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_source ON logs(source)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_run_level_source ON logs(run_id, level, source)',\n 'CREATE INDEX IF NOT EXISTS idx_execution_logs_run_id ON execution_logs(run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_execution_logs_step_id ON execution_logs(step_id)',\n 'CREATE INDEX IF NOT EXISTS idx_execution_logs_type ON execution_logs(type)',\n 'CREATE INDEX IF NOT EXISTS idx_token_events_model ON token_events(model_name)',\n 'CREATE INDEX IF NOT EXISTS idx_token_events_source ON token_events(source)',\n 'CREATE INDEX IF NOT EXISTS idx_token_events_created ON token_events(created_at)',\n 'CREATE INDEX IF NOT EXISTS idx_run_artifacts_kind ON run_artifacts(kind)',\n 'CREATE INDEX IF NOT EXISTS idx_run_artifacts_finalized ON run_artifacts(finalized_at)',\n ],\n },\n]\n","import { randomUUID } from 'node:crypto'\nimport { mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { MIGRATIONS, SCHEMA_VERSION, type DashboardMigration } from './schema.js'\nimport {\n createBetterSqlite3Database,\n DEFAULT_AGENT_QA_RUNS_DB_PATH,\n generateRunId,\n RUN_ARTIFACT_SCHEMA_VERSION,\n type BetterSqlite3Database,\n type LogEntry,\n type LogStorage,\n type RunArtifactFinalizeInput,\n type RunArtifactKind,\n type RunArtifactPayload,\n type RunArtifactStageInput,\n type RunAttributes,\n} from '@vostride/agent-qa-core'\n\nconst DASHBOARD_DB_PATH_FALLBACK = DEFAULT_AGENT_QA_RUNS_DB_PATH || '.agent-qa/runs.db'\n\nexport interface RunRow {\n id: string\n name: string\n filePath: string | null\n status: string\n priority: number\n duration: number\n attributes: RunAttributes\n environment: string | null\n metadata: Record<string, unknown> | null\n startedAt: string | null\n endedAt: string | null\n videoPath: string | null\n failureSummary: string | null\n errorLog: string | null\n memoryLog: string | null\n testId: string | null\n suiteId: string | null\n platform: string\n testFileContent: string | null\n modelName: string | null\n llmProvider: string | null\n parallel: boolean\n parentRunId: string | null\n attemptNumber: number\n retryCount: number\n maxRetries: number\n createdAt: string\n}\n\nexport interface RunArtifactRow {\n runId: string\n kind: RunArtifactKind\n schemaVersion: number\n payload: RunArtifactPayload\n finalizedAt: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface RunArtifactBundle {\n artifact: RunArtifactRow | null\n children: Array<{ run: RunRow; artifact: RunArtifactRow | null }>\n}\n\nexport interface StepRow {\n id: string\n runId: string\n name: string\n status: string\n duration: number\n action: unknown | null\n observation: string | null\n reasoning: string | null\n plannedAction: unknown | null\n result: string | null\n error: string | null\n screenshotPath: string | null\n screenshotBeforePath: string | null\n healingAttempts: unknown[] | null\n retryCount: number\n capturedVariables: Record<string, string> | null\n stepOrder: number\n annotationData: unknown | null\n healingScreenshotPaths: string[] | null\n accessibilityViolations: unknown[] | null\n confidence: number | null\n promptTokens: number\n completionTokens: number\n totalTokens: number\n subActionsData: unknown[] | null\n consoleLogs: unknown[] | null\n networkLogs: unknown[] | null\n variableSnapshot: Record<string, { value: string; source: string }> | null\n originalStepName: string | null\n screenContextBefore: string | null\n screenContextAfter: string | null\n createdAt: string\n}\n\ninterface ReasoningTraceRow {\n id: string\n stepId: string\n observeText: string | null\n observeDuration: number | null\n planReasoning: string | null\n planConfidence: number | null\n planAction: unknown | null\n planDuration: number | null\n executeAction: unknown | null\n executeDuration: number | null\n verifyReasoning: string | null\n verifySuccess: boolean | null\n verifyDuration: number | null\n healAttempts: unknown[] | null\n totalDuration: number | null\n screenStateBefore: string | null\n screenStateAfter: string | null\n createdAt: string\n}\n\ninterface ExecutionLogRow {\n id: string\n runId: string\n stepId: string | null\n type: 'hook' | 'appium-script' | 'runjs'\n name: string\n hookId: string | null\n phase: 'setup' | 'teardown' | 'inline'\n status: 'passed' | 'failed'\n duration: number\n stdout: string | null\n stderr: string | null\n returnData: unknown | null\n variables: Record<string, string> | null\n createdAt: string\n}\n\ninterface InsertExecutionLogInput {\n id: string\n runId: string\n stepId?: string | null\n type: 'hook' | 'appium-script' | 'runjs'\n name: string\n hookId?: string | null\n phase: 'setup' | 'teardown' | 'inline'\n status: 'passed' | 'failed'\n duration: number\n stdout?: string | null\n stderr?: string | null\n returnData?: unknown | null\n variables?: Record<string, string> | null\n}\n\ninterface RunsFilter {\n status?: string\n name?: string\n platform?: string\n from?: string\n to?: string\n attributePredicates?: AttributePredicate[]\n limit?: number\n offset?: number\n}\n\ninterface StatsOptions {\n from?: string\n to?: string\n attributePredicates?: AttributePredicate[]\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction deepMergeRecord(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...base }\n for (const [key, value] of Object.entries(patch)) {\n if (key === 'schemaVersion') continue\n const current = merged[key]\n merged[key] = isPlainObject(current) && isPlainObject(value)\n ? deepMergeRecord(current, value)\n : value\n }\n return merged\n}\n\nfunction mergeArtifactPayload(base: RunArtifactPayload, patch: RunArtifactStageInput): RunArtifactPayload {\n const merged = deepMergeRecord(base as unknown as Record<string, unknown>, patch as Record<string, unknown>)\n merged.schemaVersion = RUN_ARTIFACT_SCHEMA_VERSION\n return merged as unknown as RunArtifactPayload\n}\n\nexport type InsightsBreakdownDimension = 'test' | 'suite' | 'platform'\n\nexport interface InsightsBreakdownRow {\n key: string\n label: string\n runs: number\n passRate: number\n flakeRate: number\n avgDuration: number\n passed: number\n failed: number\n filePath?: string\n suiteId?: string\n}\n\nexport interface DeleteRunResult {\n deleted: boolean\n deletedRunIds: string[]\n screenshotPaths: string[]\n videoPaths: string[]\n}\n\nexport interface AttributePredicate {\n key: string\n value: string\n mode: 'exact' | 'regex'\n}\n\nexport interface AttributeKeySuggestion {\n key: string\n count: number\n}\n\nexport interface AttributeValueSuggestion {\n value: string\n count: number\n}\n\nexport function runSqliteMigrations(\n db: BetterSqlite3Database,\n migrations: readonly DashboardMigration[],\n schemaVersion: number,\n): void {\n const currentVersion = db.pragma('user_version', { simple: true }) as number\n if (currentVersion > schemaVersion) {\n throw new Error(\n `SQLite database user_version ${currentVersion} is not compatible with schema version ${schemaVersion}. `\n + 'Remove the dashboard database or use a compatible agent-qa version.',\n )\n }\n if (currentVersion === schemaVersion) return\n\n const runnableMigrations = migrations.filter(migration => migration.version <= schemaVersion)\n if (runnableMigrations.length !== schemaVersion) {\n throw new Error(`Expected ${schemaVersion} SQLite migration(s), found ${runnableMigrations.length}`)\n }\n runnableMigrations.forEach((migration, index) => {\n const expectedVersion = index + 1\n if (migration.version !== expectedVersion) {\n throw new Error(`SQLite migrations must be contiguous and sorted: expected version ${expectedVersion}, got ${migration.version}`)\n }\n })\n\n db.pragma('foreign_keys = OFF')\n try {\n for (const migration of runnableMigrations) {\n if (migration.version > currentVersion) {\n const runAll = db.transaction(() => {\n for (const sql of migration.sql) {\n db.exec(sql)\n }\n db.pragma(`user_version = ${migration.version}`)\n })\n runAll()\n }\n }\n } finally {\n db.pragma('foreign_keys = ON')\n }\n}\n\nexport class DashboardDatabase {\n private db: BetterSqlite3Database\n\n constructor({ dbPath = DASHBOARD_DB_PATH_FALLBACK }: { dbPath?: string } = {}) {\n mkdirSync(dirname(dbPath), { recursive: true })\n this.db = createBetterSqlite3Database(dbPath)\n this.db.pragma('journal_mode = WAL')\n this.db.pragma('busy_timeout = 5000')\n this.runMigrations()\n }\n\n private runMigrations(): void {\n runSqliteMigrations(this.db, MIGRATIONS, SCHEMA_VERSION)\n }\n\n insertRun(run: {\n id?: string\n name: string\n filePath?: string\n status: string\n duration: number\n attributes?: RunAttributes\n environment?: string\n metadata?: Record<string, unknown>\n startedAt: string\n endedAt: string\n videoPath?: string\n failureSummary?: string\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n parentRunId?: string\n attemptNumber?: number\n retryCount?: number\n maxRetries?: number\n testId?: string\n suiteId?: string\n }): string {\n const id = run.id || generateRunId()\n const stmt = this.db.prepare(`\n INSERT INTO runs (id, name, file_path, status, duration, attributes, environment, metadata, started_at, ended_at, video_path, failure_summary, platform, test_file_content, model_name, llm_provider, parent_run_id, attempt_number, retry_count, max_retries, test_id, suite_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n run.name,\n run.filePath ?? null,\n run.status,\n run.duration,\n JSON.stringify(run.attributes ?? {}),\n run.environment ?? null,\n run.metadata ? JSON.stringify(run.metadata) : null,\n run.startedAt,\n run.endedAt,\n run.videoPath ?? null,\n run.failureSummary ?? null,\n run.platform ?? 'web',\n run.testFileContent ?? null,\n run.modelName ?? null,\n run.llmProvider ?? null,\n run.parentRunId ?? null,\n run.attemptNumber ?? 0,\n run.retryCount ?? 0,\n run.maxRetries ?? 0,\n run.testId ?? null,\n run.suiteId ?? null,\n )\n return id\n }\n\n updateRun(id: string, updates: {\n name?: string\n status?: string\n duration?: number\n startedAt?: string\n endedAt?: string\n failureSummary?: string\n errorLog?: string\n memoryLog?: string\n videoPath?: string\n attributes?: RunAttributes\n platform?: string\n testId?: string\n suiteId?: string\n }): void {\n const fields: string[] = []\n const values: unknown[] = []\n if (updates.name !== undefined) { fields.push('name = ?'); values.push(updates.name) }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status) }\n if (updates.duration !== undefined) { fields.push('duration = ?'); values.push(updates.duration) }\n if (updates.startedAt !== undefined) { fields.push('started_at = ?'); values.push(updates.startedAt) }\n if (updates.endedAt !== undefined) { fields.push('ended_at = ?'); values.push(updates.endedAt) }\n if (updates.failureSummary !== undefined) { fields.push('failure_summary = ?'); values.push(updates.failureSummary) }\n if (updates.errorLog !== undefined) { fields.push('error_log = ?'); values.push(updates.errorLog) }\n if (updates.memoryLog !== undefined) { fields.push('memory_log = ?'); values.push(updates.memoryLog) }\n if (updates.videoPath !== undefined) { fields.push('video_path = ?'); values.push(updates.videoPath) }\n if (updates.attributes !== undefined) { fields.push('attributes = ?'); values.push(JSON.stringify(updates.attributes)) }\n if (updates.platform !== undefined) { fields.push('platform = ?'); values.push(updates.platform) }\n if (updates.testId !== undefined) { fields.push('test_id = ?'); values.push(updates.testId) }\n if (updates.suiteId !== undefined) { fields.push('suite_id = ?'); values.push(updates.suiteId) }\n if (fields.length === 0) return\n values.push(id)\n this.db.prepare(`UPDATE runs SET ${fields.join(', ')} WHERE id = ?`).run(...values)\n }\n\n updateRunMetadata(id: string, updates: {\n attributes?: RunAttributes\n metadata?: Record<string, unknown>\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n }): void {\n const fields: string[] = []\n const values: unknown[] = []\n if (updates.attributes !== undefined) { fields.push('attributes = ?'); values.push(JSON.stringify(updates.attributes)) }\n if (updates.metadata !== undefined) {\n const existing = this.db.prepare('SELECT metadata FROM runs WHERE id = ?').get(id) as { metadata: string | null } | undefined\n const existingMeta = existing?.metadata ? JSON.parse(existing.metadata) : {}\n const merged = { ...existingMeta, ...updates.metadata }\n fields.push('metadata = ?'); values.push(JSON.stringify(merged))\n }\n if (updates.platform !== undefined) { fields.push('platform = ?'); values.push(updates.platform) }\n if (updates.testFileContent !== undefined) { fields.push('test_file_content = ?'); values.push(updates.testFileContent) }\n if (updates.modelName !== undefined) { fields.push('model_name = ?'); values.push(updates.modelName) }\n if (updates.llmProvider !== undefined) { fields.push('llm_provider = ?'); values.push(updates.llmProvider) }\n if (fields.length === 0) return\n values.push(id)\n this.db.prepare(`UPDATE runs SET ${fields.join(', ')} WHERE id = ?`).run(...values)\n }\n\n insertPendingRun(run: {\n id?: string\n name: string\n filePath?: string\n attributes?: RunAttributes\n priority?: number\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n metadata?: Record<string, unknown>\n parallel?: boolean\n maxRetries?: number\n }): string {\n const id = run.id || generateRunId()\n const stmt = this.db.prepare(`\n INSERT INTO runs (id, name, file_path, status, priority, duration, attributes, started_at, ended_at, platform, test_file_content, model_name, llm_provider, metadata, parallel, max_retries)\n VALUES (?, ?, ?, 'pending', ?, 0, ?, NULL, NULL, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n run.name,\n run.filePath ?? null,\n run.priority ?? 0,\n JSON.stringify(run.attributes ?? {}),\n run.platform ?? 'web',\n run.testFileContent ?? null,\n run.modelName ?? null,\n run.llmProvider ?? null,\n run.metadata ? JSON.stringify(run.metadata) : null,\n run.parallel ? 1 : 0,\n run.maxRetries ?? 0,\n )\n return id\n }\n\n getNextPendingRun(): RunRow | undefined {\n const row = this.db.prepare(\n 'SELECT * FROM runs WHERE status = ? ORDER BY priority DESC, created_at ASC, rowid ASC LIMIT 1'\n ).get('pending') as Record<string, unknown> | undefined\n return row ? this.mapRunRow(row) : undefined\n }\n\n getPendingRuns(): RunRow[] {\n const rows = this.db.prepare(\n 'SELECT * FROM runs WHERE status = ? ORDER BY priority DESC, created_at ASC, rowid ASC'\n ).all('pending') as Record<string, unknown>[]\n return rows.map(r => this.mapRunRow(r))\n }\n\n updateRunStatus(id: string, status: string): void {\n this.db.prepare('UPDATE runs SET status = ? WHERE id = ?').run(status, id)\n }\n\n insertStep(step: {\n id?: string\n runId: string\n name: string\n status: string\n duration: number\n action?: unknown\n observation?: string\n reasoning?: string\n plannedAction?: unknown\n result?: string\n error?: string\n screenshotPath?: string\n screenshotBeforePath?: string\n healingAttempts?: unknown[]\n retryCount?: number\n capturedVariables?: Record<string, string>\n stepOrder: number\n annotationData?: unknown\n healingScreenshotPaths?: string[]\n accessibilityViolations?: unknown[]\n confidence?: number\n promptTokens?: number\n completionTokens?: number\n totalTokens?: number\n subActionsData?: unknown[]\n consoleLogs?: unknown[]\n networkLogs?: unknown[]\n variableSnapshot?: Record<string, unknown>\n originalStepName?: string\n screenContextBefore?: string\n screenContextAfter?: string\n }): string {\n const id = step.id || randomUUID()\n const stmt = this.db.prepare(`\n INSERT INTO steps (id, run_id, name, status, duration, action, observation, reasoning, planned_action, result, error, screenshot_path, screenshot_before_path, healing_attempts, retry_count, captured_variables, step_order, annotation_data, healing_screenshot_paths, accessibility_violations, confidence, prompt_tokens, completion_tokens, total_tokens, sub_actions_data, console_logs, network_logs, variable_snapshot, original_step_name, screen_context_before, screen_context_after)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n step.runId,\n step.name,\n step.status,\n step.duration,\n step.action ? JSON.stringify(step.action) : null,\n step.observation ?? null,\n step.reasoning ?? null,\n step.plannedAction ? JSON.stringify(step.plannedAction) : null,\n step.result ?? null,\n step.error ?? null,\n step.screenshotPath ?? null,\n step.screenshotBeforePath ?? null,\n step.healingAttempts ? JSON.stringify(step.healingAttempts) : null,\n step.retryCount ?? 0,\n step.capturedVariables ? JSON.stringify(step.capturedVariables) : null,\n step.stepOrder,\n step.annotationData ? JSON.stringify(step.annotationData) : null,\n step.healingScreenshotPaths ? JSON.stringify(step.healingScreenshotPaths) : null,\n step.accessibilityViolations ? JSON.stringify(step.accessibilityViolations) : null,\n step.confidence ?? null,\n step.promptTokens ?? 0,\n step.completionTokens ?? 0,\n step.totalTokens ?? 0,\n step.subActionsData ? JSON.stringify(step.subActionsData) : null,\n step.consoleLogs ? JSON.stringify(step.consoleLogs) : null,\n step.networkLogs ? JSON.stringify(step.networkLogs) : null,\n step.variableSnapshot ? JSON.stringify(step.variableSnapshot) : null,\n step.originalStepName ?? null,\n step.screenContextBefore ?? null,\n step.screenContextAfter ?? null,\n )\n return id\n }\n\n private appendAttributePredicateConditions(\n conditions: string[],\n params: unknown[],\n predicates: AttributePredicate[] | undefined,\n ): boolean {\n let hasRegex = false\n for (const predicate of predicates ?? []) {\n if (predicate.mode === 'exact') {\n conditions.push(`EXISTS (\n SELECT 1\n FROM json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE run_attr.key = ? AND run_attr.value = ?\n )`)\n params.push(predicate.key, predicate.value)\n } else {\n hasRegex = true\n conditions.push(`EXISTS (\n SELECT 1\n FROM json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE run_attr.key = ?\n )`)\n params.push(predicate.key)\n }\n }\n return hasRegex\n }\n\n private applyRegexAttributePredicates(\n runs: RunRow[],\n predicates: AttributePredicate[] | undefined,\n ): RunRow[] {\n const regexPredicates = (predicates ?? []).filter((predicate) => predicate.mode === 'regex')\n if (regexPredicates.length === 0) return runs\n const compiled = regexPredicates.map((predicate) => ({\n key: predicate.key,\n regex: new RegExp(predicate.value),\n }))\n return runs.filter((run) =>\n compiled.every((predicate) => {\n const value = run.attributes[predicate.key]\n return typeof value === 'string' && predicate.regex.test(value)\n }),\n )\n }\n\n private queryRunsWithAttributePredicates(input: {\n conditions: string[]\n params: unknown[]\n attributePredicates?: AttributePredicate[]\n orderBy?: string\n limit?: number\n offset?: number\n }): RunRow[] {\n const conditions = [...input.conditions]\n const params = [...input.params]\n const hasRegex = this.appendAttributePredicateConditions(conditions, params, input.attributePredicates)\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n let sql = `SELECT * FROM runs ${where} ${input.orderBy ?? 'ORDER BY created_at DESC'}`\n\n if (!hasRegex && input.limit !== undefined) {\n sql += ' LIMIT ?'\n params.push(input.limit)\n }\n if (!hasRegex && input.offset !== undefined) {\n sql += ' OFFSET ?'\n params.push(input.offset)\n }\n\n const rows = this.db.prepare(sql).all(...params) as Record<string, unknown>[]\n const runs = this.applyRegexAttributePredicates(rows.map(r => this.mapRunRow(r)), input.attributePredicates)\n if (!hasRegex) return runs\n\n const start = input.offset ?? 0\n const end = input.limit !== undefined ? start + input.limit : undefined\n return runs.slice(start, end)\n }\n\n private buildTrendsFromRuns(runs: RunRow[]): {\n daily: { date: string; passed: number; failed: number; total: number; avgDuration: number }[]\n passRate: number\n totalRuns: number\n avgDuration: number\n } {\n const totalRuns = runs.length\n const passedTotal = runs.filter((run) => this.isSuccessfulRunStatus(run.status)).length\n const avgDuration = totalRuns > 0\n ? runs.reduce((sum, run) => sum + run.duration, 0) / totalRuns\n : 0\n const byDate = new Map<string, RunRow[]>()\n for (const run of runs) {\n const date = (run.startedAt ?? run.createdAt).slice(0, 10)\n const dayRuns = byDate.get(date)\n if (dayRuns) dayRuns.push(run)\n else byDate.set(date, [run])\n }\n\n return {\n daily: [...byDate.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([date, dayRuns]) => {\n const total = dayRuns.length\n return {\n date,\n passed: dayRuns.filter((run) => this.isSuccessfulRunStatus(run.status)).length,\n failed: dayRuns.filter((run) => run.status === 'failed').length,\n total,\n avgDuration: total > 0 ? dayRuns.reduce((sum, run) => sum + run.duration, 0) / total : 0,\n }\n }),\n passRate: totalRuns > 0 ? passedTotal / totalRuns : 0,\n totalRuns,\n avgDuration,\n }\n }\n\n getRuns(opts: RunsFilter = {}): RunRow[] {\n const conditions: string[] = ['parent_run_id IS NULL']\n const params: unknown[] = []\n\n if (opts.status) {\n conditions.push('status = ?')\n params.push(opts.status)\n }\n if (opts.name) {\n conditions.push('(name LIKE ? OR id LIKE ?)')\n params.push(`%${opts.name}%`, `%${opts.name}%`)\n }\n if (opts.platform) {\n conditions.push('platform = ?')\n params.push(opts.platform)\n }\n if (opts.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n if (opts.to) {\n conditions.push('started_at <= ?')\n params.push(opts.to)\n }\n\n return this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts.attributePredicates,\n orderBy: 'ORDER BY created_at DESC',\n limit: opts.limit,\n offset: opts.offset,\n })\n }\n\n getRun(id: string): RunRow | undefined {\n const row = this.db.prepare('SELECT * FROM runs WHERE id = ?').get(id) as Record<string, unknown> | undefined\n return row ? this.mapRunRow(row) : undefined\n }\n\n listRunAttributeKeys(opts: { limit?: number; q?: string } = {}): AttributeKeySuggestion[] {\n const limit = opts.limit ?? 50\n const params: unknown[] = []\n const filters: string[] = []\n if (opts.q && opts.q.trim().length > 0) {\n filters.push('run_attr.key LIKE ?')\n params.push(`%${opts.q.trim()}%`)\n }\n params.push(limit)\n const rows = this.db.prepare(`\n SELECT run_attr.key as key, COUNT(*) as count\n FROM runs, json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE ${filters.length > 0 ? `${filters.join(' AND ')} AND` : ''} run_attr.type = 'text'\n GROUP BY run_attr.key\n ORDER BY count DESC, key ASC\n LIMIT ?\n `).all(...params) as Array<{ key: string; count: number }>\n\n return rows.map((row) => ({ key: row.key, count: row.count }))\n }\n\n listRunAttributeValues(key: string, opts: { limit?: number; q?: string } = {}): AttributeValueSuggestion[] {\n const limit = opts.limit ?? 50\n const params: unknown[] = [key]\n const filters = ['run_attr.key = ?']\n if (opts.q && opts.q.trim().length > 0) {\n filters.push('run_attr.value LIKE ?')\n params.push(`%${opts.q.trim()}%`)\n }\n params.push(limit)\n const rows = this.db.prepare(`\n SELECT run_attr.value as value, COUNT(*) as count\n FROM runs, json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE ${filters.join(' AND ')}\n AND run_attr.type = 'text'\n GROUP BY run_attr.value\n ORDER BY count DESC, value ASC\n LIMIT ?\n `).all(...params) as Array<{ value: string; count: number }>\n\n return rows.map((row) => ({ value: row.value, count: row.count }))\n }\n\n deleteRun(id: string): DeleteRunResult {\n const runRows = this.db.prepare(`\n WITH RECURSIVE run_tree(id) AS (\n SELECT id FROM runs WHERE id = ?\n UNION ALL\n SELECT runs.id\n FROM runs\n INNER JOIN run_tree ON runs.parent_run_id = run_tree.id\n )\n SELECT *\n FROM runs\n WHERE id IN (SELECT id FROM run_tree)\n ORDER BY CASE WHEN id = ? THEN 0 ELSE 1 END, created_at ASC\n `).all(id, id) as Record<string, unknown>[]\n\n if (runRows.length === 0) {\n return {\n deleted: false,\n deletedRunIds: [],\n screenshotPaths: [],\n videoPaths: [],\n }\n }\n\n const deletedRunIds = runRows.map((row) => row.id as string)\n const runPlaceholders = deletedRunIds.map(() => '?').join(', ')\n const stepRows = this.db.prepare(`\n SELECT id, screenshot_path, screenshot_before_path, healing_screenshot_paths\n FROM steps\n WHERE run_id IN (${runPlaceholders})\n `).all(...deletedRunIds) as Array<{\n id: string\n screenshot_path: string | null\n screenshot_before_path: string | null\n healing_screenshot_paths: string | null\n }>\n const deletedStepIds = stepRows.map((row) => row.id)\n const screenshotPaths = stepRows.flatMap((row) => {\n const healingPaths = (() => {\n if (!row.healing_screenshot_paths) return []\n try {\n const parsed = JSON.parse(row.healing_screenshot_paths) as unknown\n return Array.isArray(parsed)\n ? parsed.filter((value): value is string => typeof value === 'string' && value.length > 0)\n : []\n } catch {\n return []\n }\n })()\n\n return [\n row.screenshot_path,\n row.screenshot_before_path,\n ...healingPaths,\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n })\n const videoPaths = runRows\n .map((row) => row.video_path)\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n const deleteAll = this.db.transaction(() => {\n if (deletedStepIds.length > 0) {\n const stepPlaceholders = deletedStepIds.map(() => '?').join(', ')\n this.db.prepare(`\n DELETE FROM reasoning_traces\n WHERE step_id IN (${stepPlaceholders})\n `).run(...deletedStepIds)\n }\n\n this.db.prepare(`\n DELETE FROM steps\n WHERE run_id IN (${runPlaceholders})\n `).run(...deletedRunIds)\n\n this.db.prepare(`\n DELETE FROM runs\n WHERE id IN (${runPlaceholders})\n `).run(...deletedRunIds)\n })\n\n deleteAll()\n\n return {\n deleted: true,\n deletedRunIds,\n screenshotPaths,\n videoPaths,\n }\n }\n\n getSteps(runId: string): StepRow[] {\n const rows = this.db.prepare('SELECT * FROM steps WHERE run_id = ? ORDER BY step_order').all(runId) as Record<string, unknown>[]\n return rows.map(r => this.mapStepRow(r))\n }\n\n getCapturedVariableNames(testId: string): string[] {\n const rows = this.db.prepare(`\n SELECT DISTINCT captured_variables FROM steps\n WHERE run_id IN (SELECT id FROM runs WHERE test_id = ?)\n AND captured_variables IS NOT NULL\n LIMIT 100\n `).all(testId) as Array<{ captured_variables: string }>\n\n const nameSet = new Set<string>()\n for (const row of rows) {\n try {\n const parsed = JSON.parse(row.captured_variables) as Record<string, string>\n for (const key of Object.keys(parsed)) nameSet.add(key)\n } catch { /* skip malformed */ }\n }\n return [...nameSet].sort()\n }\n\n getRunsByParent(parentRunId: string): RunRow[] {\n const rows = this.db.prepare(\n 'SELECT * FROM runs WHERE parent_run_id = ? ORDER BY created_at ASC'\n ).all(parentRunId) as Record<string, unknown>[]\n return rows.map(r => this.mapRunRow(r))\n }\n\n insertRunArtifact(input: {\n runId: string\n kind?: RunArtifactKind\n payload?: RunArtifactStageInput\n }): RunArtifactRow {\n const payload = mergeArtifactPayload(\n { schemaVersion: RUN_ARTIFACT_SCHEMA_VERSION },\n input.payload ?? {},\n )\n this.db.prepare(`\n INSERT OR IGNORE INTO run_artifacts (run_id, kind, schema_version, payload)\n VALUES (?, ?, ?, ?)\n `).run(\n input.runId,\n input.kind ?? 'unknown',\n RUN_ARTIFACT_SCHEMA_VERSION,\n JSON.stringify(payload),\n )\n\n const existing = this.getRunArtifact(input.runId)\n if (!existing) {\n throw new Error(`Run artifact ${input.runId} was not created`)\n }\n if (existing.finalizedAt) return existing\n\n const updates: string[] = []\n const values: unknown[] = []\n if (input.kind && existing.kind !== input.kind) {\n updates.push('kind = ?')\n values.push(input.kind)\n }\n if (input.payload && Object.keys(input.payload).some((key) => key !== 'schemaVersion')) {\n const merged = mergeArtifactPayload(existing.payload, input.payload)\n updates.push('payload = ?')\n values.push(JSON.stringify(merged))\n }\n if (updates.length > 0) {\n updates.push('updated_at = CURRENT_TIMESTAMP')\n this.db.prepare(`UPDATE run_artifacts SET ${updates.join(', ')} WHERE run_id = ?`).run(...values, input.runId)\n }\n\n return this.getRunArtifact(input.runId)!\n }\n\n stageRunArtifact(runId: string, patch: RunArtifactStageInput): RunArtifactRow {\n const row = this.getRunArtifact(runId)\n if (!row) {\n throw new Error(`Run artifact ${runId} does not exist`)\n }\n if (row.finalizedAt) {\n throw new Error(`Run artifact ${runId} is finalized`)\n }\n const payload = mergeArtifactPayload(row.payload, patch)\n this.db.prepare(`\n UPDATE run_artifacts\n SET payload = ?, updated_at = CURRENT_TIMESTAMP\n WHERE run_id = ?\n `).run(JSON.stringify(payload), runId)\n return this.getRunArtifact(runId)!\n }\n\n finalizeRunArtifact(runId: string, updates?: RunArtifactFinalizeInput): RunArtifactRow {\n const row = this.getRunArtifact(runId)\n if (!row) {\n throw new Error(`Run artifact ${runId} does not exist`)\n }\n if (row.finalizedAt) return row\n\n let payload = row.payload\n const finalizedAt = updates?.finalizedAt ?? new Date().toISOString()\n if (updates) {\n const { finalizedAt: _finalizedAt, ...patch } = updates\n payload = mergeArtifactPayload(payload, patch)\n }\n\n this.db.prepare(`\n UPDATE run_artifacts\n SET payload = ?, finalized_at = ?, updated_at = CURRENT_TIMESTAMP\n WHERE run_id = ? AND finalized_at IS NULL\n `).run(JSON.stringify(payload), finalizedAt, runId)\n\n return this.getRunArtifact(runId)!\n }\n\n getRunArtifact(runId: string): RunArtifactRow | null {\n const row = this.db.prepare('SELECT * FROM run_artifacts WHERE run_id = ?').get(runId) as Record<string, unknown> | undefined\n return row ? this.mapRunArtifactRow(row) : null\n }\n\n getRunArtifactBundle(runId: string): RunArtifactBundle {\n const children = this.getRunsByParent(runId).map((run) => ({\n run,\n artifact: this.getRunArtifact(run.id),\n }))\n return {\n artifact: this.getRunArtifact(runId),\n children,\n }\n }\n\n updateRunRetryInfo(id: string, info: { retryCount: number; maxRetries: number }): void {\n this.db.prepare('UPDATE runs SET retry_count = ?, max_retries = ? WHERE id = ?')\n .run(info.retryCount, info.maxRetries, id)\n }\n\n private isSuccessfulRunStatus(status: string): boolean {\n return status === 'passed' || status === 'flaky'\n }\n\n private getHealedRunIds(runIds: string[]): Set<string> {\n if (runIds.length === 0) return new Set()\n\n const placeholders = runIds.map(() => '?').join(', ')\n const rows = this.db.prepare(`\n SELECT DISTINCT run_id\n FROM steps\n WHERE status = 'healed'\n AND run_id IN (${placeholders})\n `).all(...runIds) as Array<{ run_id: string }>\n\n return new Set(rows.map((row) => row.run_id))\n }\n\n private summarizeAnalyticsRuns(\n runs: Array<Pick<RunRow, 'id' | 'status' | 'duration'>>,\n healedRunIds: Set<string>,\n ) {\n const totalRuns = runs.length\n const passed = runs.filter((run) => this.isSuccessfulRunStatus(run.status)).length\n const failed = runs.filter((run) => run.status === 'failed').length\n const flaky = runs.filter((run) => run.status === 'flaky' || healedRunIds.has(run.id)).length\n const totalDuration = runs.reduce((sum, run) => sum + run.duration, 0)\n\n return {\n totalRuns,\n passed,\n failed,\n flaky,\n passRate: totalRuns > 0 ? passed / totalRuns : 0,\n flakeRate: totalRuns > 0 ? flaky / totalRuns : 0,\n avgDuration: totalRuns > 0 ? totalDuration / totalRuns : 0,\n }\n }\n\n private listRunsForInsights(\n dimension: InsightsBreakdownDimension,\n opts: StatsOptions & { limit?: number } = {},\n ): RunRow[] {\n const conditions: string[] = []\n const params: unknown[] = []\n\n if (dimension === 'suite') {\n conditions.push('parent_run_id IS NULL')\n conditions.push('suite_id IS NOT NULL')\n } else if (dimension === 'platform') {\n conditions.push('parent_run_id IS NULL')\n } else {\n conditions.push('NOT (suite_id IS NOT NULL AND parent_run_id IS NULL)')\n }\n\n if (opts.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n if (opts.to) {\n conditions.push('started_at <= ?')\n params.push(opts.to)\n }\n\n return this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts.attributePredicates,\n orderBy: 'ORDER BY started_at DESC',\n })\n }\n\n getStats(opts: StatsOptions = {}): {\n totalRuns: number\n passed: number\n failed: number\n flaky: number\n flakeRate: number\n avgDuration: number\n totalTokens: number\n runs: { date: string; passed: number; failed: number; healed: number; duration: number }[]\n memory: {\n runs: number\n added: number\n confirmed: number\n deprecated: number\n deleted: number\n curatorTokens: number\n }\n } {\n const runs = this.listRunsForInsights('platform', opts)\n const healedRunIds = this.getHealedRunIds(runs.map((run) => run.id))\n const summary = this.summarizeAnalyticsRuns(runs, healedRunIds)\n\n const byDay = new Map<string, RunRow[]>()\n for (const run of runs) {\n const date = (run.startedAt ?? run.createdAt).slice(0, 10)\n const dayRuns = byDay.get(date)\n if (dayRuns) {\n dayRuns.push(run)\n } else {\n byDay.set(date, [run])\n }\n }\n\n const daily = [...byDay.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([date, dayRuns]) => {\n const dayHealedRunIds = new Set(\n dayRuns\n .filter((run) => healedRunIds.has(run.id))\n .map((run) => run.id),\n )\n const daySummary = this.summarizeAnalyticsRuns(dayRuns, dayHealedRunIds)\n\n return {\n date,\n passed: daySummary.passed,\n failed: daySummary.failed,\n healed: dayHealedRunIds.size,\n duration: daySummary.avgDuration,\n }\n })\n\n const runIds = runs.map((run) => run.id)\n const totalTokens = runIds.length > 0\n ? ((this.db.prepare(`\n SELECT COALESCE(SUM(total_tokens), 0) as total_tokens\n FROM steps\n WHERE run_id IN (${runIds.map(() => '?').join(',')})\n `).get(...runIds) as Record<string, unknown>).total_tokens as number) || 0\n : 0\n\n const memorySummary = {\n runs: 0,\n added: 0,\n confirmed: 0,\n deprecated: 0,\n deleted: 0,\n curatorTokens: 0,\n }\n for (const run of runs) {\n if (!run.memoryLog) continue\n memorySummary.runs++\n try {\n const parsed = JSON.parse(run.memoryLog) as Record<string, unknown>\n memorySummary.added += Number(parsed.added ?? 0) || 0\n memorySummary.confirmed += Number(parsed.confirmed ?? 0) || 0\n memorySummary.deprecated += Number(parsed.deprecated ?? 0) || 0\n memorySummary.deleted += Number(parsed.deleted ?? 0) || 0\n const tokenUsage = parsed.tokenUsage && typeof parsed.tokenUsage === 'object'\n ? parsed.tokenUsage as Record<string, unknown>\n : {}\n memorySummary.curatorTokens += Number(tokenUsage.totalTokens ?? 0) || 0\n } catch {\n // Ignore malformed historical memory logs in aggregate insights.\n }\n }\n\n return {\n totalRuns: summary.totalRuns,\n passed: summary.passed,\n failed: summary.failed,\n flaky: summary.flaky,\n flakeRate: summary.flakeRate,\n avgDuration: summary.avgDuration,\n totalTokens,\n runs: daily,\n memory: memorySummary,\n }\n }\n\n getCostStats(opts: StatsOptions = {}): {\n runs: { runId: string; name: string; startedAt: string | null; promptTokens: number; completionTokens: number; totalTokens: number }[]\n totals: { promptTokens: number; completionTokens: number; totalTokens: number }\n } {\n const conditions: string[] = []\n const params: unknown[] = []\n if (opts.from) { conditions.push('r.started_at >= ?'); params.push(opts.from) }\n if (opts.to) { conditions.push('r.started_at <= ?'); params.push(opts.to) }\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\n const rows = this.db.prepare(`\n SELECT\n r.id as run_id,\n r.name,\n r.started_at,\n COALESCE(SUM(s.prompt_tokens), 0) as prompt_tokens,\n COALESCE(SUM(s.completion_tokens), 0) as completion_tokens,\n COALESCE(SUM(s.total_tokens), 0) as total_tokens\n FROM runs r\n LEFT JOIN steps s ON s.run_id = r.id\n ${where}\n GROUP BY r.id\n ORDER BY r.started_at DESC\n `).all(...params) as Record<string, unknown>[]\n\n const runs = rows.map(r => {\n const promptTokens = (r.prompt_tokens as number) || 0\n const completionTokens = (r.completion_tokens as number) || 0\n const totalTokens = (r.total_tokens as number) || 0\n return {\n runId: r.run_id as string,\n name: r.name as string,\n startedAt: r.started_at as string | null,\n promptTokens,\n completionTokens,\n totalTokens,\n }\n })\n\n const totalPrompt = runs.reduce((sum, r) => sum + r.promptTokens, 0)\n const totalCompletion = runs.reduce((sum, r) => sum + r.completionTokens, 0)\n const totalTotal = runs.reduce((sum, r) => sum + r.totalTokens, 0)\n\n return {\n runs,\n totals: {\n promptTokens: totalPrompt,\n completionTokens: totalCompletion,\n totalTokens: totalTotal,\n },\n }\n }\n\n insertTokenEvent(event: {\n modelName: string\n promptTokens: number\n completionTokens: number\n source: 'test-run' | 'live-editor'\n }): string {\n const id = randomUUID()\n this.db.prepare(`\n INSERT INTO token_events (id, model_name, prompt_tokens, completion_tokens, source)\n VALUES (?, ?, ?, ?, ?)\n `).run(id, event.modelName, event.promptTokens, event.completionTokens, event.source)\n return id\n }\n\n getTokenEventStats(opts: { from?: string; to?: string } = {}): {\n byModel: { date: string; model: string; promptTokens: number; completionTokens: number }[]\n bySource: Record<string, { promptTokens: number; completionTokens: number }>\n totals: { promptTokens: number; completionTokens: number }\n } {\n const conditions: string[] = []\n const params: unknown[] = []\n if (opts.from) { conditions.push('created_at >= ?'); params.push(opts.from) }\n if (opts.to) { conditions.push('created_at <= ?'); params.push(opts.to) }\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\n const byModel = this.db.prepare(`\n SELECT\n DATE(created_at) as date,\n model_name as model,\n SUM(prompt_tokens) as promptTokens,\n SUM(completion_tokens) as completionTokens\n FROM token_events\n ${where}\n GROUP BY DATE(created_at), model_name\n ORDER BY date\n `).all(...params) as { date: string; model: string; promptTokens: number; completionTokens: number }[]\n\n const bySourceRows = this.db.prepare(`\n SELECT\n source,\n SUM(prompt_tokens) as promptTokens,\n SUM(completion_tokens) as completionTokens\n FROM token_events\n ${where}\n GROUP BY source\n `).all(...params) as { source: string; promptTokens: number; completionTokens: number }[]\n\n const bySource: Record<string, { promptTokens: number; completionTokens: number }> = {}\n for (const row of bySourceRows) {\n bySource[row.source] = { promptTokens: row.promptTokens, completionTokens: row.completionTokens }\n }\n\n const totalsRow = this.db.prepare(`\n SELECT\n COALESCE(SUM(prompt_tokens), 0) as promptTokens,\n COALESCE(SUM(completion_tokens), 0) as completionTokens\n FROM token_events\n ${where}\n `).get(...params) as { promptTokens: number; completionTokens: number }\n\n return {\n byModel,\n bySource,\n totals: { promptTokens: totalsRow.promptTokens, completionTokens: totalsRow.completionTokens },\n }\n }\n\n getRunsByTestName(name: string, opts?: { limit?: number; offset?: number; attributePredicates?: AttributePredicate[] }): RunRow[] {\n return this.queryRunsWithAttributePredicates({\n conditions: ['name = ?', 'parent_run_id IS NULL'],\n params: [name],\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at DESC',\n limit: opts?.limit,\n offset: opts?.offset,\n })\n }\n\n getRunsByTestNameCount(name: string, opts?: { attributePredicates?: AttributePredicate[] }): number {\n if (opts?.attributePredicates?.length) {\n return this.getRunsByTestName(name, { attributePredicates: opts.attributePredicates }).length\n }\n const row = this.db.prepare('SELECT COUNT(*) as cnt FROM runs WHERE name = ? AND parent_run_id IS NULL').get(name) as { cnt: number }\n return row.cnt\n }\n\n getTestTrends(name: string, opts?: { from?: string; attributePredicates?: AttributePredicate[] }): {\n daily: { date: string; passed: number; failed: number; total: number; avgDuration: number }[]\n passRate: number\n totalRuns: number\n avgDuration: number\n } {\n const conditions = ['name = ?', 'parent_run_id IS NULL']\n const params: unknown[] = [name]\n if (opts?.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n return this.buildTrendsFromRuns(this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at ASC',\n }))\n }\n\n getRunsBySuiteId(suiteId: string, opts?: { limit?: number; offset?: number; attributePredicates?: AttributePredicate[] }): RunRow[] {\n return this.queryRunsWithAttributePredicates({\n conditions: ['suite_id = ?', 'parent_run_id IS NULL'],\n params: [suiteId],\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at DESC',\n limit: opts?.limit,\n offset: opts?.offset,\n })\n }\n\n getRunsBySuiteIdCount(suiteId: string, opts?: { attributePredicates?: AttributePredicate[] }): number {\n if (opts?.attributePredicates?.length) {\n return this.getRunsBySuiteId(suiteId, { attributePredicates: opts.attributePredicates }).length\n }\n const row = this.db.prepare(`\n SELECT COUNT(*) as cnt\n FROM runs\n WHERE suite_id = ?\n AND parent_run_id IS NULL\n `).get(suiteId) as { cnt: number }\n return row.cnt\n }\n\n getSuiteTrends(suiteId: string, opts?: { from?: string; attributePredicates?: AttributePredicate[] }): {\n daily: { date: string; passed: number; failed: number; total: number; avgDuration: number }[]\n passRate: number\n totalRuns: number\n avgDuration: number\n } {\n const conditions = ['suite_id = ?', 'parent_run_id IS NULL']\n const params: unknown[] = [suiteId]\n if (opts?.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n return this.buildTrendsFromRuns(this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at ASC',\n }))\n }\n\n getInsightsBreakdown(\n dimension: InsightsBreakdownDimension,\n opts: StatsOptions & { limit?: number } = {},\n ): InsightsBreakdownRow[] {\n const runs = this.listRunsForInsights(dimension, opts)\n const healedRunIds = this.getHealedRunIds(runs.map((run) => run.id))\n const grouped = new Map<string, Array<RunRow>>()\n\n for (const run of runs) {\n const key = dimension === 'suite'\n ? (run.suiteId ?? 'unknown')\n : dimension === 'platform'\n ? (run.platform || 'unknown')\n : run.name\n\n const groupRuns = grouped.get(key)\n if (groupRuns) {\n groupRuns.push(run)\n } else {\n grouped.set(key, [run])\n }\n }\n\n const rows = [...grouped.entries()].map(([key, groupRuns]) => {\n const groupHealedRunIds = new Set(\n groupRuns\n .filter((run) => healedRunIds.has(run.id))\n .map((run) => run.id),\n )\n const filePaths = new Set(\n groupRuns\n .map((run) => run.filePath)\n .filter((value): value is string => typeof value === 'string' && value.length > 0),\n )\n const summary = this.summarizeAnalyticsRuns(groupRuns, groupHealedRunIds)\n const row: InsightsBreakdownRow = {\n key,\n label: key,\n runs: summary.totalRuns,\n passRate: summary.passRate,\n flakeRate: summary.flakeRate,\n avgDuration: summary.avgDuration,\n passed: summary.passed,\n failed: summary.failed,\n }\n\n if (dimension === 'test' && filePaths.size === 1) {\n row.filePath = [...filePaths][0]\n }\n\n if (dimension === 'suite') {\n row.suiteId = key\n }\n\n return row\n })\n\n rows.sort((left, right) =>\n right.runs - left.runs ||\n right.flakeRate - left.flakeRate ||\n left.passRate - right.passRate ||\n left.label.localeCompare(right.label),\n )\n\n const limit = opts.limit ?? 25\n return rows.slice(0, limit)\n }\n\n getFlakyTests(opts?: { minRuns?: number; limit?: number }): {\n name: string; filePath: string | null; totalRuns: number; passRate: number; flakyScore: number\n }[] {\n const minRuns = opts?.minRuns ?? 3\n const limit = opts?.limit ?? 50\n\n const tests = this.db.prepare(`\n SELECT name,\n MAX(file_path) as file_path,\n COUNT(*) as total_runs,\n SUM(CASE WHEN status = 'passed' THEN 1 ELSE 0 END) as passed,\n GROUP_CONCAT(status, ',') as status_seq\n FROM (\n SELECT name, status, file_path FROM runs\n WHERE status IN ('passed', 'failed')\n ORDER BY name, started_at DESC\n )\n GROUP BY name\n HAVING COUNT(*) >= ?\n LIMIT ?\n `).all(minRuns, limit) as Record<string, unknown>[]\n\n return tests.map(t => {\n const statusSeq = (t.status_seq as string).split(',')\n let alternations = 0\n for (let i = 1; i < statusSeq.length; i++) {\n if (statusSeq[i] !== statusSeq[i - 1]) alternations++\n }\n const flakyScore = statusSeq.length > 1 ? alternations / (statusSeq.length - 1) : 0\n const totalRuns = t.total_runs as number\n const passed = t.passed as number\n\n return {\n name: t.name as string,\n filePath: (t.file_path as string) ?? null,\n totalRuns,\n passRate: passed / totalRuns,\n flakyScore,\n }\n }).sort((a, b) => b.flakyScore - a.flakyScore)\n }\n\n getAccessibilitySummary(runId: string) {\n const steps = this.getSteps(runId)\n const allViolations: any[] = []\n let stepsWithViolations = 0\n let scannedSteps = 0\n\n for (const step of steps) {\n if (Array.isArray(step.accessibilityViolations)) {\n scannedSteps++\n if ((step.accessibilityViolations as any[]).length > 0) {\n stepsWithViolations++\n allViolations.push(...(step.accessibilityViolations as any[]))\n }\n }\n }\n\n const bySeverity: Record<string, number> = { critical: 0, serious: 0, moderate: 0, minor: 0 }\n const byRule: Record<string, { count: number; impact: string }> = {}\n\n for (const v of allViolations) {\n bySeverity[v.impact] = (bySeverity[v.impact] || 0) + 1\n if (!byRule[v.ruleId]) byRule[v.ruleId] = { count: 0, impact: v.impact }\n byRule[v.ruleId].count++\n }\n\n return {\n enabled: this.getRunAccessibilityEnabled(runId),\n total: allViolations.length,\n bySeverity,\n byRule: Object.entries(byRule)\n .map(([ruleId, data]) => ({ ruleId, ...data }))\n .sort((a, b) => b.count - a.count),\n stepsWithViolations,\n scannedSteps,\n unscannedSteps: Math.max(0, steps.length - scannedSteps),\n totalSteps: steps.length,\n }\n }\n\n private getRunAccessibilityEnabled(runId: string): boolean | null {\n const artifact = this.getRunArtifact(runId)\n const payload = artifact?.payload\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return null\n const config = (payload as unknown as Record<string, unknown>).config\n if (!config || typeof config !== 'object' || Array.isArray(config)) return null\n\n const configRecord = config as Record<string, unknown>\n const candidates = [configRecord.effectiveConfig, configRecord.parsedConfig]\n let sawConfig = false\n let sawAccessibility = false\n\n for (const candidate of candidates) {\n if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) continue\n sawConfig = true\n const services = (candidate as Record<string, unknown>).services\n if (!services || typeof services !== 'object' || Array.isArray(services)) continue\n const accessibility = (services as Record<string, unknown>).accessibility\n if (!accessibility || typeof accessibility !== 'object' || Array.isArray(accessibility)) continue\n sawAccessibility = true\n const enabled = (accessibility as Record<string, unknown>).enabled\n if (typeof enabled === 'boolean') return enabled\n }\n\n return sawConfig || sawAccessibility ? false : null\n }\n\n getStep(stepId: string): StepRow | undefined {\n const row = this.db.prepare('SELECT * FROM steps WHERE id = ?').get(stepId) as Record<string, unknown> | undefined\n return row ? this.mapStepRow(row) : undefined\n }\n\n insertReasoningTrace(trace: {\n stepId: string\n observeText?: string\n observeDuration?: number\n planReasoning?: string\n planConfidence?: number\n planAction?: unknown\n planDuration?: number\n executeAction?: unknown\n executeDuration?: number\n verifyReasoning?: string\n verifySuccess?: boolean\n verifyDuration?: number\n healAttempts?: unknown[]\n totalDuration?: number\n screenStateBefore?: string\n screenStateAfter?: string\n }): string {\n const id = randomUUID()\n const stmt = this.db.prepare(`\n INSERT INTO reasoning_traces (id, step_id, observe_text, observe_duration, plan_reasoning, plan_confidence, plan_action, plan_duration, execute_action, execute_duration, verify_reasoning, verify_success, verify_duration, heal_attempts, total_duration, screen_state_before, screen_state_after)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n trace.stepId,\n trace.observeText ?? null,\n trace.observeDuration ?? null,\n trace.planReasoning ?? null,\n trace.planConfidence ?? null,\n trace.planAction ? JSON.stringify(trace.planAction) : null,\n trace.planDuration ?? null,\n trace.executeAction ? JSON.stringify(trace.executeAction) : null,\n trace.executeDuration ?? null,\n trace.verifyReasoning ?? null,\n trace.verifySuccess !== undefined ? (trace.verifySuccess ? 1 : 0) : null,\n trace.verifyDuration ?? null,\n trace.healAttempts ? JSON.stringify(trace.healAttempts) : null,\n trace.totalDuration ?? null,\n trace.screenStateBefore ?? null,\n trace.screenStateAfter ?? null,\n )\n return id\n }\n\n getReasoningTrace(runId: string, stepOrder: number): ReasoningTraceRow | undefined {\n const row = this.db.prepare(`\n SELECT rt.* FROM reasoning_traces rt\n INNER JOIN steps s ON s.id = rt.step_id\n WHERE s.run_id = ? AND s.step_order = ?\n `).get(runId, stepOrder) as Record<string, unknown> | undefined\n return row ? this.mapReasoningTraceRow(row) : undefined\n }\n\n // Satisfies LogStorage interface from @vostride/agent-qa-core (structural typing)\n insertLogs(entries: LogEntry[]): void {\n if (entries.length === 0) return\n const stmt = this.db.prepare(\n 'INSERT INTO logs (id, step_id, run_id, level, source, message, data, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',\n )\n const insertAll = this.db.transaction(() => {\n for (const entry of entries) {\n stmt.run(\n entry.id,\n entry.stepId,\n entry.runId,\n entry.level,\n entry.source,\n entry.message,\n JSON.stringify(entry.data),\n entry.timestamp,\n )\n }\n })\n try {\n insertAll()\n } catch {\n // FK violations (e.g. run_id not yet in runs table) are non-fatal for logs\n }\n }\n\n getLogs(opts: {\n runId?: string\n stepId?: string\n level?: string\n source?: string\n limit?: number\n offset?: number\n } = {}): LogEntry[] {\n const conditions: string[] = []\n const params: unknown[] = []\n\n if (opts.runId) {\n conditions.push('run_id = ?')\n params.push(opts.runId)\n }\n if (opts.stepId) {\n conditions.push('step_id = ?')\n params.push(opts.stepId)\n }\n if (opts.level) {\n conditions.push('level = ?')\n params.push(opts.level)\n }\n if (opts.source) {\n conditions.push('source = ?')\n params.push(opts.source)\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n const limit = opts.limit ?? 1000\n const offset = opts.offset ?? 0\n params.push(limit, offset)\n\n const rows = this.db.prepare(\n `SELECT * FROM logs ${where} ORDER BY timestamp ASC LIMIT ? OFFSET ?`,\n ).all(...params) as Record<string, unknown>[]\n\n return rows.map(r => this.mapLogRow(r))\n }\n\n insertExecutionLog(data: InsertExecutionLogInput): void {\n const stmt = this.db.prepare(`\n INSERT INTO execution_logs (id, run_id, step_id, type, name, hook_id, phase, status, duration, stdout, stderr, return_data, variables)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n data.id,\n data.runId,\n data.stepId ?? null,\n data.type,\n data.name,\n data.hookId ?? null,\n data.phase,\n data.status,\n data.duration,\n data.stdout ?? null,\n data.stderr ?? null,\n data.returnData != null ? JSON.stringify(data.returnData) : null,\n data.variables != null ? JSON.stringify(data.variables) : null,\n )\n }\n\n getExecutionLogs(filter: { runId?: string; stepId?: string; type?: string }): ExecutionLogRow[] {\n const conditions: string[] = []\n const params: unknown[] = []\n if (filter.runId) { conditions.push('run_id = ?'); params.push(filter.runId) }\n if (filter.stepId) { conditions.push('step_id = ?'); params.push(filter.stepId) }\n if (filter.type) { conditions.push('type = ?'); params.push(filter.type) }\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n const rows = this.db.prepare(`SELECT * FROM execution_logs ${where} ORDER BY created_at`).all(...params) as Record<string, unknown>[]\n return rows.map(r => ({\n id: r.id as string,\n runId: r.run_id as string,\n stepId: r.step_id as string | null,\n type: r.type as 'hook' | 'appium-script' | 'runjs',\n name: r.name as string,\n hookId: r.hook_id as string | null,\n phase: r.phase as 'setup' | 'teardown' | 'inline',\n status: r.status as 'passed' | 'failed',\n duration: r.duration as number,\n stdout: r.stdout as string | null,\n stderr: r.stderr as string | null,\n returnData: r.return_data ? JSON.parse(r.return_data as string) : null,\n variables: r.variables ? JSON.parse(r.variables as string) : null,\n createdAt: r.created_at as string,\n }))\n }\n\n close(): void {\n this.db.close()\n }\n\n private parseRunAttributes(value: unknown): RunAttributes {\n if (typeof value !== 'string' || value.length === 0) return {}\n try {\n const parsed = JSON.parse(value) as unknown\n if (!isPlainObject(parsed)) return {}\n const attributes: RunAttributes = {}\n for (const [key, attrValue] of Object.entries(parsed)) {\n if (typeof attrValue === 'string') attributes[key] = attrValue\n }\n return attributes\n } catch {\n return {}\n }\n }\n\n private mapRunRow(r: Record<string, unknown>): RunRow {\n return {\n id: r.id as string,\n name: r.name as string,\n filePath: r.file_path as string | null,\n status: r.status as string,\n priority: (r.priority as number) ?? 0,\n duration: r.duration as number,\n attributes: this.parseRunAttributes(r.attributes),\n environment: r.environment as string | null,\n metadata: r.metadata ? JSON.parse(r.metadata as string) : null,\n startedAt: r.started_at as string | null,\n endedAt: r.ended_at as string | null,\n videoPath: (r.video_path as string) ?? null,\n failureSummary: (r.failure_summary as string) ?? null,\n errorLog: (r.error_log as string) ?? null,\n memoryLog: (r.memory_log as string) ?? null,\n testId: (r.test_id as string) ?? null,\n suiteId: (r.suite_id as string) ?? null,\n platform: (r.platform as string) ?? 'web',\n testFileContent: (r.test_file_content as string) ?? null,\n modelName: (r.model_name as string) ?? null,\n llmProvider: (r.llm_provider as string) ?? null,\n parallel: Boolean(r.parallel),\n parentRunId: (r.parent_run_id as string) ?? null,\n attemptNumber: (r.attempt_number as number) ?? 0,\n retryCount: (r.retry_count as number) ?? 0,\n maxRetries: (r.max_retries as number) ?? 0,\n createdAt: r.created_at as string,\n }\n }\n\n private mapRunArtifactRow(r: Record<string, unknown>): RunArtifactRow {\n return {\n runId: r.run_id as string,\n kind: r.kind as RunArtifactKind,\n schemaVersion: r.schema_version as number,\n payload: r.payload ? JSON.parse(r.payload as string) : { schemaVersion: RUN_ARTIFACT_SCHEMA_VERSION },\n finalizedAt: (r.finalized_at as string) ?? null,\n createdAt: r.created_at as string,\n updatedAt: r.updated_at as string,\n }\n }\n\n private mapStepRow(r: Record<string, unknown>): StepRow {\n return {\n id: r.id as string,\n runId: r.run_id as string,\n name: r.name as string,\n status: r.status as string,\n duration: r.duration as number,\n action: r.action ? JSON.parse(r.action as string) : null,\n observation: r.observation as string | null,\n reasoning: r.reasoning as string | null,\n plannedAction: r.planned_action ? JSON.parse(r.planned_action as string) : null,\n result: r.result as string | null,\n error: r.error as string | null,\n screenshotPath: r.screenshot_path as string | null,\n screenshotBeforePath: (r.screenshot_before_path as string) ?? null,\n healingAttempts: r.healing_attempts ? JSON.parse(r.healing_attempts as string) : null,\n retryCount: r.retry_count as number,\n capturedVariables: r.captured_variables ? JSON.parse(r.captured_variables as string) : null,\n stepOrder: r.step_order as number,\n annotationData: r.annotation_data ? JSON.parse(r.annotation_data as string) : null,\n healingScreenshotPaths: r.healing_screenshot_paths ? JSON.parse(r.healing_screenshot_paths as string) : null,\n accessibilityViolations: r.accessibility_violations ? JSON.parse(r.accessibility_violations as string) : null,\n confidence: (r.confidence as number) ?? null,\n promptTokens: (r.prompt_tokens as number) ?? 0,\n completionTokens: (r.completion_tokens as number) ?? 0,\n totalTokens: (r.total_tokens as number) ?? 0,\n subActionsData: r.sub_actions_data ? JSON.parse(r.sub_actions_data as string) : null,\n consoleLogs: r.console_logs ? JSON.parse(r.console_logs as string) : null,\n networkLogs: r.network_logs ? JSON.parse(r.network_logs as string) : null,\n variableSnapshot: r.variable_snapshot ? JSON.parse(r.variable_snapshot as string) : null,\n originalStepName: (r.original_step_name as string) ?? null,\n screenContextBefore: (r.screen_context_before as string) ?? null,\n screenContextAfter: (r.screen_context_after as string) ?? null,\n createdAt: r.created_at as string,\n }\n }\n\n private mapLogRow(r: Record<string, unknown>): LogEntry {\n let data: Record<string, unknown> = {}\n if (r.data) {\n try { data = JSON.parse(r.data as string) } catch { /* invalid JSON → empty */ }\n }\n return {\n id: r.id as string,\n stepId: (r.step_id as string) ?? null,\n runId: r.run_id as string,\n level: r.level as LogEntry['level'],\n source: r.source as LogEntry['source'],\n message: r.message as string,\n data,\n timestamp: r.timestamp as string,\n }\n }\n\n private mapReasoningTraceRow(r: Record<string, unknown>): ReasoningTraceRow {\n return {\n id: r.id as string,\n stepId: r.step_id as string,\n observeText: r.observe_text as string | null,\n observeDuration: r.observe_duration as number | null,\n planReasoning: r.plan_reasoning as string | null,\n planConfidence: r.plan_confidence as number | null,\n planAction: r.plan_action ? JSON.parse(r.plan_action as string) : null,\n planDuration: r.plan_duration as number | null,\n executeAction: r.execute_action ? JSON.parse(r.execute_action as string) : null,\n executeDuration: r.execute_duration as number | null,\n verifyReasoning: r.verify_reasoning as string | null,\n verifySuccess: r.verify_success !== null ? Boolean(r.verify_success) : null,\n verifyDuration: r.verify_duration as number | null,\n healAttempts: r.heal_attempts ? JSON.parse(r.heal_attempts as string) : null,\n totalDuration: r.total_duration as number | null,\n screenStateBefore: r.screen_state_before as string | null,\n screenStateAfter: r.screen_state_after as string | null,\n createdAt: r.created_at as string,\n }\n }\n}\n","import { copyFile, mkdir, rename, stat, unlink } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, relative, resolve } from 'node:path'\nimport { isCanonicalRunId } from '@vostride/agent-qa-ids'\nimport { createBetterSqlite3Database, generateRunId, type BetterSqlite3Database } from '@vostride/agent-qa-core'\n\ninterface RunIdMigrationRunRow {\n id: string\n parent_run_id: string | null\n video_path: string | null\n}\n\ninterface RunIdMigrationStepRow {\n id: string\n screenshot_path: string | null\n screenshot_before_path: string | null\n healing_screenshot_paths: string | null\n}\n\ninterface FlatVideoFileMove {\n fromPath: string\n toPath: string\n}\n\nexport interface RunIdMigrationOptions {\n dbPath: string\n screenshotsDir?: string\n videosDir?: string\n logger?: (message: string) => void\n}\n\nexport interface RunIdMigrationResult {\n migratedRunCount: number\n totalRunCount: number\n runIdMap: Record<string, string>\n preservedRunIds: string[]\n updatedScreenshotRows: number\n updatedVideoRows: number\n renamedScreenshotDirs: Array<{ from: string; to: string }>\n renamedVideoDirs: Array<{ from: string; to: string }>\n missingArtifacts: string[]\n}\n\nfunction rewriteArtifactPath(\n value: string | null,\n mapping: Map<string, string>,\n rootDir?: string,\n apiPrefix?: '/api/screenshots/' | '/api/videos/',\n): string | null {\n if (!value) return value\n const trimmed = value.trim()\n if (!trimmed) return value\n\n let relativePath: string\n let mode: 'relative' | 'absolute' | 'api' = 'relative'\n\n if (apiPrefix && trimmed.startsWith(apiPrefix)) {\n relativePath = trimmed.slice(apiPrefix.length)\n mode = 'api'\n } else if (rootDir && isAbsolute(trimmed)) {\n const resolvedRoot = resolve(rootDir)\n const resolvedValue = resolve(trimmed)\n const insideRoot = relative(resolvedRoot, resolvedValue)\n if (!insideRoot || insideRoot.startsWith('..') || isAbsolute(insideRoot)) {\n return value\n }\n relativePath = insideRoot\n mode = 'absolute'\n } else {\n relativePath = trimmed\n }\n\n const segments = relativePath.split(/[\\\\/]+/).filter(Boolean)\n if (segments.length === 0) return value\n\n const nextHead = mapping.get(segments[0])\n if (!nextHead) return value\n\n const rewrittenRelative = [nextHead, ...segments.slice(1)].join('/')\n if (mode === 'api' && apiPrefix) return `${apiPrefix}${rewrittenRelative}`\n if (mode === 'absolute' && rootDir) return resolve(rootDir, rewrittenRelative)\n return rewrittenRelative\n}\n\nfunction rewriteJsonStringArray(\n value: string | null,\n mapping: Map<string, string>,\n rootDir?: string,\n apiPrefix?: '/api/screenshots/' | '/api/videos/',\n): string | null {\n if (!value) return value\n try {\n const parsed = JSON.parse(value) as unknown\n if (!Array.isArray(parsed)) return value\n let changed = false\n const rewritten = parsed.map((entry) => {\n if (typeof entry !== 'string') return entry\n const nextValue = rewriteArtifactPath(entry, mapping, rootDir, apiPrefix)\n if (nextValue !== entry) changed = true\n return nextValue\n })\n return changed ? JSON.stringify(rewritten) : value\n } catch {\n return value\n }\n}\n\nfunction getRelativeArtifactPath(\n value: string,\n rootDir: string,\n apiPrefix: '/api/screenshots/' | '/api/videos/',\n): { relativePath: string; sourcePath: string } | null {\n const trimmed = value.trim()\n if (!trimmed) return null\n const resolvedRoot = resolve(rootDir)\n\n if (trimmed.startsWith(apiPrefix)) {\n const relativePath = trimmed.slice(apiPrefix.length)\n const sourcePath = resolve(resolvedRoot, relativePath)\n const insideRoot = relative(resolvedRoot, sourcePath)\n if (!insideRoot || insideRoot.startsWith('..') || isAbsolute(insideRoot)) return null\n return { relativePath: insideRoot, sourcePath }\n }\n\n if (isAbsolute(trimmed)) {\n const sourcePath = resolve(trimmed)\n const relativePath = relative(resolvedRoot, sourcePath)\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) return null\n return { relativePath, sourcePath }\n }\n\n const sourcePath = resolve(resolvedRoot, trimmed)\n const relativePath = relative(resolvedRoot, sourcePath)\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) return null\n return { relativePath, sourcePath }\n}\n\nfunction rewriteRunVideoPath(\n run: RunIdMigrationRunRow,\n mapping: Map<string, string>,\n videosDir: string | undefined,\n flatVideoFileMoves: FlatVideoFileMove[],\n): string | null {\n const nextVideoPath = rewriteArtifactPath(run.video_path, mapping, videosDir, '/api/videos/')\n if (nextVideoPath !== run.video_path) return nextVideoPath\n if (!run.video_path || !videosDir) return run.video_path\n\n const newRunId = mapping.get(run.id)\n if (!newRunId) return run.video_path\n\n const artifact = getRelativeArtifactPath(run.video_path, videosDir, '/api/videos/')\n if (!artifact) return run.video_path\n\n const segments = artifact.relativePath.split(/[\\\\/]+/).filter(Boolean)\n if (segments.length !== 1) return run.video_path\n\n const fileName = basename(segments[0])\n if (!fileName) return run.video_path\n\n const rewrittenRelative = `${newRunId}/${fileName}`\n flatVideoFileMoves.push({\n fromPath: artifact.sourcePath,\n toPath: resolve(videosDir, rewrittenRelative),\n })\n return rewrittenRelative\n}\n\nasync function renameDirectoryIfPresent(\n fromPath: string,\n toPath: string,\n renamed: Array<{ from: string; to: string }>,\n missingArtifacts: string[],\n logger?: (message: string) => void,\n): Promise<void> {\n try {\n const info = await stat(fromPath)\n if (!info.isDirectory()) return\n await mkdir(dirname(toPath), { recursive: true })\n await rename(fromPath, toPath)\n renamed.push({ from: fromPath, to: toPath })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n missingArtifacts.push(fromPath)\n return\n }\n logger?.(`Skipping artifact rename ${fromPath} -> ${toPath}: ${String(error)}`)\n }\n}\n\nasync function moveFileIfPresent(\n fromPath: string,\n toPath: string,\n missingArtifacts: string[],\n logger?: (message: string) => void,\n): Promise<void> {\n try {\n const info = await stat(fromPath)\n if (!info.isFile()) return\n await mkdir(dirname(toPath), { recursive: true })\n try {\n await rename(fromPath, toPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'EXDEV') {\n await copyFile(fromPath, toPath)\n await unlink(fromPath)\n return\n }\n throw error\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n missingArtifacts.push(fromPath)\n return\n }\n logger?.(`Skipping artifact move ${fromPath} -> ${toPath}: ${String(error)}`)\n }\n}\n\nfunction buildRunIdMap(runIds: string[]): Map<string, string> {\n const mapping = new Map<string, string>()\n const assignedIds = new Set(runIds)\n\n for (const runId of runIds) {\n if (isCanonicalRunId(runId)) continue\n\n let nextId = generateRunId()\n while (assignedIds.has(nextId) || mappingHasValue(mapping, nextId)) {\n nextId = generateRunId()\n }\n mapping.set(runId, nextId)\n assignedIds.add(nextId)\n }\n\n return mapping\n}\n\nfunction mappingHasValue(mapping: Map<string, string>, value: string): boolean {\n for (const mappedValue of mapping.values()) {\n if (mappedValue === value) return true\n }\n return false\n}\n\nfunction runForeignKeyCheck(db: BetterSqlite3Database): void {\n const violations = db.pragma('foreign_key_check') as Array<Record<string, unknown>>\n if (violations.length === 0) return\n throw new Error(`Run-id migration left ${violations.length} foreign key violation(s)`)\n}\n\nexport async function migrateWorkspaceRunIds({\n dbPath,\n screenshotsDir,\n videosDir,\n logger,\n}: RunIdMigrationOptions): Promise<RunIdMigrationResult> {\n const db = createBetterSqlite3Database(dbPath)\n const renamedScreenshotDirs: Array<{ from: string; to: string }> = []\n const renamedVideoDirs: Array<{ from: string; to: string }> = []\n const flatVideoFileMoves: FlatVideoFileMove[] = []\n const missingArtifacts: string[] = []\n\n try {\n const runs = db.prepare('SELECT id, parent_run_id, video_path FROM runs ORDER BY rowid ASC').all() as RunIdMigrationRunRow[]\n const steps = db.prepare('SELECT id, screenshot_path, screenshot_before_path, healing_screenshot_paths FROM steps ORDER BY rowid ASC').all() as RunIdMigrationStepRow[]\n const mapping = buildRunIdMap(runs.map((run) => run.id))\n\n if (mapping.size === 0) {\n return {\n migratedRunCount: 0,\n totalRunCount: runs.length,\n runIdMap: {},\n preservedRunIds: runs.map((run) => run.id),\n updatedScreenshotRows: 0,\n updatedVideoRows: 0,\n renamedScreenshotDirs,\n renamedVideoDirs,\n missingArtifacts,\n }\n }\n\n const updateStepsRunId = db.prepare('UPDATE steps SET run_id = ? WHERE run_id = ?')\n const updateLogsRunId = db.prepare('UPDATE logs SET run_id = ? WHERE run_id = ?')\n const updateExecutionLogsRunId = db.prepare('UPDATE execution_logs SET run_id = ? WHERE run_id = ?')\n const updateRunsParentId = db.prepare('UPDATE runs SET parent_run_id = ? WHERE parent_run_id = ?')\n const updateRunId = db.prepare('UPDATE runs SET id = ? WHERE id = ?')\n const updateStepArtifacts = db.prepare(`\n UPDATE steps\n SET screenshot_path = ?, screenshot_before_path = ?, healing_screenshot_paths = ?\n WHERE id = ?\n `)\n const updateRunVideoPath = db.prepare('UPDATE runs SET video_path = ? WHERE id = ?')\n\n let updatedScreenshotRows = 0\n let updatedVideoRows = 0\n\n db.pragma('foreign_keys = OFF')\n const migrate = db.transaction(() => {\n for (const step of steps) {\n const nextScreenshotPath = rewriteArtifactPath(step.screenshot_path, mapping, screenshotsDir, '/api/screenshots/')\n const nextScreenshotBeforePath = rewriteArtifactPath(step.screenshot_before_path, mapping, screenshotsDir, '/api/screenshots/')\n const nextHealingScreenshotPaths = rewriteJsonStringArray(step.healing_screenshot_paths, mapping, screenshotsDir, '/api/screenshots/')\n\n if (\n nextScreenshotPath !== step.screenshot_path\n || nextScreenshotBeforePath !== step.screenshot_before_path\n || nextHealingScreenshotPaths !== step.healing_screenshot_paths\n ) {\n updateStepArtifacts.run(\n nextScreenshotPath,\n nextScreenshotBeforePath,\n nextHealingScreenshotPaths,\n step.id,\n )\n updatedScreenshotRows += 1\n }\n }\n\n for (const run of runs) {\n const nextVideoPath = rewriteRunVideoPath(run, mapping, videosDir, flatVideoFileMoves)\n if (nextVideoPath !== run.video_path) {\n updateRunVideoPath.run(nextVideoPath, run.id)\n updatedVideoRows += 1\n }\n }\n\n for (const [oldId, newId] of mapping) {\n updateStepsRunId.run(newId, oldId)\n updateLogsRunId.run(newId, oldId)\n updateExecutionLogsRunId.run(newId, oldId)\n updateRunsParentId.run(newId, oldId)\n }\n\n for (const [oldId, newId] of mapping) {\n updateRunId.run(newId, oldId)\n }\n\n runForeignKeyCheck(db)\n })\n\n migrate()\n db.pragma('foreign_keys = ON')\n\n if (screenshotsDir) {\n for (const [oldId, newId] of mapping) {\n await renameDirectoryIfPresent(\n resolve(screenshotsDir, oldId),\n resolve(screenshotsDir, newId),\n renamedScreenshotDirs,\n missingArtifacts,\n logger,\n )\n }\n\n }\n\n if (videosDir) {\n for (const [oldId, newId] of mapping) {\n await renameDirectoryIfPresent(\n resolve(videosDir, oldId),\n resolve(videosDir, newId),\n renamedVideoDirs,\n missingArtifacts,\n logger,\n )\n }\n\n for (const move of flatVideoFileMoves) {\n await moveFileIfPresent(move.fromPath, move.toPath, missingArtifacts, logger)\n }\n }\n\n return {\n migratedRunCount: mapping.size,\n totalRunCount: runs.length,\n runIdMap: Object.fromEntries(mapping),\n preservedRunIds: runs.filter((run) => !mapping.has(run.id)).map((run) => run.id),\n updatedScreenshotRows,\n updatedVideoRows,\n renamedScreenshotDirs,\n renamedVideoDirs,\n missingArtifacts,\n }\n } finally {\n db.close()\n }\n}\n","import { existsSync, mkdirSync, renameSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { DEFAULT_AGENT_QA_RUNS_DB_PATH, LEGACY_AGENT_QA_DASHBOARD_DB_PATH } from '@vostride/agent-qa-core'\n\nconst RUNS_DB_PATH_FALLBACK = DEFAULT_AGENT_QA_RUNS_DB_PATH || '.agent-qa/runs.db'\nconst LEGACY_DB_PATH_FALLBACK = LEGACY_AGENT_QA_DASHBOARD_DB_PATH || '.agent-qa/dashboard.db'\n\nexport interface ResolveDashboardDbPathOptions {\n configDir: string\n configuredDbPath?: string\n}\n\nexport function resolveDashboardDbPath({\n configDir,\n configuredDbPath,\n}: ResolveDashboardDbPathOptions): string {\n const configured = configuredDbPath?.trim()\n if (configured) {\n return resolve(configDir, configured)\n }\n\n const defaultPath = resolve(configDir, RUNS_DB_PATH_FALLBACK)\n const legacyPath = resolve(configDir, LEGACY_DB_PATH_FALLBACK)\n\n if (!existsSync(defaultPath) && existsSync(legacyPath)) {\n mkdirSync(dirname(defaultPath), { recursive: true })\n renameSync(legacyPath, defaultPath)\n }\n\n return defaultPath\n}\n","import { copyFile, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { buildInternalRunAttributes, redactSecretValue, validateTrustedRunAttributes } from '@vostride/agent-qa-core'\nimport type { Reporter, RunArtifactReporterContext, RunSummary, TestDefinition, StepResult, TestResult, SuiteDefinition, SuiteSummary, HookEvent, HookResultEvent, SecretRedactor } from '@vostride/agent-qa-core'\nimport type { RunAttributes } from '@vostride/agent-qa-core'\nimport type { DashboardDatabase } from '../db/database.js'\n\nfunction isPathInside(rootDir: string, candidatePath: string): boolean {\n const relativePath = relative(rootDir, candidatePath)\n return Boolean(relativePath) && !relativePath.startsWith('..') && !isAbsolute(relativePath)\n}\n\nasync function moveArtifactFile(sourcePath: string, targetPath: string): Promise<void> {\n await mkdir(dirname(targetPath), { recursive: true })\n try {\n await rename(sourcePath, targetPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'EXDEV') {\n await copyFile(sourcePath, targetPath)\n await unlink(sourcePath)\n return\n }\n throw error\n }\n}\n\nasync function materializeVideoPath(videoPath: string | undefined, artifactsDir: string, runId: string): Promise<string | undefined> {\n if (!videoPath) return videoPath\n const trimmed = videoPath.trim()\n if (!trimmed) return videoPath\n\n const videosDir = resolve(artifactsDir, 'videos')\n let relativePath: string\n let sourcePath: string\n\n if (isAbsolute(trimmed)) {\n sourcePath = resolve(trimmed)\n if (!isPathInside(videosDir, sourcePath)) {\n return trimmed\n }\n relativePath = relative(videosDir, sourcePath)\n } else {\n relativePath = trimmed.replace(/\\\\/g, '/')\n sourcePath = resolve(videosDir, relativePath)\n if (!isPathInside(videosDir, sourcePath)) {\n return relativePath\n }\n }\n\n const normalizedRelativePath = relativePath.replace(/\\\\/g, '/')\n if (normalizedRelativePath.startsWith(`${runId}/`)) {\n return normalizedRelativePath\n }\n\n const targetRelativePath = `${runId}/${basename(normalizedRelativePath)}`\n const targetPath = resolve(videosDir, targetRelativePath)\n try {\n await moveArtifactFile(sourcePath, targetPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return targetRelativePath\n }\n throw error\n }\n\n return targetRelativePath\n}\n\nfunction normalizeVideoPath(videoPath: string | undefined, artifactsDir: string): string | undefined {\n if (!videoPath) return videoPath\n const trimmed = videoPath.trim()\n if (!trimmed || !isAbsolute(trimmed)) return trimmed\n\n const videosDir = resolve(artifactsDir, 'videos')\n const relativePath = relative(videosDir, resolve(trimmed))\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) {\n return trimmed\n }\n return relativePath.replace(/\\\\/g, '/')\n}\n\ninterface TestState {\n runId: string\n name: string\n startedAt: string\n filePath: string\n stepCount: number\n executionKey: string\n attributes: RunAttributes\n}\n\ntype ArtifactReporterContext = RunArtifactReporterContext\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction readAttributesRecord(value: unknown): RunAttributes | null {\n try {\n const attributes = validateTrustedRunAttributes(value, 'run artifact attributes')\n return Object.keys(attributes).length > 0 ? attributes : null\n } catch {\n return null\n }\n}\n\nfunction readArtifactRuntimePlatform(context?: ArtifactReporterContext): string | undefined {\n const runtime = context?.artifact?.runtime\n if (!isRecord(runtime)) return undefined\n const platform = runtime.platform\n return typeof platform === 'string' && platform.trim() ? platform : undefined\n}\n\nfunction resolveRunPlatform(source: unknown, context?: ArtifactReporterContext): string | undefined {\n if (isRecord(source)) {\n const resolvedPlatform = source.resolvedPlatform\n if (typeof resolvedPlatform === 'string' && resolvedPlatform.trim()) return resolvedPlatform\n }\n return readArtifactRuntimePlatform(context)\n}\n\nclass FatalReporterError extends Error {\n readonly fatal = true\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options)\n this.name = 'FatalReporterError'\n }\n}\n\nexport class DashboardReporter implements Reporter {\n private db: DashboardDatabase\n private artifactsDir: string\n private suiteRunId: string | null = null\n private currentSuiteId: string | null = null\n private runIdToState = new Map<string, TestState>()\n private executionKeyToRunId = new Map<string, string>()\n private nameToCurrentRunId = new Map<string, string>()\n private completedResultRunIds = new Map<string, string>()\n private runStartTime: string | null = null\n private onRunCreated?: (runId: string) => void\n private redactor?: SecretRedactor\n\n constructor({\n db,\n artifactsDir = '.agent-qa/artifacts',\n onRunCreated,\n redactor,\n }: {\n db: DashboardDatabase\n artifactsDir?: string\n onRunCreated?: (runId: string) => void\n redactor?: SecretRedactor\n }) {\n this.db = db\n this.artifactsDir = artifactsDir\n this.onRunCreated = onRunCreated\n this.redactor = redactor\n }\n\n private redactValue<T>(value: T): T {\n return redactSecretValue(value, this.redactor)\n }\n\n private redactString(value: string | undefined): string | undefined {\n return value === undefined ? undefined : this.redactValue(value)\n }\n\n private sanitizeSecretsFileMetadata(value: unknown): unknown {\n if (value === null || value === undefined) return value\n if (!isRecord(value)) return value\n return {\n path: typeof value.path === 'string' || value.path === null ? value.path : null,\n status: typeof value.status === 'string' ? value.status : 'loaded',\n ...(typeof value.count === 'number' ? { count: value.count } : {}),\n }\n }\n\n private sanitizeArtifactPayload<T extends Record<string, unknown>>(payload: T): T {\n const safePayload = this.redactValue(payload) as Record<string, unknown>\n const config = safePayload.config\n if (isRecord(config) && 'secretsFile' in config) {\n safePayload.config = {\n ...config,\n secretsFile: this.sanitizeSecretsFileMetadata(config.secretsFile),\n }\n }\n return safePayload as T\n }\n\n private fallbackAttributes(): RunAttributes {\n return buildInternalRunAttributes({ trigger: 'cli', runner: 'local' })\n }\n\n private readAttributesFromEnv(): RunAttributes | null {\n const raw = process.env.AGENT_QA_RUN_ATTRIBUTES_JSON\n if (!raw) return null\n try {\n return readAttributesRecord(JSON.parse(raw))\n } catch {\n return null\n }\n }\n\n private resolveAttributes(context?: ArtifactReporterContext, existing?: { attributes?: RunAttributes } | null): RunAttributes {\n const contextAttributes = readAttributesRecord(context?.artifact?.metadata?.attributes)\n if (contextAttributes) return contextAttributes\n const envAttributes = this.readAttributesFromEnv()\n if (envAttributes) return envAttributes\n if (existing?.attributes && Object.keys(existing.attributes).length > 0) return existing.attributes\n if (context?.parentRunId) {\n const parent = this.db.getRun(context.parentRunId)\n if (parent?.attributes && Object.keys(parent.attributes).length > 0) return parent.attributes\n }\n if (this.suiteRunId) {\n const parent = this.db.getRun(this.suiteRunId)\n if (parent?.attributes && Object.keys(parent.attributes).length > 0) return parent.attributes\n }\n return this.fallbackAttributes()\n }\n\n private withAttributeMetadata<T extends Record<string, unknown>>(payload: T, attributes: RunAttributes): T {\n const metadata = isRecord(payload.metadata) ? payload.metadata : {}\n return {\n ...payload,\n metadata: {\n ...metadata,\n attributes,\n },\n }\n }\n\n onSuiteStart(suite: SuiteDefinition, context?: ArtifactReporterContext): void {\n const startedAt = new Date().toISOString()\n const suiteId = (suite as any)['suite-id'] ?? null\n const safeSuite = this.redactValue(suite)\n this.currentSuiteId = suiteId\n const requestedRunId = context?.runId ?? process.env.AGENT_QA_SUITE_QUEUE_ID\n const existingSuiteRun = requestedRunId ? this.db.getRun(requestedRunId) : null\n const attributes = this.resolveAttributes(context, existingSuiteRun)\n const platform = resolveRunPlatform(suite, context) ?? 'web'\n if (requestedRunId) {\n this.suiteRunId = requestedRunId\n if (existingSuiteRun) {\n this.db.updateRun(requestedRunId, {\n name: safeSuite.name,\n status: 'running',\n startedAt,\n platform,\n suiteId: suiteId ?? undefined,\n attributes,\n })\n } else {\n this.db.insertRun({\n id: requestedRunId,\n name: safeSuite.name,\n status: 'running',\n duration: 0,\n attributes,\n startedAt,\n endedAt: startedAt,\n platform,\n suiteId: suiteId ?? undefined,\n })\n }\n } else {\n this.suiteRunId = this.db.insertRun({\n name: safeSuite.name,\n status: 'running',\n duration: 0,\n attributes,\n startedAt,\n endedAt: startedAt,\n platform,\n suiteId: suiteId ?? undefined,\n })\n }\n if (this.suiteRunId) {\n this.writeArtifact(() => {\n this.db.insertRunArtifact({\n runId: this.suiteRunId!,\n kind: 'suite-parent',\n payload: this.sanitizeArtifactPayload(this.withAttributeMetadata({\n source: {\n kind: 'suite',\n suiteId,\n name: safeSuite.name,\n resolvedDefinition: safeSuite,\n loadStatus: 'loaded',\n },\n ...(context?.artifact ?? {}),\n }, attributes)),\n })\n })\n }\n }\n\n onSuiteEnd(summary: SuiteSummary): void {\n if (!this.suiteRunId) return\n const safeSummary = this.redactValue(summary)\n this.db.updateRun(this.suiteRunId, {\n status: safeSummary.status,\n duration: safeSummary.duration,\n endedAt: new Date().toISOString(),\n })\n this.writeArtifact(() => {\n this.stageSuiteSummary(this.suiteRunId!, safeSummary)\n this.db.finalizeRunArtifact(this.suiteRunId!, {\n runtime: {\n status: safeSummary.status,\n duration: safeSummary.duration,\n endedAt: new Date().toISOString(),\n },\n })\n })\n this.suiteRunId = null\n this.currentSuiteId = null\n }\n\n onRunStart(_tests: TestDefinition[]): void {\n this.runStartTime = new Date().toISOString()\n }\n\n async onTestStart(test: TestDefinition, filePath: string, context?: ArtifactReporterContext): Promise<void> {\n const startedAt = new Date().toISOString()\n const testId = (test as any)['test-id'] ?? null\n const executionKey = this.createExecutionKey(test, filePath, startedAt)\n const existingStateRunId = this.executionKeyToRunId.get(executionKey)\n if (existingStateRunId && this.runIdToState.has(existingStateRunId)) return\n\n const modelName = process.env.AGENT_QA_LLM_MODEL ?? undefined\n const llmProvider = process.env.AGENT_QA_LLM_PROVIDER ?? undefined\n\n // Insert a 'running' row immediately so the run is visible even if the\n // process is killed before onTestEnd fires (e.g. SIGKILL on cancel).\n const platform = resolveRunPlatform(test, context)\n\n // Snapshot the test file content at run time so we can see exactly what\n // was executed, even if the file is edited later.\n let testFileContent: string | undefined\n try {\n testFileContent = await readFile(filePath, 'utf-8')\n } catch { /* file may not be accessible — non-fatal */ }\n const safeTest = this.redactValue(test)\n const safeTestFileContent = this.redactString(testFileContent)\n const safeTestMeta = this.redactValue(safeTest.meta as Record<string, unknown> | undefined)\n\n const parentRunId = context?.parentRunId ?? process.env.AGENT_QA_PARENT_RUN_ID\n const existingRunId = context?.runId ?? process.env.AGENT_QA_RUN_ID\n const existingRun = existingRunId ? this.db.getRun(existingRunId) : null\n const attributeContext = parentRunId && context?.parentRunId !== parentRunId\n ? { ...context, parentRunId }\n : context\n const attributes = this.resolveAttributes(attributeContext, existingRun)\n let runId: string\n\n if (parentRunId) {\n // Retry attempt — always INSERT a new child run linked to the parent\n const attemptNumber = parseInt(process.env.AGENT_QA_ATTEMPT_NUMBER ?? '1', 10)\n const maxRetries = parseInt(process.env.AGENT_QA_MAX_RETRIES ?? '0', 10)\n runId = this.db.insertRun({\n id: existingRunId,\n name: safeTest.name,\n filePath,\n status: 'running',\n duration: 0,\n attributes,\n metadata: safeTestMeta,\n startedAt,\n endedAt: startedAt,\n parentRunId: this.suiteRunId ?? parentRunId,\n\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n attemptNumber,\n maxRetries,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n })\n } else if (existingRunId) {\n if (existingRun) {\n // Run row already exists from JobQueue.enqueue() — update it instead of inserting\n this.db.updateRun(existingRunId, {\n status: 'running',\n startedAt,\n endedAt: startedAt,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n attributes,\n })\n // Also update fields that insertPendingRun didn't set\n this.db.updateRunMetadata(existingRunId, {\n metadata: safeTestMeta,\n attributes,\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n })\n } else {\n this.db.insertRun({\n id: existingRunId,\n name: safeTest.name,\n filePath,\n status: 'running',\n duration: 0,\n attributes,\n metadata: safeTestMeta,\n startedAt,\n endedAt: startedAt,\n parentRunId: this.suiteRunId ?? undefined,\n\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n })\n }\n runId = existingRunId\n } else {\n runId = this.db.insertRun({\n name: safeTest.name,\n filePath,\n status: 'running',\n duration: 0,\n attributes,\n metadata: safeTestMeta,\n startedAt,\n endedAt: startedAt,\n parentRunId: this.suiteRunId ?? undefined,\n\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n })\n }\n\n this.runIdToState.set(runId, {\n runId,\n name: test.name,\n startedAt,\n filePath,\n stepCount: 0,\n executionKey,\n attributes,\n })\n this.executionKeyToRunId.set(executionKey, runId)\n this.nameToCurrentRunId.set(test.name, runId)\n\n const artifactKind = context?.artifact?.kind ?? (this.suiteRunId ? 'suite-child' : 'test')\n const fallbackArtifact = {\n source: {\n kind: 'test',\n testId,\n name: safeTest.name,\n filePath,\n rawYaml: safeTestFileContent ?? null,\n resolvedDefinition: safeTest,\n loadStatus: 'loaded',\n },\n runtime: {\n status: 'running',\n startedAt,\n platform,\n },\n }\n this.writeArtifact(() => {\n this.db.insertRunArtifact({\n runId,\n kind: artifactKind,\n payload: this.sanitizeArtifactPayload(this.withAttributeMetadata({\n ...fallbackArtifact,\n ...(context?.artifact ?? {}),\n }, attributes)),\n })\n if (this.suiteRunId && typeof context?.artifact?.suiteIndex === 'number') {\n this.stageSuiteChildLink(this.suiteRunId, context.artifact.suiteIndex, runId)\n }\n })\n\n this.onRunCreated?.(runId)\n }\n\n async onStepEnd(result: StepResult, testName: string): Promise<void> {\n const state = this.getStateByTestName(testName)\n if (!state) return\n\n const runId = state.runId\n const stepOrder = state.stepCount++\n\n // Persist step immediately so it survives process kill on cancellation\n await this.persistStep(result, runId, stepOrder)\n }\n\n async onTestEnd(result: TestResult): Promise<void> {\n const state = this.getStateForResult(result)\n const safeResult = this.redactValue(result)\n const endedAt = new Date().toISOString()\n const errorLog = this.buildResultErrorLog(safeResult)\n let fallbackResultAttributes: RunAttributes | undefined\n\n let runId: string\n if (state) {\n // The run row was already inserted in onTestStart with status='running'.\n // Update it with the final status, duration, and summary.\n runId = state.runId\n const normalizedVideoPath = await materializeVideoPath(safeResult.videoPath, this.artifactsDir, runId)\n this.db.updateRun(runId, {\n name: safeResult.name,\n status: safeResult.status,\n duration: safeResult.duration,\n endedAt,\n failureSummary: safeResult.failureSummary,\n errorLog,\n videoPath: normalizedVideoPath,\n })\n if (safeResult.metadata) {\n this.db.updateRunMetadata(runId, { metadata: safeResult.metadata as Record<string, unknown> })\n }\n if ((safeResult as any).memoryLog) {\n this.db.updateRun(runId, {\n memoryLog: JSON.stringify((safeResult as any).memoryLog),\n })\n }\n } else {\n // Fallback: onTestStart was never called (programmatic usage).\n // Insert the run directly with the final result.\n const modelName = process.env.AGENT_QA_LLM_MODEL ?? undefined\n const llmProvider = process.env.AGENT_QA_LLM_PROVIDER ?? undefined\n const resultMetadata = isRecord(safeResult.metadata) ? safeResult.metadata : undefined\n const resultAttributes = readAttributesRecord(resultMetadata?.attributes)\n const attributes = resultAttributes ?? this.resolveAttributes()\n fallbackResultAttributes = attributes\n const fallbackRunId = process.env.AGENT_QA_RUN_ID || undefined\n\n let testFileContent: string | undefined\n if (result.filePath) {\n try {\n testFileContent = await readFile(result.filePath, 'utf-8')\n } catch { /* non-fatal */ }\n }\n\n runId = this.db.insertRun({\n id: fallbackRunId,\n name: safeResult.name,\n filePath: safeResult.filePath,\n status: safeResult.status,\n duration: safeResult.duration,\n attributes,\n metadata: safeResult.metadata,\n startedAt: endedAt,\n endedAt,\n parentRunId: this.suiteRunId ?? undefined,\n\n videoPath: undefined,\n failureSummary: safeResult.failureSummary,\n platform: (safeResult.metadata as Record<string, unknown> | undefined)?.platform as string | undefined,\n testFileContent: this.redactString(testFileContent),\n modelName,\n llmProvider,\n suiteId: this.currentSuiteId ?? undefined,\n })\n const normalizedVideoPath = await materializeVideoPath(safeResult.videoPath, this.artifactsDir, runId)\n this.db.updateRun(runId, { videoPath: normalizedVideoPath })\n if (errorLog) {\n this.db.updateRun(runId, { errorLog })\n }\n this.writeArtifact(() => {\n this.db.insertRunArtifact({\n runId,\n kind: this.suiteRunId ? 'suite-child' : 'test',\n payload: {\n source: {\n kind: 'test',\n name: safeResult.name,\n filePath: safeResult.filePath,\n rawYaml: this.redactString(testFileContent) ?? null,\n loadStatus: 'runtime-error',\n },\n metadata: { attributes },\n },\n })\n })\n }\n\n // Steps were already persisted in onStepEnd. If onStepEnd was not called\n // (e.g. programmatic usage without per-step callbacks), persist any remaining.\n if (!state || state.stepCount === 0) {\n for (let i = 0; i < safeResult.steps.length; i++) {\n await this.persistStep(safeResult.steps[i], runId, i)\n }\n }\n\n const storedVideoPath = this.db.getRun(runId)?.videoPath ?? normalizeVideoPath(safeResult.videoPath, this.artifactsDir)\n const memoryLog = (safeResult as any).memoryLog\n this.writeArtifact(() => {\n const patch: Record<string, unknown> = {\n runtime: {\n status: safeResult.status,\n duration: safeResult.duration,\n endedAt,\n videoPath: storedVideoPath ?? null,\n failureSummary: safeResult.failureSummary ?? null,\n errorLog: errorLog ?? null,\n metadata: safeResult.metadata ?? null,\n },\n }\n if ((safeResult.status === 'failed' || safeResult.status === 'cancelled') && (safeResult.failureSummary || errorLog)) {\n patch.errors = [{\n code: safeResult.status,\n phase: 'test',\n message: safeResult.failureSummary ?? errorLog!,\n }]\n }\n if (memoryLog) {\n patch.memory = { log: memoryLog }\n }\n patch.metadata = { attributes: state?.attributes ?? fallbackResultAttributes ?? this.resolveAttributes() }\n const artifact = this.db.getRunArtifact(runId)\n if (artifact && !artifact.finalizedAt) {\n this.db.stageRunArtifact(runId, patch as any)\n }\n })\n\n this.completedResultRunIds.set(this.resultKey(result), runId)\n this.deleteState(state, result.name)\n }\n\n onRunEnd(summary: RunSummary): void {\n for (const result of summary.results) {\n const runId = this.completedResultRunIds.get(this.resultKey(result))\n if (!runId) continue\n this.writeArtifact(() => {\n const artifact = this.db.getRunArtifact(runId)\n if (!artifact || artifact.finalizedAt) return\n const memoryLog = this.redactValue((result as any).memoryLog)\n if (memoryLog) {\n this.db.updateRun(runId, { memoryLog: JSON.stringify(memoryLog) })\n this.db.stageRunArtifact(runId, { memory: { log: memoryLog } as any })\n }\n this.db.finalizeRunArtifact(runId)\n })\n this.completedResultRunIds.delete(this.resultKey(result))\n }\n }\n\n onHookEnd(event: HookResultEvent): void {\n const safeEvent = this.redactValue(event)\n const runId = safeEvent.runId ?? this.getCurrentRunId() ?? this.suiteRunId\n if (!runId) return\n\n try {\n this.db.insertExecutionLog({\n id: safeEvent.hookExecutionId,\n runId,\n stepId: safeEvent.stepId ?? null,\n type: safeEvent.type ?? 'hook',\n name: safeEvent.hookName,\n hookId: safeEvent.hookId ?? null,\n phase: safeEvent.phase,\n status: safeEvent.status,\n duration: safeEvent.duration,\n stdout: safeEvent.stdout || null,\n stderr: safeEvent.stderr || null,\n variables: Object.keys(safeEvent.variables).length > 0 ? safeEvent.variables : null,\n })\n } catch {\n // DB write failure should not crash the test\n }\n }\n\n private getCurrentRunId(): string | null {\n for (const state of this.runIdToState.values()) {\n return state.runId\n }\n return null\n }\n\n private createExecutionKey(test: TestDefinition, filePath: string, startedAt: string): string {\n const testId = (test as any)['test-id'] as string | undefined\n return `${testId ?? test.name}|${filePath || startedAt}`\n }\n\n private getStateByTestName(testName: string): TestState | undefined {\n const runId = this.nameToCurrentRunId.get(testName)\n return runId ? this.runIdToState.get(runId) : undefined\n }\n\n private getStateForResult(result: TestResult): TestState | undefined {\n if (result.runId) {\n const state = this.runIdToState.get(result.runId)\n if (state) return state\n }\n for (const state of this.runIdToState.values()) {\n if (state.name === result.name && (!result.filePath || state.filePath === result.filePath)) {\n return state\n }\n }\n return this.getStateByTestName(result.name)\n }\n\n private deleteState(state: TestState | undefined, testName: string): void {\n if (!state) return\n this.runIdToState.delete(state.runId)\n this.executionKeyToRunId.delete(state.executionKey)\n if (this.nameToCurrentRunId.get(testName) === state.runId) {\n this.nameToCurrentRunId.delete(testName)\n }\n }\n\n private resultKey(result: Pick<TestResult, 'name' | 'filePath'>): string {\n return `${result.name}|${result.filePath ?? ''}`\n }\n\n private buildResultErrorLog(result: TestResult): string | undefined {\n if (result.status !== 'failed' && result.status !== 'cancelled') return undefined\n const lines = [\n result.failureSummary,\n ...result.steps.flatMap((step) => [\n step.error,\n step.trace?.error,\n ]),\n ].filter((line): line is string => typeof line === 'string' && line.trim().length > 0)\n return lines.length > 0 ? [...new Set(lines)].join('\\n') : undefined\n }\n\n private writeArtifact<T>(fn: () => T): T {\n try {\n return fn()\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new FatalReporterError(`Artifact persistence failed: ${message}`, { cause: err })\n }\n }\n\n private stageSuiteChildLink(parentRunId: string, suiteIndex: number, childRunId: string): void {\n const parent = this.db.getRunArtifact(parentRunId)\n const source = parent?.payload.source\n if (!source || typeof source !== 'object' || !('members' in source) || !Array.isArray((source as any).members)) {\n return\n }\n const members = [...(source as any).members]\n const member = members[suiteIndex]\n if (!member || typeof member !== 'object') return\n members[suiteIndex] = { ...member, childRunId }\n this.db.stageRunArtifact(parentRunId, {\n source: {\n members,\n } as any,\n })\n }\n\n private stageSuiteSummary(parentRunId: string, summary: SuiteSummary): void {\n const parent = this.db.getRunArtifact(parentRunId)\n const source = parent?.payload.source\n if (!source || typeof source !== 'object' || !('members' in source) || !Array.isArray((source as any).members)) {\n return\n }\n const childRuns = this.db.getRunsByParent(parentRunId)\n const members = [...(source as any).members].map((member, index) => {\n if (!member || typeof member !== 'object') return member\n const memberRecord = { ...(member as Record<string, unknown>) }\n const child = childRuns.find((run) =>\n run.filePath === memberRecord.filePath\n || (typeof memberRecord.name === 'string' && run.name === memberRecord.name)\n )\n if (child) memberRecord.childRunId = child.id\n const result = summary.tests[index]\n const skipReason = (result?.metadata as Record<string, unknown> | undefined)?.skipReason\n if (result?.status === 'skipped' && typeof skipReason === 'string') {\n memberRecord.loadStatus = 'skipped'\n memberRecord.skipReason = skipReason\n }\n return memberRecord\n })\n this.db.stageRunArtifact(parentRunId, {\n source: { members } as any,\n memory: { aggregate: this.buildSuiteMemoryAggregate(parentRunId) } as any,\n })\n }\n\n private buildSuiteMemoryAggregate(parentRunId: string): Record<string, unknown> {\n const children = this.db.getRunsByParent(parentRunId)\n const aggregate = {\n added: 0,\n confirmed: 0,\n deprecated: 0,\n deleted: 0,\n errors: 0,\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n childRunIds: [] as string[],\n }\n for (const child of children) {\n let rawLog: unknown = null\n if (child.memoryLog) {\n try {\n rawLog = JSON.parse(child.memoryLog)\n } catch {\n rawLog = null\n }\n }\n if (!rawLog) {\n const childArtifact = this.db.getRunArtifact(child.id)\n const memory = childArtifact?.payload.memory\n rawLog = isRecord(memory) ? memory.log : null\n }\n if (!isRecord(rawLog)) continue\n try {\n const log = rawLog as {\n added?: number\n confirmed?: number\n deprecated?: number\n deleted?: number\n errors?: unknown[]\n tokenUsage?: { promptTokens?: number; completionTokens?: number; totalTokens?: number }\n }\n aggregate.added += log.added ?? 0\n aggregate.confirmed += log.confirmed ?? 0\n aggregate.deprecated += log.deprecated ?? 0\n aggregate.deleted += log.deleted ?? 0\n aggregate.errors += Array.isArray(log.errors) ? log.errors.length : 0\n aggregate.promptTokens += log.tokenUsage?.promptTokens ?? 0\n aggregate.completionTokens += log.tokenUsage?.completionTokens ?? 0\n aggregate.totalTokens += log.tokenUsage?.totalTokens ?? 0\n aggregate.childRunIds.push(child.id)\n } catch { /* skip malformed log */ }\n }\n return aggregate\n }\n\n private async persistStep(step: StepResult, runId: string, stepOrder: number): Promise<void> {\n const safeStep = this.redactValue(step)\n let screenshotPath: string | undefined\n let screenshotBeforePath: string | undefined\n\n if (safeStep.screenshotBefore) {\n screenshotBeforePath = await this.saveScreenshot(safeStep.screenshotBefore, runId, stepOrder, safeStep.name, 'before')\n }\n if (safeStep.screenshot) {\n screenshotPath = await this.saveScreenshot(safeStep.screenshot, runId, stepOrder, safeStep.name)\n }\n\n let healingScreenshotPaths: string[] | undefined\n if (safeStep.healingScreenshots && safeStep.healingScreenshots.length > 0) {\n healingScreenshotPaths = []\n for (let j = 0; j < safeStep.healingScreenshots.length; j++) {\n const healPath = await this.saveHealingScreenshot(safeStep.healingScreenshots[j], runId, stepOrder, j)\n healingScreenshotPaths.push(healPath)\n }\n }\n\n let subActionsForDb: unknown[] | undefined\n if (safeStep.trace?.subActions && safeStep.trace.subActions.length > 0) {\n subActionsForDb = []\n for (let j = 0; j < safeStep.trace.subActions.length; j++) {\n const sub = safeStep.trace.subActions[j]\n const mapped: Record<string, unknown> = { ...sub }\n delete mapped.screenshotBefore\n delete mapped.screenshotAfter\n if (sub.screenshotBefore) {\n mapped.screenshotBeforePath = await this.saveSubActionScreenshot(sub.screenshotBefore, runId, stepOrder, j, 'before')\n }\n if (sub.screenshotAfter) {\n mapped.screenshotAfterPath = await this.saveSubActionScreenshot(sub.screenshotAfter, runId, stepOrder, j, 'after')\n }\n subActionsForDb.push(mapped)\n }\n }\n\n const stepId = this.db.insertStep({\n id: safeStep.id,\n runId,\n name: safeStep.name,\n status: safeStep.status,\n duration: safeStep.duration,\n action: safeStep.action,\n observation: safeStep.trace?.observation ?? safeStep.observation,\n reasoning: safeStep.trace?.reasoning,\n plannedAction: safeStep.trace?.plannedAction,\n result: safeStep.trace?.result,\n error: safeStep.error ?? safeStep.trace?.error,\n screenshotPath,\n screenshotBeforePath,\n healingAttempts: safeStep.healingAttempts,\n retryCount: safeStep.retryCount,\n capturedVariables: safeStep.capturedVariables,\n stepOrder,\n annotationData: safeStep.annotation,\n healingScreenshotPaths,\n accessibilityViolations: safeStep.accessibilityViolations,\n confidence: safeStep.trace?.confidence,\n promptTokens: safeStep.trace?.tokenUsage?.promptTokens,\n completionTokens: safeStep.trace?.tokenUsage?.completionTokens,\n totalTokens: safeStep.trace?.tokenUsage?.totalTokens,\n subActionsData: subActionsForDb,\n consoleLogs: safeStep.consoleLogs,\n networkLogs: safeStep.networkLogs,\n variableSnapshot: safeStep.variableSnapshot,\n originalStepName: safeStep.originalStepName,\n screenContextBefore: safeStep.trace?.screenContextBefore,\n screenContextAfter: safeStep.trace?.screenContextAfter,\n })\n\n if (safeStep.trace?.tokenUsage && (safeStep.trace.tokenUsage.promptTokens > 0 || safeStep.trace.tokenUsage.completionTokens > 0)) {\n const modelName = process.env.AGENT_QA_LLM_MODEL ?? 'unknown'\n this.db.insertTokenEvent({\n modelName,\n promptTokens: safeStep.trace.tokenUsage.promptTokens,\n completionTokens: safeStep.trace.tokenUsage.completionTokens,\n source: 'test-run',\n })\n }\n\n if (safeStep.trace?.phaseDurations) {\n this.db.insertReasoningTrace({\n stepId,\n observeText: safeStep.trace.observation,\n observeDuration: safeStep.trace.phaseDurations.observe,\n planReasoning: safeStep.trace.reasoning,\n planConfidence: safeStep.trace.confidence,\n planAction: safeStep.trace.plannedAction,\n planDuration: safeStep.trace.phaseDurations.plan,\n executeAction: safeStep.action,\n executeDuration: safeStep.trace.phaseDurations.execute,\n verifyReasoning: safeStep.trace.verifierReasoning,\n verifySuccess: safeStep.trace.result === 'success',\n verifyDuration: safeStep.trace.phaseDurations.verify,\n healAttempts: safeStep.healingAttempts,\n totalDuration: safeStep.duration,\n screenStateBefore: safeStep.trace.screenStateBefore,\n screenStateAfter: safeStep.trace.screenStateAfter,\n })\n }\n }\n\n private async saveScreenshot(buffer: Buffer, runId: string, stepOrder: number, stepName: string, suffix?: string): Promise<string> {\n const sanitized = stepName.replace(/[^a-zA-Z0-9_-]/g, '_').substring(0, 50)\n const dir = join(this.artifactsDir, 'screenshots', runId)\n await mkdir(dir, { recursive: true })\n const filename = suffix\n ? `${stepOrder}-${sanitized}-${suffix}.png`\n : `${stepOrder}-${sanitized}.png`\n await writeFile(join(dir, filename), buffer)\n return join(runId, filename)\n }\n\n private async saveHealingScreenshot(buffer: Buffer, runId: string, stepOrder: number, attemptIndex: number): Promise<string> {\n const dir = join(this.artifactsDir, 'screenshots', runId)\n await mkdir(dir, { recursive: true })\n const filename = `${stepOrder}-healing-${attemptIndex}.png`\n await writeFile(join(dir, filename), buffer)\n return join(runId, filename)\n }\n\n private async saveSubActionScreenshot(buffer: Buffer, runId: string, stepOrder: number, subIndex: number, suffix: 'before' | 'after'): Promise<string> {\n const dir = join(this.artifactsDir, 'screenshots', runId)\n await mkdir(dir, { recursive: true })\n const filename = `${stepOrder}-sub-${subIndex}-${suffix}.png`\n await writeFile(join(dir, filename), buffer)\n return join(runId, filename)\n }\n}\n","import { createServer, type Server } from 'node:http'\nimport { readFile, stat } from 'node:fs/promises'\nimport { join, extname, resolve } from 'node:path'\nimport { cpus } from 'node:os'\nimport type { DashboardDatabase } from '../db/database.js'\nimport { createRouter } from './routes.js'\nimport { TestRunner } from '../execution/test-runner.js'\nimport { JobQueue } from '../queue/job-queue.js'\nimport { TestFileManager } from '../tests/test-file-manager.js'\nimport { SuiteFileManager } from '../tests/suite-file-manager.js'\nimport { ConfigManager } from '../config/index.js'\nimport { AppiumManager } from '../execution/appium-manager.js'\nimport { WebSocketServer } from 'ws'\nimport { SessionManager } from '../live-editor/session-manager.js'\nimport { createSessionHandler } from '../live-editor/ws-handler.js'\nimport {\n buildAnalyticsEvent,\n captureAnalytics,\n resolveAnalyticsStandardProperties,\n type ModelConfig,\n type ResolvedWorkspacePaths,\n} from '@vostride/agent-qa-core'\nimport {\n createLocalMcpHttpHandler,\n resolveLocalMcpEndpoint,\n resolveMcpEndpointShape,\n type LocalMcpEndpointConfig,\n type LocalMcpTransport,\n} from '@vostride/agent-qa-mcp'\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript',\n '.mjs': 'application/javascript',\n '.css': 'text/css',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.svg': 'image/svg+xml',\n '.json': 'application/json',\n '.woff2': 'font/woff2',\n '.woff': 'font/woff',\n '.ttf': 'font/ttf',\n '.ico': 'image/x-icon',\n '.map': 'application/json',\n '.webp': 'image/webp',\n}\n\nfunction isAnalyticsPrivacyEnabled(config: unknown): boolean {\n if (!config || typeof config !== 'object') return false\n const analytics = (config as { analytics?: unknown }).analytics\n return Boolean(analytics && typeof analytics === 'object'\n && (analytics as { privacy?: unknown }).privacy === true)\n}\n\ninterface StartServerOptions {\n db: DashboardDatabase\n port?: number\n uiDir?: string\n artifactsDir?: string\n workspacePaths?: ResolvedWorkspacePaths\n configPath?: string\n mcp?: LocalMcpEndpointConfig\n llmConfig?: Pick<\n ModelConfig,\n 'provider' | 'model' | 'apiKey' | 'authToken' | 'baseURL' | 'providerHeaders'\n > & {\n screenshotSize?: number\n effectiveResolution?: number\n }\n authFetch?: typeof globalThis.fetch\n}\n\ninterface McpStartupInfo {\n enabled: boolean\n transport: LocalMcpTransport\n host?: string\n port?: number\n path?: string\n url?: string\n}\n\nexport async function startServer(opts: StartServerOptions): Promise<{\n server: Server\n port: number\n mcp: McpStartupInfo\n close: () => void\n}> {\n const { db, port = 3470, uiDir, artifactsDir, workspacePaths, configPath, mcp, llmConfig, authFetch } = opts\n\n const resolvedConfigPath = configPath ?? resolve('agent-qa.config.yaml')\n const configManager = new ConfigManager(resolvedConfigPath)\n\n // Read concurrency from config (defaults to os.cpus().length)\n const config = await configManager.read().catch(() => ({}))\n const concurrency = typeof (config as any).concurrency === 'number'\n ? (config as any).concurrency\n : cpus().length\n\n let testRunner: TestRunner | undefined\n\n const finalizeRunArtifactBestEffort = (\n runId: string,\n code: string,\n phase: string,\n message: string,\n runtime: Record<string, unknown> = {},\n ): void => {\n try {\n const artifact = db.getRunArtifact(runId)\n if (!artifact || artifact.finalizedAt) return\n db.finalizeRunArtifact(runId, {\n runtime,\n errors: [{ code, phase, message }],\n } as any)\n } catch { /* best-effort cleanup */ }\n }\n\n // Resolve CLI binary once — used by TestRunner\n let cliBin: string | undefined\n try {\n cliBin = TestRunner.resolveCliBin()\n } catch {\n console.warn('Warning: Could not resolve agent-qa CLI binary. Execution will not work.')\n }\n\n // TestRunner for live test execution\n if (cliBin) {\n testRunner = new TestRunner({\n cliBin,\n onProcessClose: (runId, status) => {\n // If the child process exited but the DB row is still 'running',\n // update it so the dashboard doesn't show a stuck run.\n try {\n const run = db.getRun(runId)\n const handle = testRunner!.getHandle(runId)\n const isBrowserDisconnect = handle?.output.some(line =>\n line.includes('Target page, context or browser has been closed') ||\n line.includes('Browser closed by user')\n )\n if (run && (run.status === 'running' || run.status === 'cancelled')) {\n const duration = run.startedAt\n ? Date.now() - new Date(run.startedAt).getTime()\n : 0\n\n let dbStatus: string\n let failureSummary: string | undefined\n let errorLog: string | undefined\n const explicitCancellation = run.status === 'cancelled' || status === 'cancelled'\n if (explicitCancellation) {\n dbStatus = 'cancelled'\n failureSummary = undefined\n } else if (status === 'timeout') {\n dbStatus = 'failed'\n failureSummary = 'Test timed out -- process was killed'\n } else if (status === 'completed') {\n dbStatus = 'failed'\n failureSummary = 'Process exited before test completed'\n } else if (isBrowserDisconnect) {\n dbStatus = 'cancelled'\n failureSummary = 'Browser closed by user'\n } else {\n dbStatus = 'failed'\n const outputLines = handle?.output.map(l => l.replace(/\\x1b\\[[0-9;]*m/g, '')) ?? []\n const meaningfulLine = [...outputLines].reverse().find(l =>\n /error/i.test(l) || l.includes('Parse') || l.includes('not found') || l.includes('rejected')\n )\n failureSummary = meaningfulLine\n ? meaningfulLine.slice(0, 300)\n : 'Process exited before test completed'\n }\n\n if (dbStatus === 'failed' && handle?.output.length) {\n errorLog = handle.output\n .join('\\n')\n .replace(/\\x1b\\[[0-9;]*m/g, '')\n .slice(-10000) || undefined\n }\n\n // Suite parent: derive status from child test runs\n if (run.suiteId && !run.parentRunId) {\n const children = db.getRunsByParent(runId)\n const incompleteChildStatus = dbStatus === 'cancelled' ? 'cancelled' : 'failed'\n const incompleteChildSummary = incompleteChildStatus === 'cancelled'\n ? 'Suite cancelled'\n : failureSummary ?? 'Suite process terminated'\n\n for (const child of children) {\n if (child.status === 'running' || child.status === 'pending') {\n db.updateRun(child.id, {\n status: incompleteChildStatus,\n endedAt: new Date().toISOString(),\n failureSummary: incompleteChildSummary,\n })\n finalizeRunArtifactBestEffort(\n child.id,\n 'suite-process-close',\n 'process-close',\n incompleteChildSummary,\n { status: incompleteChildStatus, finalStatus: incompleteChildStatus, processStatus: status },\n )\n }\n }\n\n const updatedChildren = db.getRunsByParent(runId)\n\n const statusPriority: Record<string, number> = {\n failed: 4,\n cancelled: 3,\n flaky: 2,\n passed: 1,\n skipped: 0,\n pending: 0,\n running: 0,\n }\n\n let worstStatus = 'passed'\n let worstPriority = 0\n for (const child of updatedChildren) {\n const p = statusPriority[child.status] ?? 0\n if (p > worstPriority) {\n worstPriority = p\n worstStatus = child.status\n }\n }\n\n if (updatedChildren.length === 0) {\n if (isBrowserDisconnect) {\n worstStatus = 'cancelled'\n } else {\n worstStatus = dbStatus\n }\n }\n\n db.updateRun(runId, {\n status: worstStatus,\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: worstStatus === 'failed' ? 'Suite test(s) failed'\n : worstStatus === 'cancelled' ? (isBrowserDisconnect ? 'Browser closed by user' : 'Suite cancelled')\n : undefined,\n })\n finalizeRunArtifactBestEffort(\n runId,\n 'suite-process-close',\n 'process-close',\n worstStatus === 'cancelled' ? (isBrowserDisconnect ? 'Browser closed by user' : 'Suite cancelled') : 'Suite process closed',\n { status: worstStatus, finalStatus: worstStatus, processStatus: status, duration },\n )\n\n releaseMobileAppiumLease(runId, 'suite-process-close')\n jobQueue.onSlotFreed(runId)\n return\n }\n\n // Check for retry child runs and classify accordingly\n const childRuns = db.getRunsByParent(runId)\n if (childRuns.length > 0) {\n const incompleteChildStatus = dbStatus === 'cancelled' ? 'cancelled' : 'failed'\n const incompleteChildSummary = incompleteChildStatus === 'cancelled'\n ? 'Retry cancelled'\n : failureSummary ?? 'Retry process terminated'\n for (const child of childRuns) {\n if (child.status === 'running' || child.status === 'pending') {\n db.updateRun(child.id, {\n status: incompleteChildStatus,\n endedAt: new Date().toISOString(),\n failureSummary: incompleteChildSummary,\n })\n finalizeRunArtifactBestEffort(\n child.id,\n 'retry-process-close',\n 'process-close',\n incompleteChildSummary,\n { status: incompleteChildStatus, finalStatus: incompleteChildStatus, processStatus: status },\n )\n }\n }\n\n const updatedChildRuns = db.getRunsByParent(runId)\n const anyPassed = updatedChildRuns.some(r => r.status === 'passed')\n const firstPassed = updatedChildRuns[0]?.status === 'passed'\n if (anyPassed && !firstPassed) {\n dbStatus = 'flaky'\n } else if (anyPassed && firstPassed) {\n dbStatus = 'passed'\n } else if (dbStatus === 'cancelled' || updatedChildRuns.some(r => r.status === 'cancelled')) {\n dbStatus = 'cancelled'\n } else {\n dbStatus = 'failed'\n }\n const lastChild = updatedChildRuns[updatedChildRuns.length - 1]\n db.updateRun(runId, {\n status: dbStatus,\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: dbStatus === 'failed' ? 'All retry attempts failed'\n : dbStatus === 'cancelled' ? 'Retry cancelled'\n : undefined,\n })\n finalizeRunArtifactBestEffort(\n runId,\n 'retry-process-close',\n 'process-close',\n dbStatus === 'failed' ? 'All retry attempts failed'\n : dbStatus === 'cancelled' ? 'Retry cancelled'\n : 'Retry process closed',\n { status: dbStatus, finalStatus: dbStatus, processStatus: status, duration },\n )\n db.updateRunRetryInfo(runId, {\n retryCount: updatedChildRuns.length,\n maxRetries: lastChild?.maxRetries ?? run.maxRetries,\n })\n releaseMobileAppiumLease(runId, 'retry-process-close')\n jobQueue.onSlotFreed(runId)\n return\n }\n\n db.updateRun(runId, {\n status: dbStatus,\n duration,\n endedAt: new Date().toISOString(),\n failureSummary,\n errorLog,\n })\n finalizeRunArtifactBestEffort(\n runId,\n isBrowserDisconnect ? 'browser-disconnect' : 'process-close',\n 'process-close',\n failureSummary ?? 'Process closed',\n { status: dbStatus, finalStatus: dbStatus, processStatus: status, duration },\n )\n }\n } catch { /* best-effort */ }\n\n releaseMobileAppiumLease(runId, status)\n jobQueue.onSlotFreed(runId)\n },\n })\n }\n\n // Clean up orphaned runs from previous server sessions — any run still\n // marked 'running' in the DB has no live process and should be failed.\n // Suite parents with active children are skipped (CLI process may still be running).\n const orphaned = db.getRuns({ status: 'running' })\n let cleaned = 0\n for (const run of orphaned) {\n if (run.suiteId && !run.parentRunId) {\n const children = db.getRunsByParent(run.id)\n if (children.some(c => c.status === 'running')) {\n continue\n }\n }\n const duration = run.startedAt\n ? Date.now() - new Date(run.startedAt).getTime()\n : 0\n db.updateRun(run.id, {\n status: 'failed',\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: 'Process terminated unexpectedly (server restarted)',\n })\n finalizeRunArtifactBestEffort(run.id, 'server-restart', 'startup-cleanup', 'Process terminated unexpectedly (server restarted)', { status: 'failed', duration })\n cleaned++\n }\n if (cleaned > 0) {\n console.log(`Cleaned up ${cleaned} orphaned run(s) stuck in 'running' state`)\n }\n\n // Log any pending rows left from previous session (benign — picked up when queue starts)\n const pendingOrphans = db.getRuns({ status: 'pending' })\n if (pendingOrphans.length > 0) {\n console.log(`Found ${pendingOrphans.length} pending run(s) from previous session — will be processed when queue starts`)\n }\n\n // Appium lifecycle manager — auto-starts Appium for mobile tests\n const appiumManager = new AppiumManager()\n const mobileRuns = new Map<string, 'android' | 'ios'>()\n\n const releaseMobileAppiumLease = (runId: string, reason: string): void => {\n const platform = mobileRuns.get(runId)\n if (!platform) return\n mobileRuns.delete(runId)\n appiumManager.releaseLease(runId, reason)\n }\n\n const releaseAllMobileAppiumLeases = (reason: string): void => {\n for (const runId of [...mobileRuns.keys()]) {\n releaseMobileAppiumLease(runId, reason)\n }\n }\n\n // Persistent job queue — all triggers route through this\n const jobQueue = new JobQueue({ db, concurrency })\n console.log(`Job queue started with ${concurrency} concurrency slot(s)`)\n console.log('Appium lifecycle manager initialized (auto-start on first mobile test)')\n\n // Wire JobQueue 'execute' event to TestRunner\n jobQueue.on('execute', async (run) => {\n if (!testRunner) return\n\n const platform = run.platform ?? 'web'\n const isMobile = platform === 'ios' || platform === 'android'\n\n // Ensure Appium is running before mobile test execution\n if (isMobile) {\n try {\n await appiumManager.acquireLease({ runId: run.id, platform })\n mobileRuns.set(run.id, platform)\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Failed to start Appium for run ${run.id}: ${message}`)\n db.updateRun(run.id, {\n status: 'failed',\n failureSummary: `Appium server failed to start: ${message}`,\n endedAt: new Date().toISOString(),\n })\n finalizeRunArtifactBestEffort(run.id, 'appium-startup', 'appium-startup', `Appium server failed to start: ${message}`, { status: 'failed' })\n jobQueue.onSlotFreed(run.id)\n return\n }\n }\n\n const meta = (run.metadata ?? {}) as Record<string, unknown>\n const args = Array.isArray(meta.args)\n ? meta.args.filter((arg): arg is string => typeof arg === 'string')\n : []\n if (args.length === 0 && run.filePath) {\n args.push(run.filePath)\n }\n testRunner.execute({\n runId: run.id,\n args,\n source: meta.isSuite ? 'suite' : 'dashboard',\n attributes: run.attributes,\n timeout: meta.timeout as number | undefined,\n maxRetries: run.maxRetries,\n env: isMobile ? { AGENT_QA_APPIUM_URL: appiumManager.getUrl() } : undefined,\n })\n })\n\n // Wire cancellation — running jobs need process kill via TestRunner\n jobQueue.on('cancel-running', (runId: string) => {\n testRunner?.kill(runId)\n })\n\n // Start the queue polling loop\n jobQueue.start()\n\n // TestFileManager for test file CRUD\n const testFileManager = workspacePaths ? new TestFileManager(workspacePaths) : undefined\n\n const suiteFileManager = workspacePaths ? new SuiteFileManager(workspacePaths, testFileManager) : undefined\n\n const sessionManager = new SessionManager({\n appiumManager,\n configManager,\n configPath: resolvedConfigPath,\n })\n\n const apiRouter = createRouter({\n db,\n artifactsDir,\n workspacePaths,\n testRunner,\n jobQueue,\n testFileManager,\n suiteFileManager,\n configManager,\n configPath: resolvedConfigPath,\n llmConfig,\n authFetch,\n sessionManager,\n })\n\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', 'http://localhost')\n const path = url.pathname\n\n // API routes\n if (path.startsWith('/api/')) {\n apiRouter(req, res)\n return\n }\n\n // OPTIONS preflight\n if (req.method === 'OPTIONS') {\n res.writeHead(204, {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n })\n res.end()\n return\n }\n\n // Static file serving\n if (uiDir) {\n const filePath = path === '/' ? join(uiDir, 'index.html') : join(uiDir, path)\n\n try {\n const fileStat = await stat(filePath)\n if (fileStat.isFile()) {\n const content = await readFile(filePath)\n const ext = extname(filePath)\n const contentType = MIME_TYPES[ext] || 'application/octet-stream'\n res.writeHead(200, {\n 'Content-Type': contentType,\n 'Content-Length': content.length,\n 'Access-Control-Allow-Origin': '*',\n })\n res.end(content)\n return\n }\n } catch {\n // File not found — fall through to SPA fallback\n }\n\n // SPA fallback: serve index.html for non-file paths\n try {\n const indexPath = join(uiDir, 'index.html')\n const content = await readFile(indexPath)\n res.writeHead(200, {\n 'Content-Type': 'text/html',\n 'Content-Length': content.length,\n 'Access-Control-Allow-Origin': '*',\n })\n res.end(content)\n return\n } catch {\n // No index.html available\n }\n }\n\n res.writeHead(404, { 'Content-Type': 'text/plain' })\n res.end('Not Found')\n })\n\n const wss = new WebSocketServer({ noServer: true })\n\n server.on('upgrade', (request, socket, head) => {\n const url = new URL(request.url ?? '/', 'http://localhost')\n if (url.pathname === '/api/live-editor/ws') {\n const sessionId = url.searchParams.get('sessionId')\n if (!sessionId) {\n socket.destroy()\n return\n }\n const session = sessionManager.getSession(sessionId)\n if (!session) {\n socket.destroy()\n return\n }\n\n wss.handleUpgrade(request, socket, head, (ws) => {\n session.clearIdleTimer()\n const handler = createSessionHandler(session, () => {\n sessionManager.terminateSession(sessionId)\n }, (event) => {\n db.insertTokenEvent(event)\n }, testFileManager)\n handler(ws)\n })\n } else {\n socket.destroy()\n }\n })\n\n const gracefulShutdown = () => {\n sessionManager.cleanupAll()\n }\n process.on('SIGTERM', gracefulShutdown)\n process.on('SIGINT', gracefulShutdown)\n\n const configuredMcp = (mcp ?? (config as any).services?.mcp ?? {}) as LocalMcpEndpointConfig\n const effectiveMcpConfig = configuredMcp.port === undefined && port === 0\n ? { ...configuredMcp, port: 0 }\n : configuredMcp\n const resolvedMcp = resolveLocalMcpEndpoint(effectiveMcpConfig)\n let mcpHttpServer: Server | undefined\n let mcpInfo: McpStartupInfo\n const captureMcpLifecycle = async (\n properties: {\n mcp_server_state: 'started' | 'disabled'\n mcp_transport: LocalMcpTransport\n mcp_host_kind?: 'loopback' | 'other'\n mcp_port_kind?: 'default' | 'custom'\n mcp_path_kind?: 'default' | 'custom'\n },\n ): Promise<void> => {\n if (isAnalyticsPrivacyEnabled(config)) return\n\n try {\n const standardProperties = await resolveAnalyticsStandardProperties({ surface: 'dashboard-server' })\n await captureAnalytics(buildAnalyticsEvent({\n name: 'agent-qa.mcp.server.lifecycle',\n properties: {\n ...standardProperties,\n surface: 'dashboard-server',\n ...properties,\n },\n }), { config }).catch(() => {})\n } catch {\n // Dashboard MCP lifecycle analytics must not alter startup behavior.\n }\n }\n const cleanupRuntimeResources = () => {\n jobQueue.stop()\n if (testRunner) {\n testRunner.killAll()\n }\n releaseAllMobileAppiumLeases('server-startup-error')\n appiumManager.shutdown()\n sessionManager.cleanupAll()\n db.close()\n }\n\n if (!resolvedMcp.enabled) {\n mcpInfo = {\n enabled: false,\n transport: resolvedMcp.transport,\n }\n await captureMcpLifecycle({\n mcp_server_state: 'disabled',\n mcp_transport: resolvedMcp.transport,\n })\n console.log('MCP disabled by services.mcp.enabled: false')\n } else if (resolvedMcp.transport === 'stdio') {\n mcpInfo = {\n enabled: false,\n transport: 'stdio',\n }\n console.log('MCP stdio transport selected; start editor MCP with `agent-qa mcp`')\n } else {\n let mcpHttpHandler = createLocalMcpHttpHandler({\n endpoint: resolvedMcp,\n dashboardUrl: `http://localhost:${port}`,\n configPath: resolvedConfigPath,\n analyticsConfig: config,\n })\n mcpHttpServer = createServer((req, res) => {\n void mcpHttpHandler(req, res)\n })\n\n try {\n await new Promise<void>((resolveMcp, rejectMcp) => {\n const onError = (err: Error) => {\n rejectMcp(err)\n }\n mcpHttpServer!.once('error', onError)\n mcpHttpServer!.listen(resolvedMcp.port, resolvedMcp.host, () => {\n mcpHttpServer!.off('error', onError)\n resolveMcp()\n })\n })\n } catch (err) {\n mcpHttpServer.close()\n cleanupRuntimeResources()\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`Failed to start MCP endpoint at ${resolvedMcp.url}: ${message}`)\n }\n\n const mcpAddress = mcpHttpServer.address()\n const actualMcpPort = typeof mcpAddress === 'object' && mcpAddress\n ? mcpAddress.port\n : resolvedMcp.port\n const actualMcp = resolveLocalMcpEndpoint({\n ...resolvedMcp,\n port: actualMcpPort,\n })\n if (actualMcpPort !== resolvedMcp.port) {\n mcpHttpHandler = createLocalMcpHttpHandler({\n endpoint: actualMcp,\n dashboardUrl: `http://localhost:${port}`,\n configPath: resolvedConfigPath,\n analyticsConfig: config,\n })\n }\n\n mcpInfo = {\n enabled: true,\n transport: 'http',\n host: actualMcp.host,\n port: actualMcp.port,\n path: actualMcp.path,\n url: actualMcp.url,\n }\n await captureMcpLifecycle({\n mcp_server_state: 'started',\n mcp_transport: 'http',\n ...resolveMcpEndpointShape(actualMcp),\n })\n console.log(`MCP running locally at ${actualMcp.url} (Streamable HTTP, loopback only)`)\n }\n\n return new Promise((resolve, reject) => {\n const onError = (err: Error) => {\n mcpHttpServer?.close()\n cleanupRuntimeResources()\n reject(err)\n }\n server.once('error', onError)\n server.listen(port, () => {\n server.off('error', onError)\n console.log(`Dashboard running at http://localhost:${port}`)\n resolve({\n server,\n port,\n mcp: mcpInfo,\n close: () => {\n jobQueue.stop()\n if (testRunner) {\n testRunner.killAll()\n }\n releaseAllMobileAppiumLeases('server-close')\n appiumManager.shutdown()\n sessionManager.cleanupAll()\n mcpHttpServer?.close()\n server.close()\n db.close()\n },\n })\n })\n })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { randomUUID } from 'node:crypto'\nimport { readFile, writeFile, stat, readdir, rm } from 'node:fs/promises'\nimport { createReadStream } from 'node:fs'\nimport { join, isAbsolute, basename, resolve, dirname, relative } from 'node:path'\n\nimport type { AttributePredicate, DashboardDatabase, InsightsBreakdownDimension, RunArtifactRow, RunRow, StepRow } from '../db/database.js'\nimport type { TestRunner } from '../execution/test-runner.js'\nimport type { JobQueue } from '../queue/job-queue.js'\nimport { MemoryCatalogManager, isValidMemoryScopeId, type MemoryScope } from '../memory/memory-catalog-manager.js'\nimport { extractTestFileMetadata, type SupportedPlatform, type TestFileManager } from '../tests/test-file-manager.js'\nimport type { SuiteFileManager } from '../tests/suite-file-manager.js'\nimport type { ConfigManager } from '../config/index.js'\nimport { HookRegistryManager, isHookRegistryMutationError } from '../hooks/hook-registry-manager.js'\nimport { readJsonBody } from './body-parser.js'\nimport type { AnalyticsServiceConfig, LLMAuthProviderPlugin, ModelConfig, OAuthTokens } from '@vostride/agent-qa-core'\nimport { buildAnalyticsEvent, buildInternalRunAttributes, captureAnalytics, mergeRunAttributes, readAuth, writeAuth, removeAuth, getAgentQaVersion, getProviderOptions, getLLMAuthProviderPlugin, listLLMAuthProviderPlugins, ModelConfigSchema, NamedLLMConfigSchema, WorkspaceSchema, ServicesSchema, RegistrySchema, UseSchema, MobileAppStateSchema, hashStepInstruction, TimeoutConfigSchema, CacheConfigSchema, HealingConfigSchema, PlannerConfigSchema, LoggingConfigSchema, LogCaptureConfigSchema, AccessibilityConfigSchema, DashboardConfigSchema, McpConfigSchema, RecordingConfigSchema, BrowserConfigSchema, AnalyticsSchema, AgentQaConfigSchema, TestDefinitionSchema, SuiteDefinitionSchema, parseEnvFile, serializeEnvFile, parseHooksFile, runHookInSandbox, RUNTIME_IMAGE_MAP, SecretStore, SecretRedactor, validateUserRunAttributes, discoverWorkspaceFiles, isWorkspacePathMatch, resolveAnalyticsStandardProperties, resolveMemoryRoot, resolveWorkspaceFileTarget } from '@vostride/agent-qa-core'\nimport type { ResolvedWorkspacePaths, RunAttributes, WorkspaceFileKind, WorkspaceFileRecord } from '@vostride/agent-qa-core'\nimport { parse as parseYaml } from 'yaml'\n\nconst LLM_PROVIDER_MODES = new Set([\n 'openai-compatible',\n 'anthropic-compatible',\n 'gemini',\n])\nconst API_KEY_CREDENTIAL_PROVIDERS = new Set([\n 'openai-compatible',\n 'anthropic-compatible',\n 'gemini',\n])\nconst LLM_TEST_UNAUTHENTICATED_MESSAGE = 'Testing without a saved credential.'\nconst LLM_TEST_AUTH_ERROR_MESSAGE = 'Authentication failed. Check the saved credential for this config.'\nconst LLM_TEST_MODEL_NOT_FOUND_MESSAGE = 'Model not found. Check the model name.'\nconst LLM_TEST_NETWORK_ERROR_MESSAGE = 'Network error. Check the exact base URL and try again.'\nconst DASHBOARD_EXECUTION_TIMEOUT_BUFFER_MS = 60_000\nconst REMOTE_LLM_CONNECTION_TEST_TIMEOUT_MS = 10_000\nconst LOCAL_COMPATIBLE_LLM_CONNECTION_TEST_TIMEOUT_MS = 120_000\nconst LOCAL_COMPATIBLE_LLM_PROVIDERS = new Set(['openai-compatible', 'anthropic-compatible'])\nconst PLUGIN_OAUTH_SESSION_TTL_MS = 10 * 60 * 1000\nconst DASHBOARD_PRODUCT_EVENT_NAMES = [\n 'agent-qa.dashboard.opened',\n 'agent-qa.dashboard.live_mode.started',\n 'agent-qa.dashboard.entity.created',\n] as const\ntype DashboardProductEventName = typeof DASHBOARD_PRODUCT_EVENT_NAMES[number]\nconst DASHBOARD_PRODUCT_EVENT_NAME_SET = new Set<DashboardProductEventName>(DASHBOARD_PRODUCT_EVENT_NAMES)\nconst DASHBOARD_PRODUCT_EVENT_PROPERTY_KEYS = {\n 'agent-qa.dashboard.opened': [],\n 'agent-qa.dashboard.live_mode.started': ['platform', 'entity_type'],\n 'agent-qa.dashboard.entity.created': ['entity_type', 'outcome'],\n} as const satisfies Record<DashboardProductEventName, readonly string[]>\n\ntype DashboardExecutionTimeoutSource =\n | 'test.use.timeout.test'\n | 'suite.use.timeout.test'\n | 'config.use.timeout.test'\n | 'none'\n\ntype ConfigSectionValidationResult =\n | { success: true }\n | { success: false; error: { issues: { message: string; path: PropertyKey[] }[] } }\n\ninterface DashboardExecutionTimeout {\n timeoutMs?: number\n source: DashboardExecutionTimeoutSource\n baseTimeoutMs?: number\n bufferMs?: number\n}\n\nfunction toProductProviderLabel(provider: string): string {\n const plugin = listLLMAuthProviderPlugins()\n .find((candidate) => candidate.credentialProviderId === provider)\n return plugin?.providerId ?? provider\n}\n\nfunction isKnownLLMProvider(provider: string): boolean {\n return LLM_PROVIDER_MODES.has(provider) || Boolean(getLLMAuthProviderPlugin(provider))\n}\n\nasync function requirePluginAuthConfig(\n configManager: ConfigManager | undefined,\n configName: unknown,\n plugin: LLMAuthProviderPlugin,\n): Promise<{ ok: true; configName: string } | { ok: false; error: string }> {\n const targetConfigName = typeof configName === 'string' ? configName.trim() : ''\n if (!targetConfigName) {\n return { ok: false, error: 'configName is required' }\n }\n if (!configManager) {\n return { ok: false, error: 'Config manager is required to save OAuth credentials' }\n }\n\n const config = await configManager.read() as { registry?: { llms?: unknown[] } }\n const llms = Array.isArray(config.registry?.llms) ? config.registry.llms : []\n const match = llms.find((item) => {\n return Boolean(item)\n && typeof item === 'object'\n && !Array.isArray(item)\n && (item as { name?: unknown }).name === targetConfigName\n }) as { provider?: unknown } | undefined\n\n if (!match) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" not found` }\n }\n if (match.provider !== plugin.providerId) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" uses ${String(match.provider)}, not ${plugin.providerId}` }\n }\n\n return { ok: true, configName: targetConfigName }\n}\n\nasync function requireCredentialConfig(\n configManager: ConfigManager | undefined,\n configName: unknown,\n provider: string,\n): Promise<{ ok: true; configName: string } | { ok: false; error: string }> {\n const targetConfigName = typeof configName === 'string' ? configName.trim() : ''\n if (!targetConfigName) {\n return { ok: false, error: 'configName is required' }\n }\n if (!API_KEY_CREDENTIAL_PROVIDERS.has(provider)) {\n return { ok: false, error: 'provider must support typed credentials' }\n }\n if (!configManager) {\n return { ok: false, error: 'Config manager is required to save credentials' }\n }\n\n const config = await configManager.read() as { registry?: { llms?: unknown[] } }\n const llms = Array.isArray(config.registry?.llms) ? config.registry.llms : []\n const match = llms.find((item) => {\n return Boolean(item)\n && typeof item === 'object'\n && !Array.isArray(item)\n && (item as { name?: unknown }).name === targetConfigName\n }) as { provider?: unknown } | undefined\n\n if (!match) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" not found` }\n }\n if (match.provider !== provider) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" uses ${String(match.provider)}, not ${provider}` }\n }\n\n return { ok: true, configName: targetConfigName }\n}\n\ntype DashboardAuthCredential =\n | { type: 'oauth'; provider?: string; tokens: { expires: number } }\n | { type: 'api'; provider?: string; key?: string }\n | { type: 'bearer'; provider: string; token?: string }\n\ninterface DashboardLLMProviderMetadata {\n id: string\n label: string\n auth:\n | { kind: 'api-key'; credentialTypes: Array<'api-key' | 'bearer-token'>; optional?: boolean }\n | { kind: 'oauth-plugin'; mode: 'browser-poll' | 'manual-code'; buttonLabel?: string }\n modelAdapter?: 'openai-responses' | 'anthropic-messages'\n}\n\ninterface PluginOAuthSession {\n providerId: string\n credentialProviderId: string\n configName: string\n sessionState?: unknown\n cleanup?: () => void\n status: 'pending' | 'completed' | 'error'\n expiresAt: number\n error?: string\n}\n\nfunction builtinLLMProviderMetadata(): DashboardLLMProviderMetadata[] {\n return [\n {\n id: 'openai-compatible',\n label: 'OpenAI-compatible',\n auth: { kind: 'api-key', credentialTypes: ['api-key'], optional: true },\n modelAdapter: 'openai-responses',\n },\n {\n id: 'anthropic-compatible',\n label: 'Anthropic-compatible',\n auth: { kind: 'api-key', credentialTypes: ['api-key', 'bearer-token'], optional: true },\n modelAdapter: 'anthropic-messages',\n },\n {\n id: 'gemini',\n label: 'Gemini',\n auth: { kind: 'api-key', credentialTypes: ['api-key'] },\n },\n ]\n}\n\nfunction serializeAuthProviderPlugin(plugin: LLMAuthProviderPlugin): DashboardLLMProviderMetadata {\n return {\n id: plugin.providerId,\n label: plugin.label,\n modelAdapter: plugin.modelAdapter,\n auth: {\n kind: 'oauth-plugin',\n mode: plugin.dashboardAuth.mode,\n ...(plugin.dashboardAuth.buttonLabel ? { buttonLabel: plugin.dashboardAuth.buttonLabel } : {}),\n },\n }\n}\n\ntype DashboardRuntimeLLMConfig = Pick<\n ModelConfig,\n 'provider' | 'model' | 'apiKey' | 'authToken' | 'baseURL' | 'providerHeaders'\n> & {\n screenshotSize?: number\n effectiveResolution?: number\n modelAdapter?: 'openai-responses' | 'anthropic-messages'\n}\n\nconst writeDashboardAuth = writeAuth as unknown as (\n provider: string,\n credential: DashboardAuthCredential,\n) => Promise<void>\n\ntype DashboardResolvedRuntimeLLM =\n | { ok: true; llmConfig: DashboardRuntimeLLMConfig; authFetch?: typeof globalThis.fetch }\n | { ok: false; error: string }\n\nfunction normalizeRuntimeLLMConfig(raw: unknown): { configName: string; config: DashboardRuntimeLLMConfig } | undefined {\n if (!isPlainRecord(raw)) return undefined\n if (typeof raw.name !== 'string' || !raw.name.trim()) return undefined\n if (typeof raw.provider !== 'string' || !raw.provider.trim()) return undefined\n if (typeof raw.model !== 'string' || !raw.model.trim()) return undefined\n\n const config: DashboardRuntimeLLMConfig = {\n provider: raw.provider,\n model: raw.model,\n }\n if (typeof raw.baseURL === 'string') config.baseURL = raw.baseURL\n if (isPlainRecord(raw.providerHeaders)) {\n const headers: Record<string, string> = {}\n for (const [key, value] of Object.entries(raw.providerHeaders)) {\n if (typeof value === 'string') headers[key] = value\n }\n config.providerHeaders = headers\n }\n if (typeof raw.screenshotSize === 'number') config.screenshotSize = raw.screenshotSize\n if (typeof raw.effectiveResolution === 'number') config.effectiveResolution = raw.effectiveResolution\n\n return { configName: raw.name, config }\n}\n\nasync function resolveDashboardRuntimeLLM(\n configManager: ConfigManager | undefined,\n fallbackLLMConfig: DashboardRuntimeLLMConfig | undefined,\n fallbackAuthFetch: typeof globalThis.fetch | undefined,\n): Promise<DashboardResolvedRuntimeLLM> {\n if (!configManager) {\n if (!fallbackLLMConfig) {\n return { ok: false, error: 'LLM not configured. Set up LLM provider in settings.' }\n }\n return { ok: true, llmConfig: fallbackLLMConfig, authFetch: fallbackAuthFetch }\n }\n\n const rawConfig = await configManager.read()\n const registry = isPlainRecord(rawConfig.registry) ? rawConfig.registry : {}\n const use = isPlainRecord(rawConfig.use) ? rawConfig.use : {}\n const llms = Array.isArray(registry.llms) ? registry.llms : []\n const selectedName = typeof use.llm === 'string' ? use.llm : undefined\n const selected = selectedName\n ? llms.find((candidate) => isPlainRecord(candidate) && candidate.name === selectedName)\n : llms[0]\n\n const normalized = normalizeRuntimeLLMConfig(selected)\n if (!normalized) {\n if (!fallbackLLMConfig) {\n return { ok: false, error: 'LLM not configured. Set up LLM provider in settings.' }\n }\n return { ok: true, llmConfig: fallbackLLMConfig, authFetch: fallbackAuthFetch }\n }\n\n const coreAuth = await import('@vostride/agent-qa-core') as typeof import('@vostride/agent-qa-core') & {\n resolveLLMAuth: (\n configName: string,\n config: DashboardRuntimeLLMConfig,\n ) => Promise<\n | { kind: 'api-key'; apiKey: string }\n | { kind: 'bearer-token'; token: string }\n | { kind: 'auth-fetch'; fetch: typeof globalThis.fetch; modelAdapter: 'openai-responses' | 'anthropic-messages' }\n | { kind: 'unauthenticated'; message: string }\n | { kind: 'missing'; message: string }\n >\n }\n const auth = await coreAuth.resolveLLMAuth(normalized.configName, normalized.config)\n if (auth.kind === 'missing') {\n return { ok: false, error: auth.message }\n }\n\n const runtimeConfig: DashboardRuntimeLLMConfig = { ...normalized.config }\n let resolvedAuthFetch: typeof globalThis.fetch | undefined\n if (auth.kind === 'api-key') {\n runtimeConfig.apiKey = auth.apiKey\n } else if (auth.kind === 'bearer-token') {\n runtimeConfig.authToken = auth.token\n } else if (auth.kind === 'auth-fetch') {\n runtimeConfig.modelAdapter = auth.modelAdapter\n resolvedAuthFetch = auth.fetch\n }\n\n return { ok: true, llmConfig: runtimeConfig, authFetch: resolvedAuthFetch }\n}\n\nfunction cleanupPluginOAuthSession(session: PluginOAuthSession): void {\n const cleanup = session.cleanup\n session.cleanup = undefined\n if (!cleanup) return\n try {\n cleanup()\n } catch {\n // Best-effort cleanup for plugin-owned local callback servers.\n }\n}\n\nfunction pruneExpiredPluginOAuthSessions(sessions: Map<string, PluginOAuthSession>, now = Date.now()): void {\n for (const [sessionId, session] of sessions) {\n if (session.expiresAt <= now) {\n cleanupPluginOAuthSession(session)\n sessions.delete(sessionId)\n }\n }\n}\n\nfunction extractProviderErrorMessage(err: unknown): { message: string; statusCode?: number } {\n const errObj = err as Record<string, unknown>\n const statusCode = errObj?.statusCode as number | undefined\n const responseBody = errObj?.responseBody as string | undefined\n const data = errObj?.data as Record<string, unknown> | undefined\n const apiError = data?.error as Record<string, string> | undefined\n\n let message = err instanceof Error ? err.message : String(err)\n\n if (apiError?.message && apiError.message !== 'Error') {\n message = apiError.message\n } else if (data?.detail && typeof data.detail === 'string') {\n message = data.detail\n } else if (responseBody) {\n try {\n const body = JSON.parse(responseBody)\n if (body?.detail) message = body.detail\n else if (body?.error?.message && body.error.message !== 'Error') message = body.error.message\n } catch {\n // response body was not JSON\n }\n }\n\n return { message, statusCode }\n}\n\nfunction classifyProviderError(message: string, statusCode?: number): string {\n const fullContext = `${message} ${statusCode ?? ''}`\n if (/auth|unauthorized|401|invalid.*key|permission/i.test(fullContext)) {\n return 'auth_error'\n }\n if (/model.*not.*support|model.*not.*found|not found|404|does not exist/i.test(fullContext)) {\n return 'model_not_found'\n }\n if (/ECONNREFUSED|ENOTFOUND|timeout|abort|fetch failed|network/i.test(fullContext)) {\n return 'network_error'\n }\n if (/rate|429|quota|limit/i.test(fullContext)) {\n return 'rate_limit'\n }\n if (/invalid_request|400|bad request/i.test(fullContext)) {\n return 'invalid_request'\n }\n return 'provider_error'\n}\n\nfunction publicLLMTestMessage(category: string, providerMessage: string): string {\n switch (category) {\n case 'auth_error':\n return LLM_TEST_AUTH_ERROR_MESSAGE\n case 'model_not_found':\n return LLM_TEST_MODEL_NOT_FOUND_MESSAGE\n case 'network_error':\n return LLM_TEST_NETWORK_ERROR_MESSAGE\n case 'provider_error':\n return `Connection failed. ${providerMessage}`\n default:\n return providerMessage\n }\n}\n\nfunction isLocalLLMBaseURL(baseURL: unknown): boolean {\n if (typeof baseURL !== 'string' || !baseURL.trim()) return false\n try {\n const url = new URL(baseURL)\n const hostname = url.hostname.toLowerCase()\n return hostname === 'localhost'\n || hostname === '0.0.0.0'\n || hostname === '::1'\n || hostname === '[::1]'\n || hostname.startsWith('127.')\n || hostname.endsWith('.local')\n } catch {\n return false\n }\n}\n\nfunction llmConnectionTestTimeoutMs(config: { provider?: unknown; baseURL?: unknown }): number {\n // Connectivity probes are config-screen smoke checks only; real run execution\n // uses configured test timeout metadata and does not read this value.\n if (LOCAL_COMPATIBLE_LLM_PROVIDERS.has(String(config.provider)) && isLocalLLMBaseURL(config.baseURL)) {\n return LOCAL_COMPATIBLE_LLM_CONNECTION_TEST_TIMEOUT_MS\n }\n return REMOTE_LLM_CONNECTION_TEST_TIMEOUT_MS\n}\n\nfunction parseUrl(req: IncomingMessage): URL {\n return new URL(req.url ?? '/', 'http://localhost')\n}\n\nfunction json(res: ServerResponse, data: unknown, status = 200): void {\n const body = JSON.stringify(data)\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n })\n res.end(body)\n}\n\nfunction notFound(res: ServerResponse, message = 'Not found'): void {\n json(res, { error: message }, 404)\n}\n\nfunction cors(res: ServerResponse): void {\n res.writeHead(204, {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n })\n res.end()\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isDashboardProductEventName(value: unknown): value is DashboardProductEventName {\n return typeof value === 'string' && DASHBOARD_PRODUCT_EVENT_NAME_SET.has(value as DashboardProductEventName)\n}\n\nfunction filterDashboardProductEventProperties(\n name: DashboardProductEventName,\n properties: Record<string, unknown>,\n): Record<string, unknown> {\n const allowedKeys = DASHBOARD_PRODUCT_EVENT_PROPERTY_KEYS[name]\n const filtered: Record<string, unknown> = {}\n for (const key of allowedKeys) {\n if (Object.prototype.hasOwnProperty.call(properties, key)) {\n filtered[key] = properties[key]\n }\n }\n return filtered\n}\n\nasync function readAnalyticsServiceConfig(configManager: ConfigManager | undefined): Promise<AnalyticsServiceConfig> {\n if (!configManager) return {}\n\n try {\n const config = await configManager.read() as { analytics?: { privacy?: unknown } } | undefined\n if (config?.analytics?.privacy === true) {\n return { analytics: { privacy: true } }\n }\n } catch {\n // Fail closed for telemetry while keeping the HTTP route non-blocking.\n return { analytics: { privacy: true } }\n }\n return {}\n}\n\nfunction getPathInsideDir(candidatePath: string, rootDir: string): string | null {\n const relativePath = relative(rootDir, candidatePath)\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) {\n return null\n }\n return relativePath\n}\n\nfunction isPlainFileName(value: string): boolean {\n const fileName = value.trim()\n return fileName.length > 0\n && fileName !== '.'\n && fileName !== '..'\n && !isAbsolute(fileName)\n && fileName === basename(fileName)\n && !/[\\\\/\\0]/.test(fileName)\n}\n\nfunction createHookRegistryManager(configManager?: ConfigManager, configPath?: string): HookRegistryManager | null {\n if (!configManager || !configPath) {\n return null\n }\n return new HookRegistryManager(configManager, configPath)\n}\n\nfunction normalizeRunFilterValue(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim().toLowerCase()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction buildRunRequestAttributes(input: {\n trigger: 'dashboard' | 'api' | 'mcp'\n runner?: 'local' | 'browserstack'\n userAttributes?: unknown\n}): RunAttributes {\n const internal = buildInternalRunAttributes({\n trigger: input.trigger,\n runner: input.runner ?? 'local',\n })\n const user = validateUserRunAttributes(input.userAttributes, 'run attributes')\n return mergeRunAttributes(internal, user)\n}\n\nfunction parseDashboardRunTriggerSource(value: unknown): { ok: true; trigger: 'dashboard' | 'mcp' } | { ok: false; error: string } {\n if (value === undefined || value === null) return { ok: true, trigger: 'dashboard' }\n if (value === 'dashboard' || value === 'mcp') return { ok: true, trigger: value }\n return { ok: false, error: 'triggerSource must be one of: dashboard, mcp' }\n}\n\nfunction parseAttributePredicates(searchParams: URLSearchParams): { ok: true; predicates: AttributePredicate[] } | { ok: false; error: string } {\n const predicates = new Map<string, AttributePredicate>()\n for (const [paramKey, value] of searchParams.entries()) {\n const match = /^attributes\\[([^\\]]*)\\](?:\\[(regex)\\])?$/.exec(paramKey)\n if (!match) continue\n const key = match[1]\n const mode = match[2] === 'regex' ? 'regex' : 'exact'\n if (!key.trim()) return { ok: false, error: 'Attribute key must be non-empty' }\n if (!value.trim()) return { ok: false, error: 'Attribute value must be non-empty' }\n const existing = predicates.get(key)\n if (existing && existing.mode !== mode) {\n return { ok: false, error: `Cannot combine exact and regex attribute filters for \"${key}\"` }\n }\n if (mode === 'regex') {\n try {\n new RegExp(value)\n } catch {\n return { ok: false, error: `Invalid attribute regex for \"${key}\"` }\n }\n }\n predicates.set(key, { key, value, mode })\n }\n return { ok: true, predicates: [...predicates.values()] }\n}\n\nfunction parseAnalyticsScopePredicates(config: Record<string, unknown> | undefined): { ok: true; predicates: AttributePredicate[] } | { ok: false; error: string } {\n const analytics = config?.analytics\n if (!analytics || typeof analytics !== 'object' || Array.isArray(analytics)) return { ok: true, predicates: [] }\n const passRateScope = (analytics as Record<string, unknown>).passRateScope\n if (!passRateScope || typeof passRateScope !== 'object' || Array.isArray(passRateScope)) return { ok: true, predicates: [] }\n const attributes = (passRateScope as Record<string, unknown>).attributes\n if (!attributes || typeof attributes !== 'object' || Array.isArray(attributes)) return { ok: true, predicates: [] }\n\n const predicates: AttributePredicate[] = []\n for (const [key, rawValue] of Object.entries(attributes)) {\n if (!key.trim()) return { ok: false, error: 'analytics.passRateScope attribute key must be non-empty' }\n if (typeof rawValue === 'string') {\n if (!rawValue.trim()) return { ok: false, error: `analytics.passRateScope attribute \"${key}\" must be non-empty` }\n predicates.push({ key, value: rawValue, mode: 'exact' })\n continue\n }\n if (rawValue && typeof rawValue === 'object' && !Array.isArray(rawValue) && typeof (rawValue as { regex?: unknown }).regex === 'string') {\n const regex = (rawValue as { regex: string }).regex\n if (!regex.trim()) return { ok: false, error: `analytics.passRateScope attribute \"${key}\" regex must be non-empty` }\n try {\n new RegExp(regex)\n } catch {\n return { ok: false, error: `Invalid analytics.passRateScope regex for \"${key}\"` }\n }\n predicates.push({ key, value: regex, mode: 'regex' })\n }\n }\n return { ok: true, predicates }\n}\n\nfunction validateAnalyticsPassRateScope(value: unknown): ConfigSectionValidationResult {\n const result = AnalyticsSchema.shape.passRateScope.safeParse(value)\n if (result.success) return { success: true }\n return {\n success: false,\n error: {\n issues: result.error.issues.map((issue) => ({\n message: issue.message,\n path: issue.path,\n })),\n },\n }\n}\n\nasync function readAnalyticsScopePredicates(configManager: ConfigManager | undefined): Promise<{ ok: true; predicates: AttributePredicate[] } | { ok: false; error: string }> {\n if (!configManager) return { ok: true, predicates: [] }\n const config = await configManager.read()\n const parsedConfig = AgentQaConfigSchema.safeParse(config)\n if (!parsedConfig.success) {\n return { ok: true, predicates: [] }\n }\n return parseAnalyticsScopePredicates(parsedConfig.data as Record<string, unknown>)\n}\n\nfunction calculateFlakyMetrics(runs: RunRow[]): { score: number; statusCount: number } {\n const statuses = runs\n .filter(r => r.status === 'passed' || r.status === 'failed')\n .map(r => r.status)\n let alternations = 0\n for (let i = 1; i < statuses.length; i++) {\n if (statuses[i] !== statuses[i - 1]) alternations++\n }\n return {\n score: statuses.length > 1 ? alternations / (statuses.length - 1) : 0,\n statusCount: statuses.length,\n }\n}\n\nfunction normalizeSupportedPlatform(value: unknown): SupportedPlatform | null {\n if (value !== 'web' && value !== 'android' && value !== 'ios') return null\n return value\n}\n\nfunction parseIsoDateQueryParam(\n value: string | null,\n field: 'from' | 'to',\n): { ok: true; value?: string } | { ok: false; error: string } {\n if (!value) return { ok: true, value: undefined }\n return Number.isNaN(Date.parse(value))\n ? { ok: false, error: `${field} must be a valid ISO date` }\n : { ok: true, value }\n}\n\nfunction parseBoundedIntegerQueryParam(\n value: string | null,\n field: string,\n min: number,\n max: number,\n fallback: number,\n): { ok: true; value: number } | { ok: false; error: string } {\n if (!value) return { ok: true, value: fallback }\n const parsed = Number.parseInt(value, 10)\n if (!Number.isFinite(parsed)) {\n return { ok: false, error: `${field} must be an integer` }\n }\n return { ok: true, value: Math.min(max, Math.max(min, parsed)) }\n}\n\nfunction getTargetPlatformMap(config: unknown): Map<string, SupportedPlatform> {\n const targetsValue = (config as {\n registry?: { targets?: Record<string, { platform?: unknown }> }\n }).registry?.targets\n\n const targetPlatforms = new Map<string, SupportedPlatform>()\n if (!targetsValue || typeof targetsValue !== 'object') return targetPlatforms\n\n for (const [targetName, targetConfig] of Object.entries(targetsValue)) {\n const platform = normalizeSupportedPlatform(targetConfig?.platform)\n if (platform) targetPlatforms.set(targetName, platform)\n }\n\n return targetPlatforms\n}\n\nasync function readTargetPlatformMap(configManager?: ConfigManager): Promise<Map<string, SupportedPlatform>> {\n if (!configManager) return new Map()\n try {\n const config = await configManager.read()\n return getTargetPlatformMap(config)\n } catch {\n return new Map()\n }\n}\n\nfunction parseTimeoutConfigTestTimeoutMs(timeoutConfig: unknown): number | undefined {\n if (timeoutConfig && typeof timeoutConfig === 'object' && !Array.isArray(timeoutConfig)) {\n const transformedTimeout = (timeoutConfig as { test?: unknown }).test\n if (typeof transformedTimeout === 'number' && Number.isFinite(transformedTimeout) && transformedTimeout > 0) {\n return transformedTimeout\n }\n }\n const parsed = TimeoutConfigSchema.partial().safeParse(timeoutConfig)\n if (!parsed.success) return undefined\n const testTimeout = parsed.data.test\n return typeof testTimeout === 'number' && Number.isFinite(testTimeout) && testTimeout > 0\n ? testTimeout\n : undefined\n}\n\nfunction parseUseTestTimeoutMs(useConfig: unknown): number | undefined {\n if (!useConfig || typeof useConfig !== 'object' || Array.isArray(useConfig)) return undefined\n return parseTimeoutConfigTestTimeoutMs((useConfig as { timeout?: unknown }).timeout)\n}\n\nasync function readConfigTestTimeoutMs(configManager?: ConfigManager): Promise<number | undefined> {\n if (!configManager) return undefined\n try {\n const config = await configManager.read()\n const parsed = AgentQaConfigSchema.safeParse(config)\n if (parsed.success) {\n return parseUseTestTimeoutMs(parsed.data.use)\n }\n return parseUseTestTimeoutMs((config as { use?: unknown }).use)\n } catch {\n return undefined\n }\n}\n\nfunction readTestYamlTimeoutMs(content: string): number | undefined {\n try {\n const parsedYaml = parseYaml(content)\n const parsedTest = TestDefinitionSchema.safeParse(parsedYaml)\n if (parsedTest.success) {\n return parseUseTestTimeoutMs(parsedTest.data.use)\n }\n return parseUseTestTimeoutMs((parsedYaml as { use?: unknown } | null | undefined)?.use)\n } catch {\n return undefined\n }\n}\n\nfunction readSuiteYamlTimeoutMs(content: string): number | undefined {\n try {\n const parsedYaml = parseYaml(content)\n const parsedSuite = SuiteDefinitionSchema.safeParse(parsedYaml)\n if (parsedSuite.success) {\n return parseUseTestTimeoutMs(parsedSuite.data.use)\n }\n return parseUseTestTimeoutMs((parsedYaml as { use?: unknown } | null | undefined)?.use)\n } catch {\n return undefined\n }\n}\n\nfunction parseUseParallel(useConfig: unknown): boolean | undefined {\n if (!isRecord(useConfig)) return undefined\n return typeof useConfig.parallel === 'boolean' ? useConfig.parallel : undefined\n}\n\nasync function readConfigUseParallel(configManager?: ConfigManager): Promise<boolean | undefined> {\n if (!configManager) return undefined\n try {\n const config = await configManager.read()\n const parsed = AgentQaConfigSchema.safeParse(config)\n if (parsed.success) {\n return parseUseParallel(parsed.data.use)\n }\n return parseUseParallel((config as { use?: unknown }).use)\n } catch {\n return undefined\n }\n}\n\nfunction readSuiteYamlParallel(content: string): boolean | undefined {\n try {\n const parsedYaml = parseYaml(content)\n const parsedSuite = SuiteDefinitionSchema.safeParse(parsedYaml)\n if (parsedSuite.success) {\n return parseUseParallel(parsedSuite.data.use)\n }\n return parseUseParallel((parsedYaml as { use?: unknown } | null | undefined)?.use)\n } catch {\n return undefined\n }\n}\n\nfunction withDashboardExecutionBuffer(\n baseTimeoutMs: number | undefined,\n source: DashboardExecutionTimeoutSource,\n): DashboardExecutionTimeout {\n if (!baseTimeoutMs) {\n return { source: 'none' }\n }\n return {\n timeoutMs: baseTimeoutMs + DASHBOARD_EXECUTION_TIMEOUT_BUFFER_MS,\n source,\n baseTimeoutMs,\n bufferMs: DASHBOARD_EXECUTION_TIMEOUT_BUFFER_MS,\n }\n}\n\nasync function resolveDashboardExecutionTimeout(opts: {\n isSuite: boolean\n file?: string\n normalizedTestPath?: string\n testFileManager?: TestFileManager\n suiteFileManager?: SuiteFileManager\n configManager?: ConfigManager\n}): Promise<DashboardExecutionTimeout> {\n if (opts.file) {\n if (opts.isSuite && opts.suiteFileManager) {\n try {\n const suiteContent = await opts.suiteFileManager.read(opts.file)\n const suiteTimeout = readSuiteYamlTimeoutMs(suiteContent)\n if (suiteTimeout) {\n return withDashboardExecutionBuffer(suiteTimeout, 'suite.use.timeout.test')\n }\n } catch {\n // Fall through to config timeout for draft or unreadable suite files.\n }\n } else if (!opts.isSuite && opts.testFileManager) {\n try {\n const testContent = await opts.testFileManager.read(opts.normalizedTestPath ?? opts.file)\n const testTimeout = readTestYamlTimeoutMs(testContent)\n if (testTimeout) {\n return withDashboardExecutionBuffer(testTimeout, 'test.use.timeout.test')\n }\n } catch {\n // Fall through to config timeout for draft or unreadable test files.\n }\n }\n }\n\n const configTimeout = await readConfigTestTimeoutMs(opts.configManager)\n return withDashboardExecutionBuffer(configTimeout, configTimeout ? 'config.use.timeout.test' : 'none')\n}\n\nfunction toExecutionTimeoutMetadata(timeout: DashboardExecutionTimeout): Record<string, unknown> {\n if (!timeout.timeoutMs) {\n return { timeoutSource: timeout.source }\n }\n return {\n timeout: timeout.timeoutMs,\n timeoutSource: timeout.source,\n timeoutBaseMs: timeout.baseTimeoutMs,\n timeoutBufferMs: timeout.bufferMs,\n }\n}\n\nfunction resolveEffectivePlatform(\n platform: string | null | undefined,\n targetName: string | null | undefined,\n targetPlatforms: Map<string, SupportedPlatform>,\n fallbackPlatform?: string | null,\n): SupportedPlatform | null {\n const explicitPlatform = normalizeSupportedPlatform(platform)\n if (explicitPlatform) return explicitPlatform\n\n if (targetName) {\n const targetPlatform = targetPlatforms.get(targetName)\n if (targetPlatform) return targetPlatform\n }\n\n return normalizeSupportedPlatform(fallbackPlatform)\n}\n\nfunction extractRunTargetName(testFileContent: string | null | undefined): string | null {\n if (!testFileContent) return null\n return extractTestFileMetadata(testFileContent).targetName\n}\n\ntype EnrichedRunRow = RunRow & {\n targetName: string | null\n tests?: EnrichedRunRow[]\n}\n\nfunction enrichRunRow(\n run: RunRow,\n targetPlatforms: Map<string, SupportedPlatform>,\n tests?: EnrichedRunRow[],\n): EnrichedRunRow {\n const metadata = run.testFileContent ? extractTestFileMetadata(run.testFileContent) : null\n let targetName = metadata?.targetName ?? extractRunTargetName(run.testFileContent)\n if (!targetName && tests && tests.length > 0) {\n const uniqueChildTargets = [...new Set(\n tests\n .map((test) => test.targetName)\n .filter((value): value is string => typeof value === 'string' && value.length > 0),\n )]\n if (uniqueChildTargets.length === 1) {\n targetName = uniqueChildTargets[0]\n }\n }\n\n const uniqueChildPlatforms = tests\n ? [...new Set(\n tests\n .map((test) => normalizeSupportedPlatform(test.platform))\n .filter((value): value is SupportedPlatform => value !== null),\n )]\n : []\n\n const platform = resolveEffectivePlatform(\n metadata?.platform,\n targetName,\n targetPlatforms,\n uniqueChildPlatforms.length === 1 ? uniqueChildPlatforms[0] : run.platform,\n )\n\n return {\n ...run,\n platform: platform ?? run.platform,\n targetName,\n ...(tests ? { tests } : {}),\n }\n}\n\nfunction matchesTargetFilter(run: EnrichedRunRow, filterValue: string | null): boolean {\n if (!filterValue) return true\n if (normalizeRunFilterValue(run.targetName) === filterValue) return true\n return run.tests?.some((test) => normalizeRunFilterValue(test.targetName) === filterValue) ?? false\n}\n\nfunction matchesPlatformFilter(run: EnrichedRunRow, filterValue: SupportedPlatform | null): boolean {\n if (!filterValue) return true\n if (normalizeSupportedPlatform(run.platform) === filterValue) return true\n return run.tests?.some((test) => normalizeSupportedPlatform(test.platform) === filterValue) ?? false\n}\n\nfunction getArtifactMissingSections(artifact: RunArtifactRow | null): string[] {\n if (!artifact) return ['artifact']\n const missing: string[] = []\n const payload = artifact.payload\n if (!('config' in payload)) missing.push('config')\n if (!('source' in payload)) missing.push('source')\n if (!('memory' in payload)) missing.push('memory')\n return missing\n}\n\nconst SECRET_TEMPLATE_RE = /\\{\\{secret:(\\w+)\\}\\}/g\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction sanitizeSecretTemplates(value: unknown): unknown {\n if (typeof value === 'string') {\n return value.replace(SECRET_TEMPLATE_RE, (_match, name: string) => `[secret:${name}]`)\n }\n if (Array.isArray(value)) {\n return value.map((item) => sanitizeSecretTemplates(item))\n }\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n return value\n }\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, sanitizeSecretTemplates(item)]),\n )\n }\n return value\n}\n\nfunction sanitizeSecretsFileMetadata(value: unknown): unknown {\n if (value === null || value === undefined) return value\n if (!isRecord(value)) return value\n return {\n path: typeof value.path === 'string' || value.path === null ? value.path : null,\n status: typeof value.status === 'string' ? value.status : 'loaded',\n ...(typeof value.count === 'number' ? { count: value.count } : {}),\n }\n}\n\nfunction sanitizeArtifactPayloadForResponse(payload: RunArtifactRow['payload']): RunArtifactRow['payload'] {\n const sanitized = sanitizeSecretTemplates(payload)\n if (!isRecord(sanitized)) return payload\n const config = sanitized.config\n if (!isRecord(config) || !('secretsFile' in config)) return sanitized as unknown as RunArtifactRow['payload']\n return {\n ...sanitized,\n config: {\n ...config,\n secretsFile: sanitizeSecretsFileMetadata(config.secretsFile),\n },\n } as RunArtifactRow['payload']\n}\n\nfunction sanitizeArtifactForResponse(artifact: RunArtifactRow | null): RunArtifactRow | null {\n if (!artifact) return null\n return {\n ...artifact,\n payload: sanitizeArtifactPayloadForResponse(artifact.payload),\n }\n}\n\nasync function normalizeDashboardWorkspacePath(\n filePath: string,\n workspacePaths: ResolvedWorkspacePaths | undefined,\n kind: WorkspaceFileKind,\n requireExisting = true,\n): Promise<{ storagePath: string; executionPath: string }> {\n if (!workspacePaths) {\n throw new Error('Workspace path resolution is required for dashboard-triggered runs')\n }\n\n const record = await resolveWorkspaceFileTarget({\n workspace: workspacePaths,\n kind,\n filePath,\n requireExisting,\n })\n\n return { storagePath: record.workspaceRelativePath, executionPath: record.absolutePath }\n}\n\nfunction workspaceRecordToPath(record: WorkspaceFileRecord): { storagePath: string; executionPath: string } {\n return { storagePath: record.workspaceRelativePath, executionPath: record.absolutePath }\n}\n\nasync function resolveDashboardTestPattern(\n pattern: string,\n workspacePaths: ResolvedWorkspacePaths | undefined,\n): Promise<Array<{ storagePath: string; executionPath: string }>> {\n if (!workspacePaths) {\n throw new Error('Workspace path resolution is required for dashboard-triggered runs')\n }\n\n const normalizedPattern = pattern.replace(/\\\\/g, '/')\n if (isAbsolute(pattern) || normalizedPattern.split('/').includes('..')) {\n throw new Error(`Workspace test pattern is not allowed: ${pattern}`)\n }\n\n const candidates = await discoverWorkspaceFiles({ workspace: workspacePaths, kind: 'test' })\n const patternWorkspace: ResolvedWorkspacePaths = {\n ...workspacePaths,\n testMatch: [pattern],\n suiteMatch: [],\n }\n return candidates\n .filter((record) => isWorkspacePathMatch({\n workspace: patternWorkspace,\n kind: 'test',\n workspaceRelativePath: record.workspaceRelativePath,\n }))\n .map(workspaceRecordToPath)\n}\n\nfunction isSuiteFilePath(filePath: string | undefined): boolean {\n if (!filePath) return false\n const normalized = filePath.toLowerCase()\n return normalized.endsWith('.suite.yaml') || normalized.endsWith('.suite.yml')\n}\n\nasync function normalizeDashboardSuitePath(\n filePath: string,\n suiteFileManager?: SuiteFileManager,\n): Promise<{ storagePath: string; executionPath: string }> {\n if (!suiteFileManager) {\n throw new Error('Suite file management is required for dashboard-triggered suite runs')\n }\n\n return suiteFileManager.resolvePath(filePath)\n}\n\nfunction sanitizeQueuedRunMetadata(metadata: Record<string, unknown> | undefined): Record<string, unknown> {\n const { args: _args, target: _target, isSuite: _isSuite, ...safeMetadata } = metadata ?? {}\n return safeMetadata\n}\n\nfunction resolveArtifactPath(\n candidatePath: string,\n rootDir: string,\n apiPrefix: '/api/screenshots/' | '/api/videos/',\n): string | null {\n const normalizedCandidate = candidatePath.trim()\n if (!normalizedCandidate) return null\n const resolvedRootDir = resolve(rootDir)\n\n if (isAbsolute(normalizedCandidate)) {\n const resolvedAbsolute = resolve(normalizedCandidate)\n return getPathInsideDir(resolvedAbsolute, resolvedRootDir) ? resolvedAbsolute : null\n }\n\n const relativePath = normalizedCandidate.startsWith(apiPrefix)\n ? normalizedCandidate.slice(apiPrefix.length)\n : normalizedCandidate\n const resolvedPath = resolve(resolvedRootDir, relativePath)\n return getPathInsideDir(resolvedPath, resolvedRootDir) ? resolvedPath : null\n}\n\nasync function cleanupDeletedRunArtifacts(\n deletedRunIds: string[],\n screenshotPaths: string[],\n videoPaths: string[],\n dirs: {\n screenshotsDir?: string\n videosDir?: string\n },\n): Promise<void> {\n const cleanupTargets = new Set<string>()\n\n for (const runId of deletedRunIds) {\n if (dirs.screenshotsDir) cleanupTargets.add(join(dirs.screenshotsDir, runId))\n if (dirs.videosDir) cleanupTargets.add(join(dirs.videosDir, runId))\n }\n\n if (dirs.screenshotsDir) {\n for (const screenshotPath of screenshotPaths) {\n const resolvedPath = resolveArtifactPath(screenshotPath, dirs.screenshotsDir, '/api/screenshots/')\n if (resolvedPath) cleanupTargets.add(resolvedPath)\n }\n }\n\n if (dirs.videosDir) {\n for (const videoPath of videoPaths) {\n const resolvedPath = resolveArtifactPath(videoPath, dirs.videosDir, '/api/videos/')\n if (resolvedPath) cleanupTargets.add(resolvedPath)\n }\n }\n\n await Promise.allSettled(\n [...cleanupTargets].map((targetPath) => rm(targetPath, { recursive: true, force: true })),\n )\n}\n\nasync function readWorkspaceHooks(\n configManager: ConfigManager | undefined,\n configPath: string | undefined,\n): Promise<{\n hooks: Array<{ name: string }>\n filePath: string\n resolvedHooks: Map<string, import('@vostride/agent-qa-core').HookDefinition>\n errors: string[]\n missing: boolean\n hookRegistryError?: string\n}> {\n const hookRegistryManager = createHookRegistryManager(configManager, configPath)\n if (!hookRegistryManager) {\n return {\n hooks: [],\n filePath: '',\n resolvedHooks: new Map(),\n errors: ['Config management not available'],\n missing: true,\n hookRegistryError: 'Config management not available',\n }\n }\n\n const [hookCatalog, prepareResult] = await Promise.all([\n hookRegistryManager.readCatalog(),\n hookRegistryManager.prepareForExecution(),\n ])\n\n return {\n hooks: hookCatalog.hooks.map((hook) => ({ name: hook.name })),\n filePath: hookCatalog.filePath,\n resolvedHooks: prepareResult.resolvedHooks,\n errors: hookCatalog.errors,\n missing: hookCatalog.missing,\n hookRegistryError: prepareResult.hookRegistryError,\n }\n}\n\nasync function readWorkspaceEnvVars(\n workspacePaths: ResolvedWorkspacePaths | undefined,\n): Promise<Record<string, string>> {\n if (!workspacePaths) {\n return {}\n }\n\n try {\n const content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n return parseEnvFile(content)\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`workspace.envFile not found: ${workspacePaths.envFile.absolutePath}`)\n }\n throw error\n }\n}\n\nfunction validateHookRunRequest(body: unknown): {\n overrides: Record<string, string>\n fieldErrors: Array<{ field: 'registry'; code: string; message: string }>\n} {\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n return {\n overrides: {},\n fieldErrors: [\n {\n field: 'registry',\n code: 'invalid_payload',\n message: 'Hook run payload is required',\n },\n ],\n }\n }\n\n const rawOverrides = (body as { overrides?: unknown }).overrides\n if (rawOverrides === undefined) {\n return { overrides: {}, fieldErrors: [] }\n }\n\n if (!Array.isArray(rawOverrides)) {\n return {\n overrides: {},\n fieldErrors: [\n {\n field: 'registry',\n code: 'invalid_overrides',\n message: 'Hook run overrides must be an array',\n },\n ],\n }\n }\n\n const fieldErrors: Array<{ field: 'registry'; code: string; message: string }> = []\n const overrides: Record<string, string> = {}\n const seenKeys = new Set<string>()\n\n rawOverrides.forEach((entry, index) => {\n if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {\n fieldErrors.push({\n field: 'registry',\n code: 'invalid_override',\n message: `Override ${index + 1} must be an object with key and value`,\n })\n return\n }\n\n const key = typeof (entry as { key?: unknown }).key === 'string'\n ? (entry as { key: string }).key.trim()\n : ''\n const value = (entry as { value?: unknown }).value\n\n if (!key) {\n fieldErrors.push({\n field: 'registry',\n code: 'invalid_override_key',\n message: `Override ${index + 1} must include a non-empty key`,\n })\n return\n }\n\n if (seenKeys.has(key)) {\n fieldErrors.push({\n field: 'registry',\n code: 'duplicate_override_key',\n message: `Override key \"${key}\" is duplicated`,\n })\n return\n }\n\n if (typeof value !== 'string') {\n fieldErrors.push({\n field: 'registry',\n code: 'invalid_override_value',\n message: `Override \"${key}\" must have a string value`,\n })\n return\n }\n\n seenKeys.add(key)\n overrides[key] = value\n })\n\n return { overrides, fieldErrors }\n}\n\nfunction summarizeHookNetworkLogs(\n networkLogs: Array<{\n url: string\n method: string\n status: number\n startTime: number\n endTime: number\n }> | undefined,\n): import('../hooks/hook-registry-types.js').HookRunNetworkLogEntry[] {\n return (networkLogs ?? []).map((entry, index) => ({\n id: `network-${index + 1}`,\n method: entry.method,\n url: entry.url,\n statusCode: Number.isFinite(entry.status) ? entry.status : null,\n durationMs: Number.isFinite(entry.endTime - entry.startTime)\n ? Math.max(0, entry.endTime - entry.startTime)\n : null,\n error: null,\n }))\n}\n\ninterface RouterDeps {\n db: DashboardDatabase\n artifactsDir?: string\n workspacePaths?: ResolvedWorkspacePaths\n testRunner?: TestRunner\n jobQueue?: JobQueue\n testFileManager?: TestFileManager\n suiteFileManager?: SuiteFileManager\n configManager?: ConfigManager\n configPath?: string\n\n llmConfig?: DashboardRuntimeLLMConfig\n authFetch?: typeof globalThis.fetch\n sessionManager?: import('../live-editor/session-manager.js').SessionManager\n analyticsBridge?: {\n buildAnalyticsEvent: typeof buildAnalyticsEvent\n captureAnalytics: typeof captureAnalytics\n resolveAnalyticsStandardProperties: typeof resolveAnalyticsStandardProperties\n }\n}\n\nexport function createRouter(deps: RouterDeps): (req: IncomingMessage, res: ServerResponse) => void\nexport function createRouter(db: DashboardDatabase, artifactsDir?: string): (req: IncomingMessage, res: ServerResponse) => void\nexport function createRouter(dbOrDeps: DashboardDatabase | RouterDeps, artifactsDir?: string): (req: IncomingMessage, res: ServerResponse) => void {\n const deps: RouterDeps = 'db' in dbOrDeps && typeof (dbOrDeps as RouterDeps).db === 'object' && 'getRuns' in ((dbOrDeps as RouterDeps).db ?? {})\n ? dbOrDeps as RouterDeps\n : { db: dbOrDeps as DashboardDatabase, artifactsDir }\n const { db, testRunner, jobQueue, testFileManager, suiteFileManager, configManager, workspacePaths, llmConfig, authFetch, sessionManager } = deps\n const pluginOAuthSessions = new Map<string, PluginOAuthSession>()\n const analyticsBridge = deps.analyticsBridge ?? {\n buildAnalyticsEvent,\n captureAnalytics,\n resolveAnalyticsStandardProperties,\n }\n const ssDir = deps.artifactsDir ? join(deps.artifactsDir, 'screenshots') : undefined\n const vidDir = deps.artifactsDir ? join(deps.artifactsDir, 'videos') : undefined\n const memoryCatalogManager = new MemoryCatalogManager({ configManager, configPath: deps.configPath })\n\n return (req: IncomingMessage, res: ServerResponse) => {\n if (req.method === 'OPTIONS') {\n cors(res)\n return\n }\n\n const url = parseUrl(req)\n const path = url.pathname\n\n // POST /api/analytics/events — best-effort dashboard product analytics bridge\n if (path === '/api/analytics/events' && req.method === 'POST') {\n readJsonBody<{ name?: unknown; properties?: unknown }>(req)\n .then((body) => {\n if (\n !isPlainRecord(body)\n || !isDashboardProductEventName(body.name)\n || (\n Object.prototype.hasOwnProperty.call(body, 'properties')\n && body.properties !== undefined\n && !isPlainRecord(body.properties)\n )\n ) {\n json(res, { error: 'Invalid analytics event' }, 400)\n return\n }\n\n const name = body.name\n const browserProperties = isPlainRecord(body.properties) ? body.properties : {}\n json(res, { accepted: true }, 202)\n\n void (async () => {\n try {\n const config = await readAnalyticsServiceConfig(configManager)\n if (config.analytics?.privacy === true) {\n return\n }\n\n const standardProperties = await analyticsBridge.resolveAnalyticsStandardProperties({ surface: 'dashboard-ui' })\n const event = analyticsBridge.buildAnalyticsEvent({\n name,\n properties: {\n ...filterDashboardProductEventProperties(name, browserProperties),\n ...standardProperties,\n },\n })\n await analyticsBridge.captureAnalytics(event, { config })\n } catch {\n // Analytics is intentionally best-effort and invisible to dashboard users.\n }\n })()\n })\n .catch(() => json(res, { error: 'Invalid analytics event' }, 400))\n return\n }\n\n // GET /api/runs\n if (path === '/api/runs' && req.method === 'GET') {\n const status = url.searchParams.get('status') ?? undefined\n const name = url.searchParams.get('name') ?? undefined\n const platform = url.searchParams.get('platform') ?? undefined\n const target = normalizeRunFilterValue(url.searchParams.get('target'))\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const attributePredicatesResult = parseAttributePredicates(url.searchParams)\n if (!attributePredicatesResult.ok) {\n json(res, { error: attributePredicatesResult.error }, 400)\n return\n }\n\n void readTargetPlatformMap(configManager)\n .then((targetPlatforms) => {\n const allRuns = db.getRuns({\n status,\n name,\n from,\n to,\n attributePredicates: attributePredicatesResult.predicates,\n })\n const enrichedRuns = allRuns.map(run => {\n if (run.suiteId && !run.parentRunId) {\n const tests = db.getRunsByParent(run.id).map(test => enrichRunRow(test, targetPlatforms))\n return enrichRunRow(run, targetPlatforms, tests)\n }\n return enrichRunRow(run, targetPlatforms)\n })\n const platformFilteredRuns = enrichedRuns.filter(run =>\n matchesPlatformFilter(run, normalizeSupportedPlatform(platform)),\n )\n const targetOptions = Array.from(new Set(\n platformFilteredRuns\n .flatMap(run => [run.targetName, ...(run.tests?.map(test => test.targetName) ?? [])])\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0),\n )).sort((a, b) => a.localeCompare(b))\n const filtered = platformFilteredRuns.filter(run => matchesTargetFilter(run, target))\n\n const runs = filtered.slice(offset, offset + limit)\n json(res, { runs, total: filtered.length, targets: targetOptions })\n })\n .catch(() => json(res, { error: 'Failed to list runs' }, 500))\n return\n }\n\n // GET /api/runs/attributes/keys\n if (path === '/api/runs/attributes/keys' && req.method === 'GET') {\n const limitResult = parseBoundedIntegerQueryParam(url.searchParams.get('limit'), 'limit', 1, 100, 50)\n if (!limitResult.ok) {\n json(res, { error: limitResult.error }, 400)\n return\n }\n json(res, {\n keys: db.listRunAttributeKeys({\n limit: limitResult.value,\n q: url.searchParams.get('q') ?? undefined,\n }),\n })\n return\n }\n\n // GET /api/runs/attributes/values\n if (path === '/api/runs/attributes/values' && req.method === 'GET') {\n const key = url.searchParams.get('key')?.trim()\n if (!key) {\n json(res, { error: 'key is required' }, 400)\n return\n }\n const limitResult = parseBoundedIntegerQueryParam(url.searchParams.get('limit'), 'limit', 1, 100, 50)\n if (!limitResult.ok) {\n json(res, { error: limitResult.error }, 400)\n return\n }\n json(res, {\n values: db.listRunAttributeValues(key, {\n limit: limitResult.value,\n q: url.searchParams.get('q') ?? undefined,\n }),\n })\n return\n }\n\n // GET /api/runs/:id/artifact\n const runArtifactMatch = path.match(/^\\/api\\/runs\\/([^/]+)\\/artifact$/)\n if (runArtifactMatch && req.method === 'GET') {\n const runId = decodeURIComponent(runArtifactMatch[1])\n const run = db.getRun(runId)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const bundle = db.getRunArtifactBundle(runId)\n json(res, {\n run,\n artifact: sanitizeArtifactForResponse(bundle.artifact),\n children: bundle.children.map((child) => ({\n ...child,\n artifact: sanitizeArtifactForResponse(child.artifact),\n })),\n missingSections: getArtifactMissingSections(bundle.artifact),\n })\n return\n }\n\n // GET /api/runs/:id/accessibility\n if (path.startsWith('/api/runs/') && path.endsWith('/accessibility') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const summary = db.getAccessibilitySummary(id)\n json(res, summary)\n return\n }\n\n // GET /api/runs/:id/steps/:n/reasoning — structured reasoning trace for a step\n const reasoningMatch = path.match(/^\\/api\\/runs\\/([^/]+)\\/steps\\/(\\d+)\\/reasoning$/)\n if (reasoningMatch && req.method === 'GET') {\n const [, runId, stepOrderStr] = reasoningMatch\n const run = db.getRun(runId)\n if (!run) { notFound(res, 'Run not found'); return }\n const stepOrder = parseInt(stepOrderStr, 10)\n const trace = db.getReasoningTrace(runId, stepOrder)\n if (trace) {\n json(res, { trace })\n return\n }\n // Fallback: construct legacy trace from step data for backward compatibility\n const steps = db.getSteps(runId)\n const step = steps.find(s => s.stepOrder === stepOrder)\n if (!step) { notFound(res, 'Step not found'); return }\n json(res, {\n trace: {\n id: null,\n stepId: step.id,\n observeText: step.observation,\n observeDuration: null,\n planReasoning: step.reasoning,\n planConfidence: step.confidence,\n planAction: step.plannedAction,\n planDuration: null,\n executeAction: step.action,\n executeDuration: null,\n verifyReasoning: null,\n verifySuccess: step.result === 'success' ? true : step.result === 'failure' ? false : null,\n verifyDuration: null,\n healAttempts: step.healingAttempts,\n totalDuration: step.duration,\n screenStateBefore: null,\n screenStateAfter: null,\n createdAt: step.createdAt,\n },\n })\n return\n }\n\n // GET /api/runs/:id/execution-logs\n if (path.startsWith('/api/runs/') && path.endsWith('/execution-logs') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const stepId = url.searchParams.get('stepId') ?? undefined\n const type = url.searchParams.get('type') ?? undefined\n\n if (run.suiteId && !run.parentRunId) {\n const childRuns = db.getRunsByParent(id)\n const allRunIds = [id, ...childRuns.map((c: any) => c.id)]\n let allLogs: any[] = []\n for (const rid of allRunIds) {\n allLogs.push(...db.getExecutionLogs({ runId: rid, stepId, type }))\n }\n json(res, { logs: allLogs })\n return\n }\n\n const logs = db.getExecutionLogs({ runId: id, stepId, type })\n json(res, { logs })\n return\n }\n\n // GET /api/runs/:id/logs\n if (path.startsWith('/api/runs/') && path.endsWith('/logs') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const stepId = url.searchParams.get('stepId') ?? undefined\n const level = url.searchParams.get('level') ?? undefined\n const source = url.searchParams.get('source') ?? undefined\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 500\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const logs = db.getLogs({ runId: id, stepId, level, source, limit, offset })\n json(res, { logs, total: logs.length })\n return\n }\n\n // GET /api/runs/:id/steps\n if (path.startsWith('/api/runs/') && path.endsWith('/steps') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const steps = db.getSteps(id)\n json(res, { steps })\n return\n }\n\n // POST /api/runs/:id/cancel — cancel a pending or running execution\n if (path.startsWith('/api/runs/') && path.endsWith('/cancel') && req.method === 'POST') {\n if (!jobQueue) {\n json(res, { error: 'Queue not available' }, 503)\n return\n }\n const runId = path.slice('/api/runs/'.length, path.length - '/cancel'.length)\n const cancelled = jobQueue.cancel(runId)\n if (cancelled) {\n // For pending jobs, JobQueue already set status='cancelled'.\n // For running jobs, JobQueue emits 'cancel-running' which triggers executionManager.kill().\n // Update DB with cancel metadata for running jobs.\n try {\n const run = db.getRun(runId)\n if (run && run.status === 'cancelled') {\n const duration = run.startedAt\n ? Date.now() - new Date(run.startedAt).getTime()\n : 0\n db.updateRun(runId, {\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: 'Test cancelled by user',\n })\n }\n } catch { /* best-effort */ }\n json(res, { cancelled: true })\n } else {\n json(res, { error: 'Run not found or not cancellable' }, 404)\n }\n return\n }\n\n // DELETE /api/runs/:id\n if (path.startsWith('/api/runs/') && req.method === 'DELETE') {\n const segments = path.split('/')\n if (segments.length !== 4) {\n notFound(res)\n return\n }\n\n const id = segments[3]\n\n try {\n const deletedRun = db.deleteRun(id)\n if (!deletedRun.deleted) {\n notFound(res, 'Run not found')\n return\n }\n\n void cleanupDeletedRunArtifacts(\n deletedRun.deletedRunIds,\n deletedRun.screenshotPaths,\n deletedRun.videoPaths,\n {\n screenshotsDir: ssDir,\n videosDir: vidDir,\n },\n ).finally(() => {\n json(res, { deleted: true, deletedRunIds: deletedRun.deletedRunIds })\n })\n } catch {\n json(res, { error: 'Failed to delete run' }, 500)\n }\n return\n }\n\n // GET /api/runs/:id\n if (path.startsWith('/api/runs/') && req.method === 'GET') {\n const segments = path.split('/')\n if (segments.length !== 4) {\n notFound(res)\n return\n }\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const steps = db.getSteps(id)\n const attempts = db.getRunsByParent(id)\n if (run.suiteId && !run.parentRunId) {\n const tests = db.getRunsByParent(id)\n json(res, { run, steps, attempts, tests })\n } else {\n json(res, { run, steps, attempts })\n }\n return\n }\n\n // GET /api/stats/costs\n if (path === '/api/stats/costs' && req.method === 'GET') {\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const costStats = db.getCostStats({ from, to })\n json(res, costStats)\n return\n }\n\n // GET /api/token-events/stats\n if (path === '/api/token-events/stats' && req.method === 'GET') {\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const stats = db.getTokenEventStats({ from, to })\n json(res, stats)\n return\n }\n\n // GET /api/stats\n if (path === '/api/stats' && req.method === 'GET') {\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const scope = url.searchParams.get('scope') ?? undefined\n if (scope !== undefined && scope !== 'passRate') {\n json(res, { error: 'scope must be passRate when provided' }, 400)\n return\n }\n\n void readAnalyticsScopePredicates(configManager)\n .then((scopeResult) => {\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n const configured = scopeResult.predicates.length > 0\n const allStats = db.getStats({ from, to })\n const scopedStats = configured\n ? db.getStats({ from, to, attributePredicates: scopeResult.predicates })\n : allStats\n const stats = scope === 'passRate' && configured ? scopedStats : allStats\n\n json(res, {\n ...stats,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount: configured ? scopedStats.totalRuns : 0,\n totalCount: allStats.totalRuns,\n },\n })\n })\n .catch(() => {\n json(res, { error: 'Unable to read analytics scope' }, 500)\n })\n return\n }\n\n // GET /api/screenshots/:runId/:filename\n if (path.startsWith('/api/screenshots/') && req.method === 'GET') {\n const segments = path.split('/')\n if (segments.length !== 5 || !ssDir) {\n notFound(res)\n return\n }\n const runId = segments[3]\n const filename = segments[4]\n\n if (runId.includes('..') || filename.includes('..') || runId.includes('/') || filename.includes('/')) {\n notFound(res, 'Invalid path')\n return\n }\n\n const filePath = join(ssDir, runId, filename)\n const resolvedPath = resolve(filePath)\n if (!resolvedPath.startsWith(resolve(ssDir))) {\n notFound(res, 'Invalid path')\n return\n }\n\n stat(filePath).then(s => {\n if (!s.isFile()) {\n notFound(res, 'Screenshot not found')\n return\n }\n readFile(filePath).then(buffer => {\n res.writeHead(200, {\n 'Content-Type': 'image/png',\n 'Content-Length': buffer.length,\n 'Access-Control-Allow-Origin': '*',\n })\n res.end(buffer)\n }).catch(() => notFound(res, 'Screenshot not found'))\n }).catch(() => notFound(res, 'Screenshot not found'))\n return\n }\n\n // GET /api/videos/:runId/:filename\n if (path.startsWith('/api/videos/') && req.method === 'GET') {\n const segments = path.split('/')\n if (segments.length !== 5 || !vidDir) {\n notFound(res)\n return\n }\n const runId = segments[3]\n const filename = segments[4]\n\n if (runId.includes('..') || filename.includes('..') || runId.includes('/') || filename.includes('/')) {\n notFound(res, 'Invalid path')\n return\n }\n\n const videoPath = join(vidDir, runId, filename)\n const resolvedVideo = resolve(videoPath)\n const resolvedVidDir = resolve(vidDir)\n if (!getPathInsideDir(resolvedVideo, resolvedVidDir)) {\n notFound(res, 'Invalid path')\n return\n }\n\n const tryServe = (filePath: string) => stat(filePath).then(s => {\n if (!s.isFile()) {\n notFound(res, 'Video not found')\n return\n }\n\n const contentType = filePath.endsWith('.mp4') ? 'video/mp4' : 'video/webm'\n const range = req.headers.range\n if (range) {\n const parts = range.replace(/bytes=/, '').split('-')\n const start = parseInt(parts[0], 10)\n const end = parts[1] ? parseInt(parts[1], 10) : s.size - 1\n const chunkSize = end - start + 1\n\n res.writeHead(206, {\n 'Content-Range': `bytes ${start}-${end}/${s.size}`,\n 'Accept-Ranges': 'bytes',\n 'Content-Length': chunkSize,\n 'Content-Type': contentType,\n 'Access-Control-Allow-Origin': '*',\n })\n createReadStream(filePath, { start, end }).pipe(res)\n } else {\n res.writeHead(200, {\n 'Content-Type': contentType,\n 'Content-Length': s.size,\n 'Accept-Ranges': 'bytes',\n 'Access-Control-Allow-Origin': '*',\n })\n createReadStream(filePath).pipe(res)\n }\n })\n tryServe(videoPath).catch(() => notFound(res, 'Video not found'))\n return\n }\n\n // GET /api/execution/active — list currently running tests\n if (path === '/api/execution/active' && req.method === 'GET') {\n const active = testRunner ? testRunner.getActiveExecutions() : []\n json(res, { executions: active })\n return\n }\n\n // POST /api/queue/enqueue — external API to enqueue a test run\n if (path === '/api/queue/enqueue' && req.method === 'POST') {\n if (!jobQueue) {\n json(res, { error: 'Queue not available' }, 503)\n return\n }\n readJsonBody<{ name: string; file?: string; priority?: number; platform?: string; parallel?: boolean; metadata?: Record<string, unknown>; attributes?: unknown }>(req)\n .then(async (body) => {\n if (!body.name || typeof body.name !== 'string') {\n json(res, { error: 'name is required' }, 400)\n return\n }\n let normalizedFileTarget: { storagePath: string; executionPath: string } | null = null\n const isSuiteFile = isSuiteFilePath(body.file)\n if (body.file) {\n try {\n normalizedFileTarget = isSuiteFile\n ? await normalizeDashboardSuitePath(body.file, suiteFileManager)\n : await normalizeDashboardWorkspacePath(body.file, workspacePaths, 'test')\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : String(err) }, 400)\n return\n }\n }\n let attributes: RunAttributes\n try {\n attributes = buildRunRequestAttributes({\n trigger: 'api',\n runner: 'local',\n userAttributes: body.attributes,\n })\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : String(err) }, 400)\n return\n }\n const runId = jobQueue.enqueue({\n name: body.name,\n filePath: normalizedFileTarget?.storagePath,\n kind: isSuiteFile ? 'suite-parent' : 'test',\n attributes,\n priority: body.priority,\n platform: body.platform,\n parallel: body.parallel,\n metadata: {\n ...sanitizeQueuedRunMetadata(body.metadata),\n args: normalizedFileTarget ? [normalizedFileTarget.executionPath] : [],\n ...(isSuiteFile ? { isSuite: true } : {}),\n },\n })\n const pending = db.getPendingRuns()\n const position = pending.findIndex(r => r.id === runId) + 1\n json(res, { runId, status: 'queued', position }, 202)\n })\n .catch(() => {\n json(res, { error: 'Invalid request body' }, 400)\n })\n return\n }\n\n // GET /api/queue/status — queue status with pending/running jobs\n if (path === '/api/queue/status' && req.method === 'GET') {\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 20\n const completed = url.searchParams.get('completed') === 'true'\n const pending = db.getPendingRuns()\n const allRuns = db.getRuns({ limit: 100 })\n const running = allRuns.filter(r => r.status === 'running')\n const response: Record<string, unknown> = {\n pending: { count: pending.length, jobs: pending },\n running: { count: running.length, jobs: running },\n concurrency: jobQueue?.getConcurrency() ?? 0,\n activeSlots: jobQueue?.getActiveCount() ?? 0,\n }\n if (completed) {\n const recent = allRuns\n .filter(r => r.status !== 'pending' && r.status !== 'running')\n .slice(0, limit)\n response.recent = recent\n }\n json(res, response)\n return\n }\n\n // POST /api/runs/trigger — enqueue a live test execution\n if (path === '/api/runs/trigger' && req.method === 'POST') {\n if (!jobQueue) {\n json(res, { error: 'Queue not available' }, 503)\n return\n }\n readJsonBody<{ file?: string; patterns?: string[]; tags?: unknown; noCache?: boolean; noMemory?: boolean; local?: boolean; triggerSource?: unknown }>(req)\n .then(async (body) => {\n if (body.tags !== undefined) {\n json(res, { error: 'tags are not supported for dashboard-triggered runs' }, 400)\n return\n }\n const triggerSource = parseDashboardRunTriggerSource(body.triggerSource)\n if (!triggerSource.ok) {\n json(res, { error: triggerSource.error }, 400)\n return\n }\n const args: string[] = []\n const isSuiteFile = isSuiteFilePath(body.file)\n let normalizedFileTarget: { storagePath: string; executionPath: string } | null = null\n try {\n normalizedFileTarget = body.file\n ? isSuiteFile\n ? await normalizeDashboardSuitePath(body.file, suiteFileManager)\n : await normalizeDashboardWorkspacePath(body.file, workspacePaths, 'test')\n : null\n\n if (body.file) {\n args.push(normalizedFileTarget?.executionPath ?? body.file)\n }\n if (body.patterns) {\n if (!Array.isArray(body.patterns)) {\n throw new Error('patterns must be an array')\n }\n for (const pattern of body.patterns) {\n if (typeof pattern !== 'string') {\n throw new Error('patterns must be strings')\n }\n const matches = await resolveDashboardTestPattern(pattern, workspacePaths)\n args.push(...matches.map((match) => match.executionPath))\n }\n }\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : String(err) }, 400)\n return\n }\n const normalizedTestTarget = body.file && !isSuiteFile\n ? normalizedFileTarget\n : null\n if (body.noCache) {\n args.push('--no-cache')\n }\n if (body.noMemory) {\n args.push('--no-memory')\n }\n const isSuite = Boolean(isSuiteFile)\n\n let testName = body.file\n ? basename(normalizedFileTarget?.storagePath ?? body.file, '.yaml')\n : 'unknown'\n\n let fileParallel: boolean | undefined\n let platform: string | undefined\n\n if (isSuite && body.file && suiteFileManager) {\n // Parse suite YAML for name and platform\n try {\n const content = await suiteFileManager.read(normalizedFileTarget?.storagePath ?? body.file)\n fileParallel = readSuiteYamlParallel(content)\n const parsed = parseYaml(content)\n if (parsed?.name) testName = parsed.name\n platform = parsed?.config?.platform ?? undefined\n } catch { /* fall back to defaults */ }\n } else if (body.file && testFileManager) {\n // Parse test YAML for name, use.parallel, and platform metadata\n try {\n const readPath = normalizedTestTarget?.storagePath ?? body.file\n const content = await testFileManager.read(readPath)\n const metadata = extractTestFileMetadata(content)\n const targetPlatforms = await readTargetPlatformMap(configManager)\n if (metadata.name) testName = metadata.name\n if (metadata.parallel !== null) fileParallel = metadata.parallel\n platform = resolveEffectivePlatform(\n metadata.platform,\n metadata.targetName,\n targetPlatforms,\n platform,\n ) ?? undefined\n } catch { /* fall back to defaults */ }\n }\n\n const configParallel = await readConfigUseParallel(configManager)\n const effectiveParallel = fileParallel ?? configParallel ?? false\n const executionTimeout = await resolveDashboardExecutionTimeout({\n isSuite,\n file: normalizedFileTarget?.storagePath ?? body.file,\n normalizedTestPath: normalizedTestTarget?.storagePath,\n testFileManager,\n suiteFileManager,\n configManager,\n })\n\n const runId = jobQueue.enqueue({\n name: testName,\n filePath: normalizedFileTarget?.storagePath ?? body.file,\n kind: isSuite ? 'suite-parent' : 'test',\n attributes: buildRunRequestAttributes({\n trigger: triggerSource.trigger,\n runner: body.local === false ? 'browserstack' : 'local',\n }),\n platform,\n parallel: effectiveParallel,\n metadata: {\n args,\n isSuite: isSuite || undefined,\n ...toExecutionTimeoutMetadata(executionTimeout),\n },\n })\n json(res, { runId, status: 'queued' }, 202)\n })\n .catch(() => {\n json(res, { error: 'Invalid request body' }, 400)\n })\n return\n }\n\n // GET /api/execution/events — SSE stream for live execution events\n if (path === '/api/execution/events' && req.method === 'GET') {\n if (!testRunner) {\n json(res, { error: 'Execution not available' }, 503)\n return\n }\n\n const runId = url.searchParams.get('runId') ?? undefined\n const lastEventId = req.headers['last-event-id'] as string | undefined\n\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n res.write(':ok\\n\\n')\n\n // Replay buffered events for reconnection\n if (lastEventId && runId) {\n const lastId = parseInt(lastEventId, 10)\n const buffered = testRunner.getBufferedEvents(runId)\n for (const evt of buffered) {\n if (evt.id > lastId) {\n res.write(`id: ${evt.id}\\nevent: ${evt.type}\\ndata: ${JSON.stringify(evt)}\\n\\n`)\n }\n }\n } else if (runId) {\n // New connection — replay all buffered events\n const buffered = testRunner.getBufferedEvents(runId)\n for (const evt of buffered) {\n res.write(`id: ${evt.id}\\nevent: ${evt.type}\\ndata: ${JSON.stringify(evt)}\\n\\n`)\n }\n }\n\n const onEvent = (evtRunId: string, event: { id: number; type: string; [key: string]: unknown }) => {\n if (runId && evtRunId !== runId) return\n res.write(`id: ${event.id}\\nevent: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`)\n }\n\n testRunner.on('execution-event', onEvent)\n\n const heartbeat = setInterval(() => {\n res.write(':\\n\\n')\n }, 15_000)\n\n req.on('close', () => {\n clearInterval(heartbeat)\n testRunner.removeListener('execution-event', onEvent)\n })\n return\n }\n\n // POST /api/suites/validate — validate suite YAML content\n if (path === '/api/suites/validate' && req.method === 'POST') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n const result = await suiteFileManager.validate(body.content ?? '')\n json(res, result)\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/suites — list all suite files\n if (path === '/api/suites' && req.method === 'GET') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n suiteFileManager.list()\n .then(files => json(res, { files }))\n .catch(() => json(res, { error: 'Failed to list suite files' }, 500))\n return\n }\n\n // POST /api/suites — create a new suite file\n if (path === '/api/suites' && req.method === 'POST') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n readJsonBody<{ path: string; content: string }>(req)\n .then(async (body) => {\n if (!body.path || typeof body.path !== 'string' || !body.content || typeof body.content !== 'string') {\n json(res, { error: 'Both path and content are required' }, 400)\n return\n }\n const validation = await suiteFileManager.validate(body.content)\n if (!validation.valid) {\n json(res, {\n error: 'Invalid suite content',\n details: validation.errors,\n missingTests: validation.missingTests,\n }, 400)\n return\n }\n try {\n await suiteFileManager.write(body.path, body.content)\n json(res, { path: body.path, created: true }, 201)\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to create suite file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // DELETE /api/suites/:path — delete a suite file\n if (path.startsWith('/api/suites/') && req.method === 'DELETE') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n const decodedPath = decodeURIComponent(path.slice('/api/suites/'.length))\n suiteFileManager.delete(decodedPath)\n .then(() => json(res, { deleted: true }))\n .catch((err: any) => {\n if (err.code === 'ENOENT') {\n notFound(res, 'Suite file not found')\n return\n }\n json(res, { error: err.message }, 500)\n })\n return\n }\n\n // PUT /api/suites/:suite-id — update suite file by suite-id (hard break D-02/D-04)\n if (path.startsWith('/api/suites/') && req.method === 'PUT') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n const sId = decodeURIComponent(path.slice('/api/suites/'.length))\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n if (!body.content || typeof body.content !== 'string') {\n json(res, { error: 'Content is required' }, 400)\n return\n }\n const found = await suiteFileManager.findBySuiteId(sId)\n if (!found) {\n notFound(res, 'Suite not found')\n return\n }\n const validation = await suiteFileManager.validate(body.content)\n if (!validation.valid) {\n json(res, {\n error: 'Invalid suite content',\n details: validation.errors,\n missingTests: validation.missingTests,\n }, 400)\n return\n }\n try {\n await suiteFileManager.write(found.path, body.content)\n json(res, { path: found.path, updated: true })\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update suite file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/suites/:suite-id — read suite file by suite-id (hard break D-02/D-04/D-05)\n if (path.startsWith('/api/suites/') && req.method === 'GET') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n const sId = decodeURIComponent(path.slice('/api/suites/'.length))\n suiteFileManager.findBySuiteId(sId)\n .then(result => {\n if (!result) {\n notFound(res, 'Suite not found')\n return\n }\n json(res, { path: result.path, content: result.content, suiteId: sId })\n })\n .catch(() => notFound(res, 'Suite not found'))\n return\n }\n\n // POST /api/tests/validate — validate YAML content (must be before parameterized /api/tests/:path)\n if (path === '/api/tests/validate' && req.method === 'POST') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n readJsonBody<{ content: string; filePath?: string }>(req)\n .then(async (body) => {\n const isSuite = body.filePath?.endsWith('.suite.yaml') || body.filePath?.endsWith('.suite.yml')\n if (isSuite && suiteFileManager) {\n const result = await suiteFileManager.validate(body.content ?? '')\n json(res, result)\n } else {\n const result = await testFileManager.validate(body.content ?? '')\n json(res, result)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/tests — list all test files\n if (path === '/api/tests' && req.method === 'GET') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n testFileManager.list()\n .then(async files => {\n const targetPlatforms = await readTargetPlatformMap(configManager)\n const resolvedFiles = files.map((file) => ({\n ...file,\n platform: resolveEffectivePlatform(file.platform, file.targetName, targetPlatforms),\n }))\n const targets = Array.from(\n new Set(\n resolvedFiles\n .map((file) => file.targetName)\n .filter((value): value is string => typeof value === 'string' && value.length > 0),\n ),\n )\n json(res, { files: resolvedFiles, targets })\n })\n .catch(() => json(res, { error: 'Failed to list test files' }, 500))\n return\n }\n\n // POST /api/tests — create a new test file\n if (path === '/api/tests' && req.method === 'POST') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n readJsonBody<{ path: string; content: string }>(req)\n .then(async (body) => {\n if (!body.path || typeof body.path !== 'string' || !body.content || typeof body.content !== 'string') {\n json(res, { error: 'Both path and content are required' }, 400)\n return\n }\n try {\n await testFileManager.write(body.path, body.content)\n json(res, { path: body.path, created: true }, 201)\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to create test file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // DELETE /api/tests/:t_id — delete test file by test-id\n if (path.startsWith('/api/tests/') && req.method === 'DELETE') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n const tId = decodeURIComponent(path.slice('/api/tests/'.length))\n testFileManager.findByTestId(tId)\n .then(async (found) => {\n if (!found) {\n notFound(res, 'Test not found')\n return\n }\n await testFileManager.delete(found.path)\n json(res, { deleted: true, path: found.path })\n })\n .catch((err: unknown) => {\n const code = (err as NodeJS.ErrnoException)?.code\n if (code === 'ENOENT') {\n notFound(res, 'Test not found')\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete test file' }, 500)\n })\n return\n }\n\n // PUT /api/tests/:t_id — update test file by test-id\n if (path.startsWith('/api/tests/') && req.method === 'PUT') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n const tId = decodeURIComponent(path.slice('/api/tests/'.length))\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n if (!body.content || typeof body.content !== 'string') {\n json(res, { error: 'Content is required' }, 400)\n return\n }\n const found = await testFileManager.findByTestId(tId)\n if (!found) {\n notFound(res, 'Test not found')\n return\n }\n try {\n await testFileManager.write(found.path, body.content)\n json(res, { path: found.path, updated: true })\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update test file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/tests/:t_id — read test file by test-id\n if (path.startsWith('/api/tests/') && req.method === 'GET') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n const tId = decodeURIComponent(path.slice('/api/tests/'.length))\n testFileManager.findByTestId(tId)\n .then(result => {\n if (!result) {\n notFound(res, 'Test not found')\n return\n }\n json(res, { path: result.path, content: result.content, testId: tId })\n })\n .catch(() => notFound(res, 'Test not found'))\n return\n }\n\n // GET /api/analytics/tests\n if (path === '/api/analytics/tests' && req.method === 'GET') {\n const minRuns = url.searchParams.has('minRuns') ? parseInt(url.searchParams.get('minRuns')!, 10) : 3\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const tests = db.getFlakyTests({ minRuns, limit })\n const result = tests.map(t => {\n return { ...t, isFlaky: t.flakyScore >= 0.4 }\n })\n json(res, { tests: result })\n return\n }\n\n // GET /api/analytics/tests/:name\n if (path.startsWith('/api/analytics/tests/') && req.method === 'GET') {\n const name = decodeURIComponent(path.slice('/api/analytics/tests/'.length))\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const from = url.searchParams.get('from') ?? undefined\n void readAnalyticsScopePredicates(configManager)\n .then((scopeResult) => {\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n\n const runs = db.getRunsByTestName(name, { limit, offset })\n const total = db.getRunsByTestNameCount(name)\n const trends = db.getTestTrends(name, { from })\n const allRunsForFlakiness = db.getRunsByTestName(name, { limit: 100 })\n const flakyMetrics = calculateFlakyMetrics(allRunsForFlakiness)\n const flakyScore = flakyMetrics.score\n const configured = scopeResult.predicates.length > 0\n const scopedRuns = configured\n ? db.getRunsByTestName(name, { limit, offset, attributePredicates: scopeResult.predicates })\n : runs\n const scopedTotal = configured\n ? db.getRunsByTestNameCount(name, { attributePredicates: scopeResult.predicates })\n : total\n const scopedTrends = configured\n ? db.getTestTrends(name, { from, attributePredicates: scopeResult.predicates })\n : trends\n const scopedRunsForFlakiness = configured\n ? db.getRunsByTestName(name, { limit: 100, attributePredicates: scopeResult.predicates })\n : allRunsForFlakiness\n const scopedFlakyScore = calculateFlakyMetrics(scopedRunsForFlakiness).score\n\n json(res, {\n name,\n runs,\n total,\n trends,\n isFlaky: flakyScore >= 0.4 && flakyMetrics.statusCount >= 3,\n flakyScore,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount: scopedTotal,\n totalCount: total,\n },\n ...(configured ? {\n scopedRuns,\n scopedTrends,\n scopedFlakyScore,\n } : {}),\n })\n })\n .catch(() => json(res, { error: 'Failed to read analytics scope' }, 500))\n return\n }\n\n // GET /api/analytics/suites/:suiteId\n if (path.startsWith('/api/analytics/suites/') && req.method === 'GET') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n\n const suiteId = decodeURIComponent(path.slice('/api/analytics/suites/'.length))\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const from = url.searchParams.get('from') ?? undefined\n\n Promise.all([suiteFileManager.findBySuiteId(suiteId), readAnalyticsScopePredicates(configManager)])\n .then(([result, scopeResult]) => {\n if (!result) {\n notFound(res, 'Suite not found')\n return\n }\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n\n const runs = db.getRunsBySuiteId(suiteId, { limit, offset })\n const total = db.getRunsBySuiteIdCount(suiteId)\n const trends = db.getSuiteTrends(suiteId, { from })\n const allRunsForFlakiness = db.getRunsBySuiteId(suiteId, { limit: 100 })\n const flakyMetrics = calculateFlakyMetrics(allRunsForFlakiness)\n const flakyScore = flakyMetrics.score\n const configured = scopeResult.predicates.length > 0\n const scopedRuns = configured\n ? db.getRunsBySuiteId(suiteId, { limit, offset, attributePredicates: scopeResult.predicates })\n : runs\n const scopedTotal = configured\n ? db.getRunsBySuiteIdCount(suiteId, { attributePredicates: scopeResult.predicates })\n : total\n const scopedTrends = configured\n ? db.getSuiteTrends(suiteId, { from, attributePredicates: scopeResult.predicates })\n : trends\n const scopedRunsForFlakiness = configured\n ? db.getRunsBySuiteId(suiteId, { limit: 100, attributePredicates: scopeResult.predicates })\n : allRunsForFlakiness\n const scopedFlakyScore = calculateFlakyMetrics(scopedRunsForFlakiness).score\n\n json(res, {\n suiteId,\n runs,\n total,\n trends,\n isFlaky: flakyScore >= 0.4 && flakyMetrics.statusCount >= 3,\n flakyScore,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount: scopedTotal,\n totalCount: total,\n },\n ...(configured ? {\n scopedRuns,\n scopedTrends,\n scopedFlakyScore,\n } : {}),\n })\n })\n .catch(() => notFound(res, 'Suite not found'))\n return\n }\n\n // GET /api/analytics/breakdowns\n if (path === '/api/analytics/breakdowns' && req.method === 'GET') {\n const dimension = url.searchParams.get('dimension')\n if (dimension !== 'test' && dimension !== 'suite' && dimension !== 'platform') {\n json(res, { error: 'dimension must be one of: test, suite, platform' }, 400)\n return\n }\n\n const limitResult = parseBoundedIntegerQueryParam(url.searchParams.get('limit'), 'limit', 1, 100, 25)\n if (!limitResult.ok) {\n json(res, { error: limitResult.error }, 400)\n return\n }\n\n const fromResult = parseIsoDateQueryParam(url.searchParams.get('from'), 'from')\n if (!fromResult.ok) {\n json(res, { error: fromResult.error }, 400)\n return\n }\n\n const toResult = parseIsoDateQueryParam(url.searchParams.get('to'), 'to')\n if (!toResult.ok) {\n json(res, { error: toResult.error }, 400)\n return\n }\n\n const scope = url.searchParams.get('scope') ?? undefined\n if (scope !== undefined && scope !== 'passRate') {\n json(res, { error: 'scope must be passRate when provided' }, 400)\n return\n }\n\n void readAnalyticsScopePredicates(configManager)\n .then(async (scopeResult) => {\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n\n const configured = scopeResult.predicates.length > 0\n const attributePredicates = scope === 'passRate' && configured ? scopeResult.predicates : undefined\n const rows = db.getInsightsBreakdown(dimension as InsightsBreakdownDimension, {\n from: fromResult.value,\n to: toResult.value,\n limit: limitResult.value,\n attributePredicates,\n })\n const scopedCount = configured\n ? db.getInsightsBreakdown(dimension as InsightsBreakdownDimension, {\n from: fromResult.value,\n to: toResult.value,\n limit: 100,\n attributePredicates: scopeResult.predicates,\n }).reduce((sum, row) => sum + row.runs, 0)\n : 0\n const totalCount = db.getInsightsBreakdown(dimension as InsightsBreakdownDimension, {\n from: fromResult.value,\n to: toResult.value,\n limit: 100,\n }).reduce((sum, row) => sum + row.runs, 0)\n const payload = {\n dimension,\n rows,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount,\n totalCount,\n },\n }\n\n if (dimension !== 'suite' || !suiteFileManager) {\n json(res, payload)\n return\n }\n\n const files = await suiteFileManager.list()\n const suiteNames = new Map(\n files\n .filter((file) => typeof file.suiteId === 'string' && file.suiteId.length > 0)\n .map((file) => [file.suiteId as string, file.name]),\n )\n\n json(res, {\n ...payload,\n rows: rows.map((row) => ({\n ...row,\n label: row.suiteId ? (suiteNames.get(row.suiteId) ?? row.label) : row.label,\n })),\n })\n })\n .catch(() => {\n json(res, { error: 'Unable to read analytics breakdown scope' }, 500)\n })\n return\n }\n\n // GET /api/app-metadata — return narrow non-sensitive app metadata\n if (path === '/api/app-metadata' && req.method === 'GET') {\n const version = getAgentQaVersion().trim() || '0.0.0'\n json(res, { version })\n return\n }\n\n // GET /api/config/targets — return registered target names\n if (path === '/api/config/targets' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const config = await configManager.read()\n const configObj = config as Record<string, unknown>\n const registry = configObj.registry as Record<string, unknown> | undefined\n const targets = registry?.targets as Record<string, unknown> | undefined\n const names = targets ? Object.keys(targets) : []\n json(res, { targets: names })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read targets' }, 500)\n }\n })()\n return\n }\n\n // GET /api/config — return masked config with active provider info\n if (path === '/api/config' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const config = await configManager.readMasked()\n const configObj = config as Record<string, unknown>\n const registry = configObj.registry as Record<string, unknown> | undefined\n const llms = (registry?.llms ?? configObj.llms) as Array<Record<string, unknown>> | undefined\n const use = configObj.use as Record<string, unknown> | undefined\n const activeLlm = (use?.llm ?? configObj.defaultLLM) as string | undefined\n const defaultCfg = llms?.find((c) => c.name === activeLlm)\n const provider = (defaultCfg?.provider as string) ?? null\n json(res, { config, provider })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read config' }, 500)\n }\n })()\n return\n }\n\n // PUT /api/config/llms — update registry.llms array + use.llm\n if (path === '/api/config/llms' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ llms: unknown[]; defaultLLM?: string; activeLlm?: string }>(req)\n .then(async (body) => {\n try {\n if (!Array.isArray(body.llms) || body.llms.length === 0) {\n json(res, { error: 'llms array is required and must not be empty' }, 400)\n return\n }\n const selectedLlm = body.activeLlm ?? body.defaultLLM\n const errors: string[] = []\n const names: string[] = []\n const sanitizedArray: Array<ReturnType<typeof NamedLLMConfigSchema.parse>> = []\n for (const item of body.llms) {\n const result = NamedLLMConfigSchema.safeParse(item)\n if (!result.success) {\n for (const issue of result.error.issues) {\n errors.push(`${issue.path.join('.')}: ${issue.message}`)\n }\n } else {\n names.push(result.data.name)\n sanitizedArray.push(result.data)\n }\n }\n const dupes = names.filter((n, i) => names.indexOf(n) !== i)\n if (dupes.length > 0) {\n errors.push(`Duplicate config names: ${[...new Set(dupes)].join(', ')}`)\n }\n if (!selectedLlm || !names.includes(selectedLlm)) {\n errors.push(`use.llm \"${selectedLlm}\" does not match any name in registry.llms`)\n }\n if (errors.length > 0) {\n json(res, { error: 'Validation failed', details: errors }, 400)\n return\n }\n await configManager.replaceSectionRaw('registry.llms', sanitizedArray)\n await configManager.replaceSectionRaw('use.llm', selectedLlm)\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update LLM config' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // PUT /api/config/default-llm — switch active LLM (use.llm)\n if (path === '/api/config/default-llm' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ defaultLLM?: string; llm?: string }>(req)\n .then(async (body) => {\n try {\n const llmName = body.llm ?? body.defaultLLM\n if (!llmName || typeof llmName !== 'string') {\n json(res, { error: 'use.llm string is required' }, 400)\n return\n }\n const config = await configManager.readMasked()\n const configObj = config as Record<string, unknown>\n const registry = configObj.registry as Record<string, unknown> | undefined\n const llms = (registry?.llms ?? configObj.llms) as Array<Record<string, unknown>> | undefined\n const names = (llms ?? []).map((c) => c.name as string)\n if (!names.includes(llmName)) {\n json(res, { error: `use.llm \"${llmName}\" does not match any name in registry.llms` }, 400)\n return\n }\n await configManager.replaceSectionRaw('use.llm', llmName)\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update use.llm' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // POST /api/config/farm/test-connection — test farm provider credentials\n if (path === '/api/config/farm/test-connection' && req.method === 'POST') {\n readJsonBody<{ provider: string; username: string; accessKey: string }>(req)\n .then(async (body) => {\n if (body.provider !== 'browserstack') {\n json(res, { error: 'Only BrowserStack is currently supported' }, 400)\n return\n }\n try {\n const auth = Buffer.from(`${body.username}:${body.accessKey}`).toString('base64')\n const response = await fetch('https://api-cloud.browserstack.com/app-automate/devices.json', {\n headers: { Authorization: `Basic ${auth}` },\n })\n if (response.ok) {\n json(res, { success: true })\n } else if (response.status === 401) {\n json(res, { success: false, error: 'Invalid credentials' })\n } else {\n json(res, { success: false, error: `BrowserStack API returned ${response.status}` })\n }\n } catch (err) {\n json(res, { success: false, error: err instanceof Error ? err.message : 'Connection failed' })\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // PUT /api/config/settings — update config sections\n if (path === '/api/config/settings' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<Record<string, unknown>>(req)\n .then(async (body) => {\n try {\n const sectionValidators: Record<string, { safeParse: (v: unknown) => ConfigSectionValidationResult }> = {\n 'use.timeout': TimeoutConfigSchema,\n 'use.healing': HealingConfigSchema,\n 'use.planner': PlannerConfigSchema,\n 'use.logCapture': LogCaptureConfigSchema,\n 'use.browser': BrowserConfigSchema,\n 'use.browser.headless': BrowserConfigSchema.shape.headless,\n 'services.memory': ServicesSchema.shape.memory,\n 'services.cache': CacheConfigSchema,\n 'services.logging': LoggingConfigSchema,\n 'services.recording': RecordingConfigSchema,\n 'services.accessibility': AccessibilityConfigSchema,\n 'services.dashboard': DashboardConfigSchema,\n 'services.mcp': McpConfigSchema,\n 'registry.targets': RegistrySchema.shape.targets,\n 'registry.devices': RegistrySchema.shape.devices,\n 'registry.providers': RegistrySchema.shape.providers,\n 'analytics.passRateScope': { safeParse: validateAnalyticsPassRateScope },\n 'workspace.testMatch': WorkspaceSchema.shape.testMatch,\n 'workspace.suiteMatch': WorkspaceSchema.shape.suiteMatch,\n 'workspace.hooksFile': WorkspaceSchema.shape.hooksFile,\n 'workspace.agentRules': WorkspaceSchema.shape.agentRules,\n 'workspace.envFile': WorkspaceSchema.shape.envFile,\n 'workspace.secretsFile': WorkspaceSchema.shape.secretsFile,\n 'use.mobile': UseSchema.shape.mobile,\n 'use.mobile.appState': MobileAppStateSchema,\n 'use.parallel': UseSchema.shape.parallel,\n }\n const objectSections = [\n 'use.timeout',\n 'use.healing',\n 'use.planner',\n 'use.logCapture',\n 'use.browser',\n 'use.mobile',\n 'services.memory',\n 'services.cache',\n 'services.logging',\n 'services.recording',\n 'services.accessibility',\n 'services.dashboard',\n 'services.mcp',\n 'registry.targets',\n 'registry.devices',\n 'registry.providers',\n 'analytics.passRateScope',\n ] as const\n const arraySections = ['workspace.testMatch', 'workspace.testPathIgnore', 'workspace.suiteMatch', 'registry.llms'] as const\n const scalarSections = [\n 'workspace.agentRules',\n 'workspace.hooksFile',\n 'workspace.envFile',\n 'workspace.secretsFile',\n 'use.llm',\n 'use.mobile.appState',\n 'use.browser.headless',\n 'use.parallel',\n ] as const\n\n const currentConfig = await configManager.read()\n const currentUse = isRecord(currentConfig.use) ? currentConfig.use : {}\n const currentBrowser = isRecord(currentUse.browser) ? currentUse.browser : {}\n const currentHasRootHeadless = typeof currentUse.headless === 'boolean'\n const currentHasBrowserHeadless = typeof currentBrowser.headless === 'boolean'\n const requestHasRootHeadless = Object.prototype.hasOwnProperty.call(body, 'use.headless')\n const requestHasBrowserHeadlessScalar = Object.prototype.hasOwnProperty.call(body, 'use.browser.headless')\n const requestBrowserBlock = body['use.browser']\n const requestHasBrowserHeadlessObject = isRecord(requestBrowserBlock) && typeof requestBrowserBlock.headless === 'boolean'\n if (\n currentHasRootHeadless\n && !currentHasBrowserHeadless\n && !requestHasBrowserHeadlessScalar\n && !requestHasBrowserHeadlessObject\n ) {\n body['use.browser.headless'] = currentUse.headless\n }\n\n const allowedSettingsPaths = new Set<string>([\n ...Object.keys(sectionValidators),\n ...objectSections,\n ...arraySections,\n ...scalarSections,\n 'use.headless',\n ])\n const unsupportedKeys = Object.keys(body).filter((key) => !allowedSettingsPaths.has(key))\n if (unsupportedKeys.length > 0) {\n json(res, { error: 'Unsupported setting path', details: unsupportedKeys }, 400)\n return\n }\n\n const errors: string[] = []\n for (const [section, validator] of Object.entries(sectionValidators)) {\n const value = body[section]\n if (value !== undefined) {\n const result = validator.safeParse(value)\n if (!result.success) {\n for (const issue of result.error!.issues) {\n const path = issue.path.length ? `${section}.${issue.path.map(String).join('.')}` : section\n errors.push(`${path}: ${issue.message}`)\n }\n }\n }\n }\n\n if (Array.isArray(body['registry.llms'])) {\n for (const [idx, item] of (body['registry.llms'] as unknown[]).entries()) {\n const result = NamedLLMConfigSchema.safeParse(item)\n if (!result.success) {\n for (const issue of result.error!.issues) {\n const p = issue.path.length ? `registry.llms[${idx}].${issue.path.join('.')}` : `registry.llms[${idx}]`\n errors.push(`${p}: ${issue.message}`)\n }\n }\n }\n }\n\n if (errors.length > 0) {\n json(res, { error: 'Validation failed', details: errors }, 400)\n return\n }\n\n for (const section of objectSections) {\n if (body[section] && typeof body[section] === 'object') {\n await configManager.replaceSection(section, body[section] as Record<string, unknown>)\n }\n }\n for (const section of arraySections) {\n if (body[section] !== undefined) {\n await configManager.replaceSectionRaw(section, body[section])\n }\n }\n for (const section of scalarSections) {\n if (body[section] !== undefined) {\n await configManager.replaceSectionRaw(section, body[section])\n }\n }\n if (currentHasRootHeadless || requestHasRootHeadless) {\n await configManager.deleteSectionRaw('use.headless')\n }\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update settings' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // DELETE /api/auth/:configName — remove stored credential\n if (path.startsWith('/api/auth/') && req.method === 'DELETE') {\n const segments = path.split('/')\n if (segments.length === 4 && segments[2] === 'auth') {\n const providerName = decodeURIComponent(segments[3])\n if (providerName === 'status' || providerName === 'credential' || providerName === 'oauth') {\n // Fall through to other handlers\n } else {\n ;(async () => {\n try {\n await removeAuth(providerName)\n json(res, { deleted: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete credential' }, 500)\n }\n })()\n return\n }\n }\n }\n\n // GET /api/auth/status — return credential info from auth store\n if (path === '/api/auth/status' && req.method === 'GET') {\n ;(async () => {\n try {\n const credentials: Array<{\n type: string\n provider: string\n configName: string\n expires: number | null\n source: string\n }> = []\n const store = await readAuth() as Record<string, DashboardAuthCredential>\n for (const [key, cred] of Object.entries(store)) {\n if (cred) {\n let provider = cred.provider ?? key\n if (cred.type === 'oauth') {\n provider = toProductProviderLabel(provider)\n } else if (cred.type === 'bearer') {\n provider = cred.provider\n }\n credentials.push({\n type: cred.type,\n provider,\n configName: key,\n expires: cred.type === 'oauth' ? cred.tokens.expires : null,\n source: 'auth-store',\n })\n }\n }\n json(res, { credentials })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read auth status' }, 500)\n }\n })()\n return\n }\n\n // GET /api/llm/providers — built-in and plugin-provided LLM provider metadata\n if (path === '/api/llm/providers' && req.method === 'GET') {\n json(res, {\n providers: [\n ...builtinLLMProviderMetadata(),\n ...listLLMAuthProviderPlugins().map(serializeAuthProviderPlugin),\n ],\n })\n return\n }\n\n if (path.startsWith('/api/auth/plugin/')) {\n pruneExpiredPluginOAuthSessions(pluginOAuthSessions)\n const segments = path.split('/')\n const provider = segments.length >= 6 ? decodeURIComponent(segments[4] ?? '') : ''\n const action = segments.length >= 6 ? segments[5] : ''\n const plugin = provider ? getLLMAuthProviderPlugin(provider) : undefined\n\n if (!plugin) {\n json(res, { error: `Auth plugin provider \"${provider}\" is not registered` }, 404)\n return\n }\n\n if (action === 'start' && req.method === 'POST') {\n readJsonBody<{ configName?: string; callbackUrl?: string }>(req)\n .then(async (body) => {\n if (!plugin.startAuth) {\n json(res, { error: `Provider \"${provider}\" does not support dashboard auth start` }, 400)\n return\n }\n\n try {\n const target = await requirePluginAuthConfig(configManager, body.configName, plugin)\n if (!target.ok) {\n json(res, { error: target.error }, 400)\n return\n }\n const started = await plugin.startAuth({\n configName: target.configName,\n callbackUrl: typeof body.callbackUrl === 'string' ? body.callbackUrl : undefined,\n })\n const sessionId = randomUUID()\n const session: PluginOAuthSession = {\n providerId: plugin.providerId,\n credentialProviderId: plugin.credentialProviderId,\n configName: target.configName,\n sessionState: started.sessionState,\n cleanup: started.cleanup,\n status: 'pending',\n expiresAt: Date.now() + PLUGIN_OAUTH_SESSION_TTL_MS,\n }\n pluginOAuthSessions.set(sessionId, session)\n\n if (started.waitForTokens) {\n started.waitForTokens\n .then(async (tokens: OAuthTokens) => {\n await writeDashboardAuth(target.configName, {\n type: 'oauth',\n provider: plugin.credentialProviderId,\n tokens,\n })\n session.status = 'completed'\n })\n .catch((err: unknown) => {\n session.status = 'error'\n session.error = err instanceof Error ? err.message : 'Authentication failed'\n })\n .finally(() => cleanupPluginOAuthSession(session))\n }\n\n json(res, {\n authorizeUrl: started.authorizeUrl,\n sessionId,\n mode: plugin.dashboardAuth.mode,\n })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to start auth plugin flow' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n if (action === 'result' && req.method === 'GET') {\n const sessionId = url.searchParams.get('session') ?? ''\n const session = pluginOAuthSessions.get(sessionId)\n if (!session || session.providerId !== provider) {\n json(res, { error: 'Auth session not found' }, 404)\n return\n }\n if (session.status === 'completed') {\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { status: 'completed', saved: true })\n return\n }\n if (session.status === 'error') {\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { status: 'error', error: session.error ?? 'Authentication failed' })\n return\n }\n json(res, { status: 'pending' })\n return\n }\n\n if (action === 'exchange' && req.method === 'POST') {\n readJsonBody<{ sessionId?: string; code?: string }>(req)\n .then(async (body) => {\n if (!plugin.exchangeCode) {\n json(res, { error: `Provider \"${provider}\" does not support code exchange` }, 400)\n return\n }\n const sessionId = typeof body.sessionId === 'string' ? body.sessionId.trim() : ''\n const code = typeof body.code === 'string' ? body.code.trim() : ''\n if (!sessionId || !code) {\n json(res, { error: 'sessionId and code are required' }, 400)\n return\n }\n const session = pluginOAuthSessions.get(sessionId)\n if (!session || session.providerId !== provider) {\n json(res, { error: 'Auth session not found' }, 404)\n return\n }\n if (session.status !== 'pending') {\n json(res, { error: 'Auth session is no longer pending' }, 409)\n return\n }\n\n try {\n const tokens = await plugin.exchangeCode({\n code,\n sessionState: session.sessionState,\n })\n await writeDashboardAuth(session.configName, {\n type: 'oauth',\n provider: session.credentialProviderId,\n tokens,\n })\n session.status = 'completed'\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { status: 'completed', saved: true })\n } catch (err: unknown) {\n session.status = 'error'\n session.error = err instanceof Error ? err.message : 'Token exchange failed'\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { error: session.error }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n json(res, { error: 'Auth plugin route not found' }, 404)\n return\n }\n\n // POST /api/auth/credential — store typed credentials from dashboard\n if (path === '/api/auth/credential' && req.method === 'POST') {\n readJsonBody<{\n configName?: string\n provider?: string\n type?: string\n secret?: string\n }>(req)\n .then(async (body) => {\n const provider = typeof body.provider === 'string' ? body.provider.trim() : ''\n const credentialType = typeof body.type === 'string' ? body.type.trim() : ''\n const secret = typeof body.secret === 'string' ? body.secret.trim() : ''\n\n if (typeof body.configName !== 'string' || body.configName.trim() === '') {\n json(res, { error: 'configName is required' }, 400)\n return\n }\n if (!provider || !isKnownLLMProvider(provider)) {\n json(res, { error: 'valid provider is required' }, 400)\n return\n }\n if (credentialType !== 'api-key' && credentialType !== 'bearer-token') {\n json(res, { error: 'type must be api-key or bearer-token' }, 400)\n return\n }\n if (!secret) {\n json(res, { error: 'secret is required' }, 400)\n return\n }\n\n if (getLLMAuthProviderPlugin(provider)) {\n json(res, { error: 'Subscription providers use OAuth login' }, 400)\n return\n }\n\n if (credentialType === 'bearer-token' && provider !== 'anthropic-compatible') {\n json(res, { error: 'bearer-token credentials are only supported for anthropic-compatible configs' }, 400)\n return\n }\n\n if (credentialType === 'api-key' && !API_KEY_CREDENTIAL_PROVIDERS.has(provider)) {\n json(res, { error: 'api-key credentials are not supported for this provider' }, 400)\n return\n }\n\n try {\n const target = await requireCredentialConfig(configManager, body.configName, provider)\n if (!target.ok) {\n json(res, { error: target.error }, 400)\n return\n }\n\n if (credentialType === 'bearer-token') {\n await writeDashboardAuth(target.configName, { type: 'bearer', provider, token: secret })\n } else {\n await writeDashboardAuth(target.configName, { type: 'api', provider, key: secret })\n }\n json(res, { saved: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to save credential' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // POST /api/llm/test — test LLM connection\n if (path === '/api/llm/test' && req.method === 'POST') {\n readJsonBody<{\n configName?: string\n provider?: string\n model?: string\n baseURL?: string\n providerHeaders?: Record<string, string>\n }>(req)\n .then(async (body) => {\n const rawBody = body as Record<string, unknown>\n if ('apiKey' in rawBody) {\n json(res, {\n success: false,\n error: 'invalid_request',\n message: 'apiKey is not accepted in LLM test requests. Save credentials for the named config instead.',\n }, 400)\n return\n }\n const providerName = typeof body.provider === 'string' ? body.provider.trim() : ''\n const modelName = typeof body.model === 'string' ? body.model.trim() : ''\n if (!providerName || !modelName) {\n json(res, { success: false, error: 'invalid_request', message: 'provider and model are required' }, 400)\n return\n }\n const configName = typeof body.configName === 'string' ? body.configName.trim() : ''\n\n const llmCandidate: Record<string, unknown> = {\n provider: providerName,\n model: modelName,\n }\n if (typeof body.baseURL === 'string') {\n llmCandidate.baseURL = body.baseURL\n }\n if (body.providerHeaders !== undefined) {\n llmCandidate.providerHeaders = body.providerHeaders\n }\n\n const parsedConfig = ModelConfigSchema.safeParse(llmCandidate)\n if (!parsedConfig.success) {\n json(res, {\n success: false,\n error: 'invalid_request',\n message: parsedConfig.error.issues\n .map((issue: { path: PropertyKey[]; message: string }) => `${issue.path.map(String).join('.') || 'config'}: ${issue.message}`)\n .join('; '),\n }, 400)\n return\n }\n\n const start = Date.now()\n const llmConfig = parsedConfig.data\n const coreAuth = await import('@vostride/agent-qa-core') as typeof import('@vostride/agent-qa-core') & {\n resolveLLMAuth: (name: string, config: typeof llmConfig) => Promise<\n | { kind: 'api-key'; apiKey: string }\n | { kind: 'bearer-token'; token: string }\n | { kind: 'auth-fetch'; fetch: typeof globalThis.fetch; modelAdapter: 'openai-responses' | 'anthropic-messages' }\n | { kind: 'unauthenticated'; message: string }\n | { kind: 'missing'; message: string }\n >\n }\n const resolvedAuth = await coreAuth.resolveLLMAuth(configName, llmConfig)\n if (resolvedAuth.kind === 'missing') {\n json(res, {\n success: false,\n error: 'missing_credential',\n message: resolvedAuth.message,\n })\n return\n }\n\n const modelConfig: Record<string, unknown> = { ...llmConfig }\n let unauthenticated = false\n let authMessage: string | undefined\n\n if (resolvedAuth.kind === 'api-key') {\n modelConfig.apiKey = resolvedAuth.apiKey\n } else if (resolvedAuth.kind === 'bearer-token') {\n modelConfig.authToken = resolvedAuth.token\n } else if (resolvedAuth.kind === 'auth-fetch') {\n modelConfig.fetch = resolvedAuth.fetch\n modelConfig.modelAdapter = resolvedAuth.modelAdapter\n } else if (resolvedAuth.kind === 'unauthenticated') {\n unauthenticated = true\n authMessage = resolvedAuth.message\n }\n\n try {\n const { createModel } = await import('@vostride/agent-qa-core')\n const model = await createModel(modelConfig as unknown as Parameters<typeof createModel>[0])\n\n const testProviderOpts = getProviderOptions(modelConfig as unknown as Parameters<typeof getProviderOptions>[0])\n const connectionTimeoutMs = llmConnectionTestTimeoutMs(llmConfig)\n\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), connectionTimeoutMs)\n try {\n const { generateText } = await import('ai')\n await generateText({\n model,\n prompt: 'Say \"ok\"',\n abortSignal: controller.signal,\n providerOptions: testProviderOpts,\n })\n } finally {\n clearTimeout(timeout)\n }\n\n json(res, {\n success: true,\n model: modelName,\n provider: providerName,\n timeoutMs: connectionTimeoutMs,\n responseTime: Date.now() - start,\n ...(unauthenticated ? { unauthenticated: true, message: authMessage ?? LLM_TEST_UNAUTHENTICATED_MESSAGE } : {}),\n })\n } catch (err: unknown) {\n const connectionTimeoutMs = llmConnectionTestTimeoutMs(llmConfig)\n const { message: providerMessage, statusCode } = extractProviderErrorMessage(err)\n const errorCategory = classifyProviderError(providerMessage, statusCode)\n const message = publicLLMTestMessage(errorCategory, providerMessage)\n\n json(res, {\n success: false,\n error: errorCategory,\n message,\n timeoutMs: connectionTimeoutMs,\n ...(statusCode ? { statusCode } : {}),\n ...(message !== providerMessage ? { details: providerMessage } : {}),\n ...(unauthenticated ? { unauthenticated: true, authMessage: authMessage ?? LLM_TEST_UNAUTHENTICATED_MESSAGE } : {}),\n })\n }\n })\n .catch(() => json(res, { success: false, error: 'invalid_request', message: 'Invalid request body' }, 400))\n return\n }\n\n // POST /api/cache/purge — purge cached action plans for a test or all tests\n if (path === '/api/cache/purge' && req.method === 'POST') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 503)\n return\n }\n readJsonBody<{ file?: string; all?: boolean }>(req)\n .then(async (body) => {\n if (!body.file && !body.all) {\n json(res, { error: 'Either file or all is required' }, 400)\n return\n }\n try {\n const cfg = await configManager.read()\n const targetPlatforms = getTargetPlatformMap(cfg)\n const cacheDir = (cfg as {\n services?: { cache?: { dir?: string } }\n cache?: { dir?: string }\n }).services?.cache?.dir\n ?? (cfg as { cache?: { dir?: string } }).cache?.dir\n if (!cacheDir) {\n json(res, { error: 'Cache directory not configured' }, 400)\n return\n }\n if (body.file) {\n // Read raw config file content for cache key scoping\n let configContent = ''\n if (deps.configPath) {\n try { configContent = await readFile(deps.configPath, 'utf-8') } catch { /* best-effort */ }\n }\n const resolvedPath = (await normalizeDashboardWorkspacePath(body.file, workspacePaths, 'test')).executionPath\n const content = await readFile(resolvedPath, 'utf-8')\n const doc = parseYaml(content)\n const metadata = extractTestFileMetadata(content)\n const platform = resolveEffectivePlatform(\n metadata.platform,\n metadata.targetName,\n targetPlatforms,\n 'web',\n ) ?? 'web'\n const steps: string[] = (doc.steps ?? []).map((s: unknown) =>\n typeof s === 'string' ? s : (s as Record<string, string>).step,\n )\n const configDir = deps.configPath ? dirname(resolve(deps.configPath)) : process.cwd()\n const resolvedCacheDir = resolve(configDir, cacheDir)\n let purged = 0\n for (const step of steps) {\n const stepHash = hashStepInstruction(step, platform, configContent, content)\n const dirPath = join(resolvedCacheDir, stepHash)\n try {\n await stat(dirPath)\n await rm(dirPath, { recursive: true, force: true })\n purged++\n } catch {\n // directory doesn't exist — skip\n }\n }\n json(res, { purged })\n } else {\n const configDir = deps.configPath ? dirname(resolve(deps.configPath)) : process.cwd()\n const resolvedDir = resolve(configDir, cacheDir)\n let entries: string[]\n try {\n entries = await readdir(resolvedDir)\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { purged: 0 })\n return\n }\n throw err\n }\n for (const entry of entries) {\n await rm(join(resolvedDir, entry), { recursive: true, force: true })\n }\n json(res, { purged: entries.length })\n }\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Cache purge failed' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // Agent Rules API\n if (path === '/api/agent-rules' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content: string\n try {\n content = await readFile(workspacePaths.agentRules.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { content: null, filePath: workspacePaths.agentRules.workspaceRelativePath, error: 'workspace.agentRules file_not_found' }, 500)\n return\n }\n throw err\n }\n json(res, { content, filePath: workspacePaths.agentRules.workspaceRelativePath })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read agent rules' }, 500)\n }\n })()\n return\n }\n\n // Hooks API\n if (path === '/api/hooks' && req.method === 'GET') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n json(res, await hookRegistryManager.readCatalog())\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read hooks' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/hooks' && req.method === 'POST') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody(req)\n .then(async (body) => {\n try {\n const result = await hookRegistryManager.createHook(body as import('../hooks/hook-registry-types.js').HookMutationRequest)\n json(res, result, 201)\n } catch (err: unknown) {\n if (isHookRegistryMutationError(err) && err.code === 'validation_failed') {\n json(res, { error: 'validation_failed', fieldErrors: err.fieldErrors }, 400)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to create hook' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n const hookRunMatch = path.match(/^\\/api\\/hooks\\/([^/]+)\\/run$/)\n if (hookRunMatch && req.method === 'POST') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<import('../hooks/hook-registry-types.js').HookRunRequest>(req)\n .then(async (body) => {\n try {\n const validation = validateHookRunRequest(body)\n if (validation.fieldErrors.length > 0) {\n json(res, { error: 'validation_failed', fieldErrors: validation.fieldErrors }, 400)\n return\n }\n\n const hookId = decodeURIComponent(hookRunMatch[1])\n const prepareResult = await hookRegistryManager.prepareForExecution()\n if (prepareResult.hookRegistryError) {\n json(res, { error: 'hook_registry_error', message: prepareResult.hookRegistryError }, 409)\n return\n }\n\n const resolvedHook = prepareResult.resolvedHooks.get(hookId)\n if (!resolvedHook) {\n const detail = await hookRegistryManager.readHook(hookId)\n if (!detail) {\n notFound(res, 'Hook not found')\n return\n }\n\n const fieldErrors = prepareResult.authoringIssuesById.get(hookId) ?? detail.fieldErrors\n if (fieldErrors.length > 0) {\n json(res, { error: 'hook_not_runnable', fieldErrors }, 409)\n return\n }\n\n json(res, { error: 'hook_not_runnable', message: 'Hook is not executable' }, 409)\n return\n }\n\n const workspaceEnv = await readWorkspaceEnvVars(workspacePaths)\n const result = await runHookInSandbox(resolvedHook, {\n envVars: {\n ...workspaceEnv,\n ...validation.overrides,\n },\n })\n const networkLogs = summarizeHookNetworkLogs(\n (result as { networkLogs?: Array<{ url: string; method: string; status: number; startTime: number; endTime: number }> }).networkLogs,\n )\n\n json(res, {\n success: result.success,\n status: result.success ? 'passed' : 'failed',\n executedAt: new Date().toISOString(),\n duration: result.duration,\n output: result.output,\n stdout: result.stdout,\n stderr: result.stderr,\n error: result.error ?? null,\n variables: result.variables,\n sandbox: {\n runtime: resolvedHook.runtime,\n image: RUNTIME_IMAGE_MAP[resolvedHook.runtime],\n networkMode: resolvedHook.network ? 'enabled' : 'disabled',\n dockerVersion: null,\n networkLogsAvailable: networkLogs.length > 0,\n networkLogs,\n },\n } satisfies import('../hooks/hook-registry-types.js').HookRunResponse)\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to run hook' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n const hookDetailMatch = path.match(/^\\/api\\/hooks\\/([^/]+)$/)\n if (hookDetailMatch && req.method === 'GET') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const detail = await hookRegistryManager.readHook(decodeURIComponent(hookDetailMatch[1]))\n if (!detail) {\n notFound(res, 'Hook not found')\n return\n }\n json(res, detail)\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read hook' }, 500)\n }\n })()\n return\n }\n\n if (hookDetailMatch && req.method === 'PUT') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody(req)\n .then(async (body) => {\n try {\n const result = await hookRegistryManager.updateHook(\n decodeURIComponent(hookDetailMatch[1]),\n body as import('../hooks/hook-registry-types.js').HookMutationRequest,\n )\n json(res, result)\n } catch (err: unknown) {\n if (isHookRegistryMutationError(err) && err.code === 'hook_not_found') {\n notFound(res, 'Hook not found')\n return\n }\n if (isHookRegistryMutationError(err) && err.code === 'validation_failed') {\n json(res, { error: 'validation_failed', fieldErrors: err.fieldErrors }, 400)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to update hook' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n if (hookDetailMatch && req.method === 'DELETE') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const result = await hookRegistryManager.deleteHook(\n decodeURIComponent(hookDetailMatch[1]),\n { force: url.searchParams.get('force') === 'true' },\n )\n if (!result.deleted) {\n json(res, { error: 'hook_in_use', references: result.references }, 409)\n return\n }\n json(res, result)\n } catch (err: unknown) {\n if (isHookRegistryMutationError(err) && err.code === 'hook_not_found') {\n notFound(res, 'Hook not found')\n return\n }\n if (isHookRegistryMutationError(err) && err.code === 'validation_failed') {\n json(res, { error: 'validation_failed', fieldErrors: err.fieldErrors }, 400)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete hook' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/agent-rules' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n try {\n if (typeof body.content !== 'string') {\n json(res, { error: 'Missing required field: content' }, 400)\n return\n }\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n await writeFile(workspacePaths.agentRules.absolutePath, body.content, 'utf-8')\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to save agent rules' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n if (path === '/api/agent-rules/create' && req.method === 'POST') {\n if (!configManager || !deps.configPath) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n const configPath = deps.configPath\n readJsonBody<{ fileName?: string }>(req)\n .then(async (body) => {\n try {\n const fileName = typeof body.fileName === 'string' && body.fileName.trim()\n ? body.fileName.trim()\n : 'agent-rules.md'\n if (!isPlainFileName(fileName)) {\n json(res, { error: 'fileName must be a plain file name' }, 400)\n return\n }\n\n const configDir = dirname(configPath)\n const resolvedPath = resolve(configDir, fileName)\n if (!getPathInsideDir(resolvedPath, configDir)) {\n json(res, { error: 'Invalid agent rules path' }, 400)\n return\n }\n\n await writeFile(resolvedPath, '', { encoding: 'utf-8', flag: 'wx' })\n await configManager!.replaceSectionRaw('workspace.agentRules', `./${fileName}`)\n json(res, { created: true, filePath: `./${fileName}` })\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n json(res, { error: 'Agent rules file already exists' }, 409)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to create agent rules file' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // Variables API\n if (path === '/api/variables' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content: string\n try {\n content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { error: `workspace.envFile not found: ${workspacePaths.envFile.workspaceRelativePath}` }, 500)\n return\n }\n throw err\n }\n const parsed = parseEnvFile(content)\n const variables = Object.entries(parsed).map(([key, value]) => ({ key, value }))\n json(res, { variables, filePath: workspacePaths.envFile.workspaceRelativePath })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read variables' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/variables' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ oldKey?: string; key: string; value: string }>(req)\n .then(async (body) => {\n try {\n if (!body.key || typeof body.key !== 'string') {\n json(res, { error: 'Missing required field: key' }, 400)\n return\n }\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(body.key)) {\n json(res, { error: 'Variable names must contain only letters, numbers, and underscores' }, 400)\n return\n }\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content = ''\n try {\n content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { error: `workspace.envFile not found: ${workspacePaths.envFile.workspaceRelativePath}` }, 500)\n return\n }\n throw err\n }\n const vars = parseEnvFile(content)\n if (body.oldKey && body.oldKey !== body.key) {\n delete vars[body.oldKey]\n }\n vars[body.key] = body.value ?? ''\n await writeFile(workspacePaths.envFile.absolutePath, serializeEnvFile(vars), 'utf-8')\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update variable' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n const varDeleteMatch = path.match(/^\\/api\\/variables\\/(.+)$/)\n if (varDeleteMatch && req.method === 'DELETE') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const varKey = decodeURIComponent(varDeleteMatch[1])\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content = ''\n try {\n content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { error: `workspace.envFile not found: ${workspacePaths.envFile.workspaceRelativePath}` }, 500)\n return\n }\n throw err\n }\n const vars = parseEnvFile(content)\n const existed = varKey in vars\n delete vars[varKey]\n await writeFile(workspacePaths.envFile.absolutePath, serializeEnvFile(vars), 'utf-8')\n json(res, { deleted: existed })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete variable' }, 500)\n }\n })()\n return\n }\n\n // POST /api/live-editor/sessions — create a new live editor session\n if (path === '/api/live-editor/sessions' && req.method === 'POST') {\n if (!sessionManager) {\n json(res, { error: 'Live editor not available' }, 503)\n return\n }\n ;(async () => {\n try {\n const body = await readJsonBody<{\n platform?: string\n targetName?: string\n url?: string\n headless?: boolean\n device?: Record<string, unknown>\n useDeviceName?: string\n appState?: string\n bundleId?: string\n appPackage?: string\n appActivity?: string\n setupHooks?: unknown\n teardownHooks?: unknown\n entity?: { type?: string; id?: string }\n }>(req)\n const platform = body?.platform ?? 'web'\n const runtimeLLM = await resolveDashboardRuntimeLLM(configManager, llmConfig, authFetch)\n if (!runtimeLLM.ok) {\n json(res, { error: runtimeLLM.error }, 400)\n return\n }\n const setupHooks = Array.isArray(body?.setupHooks)\n ? body.setupHooks.filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n : []\n const teardownHooks = Array.isArray(body?.teardownHooks)\n ? body.teardownHooks.filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n : []\n // Validate entity (ASVS V5). Only 'suite' | 'test' with a non-empty id\n // are honoured; malformed shapes are silently ignored — client may\n // send {} during the test-editor retrofit before entity threading\n // lands (downgrades to sessionNumber=null instead of a 400 error).\n let entityRef: { type: 'suite' | 'test'; id: string } | undefined\n if (body?.entity && typeof body.entity === 'object') {\n const t = body.entity.type\n const id = body.entity.id\n if ((t === 'suite' || t === 'test') && typeof id === 'string' && id.length > 0) {\n entityRef = { type: t, id }\n }\n }\n let agentRules: string | undefined\n let envVars: Record<string, string> | undefined\n let secretStore: SecretStore | undefined\n let secretRedactor: SecretRedactor | undefined\n let resolvedHooks = new Map<string, import('@vostride/agent-qa-core').HookDefinition>()\n let hookRegistryError: string | undefined\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 500)\n return\n }\n\n try {\n agentRules = await readFile(workspacePaths.agentRules.absolutePath, 'utf-8')\n } catch {\n json(res, { error: `workspace.agentRules file could not be loaded: ${workspacePaths.agentRules.workspaceRelativePath}` }, 400)\n return\n }\n\n try {\n const envContent = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n envVars = parseEnvFile(envContent)\n } catch {\n json(res, { error: `workspace.envFile file could not be loaded: ${workspacePaths.envFile.workspaceRelativePath}` }, 400)\n return\n }\n\n try {\n const secretsContent = await readFile(workspacePaths.secretsFile.absolutePath, 'utf-8')\n secretStore = SecretStore.fromEnvContent(secretsContent)\n secretRedactor = new SecretRedactor(secretStore)\n } catch {\n json(res, { error: `workspace.secretsFile file could not be loaded: ${workspacePaths.secretsFile.workspaceRelativePath}` }, 400)\n return\n }\n\n const hookCatalog = await readWorkspaceHooks(configManager, deps.configPath)\n resolvedHooks = hookCatalog.resolvedHooks\n hookRegistryError = hookCatalog.hookRegistryError\n const { sessionId, sessionNumber } = await sessionManager.createSession(\n {\n platform: platform as 'web' | 'android' | 'ios',\n targetName: typeof body?.targetName === 'string' ? body.targetName : undefined,\n llmConfig: runtimeLLM.llmConfig,\n authFetch: runtimeLLM.authFetch,\n agentRules,\n envVars,\n secretStore,\n secretRedactor,\n setupHooks,\n teardownHooks,\n resolvedHooks,\n hookRegistryError,\n url: body?.url,\n headless: body?.headless ?? false,\n useDeviceName: typeof body?.useDeviceName === 'string' ? body.useDeviceName : undefined,\n appState: body?.appState === 'preserve' || body?.appState === 'reset' ? body.appState : undefined,\n bundleId: typeof body?.bundleId === 'string' ? body.bundleId : undefined,\n appPackage: typeof body?.appPackage === 'string' ? body.appPackage : undefined,\n appActivity: typeof body?.appActivity === 'string' ? body.appActivity : undefined,\n device: body?.device as import('../live-editor/types.js').LiveSessionConfig['device'],\n },\n entityRef,\n )\n json(res, { sessionId, sessionNumber }, 201)\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n json(res, { error: message }, 500)\n }\n })()\n return\n }\n\n // GET /api/live-editor/sessions — list all active live editor sessions\n if (path === '/api/live-editor/sessions' && req.method === 'GET') {\n if (!sessionManager) {\n json(res, { error: 'Live editor not available' }, 503)\n return\n }\n json(res, { sessions: sessionManager.listSessions() })\n return\n }\n\n // DELETE /api/live-editor/sessions/:id — terminate a live editor session\n const liveEditorSessionMatch = path.match(/^\\/api\\/live-editor\\/sessions\\/([^/]+)$/)\n if (liveEditorSessionMatch && req.method === 'DELETE') {\n if (!sessionManager) {\n json(res, { error: 'Live editor not available' }, 503)\n return\n }\n const sessionId = liveEditorSessionMatch[1]\n ;(async () => {\n const terminated = await sessionManager.terminateSession(sessionId)\n if (terminated) {\n json(res, { ok: true })\n } else {\n notFound(res, 'Session not found')\n }\n })()\n return\n }\n\n // Variable suggestions: env keys\n if (path === '/api/variables/env' && req.method === 'GET') {\n if (!configManager) {\n json(res, { keys: [] })\n return\n }\n ;(async () => {\n try {\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n const content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n const parsed = parseEnvFile(content)\n json(res, { keys: Object.keys(parsed) })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read env variables' }, 500)\n }\n })()\n return\n }\n\n // Variable suggestions: hook names\n if (path === '/api/variables/hooks' && req.method === 'GET') {\n ;(async () => {\n try {\n const { hooks } = await readWorkspaceHooks(configManager, deps.configPath)\n json(res, { names: hooks.map((hook) => hook.name) })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read hooks' }, 500)\n }\n })()\n return\n }\n\n // Variable suggestions: captured variable names from prior runs\n const capturedMatch = path.match(/^\\/api\\/variables\\/captured\\/([^/]+)$/)\n if (capturedMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const testId = decodeURIComponent(capturedMatch[1])\n const names = db.getCapturedVariableNames(testId)\n json(res, { names })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read captured variables' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/memory/catalog' && req.method === 'GET') {\n ;(async () => {\n try {\n json(res, await memoryCatalogManager.readCatalog())\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read memory catalog' }, 500)\n }\n })()\n return\n }\n\n const memoryProductMatch = path.match(/^\\/api\\/memory\\/products\\/([^/]+)$/)\n if (memoryProductMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const productKey = decodeURIComponent(memoryProductMatch[1])\n if (!isValidMemoryScopeId(productKey)) {\n json(res, { error: 'Invalid memory product id' }, 400)\n return\n }\n const product = await memoryCatalogManager.readProductDetail(productKey)\n if (!product) {\n json(res, { error: 'Memory product not found' }, 404)\n return\n }\n json(res, { product })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read memory product' }, 500)\n }\n })()\n return\n }\n\n const memoryScopeMatch = path.match(/^\\/api\\/memory\\/scopes\\/([^/]+)\\/([^/]+)$/)\n if (memoryScopeMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const scope = decodeURIComponent(memoryScopeMatch[1])\n const scopeId = decodeURIComponent(memoryScopeMatch[2])\n if (!isMemoryScope(scope)) {\n json(res, { error: 'Invalid memory scope' }, 400)\n return\n }\n if (!isValidMemoryScopeId(scopeId)) {\n json(res, { error: 'Invalid memory scope id' }, 400)\n return\n }\n const payload = await memoryCatalogManager.readScopedObservations(scope, scopeId)\n if (!payload) {\n json(res, { error: 'Memory scope not found' }, 404)\n return\n }\n json(res, payload)\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read memory scope' }, 500)\n }\n })()\n return\n }\n\n // Memory observations: list for a test\n const obsListMatch = path.match(/^\\/api\\/memory\\/observations\\/([^/]+)$/)\n if (obsListMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const testId = decodeURIComponent(obsListMatch[1])\n const payload = await memoryCatalogManager.readScopedObservations('test', testId)\n json(res, {\n observations: payload?.observations ?? [],\n invalidFiles: payload?.invalidFiles ?? [],\n })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read observations' }, 500)\n }\n })()\n return\n }\n\n // Memory observations: delete\n const obsDeleteMatch = path.match(/^\\/api\\/memory\\/observations\\/([^/]+)\\/([^/]+)$/)\n if (obsDeleteMatch && req.method === 'DELETE') {\n ;(async () => {\n try {\n const testId = decodeURIComponent(obsDeleteMatch[1])\n const obsId = decodeURIComponent(obsDeleteMatch[2])\n if (!isValidMemoryScopeId(testId) || !isValidMemoryScopeId(obsId)) {\n json(res, { error: 'Invalid memory observation id' }, 400)\n return\n }\n\n const configDir = deps.configPath ? dirname(resolve(deps.configPath)) : process.cwd()\n const cfg = configManager ? await configManager.read().catch(() => undefined) : undefined\n const parsedConfig = AgentQaConfigSchema.safeParse(cfg ?? {})\n const memoryRoot = parsedConfig.success\n ? resolveMemoryRoot(parsedConfig.data, configDir)\n : resolveMemoryRoot(undefined, configDir)\n const testsRoot = join(memoryRoot, 'tests')\n const resolved = resolve(testsRoot, testId, `${obsId}.md`)\n if (!getPathInsideDir(resolved, testsRoot)) {\n json(res, { error: 'Invalid path' }, 400)\n return\n }\n\n await rm(resolved, { force: true })\n json(res, { deleted: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete observation' }, 500)\n }\n })()\n return\n }\n\n // Unknown API route\n if (path.startsWith('/api/')) {\n notFound(res)\n return\n }\n\n // Non-API routes handled by server.ts (static files)\n notFound(res)\n }\n}\n\nfunction isMemoryScope(value: string): value is MemoryScope {\n return value === 'product' || value === 'suite' || value === 'test'\n}\n","import { readdir, readFile, stat } from 'node:fs/promises'\nimport { dirname, join, resolve, sep } from 'node:path'\n\nimport {\n AgentQaConfigSchema,\n discoverWorkspaceFiles,\n listObservations,\n parseObservation,\n resolveMemoryRoot,\n resolveWorkspacePaths,\n scanContent,\n type BaseObservation,\n type SuiteObservation,\n} from '@vostride/agent-qa-core'\nimport { parse as parseYaml } from 'yaml'\n\nimport type { ConfigManager } from '../config/index.js'\nimport { extractTestFileMetadata } from '../tests/test-file-manager.js'\n\nexport type MemoryScope = 'product' | 'suite' | 'test'\n\ntype MemoryTier = 'products' | 'suites' | 'tests'\ntype MemoryObservation = BaseObservation | SuiteObservation\n\nexport interface MemoryScopeCounts {\n product: number\n suite: number\n test: number\n}\n\nexport interface MemoryCatalogSourceCounts {\n suite: number\n test: number\n}\n\nexport interface MemoryCatalogProduct {\n productKey: string\n observationCount: number\n scopeCounts: MemoryScopeCounts\n targetReferences: string[]\n sourceCounts: MemoryCatalogSourceCounts\n freshness: string | null\n sourceCoverage: number\n}\n\nexport interface MemoryScopeSummary {\n scope: MemoryScope\n observationCount: number\n freshness: string | null\n sourceCoverage: number\n scopeIds: string[]\n}\n\nexport interface MemoryAtlasObservation {\n id: string\n title: string\n content: string\n trust: number\n created: string\n last_confirmed: string\n confirmed_count: number\n contradicted_count: number\n source_test: string\n scope: MemoryScope\n scopeId: string\n}\n\nexport interface MemoryObservationReference {\n kind: 'suite' | 'test' | 'source_test'\n id: string\n label: string\n targetName: string | null\n href: string | null\n}\n\nexport interface MemoryWorkspaceObservation extends MemoryAtlasObservation {\n updated: string\n scopeRef: MemoryObservationReference | null\n sourceTestRef: MemoryObservationReference | null\n}\n\nexport interface MemoryInvalidFile {\n scope: MemoryScope\n scopeId: string\n filename: string\n code: string\n message: string\n}\n\nexport interface MemoryProductDetail extends MemoryCatalogProduct {\n scopes: Record<MemoryScope, MemoryScopeSummary>\n observations: MemoryWorkspaceObservation[]\n invalidFiles: MemoryInvalidFile[]\n}\n\nexport interface MemoryCatalogResponse {\n products: MemoryCatalogProduct[]\n}\n\nexport interface MemoryScopeReadResponse {\n scope: MemoryScope\n scopeId: string\n observations: MemoryObservation[]\n invalidFiles: MemoryInvalidFile[]\n}\n\ninterface MemoryCatalogManagerOptions {\n configManager?: ConfigManager\n configPath?: string\n}\n\ninterface WorkspaceContext {\n workspaceDir: string\n memoryRoot: string\n targetToProduct: Map<string, string>\n productToTargets: Map<string, string[]>\n suiteMetadataById: Map<string, WorkspaceEntityMetadata>\n testMetadataById: Map<string, WorkspaceEntityMetadata>\n}\n\ninterface WorkspaceEntityMetadata {\n id: string\n label: string\n targetName: string | null\n productKey: string | null\n href: string | null\n}\n\ninterface ProductAccumulator {\n productKey: string\n observationCount: number\n scopeCounts: MemoryScopeCounts\n targetReferences: string[]\n freshness: string | null\n sourceTests: Set<string>\n scopes: Record<MemoryScope, ScopeAccumulator>\n observations: MemoryWorkspaceObservation[]\n invalidFiles: MemoryInvalidFile[]\n}\n\ninterface ObservationRecord {\n observation: MemoryObservation\n updated: string\n}\n\ninterface ScopeAccumulator {\n observationCount: number\n freshness: string | null\n sourceTests: Set<string>\n scopeIds: Set<string>\n}\n\nconst MEMORY_SCOPE_TO_TIER: Record<MemoryScope, MemoryTier> = {\n product: 'products',\n suite: 'suites',\n test: 'tests',\n}\n\nconst MEMORY_SCOPE_ORDER: Record<MemoryScope, number> = {\n product: 0,\n suite: 1,\n test: 2,\n}\n\nconst EMPTY_SCOPE_COUNTS: MemoryScopeCounts = {\n product: 0,\n suite: 0,\n test: 0,\n}\n\nexport class MemoryCatalogManager {\n private readonly configManager?: ConfigManager\n private readonly configPath?: string\n\n constructor(options: MemoryCatalogManagerOptions = {}) {\n this.configManager = options.configManager\n this.configPath = options.configPath\n }\n\n async readCatalog(): Promise<MemoryCatalogResponse> {\n const products = await this.readProducts()\n return {\n products: products\n .map((product) => this.toProductSummary(product))\n .sort(compareProducts),\n }\n }\n\n async readProductDetail(productKey: string): Promise<MemoryProductDetail | null> {\n if (!isValidMemoryScopeId(productKey)) {\n return null\n }\n\n const products = await this.readProducts()\n const match = products.find((product) => product.productKey === productKey)\n return match ? this.toProductDetail(match) : null\n }\n\n async readScopedObservations(scope: MemoryScope, scopeId: string): Promise<MemoryScopeReadResponse | null> {\n if (!isValidMemoryScopeId(scopeId)) {\n return null\n }\n\n const { memoryRoot } = await this.loadWorkspaceContext()\n const tierRoot = resolve(join(memoryRoot, MEMORY_SCOPE_TO_TIER[scope]))\n const dir = resolve(join(tierRoot, scopeId))\n if (!dir.startsWith(`${tierRoot}${sep}`)) {\n return null\n }\n\n try {\n const info = await stat(dir)\n if (!info.isDirectory()) {\n return null\n }\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null\n }\n throw error\n }\n\n const context = await this.loadWorkspaceContext()\n const { observations, invalidFiles } = await readObservationDirectory(scope, scopeId, dir)\n\n return {\n scope,\n scopeId,\n observations: observations.map((record) => toMemoryWorkspaceObservation(scope, scopeId, record, context)),\n invalidFiles,\n }\n }\n\n private async readProducts(): Promise<ProductAccumulator[]> {\n const context = await this.loadWorkspaceContext()\n const products = new Map<string, ProductAccumulator>()\n\n await this.collectTier(context.memoryRoot, context.productToTargets, 'products', (scopeId) => scopeId, products, context)\n await this.collectTier(\n context.memoryRoot,\n context.productToTargets,\n 'suites',\n (scopeId) => context.suiteMetadataById.get(scopeId)?.productKey ?? null,\n products,\n context,\n )\n await this.collectTier(\n context.memoryRoot,\n context.productToTargets,\n 'tests',\n (scopeId) => context.testMetadataById.get(scopeId)?.productKey ?? null,\n products,\n context,\n )\n\n return Array.from(products.values())\n }\n\n private async collectTier(\n memoryRoot: string,\n productToTargets: Map<string, string[]>,\n tier: MemoryTier,\n resolveProductKey: (scopeId: string) => string | null,\n products: Map<string, ProductAccumulator>,\n context: WorkspaceContext,\n ): Promise<void> {\n const tierRoot = join(memoryRoot, tier)\n let entries: Array<{ isDirectory(): boolean; name: string }>\n try {\n const dirEntries = await readdir(tierRoot, { withFileTypes: true, encoding: 'utf8' })\n entries = dirEntries.map((entry) => ({\n isDirectory: () => entry.isDirectory(),\n name: String(entry.name),\n }))\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return\n }\n throw error\n }\n\n const scope = tierToScope(tier)\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const scopeId = entry.name\n const productKey = resolveProductKey(scopeId)\n if (!productKey || !isValidMemoryScopeId(productKey)) continue\n\n const { observations, invalidFiles } = await readObservationDirectory(scope, scopeId, join(tierRoot, scopeId))\n if (observations.length === 0 && invalidFiles.length === 0) continue\n\n const accumulator = products.get(productKey) ?? createProductAccumulator(\n productKey,\n productToTargets.get(productKey) ?? [],\n )\n accumulator.invalidFiles.push(...invalidFiles)\n for (const record of observations) {\n const observation = toMemoryWorkspaceObservation(scope, scopeId, record, context)\n accumulator.observationCount += 1\n accumulator.scopeCounts[scope] += 1\n accumulator.freshness = pickFreshest(accumulator.freshness, observation.last_confirmed)\n accumulator.sourceTests.add(observation.source_test)\n accumulator.observations.push(observation)\n\n const scopeAccumulator = accumulator.scopes[scope]\n scopeAccumulator.observationCount += 1\n scopeAccumulator.freshness = pickFreshest(scopeAccumulator.freshness, observation.last_confirmed)\n scopeAccumulator.sourceTests.add(observation.source_test)\n scopeAccumulator.scopeIds.add(scopeId)\n }\n\n products.set(productKey, accumulator)\n }\n }\n\n private async loadWorkspaceContext(): Promise<WorkspaceContext> {\n const workspaceDir = this.configPath ? dirname(resolve(this.configPath)) : process.cwd()\n const config = await this.readConfig()\n const targetToProduct = getTargetToProductMap(config)\n const productToTargets = getProductToTargetsMap(targetToProduct)\n const configResult = AgentQaConfigSchema.safeParse(config)\n const memoryRoot = configResult.success\n ? resolveMemoryRoot(configResult.data, workspaceDir)\n : resolveMemoryRoot(undefined, workspaceDir)\n const workspacePaths = configResult.success\n ? resolveWorkspacePaths({\n config: configResult.data,\n configPath: this.configPath ? resolve(this.configPath) : resolve(workspaceDir, 'agent-qa.config.yaml'),\n })\n : null\n const [testFiles, suiteFiles] = workspacePaths\n ? await Promise.all([\n discoverWorkspaceFiles({ workspace: workspacePaths, kind: 'test' }),\n discoverWorkspaceFiles({ workspace: workspacePaths, kind: 'suite' }),\n ])\n : [[], []]\n\n const testMetadataById = new Map<string, WorkspaceEntityMetadata>()\n for (const file of testFiles) {\n const content = await readFile(file.absolutePath, 'utf-8').catch(() => null)\n if (!content) continue\n const metadata = extractTestFileMetadata(content)\n if (!metadata.testId) continue\n const targetName = metadata.targetName ?? null\n const productKey = targetName ? targetToProduct.get(targetName) ?? null : null\n testMetadataById.set(metadata.testId, {\n id: metadata.testId,\n label: metadata.name?.trim() || metadata.testId,\n targetName,\n productKey,\n href: `/test/${metadata.testId}`,\n })\n }\n\n const suiteMetadataById = new Map<string, WorkspaceEntityMetadata>()\n for (const file of suiteFiles) {\n const content = await readFile(file.absolutePath, 'utf-8').catch(() => null)\n if (!content) continue\n const metadata = extractSuiteFileMetadata(content)\n if (!metadata.suiteId) continue\n const targetName = metadata.targetName ?? null\n const productKey = targetName ? targetToProduct.get(targetName) ?? null : null\n suiteMetadataById.set(metadata.suiteId, {\n id: metadata.suiteId,\n label: metadata.name?.trim() || metadata.suiteId,\n targetName,\n productKey,\n href: `/suite/${metadata.suiteId}`,\n })\n }\n\n return {\n workspaceDir,\n memoryRoot,\n targetToProduct,\n productToTargets,\n suiteMetadataById,\n testMetadataById,\n }\n }\n\n private async readConfig(): Promise<Record<string, unknown>> {\n if (!this.configManager) {\n return {}\n }\n\n try {\n return await this.configManager.read()\n } catch {\n return {}\n }\n }\n\n private toProductSummary(product: ProductAccumulator): MemoryCatalogProduct {\n return {\n productKey: product.productKey,\n observationCount: product.observationCount,\n scopeCounts: { ...product.scopeCounts },\n targetReferences: [...product.targetReferences],\n sourceCounts: {\n suite: product.scopes.suite.scopeIds.size,\n test: product.sourceTests.size,\n },\n freshness: product.freshness,\n sourceCoverage: product.sourceTests.size,\n }\n }\n\n private toProductDetail(product: ProductAccumulator): MemoryProductDetail {\n return {\n ...this.toProductSummary(product),\n scopes: {\n product: toScopeSummary('product', product.scopes.product),\n suite: toScopeSummary('suite', product.scopes.suite),\n test: toScopeSummary('test', product.scopes.test),\n },\n observations: [...product.observations].sort(compareMemoryWorkspaceObservations),\n invalidFiles: [...product.invalidFiles].sort(compareInvalidFiles),\n }\n }\n}\n\nfunction tierToScope(tier: MemoryTier): MemoryScope {\n switch (tier) {\n case 'products':\n return 'product'\n case 'suites':\n return 'suite'\n case 'tests':\n return 'test'\n }\n}\n\nfunction createProductAccumulator(productKey: string, targetReferences: string[]): ProductAccumulator {\n return {\n productKey,\n observationCount: 0,\n scopeCounts: { ...EMPTY_SCOPE_COUNTS },\n targetReferences: [...targetReferences],\n freshness: null,\n sourceTests: new Set<string>(),\n scopes: {\n product: createScopeAccumulator(),\n suite: createScopeAccumulator(),\n test: createScopeAccumulator(),\n },\n observations: [],\n invalidFiles: [],\n }\n}\n\nfunction createScopeAccumulator(): ScopeAccumulator {\n return {\n observationCount: 0,\n freshness: null,\n sourceTests: new Set<string>(),\n scopeIds: new Set<string>(),\n }\n}\n\nfunction toScopeSummary(scope: MemoryScope, accumulator: ScopeAccumulator): MemoryScopeSummary {\n return {\n scope,\n observationCount: accumulator.observationCount,\n freshness: accumulator.freshness,\n sourceCoverage: accumulator.sourceTests.size,\n scopeIds: Array.from(accumulator.scopeIds).sort((left, right) => left.localeCompare(right)),\n }\n}\n\nfunction compareProducts(left: MemoryCatalogProduct, right: MemoryCatalogProduct): number {\n const freshnessCompare = compareFreshness(right.freshness, left.freshness)\n if (freshnessCompare !== 0) {\n return freshnessCompare\n }\n\n const sourceCoverageCompare = right.sourceCoverage - left.sourceCoverage\n if (sourceCoverageCompare !== 0) {\n return sourceCoverageCompare\n }\n\n return left.productKey.localeCompare(right.productKey)\n}\n\nfunction compareFreshness(left: string | null, right: string | null): number {\n if (left === right) return 0\n if (!left) return -1\n if (!right) return 1\n return left.localeCompare(right)\n}\n\nfunction toMemoryWorkspaceObservation(\n scope: MemoryScope,\n scopeId: string,\n record: ObservationRecord,\n context: WorkspaceContext,\n): MemoryWorkspaceObservation {\n const observation = record.observation\n return {\n id: observation.id,\n title: observation.title,\n content: observation.content,\n trust: observation.trust,\n created: observation.created,\n last_confirmed: observation.last_confirmed,\n confirmed_count: observation.confirmed_count,\n contradicted_count: observation.contradicted_count,\n source_test: observation.source_test,\n scope,\n scopeId,\n updated: record.updated,\n scopeRef: resolveScopeReference(scope, scopeId, context),\n sourceTestRef: resolveReference('source_test', context.testMetadataById.get(observation.source_test)),\n }\n}\n\nfunction compareMemoryWorkspaceObservations(left: MemoryWorkspaceObservation, right: MemoryWorkspaceObservation): number {\n const scopeCompare = MEMORY_SCOPE_ORDER[left.scope] - MEMORY_SCOPE_ORDER[right.scope]\n if (scopeCompare !== 0) {\n return scopeCompare\n }\n\n const lastConfirmedCompare = right.last_confirmed.localeCompare(left.last_confirmed)\n if (lastConfirmedCompare !== 0) {\n return lastConfirmedCompare\n }\n\n const createdCompare = right.created.localeCompare(left.created)\n if (createdCompare !== 0) {\n return createdCompare\n }\n\n return left.id.localeCompare(right.id)\n}\n\nfunction compareInvalidFiles(left: MemoryInvalidFile, right: MemoryInvalidFile): number {\n return (\n MEMORY_SCOPE_ORDER[left.scope] - MEMORY_SCOPE_ORDER[right.scope] ||\n left.scopeId.localeCompare(right.scopeId) ||\n left.filename.localeCompare(right.filename)\n )\n}\n\nfunction pickFreshest(current: string | null, candidate: string): string {\n if (!current) return candidate\n return candidate.localeCompare(current) > 0 ? candidate : current\n}\n\nasync function readObservationDirectory(\n scope: MemoryScope,\n scopeId: string,\n dir: string,\n): Promise<{ observations: ObservationRecord[]; invalidFiles: MemoryInvalidFile[] }> {\n const filenames = await listObservations(dir)\n const observations: ObservationRecord[] = []\n const invalidFiles: MemoryInvalidFile[] = []\n\n for (const filename of filenames) {\n const filePath = join(dir, filename)\n const raw = await readFile(filePath, 'utf-8').catch(() => null)\n if (!raw) continue\n\n const parsed = parseObservation(raw, filename)\n if (!parsed.data || parsed.error) {\n invalidFiles.push({\n scope,\n scopeId,\n filename,\n code: 'parse_error',\n message: parsed.error ?? 'Observation file could not be parsed',\n })\n continue\n }\n\n const scanned = scanObservationPayload(parsed.data.title, parsed.data.content)\n if (!scanned.safe) {\n invalidFiles.push({\n scope,\n scopeId,\n filename,\n code: 'security_scan_failed',\n message: `Security scan blocked: ${scanned.matchedPattern}`,\n })\n continue\n }\n\n const fileInfo = await stat(filePath).catch(() => null)\n if (!fileInfo) continue\n\n observations.push({\n observation: parsed.data,\n updated: fileInfo.mtime.toISOString(),\n })\n }\n\n return {\n observations: observations.sort((left, right) => right.observation.last_confirmed.localeCompare(left.observation.last_confirmed)),\n invalidFiles: invalidFiles.sort(compareInvalidFiles),\n }\n}\n\nfunction scanObservationPayload(title: string, content: string) {\n return scanContent([title, content].filter(Boolean).join('\\n'))\n}\n\nfunction getTargetToProductMap(config: Record<string, unknown>): Map<string, string> {\n const registry = (config.registry ?? {}) as {\n targets?: Record<string, { product?: unknown }>\n }\n const map = new Map<string, string>()\n\n for (const [targetName, targetConfig] of Object.entries(registry.targets ?? {})) {\n const productValue = typeof targetConfig?.product === 'string' && targetConfig.product.trim().length > 0\n ? targetConfig.product.trim()\n : targetName\n if (isValidMemoryScopeId(productValue)) {\n map.set(targetName, productValue)\n }\n }\n\n return map\n}\n\nfunction getProductToTargetsMap(targetToProduct: Map<string, string>): Map<string, string[]> {\n const map = new Map<string, string[]>()\n\n for (const [targetName, productKey] of targetToProduct.entries()) {\n const targets = map.get(productKey) ?? []\n targets.push(targetName)\n map.set(productKey, targets)\n }\n\n for (const targets of map.values()) {\n targets.sort((left, right) => left.localeCompare(right))\n }\n\n return map\n}\n\nfunction extractSuiteFileMetadata(content: string): { suiteId: string | null; name: string | null; targetName: string | null } {\n let parsed: Record<string, unknown> | null = null\n\n try {\n const yamlValue = parseYaml(content)\n if (yamlValue && typeof yamlValue === 'object' && !Array.isArray(yamlValue)) {\n parsed = yamlValue as Record<string, unknown>\n }\n } catch {\n // Fall back to regex extraction for partially-authored files.\n }\n\n const name = typeof parsed?.name === 'string' && parsed.name.trim().length > 0\n ? parsed.name.trim()\n : content.match(/^name:\\s*(.+)$/m)?.[1]?.trim().replace(/^[\"'](.*)[\"']$/, '$1') ?? null\n\n const suiteId = typeof parsed?.['suite-id'] === 'string' && parsed['suite-id'].trim().length > 0\n ? parsed['suite-id'].trim()\n : content.match(/^suite-id:\\s*(.+)$/m)?.[1]?.trim().replace(/^[\"'](.*)[\"']$/, '$1') ?? null\n\n const targetName = typeof parsed?.target === 'string' && parsed.target.trim().length > 0\n ? parsed.target.trim()\n : content.match(/^target:\\s*(.+)$/m)?.[1]?.trim().replace(/^[\"'](.*)[\"']$/, '$1') ?? null\n\n return { suiteId, name, targetName }\n}\n\nfunction resolveScopeReference(\n scope: MemoryScope,\n scopeId: string,\n context: WorkspaceContext,\n): MemoryObservationReference | null {\n switch (scope) {\n case 'product':\n return null\n case 'suite':\n return resolveReference('suite', context.suiteMetadataById.get(scopeId))\n case 'test':\n return resolveReference('test', context.testMetadataById.get(scopeId))\n }\n}\n\nfunction resolveReference(\n kind: MemoryObservationReference['kind'],\n metadata: WorkspaceEntityMetadata | undefined,\n): MemoryObservationReference | null {\n if (!metadata) {\n return null\n }\n\n return {\n kind,\n id: metadata.id,\n label: metadata.label,\n targetName: metadata.targetName,\n href: metadata.href,\n }\n}\n\nexport function isValidMemoryScopeId(value: string): boolean {\n return value.trim().length > 0 && !/\\.\\./.test(value) && !/[/\\\\]/.test(value) && !/\\0/.test(value)\n}\n","import { readFile, writeFile, mkdir, rm, stat } from 'node:fs/promises'\nimport { dirname, basename } from 'node:path'\nimport { generateTestId } from '@vostride/agent-qa-ids'\nimport { parse as parseYaml } from 'yaml'\nimport {\n discoverWorkspaceFiles,\n resolveWorkspaceFileTarget,\n type ResolvedWorkspacePaths,\n} from '@vostride/agent-qa-core'\n\nexport interface TestFileInfo {\n path: string\n name: string\n testId: string | null\n targetName: string | null\n platform: string | null\n modified: string\n}\n\nexport type SupportedPlatform = 'web' | 'android' | 'ios'\n\nexport interface TestFileMetadata {\n name: string | null\n testId: string | null\n targetName: string | null\n platform: SupportedPlatform | null\n parallel: boolean | null\n}\n\nexport interface TestValidationError {\n message: string\n line?: number\n column?: number\n suggestion?: string\n}\n\nexport interface TestValidationResult {\n valid: boolean\n errors: TestValidationError[]\n}\n\nfunction normalizeQuotedString(value: string): string {\n return value.trim().replace(/^[\"'](.*)[\"']$/, '$1')\n}\n\nfunction normalizePlatform(value: unknown): SupportedPlatform | null {\n if (value !== 'web' && value !== 'android' && value !== 'ios') return null\n return value\n}\n\nexport function extractTestFileMetadata(content: string): TestFileMetadata {\n let parsed: Record<string, unknown> | null = null\n\n try {\n const yamlValue = parseYaml(content)\n if (yamlValue && typeof yamlValue === 'object' && !Array.isArray(yamlValue)) {\n parsed = yamlValue as Record<string, unknown>\n }\n } catch {\n // fall back to regex extraction for partially-authored files\n }\n\n const config = parsed?.config\n const parsedConfig = config && typeof config === 'object' && !Array.isArray(config)\n ? config as Record<string, unknown>\n : null\n const use = parsed?.use\n const parsedUse = use && typeof use === 'object' && !Array.isArray(use)\n ? use as Record<string, unknown>\n : null\n\n const nameMatch = content.match(/^name:\\s*(.+)$/m)\n const targetMatch = content.match(/^\\s*target:\\s*(.+)$/m)\n const testIdMatch = content.match(/^test-id:\\s*(.+)$/m)\n const platformMatch = content.match(/^\\s*platform:\\s*(web|android|ios)\\s*$/m)\n const parallelMatch = content.match(/^\\s*parallel:\\s*(true|false)\\s*$/m)\n\n const name = typeof parsed?.name === 'string' && parsed.name.trim().length > 0\n ? parsed.name.trim()\n : nameMatch\n ? normalizeQuotedString(nameMatch[1])\n : null\n\n const targetName = typeof parsed?.target === 'string' && parsed.target.trim().length > 0\n ? parsed.target.trim()\n : targetMatch\n ? normalizeQuotedString(targetMatch[1])\n : null\n\n const testId = typeof parsed?.['test-id'] === 'string' && parsed['test-id'].trim().length > 0\n ? parsed['test-id'].trim()\n : testIdMatch\n ? normalizeQuotedString(testIdMatch[1])\n : null\n\n const platform = normalizePlatform(parsed?.platform)\n ?? normalizePlatform(parsedConfig?.platform)\n ?? normalizePlatform(platformMatch?.[1])\n\n const parallel = typeof parsedUse?.parallel === 'boolean'\n ? parsedUse.parallel\n : typeof parsed?.parallel === 'boolean'\n ? parsed.parallel\n : typeof parsedConfig?.parallel === 'boolean'\n ? parsedConfig.parallel\n : parallelMatch\n ? parallelMatch[1] === 'true'\n : null\n\n return {\n name,\n testId,\n targetName,\n platform,\n parallel,\n }\n}\n\nexport class TestFileManager {\n constructor(private readonly workspace: ResolvedWorkspacePaths) {}\n\n async list(): Promise<TestFileInfo[]> {\n const records = await discoverWorkspaceFiles({ workspace: this.workspace, kind: 'test' })\n const files: TestFileInfo[] = []\n\n for (const record of records) {\n try {\n const s = await stat(record.absolutePath)\n if (s.isFile()) {\n let testName = basename(record.workspaceRelativePath)\n let platform: string | null = null\n let targetName: string | null = null\n let testId: string | null = null\n try {\n let content = await readFile(record.absolutePath, 'utf-8')\n const metadata = extractTestFileMetadata(content)\n if (metadata.name) testName = metadata.name\n if (metadata.targetName) targetName = metadata.targetName\n if (metadata.platform) platform = metadata.platform\n if (metadata.testId) {\n testId = metadata.testId\n } else {\n testId = generateTestId()\n content = `test-id: ${testId}\\n${content}`\n await writeFile(record.absolutePath, content, 'utf-8')\n }\n } catch { /* fall back to filename */ }\n files.push({\n path: record.workspaceRelativePath,\n name: testName,\n testId,\n targetName,\n platform,\n modified: s.mtime.toISOString(),\n })\n }\n } catch {\n // skip inaccessible files\n }\n }\n\n files.sort((a, b) => b.modified.localeCompare(a.modified))\n return files\n }\n\n async read(relativePath: string): Promise<string> {\n const target = await this.resolveTarget(relativePath, true)\n return readFile(target.absolutePath, 'utf-8')\n }\n\n async findByTestId(testId: string): Promise<{ path: string; content: string } | null> {\n const files = await this.list()\n const match = files.find(f => f.testId === testId)\n if (!match) return null\n const content = await this.read(match.path)\n return { path: match.path, content }\n }\n\n async write(relativePath: string, content: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, false)\n await mkdir(dirname(target.absolutePath), { recursive: true })\n await writeFile(target.absolutePath, content, 'utf-8')\n }\n\n async delete(relativePath: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, true)\n await rm(target.absolutePath)\n }\n\n async validate(content: string): Promise<TestValidationResult> {\n try {\n const { parseTestFile } = await import('@vostride/agent-qa-core')\n const result = parseTestFile(content, '<editor>')\n\n if (result.errors.length === 0) {\n return { valid: true, errors: [] }\n }\n\n return {\n valid: false,\n errors: result.errors.map(e => ({\n message: e.message,\n line: e.line,\n column: e.column,\n suggestion: e.suggestion,\n })),\n }\n } catch (err) {\n return {\n valid: false,\n errors: [{ message: err instanceof Error ? err.message : 'Failed to validate' }],\n }\n }\n }\n\n private async resolveTarget(relativePath: string, requireExisting: boolean) {\n return resolveWorkspaceFileTarget({\n workspace: this.workspace,\n kind: 'test',\n filePath: relativePath,\n requireExisting,\n })\n }\n}\n","import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, relative, resolve } from 'node:path'\n\nimport { HooksFileSchema, isPathInsideDir, parseHooksFile, resolveWorkspacePaths } from '@vostride/agent-qa-core'\nimport type { AgentQaConfig, HooksFileConfig } from '@vostride/agent-qa-core'\nimport { generateHookId } from '@vostride/agent-qa-ids'\nimport { parse as parseYaml, parseDocument } from 'yaml'\n\nimport type { ConfigManager } from '../config/config-manager.js'\nimport type {\n HookCatalogResponse,\n HookCatalogRow,\n HookDeleteResult,\n HookDetailResponse,\n HookDraftValidationResult,\n HookFieldError,\n HookFieldName,\n HookMutationRequest,\n HookPrepareResult,\n HookRegistryReadError,\n} from './hook-registry-types.js'\nimport { scanHookReferences } from './hook-reference-scan.js'\n\ntype ParsedHookDefinition = HooksFileConfig['hooks'][number]\ntype AuthoredHookDefinition = Omit<ParsedHookDefinition, 'timeout'> & {\n timeout: string\n}\ntype HooksFileParseData = { hooks: ParsedHookDefinition[] }\ntype ZodIssueLike = { path: PropertyKey[]; message: string }\n\ninterface HookRegistryLocation {\n filePath: string\n resolvedFilePath: string\n hooksBaseDir: string\n}\n\ninterface HookRegistryState extends HookRegistryLocation {\n hooks: ParsedHookDefinition[]\n errors: HookRegistryReadError[]\n missing: boolean\n}\n\ninterface HookRegistryMutationState extends HookRegistryLocation {\n hooks: AuthoredHookDefinition[]\n raw: string | null\n existed: boolean\n}\n\ninterface HookFileState {\n resolvedFilePath: string | null\n fileMissing: boolean\n fieldErrors: HookFieldError[]\n}\n\ninterface HookMutationResolvedPayload {\n hook: Record<string, unknown> & { id: string }\n source: string\n}\n\ninterface HookMutationPlan {\n nextHook: ParsedHookDefinition\n nextSourcePath: string\n oldSourcePath: string | null\n oldSourceContent: string | null\n oldSourceExisted: boolean\n removeOldSourcePath: boolean\n projectedHooks: AuthoredHookDefinition[]\n}\n\nclass HookRegistryMutationError extends Error {\n readonly code: string\n readonly fieldErrors: HookFieldError[]\n\n constructor(code: string, fieldErrors: HookFieldError[], message = code) {\n super(message)\n this.code = code\n this.fieldErrors = fieldErrors\n }\n}\n\nexport function isHookRegistryMutationError(error: unknown): error is {\n code: string\n fieldErrors: HookFieldError[]\n} {\n return error instanceof HookRegistryMutationError\n}\n\nexport class HookRegistryManager {\n constructor(\n private readonly configManager: ConfigManager,\n private readonly configPath: string,\n ) {}\n\n async readCatalog(): Promise<HookCatalogResponse> {\n const registry = await this.readRegistryState()\n if (registry.missing || registry.errors.length > 0) {\n return {\n hooks: [],\n filePath: registry.filePath,\n errors: registry.errors.map((error) => error.message),\n missing: registry.missing,\n }\n }\n\n const hooks = await Promise.all(\n registry.hooks.map(async (hook) => {\n const fileState = await this.inspectHookFile(hook.file, registry.hooksBaseDir)\n return this.toCatalogRow(hook, fileState.fileMissing)\n }),\n )\n\n return {\n hooks,\n filePath: registry.filePath,\n errors: [],\n missing: false,\n }\n }\n\n async readHook(hookId: string): Promise<HookDetailResponse | null> {\n const registry = await this.readRegistryState()\n if (registry.missing || registry.errors.length > 0) {\n return null\n }\n\n const hook = registry.hooks.find((candidate) => candidate.id === hookId)\n if (!hook) {\n return null\n }\n\n const fileState = await this.inspectHookFile(hook.file, registry.hooksBaseDir)\n let source: string | null = null\n\n if (fileState.resolvedFilePath && fileState.fieldErrors.length === 0) {\n source = await readFile(fileState.resolvedFilePath, 'utf-8')\n }\n\n return {\n hook: this.toCatalogRow(hook, fileState.fileMissing),\n source,\n fieldErrors: fileState.fieldErrors,\n }\n }\n\n async createHook(payload: HookMutationRequest): Promise<HookDetailResponse> {\n const registry = await this.readRegistryForMutation()\n const resolvedPayload = this.resolveMutationPayload(payload, {\n generatedId: generateHookId(),\n })\n const plan = await this.planHookMutation(registry, resolvedPayload.hook.id, resolvedPayload, 'create')\n\n await this.persistHookMutation(registry, plan, resolvedPayload.source)\n\n return {\n hook: this.toCatalogRow(plan.nextHook, false),\n source: resolvedPayload.source,\n fieldErrors: [],\n }\n }\n\n async updateHook(hookId: string, payload: HookMutationRequest): Promise<HookDetailResponse> {\n const registry = await this.readRegistryForMutation()\n const existingHook = registry.hooks.find((candidate) => candidate.id === hookId)\n if (!existingHook) {\n throw new HookRegistryMutationError('hook_not_found', [\n {\n field: 'id',\n code: 'hook_not_found',\n message: 'Hook not found',\n },\n ])\n }\n\n const resolvedPayload = this.resolveMutationPayload(payload, {\n expectedId: hookId,\n generatedId: hookId,\n })\n const plan = await this.planHookMutation(registry, hookId, resolvedPayload, 'update')\n\n await this.persistHookMutation(registry, plan, resolvedPayload.source)\n\n return {\n hook: this.toCatalogRow(plan.nextHook, false),\n source: resolvedPayload.source,\n fieldErrors: [],\n }\n }\n\n async deleteHook(\n hookId: string,\n options: { force?: boolean } = {},\n ): Promise<HookDeleteResult> {\n const registry = await this.readRegistryForMutation()\n const existingHook = registry.hooks.find((candidate) => candidate.id === hookId)\n if (!existingHook) {\n throw new HookRegistryMutationError('hook_not_found', [\n {\n field: 'id',\n code: 'hook_not_found',\n message: 'Hook not found',\n },\n ])\n }\n\n const references = await scanHookReferences(dirname(this.configPath), this.configPath, hookId)\n if (references.length > 0 && !options.force) {\n return {\n deleted: false,\n references,\n }\n }\n\n const nextHooks = registry.hooks.filter((candidate) => candidate.id !== hookId)\n const nextRegistryContent = nextHooks.length > 0\n ? this.serializeHooksDocument(registry.raw, nextHooks)\n : null\n const sourcePath = resolve(registry.hooksBaseDir, existingHook.file)\n const sourceSnapshot = await this.readOptionalFile(sourcePath)\n const sourcePathStillReferenced = nextHooks.some(\n (candidate) => resolve(registry.hooksBaseDir, candidate.file) === sourcePath,\n )\n\n try {\n if (nextRegistryContent === null) {\n await rm(registry.resolvedFilePath, { force: true })\n } else {\n await mkdir(dirname(registry.resolvedFilePath), { recursive: true })\n await writeFile(registry.resolvedFilePath, nextRegistryContent, 'utf-8')\n }\n\n if (sourceSnapshot.exists && !sourcePathStillReferenced) {\n await rm(sourcePath, { force: true })\n }\n\n return {\n deleted: true,\n references,\n }\n } catch (error) {\n await this.restoreRegistrySnapshot(registry)\n\n if (sourceSnapshot.exists && sourceSnapshot.content !== null) {\n await mkdir(dirname(sourcePath), { recursive: true })\n await writeFile(sourcePath, sourceSnapshot.content, 'utf-8')\n }\n\n throw error\n }\n }\n\n async validateDraft(draft: unknown): Promise<HookDraftValidationResult> {\n const location = await this.resolveRegistryLocation()\n const normalizedDraft = this.normalizeDraftForSchema(draft)\n const result = HooksFileSchema.safeParse(normalizedDraft)\n\n if (!result.success) {\n return {\n valid: false,\n fieldErrors: result.error.issues.map((issue: ZodIssueLike) => this.toValidationFieldError(issue.path, issue.message)),\n warnings: [],\n }\n }\n const hooksFile = result.data as HooksFileParseData\n\n const fieldErrors: HookFieldError[] = []\n const warnings: HookFieldError[] = []\n\n for (const hook of hooksFile.hooks) {\n if (isAbsolute(hook.file)) {\n fieldErrors.push({\n field: 'file',\n code: 'absolute_path',\n message: 'Hook file must be relative to the configured hooks file',\n })\n continue\n }\n\n if (!isPathInsideDir(hook.file, location.hooksBaseDir)) {\n fieldErrors.push({\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n })\n continue\n }\n\n const fileState = await this.inspectHookFile(hook.file, location.hooksBaseDir)\n warnings.push(...fileState.fieldErrors.filter((error) => error.code === 'file_missing'))\n }\n\n return {\n valid: fieldErrors.length === 0,\n fieldErrors,\n warnings,\n }\n }\n\n async prepareForExecution(): Promise<HookPrepareResult> {\n const registry = await this.readRegistryState()\n if (registry.missing) {\n return {\n resolvedHooks: new Map(),\n authoringIssuesById: new Map(),\n }\n }\n\n if (registry.errors.length > 0) {\n return {\n resolvedHooks: new Map(),\n hookRegistryError: registry.errors.map((error) => error.message).join('; '),\n authoringIssuesById: new Map(),\n }\n }\n\n const parsedHooks = await parseHooksFile(registry.resolvedFilePath)\n if (parsedHooks.errors.length > 0) {\n return {\n resolvedHooks: new Map(),\n hookRegistryError: parsedHooks.errors.join('; '),\n authoringIssuesById: new Map(),\n }\n }\n\n const resolvedHooksById = new Map(parsedHooks.hooks.map((hook) => [hook.id, hook]))\n const resolvedHooks = new Map<typeof resolvedHooksById extends Map<infer K, infer V> ? K : never, typeof resolvedHooksById extends Map<infer K, infer V> ? V : never>()\n const authoringIssuesById = new Map<string, HookFieldError[]>()\n\n for (const hook of registry.hooks) {\n const fileState = await this.inspectHookFile(hook.file, registry.hooksBaseDir)\n const resolvedHook = resolvedHooksById.get(hook.id)\n if (!resolvedHook) {\n continue\n }\n\n if (fileState.fieldErrors.length > 0) {\n authoringIssuesById.set(hook.id, fileState.fieldErrors)\n continue\n }\n\n resolvedHooks.set(hook.id, resolvedHook)\n }\n\n return {\n resolvedHooks,\n authoringIssuesById,\n }\n }\n\n private async readRegistryForMutation(): Promise<HookRegistryMutationState> {\n const location = await this.resolveRegistryLocation()\n\n let raw: string | null = null\n try {\n raw = await readFile(location.resolvedFilePath, 'utf-8')\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n ...location,\n hooks: [],\n raw: null,\n existed: false,\n }\n }\n throw error\n }\n\n let parsed: unknown\n try {\n parsed = parseYaml(raw)\n } catch (error: unknown) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_registry',\n message: `Invalid YAML in hooks file: ${(error as Error).message}`,\n },\n ])\n }\n\n const result = HooksFileSchema.safeParse(parsed)\n if (!result.success) {\n throw new HookRegistryMutationError(\n 'validation_failed',\n result.error.issues.map((issue: ZodIssueLike) => this.toValidationFieldError(issue.path, issue.message)),\n )\n }\n\n const hooksFile = result.data as HooksFileParseData\n const pathErrors = hooksFile.hooks.flatMap((hook, index) => {\n const error = this.getAuthoredPathReadError(hook.file, location.hooksBaseDir, index)\n return error ? [this.toMutationFieldError(error)] : []\n })\n if (pathErrors.length > 0) {\n throw new HookRegistryMutationError('validation_failed', pathErrors)\n }\n\n return {\n ...location,\n hooks: this.toAuthoredHookDefinitions(parsed, hooksFile.hooks),\n raw,\n existed: true,\n }\n }\n\n private resolveMutationPayload(\n payload: HookMutationRequest,\n options: { expectedId?: string; generatedId: string },\n ): HookMutationResolvedPayload {\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_payload',\n message: 'Hook mutation payload is required',\n },\n ])\n }\n\n if (typeof payload.source !== 'string') {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_source',\n message: 'Hook source must be a string',\n },\n ])\n }\n\n const hookValue = payload.hook\n if (!hookValue || typeof hookValue !== 'object' || Array.isArray(hookValue)) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_hook',\n message: 'Hook payload is required',\n },\n ])\n }\n\n const providedId = typeof hookValue.id === 'string' && hookValue.id.trim().length > 0\n ? hookValue.id.trim()\n : undefined\n if (options.expectedId && providedId && providedId !== options.expectedId) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'id',\n code: 'id_mismatch',\n message: 'Hook id in body must match the route parameter',\n },\n ])\n }\n\n return {\n hook: {\n id: providedId ?? options.generatedId,\n name: hookValue.name as string,\n runtime: hookValue.runtime as ParsedHookDefinition['runtime'],\n file: hookValue.file as string,\n timeout: hookValue.timeout as string | number,\n network: hookValue.network as boolean | undefined,\n },\n source: payload.source,\n }\n }\n\n private async planHookMutation(\n registry: HookRegistryMutationState,\n hookId: string,\n payload: HookMutationResolvedPayload,\n mode: 'create' | 'update',\n ): Promise<HookMutationPlan> {\n const existingHook = mode === 'update'\n ? registry.hooks.find((candidate) => candidate.id === hookId) ?? null\n : null\n\n const projectedHooks: Array<Record<string, unknown> | AuthoredHookDefinition> = mode === 'update'\n ? [...registry.hooks.filter((candidate) => candidate.id !== hookId), payload.hook]\n : [...registry.hooks, payload.hook]\n const validated = this.validateProjectedHooks(projectedHooks, registry.hooksBaseDir)\n if (!validated.valid) {\n throw new HookRegistryMutationError('validation_failed', validated.fieldErrors)\n }\n\n const nextHook = validated.parsedHooks.find((candidate) => candidate.id === payload.hook.id)\n if (!nextHook) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_registry',\n message: 'Hook could not be projected into the configured hooks file',\n },\n ])\n }\n\n const nextSourcePath = resolve(registry.hooksBaseDir, nextHook.file)\n const oldSourcePath = existingHook ? resolve(registry.hooksBaseDir, existingHook.file) : null\n const oldSourceSnapshot = existingHook && oldSourcePath\n ? await this.readOptionalFile(oldSourcePath)\n : { exists: false, content: null as string | null }\n\n if (mode === 'create') {\n const nextExists = await this.readOptionalFile(nextSourcePath)\n if (nextExists.exists) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'file',\n code: 'collision',\n message: 'Hook file already exists at that path',\n },\n ])\n }\n }\n\n if (mode === 'update' && oldSourcePath !== nextSourcePath) {\n const nextExists = await this.readOptionalFile(nextSourcePath)\n if (nextExists.exists) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'file',\n code: 'collision',\n message: 'Hook file already exists at that path',\n },\n ])\n }\n }\n\n return {\n nextHook,\n nextSourcePath,\n oldSourcePath,\n oldSourceContent: oldSourceSnapshot.content,\n oldSourceExisted: oldSourceSnapshot.exists,\n removeOldSourcePath: Boolean(\n oldSourcePath &&\n oldSourcePath !== nextSourcePath &&\n oldSourceSnapshot.exists &&\n !validated.authoredHooks.some(\n (candidate) =>\n candidate.id !== hookId &&\n resolve(registry.hooksBaseDir, candidate.file) === oldSourcePath,\n ),\n ),\n projectedHooks: validated.authoredHooks,\n }\n }\n\n private validateProjectedHooks(\n hooks: Array<Record<string, unknown> | AuthoredHookDefinition>,\n hooksBaseDir: string,\n ): {\n valid: boolean\n parsedHooks: ParsedHookDefinition[]\n authoredHooks: AuthoredHookDefinition[]\n fieldErrors: HookFieldError[]\n } {\n const rawFieldErrors = this.collectRawHookFieldErrors(hooks, hooksBaseDir)\n const normalizedDraft = this.normalizeDraftForSchema({ hooks })\n const result = HooksFileSchema.safeParse(normalizedDraft)\n\n if (!result.success) {\n return {\n valid: false,\n parsedHooks: [],\n authoredHooks: [],\n fieldErrors: this.dedupeFieldErrors([\n ...rawFieldErrors,\n ...result.error.issues.map((issue: ZodIssueLike) => this.toValidationFieldError(issue.path, issue.message)),\n ]),\n }\n }\n\n const hooksFile = result.data as HooksFileParseData\n const pathErrors = hooksFile.hooks.flatMap((hook, index) => {\n const error = this.getAuthoredPathReadError(hook.file, hooksBaseDir, index)\n return error ? [this.toMutationFieldError(error)] : []\n })\n\n return {\n valid: pathErrors.length === 0,\n parsedHooks: hooksFile.hooks,\n authoredHooks: this.toAuthoredHookDefinitions({ hooks }, hooksFile.hooks),\n fieldErrors: this.dedupeFieldErrors([\n ...rawFieldErrors,\n ...pathErrors,\n ]),\n }\n }\n\n private async persistHookMutation(\n registry: HookRegistryMutationState,\n plan: HookMutationPlan,\n source: string,\n ): Promise<void> {\n const nextRegistryContent = this.serializeHooksDocument(registry.raw, plan.projectedHooks)\n\n try {\n await mkdir(dirname(plan.nextSourcePath), { recursive: true })\n await writeFile(plan.nextSourcePath, source, 'utf-8')\n await mkdir(dirname(registry.resolvedFilePath), { recursive: true })\n await writeFile(registry.resolvedFilePath, nextRegistryContent, 'utf-8')\n\n if (plan.removeOldSourcePath && plan.oldSourcePath) {\n await rm(plan.oldSourcePath)\n }\n } catch (error) {\n await this.restoreRegistrySnapshot(registry)\n await this.restoreSourceSnapshot(plan)\n throw error\n }\n }\n\n private async restoreRegistrySnapshot(registry: HookRegistryMutationState): Promise<void> {\n if (!registry.existed || registry.raw === null) {\n await rm(registry.resolvedFilePath, { force: true })\n return\n }\n\n await writeFile(registry.resolvedFilePath, registry.raw, 'utf-8')\n }\n\n private async restoreSourceSnapshot(plan: HookMutationPlan): Promise<void> {\n if (plan.oldSourcePath === plan.nextSourcePath) {\n if (plan.oldSourceExisted && plan.oldSourceContent !== null) {\n await mkdir(dirname(plan.nextSourcePath), { recursive: true })\n await writeFile(plan.nextSourcePath, plan.oldSourceContent, 'utf-8')\n return\n }\n\n await rm(plan.nextSourcePath, { force: true })\n return\n }\n\n await rm(plan.nextSourcePath, { force: true })\n }\n\n private serializeHooksDocument(\n raw: string | null,\n hooks: AuthoredHookDefinition[],\n ): string {\n const doc = parseDocument(raw ?? '{}')\n doc.setIn(['hooks'], doc.createNode(hooks))\n return doc.toString()\n }\n\n private async readOptionalFile(path: string): Promise<{ exists: boolean; content: string | null }> {\n try {\n return {\n exists: true,\n content: await readFile(path, 'utf-8'),\n }\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n exists: false,\n content: null,\n }\n }\n throw error\n }\n }\n\n private collectRawHookFieldErrors(\n hooks: Array<Record<string, unknown> | AuthoredHookDefinition>,\n hooksBaseDir: string,\n ): HookFieldError[] {\n const fieldErrors: HookFieldError[] = []\n const ids = new Set<string>()\n const names = new Set<string>()\n\n for (const hook of hooks) {\n if (!hook || typeof hook !== 'object' || Array.isArray(hook)) {\n continue\n }\n\n const hookRecord = hook as Record<string, unknown>\n if (typeof hookRecord.id === 'string') {\n if (ids.has(hookRecord.id)) {\n fieldErrors.push({\n field: 'id',\n code: 'duplicate_id',\n message: `Duplicate hook id: \"${hookRecord.id}\"`,\n })\n } else {\n ids.add(hookRecord.id)\n }\n }\n\n if (typeof hookRecord.name === 'string') {\n if (names.has(hookRecord.name)) {\n fieldErrors.push({\n field: 'name',\n code: 'duplicate_name',\n message: `Duplicate hook name: \"${hookRecord.name}\"`,\n })\n } else {\n names.add(hookRecord.name)\n }\n }\n\n if (typeof hookRecord.file === 'string') {\n if (isAbsolute(hookRecord.file)) {\n fieldErrors.push({\n field: 'file',\n code: 'absolute_path',\n message: 'Hook file must be relative to the configured hooks file',\n })\n } else if (!isPathInsideDir(hookRecord.file, hooksBaseDir)) {\n fieldErrors.push({\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n })\n }\n }\n }\n\n return fieldErrors\n }\n\n private dedupeFieldErrors(fieldErrors: HookFieldError[]): HookFieldError[] {\n const seen = new Set<string>()\n return fieldErrors.filter((error) => {\n const key = `${error.field}:${error.code}:${error.message}`\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n }\n\n private async readRegistryState(): Promise<HookRegistryState> {\n const location = await this.resolveRegistryLocation()\n\n try {\n await stat(location.resolvedFilePath)\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n ...location,\n hooks: [],\n errors: [{ code: 'hooks_file_missing', message: `configured hooks file not found: ${location.filePath}` }],\n missing: true,\n }\n }\n throw err\n }\n\n const raw = await readFile(location.resolvedFilePath, 'utf-8')\n\n let parsed: unknown\n try {\n parsed = parseYaml(raw)\n } catch (err: unknown) {\n return {\n ...location,\n hooks: [],\n errors: [{ code: 'invalid_yaml', message: `Invalid YAML in hooks file: ${(err as Error).message}` }],\n missing: false,\n }\n }\n\n const result = HooksFileSchema.safeParse(parsed)\n if (!result.success) {\n return {\n ...location,\n hooks: [],\n errors: result.error.issues.map((issue: ZodIssueLike) => ({\n code: 'invalid_registry',\n message: `${issue.path.map(String).join('.')}: ${issue.message}`,\n })),\n missing: false,\n }\n }\n\n const hooksFile = result.data as HooksFileParseData\n const pathErrors = hooksFile.hooks\n .map((hook, index) => this.getAuthoredPathReadError(hook.file, location.hooksBaseDir, index))\n .filter((error): error is HookRegistryReadError => error !== null)\n\n if (pathErrors.length > 0) {\n return {\n ...location,\n hooks: [],\n errors: pathErrors,\n missing: false,\n }\n }\n\n return {\n ...location,\n hooks: hooksFile.hooks,\n errors: [],\n missing: false,\n }\n }\n\n private async resolveRegistryLocation(): Promise<HookRegistryLocation> {\n const config = await this.configManager.read() as AgentQaConfig\n const workspacePaths = resolveWorkspacePaths({ config, configPath: this.configPath })\n const configuredPath = workspacePaths.hooksFile.configuredPath\n const resolvedFilePath = workspacePaths.hooksFile.absolutePath\n\n return {\n filePath: this.toDisplayPath(configuredPath, resolvedFilePath),\n resolvedFilePath,\n hooksBaseDir: dirname(resolvedFilePath),\n }\n }\n\n private getAuthoredPathReadError(filePath: string, hooksBaseDir: string, index: number): HookRegistryReadError | null {\n if (isAbsolute(filePath)) {\n return {\n code: 'absolute_path',\n message: `hooks.${index}.file: Hook file must be relative to the configured hooks file`,\n }\n }\n\n if (!isPathInsideDir(filePath, hooksBaseDir)) {\n return {\n code: 'unsafe_path',\n message: `hooks.${index}.file: Hook file must stay inside the configured hooks file directory`,\n }\n }\n\n return null\n }\n\n private async inspectHookFile(filePath: string, hooksBaseDir: string): Promise<HookFileState> {\n if (isAbsolute(filePath) || !isPathInsideDir(filePath, hooksBaseDir)) {\n return {\n resolvedFilePath: null,\n fileMissing: true,\n fieldErrors: [\n {\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n },\n ],\n }\n }\n\n const resolvedFilePath = resolve(hooksBaseDir, filePath)\n try {\n await stat(resolvedFilePath)\n return {\n resolvedFilePath,\n fileMissing: false,\n fieldErrors: [],\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n resolvedFilePath: null,\n fileMissing: true,\n fieldErrors: [\n {\n field: 'file',\n code: 'file_missing',\n message: 'Hook file missing',\n },\n ],\n }\n }\n throw err\n }\n }\n\n private normalizeDraftForSchema(draft: unknown): unknown {\n const rawHooks = this.getRawHooksFromDraft(draft)\n if (rawHooks === null) {\n return draft\n }\n\n return {\n ...(draft as Record<string, unknown>),\n hooks: rawHooks.map((hook) => {\n if (!hook || typeof hook !== 'object' || Array.isArray(hook)) {\n return hook\n }\n\n const hookRecord = hook as Record<string, unknown>\n return {\n ...hookRecord,\n timeout: this.normalizeTimeoutValue(hookRecord.timeout),\n }\n }),\n }\n }\n\n private toAuthoredHookDefinitions(\n draft: unknown,\n parsedHooks: ParsedHookDefinition[],\n ): AuthoredHookDefinition[] {\n const rawHooks = this.getRawHooksFromDraft(draft) ?? []\n return parsedHooks.map((hook, index) => this.toAuthoredHookDefinition(rawHooks[index], hook))\n }\n\n private toAuthoredHookDefinition(\n rawHook: unknown,\n parsedHook: ParsedHookDefinition,\n ): AuthoredHookDefinition {\n const rawTimeout = rawHook && typeof rawHook === 'object' && !Array.isArray(rawHook)\n ? (rawHook as Record<string, unknown>).timeout\n : parsedHook.timeout\n const normalizedTimeout = this.normalizeTimeoutValue(rawTimeout)\n\n return {\n ...parsedHook,\n timeout: typeof normalizedTimeout === 'string'\n ? normalizedTimeout\n : this.formatDurationToken(parsedHook.timeout),\n }\n }\n\n private getRawHooksFromDraft(draft: unknown): unknown[] | null {\n if (!draft || typeof draft !== 'object' || Array.isArray(draft)) {\n return null\n }\n\n const hooks = (draft as { hooks?: unknown }).hooks\n return Array.isArray(hooks) ? hooks : null\n }\n\n private normalizeTimeoutValue(timeout: unknown): unknown {\n if (typeof timeout === 'number') {\n return this.formatDurationToken(timeout)\n }\n\n if (typeof timeout !== 'string') {\n return timeout\n }\n\n const trimmedTimeout = timeout.trim()\n if (trimmedTimeout.length === 0) {\n return trimmedTimeout\n }\n\n if (/^\\d+$/.test(trimmedTimeout)) {\n return this.formatDurationToken(Number.parseInt(trimmedTimeout, 10))\n }\n\n const millisecondTimeout = trimmedTimeout.match(/^(\\d+)ms$/i)\n if (millisecondTimeout) {\n return this.formatDurationToken(Number.parseInt(millisecondTimeout[1], 10))\n }\n\n return trimmedTimeout\n }\n\n private formatDurationToken(durationMs: number): string {\n if (!Number.isFinite(durationMs) || durationMs < 0) {\n return `${durationMs}`\n }\n\n if (durationMs === 0) {\n return '0ms'\n }\n\n const durationUnits = [\n { suffix: 'd', value: 86_400_000 },\n { suffix: 'h', value: 3_600_000 },\n { suffix: 'm', value: 60_000 },\n { suffix: 's', value: 1_000 },\n ] as const\n\n for (const unit of durationUnits) {\n if (durationMs % unit.value === 0) {\n return `${durationMs / unit.value}${unit.suffix}`\n }\n }\n\n return `${durationMs}ms`\n }\n\n private toValidationFieldError(path: PropertyKey[], message: string): HookFieldError {\n const field = this.getFieldName(path)\n\n if (field === 'id' && message.includes('Duplicate hook id')) {\n return { field, code: 'duplicate_id', message }\n }\n\n if (field === 'name' && message.includes('Duplicate hook name')) {\n return { field, code: 'duplicate_name', message }\n }\n\n if (field === 'runtime') {\n return { field, code: 'invalid_runtime', message }\n }\n\n if (field === 'timeout') {\n return { field, code: 'invalid_timeout', message }\n }\n\n if (field === 'network') {\n return { field, code: 'invalid_network', message }\n }\n\n if (field === 'file') {\n return { field, code: 'invalid_file', message }\n }\n\n if (field === 'id') {\n return { field, code: 'invalid_id', message }\n }\n\n if (field === 'name') {\n return { field, code: 'invalid_name', message }\n }\n\n return { field, code: 'invalid_registry', message }\n }\n\n private toMutationFieldError(error: HookRegistryReadError): HookFieldError {\n if (error.code === 'absolute_path') {\n return {\n field: 'file',\n code: 'absolute_path',\n message: 'Hook file must be relative to the configured hooks file',\n }\n }\n\n if (error.code === 'unsafe_path') {\n return {\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n }\n }\n\n return {\n field: 'registry',\n code: error.code,\n message: error.message,\n }\n }\n\n private getFieldName(path: PropertyKey[]): HookFieldName {\n const field = path[path.length - 1]\n if (\n field === 'id' ||\n field === 'name' ||\n field === 'runtime' ||\n field === 'file' ||\n field === 'timeout' ||\n field === 'network'\n ) {\n return field\n }\n\n return 'registry'\n }\n\n private toCatalogRow(hook: ParsedHookDefinition, fileMissing: boolean): HookCatalogRow {\n return {\n id: hook.id,\n name: hook.name,\n runtime: hook.runtime,\n file: hook.file,\n timeout: hook.timeout,\n network: hook.network,\n fileMissing,\n }\n }\n\n private toDisplayPath(configuredPath: string, resolvedFilePath: string): string {\n if (!isAbsolute(configuredPath)) {\n return configuredPath\n }\n\n const relativeToConfig = relative(dirname(this.configPath), resolvedFilePath)\n if (relativeToConfig && !relativeToConfig.startsWith('..') && !isAbsolute(relativeToConfig)) {\n return relativeToConfig.startsWith('.') ? relativeToConfig : `./${relativeToConfig}`\n }\n\n return `./${basename(resolvedFilePath)}`\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { basename } from 'node:path'\n\nimport {\n AgentQaConfigSchema,\n discoverWorkspaceFiles,\n resolveWorkspacePaths,\n type WorkspaceFileRecord,\n} from '@vostride/agent-qa-core'\nimport { parse as parseYaml } from 'yaml'\n\nimport type { HookDeleteReference } from './hook-registry-types.js'\n\nconst HOOK_INLINE_RE = /\\{\\{runHook:\"([^\"]+)\"\\}\\}/g\n\nfunction getLabel(parsed: unknown, filePath: string): string {\n if (parsed && typeof parsed === 'object' && typeof (parsed as { name?: unknown }).name === 'string') {\n const name = (parsed as { name: string }).name.trim()\n if (name.length > 0) {\n return name\n }\n }\n\n return basename(filePath)\n}\n\nfunction collectHookListReferences(\n parsed: Record<string, unknown>,\n filePath: string,\n label: string,\n kind: 'test' | 'suite',\n key: 'setup' | 'teardown',\n hookId: string,\n): HookDeleteReference[] {\n const entries = parsed[key]\n if (!Array.isArray(entries)) {\n return []\n }\n\n return entries.flatMap((entry) => {\n if (entry !== hookId) {\n return []\n }\n\n return [{\n kind,\n label,\n path: filePath,\n context: key,\n }]\n })\n}\n\nfunction collectInlineReferences(\n parsed: Record<string, unknown>,\n filePath: string,\n label: string,\n hookId: string,\n): HookDeleteReference[] {\n const steps = parsed.steps\n if (!Array.isArray(steps)) {\n return []\n }\n\n return steps.flatMap((entry, index) => {\n const text = typeof entry === 'string'\n ? entry\n : entry && typeof entry === 'object' && typeof (entry as { step?: unknown }).step === 'string'\n ? (entry as { step: string }).step\n : null\n\n if (!text) {\n return []\n }\n\n const matches = [...text.matchAll(HOOK_INLINE_RE)]\n if (!matches.some((match) => match[1] === hookId)) {\n return []\n }\n\n return [{\n kind: 'inline-runHook',\n label,\n path: filePath,\n context: typeof entry === 'string' ? `steps[${index}]` : `steps[${index}].step`,\n }]\n })\n}\n\nasync function scanYamlFile(\n record: WorkspaceFileRecord,\n hookId: string,\n): Promise<HookDeleteReference[]> {\n let parsed: unknown\n\n try {\n parsed = parseYaml(await readFile(record.absolutePath, 'utf-8'))\n } catch {\n return []\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return []\n }\n\n const parsedRecord = parsed as Record<string, unknown>\n const label = getLabel(parsed, record.workspaceRelativePath)\n const kind = record.kind\n\n return [\n ...collectHookListReferences(parsedRecord, record.workspaceRelativePath, label, kind, 'setup', hookId),\n ...collectHookListReferences(parsedRecord, record.workspaceRelativePath, label, kind, 'teardown', hookId),\n ...collectInlineReferences(parsedRecord, record.workspaceRelativePath, label, hookId),\n ]\n}\n\nfunction dedupeReferences(references: HookDeleteReference[]): HookDeleteReference[] {\n const seen = new Set<string>()\n\n return references.filter((reference) => {\n const key = `${reference.kind}:${reference.path}:${reference.context}:${reference.label}`\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\nexport async function scanHookReferences(\n _workspaceDir: string,\n configPath: string,\n hookId: string,\n): Promise<HookDeleteReference[]> {\n let parsedConfig: unknown\n\n try {\n parsedConfig = parseYaml(await readFile(configPath, 'utf-8'))\n } catch {\n return []\n }\n\n const configResult = AgentQaConfigSchema.safeParse(parsedConfig)\n if (!configResult.success) {\n return []\n }\n\n const workspace = resolveWorkspacePaths({ config: configResult.data, configPath })\n const records = await Promise.all([\n discoverWorkspaceFiles({ workspace, kind: 'test' }),\n discoverWorkspaceFiles({ workspace, kind: 'suite' }),\n ])\n const references = await Promise.all(\n records\n .flat()\n .sort((left, right) => left.workspaceRelativePath.localeCompare(right.workspaceRelativePath))\n .map((record) => scanYamlFile(record, hookId)),\n )\n\n return dedupeReferences(references.flat()).sort((left, right) =>\n left.path.localeCompare(right.path) ||\n left.context.localeCompare(right.context) ||\n left.kind.localeCompare(right.kind) ||\n left.label.localeCompare(right.label),\n )\n}\n","import type { IncomingMessage } from 'node:http'\n\nconst DEFAULT_MAX_BYTES = 1024 * 1024 // 1MB\n\nexport function readJsonBody<T>(req: IncomingMessage, maxBytes = DEFAULT_MAX_BYTES): Promise<T> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let totalBytes = 0\n\n req.on('data', (chunk: Buffer) => {\n totalBytes += chunk.length\n if (totalBytes > maxBytes) {\n req.destroy()\n reject(new Error(`Body exceeds maximum size of ${maxBytes} bytes`))\n return\n }\n chunks.push(chunk)\n })\n\n req.on('end', () => {\n const body = Buffer.concat(chunks).toString('utf-8')\n if (!body) {\n reject(new Error('Empty request body'))\n return\n }\n try {\n resolve(JSON.parse(body) as T)\n } catch {\n reject(new Error('Invalid JSON in request body'))\n }\n })\n\n req.on('error', (err) => {\n reject(err)\n })\n })\n}\n","import { EventEmitter } from 'node:events'\nimport { spawn, execSync, type ChildProcess } from 'node:child_process'\nimport treeKill from 'tree-kill'\nimport type { ExecutionBackend, ExecuteOptions } from './execution-backend.js'\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 10_000\nconst DEFAULT_STALE_THRESHOLD_MS = 30_000\nconst PROCESS_TERMINATION_GRACE_MS = 5_000\nconst HANDLE_RETENTION_MS = 5 * 60 * 1000\n\nexport interface LiveExecutionEvent {\n id: number\n type: string\n [key: string]: unknown\n}\n\nexport interface TestRunHandle {\n runId: string\n process: ChildProcess\n status: 'running' | 'completed' | 'failed' | 'cancelled' | 'timeout'\n output: string[]\n startedAt: Date\n lastEventAt: number\n completionReason?: string\n}\n\nexport class TestRunner extends EventEmitter implements ExecutionBackend {\n private cliBin: string\n private defaultTimeout: number | undefined\n private handles = new Map<string, TestRunHandle>()\n private eventBuffers = new Map<string, LiveExecutionEvent[]>()\n private eventCounters = new Map<string, number>()\n private onProcessClose?: (runId: string, status: 'completed' | 'failed' | 'cancelled' | 'timeout') => void\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null\n private heartbeatIntervalMs: number\n private staleThresholdMs: number\n\n constructor(opts: {\n cliBin: string\n defaultTimeout?: number\n onProcessClose?: (runId: string, status: 'completed' | 'failed' | 'cancelled' | 'timeout') => void\n heartbeatIntervalMs?: number\n staleThresholdMs?: number\n }) {\n super()\n this.cliBin = opts.cliBin\n this.defaultTimeout = opts.defaultTimeout\n this.onProcessClose = opts.onProcessClose\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS\n this.staleThresholdMs = Math.max(\n opts.staleThresholdMs ?? DEFAULT_STALE_THRESHOLD_MS,\n this.heartbeatIntervalMs + 1,\n )\n }\n\n static resolveCliBin(): string {\n const envBin = process.env.AGENT_QA_CLI_BIN\n if (envBin) return envBin\n\n try {\n const which = execSync('which agent-qa', { encoding: 'utf-8' }).trim()\n if (which) return which\n } catch {\n // not found in PATH\n }\n\n return './node_modules/.bin/agent-qa'\n }\n\n execute(opts: ExecuteOptions): void {\n const spawnArgs = ['run', ...opts.args]\n const maxRetries = opts.maxRetries ?? 0\n\n const env: Record<string, string | undefined> = {\n ...process.env,\n ...opts.env,\n AGENT_QA_LIVE_EVENTS: 'true',\n }\n if (opts.attributes) {\n env.AGENT_QA_RUN_ATTRIBUTES_JSON = JSON.stringify(opts.attributes)\n }\n\n if (opts.source === 'suite') {\n // Suites create their own parent row via DashboardReporter.onSuiteStart\n // Pass the enqueued run ID so the suite can update it instead of creating a duplicate\n env.AGENT_QA_SUITE_QUEUE_ID = opts.runId\n } else if (maxRetries > 0) {\n // Retry-enabled: parent run stays in 'running', reporter creates child runs\n env.AGENT_QA_PARENT_RUN_ID = opts.runId\n env.AGENT_QA_MAX_RETRIES = String(maxRetries)\n } else {\n // No retries: reporter updates the existing run row directly\n env.AGENT_QA_RUN_ID = opts.runId\n }\n\n const child = spawn(this.cliBin, spawnArgs, {\n stdio: ['ignore', 'pipe', 'pipe'],\n env,\n detached: process.platform !== 'win32',\n })\n\n const handle: TestRunHandle = {\n runId: opts.runId,\n process: child,\n status: 'running',\n output: [],\n startedAt: new Date(),\n lastEventAt: Date.now(),\n }\n this.handles.set(opts.runId, handle)\n this.eventBuffers.set(opts.runId, [])\n this.eventCounters.set(opts.runId, 0)\n\n this.startHeartbeatChecker()\n\n const processTimeoutMs = opts.timeout ?? this.defaultTimeout\n let forceKillTimer: ReturnType<typeof setTimeout> | null = null\n const timer = typeof processTimeoutMs === 'number' && Number.isFinite(processTimeoutMs) && processTimeoutMs > 0\n ? setTimeout(() => {\n if (handle.status !== 'running') return\n handle.status = 'timeout'\n handle.completionReason = `process timeout after ${processTimeoutMs}ms`\n this.signalHandle(handle, 'SIGTERM')\n forceKillTimer = setTimeout(() => {\n this.signalHandle(handle, 'SIGKILL')\n }, PROCESS_TERMINATION_GRACE_MS)\n forceKillTimer.unref()\n }, processTimeoutMs)\n : null\n timer?.unref()\n\n this.pushEvent(opts.runId, { type: 'run-start', runId: opts.runId, status: 'running' })\n\n let stdoutBuffer = ''\n // Capture the actual test result status from the reporter (test-complete event).\n // This is the ground truth — process exit code can be misleading (e.g., mobile\n // tests exit non-zero from Appium cleanup even when all steps pass).\n let testResultStatus: string | undefined\n\n child.stdout?.on('data', (chunk: Buffer) => {\n stdoutBuffer += chunk.toString()\n const lines = stdoutBuffer.split('\\n')\n stdoutBuffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line) continue\n if (line.startsWith('AGENT_QA_EVENT:')) {\n try {\n const payload = JSON.parse(line.slice('AGENT_QA_EVENT:'.length))\n handle.lastEventAt = Date.now()\n if (payload.type === 'test-complete' && payload.status) {\n testResultStatus = payload.status\n }\n this.pushEvent(opts.runId, payload)\n } catch {\n handle.output.push(line)\n this.emit('output', opts.runId, line)\n }\n } else {\n handle.output.push(line)\n this.emit('output', opts.runId, line)\n }\n }\n })\n\n child.stderr?.on('data', (chunk: Buffer) => {\n const lines = chunk.toString().split('\\n').filter(Boolean)\n for (const line of lines) {\n handle.output.push(line)\n }\n })\n\n child.on('close', (code) => {\n if (timer) clearTimeout(timer)\n if (forceKillTimer) clearTimeout(forceKillTimer)\n if (stdoutBuffer) {\n if (stdoutBuffer.startsWith('AGENT_QA_EVENT:')) {\n try {\n const payload = JSON.parse(stdoutBuffer.slice('AGENT_QA_EVENT:'.length))\n if (payload.type === 'test-complete' && payload.status) {\n testResultStatus = payload.status\n }\n this.pushEvent(opts.runId, payload)\n } catch {\n handle.output.push(stdoutBuffer)\n }\n } else {\n handle.output.push(stdoutBuffer)\n }\n stdoutBuffer = ''\n }\n\n if (handle.status !== 'timeout' && handle.status !== 'cancelled' && handle.status !== 'failed') {\n // Use the actual test result from the reporter (test-complete event) as\n // ground truth. A clean process exit without reporter completion is incomplete.\n if (testResultStatus) {\n handle.status = testResultStatus === 'passed'\n ? 'completed'\n : testResultStatus === 'cancelled'\n ? 'cancelled'\n : 'failed'\n } else {\n handle.status = 'failed'\n handle.completionReason = 'process exited before test completed'\n }\n }\n\n const duration = Date.now() - handle.startedAt.getTime()\n this.pushEvent(opts.runId, {\n type: 'run-complete',\n runId: opts.runId,\n status: handle.status,\n duration,\n ...(handle.completionReason ? { reason: handle.completionReason } : {}),\n })\n\n if (this.onProcessClose) {\n this.onProcessClose(opts.runId, handle.status)\n }\n\n const cleanupTimer = setTimeout(() => {\n this.handles.delete(opts.runId)\n this.eventBuffers.delete(opts.runId)\n this.eventCounters.delete(opts.runId)\n }, HANDLE_RETENTION_MS)\n cleanupTimer.unref()\n })\n }\n\n getBufferedEvents(runId: string): LiveExecutionEvent[] {\n return this.eventBuffers.get(runId) ?? []\n }\n\n getHandle(runId: string): TestRunHandle | undefined {\n return this.handles.get(runId)\n }\n\n getActiveExecutions(): { runId: string; status: string; startedAt: string; duration: number; testName?: string }[] {\n const active: { runId: string; status: string; startedAt: string; duration: number; testName?: string }[] = []\n for (const handle of this.handles.values()) {\n if (handle.status === 'running') {\n const events = this.eventBuffers.get(handle.runId) ?? []\n const testStart = events.find(e => e.type === 'test-start')\n active.push({\n runId: handle.runId,\n status: handle.status,\n startedAt: handle.startedAt.toISOString(),\n duration: Date.now() - handle.startedAt.getTime(),\n testName: testStart?.testName as string | undefined,\n })\n }\n }\n return active\n }\n\n kill(runId: string): boolean {\n const handle = this.handles.get(runId)\n if (handle && handle.status === 'running') {\n this.signalHandle(handle, 'SIGINT')\n const forceTimer = setTimeout(() => {\n this.signalHandle(handle, 'SIGKILL')\n }, PROCESS_TERMINATION_GRACE_MS)\n forceTimer.unref()\n handle.process.once('close', () => clearTimeout(forceTimer))\n handle.status = 'cancelled'\n return true\n }\n return false\n }\n\n killAll(): void {\n for (const handle of this.handles.values()) {\n if (handle.status === 'running') {\n handle.status = 'cancelled'\n this.signalHandle(handle, 'SIGKILL')\n }\n }\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer)\n this.heartbeatTimer = null\n }\n }\n\n private startHeartbeatChecker(): void {\n if (this.heartbeatTimer) return\n this.heartbeatTimer = setInterval(() => {\n for (const handle of this.handles.values()) {\n if (handle.status !== 'running') continue\n if (Date.now() - handle.lastEventAt > this.staleThresholdMs) {\n handle.status = 'failed'\n handle.completionReason = 'stale process — no heartbeat'\n this.signalHandle(handle, 'SIGKILL')\n }\n }\n }, this.heartbeatIntervalMs)\n this.heartbeatTimer.unref()\n }\n\n private pushEvent(runId: string, payload: Record<string, unknown>): void {\n const counter = (this.eventCounters.get(runId) ?? 0) + 1\n this.eventCounters.set(runId, counter)\n\n const event: LiveExecutionEvent = { ...payload, id: counter } as LiveExecutionEvent\n const buffer = this.eventBuffers.get(runId)\n if (buffer) {\n buffer.push(event)\n }\n this.emit('execution-event', runId, event)\n }\n\n private signalHandle(handle: TestRunHandle, signal: NodeJS.Signals): void {\n const pid = handle.process.pid\n if (!pid) return\n\n if (process.platform === 'win32') {\n treeKill(pid, signal, () => {})\n return\n }\n\n try {\n process.kill(-pid, signal)\n return\n } catch {\n // Fall back to direct child signaling when the process group is unavailable.\n }\n\n try {\n handle.process.kill(signal)\n return\n } catch {\n // Fall back to tree-kill as a last resort.\n }\n\n treeKill(pid, signal, () => {})\n }\n}\n","import { EventEmitter } from 'node:events'\nimport { cpus } from 'node:os'\nimport type { RunArtifactKind, RunAttributes } from '@vostride/agent-qa-core'\nimport type { DashboardDatabase, RunRow } from '../db/database.js'\n\ninterface EnqueueOptions {\n name: string\n filePath?: string\n kind?: RunArtifactKind\n attributes?: RunAttributes\n priority?: number\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n metadata?: Record<string, unknown>\n parallel?: boolean\n}\n\nexport class JobQueue extends EventEmitter {\n private db: DashboardDatabase\n private pollInterval: ReturnType<typeof setInterval> | null = null\n private isProcessing = false\n private concurrency: number\n private activeCount = 0\n private activePlatforms = new Set<string>()\n private activeRuns = new Map<string, { platform: string }>()\n\n constructor(opts: { db: DashboardDatabase; concurrency?: number }) {\n super()\n this.db = opts.db\n this.concurrency = opts.concurrency ?? cpus().length\n }\n\n start(intervalMs = 1000): void {\n this.pollInterval = setInterval(() => this.processNext(), intervalMs)\n this.on('enqueued', () => this.processNext())\n }\n\n stop(): void {\n if (this.pollInterval) {\n clearInterval(this.pollInterval)\n this.pollInterval = null\n }\n this.removeAllListeners('enqueued')\n }\n\n enqueue(opts: EnqueueOptions): string {\n const runId = this.db.insertPendingRun({\n name: opts.name,\n filePath: opts.filePath,\n attributes: opts.attributes,\n priority: opts.priority ?? 0,\n platform: opts.platform,\n testFileContent: opts.testFileContent,\n modelName: opts.modelName,\n llmProvider: opts.llmProvider,\n metadata: opts.metadata,\n parallel: opts.parallel,\n })\n this.db.insertRunArtifact({\n runId,\n kind: opts.kind ?? 'test',\n payload: {\n runtime: {\n platform: opts.platform ?? 'web',\n queued: true,\n },\n source: {\n name: opts.name,\n filePath: opts.filePath ?? null,\n loadStatus: 'queued',\n },\n metadata: {\n ...opts.metadata,\n attributes: opts.attributes ?? {},\n },\n },\n })\n this.emit('enqueued', runId)\n return runId\n }\n\n processNext(): void {\n if (this.isProcessing) return\n this.isProcessing = true\n try {\n while (true) {\n const next = this.findNextEligible()\n if (!next) break\n\n const isParallel = Boolean(next.parallel)\n const platform = next.platform ?? 'web'\n const isMobile = platform === 'ios' || platform === 'android'\n\n this.activeCount++\n if (isMobile) this.activePlatforms.add(platform)\n this.activeRuns.set(next.id, { platform })\n\n this.db.updateRunStatus(next.id, 'running')\n this.db.updateRun(next.id, { startedAt: new Date().toISOString() })\n this.emit('execute', next)\n\n // Sequential jobs get exclusive access — stop filling slots after dequeue\n if (!isParallel && !isMobile) break\n }\n } finally {\n this.isProcessing = false\n }\n }\n\n onSlotFreed(runId: string): void {\n const info = this.activeRuns.get(runId)\n if (!info) return\n this.activeCount--\n if (info.platform === 'ios' || info.platform === 'android') {\n this.activePlatforms.delete(info.platform)\n }\n this.activeRuns.delete(runId)\n this.processNext()\n }\n\n getActiveCount(): number {\n return this.activeCount\n }\n\n getConcurrency(): number {\n return this.concurrency\n }\n\n cancel(runId: string): boolean {\n const run = this.db.getRun(runId)\n if (!run) return false\n const now = new Date().toISOString()\n if (run.status === 'pending') {\n this.db.updateRun(runId, { status: 'cancelled', endedAt: now })\n this.cancelChildRuns(runId, now)\n this.db.finalizeRunArtifact(runId, {\n errors: [{ code: 'cancelled', phase: 'queue', message: 'Run cancelled before execution' }],\n runtime: { status: 'cancelled' },\n })\n return true\n }\n if (run.status === 'running') {\n this.db.updateRun(runId, { status: 'cancelled', endedAt: now })\n this.cancelChildRuns(runId, now)\n try {\n const artifact = this.db.getRunArtifact(runId)\n if (artifact && !artifact.finalizedAt) {\n this.db.finalizeRunArtifact(runId, {\n errors: [{ code: 'cancelled', phase: 'queue', message: 'Run cancellation requested' }],\n runtime: { status: 'cancelled' },\n })\n }\n } catch { /* cancellation still proceeds */ }\n this.emit('cancel-running', runId)\n return true\n }\n return false\n }\n\n private cancelChildRuns(parentRunId: string, endedAt: string): void {\n for (const child of this.db.getRunsByParent(parentRunId)) {\n if (child.status !== 'running' && child.status !== 'pending') continue\n this.db.updateRun(child.id, {\n status: 'cancelled',\n endedAt,\n failureSummary: 'Run cancelled by user',\n })\n try {\n const artifact = this.db.getRunArtifact(child.id)\n if (artifact && !artifact.finalizedAt) {\n this.db.finalizeRunArtifact(child.id, {\n errors: [{ code: 'cancelled', phase: 'queue', message: 'Run cancelled by user' }],\n runtime: { status: 'cancelled' },\n })\n }\n } catch { /* best-effort child cancellation */ }\n }\n }\n\n private findNextEligible(): RunRow | undefined {\n if (this.activeCount >= this.concurrency) return undefined\n\n const pending = this.db.getPendingRuns()\n for (const run of pending) {\n const isParallel = Boolean(run.parallel)\n const platform = run.platform ?? 'web'\n const isMobile = platform === 'ios' || platform === 'android'\n\n if (isMobile) {\n // Mobile: needs a slot AND its platform not already active\n // parallel flag is ignored — mobile tests serialize per platform via device mutex\n if (this.activePlatforms.has(platform)) continue\n return run\n }\n\n if (!isParallel) {\n // Sequential web: needs ALL slots free (exclusive access)\n if (this.activeCount > 0) continue\n return run\n }\n\n // Parallel web: just needs an available slot\n return run\n }\n\n return undefined\n }\n}\n","import { readFile, writeFile, mkdir, stat, rm } from 'node:fs/promises'\nimport { dirname, basename } from 'node:path'\nimport { generateSuiteId } from '@vostride/agent-qa-ids'\nimport { parse as parseYaml } from 'yaml'\nimport { discoverWorkspaceFiles, resolveWorkspaceFileTarget, SuiteDefinitionSchema } from '@vostride/agent-qa-core'\nimport type { ResolvedWorkspacePaths, SuiteDefinition } from '@vostride/agent-qa-core'\nimport type { TestFileManager } from './test-file-manager.js'\n\ninterface SuiteFileInfo {\n path: string\n suiteId: string | null\n name: string\n testCount: number\n modified: string\n platform: string | null\n}\n\ninterface SuiteValidationResult {\n valid: boolean\n errors: { message: string; line?: number; column?: number; suggestion?: string }[]\n missingTests?: Array<{ index: number; test: string; id: string }>\n}\n\nexport class SuiteFileManager {\n private testFileManager: TestFileManager | undefined\n\n constructor(\n private readonly workspace: ResolvedWorkspacePaths,\n testFileManager?: TestFileManager,\n ) {\n this.testFileManager = testFileManager\n }\n\n async list(): Promise<SuiteFileInfo[]> {\n const records = await discoverWorkspaceFiles({ workspace: this.workspace, kind: 'suite' })\n const files: SuiteFileInfo[] = []\n\n for (const record of records) {\n try {\n const s = await stat(record.absolutePath)\n if (s.isFile()) {\n let suiteName = basename(record.workspaceRelativePath)\n let testCount = 0\n let platform: string | null = null\n let suiteId: string | null = null\n try {\n let content = await readFile(record.absolutePath, 'utf-8')\n const parsed = parseYaml(content)\n if (parsed?.name) suiteName = parsed.name\n if (Array.isArray(parsed?.tests)) testCount = parsed.tests.length\n platform = parsed?.config?.platform ?? null\n const suiteIdMatch = content.match(/^suite-id:\\s*(.+)$/m)\n if (suiteIdMatch) {\n suiteId = suiteIdMatch[1].trim().replace(/^[\"'](.*)[\"']$/, '$1')\n } else {\n suiteId = generateSuiteId()\n content = `suite-id: ${suiteId}\\n${content}`\n await writeFile(record.absolutePath, content, 'utf-8')\n }\n } catch { /* fall back to filename */ }\n files.push({\n path: record.workspaceRelativePath,\n suiteId,\n name: suiteName,\n testCount,\n modified: s.mtime.toISOString(),\n platform,\n })\n }\n } catch {\n // skip inaccessible files\n }\n }\n\n files.sort((a, b) => b.modified.localeCompare(a.modified))\n return files\n }\n\n async findBySuiteId(suiteId: string): Promise<{ path: string; content: string } | null> {\n const files = await this.list()\n const match = files.find(f => f.suiteId === suiteId)\n if (!match) return null\n const content = await this.read(match.path)\n return { path: match.path, content }\n }\n\n async resolvePath(filePath: string, requireExisting = true): Promise<{ storagePath: string; executionPath: string }> {\n const trimmedPath = filePath.trim()\n if (!trimmedPath) {\n throw new Error('Suite path is required')\n }\n\n const target = await resolveWorkspaceFileTarget({\n workspace: this.workspace,\n kind: 'suite',\n filePath: trimmedPath,\n requireExisting,\n })\n return { storagePath: target.workspaceRelativePath, executionPath: target.absolutePath }\n }\n\n async read(relativePath: string): Promise<string> {\n const target = await this.resolveTarget(relativePath, true)\n return readFile(target.absolutePath, 'utf-8')\n }\n\n async write(relativePath: string, content: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, false)\n await mkdir(dirname(target.absolutePath), { recursive: true })\n await writeFile(target.absolutePath, content, 'utf-8')\n }\n\n async delete(relativePath: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, true)\n await rm(target.absolutePath)\n }\n\n async validate(content: string): Promise<SuiteValidationResult> {\n try {\n const parsed = parseYaml(content)\n const result = SuiteDefinitionSchema.safeParse(parsed)\n\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.issues.map((issue: { path: PropertyKey[]; message: string }) => ({\n message: `${issue.path.map(String).join('.')}: ${issue.message}`,\n })),\n }\n }\n\n // Save-time fail-fast: verify every referenced test path resolves (Phase 181 D-32/D-33)\n if (this.testFileManager) {\n const suite = result.data as SuiteDefinition\n const available = await this.testFileManager.list()\n const availablePaths = new Set(available.map((f) => f.path))\n const missingTests: Array<{ index: number; test: string; id: string }> = []\n suite.tests.forEach((entry: SuiteDefinition['tests'][number], index: number) => {\n if (!availablePaths.has(entry.test)) {\n // Report the ORIGINAL entry.test so the user sees what they wrote\n missingTests.push({ index, test: entry.test, id: entry.id })\n }\n })\n if (missingTests.length > 0) {\n return {\n valid: false,\n errors: [{\n message: `Cannot save — referenced tests not found: ${missingTests.map(m => m.test).join(', ')}`,\n }],\n missingTests,\n }\n }\n }\n\n return { valid: true, errors: [] }\n } catch (err) {\n return {\n valid: false,\n errors: [{ message: err instanceof Error ? err.message : 'Failed to parse YAML' }],\n }\n }\n }\n\n private async resolveTarget(relativePath: string, requireExisting: boolean) {\n return resolveWorkspaceFileTarget({\n workspace: this.workspace,\n kind: 'suite',\n filePath: relativePath,\n requireExisting,\n })\n }\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport { parseDocument, stringify, type Document } from 'yaml'\n\nconst SENSITIVE_KEYS = new Set(['apikey', 'token', 'key', 'accesskey'])\n\nfunction isSensitiveKey(key: string): boolean {\n return SENSITIVE_KEYS.has(key.toLowerCase())\n}\n\nfunction maskValue(value: string): string {\n if (value.length >= 8) {\n return value.slice(0, 3) + '****...' + value.slice(-4)\n }\n return '****'\n}\n\nfunction deepMask(obj: unknown, parentKey = ''): unknown {\n if (typeof obj === 'string' && isSensitiveKey(parentKey)) {\n return maskValue(obj)\n }\n if (Array.isArray(obj)) {\n return obj.map((item, i) => deepMask(item, String(i)))\n }\n if (typeof obj === 'object' && obj !== null) {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[key] = deepMask(value, key)\n }\n return result\n }\n return obj\n}\n\nexport class ConfigManager {\n constructor(private configPath: string) {}\n\n async read(): Promise<Record<string, unknown>> {\n try {\n const content = await readFile(this.configPath, 'utf-8')\n const doc = parseDocument(content)\n return (doc.toJSON() as Record<string, unknown>) ?? {}\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return {}\n throw err\n }\n }\n\n async readMasked(): Promise<Record<string, unknown>> {\n const config = await this.read()\n return deepMask(config) as Record<string, unknown>\n }\n\n private sectionPath(section: string): string[] {\n return section.includes('.') ? section.split('.') : [section]\n }\n\n async updateSection(section: string, value: Record<string, unknown>): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({ [section]: value }))\n return\n }\n throw err\n }\n\n const doc = parseDocument(content)\n for (const [key, val] of Object.entries(value)) {\n doc.setIn([...path, key], val)\n }\n await writeFile(this.configPath, doc.toString())\n }\n\n async replaceSection(section: string, value: Record<string, unknown>): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({ [section]: value }))\n return\n }\n throw err\n }\n const doc = parseDocument(content)\n // Overwrite in-place to preserve key ordering in the YAML file\n doc.setIn(path, doc.createNode(value))\n await writeFile(this.configPath, doc.toString())\n }\n\n async replaceSectionRaw(section: string, value: unknown): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({ [section]: value }))\n return\n }\n throw err\n }\n const doc = parseDocument(content)\n // Overwrite in-place to preserve key ordering in the YAML file\n doc.setIn(path, doc.createNode(value))\n await writeFile(this.configPath, doc.toString())\n }\n\n async deleteSectionRaw(section: string): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({}))\n return\n }\n throw err\n }\n const doc = parseDocument(content)\n doc.deleteIn(path)\n await writeFile(this.configPath, doc.toString())\n }\n\n async readDocument(): Promise<Document> {\n const content = await readFile(this.configPath, 'utf-8')\n return parseDocument(content)\n }\n}\n","import { request } from 'node:http'\nimport { spawn, type ChildProcess } from 'node:child_process'\nimport {\n formatAppiumInstallGuidance,\n resolveAppiumExecutable,\n type ResolvedAppiumExecutable,\n} from '@vostride/agent-qa-core'\nimport treeKill from 'tree-kill'\nimport pc from 'picocolors'\n\nconst APPIUM_PREFIX = pc.magenta('[appium]')\n\nexport interface AppiumLeaseOwner {\n runId: string\n platform: 'android' | 'ios'\n}\n\nexport interface AppiumLease extends AppiumLeaseOwner {\n acquiredAt: string\n}\n\nexport class AppiumManager {\n private process: ChildProcess | null = null\n private port: number\n private ready = false\n private startPromise: Promise<void> | null = null\n private managed = false\n private startupTimeoutMs: number\n private pollIntervalMs: number\n private anonymousRefCount = 0\n private leases = new Map<string, AppiumLease>()\n private logLevel: 'normal' | 'debug'\n private appiumResolver: () => ResolvedAppiumExecutable\n\n constructor(opts?: {\n port?: number\n startupTimeoutMs?: number\n pollIntervalMs?: number\n logLevel?: 'normal' | 'debug'\n appiumResolver?: () => ResolvedAppiumExecutable\n }) {\n this.port = opts?.port ?? 4723\n this.startupTimeoutMs = opts?.startupTimeoutMs ?? 30_000\n this.pollIntervalMs = opts?.pollIntervalMs ?? 500\n this.logLevel = opts?.logLevel ?? 'normal'\n this.appiumResolver = opts?.appiumResolver ?? resolveAppiumExecutable\n }\n\n async acquire(): Promise<void> {\n await this.ensureRunning()\n this.anonymousRefCount++\n }\n\n release(): void {\n if (this.anonymousRefCount > 0) this.anonymousRefCount--\n this.maybeShutdownAfterRelease()\n }\n\n async acquireLease(owner: AppiumLeaseOwner): Promise<void> {\n await this.ensureRunning()\n if (!this.leases.has(owner.runId)) {\n this.leases.set(owner.runId, {\n runId: owner.runId,\n platform: owner.platform,\n acquiredAt: new Date().toISOString(),\n })\n }\n console.log(`${APPIUM_PREFIX} lease acquired run=${owner.runId} platform=${owner.platform} leases=${this.getLeaseCount()} managed=${this.managed}`)\n }\n\n releaseLease(runId: string, reason = 'completed'): boolean {\n const lease = this.leases.get(runId)\n if (!lease) return false\n\n this.leases.delete(runId)\n console.log(`${APPIUM_PREFIX} lease released run=${runId} platform=${lease.platform} reason=${reason} leases=${this.getLeaseCount()} managed=${this.managed}`)\n this.maybeShutdownAfterRelease()\n return true\n }\n\n releaseAllLeases(reason = 'shutdown'): string[] {\n const runIds = [...this.leases.keys()]\n for (const runId of runIds) {\n this.releaseLease(runId, reason)\n }\n return runIds\n }\n\n async ensureRunning(): Promise<void> {\n if (this.ready) {\n const still = await this.checkStatus()\n if (still) return\n this.ready = false\n }\n\n if (this.startPromise) {\n await this.startPromise\n return\n }\n\n this.startPromise = (async () => {\n const alive = await this.checkStatus()\n if (alive) {\n this.ready = true\n this.managed = false\n return\n }\n await this.startAndWait()\n })()\n\n try {\n await this.startPromise\n } finally {\n this.startPromise = null\n }\n }\n\n async checkStatus(): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const req = request(\n {\n hostname: 'localhost',\n port: this.port,\n path: '/status',\n method: 'GET',\n timeout: 3000,\n },\n (res) => {\n let data = ''\n res.on('data', (chunk: Buffer) => {\n data += chunk.toString()\n })\n res.on('end', () => {\n try {\n const parsed = JSON.parse(data)\n resolve(parsed?.value?.ready === true)\n } catch {\n resolve(false)\n }\n })\n },\n )\n req.on('error', () => resolve(false))\n req.on('timeout', () => {\n req.destroy()\n resolve(false)\n })\n req.end()\n })\n }\n\n private async startAndWait(): Promise<void> {\n const appium = this.appiumResolver()\n const child = spawn(appium.command, ['-p', String(this.port), '--relaxed-security', '--log-no-colors'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n this.process = child\n this.managed = true\n\n child.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ENOENT') {\n console.error(`${APPIUM_PREFIX} Appium not found. ${formatAppiumInstallGuidance()}`)\n } else {\n console.error(`${APPIUM_PREFIX} Error: ${err.message}`)\n }\n })\n\n child.stdout?.on('data', (chunk: Buffer) => {\n if (this.logLevel !== 'debug') return\n const lines = chunk.toString().split('\\n').filter(Boolean)\n for (const line of lines) {\n console.log(`${APPIUM_PREFIX} ${pc.dim(line)}`)\n }\n })\n\n child.stderr?.on('data', (chunk: Buffer) => {\n if (this.logLevel !== 'debug') return\n const lines = chunk.toString().split('\\n').filter(Boolean)\n for (const line of lines) {\n console.error(`${APPIUM_PREFIX} ${pc.dim(line)}`)\n }\n })\n\n const start = Date.now()\n while (Date.now() - start < this.startupTimeoutMs) {\n const ok = await this.checkStatus()\n if (ok) {\n this.ready = true\n console.log(`${APPIUM_PREFIX} ${pc.green(`started on :${this.port}`)}`)\n return\n }\n await new Promise((r) => setTimeout(r, this.pollIntervalMs))\n }\n\n // Timeout — kill and throw\n if (child.pid) {\n treeKill(child.pid, 'SIGKILL', () => {})\n }\n this.process = null\n this.managed = false\n throw new Error(`Appium server did not become ready within ${this.startupTimeoutMs}ms`)\n }\n\n private performShutdown(): void {\n if (this.process?.pid && this.managed) {\n treeKill(this.process.pid, 'SIGKILL', () => {})\n console.log(`${APPIUM_PREFIX} ${pc.yellow('stopped')}`)\n }\n this.process = null\n this.ready = false\n this.managed = false\n }\n\n private maybeShutdownAfterRelease(): void {\n if (this.getRefCount() > 0) {\n console.log(`${APPIUM_PREFIX} server kept alive leases=${this.getLeaseCount()} managed=${this.managed}`)\n return\n }\n if (this.managed) {\n this.performShutdown()\n return\n }\n if (this.ready) {\n console.log(`${APPIUM_PREFIX} external server left running leases=0 managed=false`)\n }\n }\n\n shutdown(): void {\n this.anonymousRefCount = 0\n this.leases.clear()\n this.performShutdown()\n }\n\n getUrl(): string {\n return `http://localhost:${this.port}`\n }\n\n getPort(): number {\n return this.port\n }\n\n isManaged(): boolean {\n return this.managed\n }\n\n getRefCount(): number {\n return this.anonymousRefCount + this.leases.size\n }\n\n getLeaseCount(): number {\n return this.leases.size\n }\n\n getLeases(): AppiumLease[] {\n return [...this.leases.values()]\n }\n\n hasLease(runId: string): boolean {\n return this.leases.has(runId)\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { LiveSession } from './live-session.js'\nimport type { SessionState, LiveSessionConfig, EntityRef } from './types.js'\nimport type { AppiumManager } from '../execution/appium-manager.js'\nimport type { ConfigManager } from '../config/index.js'\n\nexport interface SessionManagerDeps {\n appiumManager?: AppiumManager\n configManager?: ConfigManager\n configPath?: string\n}\n\nexport class SessionManager {\n private sessions = new Map<string, LiveSession>()\n // Per-entity counter keyed by `${entityType}:${entityId}`.\n // Monotonic and ephemeral: resets on server restart per CONTEXT D-30.\n // Never decremented on terminate — a re-open of a terminated entity yields\n // the next number so \"Session #3\" after \"#2\" ends does not confuse users.\n private counters = new Map<string, number>()\n\n constructor(private deps: SessionManagerDeps = {}) {}\n\n async createSession(\n config: LiveSessionConfig,\n entity?: EntityRef,\n ): Promise<{ sessionId: string; sessionNumber: number | null }> {\n if (!config.llmConfig) {\n throw new Error('LLM not configured')\n }\n\n const sessionId = randomUUID()\n const session = new LiveSession(sessionId, this.deps)\n await session.initialize(config)\n this.sessions.set(sessionId, session)\n\n // sessionNumber is used for display only; never for authorization lookups\n // (always use sessionId UUID for that — see threat T-181.1-07).\n let sessionNumber: number | null = null\n if (entity && entity.id) {\n const key = `${entity.type}:${entity.id}`\n sessionNumber = (this.counters.get(key) ?? 0) + 1\n this.counters.set(key, sessionNumber)\n }\n\n return { sessionId, sessionNumber }\n }\n\n getSession(sessionId: string): LiveSession | undefined {\n return this.sessions.get(sessionId)\n }\n\n listSessions(): SessionState[] {\n return Array.from(this.sessions.values()).map(s => s.getState())\n }\n\n async terminateSession(sessionId: string): Promise<boolean> {\n const session = this.sessions.get(sessionId)\n if (!session) return false\n await session.cleanup()\n this.sessions.delete(sessionId)\n // Note: `counters` intentionally left untouched — per D-30 the counter is\n // monotonic per-restart.\n return true\n }\n\n async cleanupAll(): Promise<void> {\n for (const session of this.sessions.values()) {\n try { await session.cleanup() } catch {}\n }\n this.sessions.clear()\n }\n\n getCounter(entity: EntityRef): number {\n return this.counters.get(`${entity.type}:${entity.id}`) ?? 0\n }\n\n get size(): number {\n return this.sessions.size\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport {\n executeStep,\n createModel,\n getProviderOptions,\n LLMPlanner,\n LLMVerifier,\n VariableStore,\n interpolateVariables,\n findUnresolvedTemplates,\n parseHookInline,\n stripHookInline,\n runHooks,\n runHookInSandbox,\n MobileSetupError,\n redactSecretValue,\n resolveSecretTemplatesInValue,\n} from '@vostride/agent-qa-core'\nimport type {\n AgentLoopConfig,\n StepContext,\n PlatformAdapter,\n PlatformConfig,\n StepResult,\n StepPhaseEvent,\n HookDefinition,\n MobilePlatform,\n SecretRedactor,\n SecretStore,\n} from '@vostride/agent-qa-core'\nimport type { LanguageModel } from 'ai'\nimport { prepareMobileLiveSession } from './mobile-bootstrap.js'\nimport type { MobileLiveAppiumLease } from './mobile-bootstrap.js'\nimport type { AppiumManager } from '../execution/appium-manager.js'\nimport type { ConfigManager } from '../config/index.js'\nimport type {\n SessionState,\n LiveDraftMetadata,\n LiveExecutionLog,\n LiveHookOwner,\n LiveSessionConfig,\n LiveStepResultPayload,\n LiveSubActionData,\n LiveHookPayload,\n LiveTestExecutionPayload,\n LiveTestResultPayload,\n LiveTestStepPayload,\n ServerMessage,\n} from './types.js'\n\nconst IDLE_TIMEOUT_MS = 5 * 60 * 1000\n\nconst RUNJS_DBL_RE = /\\{\\{runJS:\"((?:[^\"\\\\]|\\\\.)*)\"\\}\\}/g\nconst RUNJS_SGL_RE = /\\{\\{runJS:'((?:[^'\\\\]|\\\\.)*)'\\}\\}/g\n\nexport interface LiveSessionDeps {\n appiumManager?: AppiumManager\n configManager?: ConfigManager\n configPath?: string\n}\n\nexport interface LiveStepExecutionResult extends StepResult {\n executionLogs?: LiveExecutionLog[]\n subActionsData?: LiveSubActionData[]\n}\n\n// Shared with ws-handler.ts toStepResultPayload. Kept in-module so that\n// executeTestCommand can assemble its stepResults array without a\n// cross-module import that would create a circular dependency.\nfunction toStepResultPayload(result: LiveStepExecutionResult): LiveStepResultPayload {\n const status = result.status === 'passed'\n ? 'passed'\n : result.status === 'cancelled'\n ? 'cancelled'\n : 'failed'\n\n return {\n status,\n duration: result.duration,\n error: result.error,\n capturedVariables: result.capturedVariables,\n variableSnapshot: result.variableSnapshot,\n originalStepName: result.originalStepName,\n consoleLogs: result.consoleLogs,\n networkLogs: result.networkLogs,\n executionLogs: result.executionLogs,\n subActionsData: result.subActionsData,\n }\n}\n\ninterface RunJSMatch {\n fullMatch: string\n code: string\n}\n\nfunction parseRunJSInline(text: string): RunJSMatch[] {\n const matches: RunJSMatch[] = []\n for (const match of text.matchAll(RUNJS_DBL_RE)) {\n matches.push({ fullMatch: match[0], code: match[1] })\n }\n for (const match of text.matchAll(RUNJS_SGL_RE)) {\n matches.push({ fullMatch: match[0], code: match[1] })\n }\n return matches.sort((a, b) => text.indexOf(a.fullMatch) - text.indexOf(b.fullMatch))\n}\n\nfunction coerceRunJSResult(value: unknown): string {\n if (value === undefined) return 'undefined'\n if (value === null) return 'null'\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n return String(value)\n }\n return JSON.stringify(value)\n}\n\nfunction toLiveSubActionData(result: StepResult): LiveSubActionData[] | undefined {\n return result.trace?.subActions?.map((subAction) => ({\n index: subAction.index,\n observation: subAction.observation,\n reasoning: subAction.reasoning,\n plannedAction: subAction.plannedAction,\n result: subAction.result,\n error: subAction.error,\n screenStateBefore: subAction.screenStateBefore,\n screenStateAfter: subAction.screenStateAfter,\n confidence: subAction.confidence,\n verifierReasoning: subAction.verifierReasoning,\n cached: subAction.cached,\n tokenUsage: subAction.tokenUsage,\n phaseDurations: subAction.phaseDurations,\n annotation: subAction.annotation,\n screenContextBefore: subAction.screenContextBefore,\n screenContextAfter: subAction.screenContextAfter,\n data: subAction.data,\n }))\n}\n\nfunction mobileSetupMessage(err: MobileSetupError): string {\n return `${err.category}: ${err.message}`\n}\n\nfunction classifyAdapterSetupError(err: unknown): MobileSetupError['category'] {\n const message = err instanceof Error ? err.message : String(err)\n if (/appium|ECONNREFUSED|connect|\\/session|status/i.test(message)) {\n return 'appium-startup'\n }\n return 'device-readiness'\n}\n\nfunction wrapAdapterSetupError(\n err: unknown,\n platform: MobilePlatform,\n config: PlatformConfig,\n): MobileSetupError {\n if (err instanceof MobileSetupError) return err\n const appId = platform === 'android'\n ? config.appPackage\n : config.bundleId\n return new MobileSetupError({\n category: classifyAdapterSetupError(err),\n message: `Failed to create ${platform} adapter session: ${err instanceof Error ? err.message : String(err)}`,\n platform,\n deviceName: config.device?.name,\n appId,\n cause: err,\n })\n}\n\nfunction buildHookExecutionLog(hook: LiveHookPayload): LiveExecutionLog {\n return {\n id: hook.executionId,\n type: 'hook',\n name: hook.hookName,\n hookId: hook.hookId,\n phase: hook.phase,\n status: hook.status === 'failed' ? 'failed' : 'passed',\n duration: hook.duration ?? 0,\n stdout: hook.stdout ?? null,\n stderr: hook.stderr ?? null,\n returnData: null,\n variables: hook.variables ?? null,\n createdAt: hook.createdAt,\n }\n}\n\nexport class LiveSession {\n readonly sessionId: string\n status: 'idle' | 'executing' | 'disconnected' | 'terminated' = 'idle'\n private abortController: AbortController | null = null\n stepsExecuted = 0\n createdAt = 0\n\n private adapter: PlatformAdapter | null = null\n private planner: LLMPlanner | null = null\n private verifier: LLMVerifier | null = null\n private model: LanguageModel | null = null\n private variableStore: VariableStore | null = null\n private previousSteps: { instruction: string; outcome: string; reasoning?: string; plannedAction?: string; verifierResponse?: string }[] = []\n private currentStep: string | null = null\n private platform: 'web' | 'android' | 'ios' = 'web'\n private currentUrl: string | null = null\n private executing = false\n private idleTimer: ReturnType<typeof setTimeout> | null = null\n private _modelName = 'unknown'\n private screenshotSize: number | undefined\n private effectiveResolution: number | undefined\n private readyForInteraction = false\n private terminalError: string | null = null\n private setupHooks: string[] = []\n private teardownHooks: string[] = []\n private resolvedHooks = new Map<string, HookDefinition>()\n private hookRegistryError: string | null = null\n private pendingMessages: ServerMessage[] = []\n private messageSink: ((message: ServerMessage) => void) | null = null\n private mobileAppiumLease: MobileLiveAppiumLease | null = null\n private secretStore: SecretStore | undefined\n private secretRedactor: SecretRedactor | undefined\n\n constructor(sessionId: string, private deps: LiveSessionDeps = {}) {\n this.sessionId = sessionId\n }\n\n get modelName(): string {\n return this._modelName\n }\n\n attachMessageSink(sink: ((message: ServerMessage) => void) | null): void {\n this.messageSink = sink\n if (!sink || this.pendingMessages.length === 0) return\n\n for (const message of this.pendingMessages) {\n sink(message)\n }\n this.pendingMessages = []\n }\n\n private dispatch(message: ServerMessage): void {\n message = this.redact(message)\n if (this.messageSink) {\n this.messageSink(message)\n return\n }\n this.pendingMessages.push(message)\n }\n\n private redact<T>(value: T): T {\n return redactSecretValue(value, this.secretRedactor)\n }\n\n private resolveSecrets<T>(value: T): T {\n return resolveSecretTemplatesInValue(value, this.secretStore)\n }\n\n private emitHookStart(\n hookDef: Pick<HookDefinition, 'id' | 'name'>,\n phase: 'setup' | 'teardown',\n owner: LiveHookOwner = { scope: 'suite' },\n ): LiveHookPayload {\n const hook: LiveHookPayload = {\n executionId: randomUUID(),\n hookId: hookDef.id,\n hookName: hookDef.name,\n phase,\n owner,\n status: 'running',\n createdAt: new Date().toISOString(),\n }\n this.dispatch({ type: 'hook-start', hook })\n return hook\n }\n\n private emitHookComplete(\n started: LiveHookPayload,\n updates: Omit<LiveHookPayload, 'executionId' | 'hookId' | 'hookName' | 'phase' | 'owner' | 'createdAt'>,\n ): LiveHookPayload {\n const hook: LiveHookPayload = this.redact({\n ...started,\n ...updates,\n })\n this.dispatch({ type: 'hook-complete', hook })\n return hook\n }\n\n private emitTestStepStart(step: LiveTestStepPayload): void {\n this.dispatch({ type: 'test-step-start', step })\n }\n\n private emitTestStepPhase(step: LiveTestStepPayload, event: StepPhaseEvent): void {\n this.dispatch({\n type: 'test-step-phase',\n step,\n phase: event.phase,\n data: {\n text: event.text,\n confidence: event.confidence,\n action: event.action,\n success: event.success,\n duration: event.duration,\n },\n })\n }\n\n private emitTestStepComplete(step: LiveTestStepPayload, result: LiveStepExecutionResult): void {\n if (result.status === 'cancelled') {\n this.dispatch({ type: 'test-step-cancelled', step })\n return\n }\n\n this.dispatch({\n type: 'test-step-complete',\n step,\n result: toStepResultPayload(result),\n })\n }\n\n private emitTestStepError(step: LiveTestStepPayload, error: string): void {\n this.dispatch({ type: 'test-step-error', step, error })\n }\n\n private getHookEnvVars(): Record<string, string> {\n const envVars: Record<string, string> = {}\n if (!this.variableStore) return envVars\n\n for (const [key, value] of this.variableStore.getAll()) {\n envVars[key] = value\n }\n\n return envVars\n }\n\n private async runLifecycleHooks(\n phase: 'setup' | 'teardown',\n hookIds: string[],\n owner: LiveHookOwner = { scope: 'suite' },\n ): Promise<{ allPassed: boolean; logs: LiveExecutionLog[] }> {\n const logs: LiveExecutionLog[] = []\n\n for (const hookId of hookIds) {\n const hookDef = this.resolvedHooks.get(hookId)\n const started = this.emitHookStart(\n hookDef ?? { id: hookId, name: hookId },\n phase,\n owner,\n )\n\n if (!hookDef) {\n const registryHint = this.hookRegistryError ? ` (${this.hookRegistryError})` : ''\n const completed = this.emitHookComplete(started, {\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: this.hookRegistryError ?? null,\n variables: null,\n error: `Hook ID \"${hookId}\" is not defined in hooks.yaml${registryHint}`,\n })\n logs.push(buildHookExecutionLog(completed))\n if (phase === 'setup') {\n return { allPassed: false, logs }\n }\n continue\n }\n\n const result = await runHooks([hookDef], {\n envVars: this.getHookEnvVars(),\n secretStore: this.secretStore,\n secretRedactor: this.secretRedactor,\n })\n const hookResult = result.results.get(hookDef.name)\n const completed = this.emitHookComplete(started, {\n status: hookResult?.success ? 'passed' : 'failed',\n duration: hookResult?.duration ?? 0,\n stdout: hookResult?.stdout ?? null,\n stderr: hookResult?.stderr ?? null,\n variables: hookResult && Object.keys(hookResult.variables).length > 0 ? hookResult.variables : null,\n error: hookResult?.error,\n })\n logs.push(buildHookExecutionLog(completed))\n\n if (hookResult?.success && hookResult.variables && this.variableStore) {\n this.variableStore.setAll(hookResult.variables, 'hook')\n }\n\n if (!hookResult?.success && phase === 'setup') {\n return { allPassed: false, logs }\n }\n }\n\n return { allPassed: true, logs }\n }\n\n async executeHookCommand(\n phase: 'setup' | 'teardown',\n hookId: string,\n ): Promise<LiveExecutionLog> {\n if (!this.readyForInteraction || !this.variableStore) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n\n if (this.executing) {\n throw new Error('Live session is busy')\n }\n\n this.executing = true\n this.status = 'executing'\n const hookName = this.resolvedHooks.get(hookId)?.name ?? hookId\n this.currentStep = `${phase} hook: ${hookName}`\n\n try {\n const { logs } = await this.runLifecycleHooks(phase, [hookId])\n return logs[0] ?? {\n id: randomUUID(),\n type: 'hook',\n name: hookName,\n hookId,\n phase,\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: null,\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n }\n } finally {\n this.executing = false\n this.currentStep = null\n this.status = 'idle'\n }\n }\n\n private releaseMobileAppiumLease(reason: string): void {\n if (!this.mobileAppiumLease) return\n this.mobileAppiumLease.release(reason)\n this.mobileAppiumLease = null\n }\n\n private legacyMobilePlatformConfig(config: LiveSessionConfig): PlatformConfig {\n const platform = config.platform as MobilePlatform\n return {\n platform,\n bundleId: config.bundleId,\n appPackage: config.appPackage,\n appActivity: config.appActivity,\n deepLinkAppId: platform === 'android' ? config.appPackage : config.bundleId,\n appState: config.appState,\n device: config.device\n ? {\n name: config.device.name,\n platform,\n transport: 'local',\n match: config.device,\n }\n : undefined,\n }\n }\n\n private async resolveMobilePlatformConfig(config: LiveSessionConfig): Promise<PlatformConfig> {\n if (\n this.deps.appiumManager\n && this.deps.configManager\n && this.deps.configPath\n && config.targetName\n ) {\n const prepared = await prepareMobileLiveSession({\n sessionId: this.sessionId,\n platform: config.platform as MobilePlatform,\n targetName: config.targetName,\n useDeviceName: config.useDeviceName,\n appState: config.appState,\n appiumManager: this.deps.appiumManager,\n configManager: this.deps.configManager,\n configPath: this.deps.configPath,\n })\n this.mobileAppiumLease = prepared.appiumLease\n return prepared.platformConfig\n }\n\n return this.legacyMobilePlatformConfig(config)\n }\n\n private async setupMobileAdapter(platform: MobilePlatform, config: LiveSessionConfig): Promise<void> {\n let adapter: PlatformAdapter | null = null\n try {\n const platformConfig = await this.resolveMobilePlatformConfig(config)\n const platformLabel = platform === 'android' ? 'Android' : 'iOS'\n try {\n if (platform === 'android') {\n const { AndroidPlatformAdapter } = await import('@vostride/agent-qa-android')\n adapter = new AndroidPlatformAdapter()\n } else {\n const { IOSPlatformAdapter } = await import('@vostride/agent-qa-ios')\n adapter = new IOSPlatformAdapter()\n }\n } catch (err) {\n throw new MobileSetupError({\n category: 'adapter-load',\n message: `Failed to load ${platformLabel} adapter (@vostride/agent-qa-${platform}). Is the package installed? ${err instanceof Error ? err.message : String(err)}`,\n platform,\n targetName: config.targetName,\n deviceName: platformConfig.device?.name,\n appId: platform === 'android' ? platformConfig.appPackage : platformConfig.bundleId,\n cause: err,\n })\n }\n\n try {\n await adapter.setup(platformConfig)\n } catch (err) {\n throw wrapAdapterSetupError(err, platform, platformConfig)\n }\n this.adapter = adapter\n } catch (err) {\n try {\n await adapter?.cleanup()\n } catch {}\n this.releaseMobileAppiumLease('setup-failed')\n if (err instanceof MobileSetupError) {\n throw new Error(mobileSetupMessage(err))\n }\n throw err\n }\n }\n\n async initialize(config: LiveSessionConfig): Promise<void> {\n this.platform = config.platform\n this._modelName = config.llmConfig.model ?? 'unknown'\n this.variableStore = new VariableStore()\n this.secretStore = config.secretStore\n this.secretRedactor = config.secretRedactor\n if (config.envVars) {\n this.variableStore.setAll(config.envVars, 'env')\n }\n this.setupHooks = [...(config.setupHooks ?? [])]\n this.teardownHooks = [...(config.teardownHooks ?? [])]\n this.resolvedHooks = new Map(config.resolvedHooks ?? [])\n this.hookRegistryError = config.hookRegistryError ?? null\n this.screenshotSize = config.llmConfig.screenshotSize\n this.effectiveResolution = config.llmConfig.effectiveResolution\n this.readyForInteraction = false\n this.terminalError = null\n\n const setupResult = await this.runLifecycleHooks('setup', this.setupHooks)\n if (!setupResult.allPassed) {\n this.status = 'idle'\n this.createdAt = Date.now()\n this.terminalError = 'Setup hooks failed. End the session or fix the hook configuration and reconnect.'\n return\n }\n\n if (config.platform === 'android') {\n await this.setupMobileAdapter('android', config)\n this.currentUrl = null\n } else if (config.platform === 'ios') {\n await this.setupMobileAdapter('ios', config)\n this.currentUrl = null\n } else {\n const { WebPlatformAdapter } = await import('@vostride/agent-qa-web')\n const adapter = new WebPlatformAdapter()\n await adapter.setup({ platform: 'web', browser: { name: 'chromium', headless: config.headless ?? true } })\n this.adapter = adapter\n\n if (config.url) {\n const resolvedUrl = this.resolveSecrets(config.url)\n await adapter.execute({ type: 'navigate', url: resolvedUrl })\n this.currentUrl = resolvedUrl\n } else {\n this.currentUrl = 'about:blank'\n }\n }\n\n const modelConfig = {\n ...config.llmConfig,\n ...(config.authFetch ? { fetch: config.authFetch } : {}),\n }\n this.model = await createModel(modelConfig)\n const providerOptions = getProviderOptions(modelConfig)\n this.planner = new LLMPlanner(this.model, config.platform, providerOptions, undefined, config.agentRules)\n this.verifier = new LLMVerifier(this.model, providerOptions)\n\n this.status = 'idle'\n this.createdAt = Date.now()\n this.readyForInteraction = true\n }\n\n private async resolveStepInstruction(stepInstruction: string): Promise<{\n instruction: string\n originalStepName?: string\n executionLogs: LiveExecutionLog[]\n preparationError?: string\n }> {\n const originalStepName = stepInstruction\n let instruction = stepInstruction\n let hasTemplateVars = false\n const executionLogs: LiveExecutionLog[] = []\n\n const inlineHookCalls = parseHookInline(stepInstruction)\n if (inlineHookCalls.length > 0) {\n let inlineHookFailed = false\n\n for (const call of inlineHookCalls) {\n const hookDef = this.resolvedHooks.get(call.hookId)\n if (!hookDef) {\n return {\n instruction: stepInstruction,\n originalStepName,\n executionLogs,\n preparationError: `Inline hook \"${call.hookId}\" is not defined in hooks.yaml`,\n }\n }\n\n const startedAt = performance.now()\n try {\n const result = await runHookInSandbox(hookDef, {\n envVars: this.getHookEnvVars(),\n secretStore: this.secretStore,\n secretRedactor: this.secretRedactor,\n })\n executionLogs.push({\n id: randomUUID(),\n type: 'hook',\n name: hookDef.name,\n hookId: hookDef.id,\n phase: 'inline',\n status: result.success ? 'passed' : 'failed',\n duration: result.duration,\n stdout: this.redact(result.stdout),\n stderr: this.redact(result.stderr),\n returnData: null,\n variables: Object.keys(result.variables).length > 0 ? this.redact(result.variables) : null,\n createdAt: new Date().toISOString(),\n })\n\n if (result.success) {\n if (Object.keys(result.variables).length > 0) {\n this.variableStore!.setAll(result.variables, 'hook')\n }\n } else {\n inlineHookFailed = true\n break\n }\n } catch (error) {\n executionLogs.push({\n id: randomUUID(),\n type: 'hook',\n name: hookDef.name,\n hookId: hookDef.id,\n phase: 'inline',\n status: 'failed',\n duration: performance.now() - startedAt,\n stdout: null,\n stderr: this.redact(error instanceof Error ? error.message : String(error)),\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n inlineHookFailed = true\n break\n }\n }\n\n instruction = stripHookInline(stepInstruction)\n hasTemplateVars = true\n\n if (inlineHookFailed) {\n return {\n instruction,\n originalStepName,\n executionLogs,\n preparationError: 'Inline hook execution failed',\n }\n }\n }\n\n instruction = interpolateVariables(instruction, this.variableStore!)\n hasTemplateVars = hasTemplateVars || originalStepName !== instruction\n\n const runJSMatches = parseRunJSInline(instruction)\n if (runJSMatches.length > 0) {\n if (this.adapter?.platform === 'web') {\n const page = 'getPage' in this.adapter\n ? (this.adapter as { getPage?: () => { evaluate: (code: string) => Promise<unknown> } | undefined }).getPage?.()\n : undefined\n\n if (page) {\n for (const match of runJSMatches) {\n const startedAt = performance.now()\n let status: 'passed' | 'failed' = 'passed'\n let stderr: string | null = null\n let stdout: string\n let returnData: unknown = null\n\n try {\n returnData = await page.evaluate(match.code)\n returnData = this.redact(returnData)\n stdout = this.redact(coerceRunJSResult(returnData))\n instruction = instruction.replace(match.fullMatch, stdout)\n } catch (err) {\n status = 'failed'\n stderr = this.redact(err instanceof Error ? err.message : String(err))\n stdout = `[runJS error: ${stderr}]`\n instruction = instruction.replace(match.fullMatch, stdout)\n }\n\n executionLogs.push({\n id: randomUUID(),\n type: 'runjs',\n name: match.code.slice(0, 200),\n phase: 'inline',\n status,\n duration: performance.now() - startedAt,\n stdout: status === 'passed' ? stdout : '',\n stderr,\n returnData,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n }\n } else {\n for (const match of runJSMatches) {\n const stdout = '[runJS error: no browser page available]'\n instruction = instruction.replace(\n match.fullMatch,\n stdout,\n )\n executionLogs.push({\n id: randomUUID(),\n type: 'runjs',\n name: match.code.slice(0, 200),\n phase: 'inline',\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: 'no browser page available',\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n }\n }\n } else {\n for (const match of runJSMatches) {\n const stdout = '[runJS error: runJS is only supported on web platform]'\n instruction = instruction.replace(\n match.fullMatch,\n stdout,\n )\n executionLogs.push({\n id: randomUUID(),\n type: 'runjs',\n name: match.code.slice(0, 200),\n phase: 'inline',\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: 'runJS is only supported on web platform',\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n }\n }\n hasTemplateVars = true\n }\n\n return {\n instruction,\n originalStepName: hasTemplateVars ? originalStepName : undefined,\n executionLogs,\n }\n }\n\n private buildPreparationFailureResult(\n instruction: string,\n error: string,\n originalStepName: string | undefined,\n executionLogs: LiveExecutionLog[],\n ): LiveStepExecutionResult {\n const result: LiveStepExecutionResult = {\n name: instruction,\n status: 'failed',\n duration: 0,\n error,\n trace: {\n observation: '',\n reasoning: error,\n plannedAction: { type: 'waitFor', condition: 'none', timeout: 0 },\n result: 'failure',\n error,\n screenStateBefore: '',\n },\n variableSnapshot: this.variableStore!.snapshot(),\n executionLogs,\n originalStepName,\n }\n return this.redact(result)\n }\n\n // Inner step execution — no gating. Callers must own the executing/status\n // lifecycle (executeStepCommand for single steps, executeTestCommand for\n // the per-test loop that runs many steps under one outer gate).\n private async executeStepInternal(\n stepInstruction: string,\n stepIndex: number | undefined,\n onPhase: ((event: StepPhaseEvent) => void) | undefined,\n draft: LiveDraftMetadata | undefined,\n ): Promise<LiveStepExecutionResult> {\n this.abortController = new AbortController()\n try {\n const prepared = await this.resolveStepInstruction(stepInstruction)\n if (prepared.preparationError) {\n const result = this.buildPreparationFailureResult(\n prepared.instruction,\n prepared.preparationError,\n prepared.originalStepName,\n prepared.executionLogs,\n )\n this.stepsExecuted++\n return result\n }\n const unresolvedTemplates = findUnresolvedTemplates(prepared.instruction)\n if (unresolvedTemplates.length > 0) {\n const errorLines = unresolvedTemplates.map((template) => ` - ${template.pattern}: ${template.message}`)\n const error = `Unresolved template variable(s):\\n${errorLines.join('\\n')}`\n const result = this.buildPreparationFailureResult(\n prepared.instruction,\n error,\n prepared.originalStepName,\n prepared.executionLogs,\n )\n this.stepsExecuted++\n return result\n }\n\n const loopConfig: AgentLoopConfig = {\n adapter: this.adapter!,\n planner: this.planner!,\n verifier: this.verifier!,\n healingConfig: { maxAttempts: 3 },\n plannerConfig: { maxSubActions: 50, previousStepCount: 5 },\n screenshotSize: this.screenshotSize,\n effectiveResolution: this.effectiveResolution,\n onSetVariable: (name, value) => this.variableStore!.set(name, value, 'step'),\n onPhase,\n stepIndex,\n abortSignal: this.abortController.signal,\n secretStore: this.secretStore,\n secretRedactor: this.secretRedactor,\n }\n\n const allVars = this.variableStore!.getAll()\n const variables: Record<string, string> = {}\n for (const [k, v] of allVars) variables[k] = v\n\n const stepContext: StepContext = {\n stepInstruction: prepared.instruction,\n testName: draft?.testName?.trim() || 'Unnamed live draft',\n testContext: draft?.testContext?.trim() || undefined,\n previousSteps: this.previousSteps,\n plannerModel: this.model!,\n verifierModel: this.model!,\n healingConfig: { maxAttempts: 3 },\n variables: this.redact(variables),\n }\n\n let result = await executeStep(prepared.instruction, loopConfig, stepContext) as LiveStepExecutionResult\n result.originalStepName = prepared.originalStepName\n result.variableSnapshot = this.variableStore!.snapshot()\n result.executionLogs = this.redact(prepared.executionLogs)\n result.subActionsData = toLiveSubActionData(result)\n if ('pollDeviceLogs' in this.adapter! && typeof (this.adapter as { pollDeviceLogs?: () => Promise<void> }).pollDeviceLogs === 'function') {\n await (this.adapter as { pollDeviceLogs: () => Promise<void> }).pollDeviceLogs()\n }\n result.consoleLogs = this.adapter!.drainConsoleLogs?.()\n result.networkLogs = this.adapter!.drainNetworkLogs?.()\n result = this.redact(result)\n\n if (result.status !== 'cancelled') {\n this.previousSteps.push({ instruction: prepared.instruction, outcome: result.status })\n }\n this.stepsExecuted++\n return result\n } finally {\n this.abortController = null\n }\n }\n\n async executeStepCommand(\n stepInstruction: string,\n stepIndex?: number,\n onPhase?: (event: StepPhaseEvent) => void,\n draft?: LiveDraftMetadata,\n ): Promise<LiveStepExecutionResult> {\n if (!this.readyForInteraction || !this.adapter || !this.model || !this.planner || !this.verifier || !this.variableStore) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n\n if (this.executing) {\n throw new Error('Step already executing')\n }\n\n this.executing = true\n this.status = 'executing'\n this.currentStep = stepInstruction\n try {\n return await this.executeStepInternal(stepInstruction, stepIndex, onPhase, draft)\n } finally {\n this.executing = false\n this.currentStep = null\n this.status = 'idle'\n }\n }\n\n async executeTestCommand(\n testExecutionId: string,\n testDraft: {\n testIndex: number\n testId: string\n testName: string\n testContext?: string\n steps: string[]\n setup: string[]\n teardown: string[]\n },\n onPhase?: (event: StepPhaseEvent) => void,\n ): Promise<LiveTestResultPayload> {\n if (!this.readyForInteraction || !this.adapter || !this.model || !this.planner || !this.verifier || !this.variableStore) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n\n if (this.executing) {\n throw new Error('Test already executing')\n }\n\n this.executing = true\n this.status = 'executing'\n this.currentStep = `test: ${testDraft.testName}`\n const start = performance.now()\n const testExecution: LiveTestExecutionPayload = {\n testExecutionId,\n testIndex: testDraft.testIndex,\n testId: testDraft.testId,\n testName: testDraft.testName,\n }\n const testOwner: LiveHookOwner = {\n scope: 'test',\n testExecutionId,\n testIndex: testDraft.testIndex,\n testId: testDraft.testId,\n testName: testDraft.testName,\n }\n\n try {\n // Per-test setup (D-09). Per-test setup failure short-circuits the\n // test AND skips per-test teardown, matching suite/runner.ts:230 break\n // (Pitfall 2). Suite-level teardown still fires at session cleanup.\n const setupHookPayloads: LiveHookPayload[] = []\n const setupResult = await this.runLifecycleHooksCapturing(\n 'setup',\n testDraft.setup,\n setupHookPayloads,\n testOwner,\n )\n if (!setupResult.allPassed) {\n const failedHook = setupHookPayloads.find((h) => h.status === 'failed')\n const detail = failedHook\n ? `Setup hook \"${failedHook.hookName}\" failed${failedHook.error ? `: ${failedHook.error}` : ''}${failedHook.stderr ? ` — ${failedHook.stderr.split('\\n')[0].slice(0, 200)}` : ''}`\n : 'Per-test setup hook failed'\n console.warn(`[live-session] executeTestCommand: ${detail}`, {\n testName: testDraft.testName,\n setupHooks: testDraft.setup,\n failedHook: failedHook ? { name: failedHook.hookName, stderr: failedHook.stderr, error: failedHook.error } : null,\n })\n return {\n status: 'failed',\n duration: performance.now() - start,\n error: detail,\n setupHookExecutions: setupHookPayloads,\n stepResults: [],\n teardownHookExecutions: [],\n }\n }\n\n // Shared browser context (D-01): each step reuses the same adapter\n // instance. Per-step context carries the TEST's name/context, not\n // the suite's, so the LLMPlanner matches production runTest behaviour.\n const stepResults: LiveStepResultPayload[] = []\n const perStepDraft: LiveDraftMetadata = {\n testName: testDraft.testName,\n testContext: testDraft.testContext,\n }\n let anyCancelled = false\n let anyFailed = false\n for (let i = 0; i < testDraft.steps.length; i++) {\n const stepPayload: LiveTestStepPayload = {\n ...testExecution,\n stepIndex: i,\n stepInstruction: testDraft.steps[i],\n }\n this.emitTestStepStart(stepPayload)\n\n let execResult: LiveStepExecutionResult\n try {\n execResult = await this.executeStepInternal(\n testDraft.steps[i],\n i,\n (event) => {\n this.emitTestStepPhase(stepPayload, event)\n onPhase?.(event)\n },\n perStepDraft,\n )\n } catch (error) {\n const message = this.redact(error instanceof Error ? error.message : String(error))\n this.emitTestStepError(stepPayload, message)\n stepResults.push({\n status: 'failed',\n duration: 0,\n error: message,\n })\n anyFailed = true\n break\n }\n\n this.emitTestStepComplete(stepPayload, execResult)\n stepResults.push(toStepResultPayload(execResult))\n if (execResult.status === 'cancelled') {\n anyCancelled = true\n break\n }\n if (execResult.status === 'failed') {\n anyFailed = true\n break\n }\n }\n\n // Per-test teardown always fires when steps began (D-09 + D-25).\n const teardownHookPayloads: LiveHookPayload[] = []\n const teardownResult = await this.runLifecycleHooksCapturing(\n 'teardown',\n testDraft.teardown,\n teardownHookPayloads,\n testOwner,\n )\n\n const finalStatus: LiveTestResultPayload['status'] = anyCancelled\n ? 'cancelled'\n : anyFailed || !teardownResult.allPassed\n ? 'failed'\n : 'passed'\n\n let topLevelError: string | undefined\n if (anyFailed) {\n const failedStep = stepResults.find((s) => s.status === 'failed')\n if (failedStep) {\n const stepIdx = stepResults.indexOf(failedStep)\n topLevelError = `Step ${stepIdx + 1} (${testDraft.steps[stepIdx] ?? '<unknown>'}) failed${failedStep.error ? `: ${failedStep.error}` : ''}`\n }\n } else if (!teardownResult.allPassed) {\n const failedHook = teardownHookPayloads.find((h) => h.status === 'failed')\n topLevelError = failedHook\n ? `Teardown hook \"${failedHook.hookName}\" failed${failedHook.error ? `: ${failedHook.error}` : ''}`\n : 'Teardown hook failed'\n }\n if (topLevelError) {\n console.warn(`[live-session] executeTestCommand: ${topLevelError}`, { testName: testDraft.testName })\n }\n\n return this.redact({\n status: finalStatus,\n duration: performance.now() - start,\n error: topLevelError,\n setupHookExecutions: setupHookPayloads,\n stepResults,\n teardownHookExecutions: teardownHookPayloads,\n })\n } finally {\n this.executing = false\n this.currentStep = null\n this.status = 'idle'\n }\n }\n\n // Thin wrapper around runLifecycleHooks that also captures the dispatched\n // hook payloads (hook-start / hook-complete) for inclusion in the\n // LiveTestResultPayload. Uses a sink intercept so existing callers of\n // runLifecycleHooks (executeHookCommand, initialize, cleanup) keep their\n // current behaviour unchanged.\n private async runLifecycleHooksCapturing(\n phase: 'setup' | 'teardown',\n hookIds: string[],\n sink: LiveHookPayload[],\n owner: LiveHookOwner = { scope: 'suite' },\n ): Promise<{ allPassed: boolean; logs: LiveExecutionLog[] }> {\n const originalSink = this.messageSink\n const wrappedSink = (message: ServerMessage) => {\n if (message.type === 'hook-complete') {\n sink.push(message.hook)\n }\n if (originalSink) originalSink(message)\n else this.pendingMessages.push(message)\n }\n this.messageSink = wrappedSink\n try {\n return await this.runLifecycleHooks(phase, hookIds, owner)\n } finally {\n this.messageSink = originalSink\n }\n }\n\n cancelStep(): void {\n this.abortController?.abort()\n }\n\n async navigate(url: string): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n const resolvedUrl = this.resolveSecrets(url)\n await this.adapter!.execute({ type: 'navigate', url: resolvedUrl })\n if (this.platform === 'web') {\n this.currentUrl = resolvedUrl\n } else {\n this.currentUrl = null\n }\n return this.currentUrl\n }\n\n async refreshPage(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n if (this.platform !== 'web') return this.currentUrl\n await this.adapter!.execute({ type: 'refresh' })\n const page = (this.adapter as any).getPage?.()\n if (page) this.currentUrl = page.url()\n return this.currentUrl ?? 'about:blank'\n }\n\n async goBack(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n if (this.platform !== 'web') return this.currentUrl\n await this.adapter!.execute({ type: 'navigateHistory', direction: 'back' })\n const page = (this.adapter as any).getPage?.()\n if (page) this.currentUrl = page.url()\n return this.currentUrl ?? 'about:blank'\n }\n\n async goForward(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n if (this.platform !== 'web') return this.currentUrl\n await this.adapter!.execute({ type: 'navigateHistory', direction: 'forward' })\n const page = (this.adapter as any).getPage?.()\n if (page) this.currentUrl = page.url()\n return this.currentUrl ?? 'about:blank'\n }\n\n async drainDeviceLogs(): Promise<Array<{ level: string; message: string; timestamp: number }>> {\n if (!this.adapter) return []\n if (typeof (this.adapter as any).pollDeviceLogs === 'function') {\n await (this.adapter as any).pollDeviceLogs()\n }\n if (typeof this.adapter.drainConsoleLogs === 'function') {\n return this.redact(this.adapter.drainConsoleLogs().map((e) => ({ level: e.level, message: e.text, timestamp: e.timestamp })))\n }\n return []\n }\n\n getState(): SessionState {\n return {\n sessionId: this.sessionId,\n platform: (this.adapter?.platform ?? this.platform) as 'web' | 'android' | 'ios',\n status: this.status === 'terminated' ? 'idle' : this.status === 'executing' ? 'executing' : this.status,\n currentStep: this.currentStep,\n currentUrl: this.currentUrl,\n stepsExecuted: this.stepsExecuted,\n createdAt: this.createdAt,\n interactive: this.readyForInteraction,\n terminalError: this.terminalError,\n }\n }\n\n async getScreenshot(): Promise<Buffer | undefined> {\n if (!this.readyForInteraction) return undefined\n return this.adapter?.screenshot?.()\n }\n\n async getAriaTree(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) return null\n if (!this.adapter) return null\n const screenState = await this.adapter.observe()\n return screenState.tree\n }\n\n startIdleTimer(onExpire: () => void): void {\n this.clearIdleTimer()\n this.idleTimer = setTimeout(onExpire, IDLE_TIMEOUT_MS)\n }\n\n clearIdleTimer(): void {\n if (this.idleTimer) {\n clearTimeout(this.idleTimer)\n this.idleTimer = null\n }\n }\n\n async cleanup(): Promise<void> {\n this.clearIdleTimer()\n this.readyForInteraction = false\n try {\n await this.adapter?.cleanup()\n } finally {\n try {\n await this.runLifecycleHooks('teardown', this.teardownHooks)\n } finally {\n this.releaseMobileAppiumLease('session-cleanup')\n this.messageSink = null\n this.status = 'terminated'\n }\n }\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { parse as parseYaml } from 'yaml'\nimport {\n MobileSetupError,\n resolveMobileRunConfig,\n} from '@vostride/agent-qa-core'\nimport type {\n MobilePlatform,\n PlatformConfig,\n ResolvedMobileRunConfig,\n} from '@vostride/agent-qa-core'\nimport type { AppiumManager } from '../execution/appium-manager.js'\nimport type { ConfigManager } from '../config/index.js'\n\ninterface LocalMobileBindings {\n devices?: Record<string, Record<string, unknown>>\n providers?: Record<string, Record<string, unknown>>\n apps?: Record<string, { path?: string; browserstack?: string }>\n filePath?: string\n}\n\nexport interface MobileLiveAppiumLease {\n runId: string\n url: string\n release: (reason?: string) => boolean\n}\n\nexport interface PreparedMobileLiveSession {\n platformConfig: PlatformConfig\n appiumLease: MobileLiveAppiumLease\n resolved: ResolvedMobileRunConfig\n}\n\nexport interface PrepareMobileLiveSessionInput {\n sessionId: string\n platform: MobilePlatform\n targetName?: string\n useDeviceName?: string\n appState?: 'preserve' | 'reset'\n configManager: ConfigManager\n configPath: string\n appiumManager: AppiumManager\n}\n\nasync function loadLocalBindings(configPath: string): Promise<LocalMobileBindings | null> {\n const filePath = join(dirname(configPath), 'agent-qa.local.yaml')\n try {\n const content = await readFile(filePath, 'utf-8')\n const parsed = parseYaml(content) as LocalMobileBindings | null\n return parsed && typeof parsed === 'object'\n ? {\n devices: parsed.devices,\n providers: parsed.providers,\n apps: parsed.apps,\n filePath,\n }\n : { filePath }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null\n throw err\n }\n}\n\nfunction asMobileSetupError(\n err: unknown,\n category: MobileSetupError['category'],\n message: string,\n input: Pick<PrepareMobileLiveSessionInput, 'platform' | 'targetName'>,\n): MobileSetupError {\n if (err instanceof MobileSetupError) return err\n return new MobileSetupError({\n category,\n message: `${message}: ${err instanceof Error ? err.message : String(err)}`,\n platform: input.platform,\n targetName: input.targetName,\n cause: err,\n })\n}\n\nexport async function prepareMobileLiveSession(\n input: PrepareMobileLiveSessionInput,\n): Promise<PreparedMobileLiveSession> {\n if (!input.targetName) {\n throw new MobileSetupError({\n category: 'device-resolution',\n message: `No targetName provided for ${input.platform} live session`,\n platform: input.platform,\n })\n }\n\n const config = await input.configManager.read()\n let localBindings: LocalMobileBindings | null = null\n\n try {\n localBindings = await loadLocalBindings(input.configPath)\n } catch (err) {\n throw asMobileSetupError(err, 'device-resolution', 'Failed to read local device bindings', input)\n }\n\n const configuredAppState = (config.use as { mobile?: { appState?: 'preserve' | 'reset' } } | undefined)?.mobile?.appState\n\n let resolved: ResolvedMobileRunConfig\n try {\n resolved = resolveMobileRunConfig({\n config,\n targetName: input.targetName,\n platform: input.platform,\n useDeviceName: input.useDeviceName,\n appState: input.appState ?? configuredAppState,\n localBindings,\n configFilePath: input.configPath,\n localConfigFilePath: localBindings?.filePath,\n })\n } catch (err) {\n throw asMobileSetupError(err, 'device-resolution', 'Failed to resolve mobile live target', input)\n }\n\n try {\n await input.appiumManager.acquireLease({ runId: input.sessionId, platform: input.platform })\n } catch (err) {\n throw new MobileSetupError({\n category: 'appium-startup',\n message: `Failed to acquire Appium for ${input.platform} live session: ${err instanceof Error ? err.message : String(err)}`,\n platform: input.platform,\n targetName: input.targetName,\n deviceName: resolved.deviceName,\n appId: resolved.app.deepLinkAppId,\n sourceTrace: resolved.sourceTrace,\n cause: err,\n })\n }\n\n const appiumUrl = input.appiumManager.getUrl()\n let released = false\n const appiumLease: MobileLiveAppiumLease = {\n runId: input.sessionId,\n url: appiumUrl,\n release: (reason = 'completed') => {\n if (released) return false\n released = true\n return input.appiumManager.releaseLease(input.sessionId, reason)\n },\n }\n\n return {\n resolved: {\n ...resolved,\n appium: {\n url: appiumUrl,\n managed: true,\n },\n },\n appiumLease,\n platformConfig: {\n platform: input.platform,\n device: resolved.device,\n appiumUrl,\n bundleId: resolved.app.bundleId,\n appPackage: resolved.app.appPackage,\n appActivity: resolved.app.appActivity,\n deepLinkAppId: resolved.app.deepLinkAppId,\n appPath: resolved.app.install?.path,\n browserstackApp: resolved.app.install?.browserstack,\n appState: resolved.appState,\n },\n }\n}\n","import type WebSocket from 'ws'\nimport { parseTestFile } from '@vostride/agent-qa-core'\nimport type { LiveSession } from './live-session.js'\nimport type {\n LiveStepResultPayload,\n ServerMessage,\n} from './types.js'\nimport type { TestFileManager } from '../tests/test-file-manager.js'\n\nfunction send(ws: WebSocket, msg: ServerMessage): void {\n if (ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify(msg))\n }\n}\n\nfunction toStepResultPayload(result: Awaited<ReturnType<LiveSession['executeStepCommand']>>): LiveStepResultPayload {\n const status = result.status === 'passed'\n ? 'passed'\n : result.status === 'cancelled'\n ? 'cancelled'\n : 'failed'\n\n return {\n status,\n duration: result.duration,\n error: result.error,\n capturedVariables: result.capturedVariables,\n variableSnapshot: result.variableSnapshot,\n originalStepName: result.originalStepName,\n consoleLogs: result.consoleLogs,\n networkLogs: result.networkLogs,\n executionLogs: result.executionLogs,\n subActionsData: result.subActionsData,\n }\n}\n\nexport function createSessionHandler(\n session: LiveSession,\n onTerminate: () => void,\n onTokenUsage?: (event: { modelName: string; promptTokens: number; completionTokens: number; source: 'live-editor' }) => void,\n testFileManager?: TestFileManager,\n): (ws: WebSocket) => void {\n return (ws: WebSocket) => {\n let cleanedUp = false\n\n async function cleanupSession(): Promise<void> {\n if (cleanedUp) return\n cleanedUp = true\n if (logPollInterval) clearInterval(logPollInterval)\n if (session.status !== 'terminated') {\n await session.cleanup()\n }\n onTerminate()\n }\n\n session.clearIdleTimer()\n\n const state = session.getState()\n send(ws, {\n type: 'session-ready',\n sessionId: session.sessionId,\n platform: state.platform,\n interactive: state.interactive,\n error: state.terminalError,\n })\n session.attachMessageSink((message) => {\n send(ws, message)\n })\n send(ws, { type: 'session-state', state })\n\n let logPollInterval: ReturnType<typeof setInterval> | null = null\n const platform = state.platform\n if (platform !== 'web' && state.interactive) {\n logPollInterval = setInterval(async () => {\n if (session.status === 'executing') {\n return\n }\n try {\n const entries = await session.drainDeviceLogs()\n if (entries.length > 0) {\n send(ws, { type: 'device-logs', entries })\n }\n } catch {}\n }, 2000)\n }\n\n ws.on('message', async (data) => {\n let msg: any\n try {\n msg = JSON.parse(data.toString())\n } catch {\n send(ws, { type: 'error', message: 'Invalid JSON' })\n return\n }\n\n switch (msg.type) {\n case 'execute-step': {\n if (session.status === 'executing') {\n send(ws, {\n type: 'step-busy',\n currentStep: session.getState().currentStep ?? 'unknown',\n })\n return\n }\n try {\n const result = await session.executeStepCommand(\n msg.stepInstruction,\n msg.stepIndex,\n (phase) => {\n send(ws, {\n type: 'step-phase',\n phase: phase.phase,\n data: {\n text: phase.text,\n confidence: phase.confidence,\n action: phase.action,\n success: phase.success,\n duration: phase.duration,\n },\n })\n },\n msg.draft,\n )\n if (result.status === 'cancelled') {\n send(ws, { type: 'step-cancelled' })\n } else {\n send(ws, {\n type: 'step-complete',\n result: toStepResultPayload(result),\n })\n if (onTokenUsage && result.trace?.tokenUsage &&\n (result.trace.tokenUsage.promptTokens > 0 || result.trace.tokenUsage.completionTokens > 0)) {\n onTokenUsage({\n modelName: session.modelName,\n promptTokens: result.trace.tokenUsage.promptTokens,\n completionTokens: result.trace.tokenUsage.completionTokens,\n source: 'live-editor',\n })\n }\n try {\n const tree = await session.getAriaTree()\n if (tree) send(ws, { type: 'aria-tree', tree })\n } catch {}\n }\n send(ws, { type: 'session-state', state: session.getState() })\n const adapter = (session as any).adapter\n if (adapter && typeof adapter.isBrowserDisconnected === 'boolean' && adapter.isBrowserDisconnected) {\n send(ws, { type: 'browser-disconnected' })\n }\n } catch (err: any) {\n send(ws, { type: 'step-error', error: err.message })\n const adapter = (session as any).adapter\n if (adapter && typeof adapter.isBrowserDisconnected === 'boolean' && adapter.isBrowserDisconnected) {\n send(ws, { type: 'browser-disconnected' })\n }\n }\n break\n }\n\n case 'execute-hook': {\n if (session.status === 'executing') {\n send(ws, {\n type: 'step-busy',\n currentStep: session.getState().currentStep ?? 'unknown',\n })\n return\n }\n try {\n await session.executeHookCommand(msg.phase, msg.hookId)\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'execute-test': {\n if (session.status === 'executing') {\n send(ws, {\n type: 'step-busy',\n currentStep: session.getState().currentStep ?? 'unknown',\n })\n return\n }\n try {\n if (!testFileManager) {\n throw new Error('Test file manager unavailable — configure workspace.testMatch to run tests live')\n }\n\n let raw: string\n try {\n raw = await testFileManager.read(msg.path)\n } catch (readErr: any) {\n console.error(`[ws-handler] execute-test: read failed for path=${msg.path}`, readErr)\n throw new Error(`Cannot read test file \"${msg.path}\": ${readErr?.message ?? String(readErr)}`)\n }\n\n const parsed = parseTestFile(raw, msg.path)\n if (parsed.errors.length > 0) {\n console.error(`[ws-handler] execute-test: parse errors for ${msg.path}`, parsed.errors)\n throw new Error(`Parse error in ${msg.path}: ${parsed.errors[0].message}`)\n }\n const testDef = parsed.tests[0]\n if (!testDef) {\n throw new Error(`Test file \"${msg.path}\" is empty or has no valid test documents`)\n }\n const stepInstructions: string[] = testDef.steps.map((s: string | { step: string }) =>\n typeof s === 'string' ? s : s.step,\n )\n console.log(`[ws-handler] execute-test: starting \"${testDef.name}\" (${stepInstructions.length} steps, setup=${(testDef.setup ?? []).length}, teardown=${(testDef.teardown ?? []).length})`)\n\n send(ws, {\n type: 'test-start',\n test: {\n testExecutionId: msg.testExecutionId,\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: testDef.name,\n },\n })\n\n const result = await session.executeTestCommand(\n msg.testExecutionId,\n {\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: testDef.name,\n testContext: testDef.context,\n steps: stepInstructions,\n setup: testDef.setup ?? [],\n teardown: testDef.teardown ?? [],\n },\n )\n\n console.log(`[ws-handler] execute-test: finished \"${testDef.name}\" status=${result.status} duration=${result.duration}ms${result.error ? ` error=${result.error}` : ''}`)\n send(ws, {\n type: 'test-complete',\n test: {\n testExecutionId: msg.testExecutionId,\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: testDef.name,\n },\n result,\n })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n console.error(`[ws-handler] execute-test: caught error for path=${msg.path}`, {\n message: err?.message,\n stack: err?.stack,\n code: err?.code,\n })\n send(ws, {\n type: 'test-error',\n test: {\n testExecutionId: msg.testExecutionId,\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: msg.path.split(/[\\\\/]/).pop() ?? msg.path,\n },\n error: err?.message ?? String(err),\n })\n send(ws, { type: 'session-state', state: session.getState() })\n }\n break\n }\n\n case 'cancel-step': {\n session.cancelStep()\n break\n }\n\n case 'terminate-session': {\n await cleanupSession()\n send(ws, { type: 'session-terminated' })\n ws.close(1000, 'Session terminated')\n break\n }\n\n case 'get-screenshot': {\n const buf = await session.getScreenshot()\n if (buf) {\n send(ws, { type: 'screenshot', data: buf.toString('base64') })\n } else {\n send(ws, { type: 'error', message: 'Screenshot unavailable' })\n }\n break\n }\n\n case 'get-state': {\n send(ws, { type: 'session-state', state: session.getState() })\n break\n }\n\n case 'navigate': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.navigate(msg.url)\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'refresh-page': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.refreshPage()\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'go-back': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.goBack()\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'go-forward': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.goForward()\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'get-aria-tree': {\n if (session.status === 'executing') {\n send(ws, { type: 'error', message: 'Cannot inspect ARIA tree while step is executing' })\n return\n }\n try {\n const tree = await session.getAriaTree()\n if (tree) {\n send(ws, { type: 'aria-tree', tree })\n } else {\n send(ws, { type: 'error', message: 'ARIA tree unavailable' })\n }\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n default: {\n send(ws, { type: 'error', message: `Unknown message type: ${msg.type}` })\n break\n }\n }\n })\n\n ws.on('close', () => {\n session.attachMessageSink(null)\n void cleanupSession()\n })\n\n ws.on('error', () => {\n session.attachMessageSink(null)\n void cleanupSession()\n })\n }\n}\n"],"mappings":"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","names":["dirname","createBetterSqlite3Database","generateRunId","relativePath","sourcePath","mkdirSync","dirname","resolve","DEFAULT_AGENT_QA_RUNS_DB_PATH","copyFile","mkdir","rename","unlink","basename","dirname","isAbsolute","relative","resolve","readFile","stat","join","resolve","cpus","randomUUID","readFile","writeFile","stat","readdir","rm","join","isAbsolute","basename","resolve","dirname","relative","readFile","stat","dirname","join","resolve","discoverWorkspaceFiles","parseYaml","readFile","writeFile","mkdir","stat","dirname","basename","parseTestFile","resolve","join","stat","dirname","discoverWorkspaceFiles","readFile","parseYaml","mkdir","readFile","rm","stat","writeFile","basename","dirname","isAbsolute","relative","resolve","resolveWorkspacePaths","parseYaml","readFile","basename","AgentQaConfigSchema","discoverWorkspaceFiles","resolveWorkspacePaths","parseYaml","readFile","dirname","resolve","rm","mkdir","writeFile","isAbsolute","parseYaml","stat","resolveWorkspacePaths","relative","basename","resolve","buildInternalRunAttributes","AgentQaConfigSchema","discoverWorkspaceFiles","resolveMemoryRoot","resolveWorkspaceFileTarget","parseYaml","relative","isAbsolute","basename","isRecord","resolve","join","rm","readFile","stat","path","randomUUID","llmConfig","createModel","dirname","readdir","writeFile","EventEmitter","readFile","writeFile","mkdir","stat","rm","dirname","basename","parseYaml","discoverWorkspaceFiles","resolveWorkspaceFileTarget","SuiteDefinitionSchema","readFile","writeFile","mkdir","dirname","parseDocument","spawn","treeKill","resolve","randomUUID","randomUUID","getProviderOptions","runHookInSandbox","MobileSetupError","redactSecretValue","readFile","dirname","join","parseYaml","MobileSetupError","redactSecretValue","randomUUID","completed","getProviderOptions","runHookInSandbox","result","randomUUID","toStepResultPayload","buildAnalyticsEvent","captureAnalytics","resolveAnalyticsStandardProperties","resolve","cpus","join","stat","readFile","request"]}
|
|
1
|
+
{"version":3,"sources":["../src/db/schema.ts","../src/db/database.ts","../src/db/run-id-migration.ts","../src/db/runtime-db-path.ts","../src/reporter/dashboard-reporter.ts","../src/server/server.ts","../src/server/routes.ts","../src/memory/memory-catalog-manager.ts","../src/tests/test-file-manager.ts","../src/hooks/hook-registry-manager.ts","../src/hooks/hook-reference-scan.ts","../src/server/body-parser.ts","../src/execution/test-runner.ts","../src/queue/job-queue.ts","../src/tests/suite-file-manager.ts","../src/config/config-manager.ts","../src/execution/appium-manager.ts","../src/live-editor/session-manager.ts","../src/live-editor/live-session.ts","../src/live-editor/mobile-bootstrap.ts","../src/live-editor/ws-handler.ts"],"sourcesContent":["export const SCHEMA_VERSION = 1\n\nexport interface DashboardMigration {\n version: number\n sql: string[]\n}\n\nexport const MIGRATIONS: DashboardMigration[] = [\n {\n version: 1,\n sql: [\n `CREATE TABLE IF NOT EXISTS runs (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n file_path TEXT,\n status TEXT NOT NULL CHECK(status IN ('passed','failed','skipped','running','cancelled','pending','flaky')),\n priority INTEGER NOT NULL DEFAULT 0,\n duration INTEGER NOT NULL DEFAULT 0,\n attributes TEXT NOT NULL DEFAULT '{}',\n environment TEXT,\n metadata TEXT,\n started_at TEXT,\n ended_at TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n video_path TEXT,\n failure_summary TEXT,\n platform TEXT DEFAULT 'web',\n test_file_content TEXT,\n model_name TEXT,\n llm_provider TEXT,\n parallel INTEGER DEFAULT 0,\n parent_run_id TEXT,\n attempt_number INTEGER DEFAULT 0,\n retry_count INTEGER DEFAULT 0,\n max_retries INTEGER DEFAULT 0,\n error_log TEXT,\n memory_log TEXT,\n test_id TEXT,\n suite_id TEXT\n )`,\n `CREATE TABLE IF NOT EXISTS steps (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES runs(id),\n name TEXT NOT NULL,\n status TEXT NOT NULL CHECK(status IN ('passed','failed','healed','skipped','cancelled')),\n duration INTEGER NOT NULL DEFAULT 0,\n action TEXT,\n observation TEXT,\n reasoning TEXT,\n planned_action TEXT,\n result TEXT CHECK(result IN ('success','failure')),\n error TEXT,\n screenshot_path TEXT,\n screenshot_before_path TEXT,\n healing_attempts TEXT,\n retry_count INTEGER DEFAULT 0,\n captured_variables TEXT,\n step_order INTEGER NOT NULL DEFAULT 0,\n annotation_data TEXT,\n healing_screenshot_paths TEXT,\n accessibility_violations TEXT,\n confidence REAL,\n prompt_tokens INTEGER DEFAULT 0,\n completion_tokens INTEGER DEFAULT 0,\n total_tokens INTEGER DEFAULT 0,\n sub_actions_data TEXT,\n console_logs TEXT,\n network_logs TEXT,\n variable_snapshot TEXT,\n original_step_name TEXT,\n screen_context_before TEXT,\n screen_context_after TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n `CREATE TABLE IF NOT EXISTS reasoning_traces (\n id TEXT PRIMARY KEY,\n step_id TEXT NOT NULL REFERENCES steps(id),\n observe_text TEXT,\n observe_duration INTEGER,\n plan_reasoning TEXT,\n plan_confidence REAL,\n plan_action TEXT,\n plan_duration INTEGER,\n execute_action TEXT,\n execute_duration INTEGER,\n verify_reasoning TEXT,\n verify_success INTEGER,\n verify_duration INTEGER,\n heal_attempts TEXT,\n total_duration INTEGER,\n screen_state_before TEXT,\n screen_state_after TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n `CREATE TABLE IF NOT EXISTS logs (\n id TEXT PRIMARY KEY,\n step_id TEXT REFERENCES steps(id) ON DELETE CASCADE,\n run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,\n level TEXT NOT NULL CHECK(level IN ('debug','info','warn','error')),\n source TEXT NOT NULL CHECK(source IN ('agent','adapter','cache','planner','healer','hook','runner')),\n message TEXT NOT NULL,\n data TEXT,\n timestamp TEXT NOT NULL\n )`,\n `CREATE TABLE IF NOT EXISTS execution_logs (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,\n step_id TEXT,\n type TEXT NOT NULL CHECK(type IN ('hook', 'appium-script', 'runjs')),\n name TEXT NOT NULL,\n phase TEXT NOT NULL CHECK(phase IN ('setup', 'teardown', 'inline')),\n status TEXT NOT NULL CHECK(status IN ('passed', 'failed')),\n duration INTEGER NOT NULL DEFAULT 0,\n stdout TEXT,\n stderr TEXT,\n return_data TEXT,\n variables TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n hook_id TEXT\n )`,\n `CREATE TABLE IF NOT EXISTS token_events (\n id TEXT PRIMARY KEY,\n model_name TEXT NOT NULL,\n prompt_tokens INTEGER NOT NULL DEFAULT 0,\n completion_tokens INTEGER NOT NULL DEFAULT 0,\n source TEXT NOT NULL CHECK(source IN ('test-run', 'live-editor')),\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n `CREATE TABLE IF NOT EXISTS run_artifacts (\n run_id TEXT PRIMARY KEY REFERENCES runs(id) ON DELETE CASCADE,\n kind TEXT NOT NULL CHECK(kind IN ('test', 'suite-parent', 'suite-child', 'unknown')),\n schema_version INTEGER NOT NULL,\n payload TEXT NOT NULL DEFAULT '{}',\n finalized_at TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n 'CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_started_at ON runs(started_at)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_name ON runs(name)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_queue ON runs(status, priority, created_at)',\n 'CREATE INDEX IF NOT EXISTS idx_runs_parent ON runs(parent_run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_steps_run_id ON steps(run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_reasoning_traces_step_id ON reasoning_traces(step_id)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_step_id ON logs(step_id)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_run_id ON logs(run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_level ON logs(level)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_source ON logs(source)',\n 'CREATE INDEX IF NOT EXISTS idx_logs_run_level_source ON logs(run_id, level, source)',\n 'CREATE INDEX IF NOT EXISTS idx_execution_logs_run_id ON execution_logs(run_id)',\n 'CREATE INDEX IF NOT EXISTS idx_execution_logs_step_id ON execution_logs(step_id)',\n 'CREATE INDEX IF NOT EXISTS idx_execution_logs_type ON execution_logs(type)',\n 'CREATE INDEX IF NOT EXISTS idx_token_events_model ON token_events(model_name)',\n 'CREATE INDEX IF NOT EXISTS idx_token_events_source ON token_events(source)',\n 'CREATE INDEX IF NOT EXISTS idx_token_events_created ON token_events(created_at)',\n 'CREATE INDEX IF NOT EXISTS idx_run_artifacts_kind ON run_artifacts(kind)',\n 'CREATE INDEX IF NOT EXISTS idx_run_artifacts_finalized ON run_artifacts(finalized_at)',\n ],\n },\n]\n","import { randomUUID } from 'node:crypto'\nimport { mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { MIGRATIONS, SCHEMA_VERSION, type DashboardMigration } from './schema.js'\nimport {\n createBetterSqlite3Database,\n DEFAULT_AGENT_QA_RUNS_DB_PATH,\n generateRunId,\n RUN_ARTIFACT_SCHEMA_VERSION,\n type BetterSqlite3Database,\n type LogEntry,\n type LogStorage,\n type RunArtifactFinalizeInput,\n type RunArtifactKind,\n type RunArtifactPayload,\n type RunArtifactStageInput,\n type RunAttributes,\n} from '@vostride/agent-qa-core'\n\nconst DASHBOARD_DB_PATH_FALLBACK = DEFAULT_AGENT_QA_RUNS_DB_PATH || '.agent-qa/runs.db'\n\nexport interface RunRow {\n id: string\n name: string\n filePath: string | null\n status: string\n priority: number\n duration: number\n attributes: RunAttributes\n environment: string | null\n metadata: Record<string, unknown> | null\n startedAt: string | null\n endedAt: string | null\n videoPath: string | null\n failureSummary: string | null\n errorLog: string | null\n memoryLog: string | null\n testId: string | null\n suiteId: string | null\n platform: string\n testFileContent: string | null\n modelName: string | null\n llmProvider: string | null\n parallel: boolean\n parentRunId: string | null\n attemptNumber: number\n retryCount: number\n maxRetries: number\n createdAt: string\n}\n\nexport interface RunArtifactRow {\n runId: string\n kind: RunArtifactKind\n schemaVersion: number\n payload: RunArtifactPayload\n finalizedAt: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface RunArtifactBundle {\n artifact: RunArtifactRow | null\n children: Array<{ run: RunRow; artifact: RunArtifactRow | null }>\n}\n\nexport interface StepRow {\n id: string\n runId: string\n name: string\n status: string\n duration: number\n action: unknown | null\n observation: string | null\n reasoning: string | null\n plannedAction: unknown | null\n result: string | null\n error: string | null\n screenshotPath: string | null\n screenshotBeforePath: string | null\n healingAttempts: unknown[] | null\n retryCount: number\n capturedVariables: Record<string, string> | null\n stepOrder: number\n annotationData: unknown | null\n healingScreenshotPaths: string[] | null\n accessibilityViolations: unknown[] | null\n confidence: number | null\n promptTokens: number\n completionTokens: number\n totalTokens: number\n subActionsData: unknown[] | null\n consoleLogs: unknown[] | null\n networkLogs: unknown[] | null\n variableSnapshot: Record<string, { value: string; source: string }> | null\n originalStepName: string | null\n screenContextBefore: string | null\n screenContextAfter: string | null\n createdAt: string\n}\n\ninterface ReasoningTraceRow {\n id: string\n stepId: string\n observeText: string | null\n observeDuration: number | null\n planReasoning: string | null\n planConfidence: number | null\n planAction: unknown | null\n planDuration: number | null\n executeAction: unknown | null\n executeDuration: number | null\n verifyReasoning: string | null\n verifySuccess: boolean | null\n verifyDuration: number | null\n healAttempts: unknown[] | null\n totalDuration: number | null\n screenStateBefore: string | null\n screenStateAfter: string | null\n createdAt: string\n}\n\ninterface ExecutionLogRow {\n id: string\n runId: string\n stepId: string | null\n type: 'hook' | 'appium-script' | 'runjs'\n name: string\n hookId: string | null\n phase: 'setup' | 'teardown' | 'inline'\n status: 'passed' | 'failed'\n duration: number\n stdout: string | null\n stderr: string | null\n returnData: unknown | null\n variables: Record<string, string> | null\n createdAt: string\n}\n\ninterface InsertExecutionLogInput {\n id: string\n runId: string\n stepId?: string | null\n type: 'hook' | 'appium-script' | 'runjs'\n name: string\n hookId?: string | null\n phase: 'setup' | 'teardown' | 'inline'\n status: 'passed' | 'failed'\n duration: number\n stdout?: string | null\n stderr?: string | null\n returnData?: unknown | null\n variables?: Record<string, string> | null\n}\n\ninterface RunsFilter {\n status?: string\n name?: string\n platform?: string\n from?: string\n to?: string\n attributePredicates?: AttributePredicate[]\n limit?: number\n offset?: number\n}\n\ninterface StatsOptions {\n from?: string\n to?: string\n attributePredicates?: AttributePredicate[]\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction deepMergeRecord(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...base }\n for (const [key, value] of Object.entries(patch)) {\n if (key === 'schemaVersion') continue\n const current = merged[key]\n merged[key] = isPlainObject(current) && isPlainObject(value)\n ? deepMergeRecord(current, value)\n : value\n }\n return merged\n}\n\nfunction mergeArtifactPayload(base: RunArtifactPayload, patch: RunArtifactStageInput): RunArtifactPayload {\n const merged = deepMergeRecord(base as unknown as Record<string, unknown>, patch as Record<string, unknown>)\n merged.schemaVersion = RUN_ARTIFACT_SCHEMA_VERSION\n return merged as unknown as RunArtifactPayload\n}\n\nexport type InsightsBreakdownDimension = 'test' | 'suite' | 'platform'\n\nexport interface InsightsBreakdownRow {\n key: string\n label: string\n runs: number\n passRate: number\n flakeRate: number\n avgDuration: number\n passed: number\n failed: number\n filePath?: string\n suiteId?: string\n}\n\nexport interface DeleteRunResult {\n deleted: boolean\n deletedRunIds: string[]\n screenshotPaths: string[]\n videoPaths: string[]\n}\n\nexport interface AttributePredicate {\n key: string\n value: string\n mode: 'exact' | 'regex'\n}\n\nexport interface AttributeKeySuggestion {\n key: string\n count: number\n}\n\nexport interface AttributeValueSuggestion {\n value: string\n count: number\n}\n\nexport function runSqliteMigrations(\n db: BetterSqlite3Database,\n migrations: readonly DashboardMigration[],\n schemaVersion: number,\n): void {\n const currentVersion = db.pragma('user_version', { simple: true }) as number\n if (currentVersion > schemaVersion) {\n throw new Error(\n `SQLite database user_version ${currentVersion} is not compatible with schema version ${schemaVersion}. `\n + 'Remove the dashboard database or use a compatible agent-qa version.',\n )\n }\n if (currentVersion === schemaVersion) return\n\n const runnableMigrations = migrations.filter(migration => migration.version <= schemaVersion)\n if (runnableMigrations.length !== schemaVersion) {\n throw new Error(`Expected ${schemaVersion} SQLite migration(s), found ${runnableMigrations.length}`)\n }\n runnableMigrations.forEach((migration, index) => {\n const expectedVersion = index + 1\n if (migration.version !== expectedVersion) {\n throw new Error(`SQLite migrations must be contiguous and sorted: expected version ${expectedVersion}, got ${migration.version}`)\n }\n })\n\n db.pragma('foreign_keys = OFF')\n try {\n for (const migration of runnableMigrations) {\n if (migration.version > currentVersion) {\n const runAll = db.transaction(() => {\n for (const sql of migration.sql) {\n db.exec(sql)\n }\n db.pragma(`user_version = ${migration.version}`)\n })\n runAll()\n }\n }\n } finally {\n db.pragma('foreign_keys = ON')\n }\n}\n\nexport class DashboardDatabase {\n private db: BetterSqlite3Database\n\n constructor({ dbPath = DASHBOARD_DB_PATH_FALLBACK }: { dbPath?: string } = {}) {\n mkdirSync(dirname(dbPath), { recursive: true })\n this.db = createBetterSqlite3Database(dbPath)\n this.db.pragma('journal_mode = WAL')\n this.db.pragma('busy_timeout = 5000')\n this.runMigrations()\n }\n\n private runMigrations(): void {\n runSqliteMigrations(this.db, MIGRATIONS, SCHEMA_VERSION)\n }\n\n insertRun(run: {\n id?: string\n name: string\n filePath?: string\n status: string\n duration: number\n attributes?: RunAttributes\n environment?: string\n metadata?: Record<string, unknown>\n startedAt: string\n endedAt: string\n videoPath?: string\n failureSummary?: string\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n parentRunId?: string\n attemptNumber?: number\n retryCount?: number\n maxRetries?: number\n testId?: string\n suiteId?: string\n }): string {\n const id = run.id || generateRunId()\n const stmt = this.db.prepare(`\n INSERT INTO runs (id, name, file_path, status, duration, attributes, environment, metadata, started_at, ended_at, video_path, failure_summary, platform, test_file_content, model_name, llm_provider, parent_run_id, attempt_number, retry_count, max_retries, test_id, suite_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n run.name,\n run.filePath ?? null,\n run.status,\n run.duration,\n JSON.stringify(run.attributes ?? {}),\n run.environment ?? null,\n run.metadata ? JSON.stringify(run.metadata) : null,\n run.startedAt,\n run.endedAt,\n run.videoPath ?? null,\n run.failureSummary ?? null,\n run.platform ?? 'web',\n run.testFileContent ?? null,\n run.modelName ?? null,\n run.llmProvider ?? null,\n run.parentRunId ?? null,\n run.attemptNumber ?? 0,\n run.retryCount ?? 0,\n run.maxRetries ?? 0,\n run.testId ?? null,\n run.suiteId ?? null,\n )\n return id\n }\n\n updateRun(id: string, updates: {\n name?: string\n status?: string\n duration?: number\n startedAt?: string\n endedAt?: string\n failureSummary?: string\n errorLog?: string\n memoryLog?: string\n videoPath?: string\n attributes?: RunAttributes\n platform?: string\n testId?: string\n suiteId?: string\n }): void {\n const fields: string[] = []\n const values: unknown[] = []\n if (updates.name !== undefined) { fields.push('name = ?'); values.push(updates.name) }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status) }\n if (updates.duration !== undefined) { fields.push('duration = ?'); values.push(updates.duration) }\n if (updates.startedAt !== undefined) { fields.push('started_at = ?'); values.push(updates.startedAt) }\n if (updates.endedAt !== undefined) { fields.push('ended_at = ?'); values.push(updates.endedAt) }\n if (updates.failureSummary !== undefined) { fields.push('failure_summary = ?'); values.push(updates.failureSummary) }\n if (updates.errorLog !== undefined) { fields.push('error_log = ?'); values.push(updates.errorLog) }\n if (updates.memoryLog !== undefined) { fields.push('memory_log = ?'); values.push(updates.memoryLog) }\n if (updates.videoPath !== undefined) { fields.push('video_path = ?'); values.push(updates.videoPath) }\n if (updates.attributes !== undefined) { fields.push('attributes = ?'); values.push(JSON.stringify(updates.attributes)) }\n if (updates.platform !== undefined) { fields.push('platform = ?'); values.push(updates.platform) }\n if (updates.testId !== undefined) { fields.push('test_id = ?'); values.push(updates.testId) }\n if (updates.suiteId !== undefined) { fields.push('suite_id = ?'); values.push(updates.suiteId) }\n if (fields.length === 0) return\n values.push(id)\n this.db.prepare(`UPDATE runs SET ${fields.join(', ')} WHERE id = ?`).run(...values)\n }\n\n updateRunMetadata(id: string, updates: {\n attributes?: RunAttributes\n metadata?: Record<string, unknown>\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n }): void {\n const fields: string[] = []\n const values: unknown[] = []\n if (updates.attributes !== undefined) { fields.push('attributes = ?'); values.push(JSON.stringify(updates.attributes)) }\n if (updates.metadata !== undefined) {\n const existing = this.db.prepare('SELECT metadata FROM runs WHERE id = ?').get(id) as { metadata: string | null } | undefined\n const existingMeta = existing?.metadata ? JSON.parse(existing.metadata) : {}\n const merged = { ...existingMeta, ...updates.metadata }\n fields.push('metadata = ?'); values.push(JSON.stringify(merged))\n }\n if (updates.platform !== undefined) { fields.push('platform = ?'); values.push(updates.platform) }\n if (updates.testFileContent !== undefined) { fields.push('test_file_content = ?'); values.push(updates.testFileContent) }\n if (updates.modelName !== undefined) { fields.push('model_name = ?'); values.push(updates.modelName) }\n if (updates.llmProvider !== undefined) { fields.push('llm_provider = ?'); values.push(updates.llmProvider) }\n if (fields.length === 0) return\n values.push(id)\n this.db.prepare(`UPDATE runs SET ${fields.join(', ')} WHERE id = ?`).run(...values)\n }\n\n insertPendingRun(run: {\n id?: string\n name: string\n filePath?: string\n attributes?: RunAttributes\n priority?: number\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n metadata?: Record<string, unknown>\n parallel?: boolean\n maxRetries?: number\n }): string {\n const id = run.id || generateRunId()\n const stmt = this.db.prepare(`\n INSERT INTO runs (id, name, file_path, status, priority, duration, attributes, started_at, ended_at, platform, test_file_content, model_name, llm_provider, metadata, parallel, max_retries)\n VALUES (?, ?, ?, 'pending', ?, 0, ?, NULL, NULL, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n run.name,\n run.filePath ?? null,\n run.priority ?? 0,\n JSON.stringify(run.attributes ?? {}),\n run.platform ?? 'web',\n run.testFileContent ?? null,\n run.modelName ?? null,\n run.llmProvider ?? null,\n run.metadata ? JSON.stringify(run.metadata) : null,\n run.parallel ? 1 : 0,\n run.maxRetries ?? 0,\n )\n return id\n }\n\n getNextPendingRun(): RunRow | undefined {\n const row = this.db.prepare(\n 'SELECT * FROM runs WHERE status = ? ORDER BY priority DESC, created_at ASC, rowid ASC LIMIT 1'\n ).get('pending') as Record<string, unknown> | undefined\n return row ? this.mapRunRow(row) : undefined\n }\n\n getPendingRuns(): RunRow[] {\n const rows = this.db.prepare(\n 'SELECT * FROM runs WHERE status = ? ORDER BY priority DESC, created_at ASC, rowid ASC'\n ).all('pending') as Record<string, unknown>[]\n return rows.map(r => this.mapRunRow(r))\n }\n\n updateRunStatus(id: string, status: string): void {\n this.db.prepare('UPDATE runs SET status = ? WHERE id = ?').run(status, id)\n }\n\n insertStep(step: {\n id?: string\n runId: string\n name: string\n status: string\n duration: number\n action?: unknown\n observation?: string\n reasoning?: string\n plannedAction?: unknown\n result?: string\n error?: string\n screenshotPath?: string\n screenshotBeforePath?: string\n healingAttempts?: unknown[]\n retryCount?: number\n capturedVariables?: Record<string, string>\n stepOrder: number\n annotationData?: unknown\n healingScreenshotPaths?: string[]\n accessibilityViolations?: unknown[]\n confidence?: number\n promptTokens?: number\n completionTokens?: number\n totalTokens?: number\n subActionsData?: unknown[]\n consoleLogs?: unknown[]\n networkLogs?: unknown[]\n variableSnapshot?: Record<string, unknown>\n originalStepName?: string\n screenContextBefore?: string\n screenContextAfter?: string\n }): string {\n const id = step.id || randomUUID()\n const stmt = this.db.prepare(`\n INSERT INTO steps (id, run_id, name, status, duration, action, observation, reasoning, planned_action, result, error, screenshot_path, screenshot_before_path, healing_attempts, retry_count, captured_variables, step_order, annotation_data, healing_screenshot_paths, accessibility_violations, confidence, prompt_tokens, completion_tokens, total_tokens, sub_actions_data, console_logs, network_logs, variable_snapshot, original_step_name, screen_context_before, screen_context_after)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n step.runId,\n step.name,\n step.status,\n step.duration,\n step.action ? JSON.stringify(step.action) : null,\n step.observation ?? null,\n step.reasoning ?? null,\n step.plannedAction ? JSON.stringify(step.plannedAction) : null,\n step.result ?? null,\n step.error ?? null,\n step.screenshotPath ?? null,\n step.screenshotBeforePath ?? null,\n step.healingAttempts ? JSON.stringify(step.healingAttempts) : null,\n step.retryCount ?? 0,\n step.capturedVariables ? JSON.stringify(step.capturedVariables) : null,\n step.stepOrder,\n step.annotationData ? JSON.stringify(step.annotationData) : null,\n step.healingScreenshotPaths ? JSON.stringify(step.healingScreenshotPaths) : null,\n step.accessibilityViolations ? JSON.stringify(step.accessibilityViolations) : null,\n step.confidence ?? null,\n step.promptTokens ?? 0,\n step.completionTokens ?? 0,\n step.totalTokens ?? 0,\n step.subActionsData ? JSON.stringify(step.subActionsData) : null,\n step.consoleLogs ? JSON.stringify(step.consoleLogs) : null,\n step.networkLogs ? JSON.stringify(step.networkLogs) : null,\n step.variableSnapshot ? JSON.stringify(step.variableSnapshot) : null,\n step.originalStepName ?? null,\n step.screenContextBefore ?? null,\n step.screenContextAfter ?? null,\n )\n return id\n }\n\n private appendAttributePredicateConditions(\n conditions: string[],\n params: unknown[],\n predicates: AttributePredicate[] | undefined,\n ): boolean {\n let hasRegex = false\n for (const predicate of predicates ?? []) {\n if (predicate.mode === 'exact') {\n conditions.push(`EXISTS (\n SELECT 1\n FROM json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE run_attr.key = ? AND run_attr.value = ?\n )`)\n params.push(predicate.key, predicate.value)\n } else {\n hasRegex = true\n conditions.push(`EXISTS (\n SELECT 1\n FROM json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE run_attr.key = ?\n )`)\n params.push(predicate.key)\n }\n }\n return hasRegex\n }\n\n private applyRegexAttributePredicates(\n runs: RunRow[],\n predicates: AttributePredicate[] | undefined,\n ): RunRow[] {\n const regexPredicates = (predicates ?? []).filter((predicate) => predicate.mode === 'regex')\n if (regexPredicates.length === 0) return runs\n const compiled = regexPredicates.map((predicate) => ({\n key: predicate.key,\n regex: new RegExp(predicate.value),\n }))\n return runs.filter((run) =>\n compiled.every((predicate) => {\n const value = run.attributes[predicate.key]\n return typeof value === 'string' && predicate.regex.test(value)\n }),\n )\n }\n\n private queryRunsWithAttributePredicates(input: {\n conditions: string[]\n params: unknown[]\n attributePredicates?: AttributePredicate[]\n orderBy?: string\n limit?: number\n offset?: number\n }): RunRow[] {\n const conditions = [...input.conditions]\n const params = [...input.params]\n const hasRegex = this.appendAttributePredicateConditions(conditions, params, input.attributePredicates)\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n let sql = `SELECT * FROM runs ${where} ${input.orderBy ?? 'ORDER BY created_at DESC'}`\n\n if (!hasRegex && input.limit !== undefined) {\n sql += ' LIMIT ?'\n params.push(input.limit)\n }\n if (!hasRegex && input.offset !== undefined) {\n sql += ' OFFSET ?'\n params.push(input.offset)\n }\n\n const rows = this.db.prepare(sql).all(...params) as Record<string, unknown>[]\n const runs = this.applyRegexAttributePredicates(rows.map(r => this.mapRunRow(r)), input.attributePredicates)\n if (!hasRegex) return runs\n\n const start = input.offset ?? 0\n const end = input.limit !== undefined ? start + input.limit : undefined\n return runs.slice(start, end)\n }\n\n private buildTrendsFromRuns(runs: RunRow[]): {\n daily: { date: string; passed: number; failed: number; total: number; avgDuration: number }[]\n passRate: number\n totalRuns: number\n avgDuration: number\n } {\n const totalRuns = runs.length\n const passedTotal = runs.filter((run) => this.isSuccessfulRunStatus(run.status)).length\n const avgDuration = totalRuns > 0\n ? runs.reduce((sum, run) => sum + run.duration, 0) / totalRuns\n : 0\n const byDate = new Map<string, RunRow[]>()\n for (const run of runs) {\n const date = (run.startedAt ?? run.createdAt).slice(0, 10)\n const dayRuns = byDate.get(date)\n if (dayRuns) dayRuns.push(run)\n else byDate.set(date, [run])\n }\n\n return {\n daily: [...byDate.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([date, dayRuns]) => {\n const total = dayRuns.length\n return {\n date,\n passed: dayRuns.filter((run) => this.isSuccessfulRunStatus(run.status)).length,\n failed: dayRuns.filter((run) => run.status === 'failed').length,\n total,\n avgDuration: total > 0 ? dayRuns.reduce((sum, run) => sum + run.duration, 0) / total : 0,\n }\n }),\n passRate: totalRuns > 0 ? passedTotal / totalRuns : 0,\n totalRuns,\n avgDuration,\n }\n }\n\n getRuns(opts: RunsFilter = {}): RunRow[] {\n const conditions: string[] = ['parent_run_id IS NULL']\n const params: unknown[] = []\n\n if (opts.status) {\n conditions.push('status = ?')\n params.push(opts.status)\n }\n if (opts.name) {\n conditions.push('(name LIKE ? OR id LIKE ?)')\n params.push(`%${opts.name}%`, `%${opts.name}%`)\n }\n if (opts.platform) {\n conditions.push('platform = ?')\n params.push(opts.platform)\n }\n if (opts.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n if (opts.to) {\n conditions.push('started_at <= ?')\n params.push(opts.to)\n }\n\n return this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts.attributePredicates,\n orderBy: 'ORDER BY created_at DESC',\n limit: opts.limit,\n offset: opts.offset,\n })\n }\n\n getRun(id: string): RunRow | undefined {\n const row = this.db.prepare('SELECT * FROM runs WHERE id = ?').get(id) as Record<string, unknown> | undefined\n return row ? this.mapRunRow(row) : undefined\n }\n\n listRunAttributeKeys(opts: { limit?: number; q?: string } = {}): AttributeKeySuggestion[] {\n const limit = opts.limit ?? 50\n const params: unknown[] = []\n const filters: string[] = []\n if (opts.q && opts.q.trim().length > 0) {\n filters.push('run_attr.key LIKE ?')\n params.push(`%${opts.q.trim()}%`)\n }\n params.push(limit)\n const rows = this.db.prepare(`\n SELECT run_attr.key as key, COUNT(*) as count\n FROM runs, json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE ${filters.length > 0 ? `${filters.join(' AND ')} AND` : ''} run_attr.type = 'text'\n GROUP BY run_attr.key\n ORDER BY count DESC, key ASC\n LIMIT ?\n `).all(...params) as Array<{ key: string; count: number }>\n\n return rows.map((row) => ({ key: row.key, count: row.count }))\n }\n\n listRunAttributeValues(key: string, opts: { limit?: number; q?: string } = {}): AttributeValueSuggestion[] {\n const limit = opts.limit ?? 50\n const params: unknown[] = [key]\n const filters = ['run_attr.key = ?']\n if (opts.q && opts.q.trim().length > 0) {\n filters.push('run_attr.value LIKE ?')\n params.push(`%${opts.q.trim()}%`)\n }\n params.push(limit)\n const rows = this.db.prepare(`\n SELECT run_attr.value as value, COUNT(*) as count\n FROM runs, json_each(CASE WHEN json_valid(runs.attributes) THEN runs.attributes ELSE '{}' END) AS run_attr\n WHERE ${filters.join(' AND ')}\n AND run_attr.type = 'text'\n GROUP BY run_attr.value\n ORDER BY count DESC, value ASC\n LIMIT ?\n `).all(...params) as Array<{ value: string; count: number }>\n\n return rows.map((row) => ({ value: row.value, count: row.count }))\n }\n\n deleteRun(id: string): DeleteRunResult {\n const runRows = this.db.prepare(`\n WITH RECURSIVE run_tree(id) AS (\n SELECT id FROM runs WHERE id = ?\n UNION ALL\n SELECT runs.id\n FROM runs\n INNER JOIN run_tree ON runs.parent_run_id = run_tree.id\n )\n SELECT *\n FROM runs\n WHERE id IN (SELECT id FROM run_tree)\n ORDER BY CASE WHEN id = ? THEN 0 ELSE 1 END, created_at ASC\n `).all(id, id) as Record<string, unknown>[]\n\n if (runRows.length === 0) {\n return {\n deleted: false,\n deletedRunIds: [],\n screenshotPaths: [],\n videoPaths: [],\n }\n }\n\n const deletedRunIds = runRows.map((row) => row.id as string)\n const runPlaceholders = deletedRunIds.map(() => '?').join(', ')\n const stepRows = this.db.prepare(`\n SELECT id, screenshot_path, screenshot_before_path, healing_screenshot_paths\n FROM steps\n WHERE run_id IN (${runPlaceholders})\n `).all(...deletedRunIds) as Array<{\n id: string\n screenshot_path: string | null\n screenshot_before_path: string | null\n healing_screenshot_paths: string | null\n }>\n const deletedStepIds = stepRows.map((row) => row.id)\n const screenshotPaths = stepRows.flatMap((row) => {\n const healingPaths = (() => {\n if (!row.healing_screenshot_paths) return []\n try {\n const parsed = JSON.parse(row.healing_screenshot_paths) as unknown\n return Array.isArray(parsed)\n ? parsed.filter((value): value is string => typeof value === 'string' && value.length > 0)\n : []\n } catch {\n return []\n }\n })()\n\n return [\n row.screenshot_path,\n row.screenshot_before_path,\n ...healingPaths,\n ].filter((value): value is string => typeof value === 'string' && value.length > 0)\n })\n const videoPaths = runRows\n .map((row) => row.video_path)\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n const deleteAll = this.db.transaction(() => {\n if (deletedStepIds.length > 0) {\n const stepPlaceholders = deletedStepIds.map(() => '?').join(', ')\n this.db.prepare(`\n DELETE FROM reasoning_traces\n WHERE step_id IN (${stepPlaceholders})\n `).run(...deletedStepIds)\n }\n\n this.db.prepare(`\n DELETE FROM steps\n WHERE run_id IN (${runPlaceholders})\n `).run(...deletedRunIds)\n\n this.db.prepare(`\n DELETE FROM runs\n WHERE id IN (${runPlaceholders})\n `).run(...deletedRunIds)\n })\n\n deleteAll()\n\n return {\n deleted: true,\n deletedRunIds,\n screenshotPaths,\n videoPaths,\n }\n }\n\n getSteps(runId: string): StepRow[] {\n const rows = this.db.prepare('SELECT * FROM steps WHERE run_id = ? ORDER BY step_order').all(runId) as Record<string, unknown>[]\n return rows.map(r => this.mapStepRow(r))\n }\n\n getCapturedVariableNames(testId: string): string[] {\n const rows = this.db.prepare(`\n SELECT DISTINCT captured_variables FROM steps\n WHERE run_id IN (SELECT id FROM runs WHERE test_id = ?)\n AND captured_variables IS NOT NULL\n LIMIT 100\n `).all(testId) as Array<{ captured_variables: string }>\n\n const nameSet = new Set<string>()\n for (const row of rows) {\n try {\n const parsed = JSON.parse(row.captured_variables) as Record<string, string>\n for (const key of Object.keys(parsed)) nameSet.add(key)\n } catch { /* skip malformed */ }\n }\n return [...nameSet].sort()\n }\n\n getRunsByParent(parentRunId: string): RunRow[] {\n const rows = this.db.prepare(\n 'SELECT * FROM runs WHERE parent_run_id = ? ORDER BY created_at ASC'\n ).all(parentRunId) as Record<string, unknown>[]\n return rows.map(r => this.mapRunRow(r))\n }\n\n insertRunArtifact(input: {\n runId: string\n kind?: RunArtifactKind\n payload?: RunArtifactStageInput\n }): RunArtifactRow {\n const payload = mergeArtifactPayload(\n { schemaVersion: RUN_ARTIFACT_SCHEMA_VERSION },\n input.payload ?? {},\n )\n this.db.prepare(`\n INSERT OR IGNORE INTO run_artifacts (run_id, kind, schema_version, payload)\n VALUES (?, ?, ?, ?)\n `).run(\n input.runId,\n input.kind ?? 'unknown',\n RUN_ARTIFACT_SCHEMA_VERSION,\n JSON.stringify(payload),\n )\n\n const existing = this.getRunArtifact(input.runId)\n if (!existing) {\n throw new Error(`Run artifact ${input.runId} was not created`)\n }\n if (existing.finalizedAt) return existing\n\n const updates: string[] = []\n const values: unknown[] = []\n if (input.kind && existing.kind !== input.kind) {\n updates.push('kind = ?')\n values.push(input.kind)\n }\n if (input.payload && Object.keys(input.payload).some((key) => key !== 'schemaVersion')) {\n const merged = mergeArtifactPayload(existing.payload, input.payload)\n updates.push('payload = ?')\n values.push(JSON.stringify(merged))\n }\n if (updates.length > 0) {\n updates.push('updated_at = CURRENT_TIMESTAMP')\n this.db.prepare(`UPDATE run_artifacts SET ${updates.join(', ')} WHERE run_id = ?`).run(...values, input.runId)\n }\n\n return this.getRunArtifact(input.runId)!\n }\n\n stageRunArtifact(runId: string, patch: RunArtifactStageInput): RunArtifactRow {\n const row = this.getRunArtifact(runId)\n if (!row) {\n throw new Error(`Run artifact ${runId} does not exist`)\n }\n if (row.finalizedAt) {\n throw new Error(`Run artifact ${runId} is finalized`)\n }\n const payload = mergeArtifactPayload(row.payload, patch)\n this.db.prepare(`\n UPDATE run_artifacts\n SET payload = ?, updated_at = CURRENT_TIMESTAMP\n WHERE run_id = ?\n `).run(JSON.stringify(payload), runId)\n return this.getRunArtifact(runId)!\n }\n\n finalizeRunArtifact(runId: string, updates?: RunArtifactFinalizeInput): RunArtifactRow {\n const row = this.getRunArtifact(runId)\n if (!row) {\n throw new Error(`Run artifact ${runId} does not exist`)\n }\n if (row.finalizedAt) return row\n\n let payload = row.payload\n const finalizedAt = updates?.finalizedAt ?? new Date().toISOString()\n if (updates) {\n const { finalizedAt: _finalizedAt, ...patch } = updates\n payload = mergeArtifactPayload(payload, patch)\n }\n\n this.db.prepare(`\n UPDATE run_artifacts\n SET payload = ?, finalized_at = ?, updated_at = CURRENT_TIMESTAMP\n WHERE run_id = ? AND finalized_at IS NULL\n `).run(JSON.stringify(payload), finalizedAt, runId)\n\n return this.getRunArtifact(runId)!\n }\n\n getRunArtifact(runId: string): RunArtifactRow | null {\n const row = this.db.prepare('SELECT * FROM run_artifacts WHERE run_id = ?').get(runId) as Record<string, unknown> | undefined\n return row ? this.mapRunArtifactRow(row) : null\n }\n\n getRunArtifactBundle(runId: string): RunArtifactBundle {\n const children = this.getRunsByParent(runId).map((run) => ({\n run,\n artifact: this.getRunArtifact(run.id),\n }))\n return {\n artifact: this.getRunArtifact(runId),\n children,\n }\n }\n\n updateRunRetryInfo(id: string, info: { retryCount: number; maxRetries: number }): void {\n this.db.prepare('UPDATE runs SET retry_count = ?, max_retries = ? WHERE id = ?')\n .run(info.retryCount, info.maxRetries, id)\n }\n\n private isSuccessfulRunStatus(status: string): boolean {\n return status === 'passed' || status === 'flaky'\n }\n\n private getHealedRunIds(runIds: string[]): Set<string> {\n if (runIds.length === 0) return new Set()\n\n const placeholders = runIds.map(() => '?').join(', ')\n const rows = this.db.prepare(`\n SELECT DISTINCT run_id\n FROM steps\n WHERE status = 'healed'\n AND run_id IN (${placeholders})\n `).all(...runIds) as Array<{ run_id: string }>\n\n return new Set(rows.map((row) => row.run_id))\n }\n\n private summarizeAnalyticsRuns(\n runs: Array<Pick<RunRow, 'id' | 'status' | 'duration'>>,\n healedRunIds: Set<string>,\n ) {\n const totalRuns = runs.length\n const passed = runs.filter((run) => this.isSuccessfulRunStatus(run.status)).length\n const failed = runs.filter((run) => run.status === 'failed').length\n const flaky = runs.filter((run) => run.status === 'flaky' || healedRunIds.has(run.id)).length\n const totalDuration = runs.reduce((sum, run) => sum + run.duration, 0)\n\n return {\n totalRuns,\n passed,\n failed,\n flaky,\n passRate: totalRuns > 0 ? passed / totalRuns : 0,\n flakeRate: totalRuns > 0 ? flaky / totalRuns : 0,\n avgDuration: totalRuns > 0 ? totalDuration / totalRuns : 0,\n }\n }\n\n private listRunsForInsights(\n dimension: InsightsBreakdownDimension,\n opts: StatsOptions & { limit?: number } = {},\n ): RunRow[] {\n const conditions: string[] = []\n const params: unknown[] = []\n\n if (dimension === 'suite') {\n conditions.push('parent_run_id IS NULL')\n conditions.push('suite_id IS NOT NULL')\n } else if (dimension === 'platform') {\n conditions.push('parent_run_id IS NULL')\n } else {\n conditions.push('NOT (suite_id IS NOT NULL AND parent_run_id IS NULL)')\n }\n\n if (opts.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n if (opts.to) {\n conditions.push('started_at <= ?')\n params.push(opts.to)\n }\n\n return this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts.attributePredicates,\n orderBy: 'ORDER BY started_at DESC',\n })\n }\n\n getStats(opts: StatsOptions = {}): {\n totalRuns: number\n passed: number\n failed: number\n flaky: number\n flakeRate: number\n avgDuration: number\n totalTokens: number\n runs: { date: string; passed: number; failed: number; healed: number; duration: number }[]\n memory: {\n runs: number\n added: number\n confirmed: number\n deprecated: number\n deleted: number\n curatorTokens: number\n }\n } {\n const runs = this.listRunsForInsights('platform', opts)\n const healedRunIds = this.getHealedRunIds(runs.map((run) => run.id))\n const summary = this.summarizeAnalyticsRuns(runs, healedRunIds)\n\n const byDay = new Map<string, RunRow[]>()\n for (const run of runs) {\n const date = (run.startedAt ?? run.createdAt).slice(0, 10)\n const dayRuns = byDay.get(date)\n if (dayRuns) {\n dayRuns.push(run)\n } else {\n byDay.set(date, [run])\n }\n }\n\n const daily = [...byDay.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([date, dayRuns]) => {\n const dayHealedRunIds = new Set(\n dayRuns\n .filter((run) => healedRunIds.has(run.id))\n .map((run) => run.id),\n )\n const daySummary = this.summarizeAnalyticsRuns(dayRuns, dayHealedRunIds)\n\n return {\n date,\n passed: daySummary.passed,\n failed: daySummary.failed,\n healed: dayHealedRunIds.size,\n duration: daySummary.avgDuration,\n }\n })\n\n const runIds = runs.map((run) => run.id)\n const totalTokens = runIds.length > 0\n ? ((this.db.prepare(`\n SELECT COALESCE(SUM(total_tokens), 0) as total_tokens\n FROM steps\n WHERE run_id IN (${runIds.map(() => '?').join(',')})\n `).get(...runIds) as Record<string, unknown>).total_tokens as number) || 0\n : 0\n\n const memorySummary = {\n runs: 0,\n added: 0,\n confirmed: 0,\n deprecated: 0,\n deleted: 0,\n curatorTokens: 0,\n }\n for (const run of runs) {\n if (!run.memoryLog) continue\n memorySummary.runs++\n try {\n const parsed = JSON.parse(run.memoryLog) as Record<string, unknown>\n memorySummary.added += Number(parsed.added ?? 0) || 0\n memorySummary.confirmed += Number(parsed.confirmed ?? 0) || 0\n memorySummary.deprecated += Number(parsed.deprecated ?? 0) || 0\n memorySummary.deleted += Number(parsed.deleted ?? 0) || 0\n const tokenUsage = parsed.tokenUsage && typeof parsed.tokenUsage === 'object'\n ? parsed.tokenUsage as Record<string, unknown>\n : {}\n memorySummary.curatorTokens += Number(tokenUsage.totalTokens ?? 0) || 0\n } catch {\n // Ignore malformed historical memory logs in aggregate insights.\n }\n }\n\n return {\n totalRuns: summary.totalRuns,\n passed: summary.passed,\n failed: summary.failed,\n flaky: summary.flaky,\n flakeRate: summary.flakeRate,\n avgDuration: summary.avgDuration,\n totalTokens,\n runs: daily,\n memory: memorySummary,\n }\n }\n\n getCostStats(opts: StatsOptions = {}): {\n runs: { runId: string; name: string; startedAt: string | null; promptTokens: number; completionTokens: number; totalTokens: number }[]\n totals: { promptTokens: number; completionTokens: number; totalTokens: number }\n } {\n const conditions: string[] = []\n const params: unknown[] = []\n if (opts.from) { conditions.push('r.started_at >= ?'); params.push(opts.from) }\n if (opts.to) { conditions.push('r.started_at <= ?'); params.push(opts.to) }\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\n const rows = this.db.prepare(`\n SELECT\n r.id as run_id,\n r.name,\n r.started_at,\n COALESCE(SUM(s.prompt_tokens), 0) as prompt_tokens,\n COALESCE(SUM(s.completion_tokens), 0) as completion_tokens,\n COALESCE(SUM(s.total_tokens), 0) as total_tokens\n FROM runs r\n LEFT JOIN steps s ON s.run_id = r.id\n ${where}\n GROUP BY r.id\n ORDER BY r.started_at DESC\n `).all(...params) as Record<string, unknown>[]\n\n const runs = rows.map(r => {\n const promptTokens = (r.prompt_tokens as number) || 0\n const completionTokens = (r.completion_tokens as number) || 0\n const totalTokens = (r.total_tokens as number) || 0\n return {\n runId: r.run_id as string,\n name: r.name as string,\n startedAt: r.started_at as string | null,\n promptTokens,\n completionTokens,\n totalTokens,\n }\n })\n\n const totalPrompt = runs.reduce((sum, r) => sum + r.promptTokens, 0)\n const totalCompletion = runs.reduce((sum, r) => sum + r.completionTokens, 0)\n const totalTotal = runs.reduce((sum, r) => sum + r.totalTokens, 0)\n\n return {\n runs,\n totals: {\n promptTokens: totalPrompt,\n completionTokens: totalCompletion,\n totalTokens: totalTotal,\n },\n }\n }\n\n insertTokenEvent(event: {\n modelName: string\n promptTokens: number\n completionTokens: number\n source: 'test-run' | 'live-editor'\n }): string {\n const id = randomUUID()\n this.db.prepare(`\n INSERT INTO token_events (id, model_name, prompt_tokens, completion_tokens, source)\n VALUES (?, ?, ?, ?, ?)\n `).run(id, event.modelName, event.promptTokens, event.completionTokens, event.source)\n return id\n }\n\n getTokenEventStats(opts: { from?: string; to?: string } = {}): {\n byModel: { date: string; model: string; promptTokens: number; completionTokens: number }[]\n bySource: Record<string, { promptTokens: number; completionTokens: number }>\n totals: { promptTokens: number; completionTokens: number }\n } {\n const conditions: string[] = []\n const params: unknown[] = []\n if (opts.from) { conditions.push('created_at >= ?'); params.push(opts.from) }\n if (opts.to) { conditions.push('created_at <= ?'); params.push(opts.to) }\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\n const byModel = this.db.prepare(`\n SELECT\n DATE(created_at) as date,\n model_name as model,\n SUM(prompt_tokens) as promptTokens,\n SUM(completion_tokens) as completionTokens\n FROM token_events\n ${where}\n GROUP BY DATE(created_at), model_name\n ORDER BY date\n `).all(...params) as { date: string; model: string; promptTokens: number; completionTokens: number }[]\n\n const bySourceRows = this.db.prepare(`\n SELECT\n source,\n SUM(prompt_tokens) as promptTokens,\n SUM(completion_tokens) as completionTokens\n FROM token_events\n ${where}\n GROUP BY source\n `).all(...params) as { source: string; promptTokens: number; completionTokens: number }[]\n\n const bySource: Record<string, { promptTokens: number; completionTokens: number }> = {}\n for (const row of bySourceRows) {\n bySource[row.source] = { promptTokens: row.promptTokens, completionTokens: row.completionTokens }\n }\n\n const totalsRow = this.db.prepare(`\n SELECT\n COALESCE(SUM(prompt_tokens), 0) as promptTokens,\n COALESCE(SUM(completion_tokens), 0) as completionTokens\n FROM token_events\n ${where}\n `).get(...params) as { promptTokens: number; completionTokens: number }\n\n return {\n byModel,\n bySource,\n totals: { promptTokens: totalsRow.promptTokens, completionTokens: totalsRow.completionTokens },\n }\n }\n\n getRunsByTestName(name: string, opts?: { limit?: number; offset?: number; attributePredicates?: AttributePredicate[] }): RunRow[] {\n return this.queryRunsWithAttributePredicates({\n conditions: ['name = ?', 'parent_run_id IS NULL'],\n params: [name],\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at DESC',\n limit: opts?.limit,\n offset: opts?.offset,\n })\n }\n\n getRunsByTestNameCount(name: string, opts?: { attributePredicates?: AttributePredicate[] }): number {\n if (opts?.attributePredicates?.length) {\n return this.getRunsByTestName(name, { attributePredicates: opts.attributePredicates }).length\n }\n const row = this.db.prepare('SELECT COUNT(*) as cnt FROM runs WHERE name = ? AND parent_run_id IS NULL').get(name) as { cnt: number }\n return row.cnt\n }\n\n getTestTrends(name: string, opts?: { from?: string; attributePredicates?: AttributePredicate[] }): {\n daily: { date: string; passed: number; failed: number; total: number; avgDuration: number }[]\n passRate: number\n totalRuns: number\n avgDuration: number\n } {\n const conditions = ['name = ?', 'parent_run_id IS NULL']\n const params: unknown[] = [name]\n if (opts?.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n return this.buildTrendsFromRuns(this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at ASC',\n }))\n }\n\n getRunsBySuiteId(suiteId: string, opts?: { limit?: number; offset?: number; attributePredicates?: AttributePredicate[] }): RunRow[] {\n return this.queryRunsWithAttributePredicates({\n conditions: ['suite_id = ?', 'parent_run_id IS NULL'],\n params: [suiteId],\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at DESC',\n limit: opts?.limit,\n offset: opts?.offset,\n })\n }\n\n getRunsBySuiteIdCount(suiteId: string, opts?: { attributePredicates?: AttributePredicate[] }): number {\n if (opts?.attributePredicates?.length) {\n return this.getRunsBySuiteId(suiteId, { attributePredicates: opts.attributePredicates }).length\n }\n const row = this.db.prepare(`\n SELECT COUNT(*) as cnt\n FROM runs\n WHERE suite_id = ?\n AND parent_run_id IS NULL\n `).get(suiteId) as { cnt: number }\n return row.cnt\n }\n\n getSuiteTrends(suiteId: string, opts?: { from?: string; attributePredicates?: AttributePredicate[] }): {\n daily: { date: string; passed: number; failed: number; total: number; avgDuration: number }[]\n passRate: number\n totalRuns: number\n avgDuration: number\n } {\n const conditions = ['suite_id = ?', 'parent_run_id IS NULL']\n const params: unknown[] = [suiteId]\n if (opts?.from) {\n conditions.push('started_at >= ?')\n params.push(opts.from)\n }\n return this.buildTrendsFromRuns(this.queryRunsWithAttributePredicates({\n conditions,\n params,\n attributePredicates: opts?.attributePredicates,\n orderBy: 'ORDER BY started_at ASC',\n }))\n }\n\n getInsightsBreakdown(\n dimension: InsightsBreakdownDimension,\n opts: StatsOptions & { limit?: number } = {},\n ): InsightsBreakdownRow[] {\n const runs = this.listRunsForInsights(dimension, opts)\n const healedRunIds = this.getHealedRunIds(runs.map((run) => run.id))\n const grouped = new Map<string, Array<RunRow>>()\n\n for (const run of runs) {\n const key = dimension === 'suite'\n ? (run.suiteId ?? 'unknown')\n : dimension === 'platform'\n ? (run.platform || 'unknown')\n : run.name\n\n const groupRuns = grouped.get(key)\n if (groupRuns) {\n groupRuns.push(run)\n } else {\n grouped.set(key, [run])\n }\n }\n\n const rows = [...grouped.entries()].map(([key, groupRuns]) => {\n const groupHealedRunIds = new Set(\n groupRuns\n .filter((run) => healedRunIds.has(run.id))\n .map((run) => run.id),\n )\n const filePaths = new Set(\n groupRuns\n .map((run) => run.filePath)\n .filter((value): value is string => typeof value === 'string' && value.length > 0),\n )\n const summary = this.summarizeAnalyticsRuns(groupRuns, groupHealedRunIds)\n const row: InsightsBreakdownRow = {\n key,\n label: key,\n runs: summary.totalRuns,\n passRate: summary.passRate,\n flakeRate: summary.flakeRate,\n avgDuration: summary.avgDuration,\n passed: summary.passed,\n failed: summary.failed,\n }\n\n if (dimension === 'test' && filePaths.size === 1) {\n row.filePath = [...filePaths][0]\n }\n\n if (dimension === 'suite') {\n row.suiteId = key\n }\n\n return row\n })\n\n rows.sort((left, right) =>\n right.runs - left.runs ||\n right.flakeRate - left.flakeRate ||\n left.passRate - right.passRate ||\n left.label.localeCompare(right.label),\n )\n\n const limit = opts.limit ?? 25\n return rows.slice(0, limit)\n }\n\n getFlakyTests(opts?: { minRuns?: number; limit?: number }): {\n name: string; filePath: string | null; totalRuns: number; passRate: number; flakyScore: number\n }[] {\n const minRuns = opts?.minRuns ?? 3\n const limit = opts?.limit ?? 50\n\n const tests = this.db.prepare(`\n SELECT name,\n MAX(file_path) as file_path,\n COUNT(*) as total_runs,\n SUM(CASE WHEN status = 'passed' THEN 1 ELSE 0 END) as passed,\n GROUP_CONCAT(status, ',') as status_seq\n FROM (\n SELECT name, status, file_path FROM runs\n WHERE status IN ('passed', 'failed')\n ORDER BY name, started_at DESC\n )\n GROUP BY name\n HAVING COUNT(*) >= ?\n LIMIT ?\n `).all(minRuns, limit) as Record<string, unknown>[]\n\n return tests.map(t => {\n const statusSeq = (t.status_seq as string).split(',')\n let alternations = 0\n for (let i = 1; i < statusSeq.length; i++) {\n if (statusSeq[i] !== statusSeq[i - 1]) alternations++\n }\n const flakyScore = statusSeq.length > 1 ? alternations / (statusSeq.length - 1) : 0\n const totalRuns = t.total_runs as number\n const passed = t.passed as number\n\n return {\n name: t.name as string,\n filePath: (t.file_path as string) ?? null,\n totalRuns,\n passRate: passed / totalRuns,\n flakyScore,\n }\n }).sort((a, b) => b.flakyScore - a.flakyScore)\n }\n\n getAccessibilitySummary(runId: string) {\n const steps = this.getSteps(runId)\n const allViolations: any[] = []\n let stepsWithViolations = 0\n let scannedSteps = 0\n\n for (const step of steps) {\n if (Array.isArray(step.accessibilityViolations)) {\n scannedSteps++\n if ((step.accessibilityViolations as any[]).length > 0) {\n stepsWithViolations++\n allViolations.push(...(step.accessibilityViolations as any[]))\n }\n }\n }\n\n const bySeverity: Record<string, number> = { critical: 0, serious: 0, moderate: 0, minor: 0 }\n const byRule: Record<string, { count: number; impact: string }> = {}\n\n for (const v of allViolations) {\n bySeverity[v.impact] = (bySeverity[v.impact] || 0) + 1\n if (!byRule[v.ruleId]) byRule[v.ruleId] = { count: 0, impact: v.impact }\n byRule[v.ruleId].count++\n }\n\n return {\n enabled: this.getRunAccessibilityEnabled(runId),\n total: allViolations.length,\n bySeverity,\n byRule: Object.entries(byRule)\n .map(([ruleId, data]) => ({ ruleId, ...data }))\n .sort((a, b) => b.count - a.count),\n stepsWithViolations,\n scannedSteps,\n unscannedSteps: Math.max(0, steps.length - scannedSteps),\n totalSteps: steps.length,\n }\n }\n\n private getRunAccessibilityEnabled(runId: string): boolean | null {\n const artifact = this.getRunArtifact(runId)\n const payload = artifact?.payload\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return null\n const config = (payload as unknown as Record<string, unknown>).config\n if (!config || typeof config !== 'object' || Array.isArray(config)) return null\n\n const configRecord = config as Record<string, unknown>\n const candidates = [configRecord.effectiveConfig, configRecord.parsedConfig]\n let sawConfig = false\n let sawAccessibility = false\n\n for (const candidate of candidates) {\n if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) continue\n sawConfig = true\n const services = (candidate as Record<string, unknown>).services\n if (!services || typeof services !== 'object' || Array.isArray(services)) continue\n const accessibility = (services as Record<string, unknown>).accessibility\n if (!accessibility || typeof accessibility !== 'object' || Array.isArray(accessibility)) continue\n sawAccessibility = true\n const enabled = (accessibility as Record<string, unknown>).enabled\n if (typeof enabled === 'boolean') return enabled\n }\n\n return sawConfig || sawAccessibility ? false : null\n }\n\n getStep(stepId: string): StepRow | undefined {\n const row = this.db.prepare('SELECT * FROM steps WHERE id = ?').get(stepId) as Record<string, unknown> | undefined\n return row ? this.mapStepRow(row) : undefined\n }\n\n insertReasoningTrace(trace: {\n stepId: string\n observeText?: string\n observeDuration?: number\n planReasoning?: string\n planConfidence?: number\n planAction?: unknown\n planDuration?: number\n executeAction?: unknown\n executeDuration?: number\n verifyReasoning?: string\n verifySuccess?: boolean\n verifyDuration?: number\n healAttempts?: unknown[]\n totalDuration?: number\n screenStateBefore?: string\n screenStateAfter?: string\n }): string {\n const id = randomUUID()\n const stmt = this.db.prepare(`\n INSERT INTO reasoning_traces (id, step_id, observe_text, observe_duration, plan_reasoning, plan_confidence, plan_action, plan_duration, execute_action, execute_duration, verify_reasoning, verify_success, verify_duration, heal_attempts, total_duration, screen_state_before, screen_state_after)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n id,\n trace.stepId,\n trace.observeText ?? null,\n trace.observeDuration ?? null,\n trace.planReasoning ?? null,\n trace.planConfidence ?? null,\n trace.planAction ? JSON.stringify(trace.planAction) : null,\n trace.planDuration ?? null,\n trace.executeAction ? JSON.stringify(trace.executeAction) : null,\n trace.executeDuration ?? null,\n trace.verifyReasoning ?? null,\n trace.verifySuccess !== undefined ? (trace.verifySuccess ? 1 : 0) : null,\n trace.verifyDuration ?? null,\n trace.healAttempts ? JSON.stringify(trace.healAttempts) : null,\n trace.totalDuration ?? null,\n trace.screenStateBefore ?? null,\n trace.screenStateAfter ?? null,\n )\n return id\n }\n\n getReasoningTrace(runId: string, stepOrder: number): ReasoningTraceRow | undefined {\n const row = this.db.prepare(`\n SELECT rt.* FROM reasoning_traces rt\n INNER JOIN steps s ON s.id = rt.step_id\n WHERE s.run_id = ? AND s.step_order = ?\n `).get(runId, stepOrder) as Record<string, unknown> | undefined\n return row ? this.mapReasoningTraceRow(row) : undefined\n }\n\n // Satisfies LogStorage interface from @vostride/agent-qa-core (structural typing)\n insertLogs(entries: LogEntry[]): void {\n if (entries.length === 0) return\n const stmt = this.db.prepare(\n 'INSERT INTO logs (id, step_id, run_id, level, source, message, data, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',\n )\n const insertAll = this.db.transaction(() => {\n for (const entry of entries) {\n stmt.run(\n entry.id,\n entry.stepId,\n entry.runId,\n entry.level,\n entry.source,\n entry.message,\n JSON.stringify(entry.data),\n entry.timestamp,\n )\n }\n })\n try {\n insertAll()\n } catch {\n // FK violations (e.g. run_id not yet in runs table) are non-fatal for logs\n }\n }\n\n getLogs(opts: {\n runId?: string\n stepId?: string\n level?: string\n source?: string\n limit?: number\n offset?: number\n } = {}): LogEntry[] {\n const conditions: string[] = []\n const params: unknown[] = []\n\n if (opts.runId) {\n conditions.push('run_id = ?')\n params.push(opts.runId)\n }\n if (opts.stepId) {\n conditions.push('step_id = ?')\n params.push(opts.stepId)\n }\n if (opts.level) {\n conditions.push('level = ?')\n params.push(opts.level)\n }\n if (opts.source) {\n conditions.push('source = ?')\n params.push(opts.source)\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n const limit = opts.limit ?? 1000\n const offset = opts.offset ?? 0\n params.push(limit, offset)\n\n const rows = this.db.prepare(\n `SELECT * FROM logs ${where} ORDER BY timestamp ASC LIMIT ? OFFSET ?`,\n ).all(...params) as Record<string, unknown>[]\n\n return rows.map(r => this.mapLogRow(r))\n }\n\n insertExecutionLog(data: InsertExecutionLogInput): void {\n const stmt = this.db.prepare(`\n INSERT INTO execution_logs (id, run_id, step_id, type, name, hook_id, phase, status, duration, stdout, stderr, return_data, variables)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n stmt.run(\n data.id,\n data.runId,\n data.stepId ?? null,\n data.type,\n data.name,\n data.hookId ?? null,\n data.phase,\n data.status,\n data.duration,\n data.stdout ?? null,\n data.stderr ?? null,\n data.returnData != null ? JSON.stringify(data.returnData) : null,\n data.variables != null ? JSON.stringify(data.variables) : null,\n )\n }\n\n getExecutionLogs(filter: { runId?: string; stepId?: string; type?: string }): ExecutionLogRow[] {\n const conditions: string[] = []\n const params: unknown[] = []\n if (filter.runId) { conditions.push('run_id = ?'); params.push(filter.runId) }\n if (filter.stepId) { conditions.push('step_id = ?'); params.push(filter.stepId) }\n if (filter.type) { conditions.push('type = ?'); params.push(filter.type) }\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n const rows = this.db.prepare(`SELECT * FROM execution_logs ${where} ORDER BY created_at`).all(...params) as Record<string, unknown>[]\n return rows.map(r => ({\n id: r.id as string,\n runId: r.run_id as string,\n stepId: r.step_id as string | null,\n type: r.type as 'hook' | 'appium-script' | 'runjs',\n name: r.name as string,\n hookId: r.hook_id as string | null,\n phase: r.phase as 'setup' | 'teardown' | 'inline',\n status: r.status as 'passed' | 'failed',\n duration: r.duration as number,\n stdout: r.stdout as string | null,\n stderr: r.stderr as string | null,\n returnData: r.return_data ? JSON.parse(r.return_data as string) : null,\n variables: r.variables ? JSON.parse(r.variables as string) : null,\n createdAt: r.created_at as string,\n }))\n }\n\n close(): void {\n this.db.close()\n }\n\n private parseRunAttributes(value: unknown): RunAttributes {\n if (typeof value !== 'string' || value.length === 0) return {}\n try {\n const parsed = JSON.parse(value) as unknown\n if (!isPlainObject(parsed)) return {}\n const attributes: RunAttributes = {}\n for (const [key, attrValue] of Object.entries(parsed)) {\n if (typeof attrValue === 'string') attributes[key] = attrValue\n }\n return attributes\n } catch {\n return {}\n }\n }\n\n private mapRunRow(r: Record<string, unknown>): RunRow {\n return {\n id: r.id as string,\n name: r.name as string,\n filePath: r.file_path as string | null,\n status: r.status as string,\n priority: (r.priority as number) ?? 0,\n duration: r.duration as number,\n attributes: this.parseRunAttributes(r.attributes),\n environment: r.environment as string | null,\n metadata: r.metadata ? JSON.parse(r.metadata as string) : null,\n startedAt: r.started_at as string | null,\n endedAt: r.ended_at as string | null,\n videoPath: (r.video_path as string) ?? null,\n failureSummary: (r.failure_summary as string) ?? null,\n errorLog: (r.error_log as string) ?? null,\n memoryLog: (r.memory_log as string) ?? null,\n testId: (r.test_id as string) ?? null,\n suiteId: (r.suite_id as string) ?? null,\n platform: (r.platform as string) ?? 'web',\n testFileContent: (r.test_file_content as string) ?? null,\n modelName: (r.model_name as string) ?? null,\n llmProvider: (r.llm_provider as string) ?? null,\n parallel: Boolean(r.parallel),\n parentRunId: (r.parent_run_id as string) ?? null,\n attemptNumber: (r.attempt_number as number) ?? 0,\n retryCount: (r.retry_count as number) ?? 0,\n maxRetries: (r.max_retries as number) ?? 0,\n createdAt: r.created_at as string,\n }\n }\n\n private mapRunArtifactRow(r: Record<string, unknown>): RunArtifactRow {\n return {\n runId: r.run_id as string,\n kind: r.kind as RunArtifactKind,\n schemaVersion: r.schema_version as number,\n payload: r.payload ? JSON.parse(r.payload as string) : { schemaVersion: RUN_ARTIFACT_SCHEMA_VERSION },\n finalizedAt: (r.finalized_at as string) ?? null,\n createdAt: r.created_at as string,\n updatedAt: r.updated_at as string,\n }\n }\n\n private mapStepRow(r: Record<string, unknown>): StepRow {\n return {\n id: r.id as string,\n runId: r.run_id as string,\n name: r.name as string,\n status: r.status as string,\n duration: r.duration as number,\n action: r.action ? JSON.parse(r.action as string) : null,\n observation: r.observation as string | null,\n reasoning: r.reasoning as string | null,\n plannedAction: r.planned_action ? JSON.parse(r.planned_action as string) : null,\n result: r.result as string | null,\n error: r.error as string | null,\n screenshotPath: r.screenshot_path as string | null,\n screenshotBeforePath: (r.screenshot_before_path as string) ?? null,\n healingAttempts: r.healing_attempts ? JSON.parse(r.healing_attempts as string) : null,\n retryCount: r.retry_count as number,\n capturedVariables: r.captured_variables ? JSON.parse(r.captured_variables as string) : null,\n stepOrder: r.step_order as number,\n annotationData: r.annotation_data ? JSON.parse(r.annotation_data as string) : null,\n healingScreenshotPaths: r.healing_screenshot_paths ? JSON.parse(r.healing_screenshot_paths as string) : null,\n accessibilityViolations: r.accessibility_violations ? JSON.parse(r.accessibility_violations as string) : null,\n confidence: (r.confidence as number) ?? null,\n promptTokens: (r.prompt_tokens as number) ?? 0,\n completionTokens: (r.completion_tokens as number) ?? 0,\n totalTokens: (r.total_tokens as number) ?? 0,\n subActionsData: r.sub_actions_data ? JSON.parse(r.sub_actions_data as string) : null,\n consoleLogs: r.console_logs ? JSON.parse(r.console_logs as string) : null,\n networkLogs: r.network_logs ? JSON.parse(r.network_logs as string) : null,\n variableSnapshot: r.variable_snapshot ? JSON.parse(r.variable_snapshot as string) : null,\n originalStepName: (r.original_step_name as string) ?? null,\n screenContextBefore: (r.screen_context_before as string) ?? null,\n screenContextAfter: (r.screen_context_after as string) ?? null,\n createdAt: r.created_at as string,\n }\n }\n\n private mapLogRow(r: Record<string, unknown>): LogEntry {\n let data: Record<string, unknown> = {}\n if (r.data) {\n try { data = JSON.parse(r.data as string) } catch { /* invalid JSON → empty */ }\n }\n return {\n id: r.id as string,\n stepId: (r.step_id as string) ?? null,\n runId: r.run_id as string,\n level: r.level as LogEntry['level'],\n source: r.source as LogEntry['source'],\n message: r.message as string,\n data,\n timestamp: r.timestamp as string,\n }\n }\n\n private mapReasoningTraceRow(r: Record<string, unknown>): ReasoningTraceRow {\n return {\n id: r.id as string,\n stepId: r.step_id as string,\n observeText: r.observe_text as string | null,\n observeDuration: r.observe_duration as number | null,\n planReasoning: r.plan_reasoning as string | null,\n planConfidence: r.plan_confidence as number | null,\n planAction: r.plan_action ? JSON.parse(r.plan_action as string) : null,\n planDuration: r.plan_duration as number | null,\n executeAction: r.execute_action ? JSON.parse(r.execute_action as string) : null,\n executeDuration: r.execute_duration as number | null,\n verifyReasoning: r.verify_reasoning as string | null,\n verifySuccess: r.verify_success !== null ? Boolean(r.verify_success) : null,\n verifyDuration: r.verify_duration as number | null,\n healAttempts: r.heal_attempts ? JSON.parse(r.heal_attempts as string) : null,\n totalDuration: r.total_duration as number | null,\n screenStateBefore: r.screen_state_before as string | null,\n screenStateAfter: r.screen_state_after as string | null,\n createdAt: r.created_at as string,\n }\n }\n}\n","import { copyFile, mkdir, rename, stat, unlink } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, relative, resolve } from 'node:path'\nimport { isCanonicalRunId } from '@vostride/agent-qa-ids'\nimport { createBetterSqlite3Database, generateRunId, type BetterSqlite3Database } from '@vostride/agent-qa-core'\n\ninterface RunIdMigrationRunRow {\n id: string\n parent_run_id: string | null\n video_path: string | null\n}\n\ninterface RunIdMigrationStepRow {\n id: string\n screenshot_path: string | null\n screenshot_before_path: string | null\n healing_screenshot_paths: string | null\n}\n\ninterface FlatVideoFileMove {\n fromPath: string\n toPath: string\n}\n\nexport interface RunIdMigrationOptions {\n dbPath: string\n screenshotsDir?: string\n videosDir?: string\n logger?: (message: string) => void\n}\n\nexport interface RunIdMigrationResult {\n migratedRunCount: number\n totalRunCount: number\n runIdMap: Record<string, string>\n preservedRunIds: string[]\n updatedScreenshotRows: number\n updatedVideoRows: number\n renamedScreenshotDirs: Array<{ from: string; to: string }>\n renamedVideoDirs: Array<{ from: string; to: string }>\n missingArtifacts: string[]\n}\n\nfunction rewriteArtifactPath(\n value: string | null,\n mapping: Map<string, string>,\n rootDir?: string,\n apiPrefix?: '/api/screenshots/' | '/api/videos/',\n): string | null {\n if (!value) return value\n const trimmed = value.trim()\n if (!trimmed) return value\n\n let relativePath: string\n let mode: 'relative' | 'absolute' | 'api' = 'relative'\n\n if (apiPrefix && trimmed.startsWith(apiPrefix)) {\n relativePath = trimmed.slice(apiPrefix.length)\n mode = 'api'\n } else if (rootDir && isAbsolute(trimmed)) {\n const resolvedRoot = resolve(rootDir)\n const resolvedValue = resolve(trimmed)\n const insideRoot = relative(resolvedRoot, resolvedValue)\n if (!insideRoot || insideRoot.startsWith('..') || isAbsolute(insideRoot)) {\n return value\n }\n relativePath = insideRoot\n mode = 'absolute'\n } else {\n relativePath = trimmed\n }\n\n const segments = relativePath.split(/[\\\\/]+/).filter(Boolean)\n if (segments.length === 0) return value\n\n const nextHead = mapping.get(segments[0])\n if (!nextHead) return value\n\n const rewrittenRelative = [nextHead, ...segments.slice(1)].join('/')\n if (mode === 'api' && apiPrefix) return `${apiPrefix}${rewrittenRelative}`\n if (mode === 'absolute' && rootDir) return resolve(rootDir, rewrittenRelative)\n return rewrittenRelative\n}\n\nfunction rewriteJsonStringArray(\n value: string | null,\n mapping: Map<string, string>,\n rootDir?: string,\n apiPrefix?: '/api/screenshots/' | '/api/videos/',\n): string | null {\n if (!value) return value\n try {\n const parsed = JSON.parse(value) as unknown\n if (!Array.isArray(parsed)) return value\n let changed = false\n const rewritten = parsed.map((entry) => {\n if (typeof entry !== 'string') return entry\n const nextValue = rewriteArtifactPath(entry, mapping, rootDir, apiPrefix)\n if (nextValue !== entry) changed = true\n return nextValue\n })\n return changed ? JSON.stringify(rewritten) : value\n } catch {\n return value\n }\n}\n\nfunction getRelativeArtifactPath(\n value: string,\n rootDir: string,\n apiPrefix: '/api/screenshots/' | '/api/videos/',\n): { relativePath: string; sourcePath: string } | null {\n const trimmed = value.trim()\n if (!trimmed) return null\n const resolvedRoot = resolve(rootDir)\n\n if (trimmed.startsWith(apiPrefix)) {\n const relativePath = trimmed.slice(apiPrefix.length)\n const sourcePath = resolve(resolvedRoot, relativePath)\n const insideRoot = relative(resolvedRoot, sourcePath)\n if (!insideRoot || insideRoot.startsWith('..') || isAbsolute(insideRoot)) return null\n return { relativePath: insideRoot, sourcePath }\n }\n\n if (isAbsolute(trimmed)) {\n const sourcePath = resolve(trimmed)\n const relativePath = relative(resolvedRoot, sourcePath)\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) return null\n return { relativePath, sourcePath }\n }\n\n const sourcePath = resolve(resolvedRoot, trimmed)\n const relativePath = relative(resolvedRoot, sourcePath)\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) return null\n return { relativePath, sourcePath }\n}\n\nfunction rewriteRunVideoPath(\n run: RunIdMigrationRunRow,\n mapping: Map<string, string>,\n videosDir: string | undefined,\n flatVideoFileMoves: FlatVideoFileMove[],\n): string | null {\n const nextVideoPath = rewriteArtifactPath(run.video_path, mapping, videosDir, '/api/videos/')\n if (nextVideoPath !== run.video_path) return nextVideoPath\n if (!run.video_path || !videosDir) return run.video_path\n\n const newRunId = mapping.get(run.id)\n if (!newRunId) return run.video_path\n\n const artifact = getRelativeArtifactPath(run.video_path, videosDir, '/api/videos/')\n if (!artifact) return run.video_path\n\n const segments = artifact.relativePath.split(/[\\\\/]+/).filter(Boolean)\n if (segments.length !== 1) return run.video_path\n\n const fileName = basename(segments[0])\n if (!fileName) return run.video_path\n\n const rewrittenRelative = `${newRunId}/${fileName}`\n flatVideoFileMoves.push({\n fromPath: artifact.sourcePath,\n toPath: resolve(videosDir, rewrittenRelative),\n })\n return rewrittenRelative\n}\n\nasync function renameDirectoryIfPresent(\n fromPath: string,\n toPath: string,\n renamed: Array<{ from: string; to: string }>,\n missingArtifacts: string[],\n logger?: (message: string) => void,\n): Promise<void> {\n try {\n const info = await stat(fromPath)\n if (!info.isDirectory()) return\n await mkdir(dirname(toPath), { recursive: true })\n await rename(fromPath, toPath)\n renamed.push({ from: fromPath, to: toPath })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n missingArtifacts.push(fromPath)\n return\n }\n logger?.(`Skipping artifact rename ${fromPath} -> ${toPath}: ${String(error)}`)\n }\n}\n\nasync function moveFileIfPresent(\n fromPath: string,\n toPath: string,\n missingArtifacts: string[],\n logger?: (message: string) => void,\n): Promise<void> {\n try {\n const info = await stat(fromPath)\n if (!info.isFile()) return\n await mkdir(dirname(toPath), { recursive: true })\n try {\n await rename(fromPath, toPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'EXDEV') {\n await copyFile(fromPath, toPath)\n await unlink(fromPath)\n return\n }\n throw error\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n missingArtifacts.push(fromPath)\n return\n }\n logger?.(`Skipping artifact move ${fromPath} -> ${toPath}: ${String(error)}`)\n }\n}\n\nfunction buildRunIdMap(runIds: string[]): Map<string, string> {\n const mapping = new Map<string, string>()\n const assignedIds = new Set(runIds)\n\n for (const runId of runIds) {\n if (isCanonicalRunId(runId)) continue\n\n let nextId = generateRunId()\n while (assignedIds.has(nextId) || mappingHasValue(mapping, nextId)) {\n nextId = generateRunId()\n }\n mapping.set(runId, nextId)\n assignedIds.add(nextId)\n }\n\n return mapping\n}\n\nfunction mappingHasValue(mapping: Map<string, string>, value: string): boolean {\n for (const mappedValue of mapping.values()) {\n if (mappedValue === value) return true\n }\n return false\n}\n\nfunction runForeignKeyCheck(db: BetterSqlite3Database): void {\n const violations = db.pragma('foreign_key_check') as Array<Record<string, unknown>>\n if (violations.length === 0) return\n throw new Error(`Run-id migration left ${violations.length} foreign key violation(s)`)\n}\n\nexport async function migrateWorkspaceRunIds({\n dbPath,\n screenshotsDir,\n videosDir,\n logger,\n}: RunIdMigrationOptions): Promise<RunIdMigrationResult> {\n const db = createBetterSqlite3Database(dbPath)\n const renamedScreenshotDirs: Array<{ from: string; to: string }> = []\n const renamedVideoDirs: Array<{ from: string; to: string }> = []\n const flatVideoFileMoves: FlatVideoFileMove[] = []\n const missingArtifacts: string[] = []\n\n try {\n const runs = db.prepare('SELECT id, parent_run_id, video_path FROM runs ORDER BY rowid ASC').all() as RunIdMigrationRunRow[]\n const steps = db.prepare('SELECT id, screenshot_path, screenshot_before_path, healing_screenshot_paths FROM steps ORDER BY rowid ASC').all() as RunIdMigrationStepRow[]\n const mapping = buildRunIdMap(runs.map((run) => run.id))\n\n if (mapping.size === 0) {\n return {\n migratedRunCount: 0,\n totalRunCount: runs.length,\n runIdMap: {},\n preservedRunIds: runs.map((run) => run.id),\n updatedScreenshotRows: 0,\n updatedVideoRows: 0,\n renamedScreenshotDirs,\n renamedVideoDirs,\n missingArtifacts,\n }\n }\n\n const updateStepsRunId = db.prepare('UPDATE steps SET run_id = ? WHERE run_id = ?')\n const updateLogsRunId = db.prepare('UPDATE logs SET run_id = ? WHERE run_id = ?')\n const updateExecutionLogsRunId = db.prepare('UPDATE execution_logs SET run_id = ? WHERE run_id = ?')\n const updateRunsParentId = db.prepare('UPDATE runs SET parent_run_id = ? WHERE parent_run_id = ?')\n const updateRunId = db.prepare('UPDATE runs SET id = ? WHERE id = ?')\n const updateStepArtifacts = db.prepare(`\n UPDATE steps\n SET screenshot_path = ?, screenshot_before_path = ?, healing_screenshot_paths = ?\n WHERE id = ?\n `)\n const updateRunVideoPath = db.prepare('UPDATE runs SET video_path = ? WHERE id = ?')\n\n let updatedScreenshotRows = 0\n let updatedVideoRows = 0\n\n db.pragma('foreign_keys = OFF')\n const migrate = db.transaction(() => {\n for (const step of steps) {\n const nextScreenshotPath = rewriteArtifactPath(step.screenshot_path, mapping, screenshotsDir, '/api/screenshots/')\n const nextScreenshotBeforePath = rewriteArtifactPath(step.screenshot_before_path, mapping, screenshotsDir, '/api/screenshots/')\n const nextHealingScreenshotPaths = rewriteJsonStringArray(step.healing_screenshot_paths, mapping, screenshotsDir, '/api/screenshots/')\n\n if (\n nextScreenshotPath !== step.screenshot_path\n || nextScreenshotBeforePath !== step.screenshot_before_path\n || nextHealingScreenshotPaths !== step.healing_screenshot_paths\n ) {\n updateStepArtifacts.run(\n nextScreenshotPath,\n nextScreenshotBeforePath,\n nextHealingScreenshotPaths,\n step.id,\n )\n updatedScreenshotRows += 1\n }\n }\n\n for (const run of runs) {\n const nextVideoPath = rewriteRunVideoPath(run, mapping, videosDir, flatVideoFileMoves)\n if (nextVideoPath !== run.video_path) {\n updateRunVideoPath.run(nextVideoPath, run.id)\n updatedVideoRows += 1\n }\n }\n\n for (const [oldId, newId] of mapping) {\n updateStepsRunId.run(newId, oldId)\n updateLogsRunId.run(newId, oldId)\n updateExecutionLogsRunId.run(newId, oldId)\n updateRunsParentId.run(newId, oldId)\n }\n\n for (const [oldId, newId] of mapping) {\n updateRunId.run(newId, oldId)\n }\n\n runForeignKeyCheck(db)\n })\n\n migrate()\n db.pragma('foreign_keys = ON')\n\n if (screenshotsDir) {\n for (const [oldId, newId] of mapping) {\n await renameDirectoryIfPresent(\n resolve(screenshotsDir, oldId),\n resolve(screenshotsDir, newId),\n renamedScreenshotDirs,\n missingArtifacts,\n logger,\n )\n }\n\n }\n\n if (videosDir) {\n for (const [oldId, newId] of mapping) {\n await renameDirectoryIfPresent(\n resolve(videosDir, oldId),\n resolve(videosDir, newId),\n renamedVideoDirs,\n missingArtifacts,\n logger,\n )\n }\n\n for (const move of flatVideoFileMoves) {\n await moveFileIfPresent(move.fromPath, move.toPath, missingArtifacts, logger)\n }\n }\n\n return {\n migratedRunCount: mapping.size,\n totalRunCount: runs.length,\n runIdMap: Object.fromEntries(mapping),\n preservedRunIds: runs.filter((run) => !mapping.has(run.id)).map((run) => run.id),\n updatedScreenshotRows,\n updatedVideoRows,\n renamedScreenshotDirs,\n renamedVideoDirs,\n missingArtifacts,\n }\n } finally {\n db.close()\n }\n}\n","import { existsSync, mkdirSync, renameSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { DEFAULT_AGENT_QA_RUNS_DB_PATH, LEGACY_AGENT_QA_DASHBOARD_DB_PATH } from '@vostride/agent-qa-core'\n\nconst RUNS_DB_PATH_FALLBACK = DEFAULT_AGENT_QA_RUNS_DB_PATH || '.agent-qa/runs.db'\nconst LEGACY_DB_PATH_FALLBACK = LEGACY_AGENT_QA_DASHBOARD_DB_PATH || '.agent-qa/dashboard.db'\n\nexport interface ResolveDashboardDbPathOptions {\n configDir: string\n configuredDbPath?: string\n}\n\nexport function resolveDashboardDbPath({\n configDir,\n configuredDbPath,\n}: ResolveDashboardDbPathOptions): string {\n const configured = configuredDbPath?.trim()\n if (configured) {\n return resolve(configDir, configured)\n }\n\n const defaultPath = resolve(configDir, RUNS_DB_PATH_FALLBACK)\n const legacyPath = resolve(configDir, LEGACY_DB_PATH_FALLBACK)\n\n if (!existsSync(defaultPath) && existsSync(legacyPath)) {\n mkdirSync(dirname(defaultPath), { recursive: true })\n renameSync(legacyPath, defaultPath)\n }\n\n return defaultPath\n}\n","import { copyFile, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { buildInternalRunAttributes, redactAuthStateValue, validateTrustedRunAttributes } from '@vostride/agent-qa-core'\nimport type { Reporter, RunArtifactReporterContext, RunSummary, TestDefinition, StepResult, TestResult, SuiteDefinition, SuiteSummary, HookEvent, HookResultEvent, SecretRedactor } from '@vostride/agent-qa-core'\nimport type { RunAttributes } from '@vostride/agent-qa-core'\nimport type { DashboardDatabase } from '../db/database.js'\n\nfunction isPathInside(rootDir: string, candidatePath: string): boolean {\n const relativePath = relative(rootDir, candidatePath)\n return Boolean(relativePath) && !relativePath.startsWith('..') && !isAbsolute(relativePath)\n}\n\nasync function moveArtifactFile(sourcePath: string, targetPath: string): Promise<void> {\n await mkdir(dirname(targetPath), { recursive: true })\n try {\n await rename(sourcePath, targetPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'EXDEV') {\n await copyFile(sourcePath, targetPath)\n await unlink(sourcePath)\n return\n }\n throw error\n }\n}\n\nasync function materializeVideoPath(videoPath: string | undefined, artifactsDir: string, runId: string): Promise<string | undefined> {\n if (!videoPath) return videoPath\n const trimmed = videoPath.trim()\n if (!trimmed) return videoPath\n\n const videosDir = resolve(artifactsDir, 'videos')\n let relativePath: string\n let sourcePath: string\n\n if (isAbsolute(trimmed)) {\n sourcePath = resolve(trimmed)\n if (!isPathInside(videosDir, sourcePath)) {\n return trimmed\n }\n relativePath = relative(videosDir, sourcePath)\n } else {\n relativePath = trimmed.replace(/\\\\/g, '/')\n sourcePath = resolve(videosDir, relativePath)\n if (!isPathInside(videosDir, sourcePath)) {\n return relativePath\n }\n }\n\n const normalizedRelativePath = relativePath.replace(/\\\\/g, '/')\n if (normalizedRelativePath.startsWith(`${runId}/`)) {\n return normalizedRelativePath\n }\n\n const targetRelativePath = `${runId}/${basename(normalizedRelativePath)}`\n const targetPath = resolve(videosDir, targetRelativePath)\n try {\n await moveArtifactFile(sourcePath, targetPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return targetRelativePath\n }\n throw error\n }\n\n return targetRelativePath\n}\n\nfunction normalizeVideoPath(videoPath: string | undefined, artifactsDir: string): string | undefined {\n if (!videoPath) return videoPath\n const trimmed = videoPath.trim()\n if (!trimmed || !isAbsolute(trimmed)) return trimmed\n\n const videosDir = resolve(artifactsDir, 'videos')\n const relativePath = relative(videosDir, resolve(trimmed))\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) {\n return trimmed\n }\n return relativePath.replace(/\\\\/g, '/')\n}\n\ninterface TestState {\n runId: string\n name: string\n startedAt: string\n filePath: string\n stepCount: number\n executionKey: string\n attributes: RunAttributes\n}\n\ntype ArtifactReporterContext = RunArtifactReporterContext\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction readAttributesRecord(value: unknown): RunAttributes | null {\n try {\n const attributes = validateTrustedRunAttributes(value, 'run artifact attributes')\n return Object.keys(attributes).length > 0 ? attributes : null\n } catch {\n return null\n }\n}\n\nfunction readArtifactRuntimePlatform(context?: ArtifactReporterContext): string | undefined {\n const runtime = context?.artifact?.runtime\n if (!isRecord(runtime)) return undefined\n const platform = runtime.platform\n return typeof platform === 'string' && platform.trim() ? platform : undefined\n}\n\nfunction resolveRunPlatform(source: unknown, context?: ArtifactReporterContext): string | undefined {\n if (isRecord(source)) {\n const resolvedPlatform = source.resolvedPlatform\n if (typeof resolvedPlatform === 'string' && resolvedPlatform.trim()) return resolvedPlatform\n }\n return readArtifactRuntimePlatform(context)\n}\n\nclass FatalReporterError extends Error {\n readonly fatal = true\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options)\n this.name = 'FatalReporterError'\n }\n}\n\nexport class DashboardReporter implements Reporter {\n private db: DashboardDatabase\n private artifactsDir: string\n private suiteRunId: string | null = null\n private currentSuiteId: string | null = null\n private runIdToState = new Map<string, TestState>()\n private executionKeyToRunId = new Map<string, string>()\n private nameToCurrentRunId = new Map<string, string>()\n private completedResultRunIds = new Map<string, string>()\n private runStartTime: string | null = null\n private onRunCreated?: (runId: string) => void\n private redactor?: SecretRedactor\n\n constructor({\n db,\n artifactsDir = '.agent-qa/artifacts',\n onRunCreated,\n redactor,\n }: {\n db: DashboardDatabase\n artifactsDir?: string\n onRunCreated?: (runId: string) => void\n redactor?: SecretRedactor\n }) {\n this.db = db\n this.artifactsDir = artifactsDir\n this.onRunCreated = onRunCreated\n this.redactor = redactor\n }\n\n private redactValue<T>(value: T): T {\n return redactAuthStateValue(value, { secretRedactor: this.redactor })\n }\n\n private redactString(value: string | undefined): string | undefined {\n return value === undefined ? undefined : this.redactValue(value)\n }\n\n private sanitizeSecretsFileMetadata(value: unknown): unknown {\n if (value === null || value === undefined) return value\n if (!isRecord(value)) return value\n return {\n path: typeof value.path === 'string' || value.path === null ? value.path : null,\n status: typeof value.status === 'string' ? value.status : 'loaded',\n ...(typeof value.count === 'number' ? { count: value.count } : {}),\n }\n }\n\n private sanitizeArtifactPayload<T extends Record<string, unknown>>(payload: T): T {\n const safePayload = this.redactValue(payload) as Record<string, unknown>\n const config = safePayload.config\n if (isRecord(config) && 'secretsFile' in config) {\n safePayload.config = {\n ...config,\n secretsFile: this.sanitizeSecretsFileMetadata(config.secretsFile),\n }\n }\n return safePayload as T\n }\n\n private fallbackAttributes(): RunAttributes {\n return buildInternalRunAttributes({ trigger: 'cli', runner: 'local' })\n }\n\n private readAttributesFromEnv(): RunAttributes | null {\n const raw = process.env.AGENT_QA_RUN_ATTRIBUTES_JSON\n if (!raw) return null\n try {\n return readAttributesRecord(JSON.parse(raw))\n } catch {\n return null\n }\n }\n\n private resolveAttributes(context?: ArtifactReporterContext, existing?: { attributes?: RunAttributes } | null): RunAttributes {\n const contextAttributes = readAttributesRecord(context?.artifact?.metadata?.attributes)\n if (contextAttributes) return contextAttributes\n const envAttributes = this.readAttributesFromEnv()\n if (envAttributes) return envAttributes\n if (existing?.attributes && Object.keys(existing.attributes).length > 0) return existing.attributes\n if (context?.parentRunId) {\n const parent = this.db.getRun(context.parentRunId)\n if (parent?.attributes && Object.keys(parent.attributes).length > 0) return parent.attributes\n }\n if (this.suiteRunId) {\n const parent = this.db.getRun(this.suiteRunId)\n if (parent?.attributes && Object.keys(parent.attributes).length > 0) return parent.attributes\n }\n return this.fallbackAttributes()\n }\n\n private withAttributeMetadata<T extends Record<string, unknown>>(payload: T, attributes: RunAttributes): T {\n const metadata = isRecord(payload.metadata) ? payload.metadata : {}\n return {\n ...payload,\n metadata: {\n ...metadata,\n attributes,\n },\n }\n }\n\n onSuiteStart(suite: SuiteDefinition, context?: ArtifactReporterContext): void {\n const startedAt = new Date().toISOString()\n const suiteId = (suite as any)['suite-id'] ?? null\n const safeSuite = this.redactValue(suite)\n this.currentSuiteId = suiteId\n const requestedRunId = context?.runId ?? process.env.AGENT_QA_SUITE_QUEUE_ID\n const existingSuiteRun = requestedRunId ? this.db.getRun(requestedRunId) : null\n const attributes = this.resolveAttributes(context, existingSuiteRun)\n const platform = resolveRunPlatform(suite, context) ?? 'web'\n if (requestedRunId) {\n this.suiteRunId = requestedRunId\n if (existingSuiteRun) {\n this.db.updateRun(requestedRunId, {\n name: safeSuite.name,\n status: 'running',\n startedAt,\n platform,\n suiteId: suiteId ?? undefined,\n attributes,\n })\n } else {\n this.db.insertRun({\n id: requestedRunId,\n name: safeSuite.name,\n status: 'running',\n duration: 0,\n attributes,\n startedAt,\n endedAt: startedAt,\n platform,\n suiteId: suiteId ?? undefined,\n })\n }\n } else {\n this.suiteRunId = this.db.insertRun({\n name: safeSuite.name,\n status: 'running',\n duration: 0,\n attributes,\n startedAt,\n endedAt: startedAt,\n platform,\n suiteId: suiteId ?? undefined,\n })\n }\n if (this.suiteRunId) {\n this.writeArtifact(() => {\n this.db.insertRunArtifact({\n runId: this.suiteRunId!,\n kind: 'suite-parent',\n payload: this.sanitizeArtifactPayload(this.withAttributeMetadata({\n source: {\n kind: 'suite',\n suiteId,\n name: safeSuite.name,\n resolvedDefinition: safeSuite,\n loadStatus: 'loaded',\n },\n ...(context?.artifact ?? {}),\n }, attributes)),\n })\n })\n }\n }\n\n onSuiteEnd(summary: SuiteSummary): void {\n if (!this.suiteRunId) return\n const safeSummary = this.redactValue(summary)\n this.db.updateRun(this.suiteRunId, {\n status: safeSummary.status,\n duration: safeSummary.duration,\n endedAt: new Date().toISOString(),\n })\n this.writeArtifact(() => {\n this.stageSuiteSummary(this.suiteRunId!, safeSummary)\n this.db.finalizeRunArtifact(this.suiteRunId!, {\n runtime: {\n status: safeSummary.status,\n duration: safeSummary.duration,\n endedAt: new Date().toISOString(),\n },\n })\n })\n this.suiteRunId = null\n this.currentSuiteId = null\n }\n\n onRunStart(_tests: TestDefinition[]): void {\n this.runStartTime = new Date().toISOString()\n }\n\n async onTestStart(test: TestDefinition, filePath: string, context?: ArtifactReporterContext): Promise<void> {\n const startedAt = new Date().toISOString()\n const testId = (test as any)['test-id'] ?? null\n const executionKey = this.createExecutionKey(test, filePath, startedAt)\n const existingStateRunId = this.executionKeyToRunId.get(executionKey)\n if (existingStateRunId && this.runIdToState.has(existingStateRunId)) return\n\n const modelName = process.env.AGENT_QA_LLM_MODEL ?? undefined\n const llmProvider = process.env.AGENT_QA_LLM_PROVIDER ?? undefined\n\n // Insert a 'running' row immediately so the run is visible even if the\n // process is killed before onTestEnd fires (e.g. SIGKILL on cancel).\n const platform = resolveRunPlatform(test, context)\n\n // Snapshot the test file content at run time so we can see exactly what\n // was executed, even if the file is edited later.\n let testFileContent: string | undefined\n try {\n testFileContent = await readFile(filePath, 'utf-8')\n } catch { /* file may not be accessible — non-fatal */ }\n const safeTest = this.redactValue(test)\n const safeTestFileContent = this.redactString(testFileContent)\n const safeTestMeta = this.redactValue(safeTest.meta as Record<string, unknown> | undefined)\n\n const parentRunId = context?.parentRunId ?? process.env.AGENT_QA_PARENT_RUN_ID\n const existingRunId = context?.runId ?? process.env.AGENT_QA_RUN_ID\n const existingRun = existingRunId ? this.db.getRun(existingRunId) : null\n const attributeContext = parentRunId && context?.parentRunId !== parentRunId\n ? { ...context, parentRunId }\n : context\n const attributes = this.resolveAttributes(attributeContext, existingRun)\n let runId: string\n\n if (parentRunId) {\n // Retry attempt — always INSERT a new child run linked to the parent\n const attemptNumber = parseInt(process.env.AGENT_QA_ATTEMPT_NUMBER ?? '1', 10)\n const maxRetries = parseInt(process.env.AGENT_QA_MAX_RETRIES ?? '0', 10)\n runId = this.db.insertRun({\n id: existingRunId,\n name: safeTest.name,\n filePath,\n status: 'running',\n duration: 0,\n attributes,\n metadata: safeTestMeta,\n startedAt,\n endedAt: startedAt,\n parentRunId: this.suiteRunId ?? parentRunId,\n\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n attemptNumber,\n maxRetries,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n })\n } else if (existingRunId) {\n if (existingRun) {\n // Run row already exists from JobQueue.enqueue() — update it instead of inserting\n this.db.updateRun(existingRunId, {\n status: 'running',\n startedAt,\n endedAt: startedAt,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n attributes,\n })\n // Also update fields that insertPendingRun didn't set\n this.db.updateRunMetadata(existingRunId, {\n metadata: safeTestMeta,\n attributes,\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n })\n } else {\n this.db.insertRun({\n id: existingRunId,\n name: safeTest.name,\n filePath,\n status: 'running',\n duration: 0,\n attributes,\n metadata: safeTestMeta,\n startedAt,\n endedAt: startedAt,\n parentRunId: this.suiteRunId ?? undefined,\n\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n })\n }\n runId = existingRunId\n } else {\n runId = this.db.insertRun({\n name: safeTest.name,\n filePath,\n status: 'running',\n duration: 0,\n attributes,\n metadata: safeTestMeta,\n startedAt,\n endedAt: startedAt,\n parentRunId: this.suiteRunId ?? undefined,\n\n platform,\n testFileContent: safeTestFileContent,\n modelName,\n llmProvider,\n testId: testId ?? undefined,\n suiteId: this.currentSuiteId ?? undefined,\n })\n }\n\n this.runIdToState.set(runId, {\n runId,\n name: test.name,\n startedAt,\n filePath,\n stepCount: 0,\n executionKey,\n attributes,\n })\n this.executionKeyToRunId.set(executionKey, runId)\n this.nameToCurrentRunId.set(test.name, runId)\n\n const artifactKind = context?.artifact?.kind ?? (this.suiteRunId ? 'suite-child' : 'test')\n const fallbackArtifact = {\n source: {\n kind: 'test',\n testId,\n name: safeTest.name,\n filePath,\n rawYaml: safeTestFileContent ?? null,\n resolvedDefinition: safeTest,\n loadStatus: 'loaded',\n },\n runtime: {\n status: 'running',\n startedAt,\n platform,\n },\n }\n this.writeArtifact(() => {\n this.db.insertRunArtifact({\n runId,\n kind: artifactKind,\n payload: this.sanitizeArtifactPayload(this.withAttributeMetadata({\n ...fallbackArtifact,\n ...(context?.artifact ?? {}),\n }, attributes)),\n })\n if (this.suiteRunId && typeof context?.artifact?.suiteIndex === 'number') {\n this.stageSuiteChildLink(this.suiteRunId, context.artifact.suiteIndex, runId)\n }\n })\n\n this.onRunCreated?.(runId)\n }\n\n async onStepEnd(result: StepResult, testName: string): Promise<void> {\n const state = this.getStateByTestName(testName)\n if (!state) return\n\n const runId = state.runId\n const stepOrder = state.stepCount++\n\n // Persist step immediately so it survives process kill on cancellation\n await this.persistStep(result, runId, stepOrder)\n }\n\n async onTestEnd(result: TestResult): Promise<void> {\n const state = this.getStateForResult(result)\n const safeResult = this.redactValue(result)\n const endedAt = new Date().toISOString()\n const errorLog = this.buildResultErrorLog(safeResult)\n let fallbackResultAttributes: RunAttributes | undefined\n\n let runId: string\n if (state) {\n // The run row was already inserted in onTestStart with status='running'.\n // Update it with the final status, duration, and summary.\n runId = state.runId\n const normalizedVideoPath = await materializeVideoPath(safeResult.videoPath, this.artifactsDir, runId)\n this.db.updateRun(runId, {\n name: safeResult.name,\n status: safeResult.status,\n duration: safeResult.duration,\n endedAt,\n failureSummary: safeResult.failureSummary,\n errorLog,\n videoPath: normalizedVideoPath,\n })\n if (safeResult.metadata) {\n this.db.updateRunMetadata(runId, { metadata: safeResult.metadata as Record<string, unknown> })\n }\n if ((safeResult as any).memoryLog) {\n this.db.updateRun(runId, {\n memoryLog: JSON.stringify((safeResult as any).memoryLog),\n })\n }\n } else {\n // Fallback: onTestStart was never called (programmatic usage).\n // Insert the run directly with the final result.\n const modelName = process.env.AGENT_QA_LLM_MODEL ?? undefined\n const llmProvider = process.env.AGENT_QA_LLM_PROVIDER ?? undefined\n const resultMetadata = isRecord(safeResult.metadata) ? safeResult.metadata : undefined\n const resultAttributes = readAttributesRecord(resultMetadata?.attributes)\n const attributes = resultAttributes ?? this.resolveAttributes()\n fallbackResultAttributes = attributes\n const fallbackRunId = process.env.AGENT_QA_RUN_ID || undefined\n\n let testFileContent: string | undefined\n if (result.filePath) {\n try {\n testFileContent = await readFile(result.filePath, 'utf-8')\n } catch { /* non-fatal */ }\n }\n\n runId = this.db.insertRun({\n id: fallbackRunId,\n name: safeResult.name,\n filePath: safeResult.filePath,\n status: safeResult.status,\n duration: safeResult.duration,\n attributes,\n metadata: safeResult.metadata,\n startedAt: endedAt,\n endedAt,\n parentRunId: this.suiteRunId ?? undefined,\n\n videoPath: undefined,\n failureSummary: safeResult.failureSummary,\n platform: (safeResult.metadata as Record<string, unknown> | undefined)?.platform as string | undefined,\n testFileContent: this.redactString(testFileContent),\n modelName,\n llmProvider,\n suiteId: this.currentSuiteId ?? undefined,\n })\n const normalizedVideoPath = await materializeVideoPath(safeResult.videoPath, this.artifactsDir, runId)\n this.db.updateRun(runId, { videoPath: normalizedVideoPath })\n if (errorLog) {\n this.db.updateRun(runId, { errorLog })\n }\n this.writeArtifact(() => {\n this.db.insertRunArtifact({\n runId,\n kind: this.suiteRunId ? 'suite-child' : 'test',\n payload: {\n source: {\n kind: 'test',\n name: safeResult.name,\n filePath: safeResult.filePath,\n rawYaml: this.redactString(testFileContent) ?? null,\n loadStatus: 'runtime-error',\n },\n metadata: { attributes },\n },\n })\n })\n }\n\n // Steps were already persisted in onStepEnd. If onStepEnd was not called\n // (e.g. programmatic usage without per-step callbacks), persist any remaining.\n if (!state || state.stepCount === 0) {\n for (let i = 0; i < safeResult.steps.length; i++) {\n await this.persistStep(safeResult.steps[i], runId, i)\n }\n }\n\n const storedVideoPath = this.db.getRun(runId)?.videoPath ?? normalizeVideoPath(safeResult.videoPath, this.artifactsDir)\n const memoryLog = (safeResult as any).memoryLog\n this.writeArtifact(() => {\n const patch: Record<string, unknown> = {\n runtime: {\n status: safeResult.status,\n duration: safeResult.duration,\n endedAt,\n videoPath: storedVideoPath ?? null,\n failureSummary: safeResult.failureSummary ?? null,\n errorLog: errorLog ?? null,\n metadata: safeResult.metadata ?? null,\n },\n }\n if ((safeResult.status === 'failed' || safeResult.status === 'cancelled') && (safeResult.failureSummary || errorLog)) {\n patch.errors = [{\n code: safeResult.status,\n phase: 'test',\n message: safeResult.failureSummary ?? errorLog!,\n }]\n }\n if (memoryLog) {\n patch.memory = { log: memoryLog }\n }\n patch.metadata = { attributes: state?.attributes ?? fallbackResultAttributes ?? this.resolveAttributes() }\n const artifact = this.db.getRunArtifact(runId)\n if (artifact && !artifact.finalizedAt) {\n this.db.stageRunArtifact(runId, patch as any)\n }\n })\n\n this.completedResultRunIds.set(this.resultKey(result), runId)\n this.deleteState(state, result.name)\n }\n\n onRunEnd(summary: RunSummary): void {\n for (const result of summary.results) {\n const runId = this.completedResultRunIds.get(this.resultKey(result))\n if (!runId) continue\n this.writeArtifact(() => {\n const artifact = this.db.getRunArtifact(runId)\n if (!artifact || artifact.finalizedAt) return\n const memoryLog = this.redactValue((result as any).memoryLog)\n if (memoryLog) {\n this.db.updateRun(runId, { memoryLog: JSON.stringify(memoryLog) })\n this.db.stageRunArtifact(runId, { memory: { log: memoryLog } as any })\n }\n this.db.finalizeRunArtifact(runId)\n })\n this.completedResultRunIds.delete(this.resultKey(result))\n }\n }\n\n onHookEnd(event: HookResultEvent): void {\n const safeEvent = this.redactValue(event)\n const runId = safeEvent.runId ?? this.getCurrentRunId() ?? this.suiteRunId\n if (!runId) return\n\n try {\n this.db.insertExecutionLog({\n id: safeEvent.hookExecutionId,\n runId,\n stepId: safeEvent.stepId ?? null,\n type: safeEvent.type ?? 'hook',\n name: safeEvent.hookName,\n hookId: safeEvent.hookId ?? null,\n phase: safeEvent.phase,\n status: safeEvent.status,\n duration: safeEvent.duration,\n stdout: safeEvent.stdout || null,\n stderr: safeEvent.stderr || null,\n variables: Object.keys(safeEvent.variables).length > 0 ? safeEvent.variables : null,\n })\n } catch {\n // DB write failure should not crash the test\n }\n }\n\n private getCurrentRunId(): string | null {\n for (const state of this.runIdToState.values()) {\n return state.runId\n }\n return null\n }\n\n private createExecutionKey(test: TestDefinition, filePath: string, startedAt: string): string {\n const testId = (test as any)['test-id'] as string | undefined\n return `${testId ?? test.name}|${filePath || startedAt}`\n }\n\n private getStateByTestName(testName: string): TestState | undefined {\n const runId = this.nameToCurrentRunId.get(testName)\n return runId ? this.runIdToState.get(runId) : undefined\n }\n\n private getStateForResult(result: TestResult): TestState | undefined {\n if (result.runId) {\n const state = this.runIdToState.get(result.runId)\n if (state) return state\n }\n for (const state of this.runIdToState.values()) {\n if (state.name === result.name && (!result.filePath || state.filePath === result.filePath)) {\n return state\n }\n }\n return this.getStateByTestName(result.name)\n }\n\n private deleteState(state: TestState | undefined, testName: string): void {\n if (!state) return\n this.runIdToState.delete(state.runId)\n this.executionKeyToRunId.delete(state.executionKey)\n if (this.nameToCurrentRunId.get(testName) === state.runId) {\n this.nameToCurrentRunId.delete(testName)\n }\n }\n\n private resultKey(result: Pick<TestResult, 'name' | 'filePath'>): string {\n return `${result.name}|${result.filePath ?? ''}`\n }\n\n private buildResultErrorLog(result: TestResult): string | undefined {\n if (result.status !== 'failed' && result.status !== 'cancelled') return undefined\n const lines = [\n result.failureSummary,\n ...result.steps.flatMap((step) => [\n step.error,\n step.trace?.error,\n ]),\n ].filter((line): line is string => typeof line === 'string' && line.trim().length > 0)\n return lines.length > 0 ? [...new Set(lines)].join('\\n') : undefined\n }\n\n private writeArtifact<T>(fn: () => T): T {\n try {\n return fn()\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new FatalReporterError(`Artifact persistence failed: ${message}`, { cause: err })\n }\n }\n\n private stageSuiteChildLink(parentRunId: string, suiteIndex: number, childRunId: string): void {\n const parent = this.db.getRunArtifact(parentRunId)\n const source = parent?.payload.source\n if (!source || typeof source !== 'object' || !('members' in source) || !Array.isArray((source as any).members)) {\n return\n }\n const members = [...(source as any).members]\n const member = members[suiteIndex]\n if (!member || typeof member !== 'object') return\n members[suiteIndex] = { ...member, childRunId }\n this.db.stageRunArtifact(parentRunId, {\n source: {\n members,\n } as any,\n })\n }\n\n private stageSuiteSummary(parentRunId: string, summary: SuiteSummary): void {\n const parent = this.db.getRunArtifact(parentRunId)\n const source = parent?.payload.source\n if (!source || typeof source !== 'object' || !('members' in source) || !Array.isArray((source as any).members)) {\n return\n }\n const childRuns = this.db.getRunsByParent(parentRunId)\n const members = [...(source as any).members].map((member, index) => {\n if (!member || typeof member !== 'object') return member\n const memberRecord = { ...(member as Record<string, unknown>) }\n const child = childRuns.find((run) =>\n run.filePath === memberRecord.filePath\n || (typeof memberRecord.name === 'string' && run.name === memberRecord.name)\n )\n if (child) memberRecord.childRunId = child.id\n const result = summary.tests[index]\n const skipReason = (result?.metadata as Record<string, unknown> | undefined)?.skipReason\n if (result?.status === 'skipped' && typeof skipReason === 'string') {\n memberRecord.loadStatus = 'skipped'\n memberRecord.skipReason = skipReason\n }\n return memberRecord\n })\n this.db.stageRunArtifact(parentRunId, {\n source: { members } as any,\n memory: { aggregate: this.buildSuiteMemoryAggregate(parentRunId) } as any,\n })\n }\n\n private buildSuiteMemoryAggregate(parentRunId: string): Record<string, unknown> {\n const children = this.db.getRunsByParent(parentRunId)\n const aggregate = {\n added: 0,\n confirmed: 0,\n deprecated: 0,\n deleted: 0,\n errors: 0,\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n childRunIds: [] as string[],\n }\n for (const child of children) {\n let rawLog: unknown = null\n if (child.memoryLog) {\n try {\n rawLog = JSON.parse(child.memoryLog)\n } catch {\n rawLog = null\n }\n }\n if (!rawLog) {\n const childArtifact = this.db.getRunArtifact(child.id)\n const memory = childArtifact?.payload.memory\n rawLog = isRecord(memory) ? memory.log : null\n }\n if (!isRecord(rawLog)) continue\n try {\n const log = rawLog as {\n added?: number\n confirmed?: number\n deprecated?: number\n deleted?: number\n errors?: unknown[]\n tokenUsage?: { promptTokens?: number; completionTokens?: number; totalTokens?: number }\n }\n aggregate.added += log.added ?? 0\n aggregate.confirmed += log.confirmed ?? 0\n aggregate.deprecated += log.deprecated ?? 0\n aggregate.deleted += log.deleted ?? 0\n aggregate.errors += Array.isArray(log.errors) ? log.errors.length : 0\n aggregate.promptTokens += log.tokenUsage?.promptTokens ?? 0\n aggregate.completionTokens += log.tokenUsage?.completionTokens ?? 0\n aggregate.totalTokens += log.tokenUsage?.totalTokens ?? 0\n aggregate.childRunIds.push(child.id)\n } catch { /* skip malformed log */ }\n }\n return aggregate\n }\n\n private async persistStep(step: StepResult, runId: string, stepOrder: number): Promise<void> {\n const safeStep = this.redactValue(step)\n let screenshotPath: string | undefined\n let screenshotBeforePath: string | undefined\n\n if (safeStep.screenshotBefore) {\n screenshotBeforePath = await this.saveScreenshot(safeStep.screenshotBefore, runId, stepOrder, safeStep.name, 'before')\n }\n if (safeStep.screenshot) {\n screenshotPath = await this.saveScreenshot(safeStep.screenshot, runId, stepOrder, safeStep.name)\n }\n\n let healingScreenshotPaths: string[] | undefined\n if (safeStep.healingScreenshots && safeStep.healingScreenshots.length > 0) {\n healingScreenshotPaths = []\n for (let j = 0; j < safeStep.healingScreenshots.length; j++) {\n const healPath = await this.saveHealingScreenshot(safeStep.healingScreenshots[j], runId, stepOrder, j)\n healingScreenshotPaths.push(healPath)\n }\n }\n\n let subActionsForDb: unknown[] | undefined\n if (safeStep.trace?.subActions && safeStep.trace.subActions.length > 0) {\n subActionsForDb = []\n for (let j = 0; j < safeStep.trace.subActions.length; j++) {\n const sub = safeStep.trace.subActions[j]\n const mapped: Record<string, unknown> = { ...sub }\n delete mapped.screenshotBefore\n delete mapped.screenshotAfter\n if (sub.screenshotBefore) {\n mapped.screenshotBeforePath = await this.saveSubActionScreenshot(sub.screenshotBefore, runId, stepOrder, j, 'before')\n }\n if (sub.screenshotAfter) {\n mapped.screenshotAfterPath = await this.saveSubActionScreenshot(sub.screenshotAfter, runId, stepOrder, j, 'after')\n }\n subActionsForDb.push(mapped)\n }\n }\n\n const stepId = this.db.insertStep({\n id: safeStep.id,\n runId,\n name: safeStep.name,\n status: safeStep.status,\n duration: safeStep.duration,\n action: safeStep.action,\n observation: safeStep.trace?.observation ?? safeStep.observation,\n reasoning: safeStep.trace?.reasoning,\n plannedAction: safeStep.trace?.plannedAction,\n result: safeStep.trace?.result,\n error: safeStep.error ?? safeStep.trace?.error,\n screenshotPath,\n screenshotBeforePath,\n healingAttempts: safeStep.healingAttempts,\n retryCount: safeStep.retryCount,\n capturedVariables: safeStep.capturedVariables,\n stepOrder,\n annotationData: safeStep.annotation,\n healingScreenshotPaths,\n accessibilityViolations: safeStep.accessibilityViolations,\n confidence: safeStep.trace?.confidence,\n promptTokens: safeStep.trace?.tokenUsage?.promptTokens,\n completionTokens: safeStep.trace?.tokenUsage?.completionTokens,\n totalTokens: safeStep.trace?.tokenUsage?.totalTokens,\n subActionsData: subActionsForDb,\n consoleLogs: safeStep.consoleLogs,\n networkLogs: safeStep.networkLogs,\n variableSnapshot: safeStep.variableSnapshot,\n originalStepName: safeStep.originalStepName,\n screenContextBefore: safeStep.trace?.screenContextBefore,\n screenContextAfter: safeStep.trace?.screenContextAfter,\n })\n\n if (safeStep.trace?.tokenUsage && (safeStep.trace.tokenUsage.promptTokens > 0 || safeStep.trace.tokenUsage.completionTokens > 0)) {\n const modelName = process.env.AGENT_QA_LLM_MODEL ?? 'unknown'\n this.db.insertTokenEvent({\n modelName,\n promptTokens: safeStep.trace.tokenUsage.promptTokens,\n completionTokens: safeStep.trace.tokenUsage.completionTokens,\n source: 'test-run',\n })\n }\n\n if (safeStep.trace?.phaseDurations) {\n this.db.insertReasoningTrace({\n stepId,\n observeText: safeStep.trace.observation,\n observeDuration: safeStep.trace.phaseDurations.observe,\n planReasoning: safeStep.trace.reasoning,\n planConfidence: safeStep.trace.confidence,\n planAction: safeStep.trace.plannedAction,\n planDuration: safeStep.trace.phaseDurations.plan,\n executeAction: safeStep.action,\n executeDuration: safeStep.trace.phaseDurations.execute,\n verifyReasoning: safeStep.trace.verifierReasoning,\n verifySuccess: safeStep.trace.result === 'success',\n verifyDuration: safeStep.trace.phaseDurations.verify,\n healAttempts: safeStep.healingAttempts,\n totalDuration: safeStep.duration,\n screenStateBefore: safeStep.trace.screenStateBefore,\n screenStateAfter: safeStep.trace.screenStateAfter,\n })\n }\n }\n\n private async saveScreenshot(buffer: Buffer, runId: string, stepOrder: number, stepName: string, suffix?: string): Promise<string> {\n const sanitized = stepName.replace(/[^a-zA-Z0-9_-]/g, '_').substring(0, 50)\n const dir = join(this.artifactsDir, 'screenshots', runId)\n await mkdir(dir, { recursive: true })\n const filename = suffix\n ? `${stepOrder}-${sanitized}-${suffix}.png`\n : `${stepOrder}-${sanitized}.png`\n await writeFile(join(dir, filename), buffer)\n return join(runId, filename)\n }\n\n private async saveHealingScreenshot(buffer: Buffer, runId: string, stepOrder: number, attemptIndex: number): Promise<string> {\n const dir = join(this.artifactsDir, 'screenshots', runId)\n await mkdir(dir, { recursive: true })\n const filename = `${stepOrder}-healing-${attemptIndex}.png`\n await writeFile(join(dir, filename), buffer)\n return join(runId, filename)\n }\n\n private async saveSubActionScreenshot(buffer: Buffer, runId: string, stepOrder: number, subIndex: number, suffix: 'before' | 'after'): Promise<string> {\n const dir = join(this.artifactsDir, 'screenshots', runId)\n await mkdir(dir, { recursive: true })\n const filename = `${stepOrder}-sub-${subIndex}-${suffix}.png`\n await writeFile(join(dir, filename), buffer)\n return join(runId, filename)\n }\n}\n","import { createServer, type Server } from 'node:http'\nimport { readFile, stat } from 'node:fs/promises'\nimport { join, extname, resolve } from 'node:path'\nimport { cpus } from 'node:os'\nimport type { DashboardDatabase } from '../db/database.js'\nimport { createRouter } from './routes.js'\nimport { TestRunner } from '../execution/test-runner.js'\nimport { JobQueue } from '../queue/job-queue.js'\nimport { TestFileManager } from '../tests/test-file-manager.js'\nimport { SuiteFileManager } from '../tests/suite-file-manager.js'\nimport { ConfigManager } from '../config/index.js'\nimport { AppiumManager } from '../execution/appium-manager.js'\nimport { WebSocketServer } from 'ws'\nimport { SessionManager } from '../live-editor/session-manager.js'\nimport { createSessionHandler } from '../live-editor/ws-handler.js'\nimport {\n buildAnalyticsEvent,\n captureAnalytics,\n resolveAnalyticsStandardProperties,\n type ModelConfig,\n type ResolvedWorkspacePaths,\n} from '@vostride/agent-qa-core'\nimport {\n createLocalMcpHttpHandler,\n resolveLocalMcpEndpoint,\n resolveMcpEndpointShape,\n type LocalMcpEndpointConfig,\n type LocalMcpTransport,\n} from '@vostride/agent-qa-mcp'\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript',\n '.mjs': 'application/javascript',\n '.css': 'text/css',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.svg': 'image/svg+xml',\n '.json': 'application/json',\n '.woff2': 'font/woff2',\n '.woff': 'font/woff',\n '.ttf': 'font/ttf',\n '.ico': 'image/x-icon',\n '.map': 'application/json',\n '.webp': 'image/webp',\n}\n\nfunction isAnalyticsPrivacyEnabled(config: unknown): boolean {\n if (!config || typeof config !== 'object') return false\n const analytics = (config as { analytics?: unknown }).analytics\n return Boolean(analytics && typeof analytics === 'object'\n && (analytics as { privacy?: unknown }).privacy === true)\n}\n\ninterface StartServerOptions {\n db: DashboardDatabase\n port?: number\n uiDir?: string\n artifactsDir?: string\n workspacePaths?: ResolvedWorkspacePaths\n configPath?: string\n mcp?: LocalMcpEndpointConfig\n llmConfig?: Pick<\n ModelConfig,\n 'provider' | 'model' | 'apiKey' | 'authToken' | 'baseURL' | 'providerHeaders'\n > & {\n screenshotSize?: number\n effectiveResolution?: number\n }\n authFetch?: typeof globalThis.fetch\n}\n\ninterface McpStartupInfo {\n enabled: boolean\n transport: LocalMcpTransport\n host?: string\n port?: number\n path?: string\n url?: string\n}\n\nexport async function startServer(opts: StartServerOptions): Promise<{\n server: Server\n port: number\n mcp: McpStartupInfo\n close: () => void\n}> {\n const { db, port = 3470, uiDir, artifactsDir, workspacePaths, configPath, mcp, llmConfig, authFetch } = opts\n\n const resolvedConfigPath = configPath ?? resolve('agent-qa.config.yaml')\n const configManager = new ConfigManager(resolvedConfigPath)\n\n // Read concurrency from config (defaults to os.cpus().length)\n const config = await configManager.read().catch(() => ({}))\n const concurrency = typeof (config as any).concurrency === 'number'\n ? (config as any).concurrency\n : cpus().length\n\n let testRunner: TestRunner | undefined\n\n const finalizeRunArtifactBestEffort = (\n runId: string,\n code: string,\n phase: string,\n message: string,\n runtime: Record<string, unknown> = {},\n ): void => {\n try {\n const artifact = db.getRunArtifact(runId)\n if (!artifact || artifact.finalizedAt) return\n db.finalizeRunArtifact(runId, {\n runtime,\n errors: [{ code, phase, message }],\n } as any)\n } catch { /* best-effort cleanup */ }\n }\n\n // Resolve CLI binary once — used by TestRunner\n let cliBin: string | undefined\n try {\n cliBin = TestRunner.resolveCliBin()\n } catch {\n console.warn('Warning: Could not resolve agent-qa CLI binary. Execution will not work.')\n }\n\n // TestRunner for live test execution\n if (cliBin) {\n testRunner = new TestRunner({\n cliBin,\n onProcessClose: (runId, status) => {\n // If the child process exited but the DB row is still 'running',\n // update it so the dashboard doesn't show a stuck run.\n try {\n const run = db.getRun(runId)\n const handle = testRunner!.getHandle(runId)\n const isBrowserDisconnect = handle?.output.some(line =>\n line.includes('Target page, context or browser has been closed') ||\n line.includes('Browser closed by user')\n )\n if (run && (run.status === 'running' || run.status === 'cancelled')) {\n const duration = run.startedAt\n ? Date.now() - new Date(run.startedAt).getTime()\n : 0\n\n let dbStatus: string\n let failureSummary: string | undefined\n let errorLog: string | undefined\n const explicitCancellation = run.status === 'cancelled' || status === 'cancelled'\n if (explicitCancellation) {\n dbStatus = 'cancelled'\n failureSummary = undefined\n } else if (status === 'timeout') {\n dbStatus = 'failed'\n failureSummary = 'Test timed out -- process was killed'\n } else if (status === 'completed') {\n dbStatus = 'failed'\n failureSummary = 'Process exited before test completed'\n } else if (isBrowserDisconnect) {\n dbStatus = 'cancelled'\n failureSummary = 'Browser closed by user'\n } else {\n dbStatus = 'failed'\n const outputLines = handle?.output.map(l => l.replace(/\\x1b\\[[0-9;]*m/g, '')) ?? []\n const meaningfulLine = [...outputLines].reverse().find(l =>\n /error/i.test(l) || l.includes('Parse') || l.includes('not found') || l.includes('rejected')\n )\n failureSummary = meaningfulLine\n ? meaningfulLine.slice(0, 300)\n : 'Process exited before test completed'\n }\n\n if (dbStatus === 'failed' && handle?.output.length) {\n errorLog = handle.output\n .join('\\n')\n .replace(/\\x1b\\[[0-9;]*m/g, '')\n .slice(-10000) || undefined\n }\n\n // Suite parent: derive status from child test runs\n if (run.suiteId && !run.parentRunId) {\n const children = db.getRunsByParent(runId)\n const incompleteChildStatus = dbStatus === 'cancelled' ? 'cancelled' : 'failed'\n const incompleteChildSummary = incompleteChildStatus === 'cancelled'\n ? 'Suite cancelled'\n : failureSummary ?? 'Suite process terminated'\n\n for (const child of children) {\n if (child.status === 'running' || child.status === 'pending') {\n db.updateRun(child.id, {\n status: incompleteChildStatus,\n endedAt: new Date().toISOString(),\n failureSummary: incompleteChildSummary,\n })\n finalizeRunArtifactBestEffort(\n child.id,\n 'suite-process-close',\n 'process-close',\n incompleteChildSummary,\n { status: incompleteChildStatus, finalStatus: incompleteChildStatus, processStatus: status },\n )\n }\n }\n\n const updatedChildren = db.getRunsByParent(runId)\n\n const statusPriority: Record<string, number> = {\n failed: 4,\n cancelled: 3,\n flaky: 2,\n passed: 1,\n skipped: 0,\n pending: 0,\n running: 0,\n }\n\n let worstStatus = 'passed'\n let worstPriority = 0\n for (const child of updatedChildren) {\n const p = statusPriority[child.status] ?? 0\n if (p > worstPriority) {\n worstPriority = p\n worstStatus = child.status\n }\n }\n\n if (updatedChildren.length === 0) {\n if (isBrowserDisconnect) {\n worstStatus = 'cancelled'\n } else {\n worstStatus = dbStatus\n }\n }\n\n db.updateRun(runId, {\n status: worstStatus,\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: worstStatus === 'failed' ? 'Suite test(s) failed'\n : worstStatus === 'cancelled' ? (isBrowserDisconnect ? 'Browser closed by user' : 'Suite cancelled')\n : undefined,\n })\n finalizeRunArtifactBestEffort(\n runId,\n 'suite-process-close',\n 'process-close',\n worstStatus === 'cancelled' ? (isBrowserDisconnect ? 'Browser closed by user' : 'Suite cancelled') : 'Suite process closed',\n { status: worstStatus, finalStatus: worstStatus, processStatus: status, duration },\n )\n\n releaseMobileAppiumLease(runId, 'suite-process-close')\n jobQueue.onSlotFreed(runId)\n return\n }\n\n // Check for retry child runs and classify accordingly\n const childRuns = db.getRunsByParent(runId)\n if (childRuns.length > 0) {\n const incompleteChildStatus = dbStatus === 'cancelled' ? 'cancelled' : 'failed'\n const incompleteChildSummary = incompleteChildStatus === 'cancelled'\n ? 'Retry cancelled'\n : failureSummary ?? 'Retry process terminated'\n for (const child of childRuns) {\n if (child.status === 'running' || child.status === 'pending') {\n db.updateRun(child.id, {\n status: incompleteChildStatus,\n endedAt: new Date().toISOString(),\n failureSummary: incompleteChildSummary,\n })\n finalizeRunArtifactBestEffort(\n child.id,\n 'retry-process-close',\n 'process-close',\n incompleteChildSummary,\n { status: incompleteChildStatus, finalStatus: incompleteChildStatus, processStatus: status },\n )\n }\n }\n\n const updatedChildRuns = db.getRunsByParent(runId)\n const anyPassed = updatedChildRuns.some(r => r.status === 'passed')\n const firstPassed = updatedChildRuns[0]?.status === 'passed'\n if (anyPassed && !firstPassed) {\n dbStatus = 'flaky'\n } else if (anyPassed && firstPassed) {\n dbStatus = 'passed'\n } else if (dbStatus === 'cancelled' || updatedChildRuns.some(r => r.status === 'cancelled')) {\n dbStatus = 'cancelled'\n } else {\n dbStatus = 'failed'\n }\n const lastChild = updatedChildRuns[updatedChildRuns.length - 1]\n db.updateRun(runId, {\n status: dbStatus,\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: dbStatus === 'failed' ? 'All retry attempts failed'\n : dbStatus === 'cancelled' ? 'Retry cancelled'\n : undefined,\n })\n finalizeRunArtifactBestEffort(\n runId,\n 'retry-process-close',\n 'process-close',\n dbStatus === 'failed' ? 'All retry attempts failed'\n : dbStatus === 'cancelled' ? 'Retry cancelled'\n : 'Retry process closed',\n { status: dbStatus, finalStatus: dbStatus, processStatus: status, duration },\n )\n db.updateRunRetryInfo(runId, {\n retryCount: updatedChildRuns.length,\n maxRetries: lastChild?.maxRetries ?? run.maxRetries,\n })\n releaseMobileAppiumLease(runId, 'retry-process-close')\n jobQueue.onSlotFreed(runId)\n return\n }\n\n db.updateRun(runId, {\n status: dbStatus,\n duration,\n endedAt: new Date().toISOString(),\n failureSummary,\n errorLog,\n })\n finalizeRunArtifactBestEffort(\n runId,\n isBrowserDisconnect ? 'browser-disconnect' : 'process-close',\n 'process-close',\n failureSummary ?? 'Process closed',\n { status: dbStatus, finalStatus: dbStatus, processStatus: status, duration },\n )\n }\n } catch { /* best-effort */ }\n\n releaseMobileAppiumLease(runId, status)\n jobQueue.onSlotFreed(runId)\n },\n })\n }\n\n // Clean up orphaned runs from previous server sessions — any run still\n // marked 'running' in the DB has no live process and should be failed.\n // Suite parents with active children are skipped (CLI process may still be running).\n const orphaned = db.getRuns({ status: 'running' })\n let cleaned = 0\n for (const run of orphaned) {\n if (run.suiteId && !run.parentRunId) {\n const children = db.getRunsByParent(run.id)\n if (children.some(c => c.status === 'running')) {\n continue\n }\n }\n const duration = run.startedAt\n ? Date.now() - new Date(run.startedAt).getTime()\n : 0\n db.updateRun(run.id, {\n status: 'failed',\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: 'Process terminated unexpectedly (server restarted)',\n })\n finalizeRunArtifactBestEffort(run.id, 'server-restart', 'startup-cleanup', 'Process terminated unexpectedly (server restarted)', { status: 'failed', duration })\n cleaned++\n }\n if (cleaned > 0) {\n console.log(`Cleaned up ${cleaned} orphaned run(s) stuck in 'running' state`)\n }\n\n // Log any pending rows left from previous session (benign — picked up when queue starts)\n const pendingOrphans = db.getRuns({ status: 'pending' })\n if (pendingOrphans.length > 0) {\n console.log(`Found ${pendingOrphans.length} pending run(s) from previous session — will be processed when queue starts`)\n }\n\n // Appium lifecycle manager — auto-starts Appium for mobile tests\n const appiumManager = new AppiumManager()\n const mobileRuns = new Map<string, 'android' | 'ios'>()\n\n const releaseMobileAppiumLease = (runId: string, reason: string): void => {\n const platform = mobileRuns.get(runId)\n if (!platform) return\n mobileRuns.delete(runId)\n appiumManager.releaseLease(runId, reason)\n }\n\n const releaseAllMobileAppiumLeases = (reason: string): void => {\n for (const runId of [...mobileRuns.keys()]) {\n releaseMobileAppiumLease(runId, reason)\n }\n }\n\n // Persistent job queue — all triggers route through this\n const jobQueue = new JobQueue({ db, concurrency })\n console.log(`Job queue started with ${concurrency} concurrency slot(s)`)\n console.log('Appium lifecycle manager initialized (auto-start on first mobile test)')\n\n // Wire JobQueue 'execute' event to TestRunner\n jobQueue.on('execute', async (run) => {\n if (!testRunner) return\n\n const platform = run.platform ?? 'web'\n const isMobile = platform === 'ios' || platform === 'android'\n\n // Ensure Appium is running before mobile test execution\n if (isMobile) {\n try {\n await appiumManager.acquireLease({ runId: run.id, platform })\n mobileRuns.set(run.id, platform)\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Failed to start Appium for run ${run.id}: ${message}`)\n db.updateRun(run.id, {\n status: 'failed',\n failureSummary: `Appium server failed to start: ${message}`,\n endedAt: new Date().toISOString(),\n })\n finalizeRunArtifactBestEffort(run.id, 'appium-startup', 'appium-startup', `Appium server failed to start: ${message}`, { status: 'failed' })\n jobQueue.onSlotFreed(run.id)\n return\n }\n }\n\n const meta = (run.metadata ?? {}) as Record<string, unknown>\n const args = Array.isArray(meta.args)\n ? meta.args.filter((arg): arg is string => typeof arg === 'string')\n : []\n if (args.length === 0 && run.filePath) {\n args.push(run.filePath)\n }\n testRunner.execute({\n runId: run.id,\n args,\n source: meta.isSuite ? 'suite' : 'dashboard',\n attributes: run.attributes,\n timeout: meta.timeout as number | undefined,\n maxRetries: run.maxRetries,\n env: isMobile ? { AGENT_QA_APPIUM_URL: appiumManager.getUrl() } : undefined,\n })\n })\n\n // Wire cancellation — running jobs need process kill via TestRunner\n jobQueue.on('cancel-running', (runId: string) => {\n testRunner?.kill(runId)\n })\n\n // Start the queue polling loop\n jobQueue.start()\n\n // TestFileManager for test file CRUD\n const testFileManager = workspacePaths ? new TestFileManager(workspacePaths) : undefined\n\n const suiteFileManager = workspacePaths ? new SuiteFileManager(workspacePaths, testFileManager) : undefined\n\n const sessionManager = new SessionManager({\n appiumManager,\n configManager,\n configPath: resolvedConfigPath,\n })\n\n const apiRouter = createRouter({\n db,\n artifactsDir,\n workspacePaths,\n testRunner,\n jobQueue,\n testFileManager,\n suiteFileManager,\n configManager,\n configPath: resolvedConfigPath,\n llmConfig,\n authFetch,\n sessionManager,\n })\n\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', 'http://localhost')\n const path = url.pathname\n\n // API routes\n if (path.startsWith('/api/')) {\n apiRouter(req, res)\n return\n }\n\n // OPTIONS preflight\n if (req.method === 'OPTIONS') {\n res.writeHead(204, {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n })\n res.end()\n return\n }\n\n // Static file serving\n if (uiDir) {\n const filePath = path === '/' ? join(uiDir, 'index.html') : join(uiDir, path)\n\n try {\n const fileStat = await stat(filePath)\n if (fileStat.isFile()) {\n const content = await readFile(filePath)\n const ext = extname(filePath)\n const contentType = MIME_TYPES[ext] || 'application/octet-stream'\n res.writeHead(200, {\n 'Content-Type': contentType,\n 'Content-Length': content.length,\n 'Access-Control-Allow-Origin': '*',\n })\n res.end(content)\n return\n }\n } catch {\n // File not found — fall through to SPA fallback\n }\n\n // SPA fallback: serve index.html for non-file paths\n try {\n const indexPath = join(uiDir, 'index.html')\n const content = await readFile(indexPath)\n res.writeHead(200, {\n 'Content-Type': 'text/html',\n 'Content-Length': content.length,\n 'Access-Control-Allow-Origin': '*',\n })\n res.end(content)\n return\n } catch {\n // No index.html available\n }\n }\n\n res.writeHead(404, { 'Content-Type': 'text/plain' })\n res.end('Not Found')\n })\n\n const wss = new WebSocketServer({ noServer: true })\n\n server.on('upgrade', (request, socket, head) => {\n const url = new URL(request.url ?? '/', 'http://localhost')\n if (url.pathname === '/api/live-editor/ws') {\n const sessionId = url.searchParams.get('sessionId')\n if (!sessionId) {\n socket.destroy()\n return\n }\n const session = sessionManager.getSession(sessionId)\n if (!session) {\n socket.destroy()\n return\n }\n\n wss.handleUpgrade(request, socket, head, (ws) => {\n session.clearIdleTimer()\n const handler = createSessionHandler(session, () => {\n sessionManager.terminateSession(sessionId)\n }, (event) => {\n db.insertTokenEvent(event)\n }, testFileManager)\n handler(ws)\n })\n } else {\n socket.destroy()\n }\n })\n\n const gracefulShutdown = () => {\n sessionManager.cleanupAll()\n }\n process.on('SIGTERM', gracefulShutdown)\n process.on('SIGINT', gracefulShutdown)\n\n const configuredMcp = (mcp ?? (config as any).services?.mcp ?? {}) as LocalMcpEndpointConfig\n const effectiveMcpConfig = configuredMcp.port === undefined && port === 0\n ? { ...configuredMcp, port: 0 }\n : configuredMcp\n const resolvedMcp = resolveLocalMcpEndpoint(effectiveMcpConfig)\n let mcpHttpServer: Server | undefined\n let mcpInfo: McpStartupInfo\n const captureMcpLifecycle = async (\n properties: {\n mcp_server_state: 'started' | 'disabled'\n mcp_transport: LocalMcpTransport\n mcp_host_kind?: 'loopback' | 'other'\n mcp_port_kind?: 'default' | 'custom'\n mcp_path_kind?: 'default' | 'custom'\n },\n ): Promise<void> => {\n if (isAnalyticsPrivacyEnabled(config)) return\n\n try {\n const standardProperties = await resolveAnalyticsStandardProperties({ surface: 'dashboard-server' })\n await captureAnalytics(buildAnalyticsEvent({\n name: 'agent-qa.mcp.server.lifecycle',\n properties: {\n ...standardProperties,\n surface: 'dashboard-server',\n ...properties,\n },\n }), { config }).catch(() => {})\n } catch {\n // Dashboard MCP lifecycle analytics must not alter startup behavior.\n }\n }\n const cleanupRuntimeResources = () => {\n jobQueue.stop()\n if (testRunner) {\n testRunner.killAll()\n }\n releaseAllMobileAppiumLeases('server-startup-error')\n appiumManager.shutdown()\n sessionManager.cleanupAll()\n db.close()\n }\n\n if (!resolvedMcp.enabled) {\n mcpInfo = {\n enabled: false,\n transport: resolvedMcp.transport,\n }\n await captureMcpLifecycle({\n mcp_server_state: 'disabled',\n mcp_transport: resolvedMcp.transport,\n })\n console.log('MCP disabled by services.mcp.enabled: false')\n } else if (resolvedMcp.transport === 'stdio') {\n mcpInfo = {\n enabled: false,\n transport: 'stdio',\n }\n console.log('MCP stdio transport selected; start editor MCP with `agent-qa mcp`')\n } else {\n let mcpHttpHandler = createLocalMcpHttpHandler({\n endpoint: resolvedMcp,\n dashboardUrl: `http://localhost:${port}`,\n configPath: resolvedConfigPath,\n analyticsConfig: config,\n })\n mcpHttpServer = createServer((req, res) => {\n void mcpHttpHandler(req, res)\n })\n\n try {\n await new Promise<void>((resolveMcp, rejectMcp) => {\n const onError = (err: Error) => {\n rejectMcp(err)\n }\n mcpHttpServer!.once('error', onError)\n mcpHttpServer!.listen(resolvedMcp.port, resolvedMcp.host, () => {\n mcpHttpServer!.off('error', onError)\n resolveMcp()\n })\n })\n } catch (err) {\n mcpHttpServer.close()\n cleanupRuntimeResources()\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`Failed to start MCP endpoint at ${resolvedMcp.url}: ${message}`)\n }\n\n const mcpAddress = mcpHttpServer.address()\n const actualMcpPort = typeof mcpAddress === 'object' && mcpAddress\n ? mcpAddress.port\n : resolvedMcp.port\n const actualMcp = resolveLocalMcpEndpoint({\n ...resolvedMcp,\n port: actualMcpPort,\n })\n if (actualMcpPort !== resolvedMcp.port) {\n mcpHttpHandler = createLocalMcpHttpHandler({\n endpoint: actualMcp,\n dashboardUrl: `http://localhost:${port}`,\n configPath: resolvedConfigPath,\n analyticsConfig: config,\n })\n }\n\n mcpInfo = {\n enabled: true,\n transport: 'http',\n host: actualMcp.host,\n port: actualMcp.port,\n path: actualMcp.path,\n url: actualMcp.url,\n }\n await captureMcpLifecycle({\n mcp_server_state: 'started',\n mcp_transport: 'http',\n ...resolveMcpEndpointShape(actualMcp),\n })\n console.log(`MCP running locally at ${actualMcp.url} (Streamable HTTP, loopback only)`)\n }\n\n return new Promise((resolve, reject) => {\n const onError = (err: Error) => {\n mcpHttpServer?.close()\n cleanupRuntimeResources()\n reject(err)\n }\n server.once('error', onError)\n server.listen(port, () => {\n server.off('error', onError)\n console.log(`Dashboard running at http://localhost:${port}`)\n resolve({\n server,\n port,\n mcp: mcpInfo,\n close: () => {\n jobQueue.stop()\n if (testRunner) {\n testRunner.killAll()\n }\n releaseAllMobileAppiumLeases('server-close')\n appiumManager.shutdown()\n sessionManager.cleanupAll()\n mcpHttpServer?.close()\n server.close()\n db.close()\n },\n })\n })\n })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { randomUUID } from 'node:crypto'\nimport { readFile, writeFile, stat, readdir, rm } from 'node:fs/promises'\nimport { createReadStream } from 'node:fs'\nimport { join, isAbsolute, basename, resolve, dirname, relative } from 'node:path'\n\nimport type { AttributePredicate, DashboardDatabase, InsightsBreakdownDimension, RunArtifactRow, RunRow, StepRow } from '../db/database.js'\nimport type { TestRunner } from '../execution/test-runner.js'\nimport type { JobQueue } from '../queue/job-queue.js'\nimport { MemoryCatalogManager, isValidMemoryScopeId, type MemoryScope } from '../memory/memory-catalog-manager.js'\nimport { extractTestFileMetadata, type SupportedPlatform, type TestFileManager } from '../tests/test-file-manager.js'\nimport type { SuiteFileManager } from '../tests/suite-file-manager.js'\nimport type { ConfigManager } from '../config/index.js'\nimport { HookRegistryManager, isHookRegistryMutationError } from '../hooks/hook-registry-manager.js'\nimport { readJsonBody } from './body-parser.js'\nimport type { AnalyticsServiceConfig, LLMAuthProviderPlugin, ModelConfig, OAuthTokens } from '@vostride/agent-qa-core'\nimport { AuthStateNameSchema, buildAnalyticsEvent, buildInternalRunAttributes, captureAnalytics, mergeRunAttributes, readAuth, writeAuth, removeAuth, getAgentQaVersion, getProviderOptions, getLLMAuthProviderPlugin, listAuthStateMetadata, listLLMAuthProviderPlugins, ModelConfigSchema, NamedLLMConfigSchema, WorkspaceSchema, ServicesSchema, RegistrySchema, UseSchema, MobileAppStateSchema, hashStepInstruction, TimeoutConfigSchema, CacheConfigSchema, HealingConfigSchema, PlannerConfigSchema, LoggingConfigSchema, LogCaptureConfigSchema, AccessibilityConfigSchema, DashboardConfigSchema, McpConfigSchema, RecordingConfigSchema, BrowserConfigSchema, AnalyticsSchema, AgentQaConfigSchema, TestDefinitionSchema, SuiteDefinitionSchema, parseEnvFile, serializeEnvFile, parseHooksFile, runHookInSandbox, RUNTIME_IMAGE_MAP, SecretStore, SecretRedactor, redactAuthStateValue, validateUserRunAttributes, discoverWorkspaceFiles, isWorkspacePathMatch, resolveAnalyticsStandardProperties, resolveMemoryRoot, resolveWorkspaceFileTarget } from '@vostride/agent-qa-core'\nimport type { ResolvedWorkspacePaths, RunAttributes, WorkspaceFileKind, WorkspaceFileRecord } from '@vostride/agent-qa-core'\nimport { parse as parseYaml } from 'yaml'\n\nconst LLM_PROVIDER_MODES = new Set([\n 'openai-compatible',\n 'anthropic-compatible',\n 'gemini',\n])\nconst API_KEY_CREDENTIAL_PROVIDERS = new Set([\n 'openai-compatible',\n 'anthropic-compatible',\n 'gemini',\n])\nconst LLM_TEST_UNAUTHENTICATED_MESSAGE = 'Testing without a saved credential.'\nconst LLM_TEST_AUTH_ERROR_MESSAGE = 'Authentication failed. Check the saved credential for this config.'\nconst LLM_TEST_MODEL_NOT_FOUND_MESSAGE = 'Model not found. Check the model name.'\nconst LLM_TEST_NETWORK_ERROR_MESSAGE = 'Network error. Check the exact base URL and try again.'\nconst DASHBOARD_EXECUTION_TIMEOUT_BUFFER_MS = 60_000\nconst REMOTE_LLM_CONNECTION_TEST_TIMEOUT_MS = 10_000\nconst LOCAL_COMPATIBLE_LLM_CONNECTION_TEST_TIMEOUT_MS = 120_000\nconst LOCAL_COMPATIBLE_LLM_PROVIDERS = new Set(['openai-compatible', 'anthropic-compatible'])\nconst PLUGIN_OAUTH_SESSION_TTL_MS = 10 * 60 * 1000\nconst DASHBOARD_PRODUCT_EVENT_NAMES = [\n 'agent-qa.dashboard.opened',\n 'agent-qa.dashboard.live_mode.started',\n 'agent-qa.dashboard.entity.created',\n] as const\ntype DashboardProductEventName = typeof DASHBOARD_PRODUCT_EVENT_NAMES[number]\nconst DASHBOARD_PRODUCT_EVENT_NAME_SET = new Set<DashboardProductEventName>(DASHBOARD_PRODUCT_EVENT_NAMES)\nconst DASHBOARD_PRODUCT_EVENT_PROPERTY_KEYS = {\n 'agent-qa.dashboard.opened': [],\n 'agent-qa.dashboard.live_mode.started': ['platform', 'entity_type'],\n 'agent-qa.dashboard.entity.created': ['entity_type', 'outcome'],\n} as const satisfies Record<DashboardProductEventName, readonly string[]>\n\ntype DashboardExecutionTimeoutSource =\n | 'test.use.timeout.test'\n | 'suite.use.timeout.test'\n | 'config.use.timeout.test'\n | 'none'\n\ntype ConfigSectionValidationResult =\n | { success: true }\n | { success: false; error: { issues: { message: string; path: PropertyKey[] }[] } }\n\ninterface DashboardExecutionTimeout {\n timeoutMs?: number\n source: DashboardExecutionTimeoutSource\n baseTimeoutMs?: number\n bufferMs?: number\n}\n\nfunction toProductProviderLabel(provider: string): string {\n const plugin = listLLMAuthProviderPlugins()\n .find((candidate) => candidate.credentialProviderId === provider)\n return plugin?.providerId ?? provider\n}\n\nfunction isKnownLLMProvider(provider: string): boolean {\n return LLM_PROVIDER_MODES.has(provider) || Boolean(getLLMAuthProviderPlugin(provider))\n}\n\nasync function requirePluginAuthConfig(\n configManager: ConfigManager | undefined,\n configName: unknown,\n plugin: LLMAuthProviderPlugin,\n): Promise<{ ok: true; configName: string } | { ok: false; error: string }> {\n const targetConfigName = typeof configName === 'string' ? configName.trim() : ''\n if (!targetConfigName) {\n return { ok: false, error: 'configName is required' }\n }\n if (!configManager) {\n return { ok: false, error: 'Config manager is required to save OAuth credentials' }\n }\n\n const config = await configManager.read() as { registry?: { llms?: unknown[] } }\n const llms = Array.isArray(config.registry?.llms) ? config.registry.llms : []\n const match = llms.find((item) => {\n return Boolean(item)\n && typeof item === 'object'\n && !Array.isArray(item)\n && (item as { name?: unknown }).name === targetConfigName\n }) as { provider?: unknown } | undefined\n\n if (!match) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" not found` }\n }\n if (match.provider !== plugin.providerId) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" uses ${String(match.provider)}, not ${plugin.providerId}` }\n }\n\n return { ok: true, configName: targetConfigName }\n}\n\nasync function requireCredentialConfig(\n configManager: ConfigManager | undefined,\n configName: unknown,\n provider: string,\n): Promise<{ ok: true; configName: string } | { ok: false; error: string }> {\n const targetConfigName = typeof configName === 'string' ? configName.trim() : ''\n if (!targetConfigName) {\n return { ok: false, error: 'configName is required' }\n }\n if (!API_KEY_CREDENTIAL_PROVIDERS.has(provider)) {\n return { ok: false, error: 'provider must support typed credentials' }\n }\n if (!configManager) {\n return { ok: false, error: 'Config manager is required to save credentials' }\n }\n\n const config = await configManager.read() as { registry?: { llms?: unknown[] } }\n const llms = Array.isArray(config.registry?.llms) ? config.registry.llms : []\n const match = llms.find((item) => {\n return Boolean(item)\n && typeof item === 'object'\n && !Array.isArray(item)\n && (item as { name?: unknown }).name === targetConfigName\n }) as { provider?: unknown } | undefined\n\n if (!match) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" not found` }\n }\n if (match.provider !== provider) {\n return { ok: false, error: `LLM config \"${targetConfigName}\" uses ${String(match.provider)}, not ${provider}` }\n }\n\n return { ok: true, configName: targetConfigName }\n}\n\ntype DashboardAuthCredential =\n | { type: 'oauth'; provider?: string; tokens: { expires: number } }\n | { type: 'api'; provider?: string; key?: string }\n | { type: 'bearer'; provider: string; token?: string }\n\ninterface DashboardLLMProviderMetadata {\n id: string\n label: string\n auth:\n | { kind: 'api-key'; credentialTypes: Array<'api-key' | 'bearer-token'>; optional?: boolean }\n | { kind: 'oauth-plugin'; mode: 'browser-poll' | 'manual-code'; buttonLabel?: string }\n modelAdapter?: 'openai-responses' | 'anthropic-messages'\n}\n\ninterface PluginOAuthSession {\n providerId: string\n credentialProviderId: string\n configName: string\n sessionState?: unknown\n cleanup?: () => void\n status: 'pending' | 'completed' | 'error'\n expiresAt: number\n error?: string\n}\n\nfunction builtinLLMProviderMetadata(): DashboardLLMProviderMetadata[] {\n return [\n {\n id: 'openai-compatible',\n label: 'OpenAI-compatible',\n auth: { kind: 'api-key', credentialTypes: ['api-key'], optional: true },\n modelAdapter: 'openai-responses',\n },\n {\n id: 'anthropic-compatible',\n label: 'Anthropic-compatible',\n auth: { kind: 'api-key', credentialTypes: ['api-key', 'bearer-token'], optional: true },\n modelAdapter: 'anthropic-messages',\n },\n {\n id: 'gemini',\n label: 'Gemini',\n auth: { kind: 'api-key', credentialTypes: ['api-key'] },\n },\n ]\n}\n\nfunction serializeAuthProviderPlugin(plugin: LLMAuthProviderPlugin): DashboardLLMProviderMetadata {\n return {\n id: plugin.providerId,\n label: plugin.label,\n modelAdapter: plugin.modelAdapter,\n auth: {\n kind: 'oauth-plugin',\n mode: plugin.dashboardAuth.mode,\n ...(plugin.dashboardAuth.buttonLabel ? { buttonLabel: plugin.dashboardAuth.buttonLabel } : {}),\n },\n }\n}\n\ntype DashboardRuntimeLLMConfig = Pick<\n ModelConfig,\n 'provider' | 'model' | 'apiKey' | 'authToken' | 'baseURL' | 'providerHeaders'\n> & {\n screenshotSize?: number\n effectiveResolution?: number\n modelAdapter?: 'openai-responses' | 'anthropic-messages'\n}\n\nconst writeDashboardAuth = writeAuth as unknown as (\n provider: string,\n credential: DashboardAuthCredential,\n) => Promise<void>\n\ntype DashboardResolvedRuntimeLLM =\n | { ok: true; llmConfig: DashboardRuntimeLLMConfig; authFetch?: typeof globalThis.fetch }\n | { ok: false; error: string }\n\nfunction normalizeRuntimeLLMConfig(raw: unknown): { configName: string; config: DashboardRuntimeLLMConfig } | undefined {\n if (!isPlainRecord(raw)) return undefined\n if (typeof raw.name !== 'string' || !raw.name.trim()) return undefined\n if (typeof raw.provider !== 'string' || !raw.provider.trim()) return undefined\n if (typeof raw.model !== 'string' || !raw.model.trim()) return undefined\n\n const config: DashboardRuntimeLLMConfig = {\n provider: raw.provider,\n model: raw.model,\n }\n if (typeof raw.baseURL === 'string') config.baseURL = raw.baseURL\n if (isPlainRecord(raw.providerHeaders)) {\n const headers: Record<string, string> = {}\n for (const [key, value] of Object.entries(raw.providerHeaders)) {\n if (typeof value === 'string') headers[key] = value\n }\n config.providerHeaders = headers\n }\n if (typeof raw.screenshotSize === 'number') config.screenshotSize = raw.screenshotSize\n if (typeof raw.effectiveResolution === 'number') config.effectiveResolution = raw.effectiveResolution\n\n return { configName: raw.name, config }\n}\n\nasync function resolveDashboardRuntimeLLM(\n configManager: ConfigManager | undefined,\n fallbackLLMConfig: DashboardRuntimeLLMConfig | undefined,\n fallbackAuthFetch: typeof globalThis.fetch | undefined,\n): Promise<DashboardResolvedRuntimeLLM> {\n if (!configManager) {\n if (!fallbackLLMConfig) {\n return { ok: false, error: 'LLM not configured. Set up LLM provider in settings.' }\n }\n return { ok: true, llmConfig: fallbackLLMConfig, authFetch: fallbackAuthFetch }\n }\n\n const rawConfig = await configManager.read()\n const registry = isPlainRecord(rawConfig.registry) ? rawConfig.registry : {}\n const use = isPlainRecord(rawConfig.use) ? rawConfig.use : {}\n const llms = Array.isArray(registry.llms) ? registry.llms : []\n const selectedName = typeof use.llm === 'string' ? use.llm : undefined\n const selected = selectedName\n ? llms.find((candidate) => isPlainRecord(candidate) && candidate.name === selectedName)\n : llms[0]\n\n const normalized = normalizeRuntimeLLMConfig(selected)\n if (!normalized) {\n if (!fallbackLLMConfig) {\n return { ok: false, error: 'LLM not configured. Set up LLM provider in settings.' }\n }\n return { ok: true, llmConfig: fallbackLLMConfig, authFetch: fallbackAuthFetch }\n }\n\n const coreAuth = await import('@vostride/agent-qa-core') as typeof import('@vostride/agent-qa-core') & {\n resolveLLMAuth: (\n configName: string,\n config: DashboardRuntimeLLMConfig,\n ) => Promise<\n | { kind: 'api-key'; apiKey: string }\n | { kind: 'bearer-token'; token: string }\n | { kind: 'auth-fetch'; fetch: typeof globalThis.fetch; modelAdapter: 'openai-responses' | 'anthropic-messages' }\n | { kind: 'unauthenticated'; message: string }\n | { kind: 'missing'; message: string }\n >\n }\n const auth = await coreAuth.resolveLLMAuth(normalized.configName, normalized.config)\n if (auth.kind === 'missing') {\n return { ok: false, error: auth.message }\n }\n\n const runtimeConfig: DashboardRuntimeLLMConfig = { ...normalized.config }\n let resolvedAuthFetch: typeof globalThis.fetch | undefined\n if (auth.kind === 'api-key') {\n runtimeConfig.apiKey = auth.apiKey\n } else if (auth.kind === 'bearer-token') {\n runtimeConfig.authToken = auth.token\n } else if (auth.kind === 'auth-fetch') {\n runtimeConfig.modelAdapter = auth.modelAdapter\n resolvedAuthFetch = auth.fetch\n }\n\n return { ok: true, llmConfig: runtimeConfig, authFetch: resolvedAuthFetch }\n}\n\nfunction cleanupPluginOAuthSession(session: PluginOAuthSession): void {\n const cleanup = session.cleanup\n session.cleanup = undefined\n if (!cleanup) return\n try {\n cleanup()\n } catch {\n // Best-effort cleanup for plugin-owned local callback servers.\n }\n}\n\nfunction pruneExpiredPluginOAuthSessions(sessions: Map<string, PluginOAuthSession>, now = Date.now()): void {\n for (const [sessionId, session] of sessions) {\n if (session.expiresAt <= now) {\n cleanupPluginOAuthSession(session)\n sessions.delete(sessionId)\n }\n }\n}\n\nfunction extractProviderErrorMessage(err: unknown): { message: string; statusCode?: number } {\n const errObj = err as Record<string, unknown>\n const statusCode = errObj?.statusCode as number | undefined\n const responseBody = errObj?.responseBody as string | undefined\n const data = errObj?.data as Record<string, unknown> | undefined\n const apiError = data?.error as Record<string, string> | undefined\n\n let message = err instanceof Error ? err.message : String(err)\n\n if (apiError?.message && apiError.message !== 'Error') {\n message = apiError.message\n } else if (data?.detail && typeof data.detail === 'string') {\n message = data.detail\n } else if (responseBody) {\n try {\n const body = JSON.parse(responseBody)\n if (body?.detail) message = body.detail\n else if (body?.error?.message && body.error.message !== 'Error') message = body.error.message\n } catch {\n // response body was not JSON\n }\n }\n\n return { message, statusCode }\n}\n\nfunction classifyProviderError(message: string, statusCode?: number): string {\n const fullContext = `${message} ${statusCode ?? ''}`\n if (/auth|unauthorized|401|invalid.*key|permission/i.test(fullContext)) {\n return 'auth_error'\n }\n if (/model.*not.*support|model.*not.*found|not found|404|does not exist/i.test(fullContext)) {\n return 'model_not_found'\n }\n if (/ECONNREFUSED|ENOTFOUND|timeout|abort|fetch failed|network/i.test(fullContext)) {\n return 'network_error'\n }\n if (/rate|429|quota|limit/i.test(fullContext)) {\n return 'rate_limit'\n }\n if (/invalid_request|400|bad request/i.test(fullContext)) {\n return 'invalid_request'\n }\n return 'provider_error'\n}\n\nfunction publicLLMTestMessage(category: string, providerMessage: string): string {\n switch (category) {\n case 'auth_error':\n return LLM_TEST_AUTH_ERROR_MESSAGE\n case 'model_not_found':\n return LLM_TEST_MODEL_NOT_FOUND_MESSAGE\n case 'network_error':\n return LLM_TEST_NETWORK_ERROR_MESSAGE\n case 'provider_error':\n return `Connection failed. ${providerMessage}`\n default:\n return providerMessage\n }\n}\n\nfunction isLocalLLMBaseURL(baseURL: unknown): boolean {\n if (typeof baseURL !== 'string' || !baseURL.trim()) return false\n try {\n const url = new URL(baseURL)\n const hostname = url.hostname.toLowerCase()\n return hostname === 'localhost'\n || hostname === '0.0.0.0'\n || hostname === '::1'\n || hostname === '[::1]'\n || hostname.startsWith('127.')\n || hostname.endsWith('.local')\n } catch {\n return false\n }\n}\n\nfunction llmConnectionTestTimeoutMs(config: { provider?: unknown; baseURL?: unknown }): number {\n // Connectivity probes are config-screen smoke checks only; real run execution\n // uses configured test timeout metadata and does not read this value.\n if (LOCAL_COMPATIBLE_LLM_PROVIDERS.has(String(config.provider)) && isLocalLLMBaseURL(config.baseURL)) {\n return LOCAL_COMPATIBLE_LLM_CONNECTION_TEST_TIMEOUT_MS\n }\n return REMOTE_LLM_CONNECTION_TEST_TIMEOUT_MS\n}\n\nfunction parseUrl(req: IncomingMessage): URL {\n return new URL(req.url ?? '/', 'http://localhost')\n}\n\nfunction json(res: ServerResponse, data: unknown, status = 200): void {\n const body = JSON.stringify(data)\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n })\n res.end(body)\n}\n\nfunction notFound(res: ServerResponse, message = 'Not found'): void {\n json(res, { error: message }, 404)\n}\n\nfunction cors(res: ServerResponse): void {\n res.writeHead(204, {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n })\n res.end()\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction getConfiguredAuthStateDir(config: Record<string, unknown>): string | undefined {\n const services = isPlainRecord(config.services) ? config.services : undefined\n const authState = services && isPlainRecord(services.authState) ? services.authState : undefined\n return typeof authState?.dir === 'string' ? authState.dir : undefined\n}\n\nfunction getSessionTargetNameForAuthState(session: { getState?: () => unknown } | undefined): string {\n if (!session || typeof session.getState !== 'function') return 'selected target'\n try {\n const state = session.getState()\n if (isPlainRecord(state) && typeof state.targetName === 'string' && state.targetName.trim().length > 0) {\n return state.targetName.trim()\n }\n } catch {\n // Do not let state serialization failures leak into auth-state responses.\n }\n return 'selected target'\n}\n\nfunction buildAuthStateSaveErrorMessage(\n stateName: string,\n targetName: string,\n error: unknown,\n): { status: number; message: string } {\n const raw = error instanceof Error ? error.message : String(error)\n if (/already exists/i.test(raw)) {\n return {\n status: 409,\n message: `Auth state \"${stateName}\" for target \"${targetName}\" already exists. Use replace=true to replace it.`,\n }\n }\n\n if (/web Live Mode|not ready|executing|busy/i.test(raw)) {\n return {\n status: 409,\n message: `Could not save auth state \"${stateName}\" for target \"${targetName}\".`,\n }\n }\n\n return {\n status: 500,\n message: `Could not save auth state \"${stateName}\" for target \"${targetName}\".`,\n }\n}\n\nfunction isDashboardProductEventName(value: unknown): value is DashboardProductEventName {\n return typeof value === 'string' && DASHBOARD_PRODUCT_EVENT_NAME_SET.has(value as DashboardProductEventName)\n}\n\nfunction filterDashboardProductEventProperties(\n name: DashboardProductEventName,\n properties: Record<string, unknown>,\n): Record<string, unknown> {\n const allowedKeys = DASHBOARD_PRODUCT_EVENT_PROPERTY_KEYS[name]\n const filtered: Record<string, unknown> = {}\n for (const key of allowedKeys) {\n if (Object.prototype.hasOwnProperty.call(properties, key)) {\n filtered[key] = properties[key]\n }\n }\n return filtered\n}\n\nasync function readAnalyticsServiceConfig(configManager: ConfigManager | undefined): Promise<AnalyticsServiceConfig> {\n if (!configManager) return {}\n\n try {\n const config = await configManager.read() as { analytics?: { privacy?: unknown } } | undefined\n if (config?.analytics?.privacy === true) {\n return { analytics: { privacy: true } }\n }\n } catch {\n // Fail closed for telemetry while keeping the HTTP route non-blocking.\n return { analytics: { privacy: true } }\n }\n return {}\n}\n\nfunction getPathInsideDir(candidatePath: string, rootDir: string): string | null {\n const relativePath = relative(rootDir, candidatePath)\n if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) {\n return null\n }\n return relativePath\n}\n\nfunction isPlainFileName(value: string): boolean {\n const fileName = value.trim()\n return fileName.length > 0\n && fileName !== '.'\n && fileName !== '..'\n && !isAbsolute(fileName)\n && fileName === basename(fileName)\n && !/[\\\\/\\0]/.test(fileName)\n}\n\nfunction createHookRegistryManager(configManager?: ConfigManager, configPath?: string): HookRegistryManager | null {\n if (!configManager || !configPath) {\n return null\n }\n return new HookRegistryManager(configManager, configPath)\n}\n\nfunction normalizeRunFilterValue(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim().toLowerCase()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction buildRunRequestAttributes(input: {\n trigger: 'dashboard' | 'api' | 'mcp'\n runner?: 'local' | 'browserstack'\n userAttributes?: unknown\n}): RunAttributes {\n const internal = buildInternalRunAttributes({\n trigger: input.trigger,\n runner: input.runner ?? 'local',\n })\n const user = validateUserRunAttributes(input.userAttributes, 'run attributes')\n return mergeRunAttributes(internal, user)\n}\n\nfunction parseDashboardRunTriggerSource(value: unknown): { ok: true; trigger: 'dashboard' | 'mcp' } | { ok: false; error: string } {\n if (value === undefined || value === null) return { ok: true, trigger: 'dashboard' }\n if (value === 'dashboard' || value === 'mcp') return { ok: true, trigger: value }\n return { ok: false, error: 'triggerSource must be one of: dashboard, mcp' }\n}\n\nfunction parseAttributePredicates(searchParams: URLSearchParams): { ok: true; predicates: AttributePredicate[] } | { ok: false; error: string } {\n const predicates = new Map<string, AttributePredicate>()\n for (const [paramKey, value] of searchParams.entries()) {\n const match = /^attributes\\[([^\\]]*)\\](?:\\[(regex)\\])?$/.exec(paramKey)\n if (!match) continue\n const key = match[1]\n const mode = match[2] === 'regex' ? 'regex' : 'exact'\n if (!key.trim()) return { ok: false, error: 'Attribute key must be non-empty' }\n if (!value.trim()) return { ok: false, error: 'Attribute value must be non-empty' }\n const existing = predicates.get(key)\n if (existing && existing.mode !== mode) {\n return { ok: false, error: `Cannot combine exact and regex attribute filters for \"${key}\"` }\n }\n if (mode === 'regex') {\n try {\n new RegExp(value)\n } catch {\n return { ok: false, error: `Invalid attribute regex for \"${key}\"` }\n }\n }\n predicates.set(key, { key, value, mode })\n }\n return { ok: true, predicates: [...predicates.values()] }\n}\n\nfunction parseAnalyticsScopePredicates(config: Record<string, unknown> | undefined): { ok: true; predicates: AttributePredicate[] } | { ok: false; error: string } {\n const analytics = config?.analytics\n if (!analytics || typeof analytics !== 'object' || Array.isArray(analytics)) return { ok: true, predicates: [] }\n const passRateScope = (analytics as Record<string, unknown>).passRateScope\n if (!passRateScope || typeof passRateScope !== 'object' || Array.isArray(passRateScope)) return { ok: true, predicates: [] }\n const attributes = (passRateScope as Record<string, unknown>).attributes\n if (!attributes || typeof attributes !== 'object' || Array.isArray(attributes)) return { ok: true, predicates: [] }\n\n const predicates: AttributePredicate[] = []\n for (const [key, rawValue] of Object.entries(attributes)) {\n if (!key.trim()) return { ok: false, error: 'analytics.passRateScope attribute key must be non-empty' }\n if (typeof rawValue === 'string') {\n if (!rawValue.trim()) return { ok: false, error: `analytics.passRateScope attribute \"${key}\" must be non-empty` }\n predicates.push({ key, value: rawValue, mode: 'exact' })\n continue\n }\n if (rawValue && typeof rawValue === 'object' && !Array.isArray(rawValue) && typeof (rawValue as { regex?: unknown }).regex === 'string') {\n const regex = (rawValue as { regex: string }).regex\n if (!regex.trim()) return { ok: false, error: `analytics.passRateScope attribute \"${key}\" regex must be non-empty` }\n try {\n new RegExp(regex)\n } catch {\n return { ok: false, error: `Invalid analytics.passRateScope regex for \"${key}\"` }\n }\n predicates.push({ key, value: regex, mode: 'regex' })\n }\n }\n return { ok: true, predicates }\n}\n\nfunction validateAnalyticsPassRateScope(value: unknown): ConfigSectionValidationResult {\n const result = AnalyticsSchema.shape.passRateScope.safeParse(value)\n if (result.success) return { success: true }\n return {\n success: false,\n error: {\n issues: result.error.issues.map((issue) => ({\n message: issue.message,\n path: issue.path,\n })),\n },\n }\n}\n\nasync function readAnalyticsScopePredicates(configManager: ConfigManager | undefined): Promise<{ ok: true; predicates: AttributePredicate[] } | { ok: false; error: string }> {\n if (!configManager) return { ok: true, predicates: [] }\n const config = await configManager.read()\n const parsedConfig = AgentQaConfigSchema.safeParse(config)\n if (!parsedConfig.success) {\n return { ok: true, predicates: [] }\n }\n return parseAnalyticsScopePredicates(parsedConfig.data as Record<string, unknown>)\n}\n\nfunction calculateFlakyMetrics(runs: RunRow[]): { score: number; statusCount: number } {\n const statuses = runs\n .filter(r => r.status === 'passed' || r.status === 'failed')\n .map(r => r.status)\n let alternations = 0\n for (let i = 1; i < statuses.length; i++) {\n if (statuses[i] !== statuses[i - 1]) alternations++\n }\n return {\n score: statuses.length > 1 ? alternations / (statuses.length - 1) : 0,\n statusCount: statuses.length,\n }\n}\n\nfunction normalizeSupportedPlatform(value: unknown): SupportedPlatform | null {\n if (value !== 'web' && value !== 'android' && value !== 'ios') return null\n return value\n}\n\nfunction parseIsoDateQueryParam(\n value: string | null,\n field: 'from' | 'to',\n): { ok: true; value?: string } | { ok: false; error: string } {\n if (!value) return { ok: true, value: undefined }\n return Number.isNaN(Date.parse(value))\n ? { ok: false, error: `${field} must be a valid ISO date` }\n : { ok: true, value }\n}\n\nfunction parseBoundedIntegerQueryParam(\n value: string | null,\n field: string,\n min: number,\n max: number,\n fallback: number,\n): { ok: true; value: number } | { ok: false; error: string } {\n if (!value) return { ok: true, value: fallback }\n const parsed = Number.parseInt(value, 10)\n if (!Number.isFinite(parsed)) {\n return { ok: false, error: `${field} must be an integer` }\n }\n return { ok: true, value: Math.min(max, Math.max(min, parsed)) }\n}\n\nfunction getTargetPlatformMap(config: unknown): Map<string, SupportedPlatform> {\n const targetsValue = (config as {\n registry?: { targets?: Record<string, { platform?: unknown }> }\n }).registry?.targets\n\n const targetPlatforms = new Map<string, SupportedPlatform>()\n if (!targetsValue || typeof targetsValue !== 'object') return targetPlatforms\n\n for (const [targetName, targetConfig] of Object.entries(targetsValue)) {\n const platform = normalizeSupportedPlatform(targetConfig?.platform)\n if (platform) targetPlatforms.set(targetName, platform)\n }\n\n return targetPlatforms\n}\n\nasync function readTargetPlatformMap(configManager?: ConfigManager): Promise<Map<string, SupportedPlatform>> {\n if (!configManager) return new Map()\n try {\n const config = await configManager.read()\n return getTargetPlatformMap(config)\n } catch {\n return new Map()\n }\n}\n\nfunction parseTimeoutConfigTestTimeoutMs(timeoutConfig: unknown): number | undefined {\n if (timeoutConfig && typeof timeoutConfig === 'object' && !Array.isArray(timeoutConfig)) {\n const transformedTimeout = (timeoutConfig as { test?: unknown }).test\n if (typeof transformedTimeout === 'number' && Number.isFinite(transformedTimeout) && transformedTimeout > 0) {\n return transformedTimeout\n }\n }\n const parsed = TimeoutConfigSchema.partial().safeParse(timeoutConfig)\n if (!parsed.success) return undefined\n const testTimeout = parsed.data.test\n return typeof testTimeout === 'number' && Number.isFinite(testTimeout) && testTimeout > 0\n ? testTimeout\n : undefined\n}\n\nfunction parseUseTestTimeoutMs(useConfig: unknown): number | undefined {\n if (!useConfig || typeof useConfig !== 'object' || Array.isArray(useConfig)) return undefined\n return parseTimeoutConfigTestTimeoutMs((useConfig as { timeout?: unknown }).timeout)\n}\n\nasync function readConfigTestTimeoutMs(configManager?: ConfigManager): Promise<number | undefined> {\n if (!configManager) return undefined\n try {\n const config = await configManager.read()\n const parsed = AgentQaConfigSchema.safeParse(config)\n if (parsed.success) {\n return parseUseTestTimeoutMs(parsed.data.use)\n }\n return parseUseTestTimeoutMs((config as { use?: unknown }).use)\n } catch {\n return undefined\n }\n}\n\nfunction readTestYamlTimeoutMs(content: string): number | undefined {\n try {\n const parsedYaml = parseYaml(content)\n const parsedTest = TestDefinitionSchema.safeParse(parsedYaml)\n if (parsedTest.success) {\n return parseUseTestTimeoutMs(parsedTest.data.use)\n }\n return parseUseTestTimeoutMs((parsedYaml as { use?: unknown } | null | undefined)?.use)\n } catch {\n return undefined\n }\n}\n\nfunction readSuiteYamlTimeoutMs(content: string): number | undefined {\n try {\n const parsedYaml = parseYaml(content)\n const parsedSuite = SuiteDefinitionSchema.safeParse(parsedYaml)\n if (parsedSuite.success) {\n return parseUseTestTimeoutMs(parsedSuite.data.use)\n }\n return parseUseTestTimeoutMs((parsedYaml as { use?: unknown } | null | undefined)?.use)\n } catch {\n return undefined\n }\n}\n\nfunction parseUseParallel(useConfig: unknown): boolean | undefined {\n if (!isRecord(useConfig)) return undefined\n return typeof useConfig.parallel === 'boolean' ? useConfig.parallel : undefined\n}\n\nasync function readConfigUseParallel(configManager?: ConfigManager): Promise<boolean | undefined> {\n if (!configManager) return undefined\n try {\n const config = await configManager.read()\n const parsed = AgentQaConfigSchema.safeParse(config)\n if (parsed.success) {\n return parseUseParallel(parsed.data.use)\n }\n return parseUseParallel((config as { use?: unknown }).use)\n } catch {\n return undefined\n }\n}\n\nfunction readSuiteYamlParallel(content: string): boolean | undefined {\n try {\n const parsedYaml = parseYaml(content)\n const parsedSuite = SuiteDefinitionSchema.safeParse(parsedYaml)\n if (parsedSuite.success) {\n return parseUseParallel(parsedSuite.data.use)\n }\n return parseUseParallel((parsedYaml as { use?: unknown } | null | undefined)?.use)\n } catch {\n return undefined\n }\n}\n\nfunction withDashboardExecutionBuffer(\n baseTimeoutMs: number | undefined,\n source: DashboardExecutionTimeoutSource,\n): DashboardExecutionTimeout {\n if (!baseTimeoutMs) {\n return { source: 'none' }\n }\n return {\n timeoutMs: baseTimeoutMs + DASHBOARD_EXECUTION_TIMEOUT_BUFFER_MS,\n source,\n baseTimeoutMs,\n bufferMs: DASHBOARD_EXECUTION_TIMEOUT_BUFFER_MS,\n }\n}\n\nasync function resolveDashboardExecutionTimeout(opts: {\n isSuite: boolean\n file?: string\n normalizedTestPath?: string\n testFileManager?: TestFileManager\n suiteFileManager?: SuiteFileManager\n configManager?: ConfigManager\n}): Promise<DashboardExecutionTimeout> {\n if (opts.file) {\n if (opts.isSuite && opts.suiteFileManager) {\n try {\n const suiteContent = await opts.suiteFileManager.read(opts.file)\n const suiteTimeout = readSuiteYamlTimeoutMs(suiteContent)\n if (suiteTimeout) {\n return withDashboardExecutionBuffer(suiteTimeout, 'suite.use.timeout.test')\n }\n } catch {\n // Fall through to config timeout for draft or unreadable suite files.\n }\n } else if (!opts.isSuite && opts.testFileManager) {\n try {\n const testContent = await opts.testFileManager.read(opts.normalizedTestPath ?? opts.file)\n const testTimeout = readTestYamlTimeoutMs(testContent)\n if (testTimeout) {\n return withDashboardExecutionBuffer(testTimeout, 'test.use.timeout.test')\n }\n } catch {\n // Fall through to config timeout for draft or unreadable test files.\n }\n }\n }\n\n const configTimeout = await readConfigTestTimeoutMs(opts.configManager)\n return withDashboardExecutionBuffer(configTimeout, configTimeout ? 'config.use.timeout.test' : 'none')\n}\n\nfunction toExecutionTimeoutMetadata(timeout: DashboardExecutionTimeout): Record<string, unknown> {\n if (!timeout.timeoutMs) {\n return { timeoutSource: timeout.source }\n }\n return {\n timeout: timeout.timeoutMs,\n timeoutSource: timeout.source,\n timeoutBaseMs: timeout.baseTimeoutMs,\n timeoutBufferMs: timeout.bufferMs,\n }\n}\n\nfunction resolveEffectivePlatform(\n platform: string | null | undefined,\n targetName: string | null | undefined,\n targetPlatforms: Map<string, SupportedPlatform>,\n fallbackPlatform?: string | null,\n): SupportedPlatform | null {\n const explicitPlatform = normalizeSupportedPlatform(platform)\n if (explicitPlatform) return explicitPlatform\n\n if (targetName) {\n const targetPlatform = targetPlatforms.get(targetName)\n if (targetPlatform) return targetPlatform\n }\n\n return normalizeSupportedPlatform(fallbackPlatform)\n}\n\nfunction extractRunTargetName(testFileContent: string | null | undefined): string | null {\n if (!testFileContent) return null\n return extractTestFileMetadata(testFileContent).targetName\n}\n\ntype EnrichedRunRow = RunRow & {\n targetName: string | null\n tests?: EnrichedRunRow[]\n}\n\nfunction enrichRunRow(\n run: RunRow,\n targetPlatforms: Map<string, SupportedPlatform>,\n tests?: EnrichedRunRow[],\n): EnrichedRunRow {\n const metadata = run.testFileContent ? extractTestFileMetadata(run.testFileContent) : null\n let targetName = metadata?.targetName ?? extractRunTargetName(run.testFileContent)\n if (!targetName && tests && tests.length > 0) {\n const uniqueChildTargets = [...new Set(\n tests\n .map((test) => test.targetName)\n .filter((value): value is string => typeof value === 'string' && value.length > 0),\n )]\n if (uniqueChildTargets.length === 1) {\n targetName = uniqueChildTargets[0]\n }\n }\n\n const uniqueChildPlatforms = tests\n ? [...new Set(\n tests\n .map((test) => normalizeSupportedPlatform(test.platform))\n .filter((value): value is SupportedPlatform => value !== null),\n )]\n : []\n\n const platform = resolveEffectivePlatform(\n metadata?.platform,\n targetName,\n targetPlatforms,\n uniqueChildPlatforms.length === 1 ? uniqueChildPlatforms[0] : run.platform,\n )\n\n return {\n ...run,\n platform: platform ?? run.platform,\n targetName,\n ...(tests ? { tests } : {}),\n }\n}\n\nfunction matchesTargetFilter(run: EnrichedRunRow, filterValue: string | null): boolean {\n if (!filterValue) return true\n if (normalizeRunFilterValue(run.targetName) === filterValue) return true\n return run.tests?.some((test) => normalizeRunFilterValue(test.targetName) === filterValue) ?? false\n}\n\nfunction matchesPlatformFilter(run: EnrichedRunRow, filterValue: SupportedPlatform | null): boolean {\n if (!filterValue) return true\n if (normalizeSupportedPlatform(run.platform) === filterValue) return true\n return run.tests?.some((test) => normalizeSupportedPlatform(test.platform) === filterValue) ?? false\n}\n\nfunction getArtifactMissingSections(artifact: RunArtifactRow | null): string[] {\n if (!artifact) return ['artifact']\n const missing: string[] = []\n const payload = artifact.payload\n if (!('config' in payload)) missing.push('config')\n if (!('source' in payload)) missing.push('source')\n if (!('memory' in payload)) missing.push('memory')\n return missing\n}\n\nconst SECRET_TEMPLATE_RE = /\\{\\{secret:(\\w+)\\}\\}/g\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction sanitizeSecretTemplates(value: unknown): unknown {\n if (typeof value === 'string') {\n return value.replace(SECRET_TEMPLATE_RE, (_match, name: string) => `[secret:${name}]`)\n }\n if (Array.isArray(value)) {\n return value.map((item) => sanitizeSecretTemplates(item))\n }\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n return value\n }\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, sanitizeSecretTemplates(item)]),\n )\n }\n return value\n}\n\nfunction sanitizeSecretsFileMetadata(value: unknown): unknown {\n if (value === null || value === undefined) return value\n if (!isRecord(value)) return value\n return {\n path: typeof value.path === 'string' || value.path === null ? value.path : null,\n status: typeof value.status === 'string' ? value.status : 'loaded',\n ...(typeof value.count === 'number' ? { count: value.count } : {}),\n }\n}\n\nfunction sanitizeArtifactPayloadForResponse(payload: RunArtifactRow['payload']): RunArtifactRow['payload'] {\n const sanitized = redactAuthStateValue(sanitizeSecretTemplates(payload))\n if (!isRecord(sanitized)) return payload\n const config = sanitized.config\n if (!isRecord(config) || !('secretsFile' in config)) return sanitized as unknown as RunArtifactRow['payload']\n return {\n ...sanitized,\n config: {\n ...config,\n secretsFile: sanitizeSecretsFileMetadata(config.secretsFile),\n },\n } as RunArtifactRow['payload']\n}\n\nfunction sanitizeArtifactForResponse(artifact: RunArtifactRow | null): RunArtifactRow | null {\n if (!artifact) return null\n return {\n ...artifact,\n payload: sanitizeArtifactPayloadForResponse(artifact.payload),\n }\n}\n\nfunction sanitizeAuthStateForResponse<T>(value: T): T {\n return redactAuthStateValue(value)\n}\n\nasync function normalizeDashboardWorkspacePath(\n filePath: string,\n workspacePaths: ResolvedWorkspacePaths | undefined,\n kind: WorkspaceFileKind,\n requireExisting = true,\n): Promise<{ storagePath: string; executionPath: string }> {\n if (!workspacePaths) {\n throw new Error('Workspace path resolution is required for dashboard-triggered runs')\n }\n\n const record = await resolveWorkspaceFileTarget({\n workspace: workspacePaths,\n kind,\n filePath,\n requireExisting,\n })\n\n return { storagePath: record.workspaceRelativePath, executionPath: record.absolutePath }\n}\n\nfunction workspaceRecordToPath(record: WorkspaceFileRecord): { storagePath: string; executionPath: string } {\n return { storagePath: record.workspaceRelativePath, executionPath: record.absolutePath }\n}\n\nasync function resolveDashboardTestPattern(\n pattern: string,\n workspacePaths: ResolvedWorkspacePaths | undefined,\n): Promise<Array<{ storagePath: string; executionPath: string }>> {\n if (!workspacePaths) {\n throw new Error('Workspace path resolution is required for dashboard-triggered runs')\n }\n\n const normalizedPattern = pattern.replace(/\\\\/g, '/')\n if (isAbsolute(pattern) || normalizedPattern.split('/').includes('..')) {\n throw new Error(`Workspace test pattern is not allowed: ${pattern}`)\n }\n\n const candidates = await discoverWorkspaceFiles({ workspace: workspacePaths, kind: 'test' })\n const patternWorkspace: ResolvedWorkspacePaths = {\n ...workspacePaths,\n testMatch: [pattern],\n suiteMatch: [],\n }\n return candidates\n .filter((record) => isWorkspacePathMatch({\n workspace: patternWorkspace,\n kind: 'test',\n workspaceRelativePath: record.workspaceRelativePath,\n }))\n .map(workspaceRecordToPath)\n}\n\nfunction isSuiteFilePath(filePath: string | undefined): boolean {\n if (!filePath) return false\n const normalized = filePath.toLowerCase()\n return normalized.endsWith('.suite.yaml') || normalized.endsWith('.suite.yml')\n}\n\nasync function normalizeDashboardSuitePath(\n filePath: string,\n suiteFileManager?: SuiteFileManager,\n): Promise<{ storagePath: string; executionPath: string }> {\n if (!suiteFileManager) {\n throw new Error('Suite file management is required for dashboard-triggered suite runs')\n }\n\n return suiteFileManager.resolvePath(filePath)\n}\n\nfunction sanitizeQueuedRunMetadata(metadata: Record<string, unknown> | undefined): Record<string, unknown> {\n const { args: _args, target: _target, isSuite: _isSuite, ...safeMetadata } = metadata ?? {}\n return safeMetadata\n}\n\nfunction resolveArtifactPath(\n candidatePath: string,\n rootDir: string,\n apiPrefix: '/api/screenshots/' | '/api/videos/',\n): string | null {\n const normalizedCandidate = candidatePath.trim()\n if (!normalizedCandidate) return null\n const resolvedRootDir = resolve(rootDir)\n\n if (isAbsolute(normalizedCandidate)) {\n const resolvedAbsolute = resolve(normalizedCandidate)\n return getPathInsideDir(resolvedAbsolute, resolvedRootDir) ? resolvedAbsolute : null\n }\n\n const relativePath = normalizedCandidate.startsWith(apiPrefix)\n ? normalizedCandidate.slice(apiPrefix.length)\n : normalizedCandidate\n const resolvedPath = resolve(resolvedRootDir, relativePath)\n return getPathInsideDir(resolvedPath, resolvedRootDir) ? resolvedPath : null\n}\n\nasync function cleanupDeletedRunArtifacts(\n deletedRunIds: string[],\n screenshotPaths: string[],\n videoPaths: string[],\n dirs: {\n screenshotsDir?: string\n videosDir?: string\n },\n): Promise<void> {\n const cleanupTargets = new Set<string>()\n\n for (const runId of deletedRunIds) {\n if (dirs.screenshotsDir) cleanupTargets.add(join(dirs.screenshotsDir, runId))\n if (dirs.videosDir) cleanupTargets.add(join(dirs.videosDir, runId))\n }\n\n if (dirs.screenshotsDir) {\n for (const screenshotPath of screenshotPaths) {\n const resolvedPath = resolveArtifactPath(screenshotPath, dirs.screenshotsDir, '/api/screenshots/')\n if (resolvedPath) cleanupTargets.add(resolvedPath)\n }\n }\n\n if (dirs.videosDir) {\n for (const videoPath of videoPaths) {\n const resolvedPath = resolveArtifactPath(videoPath, dirs.videosDir, '/api/videos/')\n if (resolvedPath) cleanupTargets.add(resolvedPath)\n }\n }\n\n await Promise.allSettled(\n [...cleanupTargets].map((targetPath) => rm(targetPath, { recursive: true, force: true })),\n )\n}\n\nasync function readWorkspaceHooks(\n configManager: ConfigManager | undefined,\n configPath: string | undefined,\n): Promise<{\n hooks: Array<{ name: string }>\n filePath: string\n resolvedHooks: Map<string, import('@vostride/agent-qa-core').HookDefinition>\n errors: string[]\n missing: boolean\n hookRegistryError?: string\n}> {\n const hookRegistryManager = createHookRegistryManager(configManager, configPath)\n if (!hookRegistryManager) {\n return {\n hooks: [],\n filePath: '',\n resolvedHooks: new Map(),\n errors: ['Config management not available'],\n missing: true,\n hookRegistryError: 'Config management not available',\n }\n }\n\n const [hookCatalog, prepareResult] = await Promise.all([\n hookRegistryManager.readCatalog(),\n hookRegistryManager.prepareForExecution(),\n ])\n\n return {\n hooks: hookCatalog.hooks.map((hook) => ({ name: hook.name })),\n filePath: hookCatalog.filePath,\n resolvedHooks: prepareResult.resolvedHooks,\n errors: hookCatalog.errors,\n missing: hookCatalog.missing,\n hookRegistryError: prepareResult.hookRegistryError,\n }\n}\n\nasync function readWorkspaceEnvVars(\n workspacePaths: ResolvedWorkspacePaths | undefined,\n): Promise<Record<string, string>> {\n if (!workspacePaths) {\n return {}\n }\n\n try {\n const content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n return parseEnvFile(content)\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`workspace.envFile not found: ${workspacePaths.envFile.absolutePath}`)\n }\n throw error\n }\n}\n\nfunction validateHookRunRequest(body: unknown): {\n overrides: Record<string, string>\n fieldErrors: Array<{ field: 'registry'; code: string; message: string }>\n} {\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n return {\n overrides: {},\n fieldErrors: [\n {\n field: 'registry',\n code: 'invalid_payload',\n message: 'Hook run payload is required',\n },\n ],\n }\n }\n\n const rawOverrides = (body as { overrides?: unknown }).overrides\n if (rawOverrides === undefined) {\n return { overrides: {}, fieldErrors: [] }\n }\n\n if (!Array.isArray(rawOverrides)) {\n return {\n overrides: {},\n fieldErrors: [\n {\n field: 'registry',\n code: 'invalid_overrides',\n message: 'Hook run overrides must be an array',\n },\n ],\n }\n }\n\n const fieldErrors: Array<{ field: 'registry'; code: string; message: string }> = []\n const overrides: Record<string, string> = {}\n const seenKeys = new Set<string>()\n\n rawOverrides.forEach((entry, index) => {\n if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {\n fieldErrors.push({\n field: 'registry',\n code: 'invalid_override',\n message: `Override ${index + 1} must be an object with key and value`,\n })\n return\n }\n\n const key = typeof (entry as { key?: unknown }).key === 'string'\n ? (entry as { key: string }).key.trim()\n : ''\n const value = (entry as { value?: unknown }).value\n\n if (!key) {\n fieldErrors.push({\n field: 'registry',\n code: 'invalid_override_key',\n message: `Override ${index + 1} must include a non-empty key`,\n })\n return\n }\n\n if (seenKeys.has(key)) {\n fieldErrors.push({\n field: 'registry',\n code: 'duplicate_override_key',\n message: `Override key \"${key}\" is duplicated`,\n })\n return\n }\n\n if (typeof value !== 'string') {\n fieldErrors.push({\n field: 'registry',\n code: 'invalid_override_value',\n message: `Override \"${key}\" must have a string value`,\n })\n return\n }\n\n seenKeys.add(key)\n overrides[key] = value\n })\n\n return { overrides, fieldErrors }\n}\n\nfunction summarizeHookNetworkLogs(\n networkLogs: Array<{\n url: string\n method: string\n status: number\n startTime: number\n endTime: number\n }> | undefined,\n): import('../hooks/hook-registry-types.js').HookRunNetworkLogEntry[] {\n return (networkLogs ?? []).map((entry, index) => ({\n id: `network-${index + 1}`,\n method: entry.method,\n url: entry.url,\n statusCode: Number.isFinite(entry.status) ? entry.status : null,\n durationMs: Number.isFinite(entry.endTime - entry.startTime)\n ? Math.max(0, entry.endTime - entry.startTime)\n : null,\n error: null,\n }))\n}\n\ninterface RouterDeps {\n db: DashboardDatabase\n artifactsDir?: string\n workspacePaths?: ResolvedWorkspacePaths\n testRunner?: TestRunner\n jobQueue?: JobQueue\n testFileManager?: TestFileManager\n suiteFileManager?: SuiteFileManager\n configManager?: ConfigManager\n configPath?: string\n\n llmConfig?: DashboardRuntimeLLMConfig\n authFetch?: typeof globalThis.fetch\n sessionManager?: import('../live-editor/session-manager.js').SessionManager\n analyticsBridge?: {\n buildAnalyticsEvent: typeof buildAnalyticsEvent\n captureAnalytics: typeof captureAnalytics\n resolveAnalyticsStandardProperties: typeof resolveAnalyticsStandardProperties\n }\n}\n\nexport function createRouter(deps: RouterDeps): (req: IncomingMessage, res: ServerResponse) => void\nexport function createRouter(db: DashboardDatabase, artifactsDir?: string): (req: IncomingMessage, res: ServerResponse) => void\nexport function createRouter(dbOrDeps: DashboardDatabase | RouterDeps, artifactsDir?: string): (req: IncomingMessage, res: ServerResponse) => void {\n const deps: RouterDeps = 'db' in dbOrDeps && typeof (dbOrDeps as RouterDeps).db === 'object' && 'getRuns' in ((dbOrDeps as RouterDeps).db ?? {})\n ? dbOrDeps as RouterDeps\n : { db: dbOrDeps as DashboardDatabase, artifactsDir }\n const { db, testRunner, jobQueue, testFileManager, suiteFileManager, configManager, workspacePaths, llmConfig, authFetch, sessionManager } = deps\n const pluginOAuthSessions = new Map<string, PluginOAuthSession>()\n const analyticsBridge = deps.analyticsBridge ?? {\n buildAnalyticsEvent,\n captureAnalytics,\n resolveAnalyticsStandardProperties,\n }\n const ssDir = deps.artifactsDir ? join(deps.artifactsDir, 'screenshots') : undefined\n const vidDir = deps.artifactsDir ? join(deps.artifactsDir, 'videos') : undefined\n const memoryCatalogManager = new MemoryCatalogManager({ configManager, configPath: deps.configPath })\n\n return (req: IncomingMessage, res: ServerResponse) => {\n if (req.method === 'OPTIONS') {\n cors(res)\n return\n }\n\n const url = parseUrl(req)\n const path = url.pathname\n\n // GET /api/auth-states — list safe auth-state metadata only\n if (path === '/api/auth-states' && req.method === 'GET') {\n if (!configManager || !deps.configPath) {\n json(res, { error: 'Auth-state metadata not available' }, 503)\n return\n }\n ;(async () => {\n try {\n const config = await configManager.read()\n const targetName = url.searchParams.get('target') ?? undefined\n const authStates = await listAuthStateMetadata({\n configDir: dirname(resolve(deps.configPath!)),\n authStateDir: getConfiguredAuthStateDir(config),\n targetName,\n })\n json(res, { authStates })\n } catch {\n json(res, { error: 'Could not list auth states.' }, 500)\n }\n })()\n return\n }\n\n // POST /api/analytics/events — best-effort dashboard product analytics bridge\n if (path === '/api/analytics/events' && req.method === 'POST') {\n readJsonBody<{ name?: unknown; properties?: unknown }>(req)\n .then((body) => {\n if (\n !isPlainRecord(body)\n || !isDashboardProductEventName(body.name)\n || (\n Object.prototype.hasOwnProperty.call(body, 'properties')\n && body.properties !== undefined\n && !isPlainRecord(body.properties)\n )\n ) {\n json(res, { error: 'Invalid analytics event' }, 400)\n return\n }\n\n const name = body.name\n const browserProperties = isPlainRecord(body.properties) ? body.properties : {}\n json(res, { accepted: true }, 202)\n\n void (async () => {\n try {\n const config = await readAnalyticsServiceConfig(configManager)\n if (config.analytics?.privacy === true) {\n return\n }\n\n const standardProperties = await analyticsBridge.resolveAnalyticsStandardProperties({ surface: 'dashboard-ui' })\n const event = analyticsBridge.buildAnalyticsEvent({\n name,\n properties: {\n ...filterDashboardProductEventProperties(name, browserProperties),\n ...standardProperties,\n },\n })\n await analyticsBridge.captureAnalytics(event, { config })\n } catch {\n // Analytics is intentionally best-effort and invisible to dashboard users.\n }\n })()\n })\n .catch(() => json(res, { error: 'Invalid analytics event' }, 400))\n return\n }\n\n // GET /api/runs\n if (path === '/api/runs' && req.method === 'GET') {\n const status = url.searchParams.get('status') ?? undefined\n const name = url.searchParams.get('name') ?? undefined\n const platform = url.searchParams.get('platform') ?? undefined\n const target = normalizeRunFilterValue(url.searchParams.get('target'))\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const attributePredicatesResult = parseAttributePredicates(url.searchParams)\n if (!attributePredicatesResult.ok) {\n json(res, { error: attributePredicatesResult.error }, 400)\n return\n }\n\n void readTargetPlatformMap(configManager)\n .then((targetPlatforms) => {\n const allRuns = db.getRuns({\n status,\n name,\n from,\n to,\n attributePredicates: attributePredicatesResult.predicates,\n })\n const enrichedRuns = allRuns.map(run => {\n if (run.suiteId && !run.parentRunId) {\n const tests = db.getRunsByParent(run.id).map(test => enrichRunRow(test, targetPlatforms))\n return enrichRunRow(run, targetPlatforms, tests)\n }\n return enrichRunRow(run, targetPlatforms)\n })\n const platformFilteredRuns = enrichedRuns.filter(run =>\n matchesPlatformFilter(run, normalizeSupportedPlatform(platform)),\n )\n const targetOptions = Array.from(new Set(\n platformFilteredRuns\n .flatMap(run => [run.targetName, ...(run.tests?.map(test => test.targetName) ?? [])])\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0),\n )).sort((a, b) => a.localeCompare(b))\n const filtered = platformFilteredRuns.filter(run => matchesTargetFilter(run, target))\n\n const runs = filtered.slice(offset, offset + limit)\n json(res, { runs, total: filtered.length, targets: targetOptions })\n })\n .catch(() => json(res, { error: 'Failed to list runs' }, 500))\n return\n }\n\n // GET /api/runs/attributes/keys\n if (path === '/api/runs/attributes/keys' && req.method === 'GET') {\n const limitResult = parseBoundedIntegerQueryParam(url.searchParams.get('limit'), 'limit', 1, 100, 50)\n if (!limitResult.ok) {\n json(res, { error: limitResult.error }, 400)\n return\n }\n json(res, {\n keys: db.listRunAttributeKeys({\n limit: limitResult.value,\n q: url.searchParams.get('q') ?? undefined,\n }),\n })\n return\n }\n\n // GET /api/runs/attributes/values\n if (path === '/api/runs/attributes/values' && req.method === 'GET') {\n const key = url.searchParams.get('key')?.trim()\n if (!key) {\n json(res, { error: 'key is required' }, 400)\n return\n }\n const limitResult = parseBoundedIntegerQueryParam(url.searchParams.get('limit'), 'limit', 1, 100, 50)\n if (!limitResult.ok) {\n json(res, { error: limitResult.error }, 400)\n return\n }\n json(res, {\n values: db.listRunAttributeValues(key, {\n limit: limitResult.value,\n q: url.searchParams.get('q') ?? undefined,\n }),\n })\n return\n }\n\n // GET /api/runs/:id/artifact\n const runArtifactMatch = path.match(/^\\/api\\/runs\\/([^/]+)\\/artifact$/)\n if (runArtifactMatch && req.method === 'GET') {\n const runId = decodeURIComponent(runArtifactMatch[1])\n const run = db.getRun(runId)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const bundle = db.getRunArtifactBundle(runId)\n json(res, sanitizeAuthStateForResponse({\n run,\n artifact: sanitizeArtifactForResponse(bundle.artifact),\n children: bundle.children.map((child) => ({\n ...child,\n artifact: sanitizeArtifactForResponse(child.artifact),\n })),\n missingSections: getArtifactMissingSections(bundle.artifact),\n }))\n return\n }\n\n // GET /api/runs/:id/accessibility\n if (path.startsWith('/api/runs/') && path.endsWith('/accessibility') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const summary = db.getAccessibilitySummary(id)\n json(res, summary)\n return\n }\n\n // GET /api/runs/:id/steps/:n/reasoning — structured reasoning trace for a step\n const reasoningMatch = path.match(/^\\/api\\/runs\\/([^/]+)\\/steps\\/(\\d+)\\/reasoning$/)\n if (reasoningMatch && req.method === 'GET') {\n const [, runId, stepOrderStr] = reasoningMatch\n const run = db.getRun(runId)\n if (!run) { notFound(res, 'Run not found'); return }\n const stepOrder = parseInt(stepOrderStr, 10)\n const trace = db.getReasoningTrace(runId, stepOrder)\n if (trace) {\n json(res, sanitizeAuthStateForResponse({ trace }))\n return\n }\n // Fallback: construct legacy trace from step data for backward compatibility\n const steps = db.getSteps(runId)\n const step = steps.find(s => s.stepOrder === stepOrder)\n if (!step) { notFound(res, 'Step not found'); return }\n json(res, sanitizeAuthStateForResponse({\n trace: {\n id: null,\n stepId: step.id,\n observeText: step.observation,\n observeDuration: null,\n planReasoning: step.reasoning,\n planConfidence: step.confidence,\n planAction: step.plannedAction,\n planDuration: null,\n executeAction: step.action,\n executeDuration: null,\n verifyReasoning: null,\n verifySuccess: step.result === 'success' ? true : step.result === 'failure' ? false : null,\n verifyDuration: null,\n healAttempts: step.healingAttempts,\n totalDuration: step.duration,\n screenStateBefore: null,\n screenStateAfter: null,\n createdAt: step.createdAt,\n },\n }))\n return\n }\n\n // GET /api/runs/:id/execution-logs\n if (path.startsWith('/api/runs/') && path.endsWith('/execution-logs') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const stepId = url.searchParams.get('stepId') ?? undefined\n const type = url.searchParams.get('type') ?? undefined\n\n if (run.suiteId && !run.parentRunId) {\n const childRuns = db.getRunsByParent(id)\n const allRunIds = [id, ...childRuns.map((c: any) => c.id)]\n let allLogs: any[] = []\n for (const rid of allRunIds) {\n allLogs.push(...db.getExecutionLogs({ runId: rid, stepId, type }))\n }\n json(res, sanitizeAuthStateForResponse({ logs: allLogs }))\n return\n }\n\n const logs = db.getExecutionLogs({ runId: id, stepId, type })\n json(res, sanitizeAuthStateForResponse({ logs }))\n return\n }\n\n // GET /api/runs/:id/logs\n if (path.startsWith('/api/runs/') && path.endsWith('/logs') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const stepId = url.searchParams.get('stepId') ?? undefined\n const level = url.searchParams.get('level') ?? undefined\n const source = url.searchParams.get('source') ?? undefined\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 500\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const logs = db.getLogs({ runId: id, stepId, level, source, limit, offset })\n json(res, sanitizeAuthStateForResponse({ logs, total: logs.length }))\n return\n }\n\n // GET /api/runs/:id/steps\n if (path.startsWith('/api/runs/') && path.endsWith('/steps') && req.method === 'GET') {\n const segments = path.split('/')\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const steps = db.getSteps(id)\n json(res, sanitizeAuthStateForResponse({ steps }))\n return\n }\n\n // POST /api/runs/:id/cancel — cancel a pending or running execution\n if (path.startsWith('/api/runs/') && path.endsWith('/cancel') && req.method === 'POST') {\n if (!jobQueue) {\n json(res, { error: 'Queue not available' }, 503)\n return\n }\n const runId = path.slice('/api/runs/'.length, path.length - '/cancel'.length)\n const cancelled = jobQueue.cancel(runId)\n if (cancelled) {\n // For pending jobs, JobQueue already set status='cancelled'.\n // For running jobs, JobQueue emits 'cancel-running' which triggers executionManager.kill().\n // Update DB with cancel metadata for running jobs.\n try {\n const run = db.getRun(runId)\n if (run && run.status === 'cancelled') {\n const duration = run.startedAt\n ? Date.now() - new Date(run.startedAt).getTime()\n : 0\n db.updateRun(runId, {\n duration,\n endedAt: new Date().toISOString(),\n failureSummary: 'Test cancelled by user',\n })\n }\n } catch { /* best-effort */ }\n json(res, { cancelled: true })\n } else {\n json(res, { error: 'Run not found or not cancellable' }, 404)\n }\n return\n }\n\n // DELETE /api/runs/:id\n if (path.startsWith('/api/runs/') && req.method === 'DELETE') {\n const segments = path.split('/')\n if (segments.length !== 4) {\n notFound(res)\n return\n }\n\n const id = segments[3]\n\n try {\n const deletedRun = db.deleteRun(id)\n if (!deletedRun.deleted) {\n notFound(res, 'Run not found')\n return\n }\n\n void cleanupDeletedRunArtifacts(\n deletedRun.deletedRunIds,\n deletedRun.screenshotPaths,\n deletedRun.videoPaths,\n {\n screenshotsDir: ssDir,\n videosDir: vidDir,\n },\n ).finally(() => {\n json(res, { deleted: true, deletedRunIds: deletedRun.deletedRunIds })\n })\n } catch {\n json(res, { error: 'Failed to delete run' }, 500)\n }\n return\n }\n\n // GET /api/runs/:id\n if (path.startsWith('/api/runs/') && req.method === 'GET') {\n const segments = path.split('/')\n if (segments.length !== 4) {\n notFound(res)\n return\n }\n const id = segments[3]\n const run = db.getRun(id)\n if (!run) {\n notFound(res, 'Run not found')\n return\n }\n const steps = db.getSteps(id)\n const attempts = db.getRunsByParent(id)\n if (run.suiteId && !run.parentRunId) {\n const tests = db.getRunsByParent(id)\n json(res, sanitizeAuthStateForResponse({ run, steps, attempts, tests }))\n } else {\n json(res, sanitizeAuthStateForResponse({ run, steps, attempts }))\n }\n return\n }\n\n // GET /api/stats/costs\n if (path === '/api/stats/costs' && req.method === 'GET') {\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const costStats = db.getCostStats({ from, to })\n json(res, costStats)\n return\n }\n\n // GET /api/token-events/stats\n if (path === '/api/token-events/stats' && req.method === 'GET') {\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const stats = db.getTokenEventStats({ from, to })\n json(res, stats)\n return\n }\n\n // GET /api/stats\n if (path === '/api/stats' && req.method === 'GET') {\n const from = url.searchParams.get('from') ?? undefined\n const to = url.searchParams.get('to') ?? undefined\n const scope = url.searchParams.get('scope') ?? undefined\n if (scope !== undefined && scope !== 'passRate') {\n json(res, { error: 'scope must be passRate when provided' }, 400)\n return\n }\n\n void readAnalyticsScopePredicates(configManager)\n .then((scopeResult) => {\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n const configured = scopeResult.predicates.length > 0\n const allStats = db.getStats({ from, to })\n const scopedStats = configured\n ? db.getStats({ from, to, attributePredicates: scopeResult.predicates })\n : allStats\n const stats = scope === 'passRate' && configured ? scopedStats : allStats\n\n json(res, {\n ...stats,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount: configured ? scopedStats.totalRuns : 0,\n totalCount: allStats.totalRuns,\n },\n })\n })\n .catch(() => {\n json(res, { error: 'Unable to read analytics scope' }, 500)\n })\n return\n }\n\n // GET /api/screenshots/:runId/:filename\n if (path.startsWith('/api/screenshots/') && req.method === 'GET') {\n const segments = path.split('/')\n if (segments.length !== 5 || !ssDir) {\n notFound(res)\n return\n }\n const runId = segments[3]\n const filename = segments[4]\n\n if (runId.includes('..') || filename.includes('..') || runId.includes('/') || filename.includes('/')) {\n notFound(res, 'Invalid path')\n return\n }\n\n const filePath = join(ssDir, runId, filename)\n const resolvedPath = resolve(filePath)\n if (!resolvedPath.startsWith(resolve(ssDir))) {\n notFound(res, 'Invalid path')\n return\n }\n\n stat(filePath).then(s => {\n if (!s.isFile()) {\n notFound(res, 'Screenshot not found')\n return\n }\n readFile(filePath).then(buffer => {\n res.writeHead(200, {\n 'Content-Type': 'image/png',\n 'Content-Length': buffer.length,\n 'Access-Control-Allow-Origin': '*',\n })\n res.end(buffer)\n }).catch(() => notFound(res, 'Screenshot not found'))\n }).catch(() => notFound(res, 'Screenshot not found'))\n return\n }\n\n // GET /api/videos/:runId/:filename\n if (path.startsWith('/api/videos/') && req.method === 'GET') {\n const segments = path.split('/')\n if (segments.length !== 5 || !vidDir) {\n notFound(res)\n return\n }\n const runId = segments[3]\n const filename = segments[4]\n\n if (runId.includes('..') || filename.includes('..') || runId.includes('/') || filename.includes('/')) {\n notFound(res, 'Invalid path')\n return\n }\n\n const videoPath = join(vidDir, runId, filename)\n const resolvedVideo = resolve(videoPath)\n const resolvedVidDir = resolve(vidDir)\n if (!getPathInsideDir(resolvedVideo, resolvedVidDir)) {\n notFound(res, 'Invalid path')\n return\n }\n\n const tryServe = (filePath: string) => stat(filePath).then(s => {\n if (!s.isFile()) {\n notFound(res, 'Video not found')\n return\n }\n\n const contentType = filePath.endsWith('.mp4') ? 'video/mp4' : 'video/webm'\n const range = req.headers.range\n if (range) {\n const parts = range.replace(/bytes=/, '').split('-')\n const start = parseInt(parts[0], 10)\n const end = parts[1] ? parseInt(parts[1], 10) : s.size - 1\n const chunkSize = end - start + 1\n\n res.writeHead(206, {\n 'Content-Range': `bytes ${start}-${end}/${s.size}`,\n 'Accept-Ranges': 'bytes',\n 'Content-Length': chunkSize,\n 'Content-Type': contentType,\n 'Access-Control-Allow-Origin': '*',\n })\n createReadStream(filePath, { start, end }).pipe(res)\n } else {\n res.writeHead(200, {\n 'Content-Type': contentType,\n 'Content-Length': s.size,\n 'Accept-Ranges': 'bytes',\n 'Access-Control-Allow-Origin': '*',\n })\n createReadStream(filePath).pipe(res)\n }\n })\n tryServe(videoPath).catch(() => notFound(res, 'Video not found'))\n return\n }\n\n // GET /api/execution/active — list currently running tests\n if (path === '/api/execution/active' && req.method === 'GET') {\n const active = testRunner ? testRunner.getActiveExecutions() : []\n json(res, { executions: active })\n return\n }\n\n // POST /api/queue/enqueue — external API to enqueue a test run\n if (path === '/api/queue/enqueue' && req.method === 'POST') {\n if (!jobQueue) {\n json(res, { error: 'Queue not available' }, 503)\n return\n }\n readJsonBody<{ name: string; file?: string; priority?: number; platform?: string; parallel?: boolean; metadata?: Record<string, unknown>; attributes?: unknown }>(req)\n .then(async (body) => {\n if (!body.name || typeof body.name !== 'string') {\n json(res, { error: 'name is required' }, 400)\n return\n }\n let normalizedFileTarget: { storagePath: string; executionPath: string } | null = null\n const isSuiteFile = isSuiteFilePath(body.file)\n if (body.file) {\n try {\n normalizedFileTarget = isSuiteFile\n ? await normalizeDashboardSuitePath(body.file, suiteFileManager)\n : await normalizeDashboardWorkspacePath(body.file, workspacePaths, 'test')\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : String(err) }, 400)\n return\n }\n }\n let attributes: RunAttributes\n try {\n attributes = buildRunRequestAttributes({\n trigger: 'api',\n runner: 'local',\n userAttributes: body.attributes,\n })\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : String(err) }, 400)\n return\n }\n const runId = jobQueue.enqueue({\n name: body.name,\n filePath: normalizedFileTarget?.storagePath,\n kind: isSuiteFile ? 'suite-parent' : 'test',\n attributes,\n priority: body.priority,\n platform: body.platform,\n parallel: body.parallel,\n metadata: {\n ...sanitizeQueuedRunMetadata(body.metadata),\n args: normalizedFileTarget ? [normalizedFileTarget.executionPath] : [],\n ...(isSuiteFile ? { isSuite: true } : {}),\n },\n })\n const pending = db.getPendingRuns()\n const position = pending.findIndex(r => r.id === runId) + 1\n json(res, { runId, status: 'queued', position }, 202)\n })\n .catch(() => {\n json(res, { error: 'Invalid request body' }, 400)\n })\n return\n }\n\n // GET /api/queue/status — queue status with pending/running jobs\n if (path === '/api/queue/status' && req.method === 'GET') {\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 20\n const completed = url.searchParams.get('completed') === 'true'\n const pending = db.getPendingRuns()\n const allRuns = db.getRuns({ limit: 100 })\n const running = allRuns.filter(r => r.status === 'running')\n const response: Record<string, unknown> = {\n pending: { count: pending.length, jobs: pending },\n running: { count: running.length, jobs: running },\n concurrency: jobQueue?.getConcurrency() ?? 0,\n activeSlots: jobQueue?.getActiveCount() ?? 0,\n }\n if (completed) {\n const recent = allRuns\n .filter(r => r.status !== 'pending' && r.status !== 'running')\n .slice(0, limit)\n response.recent = recent\n }\n json(res, response)\n return\n }\n\n // POST /api/runs/trigger — enqueue a live test execution\n if (path === '/api/runs/trigger' && req.method === 'POST') {\n if (!jobQueue) {\n json(res, { error: 'Queue not available' }, 503)\n return\n }\n readJsonBody<{ file?: string; patterns?: string[]; tags?: unknown; noCache?: boolean; noMemory?: boolean; local?: boolean; triggerSource?: unknown }>(req)\n .then(async (body) => {\n if (body.tags !== undefined) {\n json(res, { error: 'tags are not supported for dashboard-triggered runs' }, 400)\n return\n }\n const triggerSource = parseDashboardRunTriggerSource(body.triggerSource)\n if (!triggerSource.ok) {\n json(res, { error: triggerSource.error }, 400)\n return\n }\n const args: string[] = []\n const isSuiteFile = isSuiteFilePath(body.file)\n let normalizedFileTarget: { storagePath: string; executionPath: string } | null = null\n try {\n normalizedFileTarget = body.file\n ? isSuiteFile\n ? await normalizeDashboardSuitePath(body.file, suiteFileManager)\n : await normalizeDashboardWorkspacePath(body.file, workspacePaths, 'test')\n : null\n\n if (body.file) {\n args.push(normalizedFileTarget?.executionPath ?? body.file)\n }\n if (body.patterns) {\n if (!Array.isArray(body.patterns)) {\n throw new Error('patterns must be an array')\n }\n for (const pattern of body.patterns) {\n if (typeof pattern !== 'string') {\n throw new Error('patterns must be strings')\n }\n const matches = await resolveDashboardTestPattern(pattern, workspacePaths)\n args.push(...matches.map((match) => match.executionPath))\n }\n }\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : String(err) }, 400)\n return\n }\n const normalizedTestTarget = body.file && !isSuiteFile\n ? normalizedFileTarget\n : null\n if (body.noCache) {\n args.push('--no-cache')\n }\n if (body.noMemory) {\n args.push('--no-memory')\n }\n const isSuite = Boolean(isSuiteFile)\n\n let testName = body.file\n ? basename(normalizedFileTarget?.storagePath ?? body.file, '.yaml')\n : 'unknown'\n\n let fileParallel: boolean | undefined\n let platform: string | undefined\n\n if (isSuite && body.file && suiteFileManager) {\n // Parse suite YAML for name and platform\n try {\n const content = await suiteFileManager.read(normalizedFileTarget?.storagePath ?? body.file)\n fileParallel = readSuiteYamlParallel(content)\n const parsed = parseYaml(content)\n if (parsed?.name) testName = parsed.name\n platform = parsed?.config?.platform ?? undefined\n } catch { /* fall back to defaults */ }\n } else if (body.file && testFileManager) {\n // Parse test YAML for name, use.parallel, and platform metadata\n try {\n const readPath = normalizedTestTarget?.storagePath ?? body.file\n const content = await testFileManager.read(readPath)\n const metadata = extractTestFileMetadata(content)\n const targetPlatforms = await readTargetPlatformMap(configManager)\n if (metadata.name) testName = metadata.name\n if (metadata.parallel !== null) fileParallel = metadata.parallel\n platform = resolveEffectivePlatform(\n metadata.platform,\n metadata.targetName,\n targetPlatforms,\n platform,\n ) ?? undefined\n } catch { /* fall back to defaults */ }\n }\n\n const configParallel = await readConfigUseParallel(configManager)\n const effectiveParallel = fileParallel ?? configParallel ?? false\n const executionTimeout = await resolveDashboardExecutionTimeout({\n isSuite,\n file: normalizedFileTarget?.storagePath ?? body.file,\n normalizedTestPath: normalizedTestTarget?.storagePath,\n testFileManager,\n suiteFileManager,\n configManager,\n })\n\n const runId = jobQueue.enqueue({\n name: testName,\n filePath: normalizedFileTarget?.storagePath ?? body.file,\n kind: isSuite ? 'suite-parent' : 'test',\n attributes: buildRunRequestAttributes({\n trigger: triggerSource.trigger,\n runner: body.local === false ? 'browserstack' : 'local',\n }),\n platform,\n parallel: effectiveParallel,\n metadata: {\n args,\n isSuite: isSuite || undefined,\n ...toExecutionTimeoutMetadata(executionTimeout),\n },\n })\n json(res, { runId, status: 'queued' }, 202)\n })\n .catch(() => {\n json(res, { error: 'Invalid request body' }, 400)\n })\n return\n }\n\n // GET /api/execution/events — SSE stream for live execution events\n if (path === '/api/execution/events' && req.method === 'GET') {\n if (!testRunner) {\n json(res, { error: 'Execution not available' }, 503)\n return\n }\n\n const runId = url.searchParams.get('runId') ?? undefined\n const lastEventId = req.headers['last-event-id'] as string | undefined\n\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n res.write(':ok\\n\\n')\n\n // Replay buffered events for reconnection\n if (lastEventId && runId) {\n const lastId = parseInt(lastEventId, 10)\n const buffered = testRunner.getBufferedEvents(runId)\n for (const evt of buffered) {\n if (evt.id > lastId) {\n res.write(`id: ${evt.id}\\nevent: ${evt.type}\\ndata: ${JSON.stringify(evt)}\\n\\n`)\n }\n }\n } else if (runId) {\n // New connection — replay all buffered events\n const buffered = testRunner.getBufferedEvents(runId)\n for (const evt of buffered) {\n res.write(`id: ${evt.id}\\nevent: ${evt.type}\\ndata: ${JSON.stringify(evt)}\\n\\n`)\n }\n }\n\n const onEvent = (evtRunId: string, event: { id: number; type: string; [key: string]: unknown }) => {\n if (runId && evtRunId !== runId) return\n res.write(`id: ${event.id}\\nevent: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`)\n }\n\n testRunner.on('execution-event', onEvent)\n\n const heartbeat = setInterval(() => {\n res.write(':\\n\\n')\n }, 15_000)\n\n req.on('close', () => {\n clearInterval(heartbeat)\n testRunner.removeListener('execution-event', onEvent)\n })\n return\n }\n\n // POST /api/suites/validate — validate suite YAML content\n if (path === '/api/suites/validate' && req.method === 'POST') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n const result = await suiteFileManager.validate(body.content ?? '')\n json(res, result)\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/suites — list all suite files\n if (path === '/api/suites' && req.method === 'GET') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n suiteFileManager.list()\n .then(files => json(res, { files }))\n .catch(() => json(res, { error: 'Failed to list suite files' }, 500))\n return\n }\n\n // POST /api/suites — create a new suite file\n if (path === '/api/suites' && req.method === 'POST') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n readJsonBody<{ path: string; content: string }>(req)\n .then(async (body) => {\n if (!body.path || typeof body.path !== 'string' || !body.content || typeof body.content !== 'string') {\n json(res, { error: 'Both path and content are required' }, 400)\n return\n }\n const validation = await suiteFileManager.validate(body.content)\n if (!validation.valid) {\n json(res, {\n error: 'Invalid suite content',\n details: validation.errors,\n missingTests: validation.missingTests,\n }, 400)\n return\n }\n try {\n await suiteFileManager.write(body.path, body.content)\n json(res, { path: body.path, created: true }, 201)\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to create suite file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // DELETE /api/suites/:path — delete a suite file\n if (path.startsWith('/api/suites/') && req.method === 'DELETE') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n const decodedPath = decodeURIComponent(path.slice('/api/suites/'.length))\n suiteFileManager.delete(decodedPath)\n .then(() => json(res, { deleted: true }))\n .catch((err: any) => {\n if (err.code === 'ENOENT') {\n notFound(res, 'Suite file not found')\n return\n }\n json(res, { error: err.message }, 500)\n })\n return\n }\n\n // PUT /api/suites/:suite-id — update suite file by suite-id (hard break D-02/D-04)\n if (path.startsWith('/api/suites/') && req.method === 'PUT') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n const sId = decodeURIComponent(path.slice('/api/suites/'.length))\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n if (!body.content || typeof body.content !== 'string') {\n json(res, { error: 'Content is required' }, 400)\n return\n }\n const found = await suiteFileManager.findBySuiteId(sId)\n if (!found) {\n notFound(res, 'Suite not found')\n return\n }\n const validation = await suiteFileManager.validate(body.content)\n if (!validation.valid) {\n json(res, {\n error: 'Invalid suite content',\n details: validation.errors,\n missingTests: validation.missingTests,\n }, 400)\n return\n }\n try {\n await suiteFileManager.write(found.path, body.content)\n json(res, { path: found.path, updated: true })\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update suite file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/suites/:suite-id — read suite file by suite-id (hard break D-02/D-04/D-05)\n if (path.startsWith('/api/suites/') && req.method === 'GET') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n const sId = decodeURIComponent(path.slice('/api/suites/'.length))\n suiteFileManager.findBySuiteId(sId)\n .then(result => {\n if (!result) {\n notFound(res, 'Suite not found')\n return\n }\n json(res, { path: result.path, content: result.content, suiteId: sId })\n })\n .catch(() => notFound(res, 'Suite not found'))\n return\n }\n\n // POST /api/tests/validate — validate YAML content (must be before parameterized /api/tests/:path)\n if (path === '/api/tests/validate' && req.method === 'POST') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n readJsonBody<{ content: string; filePath?: string }>(req)\n .then(async (body) => {\n const isSuite = body.filePath?.endsWith('.suite.yaml') || body.filePath?.endsWith('.suite.yml')\n if (isSuite && suiteFileManager) {\n const result = await suiteFileManager.validate(body.content ?? '')\n json(res, result)\n } else {\n const result = await testFileManager.validate(body.content ?? '')\n json(res, result)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/tests — list all test files\n if (path === '/api/tests' && req.method === 'GET') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n testFileManager.list()\n .then(async files => {\n const targetPlatforms = await readTargetPlatformMap(configManager)\n const resolvedFiles = files.map((file) => ({\n ...file,\n platform: resolveEffectivePlatform(file.platform, file.targetName, targetPlatforms),\n }))\n const targets = Array.from(\n new Set(\n resolvedFiles\n .map((file) => file.targetName)\n .filter((value): value is string => typeof value === 'string' && value.length > 0),\n ),\n )\n json(res, { files: resolvedFiles, targets })\n })\n .catch(() => json(res, { error: 'Failed to list test files' }, 500))\n return\n }\n\n // POST /api/tests — create a new test file\n if (path === '/api/tests' && req.method === 'POST') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n readJsonBody<{ path: string; content: string }>(req)\n .then(async (body) => {\n if (!body.path || typeof body.path !== 'string' || !body.content || typeof body.content !== 'string') {\n json(res, { error: 'Both path and content are required' }, 400)\n return\n }\n try {\n await testFileManager.write(body.path, body.content)\n json(res, { path: body.path, created: true }, 201)\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to create test file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // DELETE /api/tests/:t_id — delete test file by test-id\n if (path.startsWith('/api/tests/') && req.method === 'DELETE') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n const tId = decodeURIComponent(path.slice('/api/tests/'.length))\n testFileManager.findByTestId(tId)\n .then(async (found) => {\n if (!found) {\n notFound(res, 'Test not found')\n return\n }\n await testFileManager.delete(found.path)\n json(res, { deleted: true, path: found.path })\n })\n .catch((err: unknown) => {\n const code = (err as NodeJS.ErrnoException)?.code\n if (code === 'ENOENT') {\n notFound(res, 'Test not found')\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete test file' }, 500)\n })\n return\n }\n\n // PUT /api/tests/:t_id — update test file by test-id\n if (path.startsWith('/api/tests/') && req.method === 'PUT') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n const tId = decodeURIComponent(path.slice('/api/tests/'.length))\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n if (!body.content || typeof body.content !== 'string') {\n json(res, { error: 'Content is required' }, 400)\n return\n }\n const found = await testFileManager.findByTestId(tId)\n if (!found) {\n notFound(res, 'Test not found')\n return\n }\n try {\n await testFileManager.write(found.path, body.content)\n json(res, { path: found.path, updated: true })\n } catch (err) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update test file' }, 400)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // GET /api/tests/:t_id — read test file by test-id\n if (path.startsWith('/api/tests/') && req.method === 'GET') {\n if (!testFileManager) {\n json(res, { error: 'Test file management not configured' }, 501)\n return\n }\n const tId = decodeURIComponent(path.slice('/api/tests/'.length))\n testFileManager.findByTestId(tId)\n .then(result => {\n if (!result) {\n notFound(res, 'Test not found')\n return\n }\n json(res, { path: result.path, content: result.content, testId: tId })\n })\n .catch(() => notFound(res, 'Test not found'))\n return\n }\n\n // GET /api/analytics/tests\n if (path === '/api/analytics/tests' && req.method === 'GET') {\n const minRuns = url.searchParams.has('minRuns') ? parseInt(url.searchParams.get('minRuns')!, 10) : 3\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const tests = db.getFlakyTests({ minRuns, limit })\n const result = tests.map(t => {\n return { ...t, isFlaky: t.flakyScore >= 0.4 }\n })\n json(res, { tests: result })\n return\n }\n\n // GET /api/analytics/tests/:name\n if (path.startsWith('/api/analytics/tests/') && req.method === 'GET') {\n const name = decodeURIComponent(path.slice('/api/analytics/tests/'.length))\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const from = url.searchParams.get('from') ?? undefined\n void readAnalyticsScopePredicates(configManager)\n .then((scopeResult) => {\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n\n const runs = db.getRunsByTestName(name, { limit, offset })\n const total = db.getRunsByTestNameCount(name)\n const trends = db.getTestTrends(name, { from })\n const allRunsForFlakiness = db.getRunsByTestName(name, { limit: 100 })\n const flakyMetrics = calculateFlakyMetrics(allRunsForFlakiness)\n const flakyScore = flakyMetrics.score\n const configured = scopeResult.predicates.length > 0\n const scopedRuns = configured\n ? db.getRunsByTestName(name, { limit, offset, attributePredicates: scopeResult.predicates })\n : runs\n const scopedTotal = configured\n ? db.getRunsByTestNameCount(name, { attributePredicates: scopeResult.predicates })\n : total\n const scopedTrends = configured\n ? db.getTestTrends(name, { from, attributePredicates: scopeResult.predicates })\n : trends\n const scopedRunsForFlakiness = configured\n ? db.getRunsByTestName(name, { limit: 100, attributePredicates: scopeResult.predicates })\n : allRunsForFlakiness\n const scopedFlakyScore = calculateFlakyMetrics(scopedRunsForFlakiness).score\n\n json(res, {\n name,\n runs,\n total,\n trends,\n isFlaky: flakyScore >= 0.4 && flakyMetrics.statusCount >= 3,\n flakyScore,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount: scopedTotal,\n totalCount: total,\n },\n ...(configured ? {\n scopedRuns,\n scopedTrends,\n scopedFlakyScore,\n } : {}),\n })\n })\n .catch(() => json(res, { error: 'Failed to read analytics scope' }, 500))\n return\n }\n\n // GET /api/analytics/suites/:suiteId\n if (path.startsWith('/api/analytics/suites/') && req.method === 'GET') {\n if (!suiteFileManager) {\n json(res, { error: 'Suite file management not configured' }, 501)\n return\n }\n\n const suiteId = decodeURIComponent(path.slice('/api/analytics/suites/'.length))\n const limit = url.searchParams.has('limit') ? parseInt(url.searchParams.get('limit')!, 10) : 50\n const offset = url.searchParams.has('offset') ? parseInt(url.searchParams.get('offset')!, 10) : 0\n const from = url.searchParams.get('from') ?? undefined\n\n Promise.all([suiteFileManager.findBySuiteId(suiteId), readAnalyticsScopePredicates(configManager)])\n .then(([result, scopeResult]) => {\n if (!result) {\n notFound(res, 'Suite not found')\n return\n }\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n\n const runs = db.getRunsBySuiteId(suiteId, { limit, offset })\n const total = db.getRunsBySuiteIdCount(suiteId)\n const trends = db.getSuiteTrends(suiteId, { from })\n const allRunsForFlakiness = db.getRunsBySuiteId(suiteId, { limit: 100 })\n const flakyMetrics = calculateFlakyMetrics(allRunsForFlakiness)\n const flakyScore = flakyMetrics.score\n const configured = scopeResult.predicates.length > 0\n const scopedRuns = configured\n ? db.getRunsBySuiteId(suiteId, { limit, offset, attributePredicates: scopeResult.predicates })\n : runs\n const scopedTotal = configured\n ? db.getRunsBySuiteIdCount(suiteId, { attributePredicates: scopeResult.predicates })\n : total\n const scopedTrends = configured\n ? db.getSuiteTrends(suiteId, { from, attributePredicates: scopeResult.predicates })\n : trends\n const scopedRunsForFlakiness = configured\n ? db.getRunsBySuiteId(suiteId, { limit: 100, attributePredicates: scopeResult.predicates })\n : allRunsForFlakiness\n const scopedFlakyScore = calculateFlakyMetrics(scopedRunsForFlakiness).score\n\n json(res, {\n suiteId,\n runs,\n total,\n trends,\n isFlaky: flakyScore >= 0.4 && flakyMetrics.statusCount >= 3,\n flakyScore,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount: scopedTotal,\n totalCount: total,\n },\n ...(configured ? {\n scopedRuns,\n scopedTrends,\n scopedFlakyScore,\n } : {}),\n })\n })\n .catch(() => notFound(res, 'Suite not found'))\n return\n }\n\n // GET /api/analytics/breakdowns\n if (path === '/api/analytics/breakdowns' && req.method === 'GET') {\n const dimension = url.searchParams.get('dimension')\n if (dimension !== 'test' && dimension !== 'suite' && dimension !== 'platform') {\n json(res, { error: 'dimension must be one of: test, suite, platform' }, 400)\n return\n }\n\n const limitResult = parseBoundedIntegerQueryParam(url.searchParams.get('limit'), 'limit', 1, 100, 25)\n if (!limitResult.ok) {\n json(res, { error: limitResult.error }, 400)\n return\n }\n\n const fromResult = parseIsoDateQueryParam(url.searchParams.get('from'), 'from')\n if (!fromResult.ok) {\n json(res, { error: fromResult.error }, 400)\n return\n }\n\n const toResult = parseIsoDateQueryParam(url.searchParams.get('to'), 'to')\n if (!toResult.ok) {\n json(res, { error: toResult.error }, 400)\n return\n }\n\n const scope = url.searchParams.get('scope') ?? undefined\n if (scope !== undefined && scope !== 'passRate') {\n json(res, { error: 'scope must be passRate when provided' }, 400)\n return\n }\n\n void readAnalyticsScopePredicates(configManager)\n .then(async (scopeResult) => {\n if (!scopeResult.ok) {\n json(res, { error: scopeResult.error }, 400)\n return\n }\n\n const configured = scopeResult.predicates.length > 0\n const attributePredicates = scope === 'passRate' && configured ? scopeResult.predicates : undefined\n const rows = db.getInsightsBreakdown(dimension as InsightsBreakdownDimension, {\n from: fromResult.value,\n to: toResult.value,\n limit: limitResult.value,\n attributePredicates,\n })\n const scopedCount = configured\n ? db.getInsightsBreakdown(dimension as InsightsBreakdownDimension, {\n from: fromResult.value,\n to: toResult.value,\n limit: 100,\n attributePredicates: scopeResult.predicates,\n }).reduce((sum, row) => sum + row.runs, 0)\n : 0\n const totalCount = db.getInsightsBreakdown(dimension as InsightsBreakdownDimension, {\n from: fromResult.value,\n to: toResult.value,\n limit: 100,\n }).reduce((sum, row) => sum + row.runs, 0)\n const payload = {\n dimension,\n rows,\n scope: {\n configured,\n predicates: scopeResult.predicates,\n scopedCount,\n totalCount,\n },\n }\n\n if (dimension !== 'suite' || !suiteFileManager) {\n json(res, payload)\n return\n }\n\n const files = await suiteFileManager.list()\n const suiteNames = new Map(\n files\n .filter((file) => typeof file.suiteId === 'string' && file.suiteId.length > 0)\n .map((file) => [file.suiteId as string, file.name]),\n )\n\n json(res, {\n ...payload,\n rows: rows.map((row) => ({\n ...row,\n label: row.suiteId ? (suiteNames.get(row.suiteId) ?? row.label) : row.label,\n })),\n })\n })\n .catch(() => {\n json(res, { error: 'Unable to read analytics breakdown scope' }, 500)\n })\n return\n }\n\n // GET /api/app-metadata — return narrow non-sensitive app metadata\n if (path === '/api/app-metadata' && req.method === 'GET') {\n const version = getAgentQaVersion().trim() || '0.0.0'\n json(res, { version })\n return\n }\n\n // GET /api/config/targets — return registered target names\n if (path === '/api/config/targets' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const config = await configManager.read()\n const configObj = config as Record<string, unknown>\n const registry = configObj.registry as Record<string, unknown> | undefined\n const targets = registry?.targets as Record<string, unknown> | undefined\n const names = targets ? Object.keys(targets) : []\n json(res, { targets: names })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read targets' }, 500)\n }\n })()\n return\n }\n\n // GET /api/config — return masked config with active provider info\n if (path === '/api/config' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const config = await configManager.readMasked()\n const configObj = config as Record<string, unknown>\n const registry = configObj.registry as Record<string, unknown> | undefined\n const llms = (registry?.llms ?? configObj.llms) as Array<Record<string, unknown>> | undefined\n const use = configObj.use as Record<string, unknown> | undefined\n const activeLlm = (use?.llm ?? configObj.defaultLLM) as string | undefined\n const defaultCfg = llms?.find((c) => c.name === activeLlm)\n const provider = (defaultCfg?.provider as string) ?? null\n json(res, { config, provider })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read config' }, 500)\n }\n })()\n return\n }\n\n // PUT /api/config/llms — update registry.llms array + use.llm\n if (path === '/api/config/llms' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ llms: unknown[]; defaultLLM?: string; activeLlm?: string }>(req)\n .then(async (body) => {\n try {\n if (!Array.isArray(body.llms) || body.llms.length === 0) {\n json(res, { error: 'llms array is required and must not be empty' }, 400)\n return\n }\n const selectedLlm = body.activeLlm ?? body.defaultLLM\n const errors: string[] = []\n const names: string[] = []\n const sanitizedArray: Array<ReturnType<typeof NamedLLMConfigSchema.parse>> = []\n for (const item of body.llms) {\n const result = NamedLLMConfigSchema.safeParse(item)\n if (!result.success) {\n for (const issue of result.error.issues) {\n errors.push(`${issue.path.join('.')}: ${issue.message}`)\n }\n } else {\n names.push(result.data.name)\n sanitizedArray.push(result.data)\n }\n }\n const dupes = names.filter((n, i) => names.indexOf(n) !== i)\n if (dupes.length > 0) {\n errors.push(`Duplicate config names: ${[...new Set(dupes)].join(', ')}`)\n }\n if (!selectedLlm || !names.includes(selectedLlm)) {\n errors.push(`use.llm \"${selectedLlm}\" does not match any name in registry.llms`)\n }\n if (errors.length > 0) {\n json(res, { error: 'Validation failed', details: errors }, 400)\n return\n }\n await configManager.replaceSectionRaw('registry.llms', sanitizedArray)\n await configManager.replaceSectionRaw('use.llm', selectedLlm)\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update LLM config' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // PUT /api/config/default-llm — switch active LLM (use.llm)\n if (path === '/api/config/default-llm' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ defaultLLM?: string; llm?: string }>(req)\n .then(async (body) => {\n try {\n const llmName = body.llm ?? body.defaultLLM\n if (!llmName || typeof llmName !== 'string') {\n json(res, { error: 'use.llm string is required' }, 400)\n return\n }\n const config = await configManager.readMasked()\n const configObj = config as Record<string, unknown>\n const registry = configObj.registry as Record<string, unknown> | undefined\n const llms = (registry?.llms ?? configObj.llms) as Array<Record<string, unknown>> | undefined\n const names = (llms ?? []).map((c) => c.name as string)\n if (!names.includes(llmName)) {\n json(res, { error: `use.llm \"${llmName}\" does not match any name in registry.llms` }, 400)\n return\n }\n await configManager.replaceSectionRaw('use.llm', llmName)\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update use.llm' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // POST /api/config/farm/test-connection — test farm provider credentials\n if (path === '/api/config/farm/test-connection' && req.method === 'POST') {\n readJsonBody<{ provider: string; username: string; accessKey: string }>(req)\n .then(async (body) => {\n if (body.provider !== 'browserstack') {\n json(res, { error: 'Only BrowserStack is currently supported' }, 400)\n return\n }\n try {\n const auth = Buffer.from(`${body.username}:${body.accessKey}`).toString('base64')\n const response = await fetch('https://api-cloud.browserstack.com/app-automate/devices.json', {\n headers: { Authorization: `Basic ${auth}` },\n })\n if (response.ok) {\n json(res, { success: true })\n } else if (response.status === 401) {\n json(res, { success: false, error: 'Invalid credentials' })\n } else {\n json(res, { success: false, error: `BrowserStack API returned ${response.status}` })\n }\n } catch (err) {\n json(res, { success: false, error: err instanceof Error ? err.message : 'Connection failed' })\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // PUT /api/config/settings — update config sections\n if (path === '/api/config/settings' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<Record<string, unknown>>(req)\n .then(async (body) => {\n try {\n const sectionValidators: Record<string, { safeParse: (v: unknown) => ConfigSectionValidationResult }> = {\n 'use.timeout': TimeoutConfigSchema,\n 'use.healing': HealingConfigSchema,\n 'use.planner': PlannerConfigSchema,\n 'use.logCapture': LogCaptureConfigSchema,\n 'use.browser': BrowserConfigSchema,\n 'use.browser.headless': BrowserConfigSchema.shape.headless,\n 'services.memory': ServicesSchema.shape.memory,\n 'services.cache': CacheConfigSchema,\n 'services.logging': LoggingConfigSchema,\n 'services.recording': RecordingConfigSchema,\n 'services.accessibility': AccessibilityConfigSchema,\n 'services.dashboard': DashboardConfigSchema,\n 'services.mcp': McpConfigSchema,\n 'registry.targets': RegistrySchema.shape.targets,\n 'registry.devices': RegistrySchema.shape.devices,\n 'registry.providers': RegistrySchema.shape.providers,\n 'analytics.passRateScope': { safeParse: validateAnalyticsPassRateScope },\n 'workspace.testMatch': WorkspaceSchema.shape.testMatch,\n 'workspace.suiteMatch': WorkspaceSchema.shape.suiteMatch,\n 'workspace.hooksFile': WorkspaceSchema.shape.hooksFile,\n 'workspace.agentRules': WorkspaceSchema.shape.agentRules,\n 'workspace.envFile': WorkspaceSchema.shape.envFile,\n 'workspace.secretsFile': WorkspaceSchema.shape.secretsFile,\n 'use.mobile': UseSchema.shape.mobile,\n 'use.mobile.appState': MobileAppStateSchema,\n 'use.parallel': UseSchema.shape.parallel,\n }\n const objectSections = [\n 'use.timeout',\n 'use.healing',\n 'use.planner',\n 'use.logCapture',\n 'use.browser',\n 'use.mobile',\n 'services.memory',\n 'services.cache',\n 'services.logging',\n 'services.recording',\n 'services.accessibility',\n 'services.dashboard',\n 'services.mcp',\n 'registry.targets',\n 'registry.devices',\n 'registry.providers',\n 'analytics.passRateScope',\n ] as const\n const arraySections = ['workspace.testMatch', 'workspace.testPathIgnore', 'workspace.suiteMatch', 'registry.llms'] as const\n const scalarSections = [\n 'workspace.agentRules',\n 'workspace.hooksFile',\n 'workspace.envFile',\n 'workspace.secretsFile',\n 'use.llm',\n 'use.mobile.appState',\n 'use.browser.headless',\n 'use.parallel',\n ] as const\n\n const currentConfig = await configManager.read()\n const currentUse = isRecord(currentConfig.use) ? currentConfig.use : {}\n const currentBrowser = isRecord(currentUse.browser) ? currentUse.browser : {}\n const currentHasRootHeadless = typeof currentUse.headless === 'boolean'\n const currentHasBrowserHeadless = typeof currentBrowser.headless === 'boolean'\n const requestHasRootHeadless = Object.prototype.hasOwnProperty.call(body, 'use.headless')\n const requestHasBrowserHeadlessScalar = Object.prototype.hasOwnProperty.call(body, 'use.browser.headless')\n const requestBrowserBlock = body['use.browser']\n const requestHasBrowserHeadlessObject = isRecord(requestBrowserBlock) && typeof requestBrowserBlock.headless === 'boolean'\n if (\n currentHasRootHeadless\n && !currentHasBrowserHeadless\n && !requestHasBrowserHeadlessScalar\n && !requestHasBrowserHeadlessObject\n ) {\n body['use.browser.headless'] = currentUse.headless\n }\n\n const allowedSettingsPaths = new Set<string>([\n ...Object.keys(sectionValidators),\n ...objectSections,\n ...arraySections,\n ...scalarSections,\n 'use.headless',\n ])\n const unsupportedKeys = Object.keys(body).filter((key) => !allowedSettingsPaths.has(key))\n if (unsupportedKeys.length > 0) {\n json(res, { error: 'Unsupported setting path', details: unsupportedKeys }, 400)\n return\n }\n\n const errors: string[] = []\n for (const [section, validator] of Object.entries(sectionValidators)) {\n const value = body[section]\n if (value !== undefined) {\n const result = validator.safeParse(value)\n if (!result.success) {\n for (const issue of result.error!.issues) {\n const path = issue.path.length ? `${section}.${issue.path.map(String).join('.')}` : section\n errors.push(`${path}: ${issue.message}`)\n }\n }\n }\n }\n\n if (Array.isArray(body['registry.llms'])) {\n for (const [idx, item] of (body['registry.llms'] as unknown[]).entries()) {\n const result = NamedLLMConfigSchema.safeParse(item)\n if (!result.success) {\n for (const issue of result.error!.issues) {\n const p = issue.path.length ? `registry.llms[${idx}].${issue.path.join('.')}` : `registry.llms[${idx}]`\n errors.push(`${p}: ${issue.message}`)\n }\n }\n }\n }\n\n if (errors.length > 0) {\n json(res, { error: 'Validation failed', details: errors }, 400)\n return\n }\n\n for (const section of objectSections) {\n if (body[section] && typeof body[section] === 'object') {\n await configManager.replaceSection(section, body[section] as Record<string, unknown>)\n }\n }\n for (const section of arraySections) {\n if (body[section] !== undefined) {\n await configManager.replaceSectionRaw(section, body[section])\n }\n }\n for (const section of scalarSections) {\n if (body[section] !== undefined) {\n await configManager.replaceSectionRaw(section, body[section])\n }\n }\n if (currentHasRootHeadless || requestHasRootHeadless) {\n await configManager.deleteSectionRaw('use.headless')\n }\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update settings' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // DELETE /api/auth/:configName — remove stored credential\n if (path.startsWith('/api/auth/') && req.method === 'DELETE') {\n const segments = path.split('/')\n if (segments.length === 4 && segments[2] === 'auth') {\n const providerName = decodeURIComponent(segments[3])\n if (providerName === 'status' || providerName === 'credential' || providerName === 'oauth') {\n // Fall through to other handlers\n } else {\n ;(async () => {\n try {\n await removeAuth(providerName)\n json(res, { deleted: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete credential' }, 500)\n }\n })()\n return\n }\n }\n }\n\n // GET /api/auth/status — return credential info from auth store\n if (path === '/api/auth/status' && req.method === 'GET') {\n ;(async () => {\n try {\n const credentials: Array<{\n type: string\n provider: string\n configName: string\n expires: number | null\n source: string\n }> = []\n const store = await readAuth() as Record<string, DashboardAuthCredential>\n for (const [key, cred] of Object.entries(store)) {\n if (cred) {\n let provider = cred.provider ?? key\n if (cred.type === 'oauth') {\n provider = toProductProviderLabel(provider)\n } else if (cred.type === 'bearer') {\n provider = cred.provider\n }\n credentials.push({\n type: cred.type,\n provider,\n configName: key,\n expires: cred.type === 'oauth' ? cred.tokens.expires : null,\n source: 'auth-store',\n })\n }\n }\n json(res, { credentials })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read auth status' }, 500)\n }\n })()\n return\n }\n\n // GET /api/llm/providers — built-in and plugin-provided LLM provider metadata\n if (path === '/api/llm/providers' && req.method === 'GET') {\n json(res, {\n providers: [\n ...builtinLLMProviderMetadata(),\n ...listLLMAuthProviderPlugins().map(serializeAuthProviderPlugin),\n ],\n })\n return\n }\n\n if (path.startsWith('/api/auth/plugin/')) {\n pruneExpiredPluginOAuthSessions(pluginOAuthSessions)\n const segments = path.split('/')\n const provider = segments.length >= 6 ? decodeURIComponent(segments[4] ?? '') : ''\n const action = segments.length >= 6 ? segments[5] : ''\n const plugin = provider ? getLLMAuthProviderPlugin(provider) : undefined\n\n if (!plugin) {\n json(res, { error: `Auth plugin provider \"${provider}\" is not registered` }, 404)\n return\n }\n\n if (action === 'start' && req.method === 'POST') {\n readJsonBody<{ configName?: string; callbackUrl?: string }>(req)\n .then(async (body) => {\n if (!plugin.startAuth) {\n json(res, { error: `Provider \"${provider}\" does not support dashboard auth start` }, 400)\n return\n }\n\n try {\n const target = await requirePluginAuthConfig(configManager, body.configName, plugin)\n if (!target.ok) {\n json(res, { error: target.error }, 400)\n return\n }\n const started = await plugin.startAuth({\n configName: target.configName,\n callbackUrl: typeof body.callbackUrl === 'string' ? body.callbackUrl : undefined,\n })\n const sessionId = randomUUID()\n const session: PluginOAuthSession = {\n providerId: plugin.providerId,\n credentialProviderId: plugin.credentialProviderId,\n configName: target.configName,\n sessionState: started.sessionState,\n cleanup: started.cleanup,\n status: 'pending',\n expiresAt: Date.now() + PLUGIN_OAUTH_SESSION_TTL_MS,\n }\n pluginOAuthSessions.set(sessionId, session)\n\n if (started.waitForTokens) {\n started.waitForTokens\n .then(async (tokens: OAuthTokens) => {\n await writeDashboardAuth(target.configName, {\n type: 'oauth',\n provider: plugin.credentialProviderId,\n tokens,\n })\n session.status = 'completed'\n })\n .catch((err: unknown) => {\n session.status = 'error'\n session.error = err instanceof Error ? err.message : 'Authentication failed'\n })\n .finally(() => cleanupPluginOAuthSession(session))\n }\n\n json(res, {\n authorizeUrl: started.authorizeUrl,\n sessionId,\n mode: plugin.dashboardAuth.mode,\n })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to start auth plugin flow' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n if (action === 'result' && req.method === 'GET') {\n const sessionId = url.searchParams.get('session') ?? ''\n const session = pluginOAuthSessions.get(sessionId)\n if (!session || session.providerId !== provider) {\n json(res, { error: 'Auth session not found' }, 404)\n return\n }\n if (session.status === 'completed') {\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { status: 'completed', saved: true })\n return\n }\n if (session.status === 'error') {\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { status: 'error', error: session.error ?? 'Authentication failed' })\n return\n }\n json(res, { status: 'pending' })\n return\n }\n\n if (action === 'exchange' && req.method === 'POST') {\n readJsonBody<{ sessionId?: string; code?: string }>(req)\n .then(async (body) => {\n if (!plugin.exchangeCode) {\n json(res, { error: `Provider \"${provider}\" does not support code exchange` }, 400)\n return\n }\n const sessionId = typeof body.sessionId === 'string' ? body.sessionId.trim() : ''\n const code = typeof body.code === 'string' ? body.code.trim() : ''\n if (!sessionId || !code) {\n json(res, { error: 'sessionId and code are required' }, 400)\n return\n }\n const session = pluginOAuthSessions.get(sessionId)\n if (!session || session.providerId !== provider) {\n json(res, { error: 'Auth session not found' }, 404)\n return\n }\n if (session.status !== 'pending') {\n json(res, { error: 'Auth session is no longer pending' }, 409)\n return\n }\n\n try {\n const tokens = await plugin.exchangeCode({\n code,\n sessionState: session.sessionState,\n })\n await writeDashboardAuth(session.configName, {\n type: 'oauth',\n provider: session.credentialProviderId,\n tokens,\n })\n session.status = 'completed'\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { status: 'completed', saved: true })\n } catch (err: unknown) {\n session.status = 'error'\n session.error = err instanceof Error ? err.message : 'Token exchange failed'\n cleanupPluginOAuthSession(session)\n pluginOAuthSessions.delete(sessionId)\n json(res, { error: session.error }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n json(res, { error: 'Auth plugin route not found' }, 404)\n return\n }\n\n // POST /api/auth/credential — store typed credentials from dashboard\n if (path === '/api/auth/credential' && req.method === 'POST') {\n readJsonBody<{\n configName?: string\n provider?: string\n type?: string\n secret?: string\n }>(req)\n .then(async (body) => {\n const provider = typeof body.provider === 'string' ? body.provider.trim() : ''\n const credentialType = typeof body.type === 'string' ? body.type.trim() : ''\n const secret = typeof body.secret === 'string' ? body.secret.trim() : ''\n\n if (typeof body.configName !== 'string' || body.configName.trim() === '') {\n json(res, { error: 'configName is required' }, 400)\n return\n }\n if (!provider || !isKnownLLMProvider(provider)) {\n json(res, { error: 'valid provider is required' }, 400)\n return\n }\n if (credentialType !== 'api-key' && credentialType !== 'bearer-token') {\n json(res, { error: 'type must be api-key or bearer-token' }, 400)\n return\n }\n if (!secret) {\n json(res, { error: 'secret is required' }, 400)\n return\n }\n\n if (getLLMAuthProviderPlugin(provider)) {\n json(res, { error: 'Subscription providers use OAuth login' }, 400)\n return\n }\n\n if (credentialType === 'bearer-token' && provider !== 'anthropic-compatible') {\n json(res, { error: 'bearer-token credentials are only supported for anthropic-compatible configs' }, 400)\n return\n }\n\n if (credentialType === 'api-key' && !API_KEY_CREDENTIAL_PROVIDERS.has(provider)) {\n json(res, { error: 'api-key credentials are not supported for this provider' }, 400)\n return\n }\n\n try {\n const target = await requireCredentialConfig(configManager, body.configName, provider)\n if (!target.ok) {\n json(res, { error: target.error }, 400)\n return\n }\n\n if (credentialType === 'bearer-token') {\n await writeDashboardAuth(target.configName, { type: 'bearer', provider, token: secret })\n } else {\n await writeDashboardAuth(target.configName, { type: 'api', provider, key: secret })\n }\n json(res, { saved: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to save credential' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // POST /api/llm/test — test LLM connection\n if (path === '/api/llm/test' && req.method === 'POST') {\n readJsonBody<{\n configName?: string\n provider?: string\n model?: string\n baseURL?: string\n providerHeaders?: Record<string, string>\n }>(req)\n .then(async (body) => {\n const rawBody = body as Record<string, unknown>\n if ('apiKey' in rawBody) {\n json(res, {\n success: false,\n error: 'invalid_request',\n message: 'apiKey is not accepted in LLM test requests. Save credentials for the named config instead.',\n }, 400)\n return\n }\n const providerName = typeof body.provider === 'string' ? body.provider.trim() : ''\n const modelName = typeof body.model === 'string' ? body.model.trim() : ''\n if (!providerName || !modelName) {\n json(res, { success: false, error: 'invalid_request', message: 'provider and model are required' }, 400)\n return\n }\n const configName = typeof body.configName === 'string' ? body.configName.trim() : ''\n\n const llmCandidate: Record<string, unknown> = {\n provider: providerName,\n model: modelName,\n }\n if (typeof body.baseURL === 'string') {\n llmCandidate.baseURL = body.baseURL\n }\n if (body.providerHeaders !== undefined) {\n llmCandidate.providerHeaders = body.providerHeaders\n }\n\n const parsedConfig = ModelConfigSchema.safeParse(llmCandidate)\n if (!parsedConfig.success) {\n json(res, {\n success: false,\n error: 'invalid_request',\n message: parsedConfig.error.issues\n .map((issue: { path: PropertyKey[]; message: string }) => `${issue.path.map(String).join('.') || 'config'}: ${issue.message}`)\n .join('; '),\n }, 400)\n return\n }\n\n const start = Date.now()\n const llmConfig = parsedConfig.data\n const coreAuth = await import('@vostride/agent-qa-core') as typeof import('@vostride/agent-qa-core') & {\n resolveLLMAuth: (name: string, config: typeof llmConfig) => Promise<\n | { kind: 'api-key'; apiKey: string }\n | { kind: 'bearer-token'; token: string }\n | { kind: 'auth-fetch'; fetch: typeof globalThis.fetch; modelAdapter: 'openai-responses' | 'anthropic-messages' }\n | { kind: 'unauthenticated'; message: string }\n | { kind: 'missing'; message: string }\n >\n }\n const resolvedAuth = await coreAuth.resolveLLMAuth(configName, llmConfig)\n if (resolvedAuth.kind === 'missing') {\n json(res, {\n success: false,\n error: 'missing_credential',\n message: resolvedAuth.message,\n })\n return\n }\n\n const modelConfig: Record<string, unknown> = { ...llmConfig }\n let unauthenticated = false\n let authMessage: string | undefined\n\n if (resolvedAuth.kind === 'api-key') {\n modelConfig.apiKey = resolvedAuth.apiKey\n } else if (resolvedAuth.kind === 'bearer-token') {\n modelConfig.authToken = resolvedAuth.token\n } else if (resolvedAuth.kind === 'auth-fetch') {\n modelConfig.fetch = resolvedAuth.fetch\n modelConfig.modelAdapter = resolvedAuth.modelAdapter\n } else if (resolvedAuth.kind === 'unauthenticated') {\n unauthenticated = true\n authMessage = resolvedAuth.message\n }\n\n try {\n const { createModel } = await import('@vostride/agent-qa-core')\n const model = await createModel(modelConfig as unknown as Parameters<typeof createModel>[0])\n\n const testProviderOpts = getProviderOptions(modelConfig as unknown as Parameters<typeof getProviderOptions>[0])\n const connectionTimeoutMs = llmConnectionTestTimeoutMs(llmConfig)\n\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), connectionTimeoutMs)\n try {\n const { generateText } = await import('ai')\n await generateText({\n model,\n prompt: 'Say \"ok\"',\n abortSignal: controller.signal,\n providerOptions: testProviderOpts,\n })\n } finally {\n clearTimeout(timeout)\n }\n\n json(res, {\n success: true,\n model: modelName,\n provider: providerName,\n timeoutMs: connectionTimeoutMs,\n responseTime: Date.now() - start,\n ...(unauthenticated ? { unauthenticated: true, message: authMessage ?? LLM_TEST_UNAUTHENTICATED_MESSAGE } : {}),\n })\n } catch (err: unknown) {\n const connectionTimeoutMs = llmConnectionTestTimeoutMs(llmConfig)\n const { message: providerMessage, statusCode } = extractProviderErrorMessage(err)\n const errorCategory = classifyProviderError(providerMessage, statusCode)\n const message = publicLLMTestMessage(errorCategory, providerMessage)\n\n json(res, {\n success: false,\n error: errorCategory,\n message,\n timeoutMs: connectionTimeoutMs,\n ...(statusCode ? { statusCode } : {}),\n ...(message !== providerMessage ? { details: providerMessage } : {}),\n ...(unauthenticated ? { unauthenticated: true, authMessage: authMessage ?? LLM_TEST_UNAUTHENTICATED_MESSAGE } : {}),\n })\n }\n })\n .catch(() => json(res, { success: false, error: 'invalid_request', message: 'Invalid request body' }, 400))\n return\n }\n\n // POST /api/cache/purge — purge cached action plans for a test or all tests\n if (path === '/api/cache/purge' && req.method === 'POST') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 503)\n return\n }\n readJsonBody<{ file?: string; all?: boolean }>(req)\n .then(async (body) => {\n if (!body.file && !body.all) {\n json(res, { error: 'Either file or all is required' }, 400)\n return\n }\n try {\n const cfg = await configManager.read()\n const targetPlatforms = getTargetPlatformMap(cfg)\n const cacheDir = (cfg as {\n services?: { cache?: { dir?: string } }\n cache?: { dir?: string }\n }).services?.cache?.dir\n ?? (cfg as { cache?: { dir?: string } }).cache?.dir\n if (!cacheDir) {\n json(res, { error: 'Cache directory not configured' }, 400)\n return\n }\n if (body.file) {\n // Read raw config file content for cache key scoping\n let configContent = ''\n if (deps.configPath) {\n try { configContent = await readFile(deps.configPath, 'utf-8') } catch { /* best-effort */ }\n }\n const resolvedPath = (await normalizeDashboardWorkspacePath(body.file, workspacePaths, 'test')).executionPath\n const content = await readFile(resolvedPath, 'utf-8')\n const doc = parseYaml(content)\n const metadata = extractTestFileMetadata(content)\n const platform = resolveEffectivePlatform(\n metadata.platform,\n metadata.targetName,\n targetPlatforms,\n 'web',\n ) ?? 'web'\n const steps: string[] = (doc.steps ?? []).map((s: unknown) =>\n typeof s === 'string' ? s : (s as Record<string, string>).step,\n )\n const configDir = deps.configPath ? dirname(resolve(deps.configPath)) : process.cwd()\n const resolvedCacheDir = resolve(configDir, cacheDir)\n let purged = 0\n for (const step of steps) {\n const stepHash = hashStepInstruction(step, platform, configContent, content)\n const dirPath = join(resolvedCacheDir, stepHash)\n try {\n await stat(dirPath)\n await rm(dirPath, { recursive: true, force: true })\n purged++\n } catch {\n // directory doesn't exist — skip\n }\n }\n json(res, { purged })\n } else {\n const configDir = deps.configPath ? dirname(resolve(deps.configPath)) : process.cwd()\n const resolvedDir = resolve(configDir, cacheDir)\n let entries: string[]\n try {\n entries = await readdir(resolvedDir)\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { purged: 0 })\n return\n }\n throw err\n }\n for (const entry of entries) {\n await rm(join(resolvedDir, entry), { recursive: true, force: true })\n }\n json(res, { purged: entries.length })\n }\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Cache purge failed' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // Agent Rules API\n if (path === '/api/agent-rules' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content: string\n try {\n content = await readFile(workspacePaths.agentRules.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { content: null, filePath: workspacePaths.agentRules.workspaceRelativePath, error: 'workspace.agentRules file_not_found' }, 500)\n return\n }\n throw err\n }\n json(res, { content, filePath: workspacePaths.agentRules.workspaceRelativePath })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read agent rules' }, 500)\n }\n })()\n return\n }\n\n // Hooks API\n if (path === '/api/hooks' && req.method === 'GET') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n json(res, await hookRegistryManager.readCatalog())\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read hooks' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/hooks' && req.method === 'POST') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody(req)\n .then(async (body) => {\n try {\n const result = await hookRegistryManager.createHook(body as import('../hooks/hook-registry-types.js').HookMutationRequest)\n json(res, result, 201)\n } catch (err: unknown) {\n if (isHookRegistryMutationError(err) && err.code === 'validation_failed') {\n json(res, { error: 'validation_failed', fieldErrors: err.fieldErrors }, 400)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to create hook' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n const hookRunMatch = path.match(/^\\/api\\/hooks\\/([^/]+)\\/run$/)\n if (hookRunMatch && req.method === 'POST') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<import('../hooks/hook-registry-types.js').HookRunRequest>(req)\n .then(async (body) => {\n try {\n const validation = validateHookRunRequest(body)\n if (validation.fieldErrors.length > 0) {\n json(res, { error: 'validation_failed', fieldErrors: validation.fieldErrors }, 400)\n return\n }\n\n const hookId = decodeURIComponent(hookRunMatch[1])\n const prepareResult = await hookRegistryManager.prepareForExecution()\n if (prepareResult.hookRegistryError) {\n json(res, { error: 'hook_registry_error', message: prepareResult.hookRegistryError }, 409)\n return\n }\n\n const resolvedHook = prepareResult.resolvedHooks.get(hookId)\n if (!resolvedHook) {\n const detail = await hookRegistryManager.readHook(hookId)\n if (!detail) {\n notFound(res, 'Hook not found')\n return\n }\n\n const fieldErrors = prepareResult.authoringIssuesById.get(hookId) ?? detail.fieldErrors\n if (fieldErrors.length > 0) {\n json(res, { error: 'hook_not_runnable', fieldErrors }, 409)\n return\n }\n\n json(res, { error: 'hook_not_runnable', message: 'Hook is not executable' }, 409)\n return\n }\n\n const workspaceEnv = await readWorkspaceEnvVars(workspacePaths)\n const result = await runHookInSandbox(resolvedHook, {\n envVars: {\n ...workspaceEnv,\n ...validation.overrides,\n },\n })\n const networkLogs = summarizeHookNetworkLogs(\n (result as { networkLogs?: Array<{ url: string; method: string; status: number; startTime: number; endTime: number }> }).networkLogs,\n )\n\n json(res, sanitizeAuthStateForResponse({\n success: result.success,\n status: result.success ? 'passed' : 'failed',\n executedAt: new Date().toISOString(),\n duration: result.duration,\n output: result.output,\n stdout: result.stdout,\n stderr: result.stderr,\n error: result.error ?? null,\n variables: result.variables,\n sandbox: {\n runtime: resolvedHook.runtime,\n image: RUNTIME_IMAGE_MAP[resolvedHook.runtime],\n networkMode: resolvedHook.network ? 'enabled' : 'disabled',\n dockerVersion: null,\n networkLogsAvailable: networkLogs.length > 0,\n networkLogs,\n },\n } satisfies import('../hooks/hook-registry-types.js').HookRunResponse))\n } catch (err: unknown) {\n json(res, sanitizeAuthStateForResponse({ error: err instanceof Error ? err.message : 'Failed to run hook' }), 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n const hookDetailMatch = path.match(/^\\/api\\/hooks\\/([^/]+)$/)\n if (hookDetailMatch && req.method === 'GET') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const detail = await hookRegistryManager.readHook(decodeURIComponent(hookDetailMatch[1]))\n if (!detail) {\n notFound(res, 'Hook not found')\n return\n }\n json(res, detail)\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read hook' }, 500)\n }\n })()\n return\n }\n\n if (hookDetailMatch && req.method === 'PUT') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody(req)\n .then(async (body) => {\n try {\n const result = await hookRegistryManager.updateHook(\n decodeURIComponent(hookDetailMatch[1]),\n body as import('../hooks/hook-registry-types.js').HookMutationRequest,\n )\n json(res, result)\n } catch (err: unknown) {\n if (isHookRegistryMutationError(err) && err.code === 'hook_not_found') {\n notFound(res, 'Hook not found')\n return\n }\n if (isHookRegistryMutationError(err) && err.code === 'validation_failed') {\n json(res, { error: 'validation_failed', fieldErrors: err.fieldErrors }, 400)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to update hook' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n if (hookDetailMatch && req.method === 'DELETE') {\n const hookRegistryManager = createHookRegistryManager(configManager, deps.configPath)\n if (!hookRegistryManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const result = await hookRegistryManager.deleteHook(\n decodeURIComponent(hookDetailMatch[1]),\n { force: url.searchParams.get('force') === 'true' },\n )\n if (!result.deleted) {\n json(res, { error: 'hook_in_use', references: result.references }, 409)\n return\n }\n json(res, result)\n } catch (err: unknown) {\n if (isHookRegistryMutationError(err) && err.code === 'hook_not_found') {\n notFound(res, 'Hook not found')\n return\n }\n if (isHookRegistryMutationError(err) && err.code === 'validation_failed') {\n json(res, { error: 'validation_failed', fieldErrors: err.fieldErrors }, 400)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete hook' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/agent-rules' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ content: string }>(req)\n .then(async (body) => {\n try {\n if (typeof body.content !== 'string') {\n json(res, { error: 'Missing required field: content' }, 400)\n return\n }\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n await writeFile(workspacePaths.agentRules.absolutePath, body.content, 'utf-8')\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to save agent rules' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n if (path === '/api/agent-rules/create' && req.method === 'POST') {\n if (!configManager || !deps.configPath) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n const configPath = deps.configPath\n readJsonBody<{ fileName?: string }>(req)\n .then(async (body) => {\n try {\n const fileName = typeof body.fileName === 'string' && body.fileName.trim()\n ? body.fileName.trim()\n : 'agent-rules.md'\n if (!isPlainFileName(fileName)) {\n json(res, { error: 'fileName must be a plain file name' }, 400)\n return\n }\n\n const configDir = dirname(configPath)\n const resolvedPath = resolve(configDir, fileName)\n if (!getPathInsideDir(resolvedPath, configDir)) {\n json(res, { error: 'Invalid agent rules path' }, 400)\n return\n }\n\n await writeFile(resolvedPath, '', { encoding: 'utf-8', flag: 'wx' })\n await configManager!.replaceSectionRaw('workspace.agentRules', `./${fileName}`)\n json(res, { created: true, filePath: `./${fileName}` })\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n json(res, { error: 'Agent rules file already exists' }, 409)\n return\n }\n json(res, { error: err instanceof Error ? err.message : 'Failed to create agent rules file' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n // Variables API\n if (path === '/api/variables' && req.method === 'GET') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content: string\n try {\n content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { error: `workspace.envFile not found: ${workspacePaths.envFile.workspaceRelativePath}` }, 500)\n return\n }\n throw err\n }\n const parsed = parseEnvFile(content)\n const variables = Object.entries(parsed).map(([key, value]) => ({ key, value }))\n json(res, { variables, filePath: workspacePaths.envFile.workspaceRelativePath })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read variables' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/variables' && req.method === 'PUT') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n readJsonBody<{ oldKey?: string; key: string; value: string }>(req)\n .then(async (body) => {\n try {\n if (!body.key || typeof body.key !== 'string') {\n json(res, { error: 'Missing required field: key' }, 400)\n return\n }\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(body.key)) {\n json(res, { error: 'Variable names must contain only letters, numbers, and underscores' }, 400)\n return\n }\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content = ''\n try {\n content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { error: `workspace.envFile not found: ${workspacePaths.envFile.workspaceRelativePath}` }, 500)\n return\n }\n throw err\n }\n const vars = parseEnvFile(content)\n if (body.oldKey && body.oldKey !== body.key) {\n delete vars[body.oldKey]\n }\n vars[body.key] = body.value ?? ''\n await writeFile(workspacePaths.envFile.absolutePath, serializeEnvFile(vars), 'utf-8')\n json(res, { updated: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to update variable' }, 500)\n }\n })\n .catch(() => json(res, { error: 'Invalid request body' }, 400))\n return\n }\n\n const varDeleteMatch = path.match(/^\\/api\\/variables\\/(.+)$/)\n if (varDeleteMatch && req.method === 'DELETE') {\n if (!configManager) {\n json(res, { error: 'Config management not available' }, 501)\n return\n }\n ;(async () => {\n try {\n const varKey = decodeURIComponent(varDeleteMatch[1])\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n let content = ''\n try {\n content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n json(res, { error: `workspace.envFile not found: ${workspacePaths.envFile.workspaceRelativePath}` }, 500)\n return\n }\n throw err\n }\n const vars = parseEnvFile(content)\n const existed = varKey in vars\n delete vars[varKey]\n await writeFile(workspacePaths.envFile.absolutePath, serializeEnvFile(vars), 'utf-8')\n json(res, { deleted: existed })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete variable' }, 500)\n }\n })()\n return\n }\n\n // POST /api/live-editor/sessions/:id/auth-state — save auth state from active web Live Mode context\n const liveEditorAuthStateMatch = path.match(/^\\/api\\/live-editor\\/sessions\\/([^/]+)\\/auth-state$/)\n if (liveEditorAuthStateMatch && req.method === 'POST') {\n if (!sessionManager) {\n json(res, { error: 'Live editor not available' }, 503)\n return\n }\n ;(async () => {\n let stateName = ''\n let session: { captureWebAuthState?: (name: string, options: { replace: boolean }) => Promise<unknown>; getState?: () => unknown } | undefined\n try {\n const body = await readJsonBody<{ name?: unknown; replace?: unknown }>(req)\n const parsedName = AuthStateNameSchema.safeParse(typeof body?.name === 'string' ? body.name : '')\n if (!parsedName.success) {\n json(res, { error: 'Auth state name must be a lowercase slug.' }, 400)\n return\n }\n\n stateName = parsedName.data\n session = sessionManager.getSession(decodeURIComponent(liveEditorAuthStateMatch[1]))\n if (!session) {\n notFound(res, 'Session not found')\n return\n }\n\n if (typeof session.captureWebAuthState !== 'function') {\n json(res, {\n error: `Could not save auth state \"${stateName}\" for target \"${getSessionTargetNameForAuthState(session)}\".`,\n }, 500)\n return\n }\n\n const authState = await session.captureWebAuthState(stateName, { replace: body?.replace === true })\n json(res, { authState })\n } catch (err: unknown) {\n const targetName = getSessionTargetNameForAuthState(session)\n const response = buildAuthStateSaveErrorMessage(stateName || 'unknown', targetName, err)\n json(res, { error: response.message }, response.status)\n }\n })()\n return\n }\n\n // POST /api/live-editor/sessions — create a new live editor session\n if (path === '/api/live-editor/sessions' && req.method === 'POST') {\n if (!sessionManager) {\n json(res, { error: 'Live editor not available' }, 503)\n return\n }\n ;(async () => {\n try {\n const body = await readJsonBody<{\n platform?: string\n targetName?: string\n url?: string\n headless?: boolean\n device?: Record<string, unknown>\n useDeviceName?: string\n appState?: string\n bundleId?: string\n appPackage?: string\n appActivity?: string\n setupHooks?: unknown\n teardownHooks?: unknown\n entity?: { type?: string; id?: string }\n }>(req)\n const platform = body?.platform ?? 'web'\n const runtimeLLM = await resolveDashboardRuntimeLLM(configManager, llmConfig, authFetch)\n if (!runtimeLLM.ok) {\n json(res, { error: runtimeLLM.error }, 400)\n return\n }\n const setupHooks = Array.isArray(body?.setupHooks)\n ? body.setupHooks.filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n : []\n const teardownHooks = Array.isArray(body?.teardownHooks)\n ? body.teardownHooks.filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n : []\n // Validate entity (ASVS V5). Only 'suite' | 'test' with a non-empty id\n // are honoured; malformed shapes are silently ignored — client may\n // send {} during the test-editor retrofit before entity threading\n // lands (downgrades to sessionNumber=null instead of a 400 error).\n let entityRef: { type: 'suite' | 'test'; id: string } | undefined\n if (body?.entity && typeof body.entity === 'object') {\n const t = body.entity.type\n const id = body.entity.id\n if ((t === 'suite' || t === 'test') && typeof id === 'string' && id.length > 0) {\n entityRef = { type: t, id }\n }\n }\n let agentRules: string | undefined\n let envVars: Record<string, string> | undefined\n let secretStore: SecretStore | undefined\n let secretRedactor: SecretRedactor | undefined\n let resolvedHooks = new Map<string, import('@vostride/agent-qa-core').HookDefinition>()\n let hookRegistryError: string | undefined\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 500)\n return\n }\n\n try {\n agentRules = await readFile(workspacePaths.agentRules.absolutePath, 'utf-8')\n } catch {\n json(res, { error: `workspace.agentRules file could not be loaded: ${workspacePaths.agentRules.workspaceRelativePath}` }, 400)\n return\n }\n\n try {\n const envContent = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n envVars = parseEnvFile(envContent)\n } catch {\n json(res, { error: `workspace.envFile file could not be loaded: ${workspacePaths.envFile.workspaceRelativePath}` }, 400)\n return\n }\n\n try {\n const secretsContent = await readFile(workspacePaths.secretsFile.absolutePath, 'utf-8')\n secretStore = SecretStore.fromEnvContent(secretsContent)\n secretRedactor = new SecretRedactor(secretStore)\n } catch {\n json(res, { error: `workspace.secretsFile file could not be loaded: ${workspacePaths.secretsFile.workspaceRelativePath}` }, 400)\n return\n }\n\n const hookCatalog = await readWorkspaceHooks(configManager, deps.configPath)\n resolvedHooks = hookCatalog.resolvedHooks\n hookRegistryError = hookCatalog.hookRegistryError\n const { sessionId, sessionNumber } = await sessionManager.createSession(\n {\n platform: platform as 'web' | 'android' | 'ios',\n targetName: typeof body?.targetName === 'string' ? body.targetName : undefined,\n llmConfig: runtimeLLM.llmConfig,\n authFetch: runtimeLLM.authFetch,\n agentRules,\n envVars,\n secretStore,\n secretRedactor,\n setupHooks,\n teardownHooks,\n resolvedHooks,\n hookRegistryError,\n url: body?.url,\n headless: body?.headless ?? false,\n useDeviceName: typeof body?.useDeviceName === 'string' ? body.useDeviceName : undefined,\n appState: body?.appState === 'preserve' || body?.appState === 'reset' ? body.appState : undefined,\n bundleId: typeof body?.bundleId === 'string' ? body.bundleId : undefined,\n appPackage: typeof body?.appPackage === 'string' ? body.appPackage : undefined,\n appActivity: typeof body?.appActivity === 'string' ? body.appActivity : undefined,\n device: body?.device as import('../live-editor/types.js').LiveSessionConfig['device'],\n },\n entityRef,\n )\n json(res, { sessionId, sessionNumber }, 201)\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n json(res, { error: message }, 500)\n }\n })()\n return\n }\n\n // GET /api/live-editor/sessions — list all active live editor sessions\n if (path === '/api/live-editor/sessions' && req.method === 'GET') {\n if (!sessionManager) {\n json(res, { error: 'Live editor not available' }, 503)\n return\n }\n json(res, { sessions: sessionManager.listSessions() })\n return\n }\n\n // DELETE /api/live-editor/sessions/:id — terminate a live editor session\n const liveEditorSessionMatch = path.match(/^\\/api\\/live-editor\\/sessions\\/([^/]+)$/)\n if (liveEditorSessionMatch && req.method === 'DELETE') {\n if (!sessionManager) {\n json(res, { error: 'Live editor not available' }, 503)\n return\n }\n const sessionId = liveEditorSessionMatch[1]\n ;(async () => {\n const terminated = await sessionManager.terminateSession(sessionId)\n if (terminated) {\n json(res, { ok: true })\n } else {\n notFound(res, 'Session not found')\n }\n })()\n return\n }\n\n // Variable suggestions: env keys\n if (path === '/api/variables/env' && req.method === 'GET') {\n if (!configManager) {\n json(res, { keys: [] })\n return\n }\n ;(async () => {\n try {\n if (!workspacePaths) {\n json(res, { error: 'Workspace path resolution not available' }, 503)\n return\n }\n const content = await readFile(workspacePaths.envFile.absolutePath, 'utf-8')\n const parsed = parseEnvFile(content)\n json(res, { keys: Object.keys(parsed) })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read env variables' }, 500)\n }\n })()\n return\n }\n\n // Variable suggestions: hook names\n if (path === '/api/variables/hooks' && req.method === 'GET') {\n ;(async () => {\n try {\n const { hooks } = await readWorkspaceHooks(configManager, deps.configPath)\n json(res, { names: hooks.map((hook) => hook.name) })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read hooks' }, 500)\n }\n })()\n return\n }\n\n // Variable suggestions: captured variable names from prior runs\n const capturedMatch = path.match(/^\\/api\\/variables\\/captured\\/([^/]+)$/)\n if (capturedMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const testId = decodeURIComponent(capturedMatch[1])\n const names = db.getCapturedVariableNames(testId)\n json(res, { names })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read captured variables' }, 500)\n }\n })()\n return\n }\n\n if (path === '/api/memory/catalog' && req.method === 'GET') {\n ;(async () => {\n try {\n json(res, await memoryCatalogManager.readCatalog())\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read memory catalog' }, 500)\n }\n })()\n return\n }\n\n const memoryProductMatch = path.match(/^\\/api\\/memory\\/products\\/([^/]+)$/)\n if (memoryProductMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const productKey = decodeURIComponent(memoryProductMatch[1])\n if (!isValidMemoryScopeId(productKey)) {\n json(res, { error: 'Invalid memory product id' }, 400)\n return\n }\n const product = await memoryCatalogManager.readProductDetail(productKey)\n if (!product) {\n json(res, { error: 'Memory product not found' }, 404)\n return\n }\n json(res, { product })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read memory product' }, 500)\n }\n })()\n return\n }\n\n const memoryScopeMatch = path.match(/^\\/api\\/memory\\/scopes\\/([^/]+)\\/([^/]+)$/)\n if (memoryScopeMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const scope = decodeURIComponent(memoryScopeMatch[1])\n const scopeId = decodeURIComponent(memoryScopeMatch[2])\n if (!isMemoryScope(scope)) {\n json(res, { error: 'Invalid memory scope' }, 400)\n return\n }\n if (!isValidMemoryScopeId(scopeId)) {\n json(res, { error: 'Invalid memory scope id' }, 400)\n return\n }\n const payload = await memoryCatalogManager.readScopedObservations(scope, scopeId)\n if (!payload) {\n json(res, { error: 'Memory scope not found' }, 404)\n return\n }\n json(res, payload)\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read memory scope' }, 500)\n }\n })()\n return\n }\n\n // Memory observations: list for a test\n const obsListMatch = path.match(/^\\/api\\/memory\\/observations\\/([^/]+)$/)\n if (obsListMatch && req.method === 'GET') {\n ;(async () => {\n try {\n const testId = decodeURIComponent(obsListMatch[1])\n const payload = await memoryCatalogManager.readScopedObservations('test', testId)\n json(res, {\n observations: payload?.observations ?? [],\n invalidFiles: payload?.invalidFiles ?? [],\n })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to read observations' }, 500)\n }\n })()\n return\n }\n\n // Memory observations: delete\n const obsDeleteMatch = path.match(/^\\/api\\/memory\\/observations\\/([^/]+)\\/([^/]+)$/)\n if (obsDeleteMatch && req.method === 'DELETE') {\n ;(async () => {\n try {\n const testId = decodeURIComponent(obsDeleteMatch[1])\n const obsId = decodeURIComponent(obsDeleteMatch[2])\n if (!isValidMemoryScopeId(testId) || !isValidMemoryScopeId(obsId)) {\n json(res, { error: 'Invalid memory observation id' }, 400)\n return\n }\n\n const configDir = deps.configPath ? dirname(resolve(deps.configPath)) : process.cwd()\n const cfg = configManager ? await configManager.read().catch(() => undefined) : undefined\n const parsedConfig = AgentQaConfigSchema.safeParse(cfg ?? {})\n const memoryRoot = parsedConfig.success\n ? resolveMemoryRoot(parsedConfig.data, configDir)\n : resolveMemoryRoot(undefined, configDir)\n const testsRoot = join(memoryRoot, 'tests')\n const resolved = resolve(testsRoot, testId, `${obsId}.md`)\n if (!getPathInsideDir(resolved, testsRoot)) {\n json(res, { error: 'Invalid path' }, 400)\n return\n }\n\n await rm(resolved, { force: true })\n json(res, { deleted: true })\n } catch (err: unknown) {\n json(res, { error: err instanceof Error ? err.message : 'Failed to delete observation' }, 500)\n }\n })()\n return\n }\n\n // Unknown API route\n if (path.startsWith('/api/')) {\n notFound(res)\n return\n }\n\n // Non-API routes handled by server.ts (static files)\n notFound(res)\n }\n}\n\nfunction isMemoryScope(value: string): value is MemoryScope {\n return value === 'product' || value === 'suite' || value === 'test'\n}\n","import { readdir, readFile, stat } from 'node:fs/promises'\nimport { dirname, join, resolve, sep } from 'node:path'\n\nimport {\n AgentQaConfigSchema,\n discoverWorkspaceFiles,\n listObservations,\n parseObservation,\n resolveMemoryRoot,\n resolveWorkspacePaths,\n scanContent,\n type BaseObservation,\n type SuiteObservation,\n} from '@vostride/agent-qa-core'\nimport { parse as parseYaml } from 'yaml'\n\nimport type { ConfigManager } from '../config/index.js'\nimport { extractTestFileMetadata } from '../tests/test-file-manager.js'\n\nexport type MemoryScope = 'product' | 'suite' | 'test'\n\ntype MemoryTier = 'products' | 'suites' | 'tests'\ntype MemoryObservation = BaseObservation | SuiteObservation\n\nexport interface MemoryScopeCounts {\n product: number\n suite: number\n test: number\n}\n\nexport interface MemoryCatalogSourceCounts {\n suite: number\n test: number\n}\n\nexport interface MemoryCatalogProduct {\n productKey: string\n observationCount: number\n scopeCounts: MemoryScopeCounts\n targetReferences: string[]\n sourceCounts: MemoryCatalogSourceCounts\n freshness: string | null\n sourceCoverage: number\n}\n\nexport interface MemoryScopeSummary {\n scope: MemoryScope\n observationCount: number\n freshness: string | null\n sourceCoverage: number\n scopeIds: string[]\n}\n\nexport interface MemoryAtlasObservation {\n id: string\n title: string\n content: string\n trust: number\n created: string\n last_confirmed: string\n confirmed_count: number\n contradicted_count: number\n source_test: string\n scope: MemoryScope\n scopeId: string\n}\n\nexport interface MemoryObservationReference {\n kind: 'suite' | 'test' | 'source_test'\n id: string\n label: string\n targetName: string | null\n href: string | null\n}\n\nexport interface MemoryWorkspaceObservation extends MemoryAtlasObservation {\n updated: string\n scopeRef: MemoryObservationReference | null\n sourceTestRef: MemoryObservationReference | null\n}\n\nexport interface MemoryInvalidFile {\n scope: MemoryScope\n scopeId: string\n filename: string\n code: string\n message: string\n}\n\nexport interface MemoryProductDetail extends MemoryCatalogProduct {\n scopes: Record<MemoryScope, MemoryScopeSummary>\n observations: MemoryWorkspaceObservation[]\n invalidFiles: MemoryInvalidFile[]\n}\n\nexport interface MemoryCatalogResponse {\n products: MemoryCatalogProduct[]\n}\n\nexport interface MemoryScopeReadResponse {\n scope: MemoryScope\n scopeId: string\n observations: MemoryObservation[]\n invalidFiles: MemoryInvalidFile[]\n}\n\ninterface MemoryCatalogManagerOptions {\n configManager?: ConfigManager\n configPath?: string\n}\n\ninterface WorkspaceContext {\n workspaceDir: string\n memoryRoot: string\n targetToProduct: Map<string, string>\n productToTargets: Map<string, string[]>\n suiteMetadataById: Map<string, WorkspaceEntityMetadata>\n testMetadataById: Map<string, WorkspaceEntityMetadata>\n}\n\ninterface WorkspaceEntityMetadata {\n id: string\n label: string\n targetName: string | null\n productKey: string | null\n href: string | null\n}\n\ninterface ProductAccumulator {\n productKey: string\n observationCount: number\n scopeCounts: MemoryScopeCounts\n targetReferences: string[]\n freshness: string | null\n sourceTests: Set<string>\n scopes: Record<MemoryScope, ScopeAccumulator>\n observations: MemoryWorkspaceObservation[]\n invalidFiles: MemoryInvalidFile[]\n}\n\ninterface ObservationRecord {\n observation: MemoryObservation\n updated: string\n}\n\ninterface ScopeAccumulator {\n observationCount: number\n freshness: string | null\n sourceTests: Set<string>\n scopeIds: Set<string>\n}\n\nconst MEMORY_SCOPE_TO_TIER: Record<MemoryScope, MemoryTier> = {\n product: 'products',\n suite: 'suites',\n test: 'tests',\n}\n\nconst MEMORY_SCOPE_ORDER: Record<MemoryScope, number> = {\n product: 0,\n suite: 1,\n test: 2,\n}\n\nconst EMPTY_SCOPE_COUNTS: MemoryScopeCounts = {\n product: 0,\n suite: 0,\n test: 0,\n}\n\nexport class MemoryCatalogManager {\n private readonly configManager?: ConfigManager\n private readonly configPath?: string\n\n constructor(options: MemoryCatalogManagerOptions = {}) {\n this.configManager = options.configManager\n this.configPath = options.configPath\n }\n\n async readCatalog(): Promise<MemoryCatalogResponse> {\n const products = await this.readProducts()\n return {\n products: products\n .map((product) => this.toProductSummary(product))\n .sort(compareProducts),\n }\n }\n\n async readProductDetail(productKey: string): Promise<MemoryProductDetail | null> {\n if (!isValidMemoryScopeId(productKey)) {\n return null\n }\n\n const products = await this.readProducts()\n const match = products.find((product) => product.productKey === productKey)\n return match ? this.toProductDetail(match) : null\n }\n\n async readScopedObservations(scope: MemoryScope, scopeId: string): Promise<MemoryScopeReadResponse | null> {\n if (!isValidMemoryScopeId(scopeId)) {\n return null\n }\n\n const { memoryRoot } = await this.loadWorkspaceContext()\n const tierRoot = resolve(join(memoryRoot, MEMORY_SCOPE_TO_TIER[scope]))\n const dir = resolve(join(tierRoot, scopeId))\n if (!dir.startsWith(`${tierRoot}${sep}`)) {\n return null\n }\n\n try {\n const info = await stat(dir)\n if (!info.isDirectory()) {\n return null\n }\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null\n }\n throw error\n }\n\n const context = await this.loadWorkspaceContext()\n const { observations, invalidFiles } = await readObservationDirectory(scope, scopeId, dir)\n\n return {\n scope,\n scopeId,\n observations: observations.map((record) => toMemoryWorkspaceObservation(scope, scopeId, record, context)),\n invalidFiles,\n }\n }\n\n private async readProducts(): Promise<ProductAccumulator[]> {\n const context = await this.loadWorkspaceContext()\n const products = new Map<string, ProductAccumulator>()\n\n await this.collectTier(context.memoryRoot, context.productToTargets, 'products', (scopeId) => scopeId, products, context)\n await this.collectTier(\n context.memoryRoot,\n context.productToTargets,\n 'suites',\n (scopeId) => context.suiteMetadataById.get(scopeId)?.productKey ?? null,\n products,\n context,\n )\n await this.collectTier(\n context.memoryRoot,\n context.productToTargets,\n 'tests',\n (scopeId) => context.testMetadataById.get(scopeId)?.productKey ?? null,\n products,\n context,\n )\n\n return Array.from(products.values())\n }\n\n private async collectTier(\n memoryRoot: string,\n productToTargets: Map<string, string[]>,\n tier: MemoryTier,\n resolveProductKey: (scopeId: string) => string | null,\n products: Map<string, ProductAccumulator>,\n context: WorkspaceContext,\n ): Promise<void> {\n const tierRoot = join(memoryRoot, tier)\n let entries: Array<{ isDirectory(): boolean; name: string }>\n try {\n const dirEntries = await readdir(tierRoot, { withFileTypes: true, encoding: 'utf8' })\n entries = dirEntries.map((entry) => ({\n isDirectory: () => entry.isDirectory(),\n name: String(entry.name),\n }))\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return\n }\n throw error\n }\n\n const scope = tierToScope(tier)\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const scopeId = entry.name\n const productKey = resolveProductKey(scopeId)\n if (!productKey || !isValidMemoryScopeId(productKey)) continue\n\n const { observations, invalidFiles } = await readObservationDirectory(scope, scopeId, join(tierRoot, scopeId))\n if (observations.length === 0 && invalidFiles.length === 0) continue\n\n const accumulator = products.get(productKey) ?? createProductAccumulator(\n productKey,\n productToTargets.get(productKey) ?? [],\n )\n accumulator.invalidFiles.push(...invalidFiles)\n for (const record of observations) {\n const observation = toMemoryWorkspaceObservation(scope, scopeId, record, context)\n accumulator.observationCount += 1\n accumulator.scopeCounts[scope] += 1\n accumulator.freshness = pickFreshest(accumulator.freshness, observation.last_confirmed)\n accumulator.sourceTests.add(observation.source_test)\n accumulator.observations.push(observation)\n\n const scopeAccumulator = accumulator.scopes[scope]\n scopeAccumulator.observationCount += 1\n scopeAccumulator.freshness = pickFreshest(scopeAccumulator.freshness, observation.last_confirmed)\n scopeAccumulator.sourceTests.add(observation.source_test)\n scopeAccumulator.scopeIds.add(scopeId)\n }\n\n products.set(productKey, accumulator)\n }\n }\n\n private async loadWorkspaceContext(): Promise<WorkspaceContext> {\n const workspaceDir = this.configPath ? dirname(resolve(this.configPath)) : process.cwd()\n const config = await this.readConfig()\n const targetToProduct = getTargetToProductMap(config)\n const productToTargets = getProductToTargetsMap(targetToProduct)\n const configResult = AgentQaConfigSchema.safeParse(config)\n const memoryRoot = configResult.success\n ? resolveMemoryRoot(configResult.data, workspaceDir)\n : resolveMemoryRoot(undefined, workspaceDir)\n const workspacePaths = configResult.success\n ? resolveWorkspacePaths({\n config: configResult.data,\n configPath: this.configPath ? resolve(this.configPath) : resolve(workspaceDir, 'agent-qa.config.yaml'),\n })\n : null\n const [testFiles, suiteFiles] = workspacePaths\n ? await Promise.all([\n discoverWorkspaceFiles({ workspace: workspacePaths, kind: 'test' }),\n discoverWorkspaceFiles({ workspace: workspacePaths, kind: 'suite' }),\n ])\n : [[], []]\n\n const testMetadataById = new Map<string, WorkspaceEntityMetadata>()\n for (const file of testFiles) {\n const content = await readFile(file.absolutePath, 'utf-8').catch(() => null)\n if (!content) continue\n const metadata = extractTestFileMetadata(content)\n if (!metadata.testId) continue\n const targetName = metadata.targetName ?? null\n const productKey = targetName ? targetToProduct.get(targetName) ?? null : null\n testMetadataById.set(metadata.testId, {\n id: metadata.testId,\n label: metadata.name?.trim() || metadata.testId,\n targetName,\n productKey,\n href: `/test/${metadata.testId}`,\n })\n }\n\n const suiteMetadataById = new Map<string, WorkspaceEntityMetadata>()\n for (const file of suiteFiles) {\n const content = await readFile(file.absolutePath, 'utf-8').catch(() => null)\n if (!content) continue\n const metadata = extractSuiteFileMetadata(content)\n if (!metadata.suiteId) continue\n const targetName = metadata.targetName ?? null\n const productKey = targetName ? targetToProduct.get(targetName) ?? null : null\n suiteMetadataById.set(metadata.suiteId, {\n id: metadata.suiteId,\n label: metadata.name?.trim() || metadata.suiteId,\n targetName,\n productKey,\n href: `/suite/${metadata.suiteId}`,\n })\n }\n\n return {\n workspaceDir,\n memoryRoot,\n targetToProduct,\n productToTargets,\n suiteMetadataById,\n testMetadataById,\n }\n }\n\n private async readConfig(): Promise<Record<string, unknown>> {\n if (!this.configManager) {\n return {}\n }\n\n try {\n return await this.configManager.read()\n } catch {\n return {}\n }\n }\n\n private toProductSummary(product: ProductAccumulator): MemoryCatalogProduct {\n return {\n productKey: product.productKey,\n observationCount: product.observationCount,\n scopeCounts: { ...product.scopeCounts },\n targetReferences: [...product.targetReferences],\n sourceCounts: {\n suite: product.scopes.suite.scopeIds.size,\n test: product.sourceTests.size,\n },\n freshness: product.freshness,\n sourceCoverage: product.sourceTests.size,\n }\n }\n\n private toProductDetail(product: ProductAccumulator): MemoryProductDetail {\n return {\n ...this.toProductSummary(product),\n scopes: {\n product: toScopeSummary('product', product.scopes.product),\n suite: toScopeSummary('suite', product.scopes.suite),\n test: toScopeSummary('test', product.scopes.test),\n },\n observations: [...product.observations].sort(compareMemoryWorkspaceObservations),\n invalidFiles: [...product.invalidFiles].sort(compareInvalidFiles),\n }\n }\n}\n\nfunction tierToScope(tier: MemoryTier): MemoryScope {\n switch (tier) {\n case 'products':\n return 'product'\n case 'suites':\n return 'suite'\n case 'tests':\n return 'test'\n }\n}\n\nfunction createProductAccumulator(productKey: string, targetReferences: string[]): ProductAccumulator {\n return {\n productKey,\n observationCount: 0,\n scopeCounts: { ...EMPTY_SCOPE_COUNTS },\n targetReferences: [...targetReferences],\n freshness: null,\n sourceTests: new Set<string>(),\n scopes: {\n product: createScopeAccumulator(),\n suite: createScopeAccumulator(),\n test: createScopeAccumulator(),\n },\n observations: [],\n invalidFiles: [],\n }\n}\n\nfunction createScopeAccumulator(): ScopeAccumulator {\n return {\n observationCount: 0,\n freshness: null,\n sourceTests: new Set<string>(),\n scopeIds: new Set<string>(),\n }\n}\n\nfunction toScopeSummary(scope: MemoryScope, accumulator: ScopeAccumulator): MemoryScopeSummary {\n return {\n scope,\n observationCount: accumulator.observationCount,\n freshness: accumulator.freshness,\n sourceCoverage: accumulator.sourceTests.size,\n scopeIds: Array.from(accumulator.scopeIds).sort((left, right) => left.localeCompare(right)),\n }\n}\n\nfunction compareProducts(left: MemoryCatalogProduct, right: MemoryCatalogProduct): number {\n const freshnessCompare = compareFreshness(right.freshness, left.freshness)\n if (freshnessCompare !== 0) {\n return freshnessCompare\n }\n\n const sourceCoverageCompare = right.sourceCoverage - left.sourceCoverage\n if (sourceCoverageCompare !== 0) {\n return sourceCoverageCompare\n }\n\n return left.productKey.localeCompare(right.productKey)\n}\n\nfunction compareFreshness(left: string | null, right: string | null): number {\n if (left === right) return 0\n if (!left) return -1\n if (!right) return 1\n return left.localeCompare(right)\n}\n\nfunction toMemoryWorkspaceObservation(\n scope: MemoryScope,\n scopeId: string,\n record: ObservationRecord,\n context: WorkspaceContext,\n): MemoryWorkspaceObservation {\n const observation = record.observation\n return {\n id: observation.id,\n title: observation.title,\n content: observation.content,\n trust: observation.trust,\n created: observation.created,\n last_confirmed: observation.last_confirmed,\n confirmed_count: observation.confirmed_count,\n contradicted_count: observation.contradicted_count,\n source_test: observation.source_test,\n scope,\n scopeId,\n updated: record.updated,\n scopeRef: resolveScopeReference(scope, scopeId, context),\n sourceTestRef: resolveReference('source_test', context.testMetadataById.get(observation.source_test)),\n }\n}\n\nfunction compareMemoryWorkspaceObservations(left: MemoryWorkspaceObservation, right: MemoryWorkspaceObservation): number {\n const scopeCompare = MEMORY_SCOPE_ORDER[left.scope] - MEMORY_SCOPE_ORDER[right.scope]\n if (scopeCompare !== 0) {\n return scopeCompare\n }\n\n const lastConfirmedCompare = right.last_confirmed.localeCompare(left.last_confirmed)\n if (lastConfirmedCompare !== 0) {\n return lastConfirmedCompare\n }\n\n const createdCompare = right.created.localeCompare(left.created)\n if (createdCompare !== 0) {\n return createdCompare\n }\n\n return left.id.localeCompare(right.id)\n}\n\nfunction compareInvalidFiles(left: MemoryInvalidFile, right: MemoryInvalidFile): number {\n return (\n MEMORY_SCOPE_ORDER[left.scope] - MEMORY_SCOPE_ORDER[right.scope] ||\n left.scopeId.localeCompare(right.scopeId) ||\n left.filename.localeCompare(right.filename)\n )\n}\n\nfunction pickFreshest(current: string | null, candidate: string): string {\n if (!current) return candidate\n return candidate.localeCompare(current) > 0 ? candidate : current\n}\n\nasync function readObservationDirectory(\n scope: MemoryScope,\n scopeId: string,\n dir: string,\n): Promise<{ observations: ObservationRecord[]; invalidFiles: MemoryInvalidFile[] }> {\n const filenames = await listObservations(dir)\n const observations: ObservationRecord[] = []\n const invalidFiles: MemoryInvalidFile[] = []\n\n for (const filename of filenames) {\n const filePath = join(dir, filename)\n const raw = await readFile(filePath, 'utf-8').catch(() => null)\n if (!raw) continue\n\n const parsed = parseObservation(raw, filename)\n if (!parsed.data || parsed.error) {\n invalidFiles.push({\n scope,\n scopeId,\n filename,\n code: 'parse_error',\n message: parsed.error ?? 'Observation file could not be parsed',\n })\n continue\n }\n\n const scanned = scanObservationPayload(parsed.data.title, parsed.data.content)\n if (!scanned.safe) {\n invalidFiles.push({\n scope,\n scopeId,\n filename,\n code: 'security_scan_failed',\n message: `Security scan blocked: ${scanned.matchedPattern}`,\n })\n continue\n }\n\n const fileInfo = await stat(filePath).catch(() => null)\n if (!fileInfo) continue\n\n observations.push({\n observation: parsed.data,\n updated: fileInfo.mtime.toISOString(),\n })\n }\n\n return {\n observations: observations.sort((left, right) => right.observation.last_confirmed.localeCompare(left.observation.last_confirmed)),\n invalidFiles: invalidFiles.sort(compareInvalidFiles),\n }\n}\n\nfunction scanObservationPayload(title: string, content: string) {\n return scanContent([title, content].filter(Boolean).join('\\n'))\n}\n\nfunction getTargetToProductMap(config: Record<string, unknown>): Map<string, string> {\n const registry = (config.registry ?? {}) as {\n targets?: Record<string, { product?: unknown }>\n }\n const map = new Map<string, string>()\n\n for (const [targetName, targetConfig] of Object.entries(registry.targets ?? {})) {\n const productValue = typeof targetConfig?.product === 'string' && targetConfig.product.trim().length > 0\n ? targetConfig.product.trim()\n : targetName\n if (isValidMemoryScopeId(productValue)) {\n map.set(targetName, productValue)\n }\n }\n\n return map\n}\n\nfunction getProductToTargetsMap(targetToProduct: Map<string, string>): Map<string, string[]> {\n const map = new Map<string, string[]>()\n\n for (const [targetName, productKey] of targetToProduct.entries()) {\n const targets = map.get(productKey) ?? []\n targets.push(targetName)\n map.set(productKey, targets)\n }\n\n for (const targets of map.values()) {\n targets.sort((left, right) => left.localeCompare(right))\n }\n\n return map\n}\n\nfunction extractSuiteFileMetadata(content: string): { suiteId: string | null; name: string | null; targetName: string | null } {\n let parsed: Record<string, unknown> | null = null\n\n try {\n const yamlValue = parseYaml(content)\n if (yamlValue && typeof yamlValue === 'object' && !Array.isArray(yamlValue)) {\n parsed = yamlValue as Record<string, unknown>\n }\n } catch {\n // Fall back to regex extraction for partially-authored files.\n }\n\n const name = typeof parsed?.name === 'string' && parsed.name.trim().length > 0\n ? parsed.name.trim()\n : content.match(/^name:\\s*(.+)$/m)?.[1]?.trim().replace(/^[\"'](.*)[\"']$/, '$1') ?? null\n\n const suiteId = typeof parsed?.['suite-id'] === 'string' && parsed['suite-id'].trim().length > 0\n ? parsed['suite-id'].trim()\n : content.match(/^suite-id:\\s*(.+)$/m)?.[1]?.trim().replace(/^[\"'](.*)[\"']$/, '$1') ?? null\n\n const targetName = typeof parsed?.target === 'string' && parsed.target.trim().length > 0\n ? parsed.target.trim()\n : content.match(/^target:\\s*(.+)$/m)?.[1]?.trim().replace(/^[\"'](.*)[\"']$/, '$1') ?? null\n\n return { suiteId, name, targetName }\n}\n\nfunction resolveScopeReference(\n scope: MemoryScope,\n scopeId: string,\n context: WorkspaceContext,\n): MemoryObservationReference | null {\n switch (scope) {\n case 'product':\n return null\n case 'suite':\n return resolveReference('suite', context.suiteMetadataById.get(scopeId))\n case 'test':\n return resolveReference('test', context.testMetadataById.get(scopeId))\n }\n}\n\nfunction resolveReference(\n kind: MemoryObservationReference['kind'],\n metadata: WorkspaceEntityMetadata | undefined,\n): MemoryObservationReference | null {\n if (!metadata) {\n return null\n }\n\n return {\n kind,\n id: metadata.id,\n label: metadata.label,\n targetName: metadata.targetName,\n href: metadata.href,\n }\n}\n\nexport function isValidMemoryScopeId(value: string): boolean {\n return value.trim().length > 0 && !/\\.\\./.test(value) && !/[/\\\\]/.test(value) && !/\\0/.test(value)\n}\n","import { readFile, writeFile, mkdir, rm, stat } from 'node:fs/promises'\nimport { dirname, basename } from 'node:path'\nimport { generateTestId } from '@vostride/agent-qa-ids'\nimport { parse as parseYaml } from 'yaml'\nimport {\n discoverWorkspaceFiles,\n resolveWorkspaceFileTarget,\n type ResolvedWorkspacePaths,\n} from '@vostride/agent-qa-core'\n\nexport interface TestFileInfo {\n path: string\n name: string\n testId: string | null\n targetName: string | null\n platform: string | null\n modified: string\n}\n\nexport type SupportedPlatform = 'web' | 'android' | 'ios'\n\nexport interface TestFileMetadata {\n name: string | null\n testId: string | null\n targetName: string | null\n platform: SupportedPlatform | null\n parallel: boolean | null\n}\n\nexport interface TestValidationError {\n message: string\n line?: number\n column?: number\n suggestion?: string\n}\n\nexport interface TestValidationResult {\n valid: boolean\n errors: TestValidationError[]\n}\n\nfunction normalizeQuotedString(value: string): string {\n return value.trim().replace(/^[\"'](.*)[\"']$/, '$1')\n}\n\nfunction normalizePlatform(value: unknown): SupportedPlatform | null {\n if (value !== 'web' && value !== 'android' && value !== 'ios') return null\n return value\n}\n\nexport function extractTestFileMetadata(content: string): TestFileMetadata {\n let parsed: Record<string, unknown> | null = null\n\n try {\n const yamlValue = parseYaml(content)\n if (yamlValue && typeof yamlValue === 'object' && !Array.isArray(yamlValue)) {\n parsed = yamlValue as Record<string, unknown>\n }\n } catch {\n // fall back to regex extraction for partially-authored files\n }\n\n const config = parsed?.config\n const parsedConfig = config && typeof config === 'object' && !Array.isArray(config)\n ? config as Record<string, unknown>\n : null\n const use = parsed?.use\n const parsedUse = use && typeof use === 'object' && !Array.isArray(use)\n ? use as Record<string, unknown>\n : null\n\n const nameMatch = content.match(/^name:\\s*(.+)$/m)\n const targetMatch = content.match(/^\\s*target:\\s*(.+)$/m)\n const testIdMatch = content.match(/^test-id:\\s*(.+)$/m)\n const platformMatch = content.match(/^\\s*platform:\\s*(web|android|ios)\\s*$/m)\n const parallelMatch = content.match(/^\\s*parallel:\\s*(true|false)\\s*$/m)\n\n const name = typeof parsed?.name === 'string' && parsed.name.trim().length > 0\n ? parsed.name.trim()\n : nameMatch\n ? normalizeQuotedString(nameMatch[1])\n : null\n\n const targetName = typeof parsed?.target === 'string' && parsed.target.trim().length > 0\n ? parsed.target.trim()\n : targetMatch\n ? normalizeQuotedString(targetMatch[1])\n : null\n\n const testId = typeof parsed?.['test-id'] === 'string' && parsed['test-id'].trim().length > 0\n ? parsed['test-id'].trim()\n : testIdMatch\n ? normalizeQuotedString(testIdMatch[1])\n : null\n\n const platform = normalizePlatform(parsed?.platform)\n ?? normalizePlatform(parsedConfig?.platform)\n ?? normalizePlatform(platformMatch?.[1])\n\n const parallel = typeof parsedUse?.parallel === 'boolean'\n ? parsedUse.parallel\n : typeof parsed?.parallel === 'boolean'\n ? parsed.parallel\n : typeof parsedConfig?.parallel === 'boolean'\n ? parsedConfig.parallel\n : parallelMatch\n ? parallelMatch[1] === 'true'\n : null\n\n return {\n name,\n testId,\n targetName,\n platform,\n parallel,\n }\n}\n\nexport class TestFileManager {\n constructor(private readonly workspace: ResolvedWorkspacePaths) {}\n\n async list(): Promise<TestFileInfo[]> {\n const records = await discoverWorkspaceFiles({ workspace: this.workspace, kind: 'test' })\n const files: TestFileInfo[] = []\n\n for (const record of records) {\n try {\n const s = await stat(record.absolutePath)\n if (s.isFile()) {\n let testName = basename(record.workspaceRelativePath)\n let platform: string | null = null\n let targetName: string | null = null\n let testId: string | null = null\n try {\n let content = await readFile(record.absolutePath, 'utf-8')\n const metadata = extractTestFileMetadata(content)\n if (metadata.name) testName = metadata.name\n if (metadata.targetName) targetName = metadata.targetName\n if (metadata.platform) platform = metadata.platform\n if (metadata.testId) {\n testId = metadata.testId\n } else {\n testId = generateTestId()\n content = `test-id: ${testId}\\n${content}`\n await writeFile(record.absolutePath, content, 'utf-8')\n }\n } catch { /* fall back to filename */ }\n files.push({\n path: record.workspaceRelativePath,\n name: testName,\n testId,\n targetName,\n platform,\n modified: s.mtime.toISOString(),\n })\n }\n } catch {\n // skip inaccessible files\n }\n }\n\n files.sort((a, b) => b.modified.localeCompare(a.modified))\n return files\n }\n\n async read(relativePath: string): Promise<string> {\n const target = await this.resolveTarget(relativePath, true)\n return readFile(target.absolutePath, 'utf-8')\n }\n\n async findByTestId(testId: string): Promise<{ path: string; content: string } | null> {\n const files = await this.list()\n const match = files.find(f => f.testId === testId)\n if (!match) return null\n const content = await this.read(match.path)\n return { path: match.path, content }\n }\n\n async write(relativePath: string, content: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, false)\n await mkdir(dirname(target.absolutePath), { recursive: true })\n await writeFile(target.absolutePath, content, 'utf-8')\n }\n\n async delete(relativePath: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, true)\n await rm(target.absolutePath)\n }\n\n async validate(content: string): Promise<TestValidationResult> {\n try {\n const { parseTestFile } = await import('@vostride/agent-qa-core')\n const result = parseTestFile(content, '<editor>')\n\n if (result.errors.length === 0) {\n return { valid: true, errors: [] }\n }\n\n return {\n valid: false,\n errors: result.errors.map(e => ({\n message: e.message,\n line: e.line,\n column: e.column,\n suggestion: e.suggestion,\n })),\n }\n } catch (err) {\n return {\n valid: false,\n errors: [{ message: err instanceof Error ? err.message : 'Failed to validate' }],\n }\n }\n }\n\n private async resolveTarget(relativePath: string, requireExisting: boolean) {\n return resolveWorkspaceFileTarget({\n workspace: this.workspace,\n kind: 'test',\n filePath: relativePath,\n requireExisting,\n })\n }\n}\n","import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, relative, resolve } from 'node:path'\n\nimport { HooksFileSchema, isPathInsideDir, parseHooksFile, resolveWorkspacePaths } from '@vostride/agent-qa-core'\nimport type { AgentQaConfig, HooksFileConfig } from '@vostride/agent-qa-core'\nimport { generateHookId } from '@vostride/agent-qa-ids'\nimport { parse as parseYaml, parseDocument } from 'yaml'\n\nimport type { ConfigManager } from '../config/config-manager.js'\nimport type {\n HookCatalogResponse,\n HookCatalogRow,\n HookDeleteResult,\n HookDetailResponse,\n HookDraftValidationResult,\n HookFieldError,\n HookFieldName,\n HookMutationRequest,\n HookPrepareResult,\n HookRegistryReadError,\n} from './hook-registry-types.js'\nimport { scanHookReferences } from './hook-reference-scan.js'\n\ntype ParsedHookDefinition = HooksFileConfig['hooks'][number]\ntype AuthoredHookDefinition = Omit<ParsedHookDefinition, 'timeout'> & {\n timeout: string\n}\ntype HooksFileParseData = { hooks: ParsedHookDefinition[] }\ntype ZodIssueLike = { path: PropertyKey[]; message: string }\n\ninterface HookRegistryLocation {\n filePath: string\n resolvedFilePath: string\n hooksBaseDir: string\n}\n\ninterface HookRegistryState extends HookRegistryLocation {\n hooks: ParsedHookDefinition[]\n errors: HookRegistryReadError[]\n missing: boolean\n}\n\ninterface HookRegistryMutationState extends HookRegistryLocation {\n hooks: AuthoredHookDefinition[]\n raw: string | null\n existed: boolean\n}\n\ninterface HookFileState {\n resolvedFilePath: string | null\n fileMissing: boolean\n fieldErrors: HookFieldError[]\n}\n\ninterface HookMutationResolvedPayload {\n hook: Record<string, unknown> & { id: string }\n source: string\n}\n\ninterface HookMutationPlan {\n nextHook: ParsedHookDefinition\n nextSourcePath: string\n oldSourcePath: string | null\n oldSourceContent: string | null\n oldSourceExisted: boolean\n removeOldSourcePath: boolean\n projectedHooks: AuthoredHookDefinition[]\n}\n\nclass HookRegistryMutationError extends Error {\n readonly code: string\n readonly fieldErrors: HookFieldError[]\n\n constructor(code: string, fieldErrors: HookFieldError[], message = code) {\n super(message)\n this.code = code\n this.fieldErrors = fieldErrors\n }\n}\n\nexport function isHookRegistryMutationError(error: unknown): error is {\n code: string\n fieldErrors: HookFieldError[]\n} {\n return error instanceof HookRegistryMutationError\n}\n\nexport class HookRegistryManager {\n constructor(\n private readonly configManager: ConfigManager,\n private readonly configPath: string,\n ) {}\n\n async readCatalog(): Promise<HookCatalogResponse> {\n const registry = await this.readRegistryState()\n if (registry.missing || registry.errors.length > 0) {\n return {\n hooks: [],\n filePath: registry.filePath,\n errors: registry.errors.map((error) => error.message),\n missing: registry.missing,\n }\n }\n\n const hooks = await Promise.all(\n registry.hooks.map(async (hook) => {\n const fileState = await this.inspectHookFile(hook.file, registry.hooksBaseDir)\n return this.toCatalogRow(hook, fileState.fileMissing)\n }),\n )\n\n return {\n hooks,\n filePath: registry.filePath,\n errors: [],\n missing: false,\n }\n }\n\n async readHook(hookId: string): Promise<HookDetailResponse | null> {\n const registry = await this.readRegistryState()\n if (registry.missing || registry.errors.length > 0) {\n return null\n }\n\n const hook = registry.hooks.find((candidate) => candidate.id === hookId)\n if (!hook) {\n return null\n }\n\n const fileState = await this.inspectHookFile(hook.file, registry.hooksBaseDir)\n let source: string | null = null\n\n if (fileState.resolvedFilePath && fileState.fieldErrors.length === 0) {\n source = await readFile(fileState.resolvedFilePath, 'utf-8')\n }\n\n return {\n hook: this.toCatalogRow(hook, fileState.fileMissing),\n source,\n fieldErrors: fileState.fieldErrors,\n }\n }\n\n async createHook(payload: HookMutationRequest): Promise<HookDetailResponse> {\n const registry = await this.readRegistryForMutation()\n const resolvedPayload = this.resolveMutationPayload(payload, {\n generatedId: generateHookId(),\n })\n const plan = await this.planHookMutation(registry, resolvedPayload.hook.id, resolvedPayload, 'create')\n\n await this.persistHookMutation(registry, plan, resolvedPayload.source)\n\n return {\n hook: this.toCatalogRow(plan.nextHook, false),\n source: resolvedPayload.source,\n fieldErrors: [],\n }\n }\n\n async updateHook(hookId: string, payload: HookMutationRequest): Promise<HookDetailResponse> {\n const registry = await this.readRegistryForMutation()\n const existingHook = registry.hooks.find((candidate) => candidate.id === hookId)\n if (!existingHook) {\n throw new HookRegistryMutationError('hook_not_found', [\n {\n field: 'id',\n code: 'hook_not_found',\n message: 'Hook not found',\n },\n ])\n }\n\n const resolvedPayload = this.resolveMutationPayload(payload, {\n expectedId: hookId,\n generatedId: hookId,\n })\n const plan = await this.planHookMutation(registry, hookId, resolvedPayload, 'update')\n\n await this.persistHookMutation(registry, plan, resolvedPayload.source)\n\n return {\n hook: this.toCatalogRow(plan.nextHook, false),\n source: resolvedPayload.source,\n fieldErrors: [],\n }\n }\n\n async deleteHook(\n hookId: string,\n options: { force?: boolean } = {},\n ): Promise<HookDeleteResult> {\n const registry = await this.readRegistryForMutation()\n const existingHook = registry.hooks.find((candidate) => candidate.id === hookId)\n if (!existingHook) {\n throw new HookRegistryMutationError('hook_not_found', [\n {\n field: 'id',\n code: 'hook_not_found',\n message: 'Hook not found',\n },\n ])\n }\n\n const references = await scanHookReferences(dirname(this.configPath), this.configPath, hookId)\n if (references.length > 0 && !options.force) {\n return {\n deleted: false,\n references,\n }\n }\n\n const nextHooks = registry.hooks.filter((candidate) => candidate.id !== hookId)\n const nextRegistryContent = nextHooks.length > 0\n ? this.serializeHooksDocument(registry.raw, nextHooks)\n : null\n const sourcePath = resolve(registry.hooksBaseDir, existingHook.file)\n const sourceSnapshot = await this.readOptionalFile(sourcePath)\n const sourcePathStillReferenced = nextHooks.some(\n (candidate) => resolve(registry.hooksBaseDir, candidate.file) === sourcePath,\n )\n\n try {\n if (nextRegistryContent === null) {\n await rm(registry.resolvedFilePath, { force: true })\n } else {\n await mkdir(dirname(registry.resolvedFilePath), { recursive: true })\n await writeFile(registry.resolvedFilePath, nextRegistryContent, 'utf-8')\n }\n\n if (sourceSnapshot.exists && !sourcePathStillReferenced) {\n await rm(sourcePath, { force: true })\n }\n\n return {\n deleted: true,\n references,\n }\n } catch (error) {\n await this.restoreRegistrySnapshot(registry)\n\n if (sourceSnapshot.exists && sourceSnapshot.content !== null) {\n await mkdir(dirname(sourcePath), { recursive: true })\n await writeFile(sourcePath, sourceSnapshot.content, 'utf-8')\n }\n\n throw error\n }\n }\n\n async validateDraft(draft: unknown): Promise<HookDraftValidationResult> {\n const location = await this.resolveRegistryLocation()\n const normalizedDraft = this.normalizeDraftForSchema(draft)\n const result = HooksFileSchema.safeParse(normalizedDraft)\n\n if (!result.success) {\n return {\n valid: false,\n fieldErrors: result.error.issues.map((issue: ZodIssueLike) => this.toValidationFieldError(issue.path, issue.message)),\n warnings: [],\n }\n }\n const hooksFile = result.data as HooksFileParseData\n\n const fieldErrors: HookFieldError[] = []\n const warnings: HookFieldError[] = []\n\n for (const hook of hooksFile.hooks) {\n if (isAbsolute(hook.file)) {\n fieldErrors.push({\n field: 'file',\n code: 'absolute_path',\n message: 'Hook file must be relative to the configured hooks file',\n })\n continue\n }\n\n if (!isPathInsideDir(hook.file, location.hooksBaseDir)) {\n fieldErrors.push({\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n })\n continue\n }\n\n const fileState = await this.inspectHookFile(hook.file, location.hooksBaseDir)\n warnings.push(...fileState.fieldErrors.filter((error) => error.code === 'file_missing'))\n }\n\n return {\n valid: fieldErrors.length === 0,\n fieldErrors,\n warnings,\n }\n }\n\n async prepareForExecution(): Promise<HookPrepareResult> {\n const registry = await this.readRegistryState()\n if (registry.missing) {\n return {\n resolvedHooks: new Map(),\n authoringIssuesById: new Map(),\n }\n }\n\n if (registry.errors.length > 0) {\n return {\n resolvedHooks: new Map(),\n hookRegistryError: registry.errors.map((error) => error.message).join('; '),\n authoringIssuesById: new Map(),\n }\n }\n\n const parsedHooks = await parseHooksFile(registry.resolvedFilePath)\n if (parsedHooks.errors.length > 0) {\n return {\n resolvedHooks: new Map(),\n hookRegistryError: parsedHooks.errors.join('; '),\n authoringIssuesById: new Map(),\n }\n }\n\n const resolvedHooksById = new Map(parsedHooks.hooks.map((hook) => [hook.id, hook]))\n const resolvedHooks = new Map<typeof resolvedHooksById extends Map<infer K, infer V> ? K : never, typeof resolvedHooksById extends Map<infer K, infer V> ? V : never>()\n const authoringIssuesById = new Map<string, HookFieldError[]>()\n\n for (const hook of registry.hooks) {\n const fileState = await this.inspectHookFile(hook.file, registry.hooksBaseDir)\n const resolvedHook = resolvedHooksById.get(hook.id)\n if (!resolvedHook) {\n continue\n }\n\n if (fileState.fieldErrors.length > 0) {\n authoringIssuesById.set(hook.id, fileState.fieldErrors)\n continue\n }\n\n resolvedHooks.set(hook.id, resolvedHook)\n }\n\n return {\n resolvedHooks,\n authoringIssuesById,\n }\n }\n\n private async readRegistryForMutation(): Promise<HookRegistryMutationState> {\n const location = await this.resolveRegistryLocation()\n\n let raw: string | null = null\n try {\n raw = await readFile(location.resolvedFilePath, 'utf-8')\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n ...location,\n hooks: [],\n raw: null,\n existed: false,\n }\n }\n throw error\n }\n\n let parsed: unknown\n try {\n parsed = parseYaml(raw)\n } catch (error: unknown) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_registry',\n message: `Invalid YAML in hooks file: ${(error as Error).message}`,\n },\n ])\n }\n\n const result = HooksFileSchema.safeParse(parsed)\n if (!result.success) {\n throw new HookRegistryMutationError(\n 'validation_failed',\n result.error.issues.map((issue: ZodIssueLike) => this.toValidationFieldError(issue.path, issue.message)),\n )\n }\n\n const hooksFile = result.data as HooksFileParseData\n const pathErrors = hooksFile.hooks.flatMap((hook, index) => {\n const error = this.getAuthoredPathReadError(hook.file, location.hooksBaseDir, index)\n return error ? [this.toMutationFieldError(error)] : []\n })\n if (pathErrors.length > 0) {\n throw new HookRegistryMutationError('validation_failed', pathErrors)\n }\n\n return {\n ...location,\n hooks: this.toAuthoredHookDefinitions(parsed, hooksFile.hooks),\n raw,\n existed: true,\n }\n }\n\n private resolveMutationPayload(\n payload: HookMutationRequest,\n options: { expectedId?: string; generatedId: string },\n ): HookMutationResolvedPayload {\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_payload',\n message: 'Hook mutation payload is required',\n },\n ])\n }\n\n if (typeof payload.source !== 'string') {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_source',\n message: 'Hook source must be a string',\n },\n ])\n }\n\n const hookValue = payload.hook\n if (!hookValue || typeof hookValue !== 'object' || Array.isArray(hookValue)) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_hook',\n message: 'Hook payload is required',\n },\n ])\n }\n\n const providedId = typeof hookValue.id === 'string' && hookValue.id.trim().length > 0\n ? hookValue.id.trim()\n : undefined\n if (options.expectedId && providedId && providedId !== options.expectedId) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'id',\n code: 'id_mismatch',\n message: 'Hook id in body must match the route parameter',\n },\n ])\n }\n\n return {\n hook: {\n id: providedId ?? options.generatedId,\n name: hookValue.name as string,\n runtime: hookValue.runtime as ParsedHookDefinition['runtime'],\n file: hookValue.file as string,\n timeout: hookValue.timeout as string | number,\n network: hookValue.network as boolean | undefined,\n },\n source: payload.source,\n }\n }\n\n private async planHookMutation(\n registry: HookRegistryMutationState,\n hookId: string,\n payload: HookMutationResolvedPayload,\n mode: 'create' | 'update',\n ): Promise<HookMutationPlan> {\n const existingHook = mode === 'update'\n ? registry.hooks.find((candidate) => candidate.id === hookId) ?? null\n : null\n\n const projectedHooks: Array<Record<string, unknown> | AuthoredHookDefinition> = mode === 'update'\n ? [...registry.hooks.filter((candidate) => candidate.id !== hookId), payload.hook]\n : [...registry.hooks, payload.hook]\n const validated = this.validateProjectedHooks(projectedHooks, registry.hooksBaseDir)\n if (!validated.valid) {\n throw new HookRegistryMutationError('validation_failed', validated.fieldErrors)\n }\n\n const nextHook = validated.parsedHooks.find((candidate) => candidate.id === payload.hook.id)\n if (!nextHook) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'registry',\n code: 'invalid_registry',\n message: 'Hook could not be projected into the configured hooks file',\n },\n ])\n }\n\n const nextSourcePath = resolve(registry.hooksBaseDir, nextHook.file)\n const oldSourcePath = existingHook ? resolve(registry.hooksBaseDir, existingHook.file) : null\n const oldSourceSnapshot = existingHook && oldSourcePath\n ? await this.readOptionalFile(oldSourcePath)\n : { exists: false, content: null as string | null }\n\n if (mode === 'create') {\n const nextExists = await this.readOptionalFile(nextSourcePath)\n if (nextExists.exists) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'file',\n code: 'collision',\n message: 'Hook file already exists at that path',\n },\n ])\n }\n }\n\n if (mode === 'update' && oldSourcePath !== nextSourcePath) {\n const nextExists = await this.readOptionalFile(nextSourcePath)\n if (nextExists.exists) {\n throw new HookRegistryMutationError('validation_failed', [\n {\n field: 'file',\n code: 'collision',\n message: 'Hook file already exists at that path',\n },\n ])\n }\n }\n\n return {\n nextHook,\n nextSourcePath,\n oldSourcePath,\n oldSourceContent: oldSourceSnapshot.content,\n oldSourceExisted: oldSourceSnapshot.exists,\n removeOldSourcePath: Boolean(\n oldSourcePath &&\n oldSourcePath !== nextSourcePath &&\n oldSourceSnapshot.exists &&\n !validated.authoredHooks.some(\n (candidate) =>\n candidate.id !== hookId &&\n resolve(registry.hooksBaseDir, candidate.file) === oldSourcePath,\n ),\n ),\n projectedHooks: validated.authoredHooks,\n }\n }\n\n private validateProjectedHooks(\n hooks: Array<Record<string, unknown> | AuthoredHookDefinition>,\n hooksBaseDir: string,\n ): {\n valid: boolean\n parsedHooks: ParsedHookDefinition[]\n authoredHooks: AuthoredHookDefinition[]\n fieldErrors: HookFieldError[]\n } {\n const rawFieldErrors = this.collectRawHookFieldErrors(hooks, hooksBaseDir)\n const normalizedDraft = this.normalizeDraftForSchema({ hooks })\n const result = HooksFileSchema.safeParse(normalizedDraft)\n\n if (!result.success) {\n return {\n valid: false,\n parsedHooks: [],\n authoredHooks: [],\n fieldErrors: this.dedupeFieldErrors([\n ...rawFieldErrors,\n ...result.error.issues.map((issue: ZodIssueLike) => this.toValidationFieldError(issue.path, issue.message)),\n ]),\n }\n }\n\n const hooksFile = result.data as HooksFileParseData\n const pathErrors = hooksFile.hooks.flatMap((hook, index) => {\n const error = this.getAuthoredPathReadError(hook.file, hooksBaseDir, index)\n return error ? [this.toMutationFieldError(error)] : []\n })\n\n return {\n valid: pathErrors.length === 0,\n parsedHooks: hooksFile.hooks,\n authoredHooks: this.toAuthoredHookDefinitions({ hooks }, hooksFile.hooks),\n fieldErrors: this.dedupeFieldErrors([\n ...rawFieldErrors,\n ...pathErrors,\n ]),\n }\n }\n\n private async persistHookMutation(\n registry: HookRegistryMutationState,\n plan: HookMutationPlan,\n source: string,\n ): Promise<void> {\n const nextRegistryContent = this.serializeHooksDocument(registry.raw, plan.projectedHooks)\n\n try {\n await mkdir(dirname(plan.nextSourcePath), { recursive: true })\n await writeFile(plan.nextSourcePath, source, 'utf-8')\n await mkdir(dirname(registry.resolvedFilePath), { recursive: true })\n await writeFile(registry.resolvedFilePath, nextRegistryContent, 'utf-8')\n\n if (plan.removeOldSourcePath && plan.oldSourcePath) {\n await rm(plan.oldSourcePath)\n }\n } catch (error) {\n await this.restoreRegistrySnapshot(registry)\n await this.restoreSourceSnapshot(plan)\n throw error\n }\n }\n\n private async restoreRegistrySnapshot(registry: HookRegistryMutationState): Promise<void> {\n if (!registry.existed || registry.raw === null) {\n await rm(registry.resolvedFilePath, { force: true })\n return\n }\n\n await writeFile(registry.resolvedFilePath, registry.raw, 'utf-8')\n }\n\n private async restoreSourceSnapshot(plan: HookMutationPlan): Promise<void> {\n if (plan.oldSourcePath === plan.nextSourcePath) {\n if (plan.oldSourceExisted && plan.oldSourceContent !== null) {\n await mkdir(dirname(plan.nextSourcePath), { recursive: true })\n await writeFile(plan.nextSourcePath, plan.oldSourceContent, 'utf-8')\n return\n }\n\n await rm(plan.nextSourcePath, { force: true })\n return\n }\n\n await rm(plan.nextSourcePath, { force: true })\n }\n\n private serializeHooksDocument(\n raw: string | null,\n hooks: AuthoredHookDefinition[],\n ): string {\n const doc = parseDocument(raw ?? '{}')\n doc.setIn(['hooks'], doc.createNode(hooks))\n return doc.toString()\n }\n\n private async readOptionalFile(path: string): Promise<{ exists: boolean; content: string | null }> {\n try {\n return {\n exists: true,\n content: await readFile(path, 'utf-8'),\n }\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n exists: false,\n content: null,\n }\n }\n throw error\n }\n }\n\n private collectRawHookFieldErrors(\n hooks: Array<Record<string, unknown> | AuthoredHookDefinition>,\n hooksBaseDir: string,\n ): HookFieldError[] {\n const fieldErrors: HookFieldError[] = []\n const ids = new Set<string>()\n const names = new Set<string>()\n\n for (const hook of hooks) {\n if (!hook || typeof hook !== 'object' || Array.isArray(hook)) {\n continue\n }\n\n const hookRecord = hook as Record<string, unknown>\n if (typeof hookRecord.id === 'string') {\n if (ids.has(hookRecord.id)) {\n fieldErrors.push({\n field: 'id',\n code: 'duplicate_id',\n message: `Duplicate hook id: \"${hookRecord.id}\"`,\n })\n } else {\n ids.add(hookRecord.id)\n }\n }\n\n if (typeof hookRecord.name === 'string') {\n if (names.has(hookRecord.name)) {\n fieldErrors.push({\n field: 'name',\n code: 'duplicate_name',\n message: `Duplicate hook name: \"${hookRecord.name}\"`,\n })\n } else {\n names.add(hookRecord.name)\n }\n }\n\n if (typeof hookRecord.file === 'string') {\n if (isAbsolute(hookRecord.file)) {\n fieldErrors.push({\n field: 'file',\n code: 'absolute_path',\n message: 'Hook file must be relative to the configured hooks file',\n })\n } else if (!isPathInsideDir(hookRecord.file, hooksBaseDir)) {\n fieldErrors.push({\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n })\n }\n }\n }\n\n return fieldErrors\n }\n\n private dedupeFieldErrors(fieldErrors: HookFieldError[]): HookFieldError[] {\n const seen = new Set<string>()\n return fieldErrors.filter((error) => {\n const key = `${error.field}:${error.code}:${error.message}`\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n }\n\n private async readRegistryState(): Promise<HookRegistryState> {\n const location = await this.resolveRegistryLocation()\n\n try {\n await stat(location.resolvedFilePath)\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n ...location,\n hooks: [],\n errors: [{ code: 'hooks_file_missing', message: `configured hooks file not found: ${location.filePath}` }],\n missing: true,\n }\n }\n throw err\n }\n\n const raw = await readFile(location.resolvedFilePath, 'utf-8')\n\n let parsed: unknown\n try {\n parsed = parseYaml(raw)\n } catch (err: unknown) {\n return {\n ...location,\n hooks: [],\n errors: [{ code: 'invalid_yaml', message: `Invalid YAML in hooks file: ${(err as Error).message}` }],\n missing: false,\n }\n }\n\n const result = HooksFileSchema.safeParse(parsed)\n if (!result.success) {\n return {\n ...location,\n hooks: [],\n errors: result.error.issues.map((issue: ZodIssueLike) => ({\n code: 'invalid_registry',\n message: `${issue.path.map(String).join('.')}: ${issue.message}`,\n })),\n missing: false,\n }\n }\n\n const hooksFile = result.data as HooksFileParseData\n const pathErrors = hooksFile.hooks\n .map((hook, index) => this.getAuthoredPathReadError(hook.file, location.hooksBaseDir, index))\n .filter((error): error is HookRegistryReadError => error !== null)\n\n if (pathErrors.length > 0) {\n return {\n ...location,\n hooks: [],\n errors: pathErrors,\n missing: false,\n }\n }\n\n return {\n ...location,\n hooks: hooksFile.hooks,\n errors: [],\n missing: false,\n }\n }\n\n private async resolveRegistryLocation(): Promise<HookRegistryLocation> {\n const config = await this.configManager.read() as AgentQaConfig\n const workspacePaths = resolveWorkspacePaths({ config, configPath: this.configPath })\n const configuredPath = workspacePaths.hooksFile.configuredPath\n const resolvedFilePath = workspacePaths.hooksFile.absolutePath\n\n return {\n filePath: this.toDisplayPath(configuredPath, resolvedFilePath),\n resolvedFilePath,\n hooksBaseDir: dirname(resolvedFilePath),\n }\n }\n\n private getAuthoredPathReadError(filePath: string, hooksBaseDir: string, index: number): HookRegistryReadError | null {\n if (isAbsolute(filePath)) {\n return {\n code: 'absolute_path',\n message: `hooks.${index}.file: Hook file must be relative to the configured hooks file`,\n }\n }\n\n if (!isPathInsideDir(filePath, hooksBaseDir)) {\n return {\n code: 'unsafe_path',\n message: `hooks.${index}.file: Hook file must stay inside the configured hooks file directory`,\n }\n }\n\n return null\n }\n\n private async inspectHookFile(filePath: string, hooksBaseDir: string): Promise<HookFileState> {\n if (isAbsolute(filePath) || !isPathInsideDir(filePath, hooksBaseDir)) {\n return {\n resolvedFilePath: null,\n fileMissing: true,\n fieldErrors: [\n {\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n },\n ],\n }\n }\n\n const resolvedFilePath = resolve(hooksBaseDir, filePath)\n try {\n await stat(resolvedFilePath)\n return {\n resolvedFilePath,\n fileMissing: false,\n fieldErrors: [],\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return {\n resolvedFilePath: null,\n fileMissing: true,\n fieldErrors: [\n {\n field: 'file',\n code: 'file_missing',\n message: 'Hook file missing',\n },\n ],\n }\n }\n throw err\n }\n }\n\n private normalizeDraftForSchema(draft: unknown): unknown {\n const rawHooks = this.getRawHooksFromDraft(draft)\n if (rawHooks === null) {\n return draft\n }\n\n return {\n ...(draft as Record<string, unknown>),\n hooks: rawHooks.map((hook) => {\n if (!hook || typeof hook !== 'object' || Array.isArray(hook)) {\n return hook\n }\n\n const hookRecord = hook as Record<string, unknown>\n return {\n ...hookRecord,\n timeout: this.normalizeTimeoutValue(hookRecord.timeout),\n }\n }),\n }\n }\n\n private toAuthoredHookDefinitions(\n draft: unknown,\n parsedHooks: ParsedHookDefinition[],\n ): AuthoredHookDefinition[] {\n const rawHooks = this.getRawHooksFromDraft(draft) ?? []\n return parsedHooks.map((hook, index) => this.toAuthoredHookDefinition(rawHooks[index], hook))\n }\n\n private toAuthoredHookDefinition(\n rawHook: unknown,\n parsedHook: ParsedHookDefinition,\n ): AuthoredHookDefinition {\n const rawTimeout = rawHook && typeof rawHook === 'object' && !Array.isArray(rawHook)\n ? (rawHook as Record<string, unknown>).timeout\n : parsedHook.timeout\n const normalizedTimeout = this.normalizeTimeoutValue(rawTimeout)\n\n return {\n ...parsedHook,\n timeout: typeof normalizedTimeout === 'string'\n ? normalizedTimeout\n : this.formatDurationToken(parsedHook.timeout),\n }\n }\n\n private getRawHooksFromDraft(draft: unknown): unknown[] | null {\n if (!draft || typeof draft !== 'object' || Array.isArray(draft)) {\n return null\n }\n\n const hooks = (draft as { hooks?: unknown }).hooks\n return Array.isArray(hooks) ? hooks : null\n }\n\n private normalizeTimeoutValue(timeout: unknown): unknown {\n if (typeof timeout === 'number') {\n return this.formatDurationToken(timeout)\n }\n\n if (typeof timeout !== 'string') {\n return timeout\n }\n\n const trimmedTimeout = timeout.trim()\n if (trimmedTimeout.length === 0) {\n return trimmedTimeout\n }\n\n if (/^\\d+$/.test(trimmedTimeout)) {\n return this.formatDurationToken(Number.parseInt(trimmedTimeout, 10))\n }\n\n const millisecondTimeout = trimmedTimeout.match(/^(\\d+)ms$/i)\n if (millisecondTimeout) {\n return this.formatDurationToken(Number.parseInt(millisecondTimeout[1], 10))\n }\n\n return trimmedTimeout\n }\n\n private formatDurationToken(durationMs: number): string {\n if (!Number.isFinite(durationMs) || durationMs < 0) {\n return `${durationMs}`\n }\n\n if (durationMs === 0) {\n return '0ms'\n }\n\n const durationUnits = [\n { suffix: 'd', value: 86_400_000 },\n { suffix: 'h', value: 3_600_000 },\n { suffix: 'm', value: 60_000 },\n { suffix: 's', value: 1_000 },\n ] as const\n\n for (const unit of durationUnits) {\n if (durationMs % unit.value === 0) {\n return `${durationMs / unit.value}${unit.suffix}`\n }\n }\n\n return `${durationMs}ms`\n }\n\n private toValidationFieldError(path: PropertyKey[], message: string): HookFieldError {\n const field = this.getFieldName(path)\n\n if (field === 'id' && message.includes('Duplicate hook id')) {\n return { field, code: 'duplicate_id', message }\n }\n\n if (field === 'name' && message.includes('Duplicate hook name')) {\n return { field, code: 'duplicate_name', message }\n }\n\n if (field === 'runtime') {\n return { field, code: 'invalid_runtime', message }\n }\n\n if (field === 'timeout') {\n return { field, code: 'invalid_timeout', message }\n }\n\n if (field === 'network') {\n return { field, code: 'invalid_network', message }\n }\n\n if (field === 'file') {\n return { field, code: 'invalid_file', message }\n }\n\n if (field === 'id') {\n return { field, code: 'invalid_id', message }\n }\n\n if (field === 'name') {\n return { field, code: 'invalid_name', message }\n }\n\n return { field, code: 'invalid_registry', message }\n }\n\n private toMutationFieldError(error: HookRegistryReadError): HookFieldError {\n if (error.code === 'absolute_path') {\n return {\n field: 'file',\n code: 'absolute_path',\n message: 'Hook file must be relative to the configured hooks file',\n }\n }\n\n if (error.code === 'unsafe_path') {\n return {\n field: 'file',\n code: 'unsafe_path',\n message: 'Hook file must stay inside the configured hooks file directory',\n }\n }\n\n return {\n field: 'registry',\n code: error.code,\n message: error.message,\n }\n }\n\n private getFieldName(path: PropertyKey[]): HookFieldName {\n const field = path[path.length - 1]\n if (\n field === 'id' ||\n field === 'name' ||\n field === 'runtime' ||\n field === 'file' ||\n field === 'timeout' ||\n field === 'network'\n ) {\n return field\n }\n\n return 'registry'\n }\n\n private toCatalogRow(hook: ParsedHookDefinition, fileMissing: boolean): HookCatalogRow {\n return {\n id: hook.id,\n name: hook.name,\n runtime: hook.runtime,\n file: hook.file,\n timeout: hook.timeout,\n network: hook.network,\n fileMissing,\n }\n }\n\n private toDisplayPath(configuredPath: string, resolvedFilePath: string): string {\n if (!isAbsolute(configuredPath)) {\n return configuredPath\n }\n\n const relativeToConfig = relative(dirname(this.configPath), resolvedFilePath)\n if (relativeToConfig && !relativeToConfig.startsWith('..') && !isAbsolute(relativeToConfig)) {\n return relativeToConfig.startsWith('.') ? relativeToConfig : `./${relativeToConfig}`\n }\n\n return `./${basename(resolvedFilePath)}`\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { basename } from 'node:path'\n\nimport {\n AgentQaConfigSchema,\n discoverWorkspaceFiles,\n resolveWorkspacePaths,\n type WorkspaceFileRecord,\n} from '@vostride/agent-qa-core'\nimport { parse as parseYaml } from 'yaml'\n\nimport type { HookDeleteReference } from './hook-registry-types.js'\n\nconst HOOK_INLINE_RE = /\\{\\{runHook:\"([^\"]+)\"\\}\\}/g\n\nfunction getLabel(parsed: unknown, filePath: string): string {\n if (parsed && typeof parsed === 'object' && typeof (parsed as { name?: unknown }).name === 'string') {\n const name = (parsed as { name: string }).name.trim()\n if (name.length > 0) {\n return name\n }\n }\n\n return basename(filePath)\n}\n\nfunction collectHookListReferences(\n parsed: Record<string, unknown>,\n filePath: string,\n label: string,\n kind: 'test' | 'suite',\n key: 'setup' | 'teardown',\n hookId: string,\n): HookDeleteReference[] {\n const entries = parsed[key]\n if (!Array.isArray(entries)) {\n return []\n }\n\n return entries.flatMap((entry) => {\n if (entry !== hookId) {\n return []\n }\n\n return [{\n kind,\n label,\n path: filePath,\n context: key,\n }]\n })\n}\n\nfunction collectInlineReferences(\n parsed: Record<string, unknown>,\n filePath: string,\n label: string,\n hookId: string,\n): HookDeleteReference[] {\n const steps = parsed.steps\n if (!Array.isArray(steps)) {\n return []\n }\n\n return steps.flatMap((entry, index) => {\n const text = typeof entry === 'string'\n ? entry\n : entry && typeof entry === 'object' && typeof (entry as { step?: unknown }).step === 'string'\n ? (entry as { step: string }).step\n : null\n\n if (!text) {\n return []\n }\n\n const matches = [...text.matchAll(HOOK_INLINE_RE)]\n if (!matches.some((match) => match[1] === hookId)) {\n return []\n }\n\n return [{\n kind: 'inline-runHook',\n label,\n path: filePath,\n context: typeof entry === 'string' ? `steps[${index}]` : `steps[${index}].step`,\n }]\n })\n}\n\nasync function scanYamlFile(\n record: WorkspaceFileRecord,\n hookId: string,\n): Promise<HookDeleteReference[]> {\n let parsed: unknown\n\n try {\n parsed = parseYaml(await readFile(record.absolutePath, 'utf-8'))\n } catch {\n return []\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return []\n }\n\n const parsedRecord = parsed as Record<string, unknown>\n const label = getLabel(parsed, record.workspaceRelativePath)\n const kind = record.kind\n\n return [\n ...collectHookListReferences(parsedRecord, record.workspaceRelativePath, label, kind, 'setup', hookId),\n ...collectHookListReferences(parsedRecord, record.workspaceRelativePath, label, kind, 'teardown', hookId),\n ...collectInlineReferences(parsedRecord, record.workspaceRelativePath, label, hookId),\n ]\n}\n\nfunction dedupeReferences(references: HookDeleteReference[]): HookDeleteReference[] {\n const seen = new Set<string>()\n\n return references.filter((reference) => {\n const key = `${reference.kind}:${reference.path}:${reference.context}:${reference.label}`\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\nexport async function scanHookReferences(\n _workspaceDir: string,\n configPath: string,\n hookId: string,\n): Promise<HookDeleteReference[]> {\n let parsedConfig: unknown\n\n try {\n parsedConfig = parseYaml(await readFile(configPath, 'utf-8'))\n } catch {\n return []\n }\n\n const configResult = AgentQaConfigSchema.safeParse(parsedConfig)\n if (!configResult.success) {\n return []\n }\n\n const workspace = resolveWorkspacePaths({ config: configResult.data, configPath })\n const records = await Promise.all([\n discoverWorkspaceFiles({ workspace, kind: 'test' }),\n discoverWorkspaceFiles({ workspace, kind: 'suite' }),\n ])\n const references = await Promise.all(\n records\n .flat()\n .sort((left, right) => left.workspaceRelativePath.localeCompare(right.workspaceRelativePath))\n .map((record) => scanYamlFile(record, hookId)),\n )\n\n return dedupeReferences(references.flat()).sort((left, right) =>\n left.path.localeCompare(right.path) ||\n left.context.localeCompare(right.context) ||\n left.kind.localeCompare(right.kind) ||\n left.label.localeCompare(right.label),\n )\n}\n","import type { IncomingMessage } from 'node:http'\n\nconst DEFAULT_MAX_BYTES = 1024 * 1024 // 1MB\n\nexport function readJsonBody<T>(req: IncomingMessage, maxBytes = DEFAULT_MAX_BYTES): Promise<T> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let totalBytes = 0\n\n req.on('data', (chunk: Buffer) => {\n totalBytes += chunk.length\n if (totalBytes > maxBytes) {\n req.destroy()\n reject(new Error(`Body exceeds maximum size of ${maxBytes} bytes`))\n return\n }\n chunks.push(chunk)\n })\n\n req.on('end', () => {\n const body = Buffer.concat(chunks).toString('utf-8')\n if (!body) {\n reject(new Error('Empty request body'))\n return\n }\n try {\n resolve(JSON.parse(body) as T)\n } catch {\n reject(new Error('Invalid JSON in request body'))\n }\n })\n\n req.on('error', (err) => {\n reject(err)\n })\n })\n}\n","import { EventEmitter } from 'node:events'\nimport { spawn, execSync, type ChildProcess } from 'node:child_process'\nimport treeKill from 'tree-kill'\nimport type { ExecutionBackend, ExecuteOptions } from './execution-backend.js'\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 10_000\nconst DEFAULT_STALE_THRESHOLD_MS = 30_000\nconst PROCESS_TERMINATION_GRACE_MS = 5_000\nconst HANDLE_RETENTION_MS = 5 * 60 * 1000\n\nexport interface LiveExecutionEvent {\n id: number\n type: string\n [key: string]: unknown\n}\n\nexport interface TestRunHandle {\n runId: string\n process: ChildProcess\n status: 'running' | 'completed' | 'failed' | 'cancelled' | 'timeout'\n output: string[]\n startedAt: Date\n lastEventAt: number\n completionReason?: string\n}\n\nexport class TestRunner extends EventEmitter implements ExecutionBackend {\n private cliBin: string\n private defaultTimeout: number | undefined\n private handles = new Map<string, TestRunHandle>()\n private eventBuffers = new Map<string, LiveExecutionEvent[]>()\n private eventCounters = new Map<string, number>()\n private onProcessClose?: (runId: string, status: 'completed' | 'failed' | 'cancelled' | 'timeout') => void\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null\n private heartbeatIntervalMs: number\n private staleThresholdMs: number\n\n constructor(opts: {\n cliBin: string\n defaultTimeout?: number\n onProcessClose?: (runId: string, status: 'completed' | 'failed' | 'cancelled' | 'timeout') => void\n heartbeatIntervalMs?: number\n staleThresholdMs?: number\n }) {\n super()\n this.cliBin = opts.cliBin\n this.defaultTimeout = opts.defaultTimeout\n this.onProcessClose = opts.onProcessClose\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS\n this.staleThresholdMs = Math.max(\n opts.staleThresholdMs ?? DEFAULT_STALE_THRESHOLD_MS,\n this.heartbeatIntervalMs + 1,\n )\n }\n\n static resolveCliBin(): string {\n const envBin = process.env.AGENT_QA_CLI_BIN\n if (envBin) return envBin\n\n try {\n const which = execSync('which agent-qa', { encoding: 'utf-8' }).trim()\n if (which) return which\n } catch {\n // not found in PATH\n }\n\n return './node_modules/.bin/agent-qa'\n }\n\n execute(opts: ExecuteOptions): void {\n const spawnArgs = ['run', ...opts.args]\n const maxRetries = opts.maxRetries ?? 0\n\n const env: Record<string, string | undefined> = {\n ...process.env,\n ...opts.env,\n AGENT_QA_LIVE_EVENTS: 'true',\n }\n if (opts.attributes) {\n env.AGENT_QA_RUN_ATTRIBUTES_JSON = JSON.stringify(opts.attributes)\n }\n\n if (opts.source === 'suite') {\n // Suites create their own parent row via DashboardReporter.onSuiteStart\n // Pass the enqueued run ID so the suite can update it instead of creating a duplicate\n env.AGENT_QA_SUITE_QUEUE_ID = opts.runId\n } else if (maxRetries > 0) {\n // Retry-enabled: parent run stays in 'running', reporter creates child runs\n env.AGENT_QA_PARENT_RUN_ID = opts.runId\n env.AGENT_QA_MAX_RETRIES = String(maxRetries)\n } else {\n // No retries: reporter updates the existing run row directly\n env.AGENT_QA_RUN_ID = opts.runId\n }\n\n const child = spawn(this.cliBin, spawnArgs, {\n stdio: ['ignore', 'pipe', 'pipe'],\n env,\n detached: process.platform !== 'win32',\n })\n\n const handle: TestRunHandle = {\n runId: opts.runId,\n process: child,\n status: 'running',\n output: [],\n startedAt: new Date(),\n lastEventAt: Date.now(),\n }\n this.handles.set(opts.runId, handle)\n this.eventBuffers.set(opts.runId, [])\n this.eventCounters.set(opts.runId, 0)\n\n this.startHeartbeatChecker()\n\n const processTimeoutMs = opts.timeout ?? this.defaultTimeout\n let forceKillTimer: ReturnType<typeof setTimeout> | null = null\n const timer = typeof processTimeoutMs === 'number' && Number.isFinite(processTimeoutMs) && processTimeoutMs > 0\n ? setTimeout(() => {\n if (handle.status !== 'running') return\n handle.status = 'timeout'\n handle.completionReason = `process timeout after ${processTimeoutMs}ms`\n this.signalHandle(handle, 'SIGTERM')\n forceKillTimer = setTimeout(() => {\n this.signalHandle(handle, 'SIGKILL')\n }, PROCESS_TERMINATION_GRACE_MS)\n forceKillTimer.unref()\n }, processTimeoutMs)\n : null\n timer?.unref()\n\n this.pushEvent(opts.runId, { type: 'run-start', runId: opts.runId, status: 'running' })\n\n let stdoutBuffer = ''\n // Capture the actual test result status from the reporter (test-complete event).\n // This is the ground truth — process exit code can be misleading (e.g., mobile\n // tests exit non-zero from Appium cleanup even when all steps pass).\n let testResultStatus: string | undefined\n\n child.stdout?.on('data', (chunk: Buffer) => {\n stdoutBuffer += chunk.toString()\n const lines = stdoutBuffer.split('\\n')\n stdoutBuffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line) continue\n if (line.startsWith('AGENT_QA_EVENT:')) {\n try {\n const payload = JSON.parse(line.slice('AGENT_QA_EVENT:'.length))\n handle.lastEventAt = Date.now()\n if (payload.type === 'test-complete' && payload.status) {\n testResultStatus = payload.status\n }\n this.pushEvent(opts.runId, payload)\n } catch {\n handle.output.push(line)\n this.emit('output', opts.runId, line)\n }\n } else {\n handle.output.push(line)\n this.emit('output', opts.runId, line)\n }\n }\n })\n\n child.stderr?.on('data', (chunk: Buffer) => {\n const lines = chunk.toString().split('\\n').filter(Boolean)\n for (const line of lines) {\n handle.output.push(line)\n }\n })\n\n child.on('close', (code) => {\n if (timer) clearTimeout(timer)\n if (forceKillTimer) clearTimeout(forceKillTimer)\n if (stdoutBuffer) {\n if (stdoutBuffer.startsWith('AGENT_QA_EVENT:')) {\n try {\n const payload = JSON.parse(stdoutBuffer.slice('AGENT_QA_EVENT:'.length))\n if (payload.type === 'test-complete' && payload.status) {\n testResultStatus = payload.status\n }\n this.pushEvent(opts.runId, payload)\n } catch {\n handle.output.push(stdoutBuffer)\n }\n } else {\n handle.output.push(stdoutBuffer)\n }\n stdoutBuffer = ''\n }\n\n if (handle.status !== 'timeout' && handle.status !== 'cancelled' && handle.status !== 'failed') {\n // Use the actual test result from the reporter (test-complete event) as\n // ground truth. A clean process exit without reporter completion is incomplete.\n if (testResultStatus) {\n handle.status = testResultStatus === 'passed'\n ? 'completed'\n : testResultStatus === 'cancelled'\n ? 'cancelled'\n : 'failed'\n } else {\n handle.status = 'failed'\n handle.completionReason = 'process exited before test completed'\n }\n }\n\n const duration = Date.now() - handle.startedAt.getTime()\n this.pushEvent(opts.runId, {\n type: 'run-complete',\n runId: opts.runId,\n status: handle.status,\n duration,\n ...(handle.completionReason ? { reason: handle.completionReason } : {}),\n })\n\n if (this.onProcessClose) {\n this.onProcessClose(opts.runId, handle.status)\n }\n\n const cleanupTimer = setTimeout(() => {\n this.handles.delete(opts.runId)\n this.eventBuffers.delete(opts.runId)\n this.eventCounters.delete(opts.runId)\n }, HANDLE_RETENTION_MS)\n cleanupTimer.unref()\n })\n }\n\n getBufferedEvents(runId: string): LiveExecutionEvent[] {\n return this.eventBuffers.get(runId) ?? []\n }\n\n getHandle(runId: string): TestRunHandle | undefined {\n return this.handles.get(runId)\n }\n\n getActiveExecutions(): { runId: string; status: string; startedAt: string; duration: number; testName?: string }[] {\n const active: { runId: string; status: string; startedAt: string; duration: number; testName?: string }[] = []\n for (const handle of this.handles.values()) {\n if (handle.status === 'running') {\n const events = this.eventBuffers.get(handle.runId) ?? []\n const testStart = events.find(e => e.type === 'test-start')\n active.push({\n runId: handle.runId,\n status: handle.status,\n startedAt: handle.startedAt.toISOString(),\n duration: Date.now() - handle.startedAt.getTime(),\n testName: testStart?.testName as string | undefined,\n })\n }\n }\n return active\n }\n\n kill(runId: string): boolean {\n const handle = this.handles.get(runId)\n if (handle && handle.status === 'running') {\n this.signalHandle(handle, 'SIGINT')\n const forceTimer = setTimeout(() => {\n this.signalHandle(handle, 'SIGKILL')\n }, PROCESS_TERMINATION_GRACE_MS)\n forceTimer.unref()\n handle.process.once('close', () => clearTimeout(forceTimer))\n handle.status = 'cancelled'\n return true\n }\n return false\n }\n\n killAll(): void {\n for (const handle of this.handles.values()) {\n if (handle.status === 'running') {\n handle.status = 'cancelled'\n this.signalHandle(handle, 'SIGKILL')\n }\n }\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer)\n this.heartbeatTimer = null\n }\n }\n\n private startHeartbeatChecker(): void {\n if (this.heartbeatTimer) return\n this.heartbeatTimer = setInterval(() => {\n for (const handle of this.handles.values()) {\n if (handle.status !== 'running') continue\n if (Date.now() - handle.lastEventAt > this.staleThresholdMs) {\n handle.status = 'failed'\n handle.completionReason = 'stale process — no heartbeat'\n this.signalHandle(handle, 'SIGKILL')\n }\n }\n }, this.heartbeatIntervalMs)\n this.heartbeatTimer.unref()\n }\n\n private pushEvent(runId: string, payload: Record<string, unknown>): void {\n const counter = (this.eventCounters.get(runId) ?? 0) + 1\n this.eventCounters.set(runId, counter)\n\n const event: LiveExecutionEvent = { ...payload, id: counter } as LiveExecutionEvent\n const buffer = this.eventBuffers.get(runId)\n if (buffer) {\n buffer.push(event)\n }\n this.emit('execution-event', runId, event)\n }\n\n private signalHandle(handle: TestRunHandle, signal: NodeJS.Signals): void {\n const pid = handle.process.pid\n if (!pid) return\n\n if (process.platform === 'win32') {\n treeKill(pid, signal, () => {})\n return\n }\n\n try {\n process.kill(-pid, signal)\n return\n } catch {\n // Fall back to direct child signaling when the process group is unavailable.\n }\n\n try {\n handle.process.kill(signal)\n return\n } catch {\n // Fall back to tree-kill as a last resort.\n }\n\n treeKill(pid, signal, () => {})\n }\n}\n","import { EventEmitter } from 'node:events'\nimport { cpus } from 'node:os'\nimport type { RunArtifactKind, RunAttributes } from '@vostride/agent-qa-core'\nimport type { DashboardDatabase, RunRow } from '../db/database.js'\n\ninterface EnqueueOptions {\n name: string\n filePath?: string\n kind?: RunArtifactKind\n attributes?: RunAttributes\n priority?: number\n platform?: string\n testFileContent?: string\n modelName?: string\n llmProvider?: string\n metadata?: Record<string, unknown>\n parallel?: boolean\n}\n\nexport class JobQueue extends EventEmitter {\n private db: DashboardDatabase\n private pollInterval: ReturnType<typeof setInterval> | null = null\n private isProcessing = false\n private concurrency: number\n private activeCount = 0\n private activePlatforms = new Set<string>()\n private activeRuns = new Map<string, { platform: string }>()\n\n constructor(opts: { db: DashboardDatabase; concurrency?: number }) {\n super()\n this.db = opts.db\n this.concurrency = opts.concurrency ?? cpus().length\n }\n\n start(intervalMs = 1000): void {\n this.pollInterval = setInterval(() => this.processNext(), intervalMs)\n this.on('enqueued', () => this.processNext())\n }\n\n stop(): void {\n if (this.pollInterval) {\n clearInterval(this.pollInterval)\n this.pollInterval = null\n }\n this.removeAllListeners('enqueued')\n }\n\n enqueue(opts: EnqueueOptions): string {\n const runId = this.db.insertPendingRun({\n name: opts.name,\n filePath: opts.filePath,\n attributes: opts.attributes,\n priority: opts.priority ?? 0,\n platform: opts.platform,\n testFileContent: opts.testFileContent,\n modelName: opts.modelName,\n llmProvider: opts.llmProvider,\n metadata: opts.metadata,\n parallel: opts.parallel,\n })\n this.db.insertRunArtifact({\n runId,\n kind: opts.kind ?? 'test',\n payload: {\n runtime: {\n platform: opts.platform ?? 'web',\n queued: true,\n },\n source: {\n name: opts.name,\n filePath: opts.filePath ?? null,\n loadStatus: 'queued',\n },\n metadata: {\n ...opts.metadata,\n attributes: opts.attributes ?? {},\n },\n },\n })\n this.emit('enqueued', runId)\n return runId\n }\n\n processNext(): void {\n if (this.isProcessing) return\n this.isProcessing = true\n try {\n while (true) {\n const next = this.findNextEligible()\n if (!next) break\n\n const isParallel = Boolean(next.parallel)\n const platform = next.platform ?? 'web'\n const isMobile = platform === 'ios' || platform === 'android'\n\n this.activeCount++\n if (isMobile) this.activePlatforms.add(platform)\n this.activeRuns.set(next.id, { platform })\n\n this.db.updateRunStatus(next.id, 'running')\n this.db.updateRun(next.id, { startedAt: new Date().toISOString() })\n this.emit('execute', next)\n\n // Sequential jobs get exclusive access — stop filling slots after dequeue\n if (!isParallel && !isMobile) break\n }\n } finally {\n this.isProcessing = false\n }\n }\n\n onSlotFreed(runId: string): void {\n const info = this.activeRuns.get(runId)\n if (!info) return\n this.activeCount--\n if (info.platform === 'ios' || info.platform === 'android') {\n this.activePlatforms.delete(info.platform)\n }\n this.activeRuns.delete(runId)\n this.processNext()\n }\n\n getActiveCount(): number {\n return this.activeCount\n }\n\n getConcurrency(): number {\n return this.concurrency\n }\n\n cancel(runId: string): boolean {\n const run = this.db.getRun(runId)\n if (!run) return false\n const now = new Date().toISOString()\n if (run.status === 'pending') {\n this.db.updateRun(runId, { status: 'cancelled', endedAt: now })\n this.cancelChildRuns(runId, now)\n this.db.finalizeRunArtifact(runId, {\n errors: [{ code: 'cancelled', phase: 'queue', message: 'Run cancelled before execution' }],\n runtime: { status: 'cancelled' },\n })\n return true\n }\n if (run.status === 'running') {\n this.db.updateRun(runId, { status: 'cancelled', endedAt: now })\n this.cancelChildRuns(runId, now)\n try {\n const artifact = this.db.getRunArtifact(runId)\n if (artifact && !artifact.finalizedAt) {\n this.db.finalizeRunArtifact(runId, {\n errors: [{ code: 'cancelled', phase: 'queue', message: 'Run cancellation requested' }],\n runtime: { status: 'cancelled' },\n })\n }\n } catch { /* cancellation still proceeds */ }\n this.emit('cancel-running', runId)\n return true\n }\n return false\n }\n\n private cancelChildRuns(parentRunId: string, endedAt: string): void {\n for (const child of this.db.getRunsByParent(parentRunId)) {\n if (child.status !== 'running' && child.status !== 'pending') continue\n this.db.updateRun(child.id, {\n status: 'cancelled',\n endedAt,\n failureSummary: 'Run cancelled by user',\n })\n try {\n const artifact = this.db.getRunArtifact(child.id)\n if (artifact && !artifact.finalizedAt) {\n this.db.finalizeRunArtifact(child.id, {\n errors: [{ code: 'cancelled', phase: 'queue', message: 'Run cancelled by user' }],\n runtime: { status: 'cancelled' },\n })\n }\n } catch { /* best-effort child cancellation */ }\n }\n }\n\n private findNextEligible(): RunRow | undefined {\n if (this.activeCount >= this.concurrency) return undefined\n\n const pending = this.db.getPendingRuns()\n for (const run of pending) {\n const isParallel = Boolean(run.parallel)\n const platform = run.platform ?? 'web'\n const isMobile = platform === 'ios' || platform === 'android'\n\n if (isMobile) {\n // Mobile: needs a slot AND its platform not already active\n // parallel flag is ignored — mobile tests serialize per platform via device mutex\n if (this.activePlatforms.has(platform)) continue\n return run\n }\n\n if (!isParallel) {\n // Sequential web: needs ALL slots free (exclusive access)\n if (this.activeCount > 0) continue\n return run\n }\n\n // Parallel web: just needs an available slot\n return run\n }\n\n return undefined\n }\n}\n","import { readFile, writeFile, mkdir, stat, rm } from 'node:fs/promises'\nimport { dirname, basename } from 'node:path'\nimport { generateSuiteId } from '@vostride/agent-qa-ids'\nimport { parse as parseYaml } from 'yaml'\nimport { discoverWorkspaceFiles, resolveWorkspaceFileTarget, SuiteDefinitionSchema } from '@vostride/agent-qa-core'\nimport type { ResolvedWorkspacePaths, SuiteDefinition } from '@vostride/agent-qa-core'\nimport type { TestFileManager } from './test-file-manager.js'\n\ninterface SuiteFileInfo {\n path: string\n suiteId: string | null\n name: string\n testCount: number\n modified: string\n platform: string | null\n}\n\ninterface SuiteValidationResult {\n valid: boolean\n errors: { message: string; line?: number; column?: number; suggestion?: string }[]\n missingTests?: Array<{ index: number; test: string; id: string }>\n}\n\nexport class SuiteFileManager {\n private testFileManager: TestFileManager | undefined\n\n constructor(\n private readonly workspace: ResolvedWorkspacePaths,\n testFileManager?: TestFileManager,\n ) {\n this.testFileManager = testFileManager\n }\n\n async list(): Promise<SuiteFileInfo[]> {\n const records = await discoverWorkspaceFiles({ workspace: this.workspace, kind: 'suite' })\n const files: SuiteFileInfo[] = []\n\n for (const record of records) {\n try {\n const s = await stat(record.absolutePath)\n if (s.isFile()) {\n let suiteName = basename(record.workspaceRelativePath)\n let testCount = 0\n let platform: string | null = null\n let suiteId: string | null = null\n try {\n let content = await readFile(record.absolutePath, 'utf-8')\n const parsed = parseYaml(content)\n if (parsed?.name) suiteName = parsed.name\n if (Array.isArray(parsed?.tests)) testCount = parsed.tests.length\n platform = parsed?.config?.platform ?? null\n const suiteIdMatch = content.match(/^suite-id:\\s*(.+)$/m)\n if (suiteIdMatch) {\n suiteId = suiteIdMatch[1].trim().replace(/^[\"'](.*)[\"']$/, '$1')\n } else {\n suiteId = generateSuiteId()\n content = `suite-id: ${suiteId}\\n${content}`\n await writeFile(record.absolutePath, content, 'utf-8')\n }\n } catch { /* fall back to filename */ }\n files.push({\n path: record.workspaceRelativePath,\n suiteId,\n name: suiteName,\n testCount,\n modified: s.mtime.toISOString(),\n platform,\n })\n }\n } catch {\n // skip inaccessible files\n }\n }\n\n files.sort((a, b) => b.modified.localeCompare(a.modified))\n return files\n }\n\n async findBySuiteId(suiteId: string): Promise<{ path: string; content: string } | null> {\n const files = await this.list()\n const match = files.find(f => f.suiteId === suiteId)\n if (!match) return null\n const content = await this.read(match.path)\n return { path: match.path, content }\n }\n\n async resolvePath(filePath: string, requireExisting = true): Promise<{ storagePath: string; executionPath: string }> {\n const trimmedPath = filePath.trim()\n if (!trimmedPath) {\n throw new Error('Suite path is required')\n }\n\n const target = await resolveWorkspaceFileTarget({\n workspace: this.workspace,\n kind: 'suite',\n filePath: trimmedPath,\n requireExisting,\n })\n return { storagePath: target.workspaceRelativePath, executionPath: target.absolutePath }\n }\n\n async read(relativePath: string): Promise<string> {\n const target = await this.resolveTarget(relativePath, true)\n return readFile(target.absolutePath, 'utf-8')\n }\n\n async write(relativePath: string, content: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, false)\n await mkdir(dirname(target.absolutePath), { recursive: true })\n await writeFile(target.absolutePath, content, 'utf-8')\n }\n\n async delete(relativePath: string): Promise<void> {\n const target = await this.resolveTarget(relativePath, true)\n await rm(target.absolutePath)\n }\n\n async validate(content: string): Promise<SuiteValidationResult> {\n try {\n const parsed = parseYaml(content)\n const result = SuiteDefinitionSchema.safeParse(parsed)\n\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.issues.map((issue: { path: PropertyKey[]; message: string }) => ({\n message: `${issue.path.map(String).join('.')}: ${issue.message}`,\n })),\n }\n }\n\n // Save-time fail-fast: verify every referenced test path resolves (Phase 181 D-32/D-33)\n if (this.testFileManager) {\n const suite = result.data as SuiteDefinition\n const available = await this.testFileManager.list()\n const availablePaths = new Set(available.map((f) => f.path))\n const missingTests: Array<{ index: number; test: string; id: string }> = []\n suite.tests.forEach((entry: SuiteDefinition['tests'][number], index: number) => {\n if (!availablePaths.has(entry.test)) {\n // Report the ORIGINAL entry.test so the user sees what they wrote\n missingTests.push({ index, test: entry.test, id: entry.id })\n }\n })\n if (missingTests.length > 0) {\n return {\n valid: false,\n errors: [{\n message: `Cannot save — referenced tests not found: ${missingTests.map(m => m.test).join(', ')}`,\n }],\n missingTests,\n }\n }\n }\n\n return { valid: true, errors: [] }\n } catch (err) {\n return {\n valid: false,\n errors: [{ message: err instanceof Error ? err.message : 'Failed to parse YAML' }],\n }\n }\n }\n\n private async resolveTarget(relativePath: string, requireExisting: boolean) {\n return resolveWorkspaceFileTarget({\n workspace: this.workspace,\n kind: 'suite',\n filePath: relativePath,\n requireExisting,\n })\n }\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport { parseDocument, stringify, type Document } from 'yaml'\n\nconst SENSITIVE_KEYS = new Set(['apikey', 'token', 'key', 'accesskey'])\n\nfunction isSensitiveKey(key: string): boolean {\n return SENSITIVE_KEYS.has(key.toLowerCase())\n}\n\nfunction maskValue(value: string): string {\n if (value.length >= 8) {\n return value.slice(0, 3) + '****...' + value.slice(-4)\n }\n return '****'\n}\n\nfunction deepMask(obj: unknown, parentKey = ''): unknown {\n if (typeof obj === 'string' && isSensitiveKey(parentKey)) {\n return maskValue(obj)\n }\n if (Array.isArray(obj)) {\n return obj.map((item, i) => deepMask(item, String(i)))\n }\n if (typeof obj === 'object' && obj !== null) {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[key] = deepMask(value, key)\n }\n return result\n }\n return obj\n}\n\nexport class ConfigManager {\n constructor(private configPath: string) {}\n\n async read(): Promise<Record<string, unknown>> {\n try {\n const content = await readFile(this.configPath, 'utf-8')\n const doc = parseDocument(content)\n return (doc.toJSON() as Record<string, unknown>) ?? {}\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return {}\n throw err\n }\n }\n\n async readMasked(): Promise<Record<string, unknown>> {\n const config = await this.read()\n return deepMask(config) as Record<string, unknown>\n }\n\n private sectionPath(section: string): string[] {\n return section.includes('.') ? section.split('.') : [section]\n }\n\n async updateSection(section: string, value: Record<string, unknown>): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({ [section]: value }))\n return\n }\n throw err\n }\n\n const doc = parseDocument(content)\n for (const [key, val] of Object.entries(value)) {\n doc.setIn([...path, key], val)\n }\n await writeFile(this.configPath, doc.toString())\n }\n\n async replaceSection(section: string, value: Record<string, unknown>): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({ [section]: value }))\n return\n }\n throw err\n }\n const doc = parseDocument(content)\n // Overwrite in-place to preserve key ordering in the YAML file\n doc.setIn(path, doc.createNode(value))\n await writeFile(this.configPath, doc.toString())\n }\n\n async replaceSectionRaw(section: string, value: unknown): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({ [section]: value }))\n return\n }\n throw err\n }\n const doc = parseDocument(content)\n // Overwrite in-place to preserve key ordering in the YAML file\n doc.setIn(path, doc.createNode(value))\n await writeFile(this.configPath, doc.toString())\n }\n\n async deleteSectionRaw(section: string): Promise<void> {\n const path = this.sectionPath(section)\n let content: string\n try {\n content = await readFile(this.configPath, 'utf-8')\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n await mkdir(dirname(this.configPath), { recursive: true })\n await writeFile(this.configPath, stringify({}))\n return\n }\n throw err\n }\n const doc = parseDocument(content)\n doc.deleteIn(path)\n await writeFile(this.configPath, doc.toString())\n }\n\n async readDocument(): Promise<Document> {\n const content = await readFile(this.configPath, 'utf-8')\n return parseDocument(content)\n }\n}\n","import { request } from 'node:http'\nimport { spawn, type ChildProcess } from 'node:child_process'\nimport {\n formatAppiumInstallGuidance,\n resolveAppiumExecutable,\n type ResolvedAppiumExecutable,\n} from '@vostride/agent-qa-core'\nimport treeKill from 'tree-kill'\nimport pc from 'picocolors'\n\nconst APPIUM_PREFIX = pc.magenta('[appium]')\n\nexport interface AppiumLeaseOwner {\n runId: string\n platform: 'android' | 'ios'\n}\n\nexport interface AppiumLease extends AppiumLeaseOwner {\n acquiredAt: string\n}\n\nexport class AppiumManager {\n private process: ChildProcess | null = null\n private port: number\n private ready = false\n private startPromise: Promise<void> | null = null\n private managed = false\n private startupTimeoutMs: number\n private pollIntervalMs: number\n private anonymousRefCount = 0\n private leases = new Map<string, AppiumLease>()\n private logLevel: 'normal' | 'debug'\n private appiumResolver: () => ResolvedAppiumExecutable\n\n constructor(opts?: {\n port?: number\n startupTimeoutMs?: number\n pollIntervalMs?: number\n logLevel?: 'normal' | 'debug'\n appiumResolver?: () => ResolvedAppiumExecutable\n }) {\n this.port = opts?.port ?? 4723\n this.startupTimeoutMs = opts?.startupTimeoutMs ?? 30_000\n this.pollIntervalMs = opts?.pollIntervalMs ?? 500\n this.logLevel = opts?.logLevel ?? 'normal'\n this.appiumResolver = opts?.appiumResolver ?? resolveAppiumExecutable\n }\n\n async acquire(): Promise<void> {\n await this.ensureRunning()\n this.anonymousRefCount++\n }\n\n release(): void {\n if (this.anonymousRefCount > 0) this.anonymousRefCount--\n this.maybeShutdownAfterRelease()\n }\n\n async acquireLease(owner: AppiumLeaseOwner): Promise<void> {\n await this.ensureRunning()\n if (!this.leases.has(owner.runId)) {\n this.leases.set(owner.runId, {\n runId: owner.runId,\n platform: owner.platform,\n acquiredAt: new Date().toISOString(),\n })\n }\n console.log(`${APPIUM_PREFIX} lease acquired run=${owner.runId} platform=${owner.platform} leases=${this.getLeaseCount()} managed=${this.managed}`)\n }\n\n releaseLease(runId: string, reason = 'completed'): boolean {\n const lease = this.leases.get(runId)\n if (!lease) return false\n\n this.leases.delete(runId)\n console.log(`${APPIUM_PREFIX} lease released run=${runId} platform=${lease.platform} reason=${reason} leases=${this.getLeaseCount()} managed=${this.managed}`)\n this.maybeShutdownAfterRelease()\n return true\n }\n\n releaseAllLeases(reason = 'shutdown'): string[] {\n const runIds = [...this.leases.keys()]\n for (const runId of runIds) {\n this.releaseLease(runId, reason)\n }\n return runIds\n }\n\n async ensureRunning(): Promise<void> {\n if (this.ready) {\n const still = await this.checkStatus()\n if (still) return\n this.ready = false\n }\n\n if (this.startPromise) {\n await this.startPromise\n return\n }\n\n this.startPromise = (async () => {\n const alive = await this.checkStatus()\n if (alive) {\n this.ready = true\n this.managed = false\n return\n }\n await this.startAndWait()\n })()\n\n try {\n await this.startPromise\n } finally {\n this.startPromise = null\n }\n }\n\n async checkStatus(): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const req = request(\n {\n hostname: 'localhost',\n port: this.port,\n path: '/status',\n method: 'GET',\n timeout: 3000,\n },\n (res) => {\n let data = ''\n res.on('data', (chunk: Buffer) => {\n data += chunk.toString()\n })\n res.on('end', () => {\n try {\n const parsed = JSON.parse(data)\n resolve(parsed?.value?.ready === true)\n } catch {\n resolve(false)\n }\n })\n },\n )\n req.on('error', () => resolve(false))\n req.on('timeout', () => {\n req.destroy()\n resolve(false)\n })\n req.end()\n })\n }\n\n private async startAndWait(): Promise<void> {\n const appium = this.appiumResolver()\n const child = spawn(appium.command, ['-p', String(this.port), '--relaxed-security', '--log-no-colors'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n this.process = child\n this.managed = true\n\n child.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ENOENT') {\n console.error(`${APPIUM_PREFIX} Appium not found. ${formatAppiumInstallGuidance()}`)\n } else {\n console.error(`${APPIUM_PREFIX} Error: ${err.message}`)\n }\n })\n\n child.stdout?.on('data', (chunk: Buffer) => {\n if (this.logLevel !== 'debug') return\n const lines = chunk.toString().split('\\n').filter(Boolean)\n for (const line of lines) {\n console.log(`${APPIUM_PREFIX} ${pc.dim(line)}`)\n }\n })\n\n child.stderr?.on('data', (chunk: Buffer) => {\n if (this.logLevel !== 'debug') return\n const lines = chunk.toString().split('\\n').filter(Boolean)\n for (const line of lines) {\n console.error(`${APPIUM_PREFIX} ${pc.dim(line)}`)\n }\n })\n\n const start = Date.now()\n while (Date.now() - start < this.startupTimeoutMs) {\n const ok = await this.checkStatus()\n if (ok) {\n this.ready = true\n console.log(`${APPIUM_PREFIX} ${pc.green(`started on :${this.port}`)}`)\n return\n }\n await new Promise((r) => setTimeout(r, this.pollIntervalMs))\n }\n\n // Timeout — kill and throw\n if (child.pid) {\n treeKill(child.pid, 'SIGKILL', () => {})\n }\n this.process = null\n this.managed = false\n throw new Error(`Appium server did not become ready within ${this.startupTimeoutMs}ms`)\n }\n\n private performShutdown(): void {\n if (this.process?.pid && this.managed) {\n treeKill(this.process.pid, 'SIGKILL', () => {})\n console.log(`${APPIUM_PREFIX} ${pc.yellow('stopped')}`)\n }\n this.process = null\n this.ready = false\n this.managed = false\n }\n\n private maybeShutdownAfterRelease(): void {\n if (this.getRefCount() > 0) {\n console.log(`${APPIUM_PREFIX} server kept alive leases=${this.getLeaseCount()} managed=${this.managed}`)\n return\n }\n if (this.managed) {\n this.performShutdown()\n return\n }\n if (this.ready) {\n console.log(`${APPIUM_PREFIX} external server left running leases=0 managed=false`)\n }\n }\n\n shutdown(): void {\n this.anonymousRefCount = 0\n this.leases.clear()\n this.performShutdown()\n }\n\n getUrl(): string {\n return `http://localhost:${this.port}`\n }\n\n getPort(): number {\n return this.port\n }\n\n isManaged(): boolean {\n return this.managed\n }\n\n getRefCount(): number {\n return this.anonymousRefCount + this.leases.size\n }\n\n getLeaseCount(): number {\n return this.leases.size\n }\n\n getLeases(): AppiumLease[] {\n return [...this.leases.values()]\n }\n\n hasLease(runId: string): boolean {\n return this.leases.has(runId)\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { LiveSession } from './live-session.js'\nimport type { SessionState, LiveSessionConfig, EntityRef } from './types.js'\nimport type { AppiumManager } from '../execution/appium-manager.js'\nimport type { ConfigManager } from '../config/index.js'\n\nexport interface SessionManagerDeps {\n appiumManager?: AppiumManager\n configManager?: ConfigManager\n configPath?: string\n}\n\nexport class SessionManager {\n private sessions = new Map<string, LiveSession>()\n // Per-entity counter keyed by `${entityType}:${entityId}`.\n // Monotonic and ephemeral: resets on server restart per CONTEXT D-30.\n // Never decremented on terminate — a re-open of a terminated entity yields\n // the next number so \"Session #3\" after \"#2\" ends does not confuse users.\n private counters = new Map<string, number>()\n\n constructor(private deps: SessionManagerDeps = {}) {}\n\n async createSession(\n config: LiveSessionConfig,\n entity?: EntityRef,\n ): Promise<{ sessionId: string; sessionNumber: number | null }> {\n if (!config.llmConfig) {\n throw new Error('LLM not configured')\n }\n\n const sessionId = randomUUID()\n const session = new LiveSession(sessionId, this.deps)\n await session.initialize(config)\n this.sessions.set(sessionId, session)\n\n // sessionNumber is used for display only; never for authorization lookups\n // (always use sessionId UUID for that — see threat T-181.1-07).\n let sessionNumber: number | null = null\n if (entity && entity.id) {\n const key = `${entity.type}:${entity.id}`\n sessionNumber = (this.counters.get(key) ?? 0) + 1\n this.counters.set(key, sessionNumber)\n }\n\n return { sessionId, sessionNumber }\n }\n\n getSession(sessionId: string): LiveSession | undefined {\n return this.sessions.get(sessionId)\n }\n\n listSessions(): SessionState[] {\n return Array.from(this.sessions.values()).map(s => s.getState())\n }\n\n async terminateSession(sessionId: string): Promise<boolean> {\n const session = this.sessions.get(sessionId)\n if (!session) return false\n await session.cleanup()\n this.sessions.delete(sessionId)\n // Note: `counters` intentionally left untouched — per D-30 the counter is\n // monotonic per-restart.\n return true\n }\n\n async cleanupAll(): Promise<void> {\n for (const session of this.sessions.values()) {\n try { await session.cleanup() } catch {}\n }\n this.sessions.clear()\n }\n\n getCounter(entity: EntityRef): number {\n return this.counters.get(`${entity.type}:${entity.id}`) ?? 0\n }\n\n get size(): number {\n return this.sessions.size\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { dirname, resolve as resolvePath } from 'node:path'\nimport {\n AUTH_STATE_SCHEMA_VERSION,\n executeStep,\n createModel,\n getProviderOptions,\n LLMPlanner,\n LLMVerifier,\n VariableStore,\n interpolateVariables,\n findUnresolvedTemplates,\n parseHookInline,\n stripHookInline,\n runHooks,\n runHookInSandbox,\n MobileSetupError,\n readAuthStateMetadata,\n redactAuthStateValue,\n resolveAuthStatePaths,\n resolveSecretTemplatesInValue,\n writeAuthStateFiles,\n} from '@vostride/agent-qa-core'\nimport type {\n AgentLoopConfig,\n AuthStateMetadata,\n StepContext,\n PlatformAdapter,\n PlatformConfig,\n StepResult,\n StepPhaseEvent,\n HookDefinition,\n MobilePlatform,\n SecretRedactor,\n SecretStore,\n} from '@vostride/agent-qa-core'\nimport type { LanguageModel } from 'ai'\nimport { prepareMobileLiveSession } from './mobile-bootstrap.js'\nimport type { MobileLiveAppiumLease } from './mobile-bootstrap.js'\nimport type { AppiumManager } from '../execution/appium-manager.js'\nimport type { ConfigManager } from '../config/index.js'\nimport type {\n SessionState,\n LiveDraftMetadata,\n LiveExecutionLog,\n LiveHookOwner,\n LiveSessionConfig,\n LiveStepResultPayload,\n LiveSubActionData,\n LiveHookPayload,\n LiveTestExecutionPayload,\n LiveTestResultPayload,\n LiveTestStepPayload,\n ServerMessage,\n} from './types.js'\n\nconst IDLE_TIMEOUT_MS = 5 * 60 * 1000\n\nconst RUNJS_DBL_RE = /\\{\\{runJS:\"((?:[^\"\\\\]|\\\\.)*)\"\\}\\}/g\nconst RUNJS_SGL_RE = /\\{\\{runJS:'((?:[^'\\\\]|\\\\.)*)'\\}\\}/g\n\nexport interface LiveSessionDeps {\n appiumManager?: AppiumManager\n configManager?: ConfigManager\n configPath?: string\n}\n\nexport interface LiveStepExecutionResult extends StepResult {\n executionLogs?: LiveExecutionLog[]\n subActionsData?: LiveSubActionData[]\n}\n\ninterface WebStorageStateContext {\n storageState(options?: { indexedDB?: boolean }): Promise<unknown>\n}\n\ninterface WebStorageStatePage {\n context(): WebStorageStateContext\n}\n\n// Shared with ws-handler.ts toStepResultPayload. Kept in-module so that\n// executeTestCommand can assemble its stepResults array without a\n// cross-module import that would create a circular dependency.\nfunction toStepResultPayload(result: LiveStepExecutionResult): LiveStepResultPayload {\n const status = result.status === 'passed'\n ? 'passed'\n : result.status === 'cancelled'\n ? 'cancelled'\n : 'failed'\n\n return {\n status,\n duration: result.duration,\n error: result.error,\n capturedVariables: result.capturedVariables,\n variableSnapshot: result.variableSnapshot,\n originalStepName: result.originalStepName,\n consoleLogs: result.consoleLogs,\n networkLogs: result.networkLogs,\n executionLogs: result.executionLogs,\n subActionsData: result.subActionsData,\n }\n}\n\ninterface RunJSMatch {\n fullMatch: string\n code: string\n}\n\nfunction parseRunJSInline(text: string): RunJSMatch[] {\n const matches: RunJSMatch[] = []\n for (const match of text.matchAll(RUNJS_DBL_RE)) {\n matches.push({ fullMatch: match[0], code: match[1] })\n }\n for (const match of text.matchAll(RUNJS_SGL_RE)) {\n matches.push({ fullMatch: match[0], code: match[1] })\n }\n return matches.sort((a, b) => text.indexOf(a.fullMatch) - text.indexOf(b.fullMatch))\n}\n\nfunction coerceRunJSResult(value: unknown): string {\n if (value === undefined) return 'undefined'\n if (value === null) return 'null'\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n return String(value)\n }\n return JSON.stringify(value)\n}\n\nfunction getWebStorageStateContext(adapter: PlatformAdapter | null): WebStorageStateContext | null {\n if (!adapter || !('getPage' in adapter)) return null\n const page = (adapter as { getPage?: () => unknown }).getPage?.()\n if (!page || typeof page !== 'object') return null\n\n const contextFactory = (page as Partial<WebStorageStatePage>).context\n if (typeof contextFactory !== 'function') return null\n\n const context = contextFactory.call(page)\n if (!context || typeof context !== 'object') return null\n\n const storageState = (context as Partial<WebStorageStateContext>).storageState\n if (typeof storageState !== 'function') return null\n return context as WebStorageStateContext\n}\n\nfunction getConfiguredAuthStateDir(config: Record<string, unknown>): string | undefined {\n const services = config.services\n if (!services || typeof services !== 'object') return undefined\n const authState = (services as Record<string, unknown>).authState\n if (!authState || typeof authState !== 'object') return undefined\n const dir = (authState as Record<string, unknown>).dir\n return typeof dir === 'string' ? dir : undefined\n}\n\nfunction toLiveSubActionData(result: StepResult): LiveSubActionData[] | undefined {\n return result.trace?.subActions?.map((subAction) => ({\n index: subAction.index,\n observation: subAction.observation,\n reasoning: subAction.reasoning,\n plannedAction: subAction.plannedAction,\n result: subAction.result,\n error: subAction.error,\n screenStateBefore: subAction.screenStateBefore,\n screenStateAfter: subAction.screenStateAfter,\n confidence: subAction.confidence,\n verifierReasoning: subAction.verifierReasoning,\n cached: subAction.cached,\n tokenUsage: subAction.tokenUsage,\n phaseDurations: subAction.phaseDurations,\n annotation: subAction.annotation,\n screenContextBefore: subAction.screenContextBefore,\n screenContextAfter: subAction.screenContextAfter,\n data: subAction.data,\n }))\n}\n\nfunction mobileSetupMessage(err: MobileSetupError): string {\n return `${err.category}: ${err.message}`\n}\n\nfunction classifyAdapterSetupError(err: unknown): MobileSetupError['category'] {\n const message = err instanceof Error ? err.message : String(err)\n if (/appium|ECONNREFUSED|connect|\\/session|status/i.test(message)) {\n return 'appium-startup'\n }\n return 'device-readiness'\n}\n\nfunction wrapAdapterSetupError(\n err: unknown,\n platform: MobilePlatform,\n config: PlatformConfig,\n): MobileSetupError {\n if (err instanceof MobileSetupError) return err\n const appId = platform === 'android'\n ? config.appPackage\n : config.bundleId\n return new MobileSetupError({\n category: classifyAdapterSetupError(err),\n message: `Failed to create ${platform} adapter session: ${err instanceof Error ? err.message : String(err)}`,\n platform,\n deviceName: config.device?.name,\n appId,\n cause: err,\n })\n}\n\nfunction buildHookExecutionLog(hook: LiveHookPayload): LiveExecutionLog {\n return {\n id: hook.executionId,\n type: 'hook',\n name: hook.hookName,\n hookId: hook.hookId,\n phase: hook.phase,\n status: hook.status === 'failed' ? 'failed' : 'passed',\n duration: hook.duration ?? 0,\n stdout: hook.stdout ?? null,\n stderr: hook.stderr ?? null,\n returnData: null,\n variables: hook.variables ?? null,\n createdAt: hook.createdAt,\n }\n}\n\nexport class LiveSession {\n readonly sessionId: string\n status: 'idle' | 'executing' | 'disconnected' | 'terminated' = 'idle'\n private abortController: AbortController | null = null\n stepsExecuted = 0\n createdAt = 0\n\n private adapter: PlatformAdapter | null = null\n private planner: LLMPlanner | null = null\n private verifier: LLMVerifier | null = null\n private model: LanguageModel | null = null\n private variableStore: VariableStore | null = null\n private previousSteps: { instruction: string; outcome: string; reasoning?: string; plannedAction?: string; verifierResponse?: string }[] = []\n private currentStep: string | null = null\n private platform: 'web' | 'android' | 'ios' = 'web'\n private targetName: string | null = null\n private currentUrl: string | null = null\n private executing = false\n private idleTimer: ReturnType<typeof setTimeout> | null = null\n private _modelName = 'unknown'\n private screenshotSize: number | undefined\n private effectiveResolution: number | undefined\n private readyForInteraction = false\n private terminalError: string | null = null\n private setupHooks: string[] = []\n private teardownHooks: string[] = []\n private resolvedHooks = new Map<string, HookDefinition>()\n private hookRegistryError: string | null = null\n private pendingMessages: ServerMessage[] = []\n private messageSink: ((message: ServerMessage) => void) | null = null\n private mobileAppiumLease: MobileLiveAppiumLease | null = null\n private secretStore: SecretStore | undefined\n private secretRedactor: SecretRedactor | undefined\n\n constructor(sessionId: string, private deps: LiveSessionDeps = {}) {\n this.sessionId = sessionId\n }\n\n get modelName(): string {\n return this._modelName\n }\n\n attachMessageSink(sink: ((message: ServerMessage) => void) | null): void {\n this.messageSink = sink\n if (!sink || this.pendingMessages.length === 0) return\n\n for (const message of this.pendingMessages) {\n sink(message)\n }\n this.pendingMessages = []\n }\n\n private dispatch(message: ServerMessage): void {\n message = this.redact(message)\n if (this.messageSink) {\n this.messageSink(message)\n return\n }\n this.pendingMessages.push(message)\n }\n\n private redact<T>(value: T): T {\n return redactAuthStateValue(value, { secretRedactor: this.secretRedactor })\n }\n\n private resolveSecrets<T>(value: T): T {\n return resolveSecretTemplatesInValue(value, this.secretStore)\n }\n\n private emitHookStart(\n hookDef: Pick<HookDefinition, 'id' | 'name'>,\n phase: 'setup' | 'teardown',\n owner: LiveHookOwner = { scope: 'suite' },\n ): LiveHookPayload {\n const hook: LiveHookPayload = {\n executionId: randomUUID(),\n hookId: hookDef.id,\n hookName: hookDef.name,\n phase,\n owner,\n status: 'running',\n createdAt: new Date().toISOString(),\n }\n this.dispatch({ type: 'hook-start', hook })\n return hook\n }\n\n private emitHookComplete(\n started: LiveHookPayload,\n updates: Omit<LiveHookPayload, 'executionId' | 'hookId' | 'hookName' | 'phase' | 'owner' | 'createdAt'>,\n ): LiveHookPayload {\n const hook: LiveHookPayload = this.redact({\n ...started,\n ...updates,\n })\n this.dispatch({ type: 'hook-complete', hook })\n return hook\n }\n\n private emitTestStepStart(step: LiveTestStepPayload): void {\n this.dispatch({ type: 'test-step-start', step })\n }\n\n private emitTestStepPhase(step: LiveTestStepPayload, event: StepPhaseEvent): void {\n this.dispatch({\n type: 'test-step-phase',\n step,\n phase: event.phase,\n data: {\n text: event.text,\n confidence: event.confidence,\n action: event.action,\n success: event.success,\n duration: event.duration,\n },\n })\n }\n\n private emitTestStepComplete(step: LiveTestStepPayload, result: LiveStepExecutionResult): void {\n if (result.status === 'cancelled') {\n this.dispatch({ type: 'test-step-cancelled', step })\n return\n }\n\n this.dispatch({\n type: 'test-step-complete',\n step,\n result: toStepResultPayload(result),\n })\n }\n\n private emitTestStepError(step: LiveTestStepPayload, error: string): void {\n this.dispatch({ type: 'test-step-error', step, error })\n }\n\n private getHookEnvVars(): Record<string, string> {\n const envVars: Record<string, string> = {}\n if (!this.variableStore) return envVars\n\n for (const [key, value] of this.variableStore.getAll()) {\n envVars[key] = value\n }\n\n return envVars\n }\n\n private async runLifecycleHooks(\n phase: 'setup' | 'teardown',\n hookIds: string[],\n owner: LiveHookOwner = { scope: 'suite' },\n ): Promise<{ allPassed: boolean; logs: LiveExecutionLog[] }> {\n const logs: LiveExecutionLog[] = []\n\n for (const hookId of hookIds) {\n const hookDef = this.resolvedHooks.get(hookId)\n const started = this.emitHookStart(\n hookDef ?? { id: hookId, name: hookId },\n phase,\n owner,\n )\n\n if (!hookDef) {\n const registryHint = this.hookRegistryError ? ` (${this.hookRegistryError})` : ''\n const completed = this.emitHookComplete(started, {\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: this.hookRegistryError ?? null,\n variables: null,\n error: `Hook ID \"${hookId}\" is not defined in hooks.yaml${registryHint}`,\n })\n logs.push(buildHookExecutionLog(completed))\n if (phase === 'setup') {\n return { allPassed: false, logs }\n }\n continue\n }\n\n const result = await runHooks([hookDef], {\n envVars: this.getHookEnvVars(),\n secretStore: this.secretStore,\n secretRedactor: this.secretRedactor,\n })\n const hookResult = result.results.get(hookDef.name)\n const completed = this.emitHookComplete(started, {\n status: hookResult?.success ? 'passed' : 'failed',\n duration: hookResult?.duration ?? 0,\n stdout: hookResult?.stdout ?? null,\n stderr: hookResult?.stderr ?? null,\n variables: hookResult && Object.keys(hookResult.variables).length > 0 ? hookResult.variables : null,\n error: hookResult?.error,\n })\n logs.push(buildHookExecutionLog(completed))\n\n if (hookResult?.success && hookResult.variables && this.variableStore) {\n this.variableStore.setAll(hookResult.variables, 'hook')\n }\n\n if (!hookResult?.success && phase === 'setup') {\n return { allPassed: false, logs }\n }\n }\n\n return { allPassed: true, logs }\n }\n\n async executeHookCommand(\n phase: 'setup' | 'teardown',\n hookId: string,\n ): Promise<LiveExecutionLog> {\n if (!this.readyForInteraction || !this.variableStore) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n\n if (this.executing) {\n throw new Error('Live session is busy')\n }\n\n this.executing = true\n this.status = 'executing'\n const hookName = this.resolvedHooks.get(hookId)?.name ?? hookId\n this.currentStep = `${phase} hook: ${hookName}`\n\n try {\n const { logs } = await this.runLifecycleHooks(phase, [hookId])\n return logs[0] ?? {\n id: randomUUID(),\n type: 'hook',\n name: hookName,\n hookId,\n phase,\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: null,\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n }\n } finally {\n this.executing = false\n this.currentStep = null\n this.status = 'idle'\n }\n }\n\n private releaseMobileAppiumLease(reason: string): void {\n if (!this.mobileAppiumLease) return\n this.mobileAppiumLease.release(reason)\n this.mobileAppiumLease = null\n }\n\n private legacyMobilePlatformConfig(config: LiveSessionConfig): PlatformConfig {\n const platform = config.platform as MobilePlatform\n return {\n platform,\n bundleId: config.bundleId,\n appPackage: config.appPackage,\n appActivity: config.appActivity,\n deepLinkAppId: platform === 'android' ? config.appPackage : config.bundleId,\n appState: config.appState,\n device: config.device\n ? {\n name: config.device.name,\n platform,\n transport: 'local',\n match: config.device,\n }\n : undefined,\n }\n }\n\n private async resolveMobilePlatformConfig(config: LiveSessionConfig): Promise<PlatformConfig> {\n if (\n this.deps.appiumManager\n && this.deps.configManager\n && this.deps.configPath\n && config.targetName\n ) {\n const prepared = await prepareMobileLiveSession({\n sessionId: this.sessionId,\n platform: config.platform as MobilePlatform,\n targetName: config.targetName,\n useDeviceName: config.useDeviceName,\n appState: config.appState,\n appiumManager: this.deps.appiumManager,\n configManager: this.deps.configManager,\n configPath: this.deps.configPath,\n })\n this.mobileAppiumLease = prepared.appiumLease\n return prepared.platformConfig\n }\n\n return this.legacyMobilePlatformConfig(config)\n }\n\n private async setupMobileAdapter(platform: MobilePlatform, config: LiveSessionConfig): Promise<void> {\n let adapter: PlatformAdapter | null = null\n try {\n const platformConfig = await this.resolveMobilePlatformConfig(config)\n const platformLabel = platform === 'android' ? 'Android' : 'iOS'\n try {\n if (platform === 'android') {\n const { AndroidPlatformAdapter } = await import('@vostride/agent-qa-android')\n adapter = new AndroidPlatformAdapter()\n } else {\n const { IOSPlatformAdapter } = await import('@vostride/agent-qa-ios')\n adapter = new IOSPlatformAdapter()\n }\n } catch (err) {\n throw new MobileSetupError({\n category: 'adapter-load',\n message: `Failed to load ${platformLabel} adapter (@vostride/agent-qa-${platform}). Is the package installed? ${err instanceof Error ? err.message : String(err)}`,\n platform,\n targetName: config.targetName,\n deviceName: platformConfig.device?.name,\n appId: platform === 'android' ? platformConfig.appPackage : platformConfig.bundleId,\n cause: err,\n })\n }\n\n try {\n await adapter.setup(platformConfig)\n } catch (err) {\n throw wrapAdapterSetupError(err, platform, platformConfig)\n }\n this.adapter = adapter\n } catch (err) {\n try {\n await adapter?.cleanup()\n } catch {}\n this.releaseMobileAppiumLease('setup-failed')\n if (err instanceof MobileSetupError) {\n throw new Error(mobileSetupMessage(err))\n }\n throw err\n }\n }\n\n async initialize(config: LiveSessionConfig): Promise<void> {\n this.platform = config.platform\n this.targetName = typeof config.targetName === 'string' && config.targetName.trim().length > 0\n ? config.targetName.trim()\n : null\n this._modelName = config.llmConfig.model ?? 'unknown'\n this.variableStore = new VariableStore()\n this.secretStore = config.secretStore\n this.secretRedactor = config.secretRedactor\n if (config.envVars) {\n this.variableStore.setAll(config.envVars, 'env')\n }\n this.setupHooks = [...(config.setupHooks ?? [])]\n this.teardownHooks = [...(config.teardownHooks ?? [])]\n this.resolvedHooks = new Map(config.resolvedHooks ?? [])\n this.hookRegistryError = config.hookRegistryError ?? null\n this.screenshotSize = config.llmConfig.screenshotSize\n this.effectiveResolution = config.llmConfig.effectiveResolution\n this.readyForInteraction = false\n this.terminalError = null\n\n const setupResult = await this.runLifecycleHooks('setup', this.setupHooks)\n if (!setupResult.allPassed) {\n this.status = 'idle'\n this.createdAt = Date.now()\n this.terminalError = 'Setup hooks failed. End the session or fix the hook configuration and reconnect.'\n return\n }\n\n if (config.platform === 'android') {\n await this.setupMobileAdapter('android', config)\n this.currentUrl = null\n } else if (config.platform === 'ios') {\n await this.setupMobileAdapter('ios', config)\n this.currentUrl = null\n } else {\n const { WebPlatformAdapter } = await import('@vostride/agent-qa-web')\n const adapter = new WebPlatformAdapter()\n await adapter.setup({ platform: 'web', browser: { name: 'chromium', headless: config.headless ?? true } })\n this.adapter = adapter\n\n if (config.url) {\n const resolvedUrl = this.resolveSecrets(config.url)\n await adapter.execute({ type: 'navigate', url: resolvedUrl })\n this.currentUrl = resolvedUrl\n } else {\n this.currentUrl = 'about:blank'\n }\n }\n\n const modelConfig = {\n ...config.llmConfig,\n ...(config.authFetch ? { fetch: config.authFetch } : {}),\n }\n this.model = await createModel(modelConfig)\n const providerOptions = getProviderOptions(modelConfig)\n this.planner = new LLMPlanner(this.model, config.platform, providerOptions, undefined, config.agentRules)\n this.verifier = new LLMVerifier(this.model, providerOptions)\n\n this.status = 'idle'\n this.createdAt = Date.now()\n this.readyForInteraction = true\n }\n\n private async resolveStepInstruction(stepInstruction: string): Promise<{\n instruction: string\n originalStepName?: string\n executionLogs: LiveExecutionLog[]\n preparationError?: string\n }> {\n const originalStepName = stepInstruction\n let instruction = stepInstruction\n let hasTemplateVars = false\n const executionLogs: LiveExecutionLog[] = []\n\n const inlineHookCalls = parseHookInline(stepInstruction)\n if (inlineHookCalls.length > 0) {\n let inlineHookFailed = false\n\n for (const call of inlineHookCalls) {\n const hookDef = this.resolvedHooks.get(call.hookId)\n if (!hookDef) {\n return {\n instruction: stepInstruction,\n originalStepName,\n executionLogs,\n preparationError: `Inline hook \"${call.hookId}\" is not defined in hooks.yaml`,\n }\n }\n\n const startedAt = performance.now()\n try {\n const result = await runHookInSandbox(hookDef, {\n envVars: this.getHookEnvVars(),\n secretStore: this.secretStore,\n secretRedactor: this.secretRedactor,\n })\n executionLogs.push({\n id: randomUUID(),\n type: 'hook',\n name: hookDef.name,\n hookId: hookDef.id,\n phase: 'inline',\n status: result.success ? 'passed' : 'failed',\n duration: result.duration,\n stdout: this.redact(result.stdout),\n stderr: this.redact(result.stderr),\n returnData: null,\n variables: Object.keys(result.variables).length > 0 ? this.redact(result.variables) : null,\n createdAt: new Date().toISOString(),\n })\n\n if (result.success) {\n if (Object.keys(result.variables).length > 0) {\n this.variableStore!.setAll(result.variables, 'hook')\n }\n } else {\n inlineHookFailed = true\n break\n }\n } catch (error) {\n executionLogs.push({\n id: randomUUID(),\n type: 'hook',\n name: hookDef.name,\n hookId: hookDef.id,\n phase: 'inline',\n status: 'failed',\n duration: performance.now() - startedAt,\n stdout: null,\n stderr: this.redact(error instanceof Error ? error.message : String(error)),\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n inlineHookFailed = true\n break\n }\n }\n\n instruction = stripHookInline(stepInstruction)\n hasTemplateVars = true\n\n if (inlineHookFailed) {\n return {\n instruction,\n originalStepName,\n executionLogs,\n preparationError: 'Inline hook execution failed',\n }\n }\n }\n\n instruction = interpolateVariables(instruction, this.variableStore!)\n hasTemplateVars = hasTemplateVars || originalStepName !== instruction\n\n const runJSMatches = parseRunJSInline(instruction)\n if (runJSMatches.length > 0) {\n if (this.adapter?.platform === 'web') {\n const page = 'getPage' in this.adapter\n ? (this.adapter as { getPage?: () => { evaluate: (code: string) => Promise<unknown> } | undefined }).getPage?.()\n : undefined\n\n if (page) {\n for (const match of runJSMatches) {\n const startedAt = performance.now()\n let status: 'passed' | 'failed' = 'passed'\n let stderr: string | null = null\n let stdout: string\n let returnData: unknown = null\n\n try {\n returnData = await page.evaluate(match.code)\n returnData = this.redact(returnData)\n stdout = this.redact(coerceRunJSResult(returnData))\n instruction = instruction.replace(match.fullMatch, stdout)\n } catch (err) {\n status = 'failed'\n stderr = this.redact(err instanceof Error ? err.message : String(err))\n stdout = `[runJS error: ${stderr}]`\n instruction = instruction.replace(match.fullMatch, stdout)\n }\n\n executionLogs.push({\n id: randomUUID(),\n type: 'runjs',\n name: match.code.slice(0, 200),\n phase: 'inline',\n status,\n duration: performance.now() - startedAt,\n stdout: status === 'passed' ? stdout : '',\n stderr,\n returnData,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n }\n } else {\n for (const match of runJSMatches) {\n const stdout = '[runJS error: no browser page available]'\n instruction = instruction.replace(\n match.fullMatch,\n stdout,\n )\n executionLogs.push({\n id: randomUUID(),\n type: 'runjs',\n name: match.code.slice(0, 200),\n phase: 'inline',\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: 'no browser page available',\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n }\n }\n } else {\n for (const match of runJSMatches) {\n const stdout = '[runJS error: runJS is only supported on web platform]'\n instruction = instruction.replace(\n match.fullMatch,\n stdout,\n )\n executionLogs.push({\n id: randomUUID(),\n type: 'runjs',\n name: match.code.slice(0, 200),\n phase: 'inline',\n status: 'failed',\n duration: 0,\n stdout: null,\n stderr: 'runJS is only supported on web platform',\n returnData: null,\n variables: null,\n createdAt: new Date().toISOString(),\n })\n }\n }\n hasTemplateVars = true\n }\n\n return {\n instruction,\n originalStepName: hasTemplateVars ? originalStepName : undefined,\n executionLogs,\n }\n }\n\n private buildPreparationFailureResult(\n instruction: string,\n error: string,\n originalStepName: string | undefined,\n executionLogs: LiveExecutionLog[],\n ): LiveStepExecutionResult {\n const result: LiveStepExecutionResult = {\n name: instruction,\n status: 'failed',\n duration: 0,\n error,\n trace: {\n observation: '',\n reasoning: error,\n plannedAction: { type: 'waitFor', condition: 'none', timeout: 0 },\n result: 'failure',\n error,\n screenStateBefore: '',\n },\n variableSnapshot: this.variableStore!.snapshot(),\n executionLogs,\n originalStepName,\n }\n return this.redact(result)\n }\n\n // Inner step execution — no gating. Callers must own the executing/status\n // lifecycle (executeStepCommand for single steps, executeTestCommand for\n // the per-test loop that runs many steps under one outer gate).\n private async executeStepInternal(\n stepInstruction: string,\n stepIndex: number | undefined,\n onPhase: ((event: StepPhaseEvent) => void) | undefined,\n draft: LiveDraftMetadata | undefined,\n ): Promise<LiveStepExecutionResult> {\n this.abortController = new AbortController()\n try {\n const prepared = await this.resolveStepInstruction(stepInstruction)\n if (prepared.preparationError) {\n const result = this.buildPreparationFailureResult(\n prepared.instruction,\n prepared.preparationError,\n prepared.originalStepName,\n prepared.executionLogs,\n )\n this.stepsExecuted++\n return result\n }\n const unresolvedTemplates = findUnresolvedTemplates(prepared.instruction)\n if (unresolvedTemplates.length > 0) {\n const errorLines = unresolvedTemplates.map((template) => ` - ${template.pattern}: ${template.message}`)\n const error = `Unresolved template variable(s):\\n${errorLines.join('\\n')}`\n const result = this.buildPreparationFailureResult(\n prepared.instruction,\n error,\n prepared.originalStepName,\n prepared.executionLogs,\n )\n this.stepsExecuted++\n return result\n }\n\n const loopConfig: AgentLoopConfig = {\n adapter: this.adapter!,\n planner: this.planner!,\n verifier: this.verifier!,\n healingConfig: { maxAttempts: 3 },\n plannerConfig: { maxSubActions: 50, previousStepCount: 5 },\n screenshotSize: this.screenshotSize,\n effectiveResolution: this.effectiveResolution,\n onSetVariable: (name, value) => this.variableStore!.set(name, value, 'step'),\n onPhase,\n stepIndex,\n abortSignal: this.abortController.signal,\n secretStore: this.secretStore,\n secretRedactor: this.secretRedactor,\n }\n\n const allVars = this.variableStore!.getAll()\n const variables: Record<string, string> = {}\n for (const [k, v] of allVars) variables[k] = v\n\n const stepContext: StepContext = {\n stepInstruction: prepared.instruction,\n testName: draft?.testName?.trim() || 'Unnamed live draft',\n testContext: draft?.testContext?.trim() || undefined,\n previousSteps: this.previousSteps,\n plannerModel: this.model!,\n verifierModel: this.model!,\n healingConfig: { maxAttempts: 3 },\n variables: this.redact(variables),\n }\n\n let result = await executeStep(prepared.instruction, loopConfig, stepContext) as LiveStepExecutionResult\n result.originalStepName = prepared.originalStepName\n result.variableSnapshot = this.variableStore!.snapshot()\n result.executionLogs = this.redact(prepared.executionLogs)\n result.subActionsData = toLiveSubActionData(result)\n if ('pollDeviceLogs' in this.adapter! && typeof (this.adapter as { pollDeviceLogs?: () => Promise<void> }).pollDeviceLogs === 'function') {\n await (this.adapter as { pollDeviceLogs: () => Promise<void> }).pollDeviceLogs()\n }\n result.consoleLogs = this.adapter!.drainConsoleLogs?.()\n result.networkLogs = this.adapter!.drainNetworkLogs?.()\n result = this.redact(result)\n\n if (result.status !== 'cancelled') {\n this.previousSteps.push({ instruction: prepared.instruction, outcome: result.status })\n }\n this.stepsExecuted++\n return result\n } finally {\n this.abortController = null\n }\n }\n\n async executeStepCommand(\n stepInstruction: string,\n stepIndex?: number,\n onPhase?: (event: StepPhaseEvent) => void,\n draft?: LiveDraftMetadata,\n ): Promise<LiveStepExecutionResult> {\n if (!this.readyForInteraction || !this.adapter || !this.model || !this.planner || !this.verifier || !this.variableStore) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n\n if (this.executing) {\n throw new Error('Step already executing')\n }\n\n this.executing = true\n this.status = 'executing'\n this.currentStep = stepInstruction\n try {\n return await this.executeStepInternal(stepInstruction, stepIndex, onPhase, draft)\n } finally {\n this.executing = false\n this.currentStep = null\n this.status = 'idle'\n }\n }\n\n async executeTestCommand(\n testExecutionId: string,\n testDraft: {\n testIndex: number\n testId: string\n testName: string\n testContext?: string\n steps: string[]\n setup: string[]\n teardown: string[]\n },\n onPhase?: (event: StepPhaseEvent) => void,\n ): Promise<LiveTestResultPayload> {\n if (!this.readyForInteraction || !this.adapter || !this.model || !this.planner || !this.verifier || !this.variableStore) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n\n if (this.executing) {\n throw new Error('Test already executing')\n }\n\n this.executing = true\n this.status = 'executing'\n this.currentStep = `test: ${testDraft.testName}`\n const start = performance.now()\n const testExecution: LiveTestExecutionPayload = {\n testExecutionId,\n testIndex: testDraft.testIndex,\n testId: testDraft.testId,\n testName: testDraft.testName,\n }\n const testOwner: LiveHookOwner = {\n scope: 'test',\n testExecutionId,\n testIndex: testDraft.testIndex,\n testId: testDraft.testId,\n testName: testDraft.testName,\n }\n\n try {\n // Per-test setup (D-09). Per-test setup failure short-circuits the\n // test AND skips per-test teardown, matching suite/runner.ts:230 break\n // (Pitfall 2). Suite-level teardown still fires at session cleanup.\n const setupHookPayloads: LiveHookPayload[] = []\n const setupResult = await this.runLifecycleHooksCapturing(\n 'setup',\n testDraft.setup,\n setupHookPayloads,\n testOwner,\n )\n if (!setupResult.allPassed) {\n const failedHook = setupHookPayloads.find((h) => h.status === 'failed')\n const detail = failedHook\n ? `Setup hook \"${failedHook.hookName}\" failed${failedHook.error ? `: ${failedHook.error}` : ''}${failedHook.stderr ? ` — ${failedHook.stderr.split('\\n')[0].slice(0, 200)}` : ''}`\n : 'Per-test setup hook failed'\n console.warn(`[live-session] executeTestCommand: ${detail}`, {\n testName: testDraft.testName,\n setupHooks: testDraft.setup,\n failedHook: failedHook ? { name: failedHook.hookName, stderr: failedHook.stderr, error: failedHook.error } : null,\n })\n return {\n status: 'failed',\n duration: performance.now() - start,\n error: detail,\n setupHookExecutions: setupHookPayloads,\n stepResults: [],\n teardownHookExecutions: [],\n }\n }\n\n // Shared browser context (D-01): each step reuses the same adapter\n // instance. Per-step context carries the TEST's name/context, not\n // the suite's, so the LLMPlanner matches production runTest behaviour.\n const stepResults: LiveStepResultPayload[] = []\n const perStepDraft: LiveDraftMetadata = {\n testName: testDraft.testName,\n testContext: testDraft.testContext,\n }\n let anyCancelled = false\n let anyFailed = false\n for (let i = 0; i < testDraft.steps.length; i++) {\n const stepPayload: LiveTestStepPayload = {\n ...testExecution,\n stepIndex: i,\n stepInstruction: testDraft.steps[i],\n }\n this.emitTestStepStart(stepPayload)\n\n let execResult: LiveStepExecutionResult\n try {\n execResult = await this.executeStepInternal(\n testDraft.steps[i],\n i,\n (event) => {\n this.emitTestStepPhase(stepPayload, event)\n onPhase?.(event)\n },\n perStepDraft,\n )\n } catch (error) {\n const message = this.redact(error instanceof Error ? error.message : String(error))\n this.emitTestStepError(stepPayload, message)\n stepResults.push({\n status: 'failed',\n duration: 0,\n error: message,\n })\n anyFailed = true\n break\n }\n\n this.emitTestStepComplete(stepPayload, execResult)\n stepResults.push(toStepResultPayload(execResult))\n if (execResult.status === 'cancelled') {\n anyCancelled = true\n break\n }\n if (execResult.status === 'failed') {\n anyFailed = true\n break\n }\n }\n\n // Per-test teardown always fires when steps began (D-09 + D-25).\n const teardownHookPayloads: LiveHookPayload[] = []\n const teardownResult = await this.runLifecycleHooksCapturing(\n 'teardown',\n testDraft.teardown,\n teardownHookPayloads,\n testOwner,\n )\n\n const finalStatus: LiveTestResultPayload['status'] = anyCancelled\n ? 'cancelled'\n : anyFailed || !teardownResult.allPassed\n ? 'failed'\n : 'passed'\n\n let topLevelError: string | undefined\n if (anyFailed) {\n const failedStep = stepResults.find((s) => s.status === 'failed')\n if (failedStep) {\n const stepIdx = stepResults.indexOf(failedStep)\n topLevelError = `Step ${stepIdx + 1} (${testDraft.steps[stepIdx] ?? '<unknown>'}) failed${failedStep.error ? `: ${failedStep.error}` : ''}`\n }\n } else if (!teardownResult.allPassed) {\n const failedHook = teardownHookPayloads.find((h) => h.status === 'failed')\n topLevelError = failedHook\n ? `Teardown hook \"${failedHook.hookName}\" failed${failedHook.error ? `: ${failedHook.error}` : ''}`\n : 'Teardown hook failed'\n }\n if (topLevelError) {\n console.warn(`[live-session] executeTestCommand: ${topLevelError}`, { testName: testDraft.testName })\n }\n\n return this.redact({\n status: finalStatus,\n duration: performance.now() - start,\n error: topLevelError,\n setupHookExecutions: setupHookPayloads,\n stepResults,\n teardownHookExecutions: teardownHookPayloads,\n })\n } finally {\n this.executing = false\n this.currentStep = null\n this.status = 'idle'\n }\n }\n\n // Thin wrapper around runLifecycleHooks that also captures the dispatched\n // hook payloads (hook-start / hook-complete) for inclusion in the\n // LiveTestResultPayload. Uses a sink intercept so existing callers of\n // runLifecycleHooks (executeHookCommand, initialize, cleanup) keep their\n // current behaviour unchanged.\n private async runLifecycleHooksCapturing(\n phase: 'setup' | 'teardown',\n hookIds: string[],\n sink: LiveHookPayload[],\n owner: LiveHookOwner = { scope: 'suite' },\n ): Promise<{ allPassed: boolean; logs: LiveExecutionLog[] }> {\n const originalSink = this.messageSink\n const wrappedSink = (message: ServerMessage) => {\n if (message.type === 'hook-complete') {\n sink.push(message.hook)\n }\n if (originalSink) originalSink(message)\n else this.pendingMessages.push(message)\n }\n this.messageSink = wrappedSink\n try {\n return await this.runLifecycleHooks(phase, hookIds, owner)\n } finally {\n this.messageSink = originalSink\n }\n }\n\n async captureWebAuthState(\n name: string,\n options: { replace?: boolean } = {},\n ): Promise<AuthStateMetadata> {\n if (this.platform !== 'web') {\n throw new Error('Auth-state capture is only available for web Live Mode sessions.')\n }\n\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready for auth-state capture.')\n }\n\n if (this.adapter.platform !== 'web') {\n throw new Error('Auth-state capture is only available for web Live Mode sessions.')\n }\n\n if (this.executing) {\n throw new Error('Cannot save auth state while the Live Mode session is executing.')\n }\n\n if (!this.targetName) {\n throw new Error('Cannot save auth state because this Live Mode session has no configured target.')\n }\n\n if (!this.deps.configManager || !this.deps.configPath) {\n throw new Error('Cannot save auth state because workspace config is unavailable.')\n }\n\n const context = getWebStorageStateContext(this.adapter)\n if (!context) {\n throw new Error('Cannot save auth state because the active browser context is unavailable.')\n }\n\n const config = await this.deps.configManager.read()\n const authStateDir = getConfiguredAuthStateDir(config)\n const paths = resolveAuthStatePaths({\n configDir: dirname(resolvePath(this.deps.configPath)),\n authStateDir,\n targetName: this.targetName,\n stateName: name,\n target: { platform: 'web' },\n })\n\n let existing: AuthStateMetadata | null = null\n try {\n existing = await readAuthStateMetadata(paths)\n } catch {\n existing = null\n }\n if (existing && options.replace !== true) {\n throw new Error(`Auth state \"${paths.stateName}\" for target \"${paths.targetName}\" already exists. Use replace=true to replace it.`)\n }\n\n const payload = await context.storageState({ indexedDB: true })\n const metadata: AuthStateMetadata = {\n version: AUTH_STATE_SCHEMA_VERSION,\n kind: 'web',\n target: paths.targetName,\n name: paths.stateName,\n capturedAt: new Date().toISOString(),\n }\n\n try {\n await writeAuthStateFiles(paths, { payload, metadata })\n } catch {\n throw new Error(`Could not save auth state \"${paths.stateName}\" for target \"${paths.targetName}\".`)\n }\n\n return metadata\n }\n\n cancelStep(): void {\n this.abortController?.abort()\n }\n\n async navigate(url: string): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n const resolvedUrl = this.resolveSecrets(url)\n await this.adapter!.execute({ type: 'navigate', url: resolvedUrl })\n if (this.platform === 'web') {\n this.currentUrl = resolvedUrl\n } else {\n this.currentUrl = null\n }\n return this.currentUrl\n }\n\n async refreshPage(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n if (this.platform !== 'web') return this.currentUrl\n await this.adapter!.execute({ type: 'refresh' })\n const page = (this.adapter as any).getPage?.()\n if (page) this.currentUrl = page.url()\n return this.currentUrl ?? 'about:blank'\n }\n\n async goBack(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n if (this.platform !== 'web') return this.currentUrl\n await this.adapter!.execute({ type: 'navigateHistory', direction: 'back' })\n const page = (this.adapter as any).getPage?.()\n if (page) this.currentUrl = page.url()\n return this.currentUrl ?? 'about:blank'\n }\n\n async goForward(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) {\n throw new Error(this.terminalError ?? 'Live session is not ready')\n }\n if (this.platform !== 'web') return this.currentUrl\n await this.adapter!.execute({ type: 'navigateHistory', direction: 'forward' })\n const page = (this.adapter as any).getPage?.()\n if (page) this.currentUrl = page.url()\n return this.currentUrl ?? 'about:blank'\n }\n\n async drainDeviceLogs(): Promise<Array<{ level: string; message: string; timestamp: number }>> {\n if (!this.adapter) return []\n if (typeof (this.adapter as any).pollDeviceLogs === 'function') {\n await (this.adapter as any).pollDeviceLogs()\n }\n if (typeof this.adapter.drainConsoleLogs === 'function') {\n return this.redact(this.adapter.drainConsoleLogs().map((e) => ({ level: e.level, message: e.text, timestamp: e.timestamp })))\n }\n return []\n }\n\n getState(): SessionState {\n return {\n sessionId: this.sessionId,\n platform: (this.adapter?.platform ?? this.platform) as 'web' | 'android' | 'ios',\n targetName: this.targetName,\n status: this.status === 'terminated' ? 'idle' : this.status === 'executing' ? 'executing' : this.status,\n currentStep: this.currentStep,\n currentUrl: this.currentUrl,\n stepsExecuted: this.stepsExecuted,\n createdAt: this.createdAt,\n interactive: this.readyForInteraction,\n terminalError: this.terminalError,\n }\n }\n\n async getScreenshot(): Promise<Buffer | undefined> {\n if (!this.readyForInteraction) return undefined\n return this.adapter?.screenshot?.()\n }\n\n async getAriaTree(): Promise<string | null> {\n if (!this.readyForInteraction || !this.adapter) return null\n if (!this.adapter) return null\n const screenState = await this.adapter.observe()\n return screenState.tree\n }\n\n startIdleTimer(onExpire: () => void): void {\n this.clearIdleTimer()\n this.idleTimer = setTimeout(onExpire, IDLE_TIMEOUT_MS)\n }\n\n clearIdleTimer(): void {\n if (this.idleTimer) {\n clearTimeout(this.idleTimer)\n this.idleTimer = null\n }\n }\n\n async cleanup(): Promise<void> {\n this.clearIdleTimer()\n this.readyForInteraction = false\n try {\n await this.adapter?.cleanup()\n } finally {\n try {\n await this.runLifecycleHooks('teardown', this.teardownHooks)\n } finally {\n this.releaseMobileAppiumLease('session-cleanup')\n this.messageSink = null\n this.status = 'terminated'\n }\n }\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { parse as parseYaml } from 'yaml'\nimport {\n MobileSetupError,\n resolveMobileRunConfig,\n} from '@vostride/agent-qa-core'\nimport type {\n MobilePlatform,\n PlatformConfig,\n ResolvedMobileRunConfig,\n} from '@vostride/agent-qa-core'\nimport type { AppiumManager } from '../execution/appium-manager.js'\nimport type { ConfigManager } from '../config/index.js'\n\ninterface LocalMobileBindings {\n devices?: Record<string, Record<string, unknown>>\n providers?: Record<string, Record<string, unknown>>\n apps?: Record<string, { path?: string; browserstack?: string }>\n filePath?: string\n}\n\nexport interface MobileLiveAppiumLease {\n runId: string\n url: string\n release: (reason?: string) => boolean\n}\n\nexport interface PreparedMobileLiveSession {\n platformConfig: PlatformConfig\n appiumLease: MobileLiveAppiumLease\n resolved: ResolvedMobileRunConfig\n}\n\nexport interface PrepareMobileLiveSessionInput {\n sessionId: string\n platform: MobilePlatform\n targetName?: string\n useDeviceName?: string\n appState?: 'preserve' | 'reset'\n configManager: ConfigManager\n configPath: string\n appiumManager: AppiumManager\n}\n\nasync function loadLocalBindings(configPath: string): Promise<LocalMobileBindings | null> {\n const filePath = join(dirname(configPath), 'agent-qa.local.yaml')\n try {\n const content = await readFile(filePath, 'utf-8')\n const parsed = parseYaml(content) as LocalMobileBindings | null\n return parsed && typeof parsed === 'object'\n ? {\n devices: parsed.devices,\n providers: parsed.providers,\n apps: parsed.apps,\n filePath,\n }\n : { filePath }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null\n throw err\n }\n}\n\nfunction asMobileSetupError(\n err: unknown,\n category: MobileSetupError['category'],\n message: string,\n input: Pick<PrepareMobileLiveSessionInput, 'platform' | 'targetName'>,\n): MobileSetupError {\n if (err instanceof MobileSetupError) return err\n return new MobileSetupError({\n category,\n message: `${message}: ${err instanceof Error ? err.message : String(err)}`,\n platform: input.platform,\n targetName: input.targetName,\n cause: err,\n })\n}\n\nexport async function prepareMobileLiveSession(\n input: PrepareMobileLiveSessionInput,\n): Promise<PreparedMobileLiveSession> {\n if (!input.targetName) {\n throw new MobileSetupError({\n category: 'device-resolution',\n message: `No targetName provided for ${input.platform} live session`,\n platform: input.platform,\n })\n }\n\n const config = await input.configManager.read()\n let localBindings: LocalMobileBindings | null = null\n\n try {\n localBindings = await loadLocalBindings(input.configPath)\n } catch (err) {\n throw asMobileSetupError(err, 'device-resolution', 'Failed to read local device bindings', input)\n }\n\n const configuredAppState = (config.use as { mobile?: { appState?: 'preserve' | 'reset' } } | undefined)?.mobile?.appState\n\n let resolved: ResolvedMobileRunConfig\n try {\n resolved = resolveMobileRunConfig({\n config,\n targetName: input.targetName,\n platform: input.platform,\n useDeviceName: input.useDeviceName,\n appState: input.appState ?? configuredAppState,\n localBindings,\n configFilePath: input.configPath,\n localConfigFilePath: localBindings?.filePath,\n })\n } catch (err) {\n throw asMobileSetupError(err, 'device-resolution', 'Failed to resolve mobile live target', input)\n }\n\n try {\n await input.appiumManager.acquireLease({ runId: input.sessionId, platform: input.platform })\n } catch (err) {\n throw new MobileSetupError({\n category: 'appium-startup',\n message: `Failed to acquire Appium for ${input.platform} live session: ${err instanceof Error ? err.message : String(err)}`,\n platform: input.platform,\n targetName: input.targetName,\n deviceName: resolved.deviceName,\n appId: resolved.app.deepLinkAppId,\n sourceTrace: resolved.sourceTrace,\n cause: err,\n })\n }\n\n const appiumUrl = input.appiumManager.getUrl()\n let released = false\n const appiumLease: MobileLiveAppiumLease = {\n runId: input.sessionId,\n url: appiumUrl,\n release: (reason = 'completed') => {\n if (released) return false\n released = true\n return input.appiumManager.releaseLease(input.sessionId, reason)\n },\n }\n\n return {\n resolved: {\n ...resolved,\n appium: {\n url: appiumUrl,\n managed: true,\n },\n },\n appiumLease,\n platformConfig: {\n platform: input.platform,\n device: resolved.device,\n appiumUrl,\n bundleId: resolved.app.bundleId,\n appPackage: resolved.app.appPackage,\n appActivity: resolved.app.appActivity,\n deepLinkAppId: resolved.app.deepLinkAppId,\n appPath: resolved.app.install?.path,\n browserstackApp: resolved.app.install?.browserstack,\n appState: resolved.appState,\n },\n }\n}\n","import type WebSocket from 'ws'\nimport { parseTestFile } from '@vostride/agent-qa-core'\nimport type { LiveSession } from './live-session.js'\nimport type {\n LiveStepResultPayload,\n ServerMessage,\n} from './types.js'\nimport type { TestFileManager } from '../tests/test-file-manager.js'\n\nfunction send(ws: WebSocket, msg: ServerMessage): void {\n if (ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify(msg))\n }\n}\n\nfunction toStepResultPayload(result: Awaited<ReturnType<LiveSession['executeStepCommand']>>): LiveStepResultPayload {\n const status = result.status === 'passed'\n ? 'passed'\n : result.status === 'cancelled'\n ? 'cancelled'\n : 'failed'\n\n return {\n status,\n duration: result.duration,\n error: result.error,\n capturedVariables: result.capturedVariables,\n variableSnapshot: result.variableSnapshot,\n originalStepName: result.originalStepName,\n consoleLogs: result.consoleLogs,\n networkLogs: result.networkLogs,\n executionLogs: result.executionLogs,\n subActionsData: result.subActionsData,\n }\n}\n\nexport function createSessionHandler(\n session: LiveSession,\n onTerminate: () => void,\n onTokenUsage?: (event: { modelName: string; promptTokens: number; completionTokens: number; source: 'live-editor' }) => void,\n testFileManager?: TestFileManager,\n): (ws: WebSocket) => void {\n return (ws: WebSocket) => {\n let cleanedUp = false\n\n async function cleanupSession(): Promise<void> {\n if (cleanedUp) return\n cleanedUp = true\n if (logPollInterval) clearInterval(logPollInterval)\n if (session.status !== 'terminated') {\n await session.cleanup()\n }\n onTerminate()\n }\n\n session.clearIdleTimer()\n\n const state = session.getState()\n send(ws, {\n type: 'session-ready',\n sessionId: session.sessionId,\n platform: state.platform,\n interactive: state.interactive,\n error: state.terminalError,\n })\n session.attachMessageSink((message) => {\n send(ws, message)\n })\n send(ws, { type: 'session-state', state })\n\n let logPollInterval: ReturnType<typeof setInterval> | null = null\n const platform = state.platform\n if (platform !== 'web' && state.interactive) {\n logPollInterval = setInterval(async () => {\n if (session.status === 'executing') {\n return\n }\n try {\n const entries = await session.drainDeviceLogs()\n if (entries.length > 0) {\n send(ws, { type: 'device-logs', entries })\n }\n } catch {}\n }, 2000)\n }\n\n ws.on('message', async (data) => {\n let msg: any\n try {\n msg = JSON.parse(data.toString())\n } catch {\n send(ws, { type: 'error', message: 'Invalid JSON' })\n return\n }\n\n switch (msg.type) {\n case 'execute-step': {\n if (session.status === 'executing') {\n send(ws, {\n type: 'step-busy',\n currentStep: session.getState().currentStep ?? 'unknown',\n })\n return\n }\n try {\n const result = await session.executeStepCommand(\n msg.stepInstruction,\n msg.stepIndex,\n (phase) => {\n send(ws, {\n type: 'step-phase',\n phase: phase.phase,\n data: {\n text: phase.text,\n confidence: phase.confidence,\n action: phase.action,\n success: phase.success,\n duration: phase.duration,\n },\n })\n },\n msg.draft,\n )\n if (result.status === 'cancelled') {\n send(ws, { type: 'step-cancelled' })\n } else {\n send(ws, {\n type: 'step-complete',\n result: toStepResultPayload(result),\n })\n if (onTokenUsage && result.trace?.tokenUsage &&\n (result.trace.tokenUsage.promptTokens > 0 || result.trace.tokenUsage.completionTokens > 0)) {\n onTokenUsage({\n modelName: session.modelName,\n promptTokens: result.trace.tokenUsage.promptTokens,\n completionTokens: result.trace.tokenUsage.completionTokens,\n source: 'live-editor',\n })\n }\n try {\n const tree = await session.getAriaTree()\n if (tree) send(ws, { type: 'aria-tree', tree })\n } catch {}\n }\n send(ws, { type: 'session-state', state: session.getState() })\n const adapter = (session as any).adapter\n if (adapter && typeof adapter.isBrowserDisconnected === 'boolean' && adapter.isBrowserDisconnected) {\n send(ws, { type: 'browser-disconnected' })\n }\n } catch (err: any) {\n send(ws, { type: 'step-error', error: err.message })\n const adapter = (session as any).adapter\n if (adapter && typeof adapter.isBrowserDisconnected === 'boolean' && adapter.isBrowserDisconnected) {\n send(ws, { type: 'browser-disconnected' })\n }\n }\n break\n }\n\n case 'execute-hook': {\n if (session.status === 'executing') {\n send(ws, {\n type: 'step-busy',\n currentStep: session.getState().currentStep ?? 'unknown',\n })\n return\n }\n try {\n await session.executeHookCommand(msg.phase, msg.hookId)\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'execute-test': {\n if (session.status === 'executing') {\n send(ws, {\n type: 'step-busy',\n currentStep: session.getState().currentStep ?? 'unknown',\n })\n return\n }\n try {\n if (!testFileManager) {\n throw new Error('Test file manager unavailable — configure workspace.testMatch to run tests live')\n }\n\n let raw: string\n try {\n raw = await testFileManager.read(msg.path)\n } catch (readErr: any) {\n console.error(`[ws-handler] execute-test: read failed for path=${msg.path}`, readErr)\n throw new Error(`Cannot read test file \"${msg.path}\": ${readErr?.message ?? String(readErr)}`)\n }\n\n const parsed = parseTestFile(raw, msg.path)\n if (parsed.errors.length > 0) {\n console.error(`[ws-handler] execute-test: parse errors for ${msg.path}`, parsed.errors)\n throw new Error(`Parse error in ${msg.path}: ${parsed.errors[0].message}`)\n }\n const testDef = parsed.tests[0]\n if (!testDef) {\n throw new Error(`Test file \"${msg.path}\" is empty or has no valid test documents`)\n }\n const stepInstructions: string[] = testDef.steps.map((s: string | { step: string }) =>\n typeof s === 'string' ? s : s.step,\n )\n console.log(`[ws-handler] execute-test: starting \"${testDef.name}\" (${stepInstructions.length} steps, setup=${(testDef.setup ?? []).length}, teardown=${(testDef.teardown ?? []).length})`)\n\n send(ws, {\n type: 'test-start',\n test: {\n testExecutionId: msg.testExecutionId,\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: testDef.name,\n },\n })\n\n const result = await session.executeTestCommand(\n msg.testExecutionId,\n {\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: testDef.name,\n testContext: testDef.context,\n steps: stepInstructions,\n setup: testDef.setup ?? [],\n teardown: testDef.teardown ?? [],\n },\n )\n\n console.log(`[ws-handler] execute-test: finished \"${testDef.name}\" status=${result.status} duration=${result.duration}ms${result.error ? ` error=${result.error}` : ''}`)\n send(ws, {\n type: 'test-complete',\n test: {\n testExecutionId: msg.testExecutionId,\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: testDef.name,\n },\n result,\n })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n console.error(`[ws-handler] execute-test: caught error for path=${msg.path}`, {\n message: err?.message,\n stack: err?.stack,\n code: err?.code,\n })\n send(ws, {\n type: 'test-error',\n test: {\n testExecutionId: msg.testExecutionId,\n testIndex: msg.testIndex ?? 0,\n testId: msg.testId,\n testName: msg.path.split(/[\\\\/]/).pop() ?? msg.path,\n },\n error: err?.message ?? String(err),\n })\n send(ws, { type: 'session-state', state: session.getState() })\n }\n break\n }\n\n case 'cancel-step': {\n session.cancelStep()\n break\n }\n\n case 'terminate-session': {\n await cleanupSession()\n send(ws, { type: 'session-terminated' })\n ws.close(1000, 'Session terminated')\n break\n }\n\n case 'get-screenshot': {\n const buf = await session.getScreenshot()\n if (buf) {\n send(ws, { type: 'screenshot', data: buf.toString('base64') })\n } else {\n send(ws, { type: 'error', message: 'Screenshot unavailable' })\n }\n break\n }\n\n case 'get-state': {\n send(ws, { type: 'session-state', state: session.getState() })\n break\n }\n\n case 'navigate': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.navigate(msg.url)\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'refresh-page': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.refreshPage()\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'go-back': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.goBack()\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'go-forward': {\n if (session.status === 'executing') {\n send(ws, { type: 'step-busy', currentStep: session.getState().currentStep ?? 'unknown' })\n return\n }\n try {\n const url = await session.goForward()\n send(ws, { type: 'navigate-complete', url })\n send(ws, { type: 'session-state', state: session.getState() })\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n case 'get-aria-tree': {\n if (session.status === 'executing') {\n send(ws, { type: 'error', message: 'Cannot inspect ARIA tree while step is executing' })\n return\n }\n try {\n const tree = await session.getAriaTree()\n if (tree) {\n send(ws, { type: 'aria-tree', tree })\n } else {\n send(ws, { type: 'error', message: 'ARIA tree unavailable' })\n }\n } catch (err: any) {\n send(ws, { type: 'error', message: err.message })\n }\n break\n }\n\n default: {\n send(ws, { type: 'error', message: `Unknown message type: ${msg.type}` })\n break\n }\n }\n })\n\n ws.on('close', () => {\n session.attachMessageSink(null)\n void cleanupSession()\n })\n\n ws.on('error', () => {\n session.attachMessageSink(null)\n void cleanupSession()\n })\n }\n}\n"],"mappings":"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","names":["dirname","createBetterSqlite3Database","generateRunId","relativePath","sourcePath","mkdirSync","dirname","resolve","DEFAULT_AGENT_QA_RUNS_DB_PATH","copyFile","mkdir","rename","unlink","basename","dirname","isAbsolute","relative","resolve","readFile","stat","join","resolve","cpus","randomUUID","readFile","writeFile","stat","readdir","rm","join","isAbsolute","basename","resolve","dirname","relative","readFile","stat","dirname","join","resolve","discoverWorkspaceFiles","parseYaml","readFile","writeFile","mkdir","stat","dirname","basename","parseTestFile","resolve","join","stat","dirname","discoverWorkspaceFiles","readFile","parseYaml","mkdir","readFile","rm","stat","writeFile","basename","dirname","isAbsolute","relative","resolve","resolveWorkspacePaths","parseYaml","readFile","basename","AgentQaConfigSchema","discoverWorkspaceFiles","resolveWorkspacePaths","parseYaml","readFile","dirname","resolve","rm","mkdir","writeFile","isAbsolute","parseYaml","stat","resolveWorkspacePaths","relative","basename","resolve","buildInternalRunAttributes","AgentQaConfigSchema","redactAuthStateValue","discoverWorkspaceFiles","resolveMemoryRoot","resolveWorkspaceFileTarget","parseYaml","relative","isAbsolute","basename","isRecord","resolve","join","rm","readFile","dirname","stat","path","randomUUID","llmConfig","createModel","readdir","writeFile","EventEmitter","readFile","writeFile","mkdir","stat","rm","dirname","basename","parseYaml","discoverWorkspaceFiles","resolveWorkspaceFileTarget","SuiteDefinitionSchema","readFile","writeFile","mkdir","dirname","parseDocument","spawn","treeKill","resolve","randomUUID","randomUUID","dirname","getProviderOptions","runHookInSandbox","MobileSetupError","redactAuthStateValue","readFile","dirname","join","parseYaml","getConfiguredAuthStateDir","MobileSetupError","redactAuthStateValue","randomUUID","completed","getProviderOptions","runHookInSandbox","result","dirname","randomUUID","toStepResultPayload","buildAnalyticsEvent","captureAnalytics","resolveAnalyticsStandardProperties","resolve","cpus","join","stat","readFile","request"]}
|