@allenpan2026/harshjudge 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/types/scenario.ts","../src/types/run.ts","../src/schemas/index.ts","../src/services/file-system-service.ts","../src/services/dashboard-manager.ts","../src/handlers/init-project.ts","../src/utils/cli-helpers.ts","../src/commands/create.ts","../src/utils/slugify.ts","../src/handlers/create-scenario.ts","../src/commands/star.ts","../src/handlers/toggle-star.ts","../src/commands/status.ts","../src/handlers/get-status.ts","../src/commands/start.ts","../src/handlers/start-run.ts","../src/commands/evidence.ts","../src/handlers/record-evidence.ts","../src/commands/complete-step.ts","../src/handlers/complete-step.ts","../src/commands/complete-run.ts","../src/handlers/complete-run.ts","../src/commands/dashboard.ts","../src/handlers/open-dashboard.ts","../src/handlers/close-dashboard.ts","../src/handlers/get-dashboard-status.ts","../src/commands/discover.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { register as registerInit } from './commands/init.js';\nimport { register as registerCreate } from './commands/create.js';\nimport { register as registerStar } from './commands/star.js';\nimport { register as registerStatus } from './commands/status.js';\nimport { register as registerStart } from './commands/start.js';\nimport { register as registerEvidence } from './commands/evidence.js';\nimport { register as registerCompleteStep } from './commands/complete-step.js';\nimport { register as registerCompleteRun } from './commands/complete-run.js';\nimport { register as registerDashboard } from './commands/dashboard.js';\nimport { register as registerDiscover } from './commands/discover.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n readFileSync(join(__dirname, '..', 'package.json'), 'utf8')\n);\n\nconst program = new Command();\nprogram\n .name('harshjudge')\n .description('AI-native E2E testing orchestration CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Working directory override');\n\nregisterInit(program);\nregisterCreate(program);\nregisterStar(program);\nregisterStatus(program);\nregisterStart(program);\nregisterEvidence(program);\nregisterCompleteStep(program);\nregisterCompleteRun(program);\nregisterDashboard(program);\nregisterDiscover(program);\n\nprogram.parse();\n","import { Command } from 'commander';\nimport { handleInitProject } from '../handlers/init-project.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('init <name>')\n .description('Initialize a HarshJudge project in the current directory')\n .option('--base-url <url>', 'Base URL for the application under test')\n .action(\n withErrorHandling(\n async (name: string, opts: { baseUrl?: string }, cmd: Command) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleInitProject(\n { projectName: name, baseUrl: opts.baseUrl },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n}\n","import { z } from 'zod';\n\n// ============================================================\n// Step Types (NEW in v2)\n// ============================================================\n\n/**\n * Reference to a step file in meta.yaml\n */\nexport const StepReferenceSchema = z.object({\n id: z.string().regex(/^\\d{2}$/, 'Step ID must be zero-padded (01, 02, etc.)'),\n title: z.string().min(1),\n file: z.string().regex(/^\\d{2}-[\\w-]+\\.md$/, 'Step file must match pattern: {id}-{slug}.md'),\n});\nexport type StepReference = z.infer<typeof StepReferenceSchema>;\n\n/**\n * Full step definition with content sections\n */\nexport interface Step {\n id: string;\n title: string;\n description: string;\n preconditions: string;\n actions: string;\n expectedOutcome: string;\n}\n\n/**\n * Step file read from filesystem\n */\nexport interface StepFile {\n id: string;\n title: string;\n content: string; // Full markdown content\n}\n\n// ============================================================\n// Scenario Types (v2)\n// ============================================================\n\n/**\n * Test scenario definition (v2 - with steps)\n */\nexport interface Scenario {\n slug: string;\n title: string;\n starred: boolean;\n tags: string[];\n estimatedDuration: number;\n steps: StepReference[];\n}\n\n/**\n * Full scenario metadata stored in `meta.yaml` (v2)\n * Combines scenario definition + machine-updated statistics\n */\nexport const ScenarioMetaSchema = z.object({\n // Scenario definition\n slug: z.string().regex(/^[a-z0-9-]+$/),\n title: z.string().min(1),\n starred: z.boolean().default(false),\n tags: z.array(z.string()).default([]),\n estimatedDuration: z.number().positive().default(60),\n steps: z.array(StepReferenceSchema).default([]),\n\n // Statistics (machine-updated)\n totalRuns: z.number().nonnegative().default(0),\n passCount: z.number().nonnegative().default(0),\n failCount: z.number().nonnegative().default(0),\n lastRun: z.string().nullable().default(null),\n lastResult: z.enum(['pass', 'fail']).nullable().default(null),\n avgDuration: z.number().nonnegative().default(0),\n});\nexport type ScenarioMeta = z.infer<typeof ScenarioMetaSchema>;\n\n// ============================================================\n// Statistics Types (shared between v1 and v2)\n// ============================================================\n\n/**\n * Machine-updated statistics (shared structure)\n */\nexport interface ScenarioStats {\n totalRuns: number;\n passCount: number;\n failCount: number;\n lastRun: string | null;\n lastResult: 'pass' | 'fail' | null;\n avgDuration: number;\n}\n\n/**\n * Default statistics values for new scenarios\n */\nexport const DEFAULT_SCENARIO_STATS: ScenarioStats = {\n totalRuns: 0,\n passCount: 0,\n failCount: 0,\n lastRun: null,\n lastResult: null,\n avgDuration: 0,\n};\n\n// ============================================================\n// Legacy Types (v1 - deprecated)\n// ============================================================\n\n/**\n * @deprecated Use Scenario instead (v2)\n * Test scenario definition stored as `scenario.md` with YAML frontmatter\n */\nexport interface ScenarioV1 {\n id: string;\n title: string;\n tags: string[];\n estimatedDuration: number;\n content: string;\n}\n\n/**\n * @deprecated Use ScenarioMeta instead (v2)\n * YAML frontmatter extracted from scenario.md\n */\nexport interface ScenarioFrontmatter {\n id: string;\n title: string;\n tags: string[];\n estimatedDuration: number;\n}\n\n/**\n * @deprecated Use ScenarioStats instead\n * Machine-updated statistics stored in `meta.yaml`\n */\nexport type ScenarioMetaV1 = ScenarioStats;\n\n// ============================================================\n// Utility Functions\n// ============================================================\n\n/**\n * Generate zero-padded step ID from number\n */\nexport function padStepId(n: number): string {\n return String(n).padStart(2, '0');\n}\n\n/**\n * Generate step filename from id and title\n */\nexport function generateStepFilename(id: string, title: string): string {\n const slug = title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n return `${id}-${slug}.md`;\n}\n","import { z } from 'zod';\n\n/**\n * Result of a single step execution\n */\nexport const StepResultSchema = z.object({\n id: z.string().regex(/^\\d{2}$/, 'Step ID must be zero-padded'),\n status: z.enum(['pass', 'fail', 'skipped']),\n duration: z.number().nonnegative().optional().default(0),\n error: z.string().nullable().default(null),\n evidenceFiles: z.array(z.string()).default([]),\n /** AI-generated summary describing what happened in this step */\n summary: z.string().nullable().optional().default(null),\n});\nexport type StepResult = z.infer<typeof StepResultSchema>;\n\n/**\n * Single execution of a scenario\n */\nexport interface Run {\n id: string;\n scenarioSlug: string;\n runNumber: number;\n startedAt: string;\n status: 'running' | 'completed';\n}\n\n/**\n * Final outcome of a run stored in `result.json` (v2)\n */\nexport const RunResultSchema = z.object({\n runId: z.string(),\n scenarioSlug: z.string().optional(), // Optional for backward compat\n status: z.enum(['pass', 'fail', 'running']),\n startedAt: z.string(),\n completedAt: z.string().optional(),\n duration: z.number().nonnegative().optional().default(0),\n steps: z.array(StepResultSchema).default([]),\n failedStep: z.string().nullable().default(null), // Changed from number to string (step ID)\n errorMessage: z.string().nullable().default(null),\n});\nexport type RunResult = z.infer<typeof RunResultSchema>;\n\n/**\n * @deprecated Legacy v1 result format\n */\nexport interface RunResultV1 {\n runId: string;\n status: 'pass' | 'fail';\n duration: number;\n completedAt: string;\n failedStep: number | null;\n errorMessage: string | null;\n stepCount: number;\n evidenceCount: number;\n}\n","import { z } from 'zod';\nimport type { ProjectStatus, ScenarioDetail } from '../types/status.js';\nimport { StepResultSchema } from '../types/run.js';\n\n// ============================================================\n// initProject\n// ============================================================\n\nexport const InitProjectParamsSchema = z.object({\n projectName: z.string().min(1).max(100),\n baseUrl: z.string().url().optional(),\n});\nexport type InitProjectParams = z.infer<typeof InitProjectParamsSchema>;\n\nexport interface InitProjectResult {\n success: boolean;\n projectPath: string;\n configPath: string;\n prdPath: string;\n scenariosPath: string;\n dashboardUrl?: string;\n message?: string;\n}\n\n// ============================================================\n// saveScenario (DEPRECATED - use createScenario instead)\n// ============================================================\n\n/** @deprecated Use CreateScenarioParamsSchema instead */\nexport const SaveScenarioParamsSchema = z.object({\n slug: z\n .string()\n .regex(/^[a-z0-9-]+$/, 'Slug must be lowercase alphanumeric with hyphens'),\n title: z.string().min(1).max(200),\n content: z.string().min(1),\n tags: z.array(z.string()).optional().default([]),\n estimatedDuration: z.number().positive().optional().default(60),\n});\n/** @deprecated Use CreateScenarioParams instead */\nexport type SaveScenarioParams = z.infer<typeof SaveScenarioParamsSchema>;\n\n/** @deprecated Use CreateScenarioResult instead */\nexport interface SaveScenarioResult {\n success: boolean;\n slug: string;\n scenarioPath: string;\n metaPath: string;\n isNew: boolean;\n}\n\n// ============================================================\n// createScenario (NEW - replaces saveScenario)\n// ============================================================\n\nexport const StepInputSchema = z.object({\n title: z.string().min(1),\n description: z.string().optional().default(''),\n preconditions: z.string().optional().default(''),\n actions: z.string().min(1),\n expectedOutcome: z.string().min(1),\n});\nexport type StepInput = z.infer<typeof StepInputSchema>;\n\nexport const CreateScenarioParamsSchema = z.object({\n slug: z\n .string()\n .regex(/^[a-z0-9-]+$/, 'Slug must be lowercase alphanumeric with hyphens'),\n title: z.string().min(1).max(200),\n steps: z.array(StepInputSchema).min(1),\n tags: z.array(z.string()).optional().default([]),\n estimatedDuration: z.number().positive().optional().default(60),\n starred: z.boolean().optional().default(false),\n});\nexport type CreateScenarioParams = z.infer<typeof CreateScenarioParamsSchema>;\n\nexport interface CreateScenarioResult {\n success: boolean;\n slug: string;\n scenarioPath: string;\n metaPath: string;\n stepsPath: string;\n stepFiles: string[];\n isNew: boolean;\n}\n\n// ============================================================\n// toggleStar\n// ============================================================\n\nexport const ToggleStarParamsSchema = z.object({\n scenarioSlug: z.string().regex(/^[a-z0-9-]+$/),\n starred: z.boolean().optional(), // If omitted, toggles current state\n});\nexport type ToggleStarParams = z.infer<typeof ToggleStarParamsSchema>;\n\nexport interface ToggleStarResult {\n success: boolean;\n slug: string;\n starred: boolean;\n}\n\n// ============================================================\n// startRun\n// ============================================================\n\nexport const StartRunParamsSchema = z.object({\n scenarioSlug: z.string().regex(/^[a-z0-9-]+$/),\n});\nexport type StartRunParams = z.infer<typeof StartRunParamsSchema>;\n\nexport interface StartRunStepInfo {\n id: string; // Zero-padded step ID (e.g., \"01\", \"02\")\n title: string;\n file: string; // Filename in steps/ directory\n}\n\nexport interface StartRunResult {\n success: boolean;\n runId: string;\n runNumber: number;\n runPath: string;\n evidencePath: string;\n startedAt: string;\n // NEW: Step information for orchestration\n scenarioSlug: string;\n scenarioTitle: string;\n steps: StartRunStepInfo[];\n}\n\n// ============================================================\n// recordEvidence (v2 - stepId instead of step number)\n// ============================================================\n\nexport const RecordEvidenceParamsSchema = z.object({\n runId: z.string().min(1),\n step: z.number().int().positive(), // v2: accepts number, will be converted to zero-padded string\n type: z.enum([\n 'screenshot',\n 'db_snapshot',\n 'console_log',\n 'network_log',\n 'html_snapshot',\n 'custom',\n ]),\n name: z.string().min(1).max(100),\n data: z.string(), // For screenshot: absolute file path; for others: content\n metadata: z.record(z.unknown()).optional(),\n});\nexport type RecordEvidenceParams = z.infer<typeof RecordEvidenceParamsSchema>;\n\nexport interface RecordEvidenceResult {\n success: boolean;\n filePath: string;\n metaPath: string;\n stepPath: string; // NEW: path to the step's evidence directory\n fileSize: number;\n}\n\n// ============================================================\n// completeRun (v2 - step ID string, optional steps array)\n// ============================================================\n\nexport const CompleteRunParamsSchema = z.object({\n runId: z.string().min(1),\n status: z.enum(['pass', 'fail']),\n duration: z.number().nonnegative(),\n failedStep: z\n .string()\n .regex(/^\\d{2}$/, 'Step ID must be zero-padded')\n .optional(), // Changed from number to string\n errorMessage: z.string().optional(),\n steps: z.array(StepResultSchema).optional(), // NEW: per-step results\n});\nexport type CompleteRunParams = z.infer<typeof CompleteRunParamsSchema>;\n\nexport interface CompleteRunResult {\n success: boolean;\n resultPath: string;\n updatedMeta: {\n totalRuns: number;\n passCount: number;\n failCount: number;\n avgDuration: number;\n };\n}\n\n// ============================================================\n// completeStep (NEW in v2)\n// ============================================================\n\nexport const CompleteStepParamsSchema = z.object({\n runId: z.string().min(1),\n stepId: z\n .string()\n .regex(/^\\d{2}$/, 'Step ID must be zero-padded (e.g., \"01\", \"02\")'),\n status: z.enum(['pass', 'fail', 'skipped']),\n duration: z.number().nonnegative(),\n error: z.string().optional(),\n /** AI-generated summary describing what happened in this step and match result */\n summary: z.string().optional(),\n});\nexport type CompleteStepParams = z.infer<typeof CompleteStepParamsSchema>;\n\nexport interface CompleteStepResult {\n success: boolean;\n runId: string;\n stepId: string;\n status: 'pass' | 'fail' | 'skipped';\n nextStepId: string | null; // null if last step or should stop\n}\n\n// ============================================================\n// getStatus\n// ============================================================\n\nexport const GetStatusParamsSchema = z.object({\n scenarioSlug: z\n .string()\n .regex(/^[a-z0-9-]+$/)\n .optional(),\n starredOnly: z.boolean().optional().default(false),\n});\nexport type GetStatusParams = z.infer<typeof GetStatusParamsSchema>;\n\nexport type GetStatusResult = ProjectStatus | ScenarioDetail;\n\n// ============================================================\n// openDashboard\n// ============================================================\n\nexport const OpenDashboardParamsSchema = z.object({\n port: z.number().int().min(1024).max(65535).optional(),\n openBrowser: z.boolean().optional().default(true),\n projectPath: z\n .string()\n .optional()\n .describe(\n 'Path to the project directory containing .harshJudge folder. Defaults to current working directory.'\n ),\n});\nexport type OpenDashboardParams = z.infer<typeof OpenDashboardParamsSchema>;\n\nexport interface OpenDashboardResult {\n success: boolean;\n url: string;\n port: number;\n pid: number;\n alreadyRunning: boolean;\n message: string;\n}\n\n// ============================================================\n// closeDashboard\n// ============================================================\n\nexport const CloseDashboardParamsSchema = z.object({\n projectPath: z\n .string()\n .optional()\n .describe(\n 'Path to the project directory containing .harshJudge folder. Defaults to current working directory.'\n ),\n});\nexport type CloseDashboardParams = z.infer<typeof CloseDashboardParamsSchema>;\n\nexport interface CloseDashboardResult {\n success: boolean;\n wasRunning: boolean;\n message: string;\n}\n\n// ============================================================\n// getDashboardStatus\n// ============================================================\n\nexport const GetDashboardStatusParamsSchema = z.object({\n projectPath: z\n .string()\n .optional()\n .describe(\n 'Path to the project directory containing .harshJudge folder. Defaults to current working directory.'\n ),\n});\nexport type GetDashboardStatusParams = z.infer<\n typeof GetDashboardStatusParamsSchema\n>;\n\nexport interface GetDashboardStatusResult {\n running: boolean;\n pid?: number;\n port?: number;\n url?: string;\n startedAt?: string;\n stale?: boolean;\n message: string;\n}\n","import { mkdir, writeFile, readFile, access, readdir } from 'fs/promises';\nimport { dirname, join } from 'path';\nimport yaml from 'js-yaml';\nimport type { Step } from '../types/index.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst STEPS_DIR = 'steps';\n\n/**\n * Service for filesystem operations.\n * All file operations in handlers should go through this service.\n */\nexport class FileSystemService {\n private basePath: string;\n\n constructor(basePath: string = process.cwd()) {\n this.basePath = basePath;\n }\n\n /**\n * Resolves a relative path against the base path.\n */\n private resolve(path: string): string {\n return join(this.basePath, path);\n }\n\n /**\n * Creates a directory recursively if it doesn't exist.\n */\n async ensureDir(path: string): Promise<void> {\n await mkdir(this.resolve(path), { recursive: true });\n }\n\n /**\n * Checks if a path exists.\n */\n async exists(path: string): Promise<boolean> {\n try {\n await access(this.resolve(path));\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Writes an object as YAML to a file.\n */\n async writeYaml(path: string, data: object): Promise<void> {\n const content = yaml.dump(data, { indent: 2 });\n await this.writeFile(path, content);\n }\n\n /**\n * Reads and parses a YAML file.\n */\n async readYaml<T>(path: string): Promise<T> {\n const content = await readFile(this.resolve(path), 'utf-8');\n return yaml.load(content) as T;\n }\n\n /**\n * Writes an object as JSON to a file.\n */\n async writeJson(path: string, data: object): Promise<void> {\n const content = JSON.stringify(data, null, 2);\n await this.writeFile(path, content);\n }\n\n /**\n * Reads and parses a JSON file.\n */\n async readJson<T>(path: string): Promise<T> {\n const content = await readFile(this.resolve(path), 'utf-8');\n return JSON.parse(content) as T;\n }\n\n /**\n * Writes string or binary data to a file.\n * Creates parent directories if they don't exist.\n */\n async writeFile(path: string, data: string | Buffer): Promise<void> {\n const fullPath = this.resolve(path);\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, data);\n }\n\n /**\n * Reads a file as a string (default) or Buffer (binary mode).\n * Supports both relative paths (resolved against basePath) and absolute paths.\n */\n async readFile(path: string): Promise<string>;\n async readFile(path: string, binary: true): Promise<Buffer>;\n async readFile(path: string, binary?: boolean): Promise<string | Buffer> {\n // Detect absolute paths (Windows C:\\... or Unix /...)\n const isAbsolute = /^[A-Z]:[/\\\\]/i.test(path) || path.startsWith('/');\n const fullPath = isAbsolute ? path : this.resolve(path);\n\n if (binary) {\n return readFile(fullPath);\n }\n return readFile(fullPath, 'utf-8');\n }\n\n /**\n * Lists subdirectories in a directory.\n */\n async listDirs(path: string): Promise<string[]> {\n const entries = await readdir(this.resolve(path), { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n }\n\n /**\n * Lists files (not directories) in a directory.\n */\n async listFiles(path: string): Promise<string[]> {\n const entries = await readdir(this.resolve(path), { withFileTypes: true });\n return entries.filter((e) => e.isFile()).map((e) => e.name);\n }\n\n // ============================================================\n // Step File Operations (v2)\n // ============================================================\n\n /**\n * Ensures steps directory exists for a scenario.\n */\n async ensureStepsDir(scenarioSlug: string): Promise<void> {\n const stepsPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${scenarioSlug}/${STEPS_DIR}`;\n await this.ensureDir(stepsPath);\n }\n\n /**\n * Writes a step file to the scenario's steps directory.\n */\n async writeStepFile(\n scenarioSlug: string,\n stepId: string,\n stepSlug: string,\n content: string\n ): Promise<string> {\n const filename = `${stepId}-${stepSlug}.md`;\n const stepPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${scenarioSlug}/${STEPS_DIR}/${filename}`;\n await this.writeFile(stepPath, content);\n return stepPath;\n }\n\n /**\n * Reads a step file from the scenario's steps directory.\n */\n async readStepFile(scenarioSlug: string, filename: string): Promise<string> {\n const stepPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${scenarioSlug}/${STEPS_DIR}/${filename}`;\n return this.readFile(stepPath);\n }\n\n /**\n * Lists step files in a scenario's steps directory.\n */\n async listStepFiles(scenarioSlug: string): Promise<string[]> {\n const stepsPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${scenarioSlug}/${STEPS_DIR}`;\n if (!(await this.exists(stepsPath))) {\n return [];\n }\n const files = await this.listFiles(stepsPath);\n return files.filter((f) => /^\\d{2}-[\\w-]+\\.md$/.test(f)).sort();\n }\n\n /**\n * Gets the steps directory path for a scenario.\n */\n getStepsPath(scenarioSlug: string): string {\n return `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${scenarioSlug}/${STEPS_DIR}`;\n }\n}\n\n// ============================================================\n// Step Markdown Generator\n// ============================================================\n\n/**\n * Generates markdown content for a step file.\n */\nexport function generateStepMarkdown(step: Step): string {\n return `# Step ${step.id}: ${step.title}\n\n## Description\n${step.description}\n\n## Preconditions\n${step.preconditions}\n\n## Actions\n${step.actions}\n\n**Playwright:**\n\\`\\`\\`javascript\n// Add Playwright code here\n\\`\\`\\`\n\n## Expected Outcome\n${step.expectedOutcome}\n`;\n}\n","import { fork, ChildProcess } from 'child_process';\nimport { createServer } from 'net';\nimport { existsSync, writeFileSync, unlinkSync, readFileSync, mkdirSync } from 'fs';\nimport { join, resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { FileSystemService } from './file-system-service.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst DASHBOARD_STATE_FILE = '.dashboard-state.json';\nconst DEFAULT_DASHBOARD_PORT = 7002;\n\nexport interface DashboardState {\n pid: number;\n port: number;\n url: string;\n startedAt: string;\n projectPath: string;\n}\n\nexport interface DashboardStatus {\n running: boolean;\n pid?: number;\n port?: number;\n url?: string;\n startedAt?: string;\n stale?: boolean; // true if state file exists but process is dead\n}\n\n/**\n * Check if a port is available.\n * Binds to 0.0.0.0 (all interfaces) to match how the dashboard server binds.\n */\nexport async function isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer();\n server.once('error', () => resolve(false));\n server.once('listening', () => {\n server.close();\n resolve(true);\n });\n // Don't specify host - this binds to 0.0.0.0 like the dashboard server does\n server.listen(port);\n });\n}\n\n/**\n * Find an available port starting from the given port.\n */\nexport async function findAvailablePort(startPort: number, maxAttempts: number = 10): Promise<number> {\n for (let i = 0; i < maxAttempts; i++) {\n const port = startPort + i;\n if (await isPortAvailable(port)) {\n return port;\n }\n }\n throw new Error(`No available port found starting from ${startPort}`);\n}\n\n/**\n * Wait for a port to become unavailable (meaning server started).\n */\nexport async function waitForServer(port: number, timeoutMs: number = 5000): Promise<boolean> {\n const startTime = Date.now();\n while (Date.now() - startTime < timeoutMs) {\n if (!(await isPortAvailable(port))) {\n return true; // Server is now listening\n }\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n return false;\n}\n\n/**\n * Check if a process with the given PID is running.\n */\nexport function isProcessRunning(pid: number): boolean {\n try {\n // Sending signal 0 checks if process exists without actually sending a signal\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Kill a process by PID.\n */\nexport async function killProcess(pid: number): Promise<boolean> {\n try {\n process.kill(pid, 'SIGTERM');\n // Wait a bit for graceful shutdown\n await new Promise((resolve) => setTimeout(resolve, 300));\n // Check if still running and force kill\n if (isProcessRunning(pid)) {\n process.kill(pid, 'SIGKILL');\n }\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Dashboard lifecycle manager.\n * Starts the dashboard server in a forked process.\n */\nexport class DashboardManager {\n private fs: FileSystemService;\n private stateFilePath: string;\n private projectDir: string;\n\n constructor(fs: FileSystemService = new FileSystemService(), projectPath?: string) {\n this.fs = fs;\n this.projectDir = projectPath ? resolve(projectPath) : process.cwd();\n this.stateFilePath = join(this.projectDir, HARSH_JUDGE_DIR, DASHBOARD_STATE_FILE);\n }\n\n /**\n * Get dashboard state file path.\n */\n getStateFilePath(): string {\n return this.stateFilePath;\n }\n\n /**\n * Read the current dashboard state from file.\n */\n readState(): DashboardState | null {\n try {\n if (existsSync(this.stateFilePath)) {\n const content = readFileSync(this.stateFilePath, 'utf-8');\n return JSON.parse(content) as DashboardState;\n }\n } catch {\n // State file corrupted or unreadable\n }\n return null;\n }\n\n /**\n * Write dashboard state to file.\n */\n writeState(state: DashboardState): void {\n // Ensure .harshJudge directory exists\n const dir = dirname(this.stateFilePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(this.stateFilePath, JSON.stringify(state, null, 2));\n }\n\n /**\n * Remove dashboard state file.\n */\n clearState(): void {\n try {\n if (existsSync(this.stateFilePath)) {\n unlinkSync(this.stateFilePath);\n }\n } catch {\n // Ignore errors\n }\n }\n\n /**\n * Get the current dashboard status.\n */\n async getStatus(): Promise<DashboardStatus> {\n const state = this.readState();\n\n if (!state) {\n return { running: false };\n }\n\n // Check if process is still running\n const processAlive = isProcessRunning(state.pid);\n\n // Check if port is in use (double verification)\n const portInUse = !(await isPortAvailable(state.port));\n\n if (processAlive && portInUse) {\n return {\n running: true,\n pid: state.pid,\n port: state.port,\n url: state.url,\n startedAt: state.startedAt,\n };\n }\n\n // Stale state - process died but state file remains\n return {\n running: false,\n pid: state.pid,\n port: state.port,\n stale: true,\n };\n }\n\n /**\n * Start the dashboard server.\n */\n async start(preferredPort?: number): Promise<DashboardState> {\n // Check if already running\n const status = await this.getStatus();\n if (status.running) {\n throw new Error(`Dashboard already running on port ${status.port} (PID: ${status.pid}). Use closeDashboard first.`);\n }\n\n // Clean up stale state if exists\n if (status.stale) {\n this.clearState();\n }\n\n // Find available port\n const startPort = preferredPort ?? DEFAULT_DASHBOARD_PORT;\n const port = await findAvailablePort(startPort);\n\n // Skip in test environment\n if (process.env['NODE_ENV'] === 'test' || process.env['VITEST']) {\n const state: DashboardState = {\n pid: 0,\n port,\n url: `http://localhost:${port}`,\n startedAt: new Date().toISOString(),\n projectPath: this.projectDir,\n };\n this.writeState(state);\n return state;\n }\n\n // Find the dashboard worker script\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const workerPath = join(__dirname, 'dashboard-worker.js');\n\n console.error(`[HarshJudge] Starting dashboard on port ${port}`);\n console.error(`[HarshJudge] Project directory: ${this.projectDir}`);\n console.error(`[HarshJudge] Worker path: ${workerPath}`);\n\n // Fork the dashboard worker process\n let child: ChildProcess;\n try {\n child = fork(workerPath, [], {\n cwd: this.projectDir,\n detached: true,\n stdio: ['ignore', 'pipe', 'pipe', 'ipc'],\n env: {\n ...process.env,\n HARSHJUDGE_PORT: String(port),\n HARSHJUDGE_PROJECT_PATH: this.projectDir,\n },\n });\n } catch (err) {\n throw new Error(`Failed to fork dashboard worker: ${err}`);\n }\n\n const pid = child.pid;\n if (!pid) {\n throw new Error('Failed to fork dashboard worker - no PID returned');\n }\n\n // Capture startup errors\n let startupError = '';\n child.stderr?.on('data', (data) => {\n const msg = data.toString();\n console.error(`[Dashboard] ${msg}`);\n if (msg.toLowerCase().includes('error')) {\n startupError += msg;\n }\n });\n\n child.stdout?.on('data', (data) => {\n console.error(`[Dashboard] ${data.toString()}`);\n });\n\n // Wait for server to start\n const started = await waitForServer(port, 8000);\n\n // Disconnect IPC and unref to let parent exit\n child.disconnect?.();\n child.unref();\n\n if (!started) {\n if (startupError) {\n throw new Error(`Dashboard failed to start: ${startupError}`);\n }\n throw new Error(`Dashboard did not start within timeout on port ${port}`);\n }\n\n console.error(`[HarshJudge] Dashboard started successfully (PID: ${pid})`);\n\n // Save state\n const state: DashboardState = {\n pid,\n port,\n url: `http://localhost:${port}`,\n startedAt: new Date().toISOString(),\n projectPath: this.projectDir,\n };\n this.writeState(state);\n\n return state;\n }\n\n /**\n * Stop the dashboard server.\n */\n async stop(): Promise<{ stopped: boolean; message: string }> {\n const status = await this.getStatus();\n\n if (!status.running && !status.stale) {\n return { stopped: false, message: 'Dashboard is not running' };\n }\n\n if (status.stale) {\n this.clearState();\n return { stopped: true, message: 'Cleaned up stale dashboard state (process was already dead)' };\n }\n\n // Kill the process\n if (status.pid) {\n const killed = await killProcess(status.pid);\n if (!killed) {\n return { stopped: false, message: `Failed to kill process ${status.pid}` };\n }\n }\n\n // Clear state\n this.clearState();\n\n return { stopped: true, message: `Dashboard stopped (was running on port ${status.port})` };\n }\n\n /**\n * Restart the dashboard (stop then start).\n */\n async restart(preferredPort?: number): Promise<DashboardState> {\n await this.stop();\n return await this.start(preferredPort);\n }\n}\n","import {\n InitProjectParamsSchema,\n type InitProjectResult,\n type HarshJudgeConfig,\n} from '../types/index.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { DashboardManager } from '../services/dashboard-manager.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst CONFIG_FILE = 'config.yaml';\nconst SCENARIOS_DIR = 'scenarios';\nconst GITIGNORE_FILE = '.gitignore';\nconst PRD_FILE = 'prd.md';\n\nconst GITIGNORE_CONTENT = `# HarshJudge\n# Ignore large evidence files in CI (per-step structure)\nscenarios/*/runs/*/step-*/evidence/*.png\nscenarios/*/runs/*/step-*/evidence/*.html\n# Dashboard state (local only)\n.dashboard-state.json\n`;\n\nconst PRD_TEMPLATE_CONTENT = `# Project PRD\n\n## Application Type\n<!-- backend | fullstack | frontend | other -->\n{app_type}\n\n## Ports\n| Service | Port |\n|---------|------|\n| Frontend | {frontend_port} |\n| Backend | {backend_port} |\n| Database | {database_port} |\n\n## Main Scenarios\n<!-- High-level list of main testing scenarios -->\n- {scenario_1}\n- {scenario_2}\n- {scenario_3}\n\n## Authentication\n<!-- Auth requirements for testing -->\n- **Login URL:** {login_url}\n- **Test Credentials:**\n - Username: {test_username}\n - Password: {test_password}\n\n## Tech Stack\n<!-- Frameworks, libraries, tools -->\n- Frontend: {frontend_stack}\n- Backend: {backend_stack}\n- Testing: {testing_tools}\n\n## Notes\n<!-- Additional context for test scenarios -->\n- {note_1}\n- {note_2}\n`;\n\n/**\n * Initializes a HarshJudge project in the current directory.\n * Creates the .harshJudge directory structure with config and gitignore.\n * Automatically spawns the dashboard server.\n */\nexport async function handleInitProject(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<InitProjectResult> {\n // 1. Validate input parameters\n const validated = InitProjectParamsSchema.parse(params);\n\n // 2. Check if project is already initialized\n if (await fs.exists(HARSH_JUDGE_DIR)) {\n throw new Error(\n 'Project already initialized. Use a different directory or remove existing .harshJudge folder.'\n );\n }\n\n // 3. Create directory structure\n await fs.ensureDir(HARSH_JUDGE_DIR);\n await fs.ensureDir(`${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}`);\n\n // 4. Write config.yaml\n const config: HarshJudgeConfig = {\n projectName: validated.projectName,\n baseUrl: validated.baseUrl ?? '',\n version: '1.0',\n createdAt: new Date().toISOString(),\n };\n const configPath = `${HARSH_JUDGE_DIR}/${CONFIG_FILE}`;\n await fs.writeYaml(configPath, config);\n\n // 5. Write .gitignore\n const gitignorePath = `${HARSH_JUDGE_DIR}/${GITIGNORE_FILE}`;\n await fs.writeFile(gitignorePath, GITIGNORE_CONTENT);\n\n // 6. Write prd.md template\n const prdPath = `${HARSH_JUDGE_DIR}/${PRD_FILE}`;\n await fs.writeFile(prdPath, PRD_TEMPLATE_CONTENT);\n\n // 7. Spawn dashboard server using DashboardManager\n let dashboardUrl: string | undefined;\n let message = 'HarshJudge initialized successfully';\n\n try {\n const manager = new DashboardManager(fs);\n const state = await manager.start();\n dashboardUrl = state.url;\n message = `HarshJudge initialized successfully. Dashboard running at ${dashboardUrl} (PID: ${state.pid})`;\n console.error(`[HarshJudge] ${message}`);\n } catch (error) {\n // Dashboard spawn failure is non-fatal - project is still initialized\n console.error(`[HarshJudge] Warning: Could not start dashboard: ${error}`);\n message = `HarshJudge initialized successfully. Dashboard could not be started automatically - use openDashboard tool to start it.`;\n }\n\n // 8. Return success result\n return {\n success: true,\n projectPath: HARSH_JUDGE_DIR,\n configPath,\n prdPath,\n scenariosPath: `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}`,\n dashboardUrl,\n message,\n };\n}\n","export function withErrorHandling(fn: (...args: any[]) => Promise<void>) {\n return async (...args: any[]) => {\n try {\n await fn(...args);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(JSON.stringify({ error: message }));\n process.exit(1);\n }\n };\n}\n","import { Command } from 'commander';\nimport { handleCreateScenario } from '../handlers/create-scenario.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('create <slug>')\n .description('Create a new test scenario')\n .requiredOption('--title <title>', 'Scenario title')\n .requiredOption('--steps <json>', 'Steps as a JSON string')\n .option('--tags <tags>', 'Comma-separated list of tags')\n .option('--estimated-duration <seconds>', 'Estimated duration in seconds')\n .option('--starred', 'Mark scenario as starred')\n .action(\n withErrorHandling(\n async (\n slug: string,\n opts: {\n title: string;\n steps: string;\n tags?: string;\n estimatedDuration?: string;\n starred?: boolean;\n },\n cmd: Command\n ) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const tags = opts.tags\n ? opts.tags.split(',').map((t) => t.trim())\n : undefined;\n const result = await handleCreateScenario(\n {\n slug,\n title: opts.title,\n steps: JSON.parse(opts.steps),\n tags,\n estimatedDuration: opts.estimatedDuration\n ? parseInt(opts.estimatedDuration, 10)\n : undefined,\n starred: opts.starred,\n },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n}\n","/**\n * Convert a string to a URL-safe slug.\n * Example: \"Navigate to Login Page\" -> \"navigate-to-login-page\"\n */\nexport function slugify(text: string): string {\n return text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '') // Remove special characters\n .replace(/[\\s_-]+/g, '-') // Replace spaces and underscores with hyphens\n .replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens\n}\n","import {\n CreateScenarioParamsSchema,\n type CreateScenarioResult,\n type StepInput,\n type ScenarioMeta,\n type StepReference,\n DEFAULT_SCENARIO_STATS,\n padStepId,\n} from '../types/index.js';\nimport { FileSystemService, generateStepMarkdown } from '../services/file-system-service.js';\nimport { slugify } from '../utils/slugify.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst STEPS_DIR = 'steps';\nconst META_FILE = 'meta.yaml';\n\n/**\n * Generates a step markdown file content.\n */\nfunction generateStepContent(stepId: string, step: StepInput): string {\n return generateStepMarkdown({\n id: stepId,\n title: step.title,\n description: step.description || '',\n preconditions: step.preconditions || '',\n actions: step.actions,\n expectedOutcome: step.expectedOutcome,\n });\n}\n\n/**\n * Creates a complete scenario structure with steps (v2).\n * Replaces the deprecated saveScenario handler.\n */\nexport async function handleCreateScenario(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<CreateScenarioResult> {\n // 1. Validate input parameters\n const validated = CreateScenarioParamsSchema.parse(params);\n\n // 2. Check if project is initialized\n if (!(await fs.exists(HARSH_JUDGE_DIR))) {\n throw new Error('Project not initialized. Run initProject first.');\n }\n\n // 3. Determine if scenario already exists\n const scenarioPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${validated.slug}`;\n const stepsPath = `${scenarioPath}/${STEPS_DIR}`;\n const metaPath = `${scenarioPath}/${META_FILE}`;\n const isNew = !(await fs.exists(scenarioPath));\n\n // 4. Create directories\n await fs.ensureDir(stepsPath);\n\n // 5. If updating, remove old step files that aren't in new steps\n if (!isNew) {\n const existingStepFiles = await fs.listStepFiles(validated.slug);\n const newStepCount = validated.steps.length;\n\n for (const file of existingStepFiles) {\n const stepNum = parseInt(file.substring(0, 2), 10);\n if (stepNum > newStepCount) {\n // Remove orphaned step file\n const orphanPath = `${stepsPath}/${file}`;\n // Note: FileSystemService doesn't have delete, so we just overwrite\n // In production, you'd want to add a delete method\n }\n }\n }\n\n // 6. Generate step files\n const stepFiles: string[] = [];\n const stepRefs: StepReference[] = [];\n\n for (let i = 0; i < validated.steps.length; i++) {\n const step = validated.steps[i];\n const stepId = padStepId(i + 1);\n const stepSlug = slugify(step.title);\n const filename = `${stepId}-${stepSlug}.md`;\n const stepFilePath = `${stepsPath}/${filename}`;\n\n // Generate step content\n const content = generateStepContent(stepId, step);\n await fs.writeFile(stepFilePath, content);\n\n stepFiles.push(stepFilePath);\n stepRefs.push({\n id: stepId,\n title: step.title,\n file: filename,\n });\n }\n\n // 7. Generate and write meta.yaml\n const existingMeta = isNew ? null : await loadExistingMeta(fs, metaPath);\n\n const meta: ScenarioMeta = {\n // Definition fields\n title: validated.title,\n slug: validated.slug,\n starred: validated.starred,\n tags: validated.tags,\n estimatedDuration: validated.estimatedDuration,\n steps: stepRefs,\n // Statistics (preserve existing or initialize)\n ...DEFAULT_SCENARIO_STATS,\n ...(existingMeta\n ? {\n totalRuns: existingMeta.totalRuns,\n passCount: existingMeta.passCount,\n failCount: existingMeta.failCount,\n lastRun: existingMeta.lastRun,\n lastResult: existingMeta.lastResult,\n avgDuration: existingMeta.avgDuration,\n }\n : {}),\n };\n\n await fs.writeYaml(metaPath, meta);\n\n // 8. Return result\n return {\n success: true,\n slug: validated.slug,\n scenarioPath,\n metaPath,\n stepsPath,\n stepFiles,\n isNew,\n };\n}\n\n/**\n * Load existing meta.yaml if it exists, for preserving statistics.\n */\nasync function loadExistingMeta(\n fs: FileSystemService,\n metaPath: string\n): Promise<ScenarioMeta | null> {\n try {\n if (await fs.exists(metaPath)) {\n return await fs.readYaml<ScenarioMeta>(metaPath);\n }\n } catch {\n // Ignore errors, return null\n }\n return null;\n}\n","import { Command } from 'commander';\nimport { handleToggleStar } from '../handlers/toggle-star.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('star <slug>')\n .description('Star or unstar a scenario')\n .option('--unstar', 'Remove star from scenario')\n .action(\n withErrorHandling(\n async (slug: string, opts: { unstar?: boolean }, cmd: Command) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleToggleStar(\n { scenarioSlug: slug, starred: !opts.unstar },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n}\n","import {\n ToggleStarParamsSchema,\n type ToggleStarResult,\n type ScenarioMeta,\n} from '../types/index.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst META_FILE = 'meta.yaml';\n\n/**\n * Toggle or set the starred status of a scenario.\n */\nexport async function handleToggleStar(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<ToggleStarResult> {\n // 1. Validate input parameters\n const validated = ToggleStarParamsSchema.parse(params);\n\n // 2. Check if project is initialized\n if (!(await fs.exists(HARSH_JUDGE_DIR))) {\n throw new Error('Project not initialized. Run initProject first.');\n }\n\n // 3. Check if scenario exists\n const scenarioPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${validated.scenarioSlug}`;\n const metaPath = `${scenarioPath}/${META_FILE}`;\n\n if (!(await fs.exists(scenarioPath))) {\n throw new Error(`Scenario \"${validated.scenarioSlug}\" does not exist.`);\n }\n\n // 4. Read existing meta.yaml\n let meta: ScenarioMeta;\n if (await fs.exists(metaPath)) {\n meta = await fs.readYaml<ScenarioMeta>(metaPath);\n } else {\n throw new Error(`Scenario \"${validated.scenarioSlug}\" has no meta.yaml.`);\n }\n\n // 5. Determine new starred value\n const newStarred =\n validated.starred !== undefined ? validated.starred : !meta.starred;\n\n // 6. Update meta.yaml\n meta.starred = newStarred;\n await fs.writeYaml(metaPath, meta);\n\n // 7. Return result\n return {\n success: true,\n slug: validated.scenarioSlug,\n starred: newStarred,\n };\n}\n","import { Command } from 'commander';\nimport { handleGetStatus } from '../handlers/get-status.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('status [slug]')\n .description('Get project or scenario status')\n .option('--starred-only', 'Show only starred scenarios')\n .action(\n withErrorHandling(\n async (\n slug: string | undefined,\n opts: { starredOnly?: boolean },\n cmd: Command\n ) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleGetStatus(\n { scenarioSlug: slug, starredOnly: opts.starredOnly },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n}\n","import {\n GetStatusParamsSchema,\n type GetStatusResult,\n type ProjectStatus,\n type ScenarioDetail,\n type ScenarioSummary,\n type ScenarioMeta,\n type HarshJudgeConfig,\n type RunSummary,\n} from '../types/index.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst CONFIG_FILE = 'config.yaml';\nconst SCENARIO_FILE = 'scenario.md';\nconst META_FILE = 'meta.yaml';\nconst RUNS_DIR = 'runs';\nconst RESULT_FILE = 'result.json';\n\n/**\n * Parses YAML frontmatter from scenario.md content.\n */\nfunction parseFrontmatter(content: string): { title: string; tags: string[] } {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match || !match[1]) {\n return { title: 'Untitled', tags: [] };\n }\n\n const frontmatter = match[1];\n let title = 'Untitled';\n let tags: string[] = [];\n\n // Parse title\n const titleMatch = frontmatter.match(/^title:\\s*(.+)$/m);\n if (titleMatch && titleMatch[1]) {\n title = titleMatch[1].trim();\n }\n\n // Parse tags\n const tagsMatch = frontmatter.match(/^tags:\\s*\\[([^\\]]*)\\]/m);\n if (tagsMatch && tagsMatch[1] !== undefined) {\n tags = tagsMatch[1]\n .split(',')\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n\n return { title, tags };\n}\n\n/**\n * Gets the content of scenario.md without the frontmatter.\n */\nfunction getContentWithoutFrontmatter(content: string): string {\n return content.replace(/^---\\n[\\s\\S]*?\\n---\\n*/, '');\n}\n\n/**\n * Extended ScenarioMeta that may include v2 fields\n */\ninterface ScenarioMetaV2 extends ScenarioMeta {\n starred?: boolean;\n title?: string;\n steps?: Array<{ id: string; title: string; file: string }>;\n}\n\n/**\n * Gets project-level status with all scenarios.\n */\nasync function getProjectStatus(\n fs: FileSystemService,\n starredOnly: boolean = false\n): Promise<ProjectStatus> {\n // Read config\n const configPath = `${HARSH_JUDGE_DIR}/${CONFIG_FILE}`;\n const config = await fs.readYaml<HarshJudgeConfig>(configPath);\n\n // Get all scenarios\n const scenariosPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}`;\n const scenarioSlugs = await fs.listDirs(scenariosPath);\n\n const scenarios: ScenarioSummary[] = [];\n let passing = 0;\n let failing = 0;\n let neverRun = 0;\n\n for (const slug of scenarioSlugs) {\n const scenarioPath = `${scenariosPath}/${slug}`;\n\n // Read meta.yaml for stats (v2 format includes title, starred, steps)\n const metaPath = `${scenarioPath}/${META_FILE}`;\n let meta: ScenarioMetaV2;\n let title = 'Untitled';\n let tags: string[] = [];\n let starred = false;\n let stepCount = 0;\n\n if (await fs.exists(metaPath)) {\n meta = await fs.readYaml<ScenarioMetaV2>(metaPath);\n // v2 format: title and starred in meta.yaml\n if (meta.title) {\n title = meta.title;\n }\n starred = meta.starred ?? false;\n stepCount = meta.steps?.length ?? 0;\n } else {\n meta = {\n totalRuns: 0,\n passCount: 0,\n failCount: 0,\n lastRun: null,\n lastResult: null,\n avgDuration: 0,\n };\n }\n\n // Fallback to scenario.md for title and tags (v1 format)\n const scenarioFilePath = `${scenarioPath}/${SCENARIO_FILE}`;\n if (await fs.exists(scenarioFilePath)) {\n const scenarioContent = await fs.readFile(scenarioFilePath);\n const parsed = parseFrontmatter(scenarioContent);\n if (!meta.title) {\n title = parsed.title;\n }\n tags = parsed.tags;\n }\n\n // Skip non-starred scenarios if filter is enabled\n if (starredOnly && !starred) {\n continue;\n }\n\n // Calculate pass rate\n const passRate = meta.totalRuns > 0\n ? Math.round((meta.passCount / meta.totalRuns) * 100)\n : 0;\n\n // Count status\n if (meta.totalRuns === 0) {\n neverRun++;\n } else if (meta.lastResult === 'pass') {\n passing++;\n } else {\n failing++;\n }\n\n scenarios.push({\n slug,\n title,\n starred,\n tags,\n stepCount,\n lastResult: meta.lastResult,\n lastRun: meta.lastRun,\n totalRuns: meta.totalRuns,\n passRate,\n });\n }\n\n return {\n projectName: config.projectName,\n scenarioCount: scenarios.length,\n passing,\n failing,\n neverRun,\n scenarios,\n };\n}\n\n/**\n * Gets detailed status for a specific scenario.\n */\nasync function getScenarioDetail(\n fs: FileSystemService,\n slug: string\n): Promise<ScenarioDetail> {\n const scenarioPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${slug}`;\n\n // Check if scenario exists\n if (!(await fs.exists(scenarioPath))) {\n throw new Error(`Scenario \"${slug}\" does not exist.`);\n }\n\n // Read meta.yaml for stats (v2 format includes title, starred, steps)\n const metaPath = `${scenarioPath}/${META_FILE}`;\n let meta: ScenarioMetaV2;\n let title = 'Untitled';\n let tags: string[] = [];\n let starred = false;\n let stepCount = 0;\n let content = '';\n\n if (await fs.exists(metaPath)) {\n meta = await fs.readYaml<ScenarioMetaV2>(metaPath);\n // v2 format: title and starred in meta.yaml\n if (meta.title) {\n title = meta.title;\n }\n starred = meta.starred ?? false;\n stepCount = meta.steps?.length ?? 0;\n } else {\n meta = {\n totalRuns: 0,\n passCount: 0,\n failCount: 0,\n lastRun: null,\n lastResult: null,\n avgDuration: 0,\n };\n }\n\n // Fallback to scenario.md for title and tags (v1 format)\n const scenarioFilePath = `${scenarioPath}/${SCENARIO_FILE}`;\n if (await fs.exists(scenarioFilePath)) {\n const scenarioContent = await fs.readFile(scenarioFilePath);\n const parsed = parseFrontmatter(scenarioContent);\n if (!meta.title) {\n title = parsed.title;\n }\n tags = parsed.tags;\n content = getContentWithoutFrontmatter(scenarioContent);\n }\n\n // Get recent runs (last 10)\n const runsPath = `${scenarioPath}/${RUNS_DIR}`;\n const recentRuns: RunSummary[] = [];\n\n if (await fs.exists(runsPath)) {\n const runIds = await fs.listDirs(runsPath);\n\n // Type for run result data\n interface RunResultData {\n runId: string;\n status: 'pass' | 'fail';\n duration: number;\n completedAt: string;\n errorMessage?: string | null;\n }\n\n // Read results for completed runs\n const runResults: Array<{ id: string; result: RunResultData }> = [];\n\n for (const id of runIds) {\n const resultPath = `${runsPath}/${id}/${RESULT_FILE}`;\n if (await fs.exists(resultPath)) {\n const result = await fs.readJson<RunResultData>(resultPath);\n runResults.push({ id, result });\n }\n }\n\n // Sort by completedAt descending and take last 10\n runResults.sort((a, b) =>\n new Date(b.result.completedAt).getTime() -\n new Date(a.result.completedAt).getTime()\n );\n\n for (let i = 0; i < Math.min(10, runResults.length); i++) {\n const runData = runResults[i];\n if (runData) {\n const { id, result } = runData;\n recentRuns.push({\n id,\n runNumber: runResults.length - i, // Approximate run number\n status: result.status,\n duration: result.duration,\n completedAt: result.completedAt,\n errorMessage: result.errorMessage || null,\n });\n }\n }\n }\n\n return {\n slug,\n title,\n starred,\n tags,\n stepCount,\n content,\n meta,\n recentRuns,\n };\n}\n\n/**\n * Gets status of all scenarios or a specific scenario.\n */\nexport async function handleGetStatus(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<GetStatusResult> {\n // 1. Validate input parameters\n const validated = GetStatusParamsSchema.parse(params);\n\n // 2. Check if project is initialized\n if (!(await fs.exists(HARSH_JUDGE_DIR))) {\n throw new Error('Project not initialized. Run initProject first.');\n }\n\n // 3. Return appropriate status\n if (validated.scenarioSlug) {\n return getScenarioDetail(fs, validated.scenarioSlug);\n } else {\n return getProjectStatus(fs, validated.starredOnly);\n }\n}\n","import { Command } from 'commander';\nimport { handleStartRun } from '../handlers/start-run.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('start <slug>')\n .description('Start a new test run for a scenario')\n .action(\n withErrorHandling(async (slug: string, _opts: unknown, cmd: Command) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleStartRun({ scenarioSlug: slug }, fs);\n console.log(JSON.stringify(result));\n })\n );\n}\n","import { nanoid } from 'nanoid';\nimport {\n StartRunParamsSchema,\n type StartRunResult,\n type StartRunStepInfo,\n} from '../types/index.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst RUNS_DIR = 'runs';\nconst EVIDENCE_DIR = 'evidence';\nconst META_FILE = 'meta.yaml';\n\ninterface ScenarioMetaYaml {\n title: string;\n slug: string;\n starred?: boolean;\n tags?: string[];\n estimatedDuration?: number;\n steps?: Array<{\n id: string;\n title: string;\n file: string;\n }>;\n totalRuns?: number;\n passCount?: number;\n failCount?: number;\n avgDuration?: number;\n}\n\n/**\n * Starts a new test run for a scenario.\n * Creates run directory with evidence subdirectory.\n * Returns step information from meta.yaml for orchestration.\n */\nexport async function handleStartRun(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<StartRunResult> {\n // 1. Validate input parameters\n const validated = StartRunParamsSchema.parse(params);\n\n // 2. Check if project is initialized\n if (!(await fs.exists(HARSH_JUDGE_DIR))) {\n throw new Error('Project not initialized. Run initProject first.');\n }\n\n // 3. Check if scenario exists\n const scenarioDir = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}/${validated.scenarioSlug}`;\n if (!(await fs.exists(scenarioDir))) {\n throw new Error(`Scenario \"${validated.scenarioSlug}\" does not exist.`);\n }\n\n // 4. Read meta.yaml for step information\n const metaPath = `${scenarioDir}/${META_FILE}`;\n if (!(await fs.exists(metaPath))) {\n throw new Error(`Scenario \"${validated.scenarioSlug}\" has no meta.yaml.`);\n }\n const meta = (await fs.readYaml(metaPath)) as ScenarioMetaYaml;\n\n // 5. Extract step information\n const steps: StartRunStepInfo[] = (meta.steps || []).map((step) => ({\n id: step.id,\n title: step.title,\n file: step.file,\n }));\n\n // 6. Generate unique run ID (10 characters, URL-safe)\n const runId = nanoid(10);\n\n // 7. Calculate run number (count existing runs + 1)\n const runsDir = `${scenarioDir}/${RUNS_DIR}`;\n let runNumber = 1;\n if (await fs.exists(runsDir)) {\n const existingRuns = await fs.listDirs(runsDir);\n runNumber = existingRuns.length + 1;\n }\n\n // 8. Create run directory structure\n const runPath = `${runsDir}/${runId}`;\n const evidencePath = `${runPath}/${EVIDENCE_DIR}`;\n await fs.ensureDir(runPath);\n await fs.ensureDir(evidencePath);\n\n // 9. Record start timestamp\n const startedAt = new Date().toISOString();\n\n // 10. Return result with step information\n return {\n success: true,\n runId,\n runNumber,\n runPath,\n evidencePath,\n startedAt,\n scenarioSlug: validated.scenarioSlug,\n scenarioTitle: meta.title,\n steps,\n };\n}\n","import { Command } from 'commander';\nimport { handleRecordEvidence } from '../handlers/record-evidence.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('evidence <runId>')\n .description('Record evidence for a test run step')\n .option('--step <n>', 'Step number')\n .option(\n '--type <type>',\n 'Evidence type (screenshot, db_snapshot, console_log, etc.)'\n )\n .option('--name <name>', 'Evidence name')\n .option('--data <data>', 'Evidence data or file path')\n .action(\n withErrorHandling(\n async (\n runId: string,\n opts: { step?: string; type?: string; name?: string; data?: string },\n cmd: Command\n ) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleRecordEvidence(\n {\n runId,\n step: parseInt(opts.step ?? '1', 10),\n type: opts.type,\n name: opts.name,\n data: opts.data,\n },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n}\n","import {\n RecordEvidenceParamsSchema,\n type RecordEvidenceResult,\n} from '../types/index.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst RUNS_DIR = 'runs';\nconst RESULT_FILE = 'result.json';\n\n// Map evidence types to file extensions\nconst EVIDENCE_EXTENSIONS: Record<string, string> = {\n screenshot: 'png',\n db_snapshot: 'json',\n console_log: 'txt',\n network_log: 'json',\n html_snapshot: 'html',\n custom: 'json',\n};\n\n// Binary types that require file path input\nconst BINARY_TYPES = new Set(['screenshot']);\n\n/**\n * Check if a string looks like an absolute file path\n * Supports Windows (C:\\...) and Unix (/...) paths\n */\nfunction isAbsoluteFilePath(data: string): boolean {\n // Windows absolute path (e.g., C:\\Users\\... or D:/path/...)\n if (/^[A-Z]:[/\\\\]/i.test(data)) {\n return true;\n }\n // Unix absolute path (starts with /)\n if (data.startsWith('/')) {\n return true;\n }\n return false;\n}\n\n/**\n * Finds the run directory by searching all scenarios for the given runId.\n * Returns the full path to the run directory or null if not found.\n */\nasync function findRunDirectory(\n fs: FileSystemService,\n runId: string\n): Promise<string | null> {\n const scenariosPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}`;\n\n if (!(await fs.exists(scenariosPath))) {\n return null;\n }\n\n const scenarios = await fs.listDirs(scenariosPath);\n\n for (const scenario of scenarios) {\n const runPath = `${scenariosPath}/${scenario}/${RUNS_DIR}/${runId}`;\n if (await fs.exists(runPath)) {\n return runPath;\n }\n }\n\n return null;\n}\n\n/**\n * Checks if a run has been completed (result.json exists with status !== 'running').\n * A run is considered completed if it has status 'pass' or 'fail'.\n * Status 'running' means the run is still in progress and can accept evidence.\n */\nasync function isRunCompleted(\n fs: FileSystemService,\n runPath: string\n): Promise<boolean> {\n const resultPath = `${runPath}/${RESULT_FILE}`;\n if (!(await fs.exists(resultPath))) {\n return false;\n }\n\n const result = await fs.readJson<{ status: string }>(resultPath);\n // Only completed if status is 'pass' or 'fail', not 'running'\n return result.status === 'pass' || result.status === 'fail';\n}\n\n/**\n * Records test evidence (screenshot, log, db snapshot) for a test run.\n * v2: Evidence is stored in per-step directories: runs/{runId}/step-{stepId}/evidence/\n */\nexport async function handleRecordEvidence(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<RecordEvidenceResult> {\n // 1. Validate input parameters\n const validated = RecordEvidenceParamsSchema.parse(params);\n\n // 2. Check if project is initialized\n if (!(await fs.exists(HARSH_JUDGE_DIR))) {\n throw new Error('Project not initialized. Run initProject first.');\n }\n\n // 3. Find the run directory\n const runPath = await findRunDirectory(fs, validated.runId);\n if (!runPath) {\n throw new Error(`Run \"${validated.runId}\" does not exist.`);\n }\n\n // 4. Check if run is already completed\n if (await isRunCompleted(fs, runPath)) {\n throw new Error(`Run \"${validated.runId}\" is already completed. Cannot add evidence.`);\n }\n\n // 5. Prepare file paths (v2: per-step directory)\n const stepId = String(validated.step).padStart(2, '0');\n const extension = EVIDENCE_EXTENSIONS[validated.type] || 'bin';\n const fileName = `${validated.name}.${extension}`;\n const metaFileName = `${validated.name}.meta.json`;\n\n // v2 path structure: runs/{runId}/step-{stepId}/evidence/\n const stepPath = `${runPath}/step-${stepId}`;\n const evidencePath = `${stepPath}/evidence`;\n const filePath = `${evidencePath}/${fileName}`;\n const metaPath = `${evidencePath}/${metaFileName}`;\n\n // 6. Read/write evidence data\n let dataToWrite: string | Buffer;\n let fileSize: number;\n\n if (BINARY_TYPES.has(validated.type)) {\n // For screenshot type, data MUST be an absolute file path\n if (!isAbsoluteFilePath(validated.data)) {\n throw new Error(\n `For type=\"${validated.type}\", data must be an absolute file path to the image file. ` +\n `Got: \"${validated.data.substring(0, 50)}${validated.data.length > 50 ? '...' : ''}\". ` +\n `Use the file path from Playwright's browser_take_screenshot tool.`\n );\n }\n // Read binary file from the path\n try {\n dataToWrite = await fs.readFile(validated.data, true);\n fileSize = dataToWrite.length;\n } catch {\n throw new Error(`Cannot read screenshot file: ${validated.data}`);\n }\n } else {\n // Write as-is for text types\n dataToWrite = validated.data;\n fileSize = Buffer.byteLength(validated.data, 'utf-8');\n }\n\n await fs.ensureDir(evidencePath);\n await fs.writeFile(filePath, dataToWrite);\n\n // 7. Write metadata (v2: uses stepId instead of step number)\n const metadata = {\n runId: validated.runId,\n stepId,\n type: validated.type,\n name: validated.name,\n capturedAt: new Date().toISOString(),\n fileSize,\n metadata: validated.metadata || {},\n };\n await fs.writeJson(metaPath, metadata);\n\n // 8. Return result (v2: includes stepPath)\n return {\n success: true,\n filePath,\n metaPath,\n stepPath,\n fileSize,\n };\n}\n","import { Command } from 'commander';\nimport { handleCompleteStep } from '../handlers/complete-step.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('complete-step <runId>')\n .description('Complete a single step in a test run')\n .option('--step <id>', 'Step ID (zero-padded, e.g. 01)')\n .option('--status <status>', 'Step status (pass, fail, skipped)')\n .requiredOption('--duration <ms>', 'Step duration in milliseconds')\n .option('--error <msg>', 'Error message if step failed')\n .option('--summary <text>', 'Step summary')\n .action(\n withErrorHandling(\n async (\n runId: string,\n opts: {\n step?: string;\n status?: string;\n duration: string;\n error?: string;\n summary?: string;\n },\n cmd: Command\n ) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleCompleteStep(\n {\n runId,\n stepId: opts.step,\n status: opts.status,\n duration: parseInt(opts.duration, 10),\n error: opts.error,\n summary: opts.summary,\n },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n}\n","import {\n CompleteStepParamsSchema,\n type CompleteStepResult,\n type StepResult,\n type ScenarioMeta,\n StepReferenceSchema,\n} from '../types/index.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst RUNS_DIR = 'runs';\nconst RESULT_FILE = 'result.json';\nconst META_FILE = 'meta.yaml';\n\ninterface InProgressResult {\n runId: string;\n scenarioSlug: string;\n status: 'running';\n startedAt: string;\n steps: StepResult[];\n}\n\n/**\n * Finds the run directory and its parent scenario by searching all scenarios.\n * Returns the run path and scenario slug, or null if not found.\n */\nasync function findRunAndScenario(\n fs: FileSystemService,\n runId: string\n): Promise<{ runPath: string; scenarioSlug: string; scenarioPath: string } | null> {\n const scenariosPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}`;\n\n if (!(await fs.exists(scenariosPath))) {\n return null;\n }\n\n const scenarios = await fs.listDirs(scenariosPath);\n\n for (const scenario of scenarios) {\n const scenarioPath = `${scenariosPath}/${scenario}`;\n const runPath = `${scenarioPath}/${RUNS_DIR}/${runId}`;\n if (await fs.exists(runPath)) {\n return { runPath, scenarioSlug: scenario, scenarioPath };\n }\n }\n\n return null;\n}\n\n/**\n * Gets the next step ID from the scenario's step references.\n * Returns null if current step is the last one or no steps defined.\n */\nasync function getNextStepId(\n fs: FileSystemService,\n scenarioPath: string,\n currentStepId: string\n): Promise<string | null> {\n const metaPath = `${scenarioPath}/${META_FILE}`;\n\n if (!(await fs.exists(metaPath))) {\n return null;\n }\n\n const meta = await fs.readYaml<ScenarioMeta>(metaPath);\n\n if (!meta.steps || meta.steps.length === 0) {\n return null;\n }\n\n // Find current step index\n const currentIdx = meta.steps.findIndex((s) => s.id === currentStepId);\n\n if (currentIdx === -1 || currentIdx >= meta.steps.length - 1) {\n // Current step not found or is the last step\n return null;\n }\n\n return meta.steps[currentIdx + 1].id;\n}\n\n/**\n * Lists evidence files in a step's evidence directory.\n */\nasync function listStepEvidence(\n fs: FileSystemService,\n runPath: string,\n stepId: string\n): Promise<string[]> {\n const evidencePath = `${runPath}/step-${stepId}/evidence`;\n\n if (!(await fs.exists(evidencePath))) {\n return [];\n }\n\n const files = await fs.listFiles(evidencePath);\n return files.filter((f) => !f.endsWith('.meta.json'));\n}\n\n/**\n * Completes a single step in a test run (v2).\n * Updates the in-progress result and returns the next step ID.\n */\nexport async function handleCompleteStep(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<CompleteStepResult> {\n // 1. Validate input parameters\n const validated = CompleteStepParamsSchema.parse(params);\n\n // 2. Check if project is initialized\n if (!(await fs.exists(HARSH_JUDGE_DIR))) {\n throw new Error('Project not initialized. Run initProject first.');\n }\n\n // 3. Find the run and its scenario\n const found = await findRunAndScenario(fs, validated.runId);\n if (!found) {\n throw new Error(`Run \"${validated.runId}\" does not exist.`);\n }\n\n const { runPath, scenarioSlug, scenarioPath } = found;\n\n // 4. Check if run is already completed\n const resultPath = `${runPath}/${RESULT_FILE}`;\n if (await fs.exists(resultPath)) {\n const existingResult = await fs.readJson<{ status: string }>(resultPath);\n if (existingResult.status !== 'running') {\n throw new Error(`Run \"${validated.runId}\" is already completed. Cannot add step results.`);\n }\n }\n\n // 5. Load or create in-progress result\n let inProgress: InProgressResult;\n const runJsonPath = `${runPath}/run.json`;\n\n if (await fs.exists(resultPath)) {\n inProgress = await fs.readJson<InProgressResult>(resultPath);\n } else if (await fs.exists(runJsonPath)) {\n const runData = await fs.readJson<{ startedAt: string }>(runJsonPath);\n inProgress = {\n runId: validated.runId,\n scenarioSlug,\n status: 'running',\n startedAt: runData.startedAt,\n steps: [],\n };\n } else {\n inProgress = {\n runId: validated.runId,\n scenarioSlug,\n status: 'running',\n startedAt: new Date().toISOString(),\n steps: [],\n };\n }\n\n // 6. Collect evidence files for this step\n const evidenceFiles = await listStepEvidence(fs, runPath, validated.stepId);\n\n // 7. Create or update step result\n const stepResult: StepResult = {\n id: validated.stepId,\n status: validated.status,\n duration: validated.duration,\n error: validated.error ?? null,\n evidenceFiles,\n summary: validated.summary ?? null,\n };\n\n // Find existing step or add new one\n const existingIdx = inProgress.steps.findIndex((s) => s.id === validated.stepId);\n if (existingIdx >= 0) {\n inProgress.steps[existingIdx] = stepResult;\n } else {\n inProgress.steps.push(stepResult);\n // Sort steps by ID\n inProgress.steps.sort((a, b) => a.id.localeCompare(b.id));\n }\n\n // 8. Write updated in-progress result\n await fs.writeJson(resultPath, inProgress);\n\n // 9. Determine next step ID\n let nextStepId: string | null = null;\n\n if (validated.status === 'pass' || validated.status === 'skipped') {\n // Get next step from scenario meta\n nextStepId = await getNextStepId(fs, scenarioPath, validated.stepId);\n }\n // If status is 'fail', nextStepId stays null (stop execution)\n\n // 10. Return result\n return {\n success: true,\n runId: validated.runId,\n stepId: validated.stepId,\n status: validated.status,\n nextStepId,\n };\n}\n","import { Command } from 'commander';\nimport { handleCompleteRun } from '../handlers/complete-run.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n program\n .command('complete-run <runId>')\n .description('Complete a test run and update scenario statistics')\n .option('--status <status>', 'Run status (pass, fail)')\n .requiredOption('--duration <ms>', 'Run duration in milliseconds')\n .option('--failed-step <id>', 'ID of the failed step')\n .option('--error <msg>', 'Error message')\n .option('--steps <json>', 'Steps as a JSON string')\n .action(\n withErrorHandling(\n async (\n runId: string,\n opts: {\n status?: string;\n duration: string;\n failedStep?: string;\n error?: string;\n steps?: string;\n },\n cmd: Command\n ) => {\n const cwd = cmd.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleCompleteRun(\n {\n runId,\n status: opts.status,\n duration: parseInt(opts.duration, 10),\n failedStep: opts.failedStep,\n errorMessage: opts.error,\n steps: opts.steps ? JSON.parse(opts.steps) : undefined,\n },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n}\n","import {\n CompleteRunParamsSchema,\n type CompleteRunResult,\n type ScenarioStats,\n type StepResult,\n DEFAULT_SCENARIO_STATS,\n} from '../types/index.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\nconst HARSH_JUDGE_DIR = '.harshJudge';\nconst SCENARIOS_DIR = 'scenarios';\nconst RUNS_DIR = 'runs';\nconst RESULT_FILE = 'result.json';\nconst META_FILE = 'meta.yaml';\n\n/**\n * Finds the run directory and its parent scenario by searching all scenarios.\n * Returns the run path and scenario path, or null if not found.\n */\nasync function findRunAndScenario(\n fs: FileSystemService,\n runId: string\n): Promise<{ runPath: string; scenarioPath: string } | null> {\n const scenariosPath = `${HARSH_JUDGE_DIR}/${SCENARIOS_DIR}`;\n\n if (!(await fs.exists(scenariosPath))) {\n return null;\n }\n\n const scenarios = await fs.listDirs(scenariosPath);\n\n for (const scenario of scenarios) {\n const scenarioPath = `${scenariosPath}/${scenario}`;\n const runPath = `${scenarioPath}/${RUNS_DIR}/${runId}`;\n if (await fs.exists(runPath)) {\n return { runPath, scenarioPath };\n }\n }\n\n return null;\n}\n\n/**\n * Collects evidence files from per-step directories (v2 structure).\n * Returns array of step results with their evidence files.\n */\nasync function collectStepEvidence(\n fs: FileSystemService,\n runPath: string\n): Promise<{ stepId: string; evidenceFiles: string[] }[]> {\n const results: { stepId: string; evidenceFiles: string[] }[] = [];\n\n // List all step directories\n if (!(await fs.exists(runPath))) {\n return results;\n }\n\n const dirs = await fs.listDirs(runPath);\n const stepDirs = dirs.filter((d) => /^step-\\d{2}$/.test(d)).sort();\n\n for (const stepDir of stepDirs) {\n const stepId = stepDir.replace('step-', '');\n const evidencePath = `${runPath}/${stepDir}/evidence`;\n\n if (await fs.exists(evidencePath)) {\n const files = await fs.listFiles(evidencePath);\n const evidenceFiles = files.filter((f) => !f.endsWith('.meta.json'));\n results.push({ stepId, evidenceFiles });\n } else {\n results.push({ stepId, evidenceFiles: [] });\n }\n }\n\n return results;\n}\n\n/**\n * Gets the scenario slug from the run path.\n */\nfunction extractScenarioSlug(runPath: string): string {\n // Path format: .harshJudge/scenarios/{slug}/runs/{runId}\n const parts = runPath.split('/');\n const scenariosIdx = parts.indexOf('scenarios');\n if (scenariosIdx >= 0 && parts.length > scenariosIdx + 1) {\n return parts[scenariosIdx + 1];\n }\n return 'unknown';\n}\n\n/**\n * Completes a test run and updates scenario statistics (v2).\n * Supports per-step results and backward compatibility with v1.\n */\nexport async function handleCompleteRun(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<CompleteRunResult> {\n // 1. Validate input parameters\n const validated = CompleteRunParamsSchema.parse(params);\n\n // 2. Check if project is initialized\n if (!(await fs.exists(HARSH_JUDGE_DIR))) {\n throw new Error('Project not initialized. Run initProject first.');\n }\n\n // 3. Find the run and its scenario\n const found = await findRunAndScenario(fs, validated.runId);\n if (!found) {\n throw new Error(`Run \"${validated.runId}\" does not exist.`);\n }\n\n const { runPath, scenarioPath } = found;\n\n // 4. Check if run is already completed\n const resultPath = `${runPath}/${RESULT_FILE}`;\n let existingResult: { status: string; steps?: unknown[] } | null = null;\n\n if (await fs.exists(resultPath)) {\n existingResult = await fs.readJson<{ status: string; steps?: unknown[] }>(resultPath);\n // Only reject if the run is truly completed (not \"running\" from completeStep)\n if (existingResult.status !== 'running') {\n throw new Error(`Run \"${validated.runId}\" is already completed.`);\n }\n }\n\n // 5. Build steps array (v2)\n let steps: StepResult[];\n\n if (validated.steps && validated.steps.length > 0) {\n // Use provided steps (v2 format from params)\n steps = validated.steps;\n } else if (existingResult?.steps && Array.isArray(existingResult.steps) && existingResult.steps.length > 0) {\n // Use steps from in-progress result.json (from completeStep calls)\n steps = existingResult.steps as StepResult[];\n } else {\n // Backward compatibility: collect evidence from step directories\n const stepEvidence = await collectStepEvidence(fs, runPath);\n steps = stepEvidence.map((se) => ({\n id: se.stepId,\n status: (validated.failedStep === se.stepId ? 'fail' : 'pass') as 'pass' | 'fail' | 'skipped',\n duration: 0, // Unknown for v1 compat\n error: validated.failedStep === se.stepId ? (validated.errorMessage ?? null) : null,\n evidenceFiles: se.evidenceFiles,\n }));\n }\n\n // 6. Read startedAt from existing result.json or run.json\n let startedAt: string | undefined;\n\n // First try to get from existing result.json (from completeStep)\n if (existingResult && 'startedAt' in existingResult) {\n startedAt = (existingResult as { startedAt?: string }).startedAt;\n }\n\n // Fallback to run.json\n if (!startedAt) {\n const runJsonPath = `${runPath}/run.json`;\n if (await fs.exists(runJsonPath)) {\n const runData = await fs.readJson<{ startedAt?: string }>(runJsonPath);\n startedAt = runData.startedAt;\n }\n }\n\n // 7. Write result.json (v2 format)\n const scenarioSlug = extractScenarioSlug(runPath);\n const result = {\n runId: validated.runId,\n scenarioSlug,\n status: validated.status,\n startedAt: startedAt ?? new Date().toISOString(),\n completedAt: new Date().toISOString(),\n duration: validated.duration,\n steps,\n failedStep: validated.failedStep ?? null,\n errorMessage: validated.errorMessage ?? null,\n };\n await fs.writeJson(resultPath, result);\n\n // 8. Update scenario meta.yaml (preserve all fields, update stats only)\n const metaPath = `${scenarioPath}/${META_FILE}`;\n\n // Read entire meta.yaml to preserve all fields (title, slug, starred, tags, steps, etc.)\n let existingMeta: Record<string, unknown> = {};\n if (await fs.exists(metaPath)) {\n existingMeta = await fs.readYaml<Record<string, unknown>>(metaPath);\n }\n\n // Extract current stats with defaults\n const currentStats: ScenarioStats = {\n totalRuns: (existingMeta.totalRuns as number) ?? 0,\n passCount: (existingMeta.passCount as number) ?? 0,\n failCount: (existingMeta.failCount as number) ?? 0,\n lastRun: (existingMeta.lastRun as string | null) ?? null,\n lastResult: (existingMeta.lastResult as 'pass' | 'fail' | null) ?? null,\n avgDuration: (existingMeta.avgDuration as number) ?? 0,\n };\n\n // Update statistics\n const newTotalRuns = currentStats.totalRuns + 1;\n const newPassCount = currentStats.passCount + (validated.status === 'pass' ? 1 : 0);\n const newFailCount = currentStats.failCount + (validated.status === 'fail' ? 1 : 0);\n\n // Calculate new average duration\n const totalDuration = currentStats.avgDuration * currentStats.totalRuns + validated.duration;\n const newAvgDuration = Math.round(totalDuration / newTotalRuns);\n\n // Merge updated stats back into existing meta (preserve all other fields)\n const updatedMeta = {\n ...existingMeta,\n totalRuns: newTotalRuns,\n passCount: newPassCount,\n failCount: newFailCount,\n lastRun: new Date().toISOString(),\n lastResult: validated.status,\n avgDuration: newAvgDuration,\n };\n\n await fs.writeYaml(metaPath, updatedMeta);\n\n // 9. Return result\n return {\n success: true,\n resultPath,\n updatedMeta: {\n totalRuns: newTotalRuns,\n passCount: newPassCount,\n failCount: newFailCount,\n avgDuration: newAvgDuration,\n },\n };\n}\n","import { Command } from 'commander';\nimport { handleOpenDashboard } from '../handlers/open-dashboard.js';\nimport { handleCloseDashboard } from '../handlers/close-dashboard.js';\nimport { handleGetDashboardStatus } from '../handlers/get-dashboard-status.js';\nimport { FileSystemService } from '../services/file-system-service.js';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\nexport function register(program: Command): void {\n const dashboard = program\n .command('dashboard')\n .description('Manage the HarshJudge dashboard server');\n\n dashboard\n .command('open')\n .description('Start or reconnect to the dashboard server')\n .option('--port <n>', 'Port to run the dashboard on')\n .option('--no-browser', 'Do not open browser automatically')\n .action(\n withErrorHandling(\n async (opts: { port?: string; browser?: boolean }, cmd: Command) => {\n const cwd = cmd.parent?.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleOpenDashboard(\n {\n port: opts.port ? parseInt(opts.port, 10) : undefined,\n openBrowser: opts.browser !== false,\n projectPath: cwd,\n },\n fs\n );\n console.log(JSON.stringify(result));\n }\n )\n );\n\n dashboard\n .command('close')\n .description('Stop the dashboard server')\n .action(\n withErrorHandling(async (_opts: unknown, cmd: Command) => {\n const cwd = cmd.parent?.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleCloseDashboard({ projectPath: cwd }, fs);\n console.log(JSON.stringify(result));\n })\n );\n\n dashboard\n .command('status')\n .description('Get the current dashboard status')\n .action(\n withErrorHandling(async (_opts: unknown, cmd: Command) => {\n const cwd = cmd.parent?.parent?.opts()['cwd'] ?? process.cwd();\n const fs = new FileSystemService(cwd);\n const result = await handleGetDashboardStatus({ projectPath: cwd }, fs);\n console.log(JSON.stringify(result));\n })\n );\n}\n","import { exec } from 'child_process';\nimport {\n OpenDashboardParamsSchema,\n type OpenDashboardResult,\n} from '../types/index.js';\nimport { DashboardManager } from '../services/dashboard-manager.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\n/**\n * Opens the dashboard browser URL.\n */\nfunction openBrowser(url: string): void {\n const command = process.platform === 'win32'\n ? `start \"\" \"${url}\"`\n : process.platform === 'darwin'\n ? `open \"${url}\"`\n : `xdg-open \"${url}\"`;\n\n exec(command, (err) => {\n if (err) {\n console.error(`[HarshJudge] Failed to open browser: ${err.message}`);\n }\n });\n}\n\n/**\n * Start or reconnect to the dashboard server.\n * If already running, returns the existing URL.\n * If not running, starts a new dashboard and optionally opens browser.\n */\nexport async function handleOpenDashboard(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<OpenDashboardResult> {\n const validated = OpenDashboardParamsSchema.parse(params);\n const manager = new DashboardManager(fs, validated.projectPath);\n\n // Check current status\n const status = await manager.getStatus();\n\n if (status.running && status.url && status.port && status.pid) {\n // Already running - just open browser if requested\n if (validated.openBrowser) {\n openBrowser(status.url);\n }\n\n return {\n success: true,\n url: status.url,\n port: status.port,\n pid: status.pid,\n alreadyRunning: true,\n message: `Dashboard already running at ${status.url}`,\n };\n }\n\n // Not running - start new dashboard\n try {\n const state = await manager.start(validated.port);\n\n if (validated.openBrowser) {\n openBrowser(state.url);\n }\n\n return {\n success: true,\n url: state.url,\n port: state.port,\n pid: state.pid,\n alreadyRunning: false,\n message: `Dashboard started at ${state.url}`,\n };\n } catch (error) {\n throw new Error(`Failed to start dashboard: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","import {\n CloseDashboardParamsSchema,\n type CloseDashboardResult,\n} from '../types/index.js';\nimport { DashboardManager } from '../services/dashboard-manager.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\n/**\n * Stop the dashboard server and clean up resources.\n */\nexport async function handleCloseDashboard(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<CloseDashboardResult> {\n const validated = CloseDashboardParamsSchema.parse(params);\n\n const manager = new DashboardManager(fs, validated.projectPath);\n\n // Check current status first\n const status = await manager.getStatus();\n const wasRunning = status.running || status.stale === true;\n\n // Stop the dashboard\n const result = await manager.stop();\n\n return {\n success: result.stopped || !wasRunning,\n wasRunning,\n message: result.message,\n };\n}\n","import {\n GetDashboardStatusParamsSchema,\n type GetDashboardStatusResult,\n} from '../types/index.js';\nimport { DashboardManager } from '../services/dashboard-manager.js';\nimport { FileSystemService } from '../services/file-system-service.js';\n\n/**\n * Get the current dashboard status.\n */\nexport async function handleGetDashboardStatus(\n params: unknown,\n fs: FileSystemService = new FileSystemService()\n): Promise<GetDashboardStatusResult> {\n const validated = GetDashboardStatusParamsSchema.parse(params);\n\n const manager = new DashboardManager(fs, validated.projectPath);\n const status = await manager.getStatus();\n\n let message: string;\n if (status.running) {\n message = `Dashboard running at ${status.url} (PID: ${status.pid})`;\n } else if (status.stale) {\n message = `Dashboard state is stale (process ${status.pid} is dead). Run openDashboard to start a new one.`;\n } else {\n message = 'Dashboard is not running. Use openDashboard to start it.';\n }\n\n return {\n running: status.running,\n pid: status.pid,\n port: status.port,\n url: status.url,\n startedAt: status.startedAt,\n stale: status.stale,\n message,\n };\n}\n","import { Command } from 'commander';\nimport { readdir, readFile, stat } from 'fs/promises';\nimport { join, relative } from 'path';\nimport yaml from 'js-yaml';\nimport { withErrorHandling } from '../utils/cli-helpers.js';\n\n// Metadata fields to extract per known file type\nconst META_YAML_FIELDS = [\n 'title',\n 'slug',\n 'starred',\n 'tags',\n 'totalRuns',\n 'passCount',\n 'failCount',\n 'lastRun',\n 'lastResult',\n 'avgDuration',\n];\nconst CONFIG_YAML_FIELDS = ['projectName', 'baseUrl', 'version', 'createdAt'];\nconst RESULT_JSON_FIELDS = ['status', 'duration', 'runId'];\n\nfunction pickFields(\n obj: Record<string, unknown>,\n fields: string[]\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of fields) {\n if (key in obj) result[key] = obj[key];\n }\n return result;\n}\n\nasync function walkDir(\n dirPath: string,\n basePath: string,\n _fileName: string\n): Promise<Record<string, unknown>> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const node: Record<string, unknown> = {};\n\n for (const entry of entries) {\n const fullPath = join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n node[`${entry.name}/`] = await walkDir(fullPath, basePath, entry.name);\n } else {\n // Parse known structured files; others just appear by name (set to true as a marker)\n if (entry.name === 'meta.yaml') {\n try {\n const raw = yaml.load(await readFile(fullPath, 'utf8')) as Record<\n string,\n unknown\n >;\n node[entry.name] = pickFields(raw, META_YAML_FIELDS);\n } catch {\n node[entry.name] = {};\n }\n } else if (entry.name === 'config.yaml') {\n try {\n const raw = yaml.load(await readFile(fullPath, 'utf8')) as Record<\n string,\n unknown\n >;\n node[entry.name] = pickFields(raw, CONFIG_YAML_FIELDS);\n } catch {\n node[entry.name] = {};\n }\n } else if (entry.name === 'result.json') {\n try {\n const raw = JSON.parse(await readFile(fullPath, 'utf8')) as Record<\n string,\n unknown\n >;\n node[entry.name] = pickFields(raw, RESULT_JSON_FIELDS);\n } catch {\n node[entry.name] = {};\n }\n } else {\n // For step files, evidence files, prd.md, etc — just list by name\n node[entry.name] = true;\n }\n }\n }\n\n return node;\n}\n\n/**\n * Build a tree of .harshJudge/ with metadata extracted from YAML/JSON.\n * @param basePath Project root (parent of .harshJudge/)\n * @param subPath Optional relative path within .harshJudge/ to scope the tree\n */\nexport async function buildTree(\n basePath: string,\n subPath?: string\n): Promise<{ root: string; tree: Record<string, unknown> }> {\n const rootPath = subPath\n ? join(basePath, '.harshJudge', subPath)\n : join(basePath, '.harshJudge');\n\n const dirStat = await stat(rootPath);\n if (!dirStat.isDirectory()) {\n throw new Error(`Path is not a directory: ${rootPath}`);\n }\n\n const tree = await walkDir(rootPath, basePath, '');\n const rootLabel = relative(basePath, rootPath) + '/';\n\n return { root: rootLabel, tree };\n}\n\nconst SEARCHABLE_EXTENSIONS = new Set(['.yaml', '.yml', '.json', '.md']);\n\nasync function* walkForSearch(dirPath: string): AsyncGenerator<string> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = join(dirPath, entry.name);\n if (entry.isDirectory()) {\n yield* walkForSearch(fullPath);\n } else {\n const ext = entry.name.slice(entry.name.lastIndexOf('.'));\n if (SEARCHABLE_EXTENSIONS.has(ext)) {\n yield fullPath;\n }\n }\n }\n}\n\n/**\n * Search for pattern in file content within .harshJudge/ (or a subpath).\n * @param basePath Project root (parent of .harshJudge/)\n * @param pattern Case-insensitive string to search for\n * @param subPath Optional relative path within .harshJudge/ to restrict search\n */\nexport async function searchFiles(\n basePath: string,\n pattern: string,\n subPath?: string\n): Promise<{ matches: Array<{ file: string; match: string }> }> {\n const searchRoot = subPath\n ? join(basePath, '.harshJudge', subPath)\n : join(basePath, '.harshJudge');\n\n const lowerPattern = pattern.toLowerCase();\n const matches: Array<{ file: string; match: string }> = [];\n\n for await (const filePath of walkForSearch(searchRoot)) {\n let content: string;\n try {\n content = await readFile(filePath, 'utf8');\n } catch {\n continue;\n }\n\n const lines = content.split('\\n');\n for (const line of lines) {\n if (line.toLowerCase().includes(lowerPattern)) {\n matches.push({ file: filePath, match: line.trim() });\n }\n }\n }\n\n return { matches };\n}\n\nexport function register(program: Command): void {\n const discover = program\n .command('discover')\n .description('Explore .harshJudge/ structure');\n\n discover\n .command('tree [path]')\n .description('Show folder structure with metadata')\n .action(\n withErrorHandling(async (subPath: string | undefined, cmd: Command) => {\n const cwd = cmd.parent?.parent?.opts()['cwd'] ?? process.cwd();\n const result = await buildTree(cwd, subPath);\n console.log(JSON.stringify(result, null, 2));\n })\n );\n\n discover\n .command('search <pattern>')\n .description('Search file content in .harshJudge/')\n .option('--path <folder>', 'Restrict search to subfolder')\n .action(\n withErrorHandling(\n async (pattern: string, opts: { path?: string }, cmd: Command) => {\n const cwd = cmd.parent?.parent?.opts()['cwd'] ?? process.cwd();\n const result = await searchFiles(cwd, pattern, opts.path);\n console.log(JSON.stringify(result, null, 2));\n }\n )\n );\n}\n"],"mappings":"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","names":["Command","readFileSync","fileURLToPath","dirname","join","z","z","z","join","dirname","HARSH_JUDGE_DIR","resolve","join","dirname","state","__dirname","HARSH_JUDGE_DIR","SCENARIOS_DIR","program","HARSH_JUDGE_DIR","SCENARIOS_DIR","STEPS_DIR","register","program","HARSH_JUDGE_DIR","SCENARIOS_DIR","META_FILE","register","program","HARSH_JUDGE_DIR","SCENARIOS_DIR","CONFIG_FILE","META_FILE","register","program","HARSH_JUDGE_DIR","SCENARIOS_DIR","RUNS_DIR","META_FILE","register","program","HARSH_JUDGE_DIR","SCENARIOS_DIR","RUNS_DIR","RESULT_FILE","register","program","HARSH_JUDGE_DIR","SCENARIOS_DIR","RUNS_DIR","RESULT_FILE","META_FILE","register","program","HARSH_JUDGE_DIR","SCENARIOS_DIR","RUNS_DIR","RESULT_FILE","META_FILE","findRunAndScenario","register","program","register","program","readdir","readFile","join","yaml","readdir","join","yaml","readFile","register","program","dirname","fileURLToPath","readFileSync","join","Command","register"]}