@specmarket/cli 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/lib/auth.ts","../src/lib/convex-client.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/commands/init.ts","../src/commands/validate.ts","../src/lib/format-detection.ts","../src/commands/run.ts","../src/lib/telemetry.ts","../src/lib/ralph-loop.ts","../src/commands/search.ts","../src/commands/info.ts","../src/commands/publish.ts","../src/commands/fork.ts","../src/commands/report.ts","../src/commands/config.ts","../src/commands/issues.ts","../src/commands/comment.ts"],"sourcesContent":["/**\n * SpecMarket CLI — Entry Point\n *\n * Registers all commands and sets up the Commander.js program.\n * Commands are registered from separate files for testability.\n */\nimport { program } from 'commander';\nimport { EXIT_CODES } from '@specmarket/shared';\nimport { createLoginCommand } from './commands/login.js';\nimport { createLogoutCommand } from './commands/logout.js';\nimport { createWhoamiCommand } from './commands/whoami.js';\nimport { createInitCommand } from './commands/init.js';\nimport { createValidateCommand } from './commands/validate.js';\nimport { createRunCommand } from './commands/run.js';\nimport { createSearchCommand } from './commands/search.js';\nimport { createInfoCommand } from './commands/info.js';\nimport { createPublishCommand } from './commands/publish.js';\nimport { createForkCommand } from './commands/fork.js';\nimport { createReportCommand } from './commands/report.js';\nimport { createConfigCommand } from './commands/config.js';\nimport { createIssuesCommand } from './commands/issues.js';\nimport { createCommentCommand } from './commands/comment.js';\nimport { createRequire } from 'module';\n\n// Dynamically read version from package.json so it stays in sync with npm publishes\nconst _require = createRequire(import.meta.url);\nconst { version: VERSION } = _require('../package.json');\n\nprogram\n .name('specmarket')\n .description(\n 'SpecMarket CLI — discover, validate, run, and publish AI specs\\n\\n' +\n 'Modes:\\n' +\n ' Authenticated: run `specmarket login` for telemetry and registry access\\n' +\n ' Anonymous: validate and run specs locally with no network calls'\n )\n .version(VERSION, '-v, --version', 'Print version number')\n .addHelpText(\n 'after',\n '\\nExamples:\\n' +\n ' $ specmarket init Create a new spec\\n' +\n ' $ specmarket validate ./my-spec Validate a spec\\n' +\n ' $ specmarket run ./my-spec Execute a spec locally\\n' +\n ' $ specmarket run @user/my-spec Run a registry spec\\n' +\n ' $ specmarket search \"notion clone\" Search the registry\\n' +\n ' $ specmarket info @user/my-spec View spec details\\n' +\n ' $ specmarket publish ./my-spec Publish to registry\\n' +\n ' $ specmarket login Authenticate\\n'\n );\n\n// Auth commands\nprogram.addCommand(createLoginCommand());\nprogram.addCommand(createLogoutCommand());\nprogram.addCommand(createWhoamiCommand());\n\n// Spec lifecycle\nprogram.addCommand(createInitCommand());\nprogram.addCommand(createValidateCommand());\nprogram.addCommand(createRunCommand());\n\n// Registry\nprogram.addCommand(createSearchCommand());\nprogram.addCommand(createInfoCommand());\nprogram.addCommand(createPublishCommand());\nprogram.addCommand(createForkCommand());\n\n// Collaboration\nprogram.addCommand(createIssuesCommand());\nprogram.addCommand(createCommentCommand());\n\n// Reporting & config\nprogram.addCommand(createReportCommand());\nprogram.addCommand(createConfigCommand());\n\n// Parse and execute\nprogram.parseAsync(process.argv).catch((err: Error) => {\n console.error(`Fatal error: ${err.message}`);\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n } else if (errCode === String(EXIT_CODES.NETWORK_ERROR)) {\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n});\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { EXIT_CODES } from '@specmarket/shared';\nimport { saveCredentials, loadCredentials } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { TOKEN_EXPIRY_MS } from '@specmarket/shared';\nimport type { Credentials } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:auth');\n\n/** Maximum time to wait for device code approval before timing out */\nconst DEVICE_CODE_TIMEOUT_MS = 10 * 60 * 1000;\n\n/**\n * Handles the login flow.\n *\n * Two modes:\n * 1. --token <jwt>: Direct token injection (CI/headless use case)\n * 2. Interactive: Device code auth flow — generates a code, opens browser,\n * polls backend until the user approves the device on the web app.\n *\n * The device code flow works in headless/SSH environments because the user\n * can visit the URL on any device (phone, another computer) to authenticate.\n *\n * Tokens are stored in ~/.specmarket/credentials.json with 0600 permissions.\n */\nexport async function handleLogin(opts: { token?: string }): Promise<void> {\n // Already logged in?\n const existing = await loadCredentials();\n if (existing) {\n console.log(\n chalk.yellow(\n `Already logged in as ${chalk.bold(existing.username ?? 'unknown')}. ` +\n `Run ${chalk.cyan('specmarket logout')} first to switch accounts.`\n )\n );\n return;\n }\n\n if (opts.token) {\n await handleTokenLogin(opts.token);\n return;\n }\n\n await handleDeviceCodeLogin();\n}\n\nasync function handleTokenLogin(token: string): Promise<void> {\n const spinner = ora('Validating token...').start();\n\n try {\n const client = await getConvexClient(token);\n // Validate token by calling getMe\n const { api } = await import('@specmarket/convex/api').catch(() => ({\n api: null,\n }));\n\n let username: string | undefined;\n let userId: string | undefined;\n\n if (api) {\n try {\n const me = await client.query(api.users.getMe, {});\n username = me?.username;\n userId = me?._id;\n } catch {\n // API might not be reachable in dev\n debug('Could not validate token via getMe query');\n }\n }\n\n const creds: Credentials = {\n token,\n expiresAt: Date.now() + TOKEN_EXPIRY_MS,\n username,\n userId,\n };\n\n await saveCredentials(creds);\n\n spinner.succeed(\n chalk.green(\n `Logged in${username ? ` as ${chalk.bold(username)}` : ''}. Token stored in ~/.specmarket/credentials.json`\n )\n );\n } catch (err) {\n spinner.fail(chalk.red('Failed to validate token.'));\n throw err;\n }\n}\n\n/**\n * Implements the device-code auth flow:\n * 1. Call auth.createDeviceCode mutation to generate a code\n * 2. Display the code and URL to the user\n * 3. Attempt to open the browser\n * 4. Poll auth.checkDeviceCode every 2 seconds\n * 5. On approval: store the returned token\n * 6. On expiry/timeout: show error\n */\nasync function handleDeviceCodeLogin(): Promise<void> {\n const config = await import('../lib/config.js').then((m) => m.loadConfig());\n const baseUrl = config.convexUrl ?? process.env['CONVEX_URL'] ?? 'https://your-deployment.convex.cloud';\n const webUrl = baseUrl.replace('convex.cloud', 'specmarket.dev');\n\n const client = await getConvexClient();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n // Fallback: if API bindings unavailable, show manual instructions\n console.log(chalk.cyan('\\nSpecMarket Login'));\n console.log(chalk.gray('─────────────────────────────────────'));\n console.log('');\n console.log('To authenticate, visit the SpecMarket web app and copy your API token:');\n console.log('');\n console.log(chalk.bold(` ${webUrl}/settings/tokens`));\n console.log('');\n console.log('Then run:');\n console.log(chalk.cyan(' specmarket login --token <your-token>'));\n console.log('');\n console.log(chalk.gray('Alternatively, set SPECMARKET_TOKEN in your environment.'));\n return;\n }\n\n // Step 1: Generate device code\n const spinner = ora('Generating device code...').start();\n let deviceCode: { code: string; expiresAt: number; pollIntervalMs: number };\n\n try {\n deviceCode = await client.mutation(api.auth.createDeviceCode, {});\n } catch (err) {\n spinner.fail(chalk.red('Failed to generate device code. Is the backend reachable?'));\n debug('createDeviceCode failed: %O', err);\n // Fallback to manual instructions\n console.log('');\n console.log('You can authenticate manually:');\n console.log(chalk.cyan(' specmarket login --token <your-token>'));\n return;\n }\n\n spinner.stop();\n\n // Step 2: Display the code and URL\n const deviceUrl = `${webUrl}/device`;\n console.log('');\n console.log(chalk.cyan('SpecMarket Login'));\n console.log(chalk.gray('─────────────────────────────────────'));\n console.log('');\n console.log(` Visit: ${chalk.bold(deviceUrl)}`);\n console.log(` Code: ${chalk.bold.cyan(deviceCode.code)}`);\n console.log('');\n console.log(chalk.gray(' Log in on the web and enter the code above to authorize this device.'));\n console.log(chalk.gray(` Code expires in 10 minutes.`));\n console.log('');\n\n // Step 3: Try to open browser\n try {\n const open = (await import('open')).default;\n await open(deviceUrl);\n debug('Opened browser to %s', deviceUrl);\n } catch {\n debug('Could not open browser (headless environment)');\n }\n\n // Step 4: Poll for approval\n const pollSpinner = ora('Waiting for authorization...').start();\n const startTime = Date.now();\n const pollInterval = deviceCode.pollIntervalMs || 2000;\n\n while (Date.now() - startTime < DEVICE_CODE_TIMEOUT_MS) {\n await sleep(pollInterval);\n\n try {\n const result = await client.query(api.auth.checkDeviceCode, {\n code: deviceCode.code,\n });\n\n if (result.status === 'approved') {\n // Success!\n const creds: Credentials = {\n token: result.token,\n expiresAt: Date.now() + TOKEN_EXPIRY_MS,\n username: result.username,\n userId: result.userId,\n };\n\n await saveCredentials(creds);\n\n pollSpinner.succeed(\n chalk.green(\n `Logged in as ${chalk.bold(result.username ?? 'unknown')}. Token stored in ~/.specmarket/credentials.json`\n )\n );\n return;\n }\n\n if (result.status === 'expired') {\n pollSpinner.fail(chalk.red('Device code expired. Please try again.'));\n return;\n }\n\n // Still pending — continue polling\n } catch (err) {\n debug('Poll error (non-fatal): %O', err);\n // Network hiccup — keep polling\n }\n }\n\n pollSpinner.fail(chalk.red('Login timed out. Please try again.'));\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function createLoginCommand(): Command {\n return new Command('login')\n .description('Authenticate with SpecMarket')\n .option('--token <token>', 'Use a pre-existing token (for CI/headless environments)')\n .action(async (opts) => {\n try {\n await handleLogin(opts);\n } catch (err) {\n console.error(chalk.red(`Login failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n });\n}\n","import { readFile, writeFile, unlink, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type { Credentials } from '@specmarket/shared';\nimport { CONFIG_PATHS, TOKEN_EXPIRY_MS, EXIT_CODES } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:auth');\n\nfunction getCredentialsPath(): string {\n return join(homedir(), CONFIG_PATHS.CREDENTIALS);\n}\n\nfunction getConfigDir(): string {\n return join(homedir(), CONFIG_PATHS.DIR);\n}\n\n/**\n * Loads stored credentials from ~/.specmarket/credentials.json.\n * Returns null if the file doesn't exist, is malformed, or the token is expired.\n */\nexport async function loadCredentials(): Promise<Credentials | null> {\n try {\n const raw = await readFile(getCredentialsPath(), 'utf-8');\n const creds = JSON.parse(raw) as Credentials;\n\n if (!creds.token) {\n debug('Credentials file exists but has no token');\n return null;\n }\n\n // Check expiry\n if (creds.expiresAt && Date.now() > creds.expiresAt) {\n debug('Credentials expired at %d', creds.expiresAt);\n await clearCredentials();\n return null;\n }\n\n debug('Credentials loaded for user %s', creds.username ?? 'unknown');\n return creds;\n } catch {\n debug('No credentials file found');\n return null;\n }\n}\n\n/**\n * Saves credentials to ~/.specmarket/credentials.json.\n * Creates the directory if it doesn't exist.\n */\nexport async function saveCredentials(creds: Credentials): Promise<void> {\n await mkdir(getConfigDir(), { recursive: true });\n await writeFile(\n getCredentialsPath(),\n JSON.stringify(creds, null, 2),\n { encoding: 'utf-8', mode: 0o600 } // 600 = owner read/write only\n );\n debug('Credentials saved for user %s', creds.username ?? 'unknown');\n}\n\n/**\n * Deletes the credentials file (logout).\n */\nexport async function clearCredentials(): Promise<void> {\n try {\n await unlink(getCredentialsPath());\n debug('Credentials cleared');\n } catch {\n debug('No credentials file to clear');\n }\n}\n\n/**\n * Returns credentials if authenticated, or throws with exit code 5.\n * Use this in commands that require authentication.\n */\nexport async function requireAuth(): Promise<Credentials> {\n const creds = await loadCredentials();\n if (!creds) {\n const err = new Error(\n 'Not authenticated. Run `specmarket login` to authenticate.'\n );\n (err as NodeJS.ErrnoException).code = String(EXIT_CODES.AUTH_ERROR);\n throw err;\n }\n return creds;\n}\n\n/**\n * Returns true if the user is currently authenticated with a valid token.\n */\nexport async function isAuthenticated(): Promise<boolean> {\n const creds = await loadCredentials();\n return creds !== null;\n}\n","import { ConvexHttpClient } from 'convex/browser';\nimport { loadConfig } from './config.js';\nimport { DEFAULT_CONVEX_URL } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:convex');\n\n/**\n * Returns a ConvexHttpClient configured with the deployment URL and optional auth token.\n * The URL is resolved from (in priority order):\n * 1. CONVEX_URL environment variable\n * 2. config.json convexUrl field\n * 3. DEFAULT_CONVEX_URL constant\n *\n * If a token is provided, it's set as the auth token for authenticated mutations.\n */\nexport async function getConvexClient(token?: string): Promise<ConvexHttpClient> {\n const config = await loadConfig();\n const url =\n process.env['CONVEX_URL'] ??\n config.convexUrl ??\n DEFAULT_CONVEX_URL;\n\n if (url.includes('placeholder.convex.cloud')) {\n throw new Error(\n 'CONVEX_URL is not configured. Set the CONVEX_URL environment variable or run `specmarket config set convexUrl <url>`.'\n );\n }\n\n debug('Creating Convex client for URL: %s', url);\n const client = new ConvexHttpClient(url);\n\n if (token) {\n client.setAuth(token);\n debug('Convex client authenticated');\n }\n\n return client;\n}\n\n/**\n * Returns an authenticated ConvexHttpClient using stored credentials.\n * Returns unauthenticated client if no credentials exist.\n */\nexport async function getAuthenticatedClient(token?: string): Promise<ConvexHttpClient> {\n return getConvexClient(token);\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { clearCredentials, loadCredentials } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Clears stored credentials from ~/.specmarket/credentials.json.\n */\nexport async function handleLogout(): Promise<void> {\n const creds = await loadCredentials();\n if (!creds) {\n console.log(chalk.yellow('You are not currently logged in.'));\n return;\n }\n\n await clearCredentials();\n console.log(\n chalk.green(\n `Logged out${creds.username ? ` (was: ${chalk.bold(creds.username)})` : ''}. Credentials cleared.`\n )\n );\n}\n\nexport function createLogoutCommand(): Command {\n return new Command('logout')\n .description('Log out from SpecMarket and clear stored credentials')\n .action(async () => {\n try {\n await handleLogout();\n } catch (err) {\n console.error(chalk.red(`Logout failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadCredentials } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Displays the currently authenticated user, or \"not logged in\".\n */\nexport async function handleWhoami(): Promise<void> {\n const creds = await loadCredentials();\n if (!creds) {\n console.log(chalk.gray('Not logged in. Run `specmarket login` to authenticate.'));\n return;\n }\n\n // Try to fetch fresh profile from Convex\n try {\n const { api } = await import('@specmarket/convex/api');\n const client = await getConvexClient(creds.token);\n const me = await client.query(api.users.getMe, {});\n\n if (me) {\n console.log(chalk.green('Authenticated as:'));\n console.log(` ${chalk.bold('Username:')} @${me.username}`);\n console.log(` ${chalk.bold('Display Name:')} ${me.displayName}`);\n console.log(` ${chalk.bold('Role:')} ${me.role}`);\n console.log(` ${chalk.bold('Specs Published:')} ${me.totalSpecsPublished}`);\n console.log(` ${chalk.bold('Reputation Score:')} ${me.reputationScore}`);\n if (creds.expiresAt) {\n const expiresIn = Math.floor((creds.expiresAt - Date.now()) / 1000 / 60 / 60 / 24);\n console.log(` ${chalk.bold('Token Expires In:')} ${expiresIn} days`);\n }\n return;\n }\n } catch {\n // Convex unavailable — fall back to cached info\n }\n\n // Fall back to cached credential info\n console.log(chalk.green('Authenticated (cached):'));\n console.log(` ${chalk.bold('Username:')} @${creds.username ?? 'unknown'}`);\n if (creds.expiresAt) {\n const expiresDate = new Date(creds.expiresAt).toLocaleDateString();\n console.log(` ${chalk.bold('Token Expires:')} ${expiresDate}`);\n }\n}\n\nexport function createWhoamiCommand(): Command {\n return new Command('whoami')\n .description('Show the currently authenticated user')\n .action(async () => {\n try {\n await handleWhoami();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { mkdir, writeFile } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { EXIT_CODES } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:cli');\n\nconst SPEC_YAML_TEMPLATE = (data: {\n name: string;\n displayName: string;\n replacesSaas?: string;\n outputType: string;\n primaryStack: string;\n}) => `# SpecMarket Spec Configuration\n# See: https://specmarket.dev/docs/spec-yaml\n\nname: ${data.name}\ndisplay_name: \"${data.displayName}\"\ndescription: \"A ${data.outputType} spec${data.replacesSaas ? ` that replaces ${data.replacesSaas}` : ''}.\"\n${data.replacesSaas ? `replaces_saas: \"${data.replacesSaas}\"` : '# replaces_saas: \"SaaSProductName\"'}\n# replaces_pricing: \"$0-16/mo\"\n\noutput_type: ${data.outputType}\nprimary_stack: ${data.primaryStack}\nversion: \"1.0.0\"\nrunner: claude\nmin_model: \"claude-opus-4-5\"\n\nestimated_tokens: 50000\nestimated_cost_usd: 2.50\nestimated_time_minutes: 30\n\ntags: []\n\ninfrastructure:\n monthly_cost:\n free_tier_usd: 0\n production_usd: 0\n services: []\n # Example service:\n # - category: database\n # name: PostgreSQL\n # purpose: Primary data store\n # required: true\n # providers:\n # - name: Neon\n # free_tier: true\n # paid_starts_usd: 19\n # default_provider: Neon\n # setup_notes: Run migrations with \\`npm run db:push\\`\n user_provided: []\n setup_time_minutes: 15\n deployment_targets:\n - name: Vercel\n notes: Recommended for Next.js and Astro apps\n - name: Railway\n notes: General-purpose cloud hosting\n`;\n\nconst PROMPT_MD_TEMPLATE = (data: { displayName: string }) => `# ${data.displayName}\n\nYou are building ${data.displayName}. Read SPEC.md for full requirements.\n\n## Your Task\n\nRead the requirements in SPEC.md and implement the application step by step.\n\n## Process\n\n1. Read SPEC.md completely before writing any code\n2. Check TASKS.md for outstanding items\n3. Implement features, run tests, iterate\n4. Update TASKS.md as you complete items\n5. Verify SUCCESS_CRITERIA.md criteria are met\n\n## Rules\n\n- Follow stdlib/STACK.md for technology choices\n- Write tests for all business logic\n- Do not skip steps or take shortcuts\n- Update TASKS.md after each significant change\n`;\n\nconst SPEC_MD_TEMPLATE = (data: { displayName: string }) => `# ${data.displayName} — Specification\n\n## Overview\n\nDescribe what this application does and why it's useful.\n\n## Core Features\n\n- Feature 1: Description\n- Feature 2: Description\n- Feature 3: Description\n\n## Data Model\n\nDescribe the key entities and their relationships.\n\n## API / Interface\n\nDescribe the public interface (routes, commands, exports).\n\n## Non-Goals\n\nWhat this spec explicitly does NOT build.\n`;\n\nconst SUCCESS_CRITERIA_TEMPLATE = `# Success Criteria\n\nThe implementation is complete when ALL of the following are true:\n\n- [ ] Application builds without errors\n- [ ] All tests pass\n- [ ] Core feature 1 works end-to-end\n- [ ] Core feature 2 works end-to-end\n- [ ] README.md documents setup and usage\n`;\n\nconst STACK_MD_TEMPLATE = (primaryStack: string) => `# Stack Requirements\n\n## Primary Stack\n\n${primaryStack}\n\n## Required Tools\n\n- Node.js >= 20\n- pnpm (preferred) or npm\n\n## Code Style\n\n- TypeScript strict mode, no \\`any\\`\n- ESM modules\n- Functional components (React)\n- Async/await over callbacks\n\n## Testing\n\n- Vitest for unit tests\n- Playwright for E2E (optional)\n`;\n\nconst TASKS_MD_TEMPLATE = (displayName: string) => `# Tasks\n\n> This file tracks outstanding work. Update it after each change.\n> All items checked = implementation complete.\n\n## Phase 1: ${displayName} — Initial Implementation\n\n- [ ] Set up project structure and dependencies\n- [ ] Implement core data model\n- [ ] Implement core business logic\n- [ ] Write unit tests\n- [ ] Implement UI/interface\n- [ ] Write integration tests\n- [ ] Update README.md\n\n## Discovered Issues\n`;\n\nexport async function handleInit(opts: {\n name?: string;\n path?: string;\n}): Promise<void> {\n const { default: inquirer } = await import('inquirer');\n\n const answers = await inquirer.prompt<{\n name: string;\n displayName: string;\n replacesSaas: string;\n outputType: string;\n primaryStack: string;\n }>([\n {\n type: 'input',\n name: 'name',\n message: 'Spec name (lowercase, hyphens only):',\n default: opts.name ?? 'my-spec',\n validate: (v: string) =>\n /^[a-z0-9-]+$/.test(v) || 'Must be lowercase alphanumeric with hyphens',\n },\n {\n type: 'input',\n name: 'displayName',\n message: 'Display name:',\n default: (answers: { name: string }) =>\n answers.name\n .split('-')\n .map((w) => w[0]?.toUpperCase() + w.slice(1))\n .join(' '),\n },\n {\n type: 'input',\n name: 'replacesSaas',\n message: 'What SaaS product does this replace? (optional, press Enter to skip):',\n default: '',\n },\n {\n type: 'list',\n name: 'outputType',\n message: 'Output type:',\n choices: [\n { name: 'Web Application', value: 'web-app' },\n { name: 'CLI Tool', value: 'cli-tool' },\n { name: 'API Service', value: 'api-service' },\n { name: 'Library/Package', value: 'library' },\n { name: 'Mobile App', value: 'mobile-app' },\n ],\n },\n {\n type: 'list',\n name: 'primaryStack',\n message: 'Primary stack:',\n choices: [\n { name: 'Next.js + TypeScript', value: 'nextjs-typescript' },\n { name: 'Astro + TypeScript', value: 'astro-typescript' },\n { name: 'Python + FastAPI', value: 'python-fastapi' },\n { name: 'Go', value: 'go' },\n { name: 'Rust', value: 'rust' },\n { name: 'Other', value: 'other' },\n ],\n },\n ]);\n\n const targetDir = resolve(opts.path ?? answers.name);\n const spinner = ora(`Creating spec directory at ${targetDir}...`).start();\n\n try {\n // Create directory structure\n await mkdir(targetDir, { recursive: true });\n await mkdir(join(targetDir, 'stdlib'), { recursive: true });\n\n const data = {\n name: answers.name,\n displayName: answers.displayName,\n replacesSaas: answers.replacesSaas || undefined,\n outputType: answers.outputType,\n primaryStack: answers.primaryStack,\n };\n\n // Write all template files\n await Promise.all([\n writeFile(join(targetDir, 'spec.yaml'), SPEC_YAML_TEMPLATE(data)),\n writeFile(join(targetDir, 'PROMPT.md'), PROMPT_MD_TEMPLATE(data)),\n writeFile(join(targetDir, 'SPEC.md'), SPEC_MD_TEMPLATE(data)),\n writeFile(join(targetDir, 'SUCCESS_CRITERIA.md'), SUCCESS_CRITERIA_TEMPLATE),\n writeFile(join(targetDir, 'stdlib', 'STACK.md'), STACK_MD_TEMPLATE(answers.primaryStack)),\n writeFile(join(targetDir, 'TASKS.md'), TASKS_MD_TEMPLATE(answers.displayName)),\n ]);\n\n spinner.succeed(chalk.green(`Spec created at ${targetDir}`));\n\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. ${chalk.cyan(`cd ${answers.name}`)}`);\n console.log(` 2. Edit ${chalk.cyan('SPEC.md')} with your application requirements`);\n console.log(` 3. Edit ${chalk.cyan('SUCCESS_CRITERIA.md')} with specific pass/fail criteria`);\n console.log(` 4. Run ${chalk.cyan(`specmarket validate`)} to check your spec`);\n console.log(` 5. Run ${chalk.cyan(`specmarket run`)} to execute the spec`);\n } catch (err) {\n spinner.fail(chalk.red(`Failed to create spec: ${(err as Error).message}`));\n throw err;\n }\n}\n\nexport function createInitCommand(): Command {\n return new Command('init')\n .description('Create a new spec directory with template files')\n .option('-n, --name <name>', 'Spec name (skip prompt)')\n .option('-p, --path <path>', 'Target directory path (defaults to spec name)')\n .action(async (opts) => {\n try {\n await handleInit(opts);\n } catch (err) {\n console.error(chalk.red(`Init failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { readFile, readdir, access } from 'fs/promises';\nimport { join, resolve, relative, normalize } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport {\n specYamlSchema,\n specmarketSidecarSchema,\n EXIT_CODES,\n REQUIRED_SPEC_FILES,\n REQUIRED_STDLIB_FILES,\n SIDECAR_FILENAME,\n} from '@specmarket/shared';\nimport type { ValidationResult } from '@specmarket/shared';\nimport {\n detectSpecFormat,\n fileExists,\n directoryExists,\n hasStoryFiles,\n hasMarkdownFiles,\n} from '../lib/format-detection.js';\n\n/**\n * Recursively collects file paths relative to baseDir, filtered by extension.\n */\nasync function collectFiles(\n currentDir: string,\n baseDir: string,\n extensions: Set<string>\n): Promise<string[]> {\n const results: string[] = [];\n try {\n const entries = await readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = join(currentDir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n const subFiles = await collectFiles(fullPath, baseDir, extensions);\n results.push(...subFiles);\n } else if (entry.isFile()) {\n const ext = entry.name.includes('.') ? '.' + entry.name.split('.').pop()! : '';\n if (extensions.has(ext)) {\n results.push(relative(baseDir, fullPath));\n }\n }\n }\n } catch {\n // Directory unreadable\n }\n return results;\n}\n\n/**\n * Scans all Markdown/YAML files in the spec directory for relative file\n * references (Markdown links) and detects cycles in the reference graph.\n */\nexport async function detectCircularReferences(dir: string): Promise<string[]> {\n const textExtensions = new Set(['.md', '.yaml', '.yml']);\n const files = await collectFiles(dir, dir, textExtensions);\n const graph = new Map<string, Set<string>>();\n const linkPattern = /\\[(?:[^\\]]*)\\]\\(([^)]+)\\)/g;\n\n for (const file of files) {\n const refs = new Set<string>();\n try {\n const content = await readFile(join(dir, file), 'utf-8');\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(content)) !== null) {\n const target = match[1]!;\n if (\n target.startsWith('http://') ||\n target.startsWith('https://') ||\n target.startsWith('#') ||\n target.startsWith('mailto:')\n ) {\n continue;\n }\n const targetPath = target.split('#')[0]!;\n if (!targetPath) continue;\n const fileDir = join(dir, file, '..');\n const resolvedTarget = normalize(relative(dir, resolve(fileDir, targetPath)));\n if (!resolvedTarget.startsWith('..') && files.includes(resolvedTarget)) {\n refs.add(resolvedTarget);\n }\n }\n } catch {\n // skip\n }\n graph.set(file, refs);\n }\n\n const WHITE = 0,\n GRAY = 1,\n BLACK = 2;\n const color = new Map<string, number>();\n const parent = new Map<string, string | null>();\n const cycles: string[] = [];\n\n for (const f of files) {\n color.set(f, WHITE);\n }\n\n function dfs(node: string): void {\n color.set(node, GRAY);\n const neighbors = graph.get(node) ?? new Set();\n for (const neighbor of neighbors) {\n if (color.get(neighbor) === GRAY) {\n const cyclePath: string[] = [neighbor, node];\n let curr = node;\n while (curr !== neighbor) {\n const p = parent.get(curr);\n if (!p || p === neighbor) break;\n cyclePath.push(p);\n curr = p;\n }\n cyclePath.reverse();\n cycles.push(cyclePath.join(' -> '));\n } else if (color.get(neighbor) === WHITE) {\n parent.set(neighbor, node);\n dfs(neighbor);\n }\n }\n color.set(node, BLACK);\n }\n\n for (const f of files) {\n if (color.get(f) === WHITE) {\n parent.set(f, null);\n dfs(f);\n }\n }\n\n return cycles;\n}\n\n/**\n * Format-specific validation for specmarket-legacy. Pushes to errors/warnings.\n * Zero behavior change from original validateSpec for legacy dirs.\n */\nasync function validateLegacySpec(\n dir: string,\n errors: string[],\n warnings: string[]\n): Promise<void> {\n for (const file of REQUIRED_SPEC_FILES) {\n const filePath = join(dir, file);\n try {\n await access(filePath);\n const content = await readFile(filePath, 'utf-8');\n if (content.trim().length === 0) {\n errors.push(`${file} exists but is empty`);\n }\n } catch {\n errors.push(`Required file missing: ${file}`);\n }\n }\n\n const stdlibDir = join(dir, 'stdlib');\n for (const file of REQUIRED_STDLIB_FILES) {\n const filePath = join(stdlibDir, file);\n try {\n await access(filePath);\n const content = await readFile(filePath, 'utf-8');\n if (content.trim().length === 0) {\n errors.push(`stdlib/${file} exists but is empty`);\n }\n } catch {\n errors.push(`Required file missing: stdlib/${file}`);\n }\n }\n\n let specYaml: unknown = null;\n const specYamlPath = join(dir, 'spec.yaml');\n try {\n const raw = await readFile(specYamlPath, 'utf-8');\n specYaml = parseYaml(raw);\n } catch (err) {\n errors.push(`spec.yaml: Failed to parse YAML: ${(err as Error).message}`);\n return;\n }\n\n const parseResult = specYamlSchema.safeParse(specYaml);\n if (!parseResult.success) {\n for (const issue of parseResult.error.issues) {\n errors.push(`spec.yaml: ${issue.path.join('.')} — ${issue.message}`);\n }\n return;\n }\n\n const parsed = parseResult.data;\n\n try {\n const criteriaContent = await readFile(join(dir, 'SUCCESS_CRITERIA.md'), 'utf-8');\n const hasCriterion = /^- \\[[ x]\\]/m.test(criteriaContent);\n if (!hasCriterion) {\n errors.push(\n 'SUCCESS_CRITERIA.md: Must contain at least one criterion in format: - [ ] criterion text'\n );\n }\n } catch {\n // Already caught in required files check\n }\n\n const cycles = await detectCircularReferences(dir);\n for (const cycle of cycles) {\n errors.push(`Circular reference detected: ${cycle}`);\n }\n\n if (parsed.infrastructure) {\n const infra = parsed.infrastructure;\n if (\n ['web-app', 'api-service', 'mobile-app'].includes(parsed.output_type) &&\n infra.services.length === 0\n ) {\n warnings.push(\n `${parsed.output_type} should typically define infrastructure services (database, auth, etc.)`\n );\n }\n if (!infra.setup_time_minutes) {\n warnings.push('infrastructure.setup_time_minutes is not set');\n }\n for (const service of infra.services) {\n if (service.default_provider) {\n const providerNames = service.providers.map((p) => p.name);\n if (!providerNames.includes(service.default_provider)) {\n errors.push(\n `infrastructure.services[${service.name}].default_provider \"${service.default_provider}\" ` +\n `does not match any defined provider (${providerNames.join(', ')})`\n );\n }\n }\n }\n } else {\n if (['web-app', 'api-service', 'mobile-app'].includes(parsed.output_type)) {\n warnings.push(\n 'No infrastructure block defined. Consider adding infrastructure.services for database, auth, etc.'\n );\n }\n }\n\n if (parsed.estimated_tokens < 1000) {\n warnings.push(\n `estimated_tokens (${parsed.estimated_tokens}) seems very low. Most specs use 10,000+.`\n );\n }\n if (parsed.estimated_tokens > 10_000_000) {\n warnings.push(`estimated_tokens (${parsed.estimated_tokens}) seems very high.`);\n }\n if (parsed.estimated_cost_usd < 0.01) {\n warnings.push(\n `estimated_cost_usd ($${parsed.estimated_cost_usd}) seems very low.`\n );\n }\n if (parsed.estimated_time_minutes < 1) {\n warnings.push(\n `estimated_time_minutes (${parsed.estimated_time_minutes}) seems unrealistically low.`\n );\n }\n}\n\n/**\n * Validates a spec directory. Detects format first, then runs universal checks\n * and format-specific validation. Returns ValidationResult with format and\n * formatDetectedBy when detection ran.\n */\nexport async function validateSpec(specPath: string): Promise<ValidationResult> {\n const dir = resolve(specPath);\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const detection = await detectSpecFormat(dir);\n\n // Universal: directory non-empty (at least one readable file)\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n const hasAnyFile = entries.some((e) => e.isFile());\n if (!hasAnyFile) {\n errors.push('Directory is empty or has no readable files');\n }\n } catch {\n errors.push('Directory is empty or unreadable');\n }\n\n // If sidecar exists, validate with specmarketSidecarSchema and sanity-check estimates\n const sidecarPath = join(dir, SIDECAR_FILENAME);\n if (await fileExists(sidecarPath)) {\n try {\n const raw = await readFile(sidecarPath, 'utf-8');\n const parsed = parseYaml(raw) as unknown;\n const sidecarResult = specmarketSidecarSchema.safeParse(parsed);\n if (!sidecarResult.success) {\n for (const issue of sidecarResult.error.issues) {\n errors.push(\n `${SIDECAR_FILENAME}: ${issue.path.join('.')} — ${issue.message}`\n );\n }\n } else {\n const sidecar = sidecarResult.data;\n if (sidecar.estimated_tokens !== undefined) {\n if (sidecar.estimated_tokens < 1000) {\n warnings.push(\n `sidecar estimated_tokens (${sidecar.estimated_tokens}) seems very low.`\n );\n }\n if (sidecar.estimated_tokens > 10_000_000) {\n warnings.push(\n `sidecar estimated_tokens (${sidecar.estimated_tokens}) seems very high.`\n );\n }\n }\n if (\n sidecar.estimated_cost_usd !== undefined &&\n sidecar.estimated_cost_usd < 0.01\n ) {\n warnings.push(\n `sidecar estimated_cost_usd ($${sidecar.estimated_cost_usd}) seems very low.`\n );\n }\n if (\n sidecar.estimated_time_minutes !== undefined &&\n sidecar.estimated_time_minutes < 1\n ) {\n warnings.push(\n `sidecar estimated_time_minutes (${sidecar.estimated_time_minutes}) seems unrealistically low.`\n );\n }\n }\n } catch (err) {\n errors.push(\n `${SIDECAR_FILENAME}: Failed to read or parse: ${(err as Error).message}`\n );\n }\n }\n\n // Format-specific validation. Run legacy validation when spec.yaml exists or\n // when format is legacy (e.g. PROMPT+SUCCESS_CRITERIA but spec.yaml missing).\n const hasSpecYaml = await fileExists(join(dir, 'spec.yaml'));\n if (hasSpecYaml || detection.format === 'specmarket-legacy') {\n await validateLegacySpec(dir, errors, warnings);\n }\n\n switch (detection.format) {\n case 'specmarket-legacy':\n break;\n case 'speckit': {\n const hasSpecMd = await fileExists(join(dir, 'spec.md'));\n const hasTasksMd = await fileExists(join(dir, 'tasks.md'));\n const hasPlanMd = await fileExists(join(dir, 'plan.md'));\n const hasSpecifyDir = await directoryExists(join(dir, '.specify'));\n if (!hasSpecMd) {\n errors.push('speckit format requires spec.md');\n }\n if (!hasTasksMd && !hasPlanMd) {\n errors.push('speckit format requires tasks.md or plan.md');\n }\n if (!hasSpecifyDir) {\n warnings.push('speckit format: .specify/ directory is recommended');\n }\n break;\n }\n case 'bmad': {\n const hasPrdMd = await fileExists(join(dir, 'prd.md'));\n const hasStory = await hasStoryFiles(dir);\n if (!hasPrdMd && !hasStory) {\n errors.push('bmad format requires prd.md or story-*.md files');\n }\n const hasArch = await fileExists(join(dir, 'architecture.md'));\n if (!hasArch) {\n warnings.push('bmad format: architecture.md is recommended');\n }\n break;\n }\n case 'ralph': {\n const prdPath = join(dir, 'prd.json');\n if (!(await fileExists(prdPath))) {\n errors.push('ralph format requires prd.json');\n break;\n }\n try {\n const raw = await readFile(prdPath, 'utf-8');\n const data = JSON.parse(raw) as unknown;\n if (\n !data ||\n typeof data !== 'object' ||\n !('userStories' in data) ||\n !Array.isArray((data as { userStories: unknown }).userStories)\n ) {\n errors.push('ralph format: prd.json must have userStories array');\n }\n } catch {\n errors.push('ralph format: prd.json must be valid JSON with userStories array');\n }\n break;\n }\n case 'custom':\n default: {\n const hasMd = await hasMarkdownFiles(dir);\n if (!hasMd) {\n errors.push('custom format requires at least one .md file');\n break;\n }\n // At least one .md file > 100 bytes\n const textExtensions = new Set(['.md']);\n const mdFiles = await collectFiles(dir, dir, textExtensions);\n let hasSubstantialMd = false;\n for (const f of mdFiles) {\n try {\n const content = await readFile(join(dir, f), 'utf-8');\n if (content.length > 100) {\n hasSubstantialMd = true;\n break;\n }\n } catch {\n // skip\n }\n }\n if (!hasSubstantialMd) {\n errors.push('custom format requires at least one .md file larger than 100 bytes');\n }\n break;\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n format: detection.format,\n formatDetectedBy: detection.detectedBy,\n };\n}\n\nexport function createValidateCommand(): Command {\n return new Command('validate')\n .description('Validate a spec directory for completeness and schema compliance')\n .argument('[path]', 'Path to the spec directory (defaults to current directory)', '.')\n .action(async (specPath: string) => {\n try {\n const result = await validateSpec(specPath);\n\n if (result.format !== undefined) {\n console.log(chalk.gray(`Detected format: ${result.format}`));\n }\n\n if (result.warnings.length > 0) {\n console.log(chalk.yellow('\\nWarnings:'));\n for (const warning of result.warnings) {\n console.log(chalk.yellow(` ⚠ ${warning}`));\n }\n }\n\n if (result.errors.length > 0) {\n console.log(chalk.red('\\nErrors:'));\n for (const error of result.errors) {\n console.log(chalk.red(` ✗ ${error}`));\n }\n console.log(\n chalk.red(`\\nValidation failed with ${result.errors.length} error(s).`)\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n console.log(\n chalk.green(\n `\\n✓ Spec is valid${result.warnings.length > 0 ? ` (${result.warnings.length} warning(s))` : ''}`\n )\n );\n } catch (err) {\n console.error(chalk.red(`Validation error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { readFile, readdir, access } from 'fs/promises';\nimport { join } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { SIDECAR_FILENAME } from '@specmarket/shared';\nimport type { FormatDetectionResult } from '@specmarket/shared';\n\n/** Check if a file exists and is readable. */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Check if a directory exists and is readable. */\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n await access(dirPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Check if directory contains any story-*.md files (BMAD pattern). */\nexport async function hasStoryFiles(dir: string): Promise<boolean> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.some(\n (e) => e.isFile() && e.name.startsWith('story-') && e.name.endsWith('.md')\n );\n } catch {\n return false;\n }\n}\n\n/** Check if directory (non-recursive) or subdirs contain any .md files. */\nexport async function hasMarkdownFiles(dir: string): Promise<boolean> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.md')) return true;\n if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {\n const found = await hasMarkdownFiles(join(dir, entry.name));\n if (found) return true;\n }\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/** Read and parse specmarket.yaml; return spec_format if valid, else null. */\nexport async function tryReadSidecar(\n dir: string\n): Promise<{ spec_format: string } | null> {\n const path = join(dir, SIDECAR_FILENAME);\n if (!(await fileExists(path))) return null;\n try {\n const raw = await readFile(path, 'utf-8');\n const parsed = parseYaml(raw) as unknown;\n if (parsed && typeof parsed === 'object' && 'spec_format' in parsed) {\n const fmt = (parsed as { spec_format: unknown }).spec_format;\n if (typeof fmt === 'string' && fmt.length > 0) return { spec_format: fmt };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Detect spec format for a directory. Priority:\n * 1. Sidecar specmarket.yaml with spec_format → use that value, high confidence\n * 2. specmarket-legacy: spec.yaml + PROMPT.md + SUCCESS_CRITERIA.md\n * 3. speckit: spec.md + (plan.md | tasks.md) + .specify/ directory\n * 4. bmad: prd.md + (architecture.md | story-*.md)\n * 5. ralph: prd.json with userStories[] array\n * 6. custom: any .md files → low confidence\n * 7. Fallback: custom, low confidence\n */\nexport async function detectSpecFormat(dir: string): Promise<FormatDetectionResult> {\n const sidecar = await tryReadSidecar(dir);\n if (sidecar) {\n return {\n format: sidecar.spec_format,\n detectedBy: 'sidecar',\n confidence: 'high',\n };\n }\n\n const hasSpecYaml = await fileExists(join(dir, 'spec.yaml'));\n const hasPromptMd = await fileExists(join(dir, 'PROMPT.md'));\n const hasSuccessCriteria = await fileExists(join(dir, 'SUCCESS_CRITERIA.md'));\n if (hasSpecYaml && hasPromptMd && hasSuccessCriteria) {\n return {\n format: 'specmarket-legacy',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n if (hasPromptMd && hasSuccessCriteria) {\n return {\n format: 'specmarket-legacy',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n\n const hasSpecMd = await fileExists(join(dir, 'spec.md'));\n const hasPlanMd = await fileExists(join(dir, 'plan.md'));\n const hasTasksMd = await fileExists(join(dir, 'tasks.md'));\n if (hasSpecMd && (hasPlanMd || hasTasksMd)) {\n return {\n format: 'speckit',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n if (hasSpecMd) {\n return {\n format: 'speckit',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n\n const hasPrdMd = await fileExists(join(dir, 'prd.md'));\n const hasArchitectureMd = await fileExists(join(dir, 'architecture.md'));\n const storyFiles = await hasStoryFiles(dir);\n if (hasPrdMd && (hasArchitectureMd || storyFiles)) {\n return {\n format: 'bmad',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n\n const prdJsonPath = join(dir, 'prd.json');\n if (await fileExists(prdJsonPath)) {\n try {\n const raw = await readFile(prdJsonPath, 'utf-8');\n const data = JSON.parse(raw) as unknown;\n if (data && typeof data === 'object') {\n return {\n format: 'ralph',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n } catch {\n // not valid JSON\n }\n }\n\n if (await hasMarkdownFiles(dir)) {\n return {\n format: 'custom',\n detectedBy: 'heuristic',\n confidence: 'low',\n };\n }\n\n return {\n format: 'custom',\n detectedBy: 'heuristic',\n confidence: 'low',\n };\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { readFile, mkdir, writeFile as writeFileFn } from 'fs/promises';\nimport { join, resolve, isAbsolute } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { specYamlSchema, EXIT_CODES } from '@specmarket/shared';\nimport { validateSpec } from './validate.js';\nimport { loadCredentials, isAuthenticated } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { submitTelemetry, promptTelemetryOptIn } from '../lib/telemetry.js';\nimport { runSpec, checkClaudeCliInstalled } from '../lib/ralph-loop.js';\nimport type { LoopIteration } from '@specmarket/shared';\nimport createDebug from 'debug';\nimport { createRequire } from 'module';\n\nconst debug = createDebug('specmarket:cli');\n\n// Dynamically read version from package.json (at runtime, bundled into dist/index.js)\nconst _require = createRequire(import.meta.url);\nconst CLI_VERSION: string = _require('../package.json').version;\n\n/**\n * Core run command handler.\n *\n * Accepts either:\n * - A local path: ./my-spec, /path/to/spec, .\n * - A registry ID: my-spec, @user/my-spec, @user/my-spec@1.2.0\n *\n * Flow:\n * 1. Resolve spec (download from registry if needed)\n * 2. Validate spec (exit 1 on validation error)\n * 3. Print sandboxing warning (ALWAYS)\n * 4. If authenticated + telemetry opted in: prompt once if never asked\n * 5. Execute Ralph Loop\n * 6. Submit telemetry if opted in\n * 7. Print run summary\n */\nexport async function handleRun(\n specPathOrId: string,\n opts: {\n maxLoops?: string;\n maxBudget?: string;\n noTelemetry?: boolean;\n model?: string;\n dryRun?: boolean;\n resume?: string;\n output?: string;\n }\n): Promise<void> {\n // Resolve spec directory (and registry spec ID if downloaded from registry)\n const { specDir, registrySpecId } = await resolveSpecPath(specPathOrId);\n\n // Validate before running\n console.log(chalk.gray('Validating spec...'));\n const validation = await validateSpec(specDir);\n\n if (!validation.valid) {\n console.log(chalk.red('\\nSpec validation failed:'));\n for (const err of validation.errors) {\n console.log(chalk.red(` ✗ ${err}`));\n }\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n if (validation.warnings.length > 0) {\n for (const warning of validation.warnings) {\n console.log(chalk.yellow(` ⚠ ${warning}`));\n }\n }\n\n // Load spec.yaml\n const specYamlContent = await readFile(join(specDir, 'spec.yaml'), 'utf-8');\n const specYamlRaw = parseYaml(specYamlContent);\n const specYaml = specYamlSchema.parse(specYamlRaw);\n\n // ALWAYS print sandboxing warning (SECURITY requirement)\n console.log('');\n console.log(chalk.yellow('⚠ SECURITY WARNING'));\n console.log(chalk.yellow('─────────────────────────────────────────────────────────'));\n console.log(chalk.yellow(' AI-generated code will be executed in your environment.'));\n console.log(chalk.yellow(' It is STRONGLY RECOMMENDED to run specs in an isolated'));\n console.log(chalk.yellow(' environment:'));\n console.log(chalk.yellow(' • Docker container'));\n console.log(chalk.yellow(' • Virtual machine or cloud sandbox'));\n console.log(chalk.yellow(' • Dedicated non-root user account'));\n console.log(chalk.yellow(' NEVER run specs as root or with admin privileges.'));\n console.log(chalk.yellow('─────────────────────────────────────────────────────────'));\n console.log('');\n\n // Telemetry opt-in prompt (first run for authenticated users)\n const authed = await isAuthenticated();\n if (authed && !opts.noTelemetry) {\n await promptTelemetryOptIn();\n }\n\n // Pre-flight check: Ensure Claude CLI is installed\n try {\n await checkClaudeCliInstalled();\n } catch (err) {\n console.log(chalk.red(`\\n✗ ${(err as Error).message}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n const maxLoops = opts.maxLoops ? parseInt(opts.maxLoops, 10) : undefined;\n const maxBudget = opts.maxBudget ? parseFloat(opts.maxBudget) : undefined;\n\n console.log(chalk.cyan(`\\nRunning spec: ${chalk.bold(specYaml.display_name)}`));\n console.log(chalk.gray(` Version: ${specYaml.version}`));\n console.log(chalk.gray(` Model: ${opts.model ?? specYaml.min_model}`));\n console.log(chalk.gray(` Max loops: ${maxLoops ?? 50}`));\n console.log(chalk.gray(` Estimated tokens: ${specYaml.estimated_tokens.toLocaleString()}`));\n console.log(chalk.gray(` Estimated cost: $${specYaml.estimated_cost_usd.toFixed(2)}`));\n console.log('');\n\n const spinner = ora({ text: 'Starting loop iteration 1...', spinner: 'dots' }).start();\n\n try {\n const result = await runSpec(\n specDir,\n {\n name: specYaml.name,\n version: specYaml.version,\n estimatedTokens: specYaml.estimated_tokens,\n estimatedCostUsd: specYaml.estimated_cost_usd,\n estimatedTimeMinutes: specYaml.estimated_time_minutes,\n runner: specYaml.runner,\n minModel: specYaml.min_model,\n },\n {\n maxLoops,\n maxBudgetUsd: maxBudget,\n model: opts.model,\n dryRun: opts.dryRun,\n resumeRunId: opts.resume,\n outputDir: opts.output,\n cliVersion: CLI_VERSION,\n },\n (iteration: LoopIteration) => {\n spinner.text = `Loop ${iteration.iteration}: ${iteration.tokens.toLocaleString()} tokens, ${(iteration.durationMs / 1000).toFixed(1)}s`;\n }\n );\n\n const { report } = result;\n const statusColor =\n report.status === 'success'\n ? chalk.green\n : report.status === 'stall' || report.status === 'budget_exceeded'\n ? chalk.yellow\n : chalk.red;\n\n spinner.stop();\n console.log('');\n console.log(chalk.bold('Run Complete'));\n console.log('─────────────────────────────────');\n console.log(` Status: ${statusColor(report.status.toUpperCase())}`);\n console.log(` Loops: ${report.loopCount}`);\n console.log(` Tokens: ${report.totalTokens.toLocaleString()}`);\n console.log(` Cost: $${report.totalCostUsd.toFixed(4)}`);\n console.log(` Time: ${report.totalTimeMinutes.toFixed(1)} minutes`);\n console.log(` Run ID: ${chalk.gray(report.runId)}`);\n console.log(` Output: ${chalk.gray(result.outputDir)}`);\n\n if (report.successCriteriaResults.length > 0) {\n console.log('');\n console.log(chalk.bold('Success Criteria:'));\n for (const criterion of report.successCriteriaResults) {\n const icon = criterion.passed ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${icon} ${criterion.criterion}`);\n }\n }\n\n // Submit telemetry (non-blocking)\n // Priority: registry spec ID (from download) > forked_from_id (from spec.yaml) > undefined (local run)\n const resolvedSpecId = registrySpecId ?? specYaml.forked_from_id ?? undefined;\n const telemetrySubmitted = await submitTelemetry(\n { ...report, specId: resolvedSpecId },\n { noTelemetry: opts.noTelemetry }\n );\n if (telemetrySubmitted) {\n console.log(chalk.gray('\\n Telemetry submitted to SpecMarket platform.'));\n }\n\n if (report.status === 'budget_exceeded') {\n process.exit(EXIT_CODES.BUDGET_EXCEEDED);\n } else if (report.status === 'failure' || report.status === 'stall') {\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n } catch (err) {\n spinner.fail(chalk.red(`Run failed: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n } else if (errCode === String(EXIT_CODES.NETWORK_ERROR)) {\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n}\n\n/**\n * Result from resolveSpecPath: the local directory containing the spec,\n * and optionally the Convex document ID of the registry spec (for telemetry attribution).\n */\ninterface ResolvedSpec {\n specDir: string;\n registrySpecId?: string;\n}\n\n/**\n * Resolves a spec path-or-ID to a local directory.\n *\n * Accepts:\n * - Local paths: ./my-spec, ../specs/foo, /absolute/path, .\n * - Registry IDs: @user/name, @user/name@1.2.0, bare-name\n *\n * For registry IDs: calls specs.download to get a signed URL, downloads the zip,\n * extracts it to a temp directory, and returns the temp directory path along with\n * the spec's Convex document ID for telemetry attribution.\n */\nasync function resolveSpecPath(pathOrId: string): Promise<ResolvedSpec> {\n // Explicit local paths: ./ ../ / or bare \".\"\n if (\n pathOrId.startsWith('./') ||\n pathOrId.startsWith('../') ||\n isAbsolute(pathOrId) ||\n pathOrId === '.'\n ) {\n return { specDir: resolve(pathOrId) };\n }\n\n // Check if it's a registry reference: @user/name, @user/name@version, or bare name with no /\n const registryPattern = /^(@[\\w-]+\\/[\\w-]+(?:@[\\d.]+)?)$|^([\\w-]+)$/;\n const match = pathOrId.match(registryPattern);\n\n if (!match) {\n // Not a registry pattern, treat as local path\n debug('Treating %s as local path (no registry pattern match)', pathOrId);\n return { specDir: resolve(pathOrId) };\n }\n\n // Check if it exists as a local directory first\n const { access } = await import('fs/promises');\n const localPath = resolve(pathOrId);\n try {\n await access(localPath);\n debug('Found local directory %s — using as local spec', localPath);\n return { specDir: localPath };\n } catch {\n // Not a local directory — treat as registry ID\n }\n\n debug('Resolving registry ID: %s', pathOrId);\n\n // Parse @user/name@version format\n let scopedName: string | undefined;\n let version: string | undefined;\n\n if (pathOrId.startsWith('@')) {\n // @user/name or @user/name@1.2.0\n const versionSep = pathOrId.lastIndexOf('@', pathOrId.length - 1);\n // Check that the second @ (version separator) is after the scope @\n if (versionSep > 0 && pathOrId.indexOf('@') !== versionSep) {\n scopedName = pathOrId.slice(0, versionSep);\n version = pathOrId.slice(versionSep + 1);\n } else {\n scopedName = pathOrId;\n }\n } else {\n // Bare name — will search by slug\n scopedName = undefined;\n }\n\n // Get Convex client (auth optional for download)\n const creds = await loadCredentials();\n const client = await getConvexClient(creds?.token);\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error(\n `Registry spec \"${pathOrId}\" requested but Convex API bindings not available. ` +\n `Use a local path instead, or configure CONVEX_URL.`\n );\n }\n\n // Fetch spec metadata to resolve bare names to scopedName\n let registrySpecId: string | undefined;\n if (!scopedName) {\n // Bare name: search for it (take first result)\n const results = await client.query(api.specs.search, {\n query: pathOrId,\n limit: 1,\n });\n if (results.length === 0) {\n throw new Error(\n `Spec \"${pathOrId}\" not found in registry and does not exist as a local directory.`\n );\n }\n scopedName = results[0].scopedName;\n registrySpecId = results[0]._id;\n debug('Resolved bare name \"%s\" to %s (id: %s)', pathOrId, scopedName, registrySpecId);\n }\n\n // Fetch the spec document to get its Convex ID (needed for telemetry attribution)\n if (!registrySpecId && scopedName) {\n try {\n const specDoc = await client.query(api.specs.get, { scopedName });\n if (specDoc) {\n registrySpecId = specDoc._id;\n debug('Resolved scopedName \"%s\" to spec ID %s', scopedName, registrySpecId);\n }\n } catch (err) {\n debug('Failed to resolve spec ID for %s (non-fatal): %O', scopedName, err);\n }\n }\n\n // Download the spec zip\n const downloadArgs: { scopedName?: string; version?: string } = { scopedName };\n if (version) downloadArgs.version = version;\n\n const { url, version: resolvedVersion } = await client.action(\n api.specs.download,\n downloadArgs\n );\n debug('Got download URL for %s@%s', scopedName, resolvedVersion);\n\n // Download and extract to temp directory\n const { tmpdir } = await import('os');\n const { randomUUID } = await import('crypto');\n const tempDir = join(tmpdir(), `specmarket-${randomUUID()}`);\n await mkdir(tempDir, { recursive: true });\n\n let response: Response;\n try {\n response = await fetch(url);\n } catch (fetchErr) {\n const err = new Error(`Network error downloading spec: ${(fetchErr as Error).message}`);\n (err as NodeJS.ErrnoException).code = String(EXIT_CODES.NETWORK_ERROR);\n throw err;\n }\n if (!response.ok) {\n const exitCode = response.status === 401 || response.status === 403\n ? EXIT_CODES.AUTH_ERROR\n : EXIT_CODES.NETWORK_ERROR;\n const err = new Error(`Failed to download spec: ${response.statusText}`);\n (err as NodeJS.ErrnoException).code = String(exitCode);\n throw err;\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const zipPath = join(tempDir, 'spec.zip');\n await writeFileFn(zipPath, buffer);\n\n // Extract zip\n const { execAsync } = await import('../lib/exec.js');\n await execAsync(`unzip -q \"${zipPath}\" -d \"${tempDir}\"`);\n\n // Clean up zip file\n const { unlink } = await import('fs/promises');\n await unlink(zipPath).catch(() => {});\n\n debug('Registry spec extracted to %s', tempDir);\n console.log(chalk.gray(`Downloaded ${scopedName}@${resolvedVersion} to temporary directory`));\n\n return { specDir: tempDir, registrySpecId };\n}\n\nexport function createRunCommand(): Command {\n return new Command('run')\n .description('Execute a spec locally using the Ralph Loop')\n .argument('[path-or-id]', 'Local path to spec directory or registry ID (@user/name[@version])', '.')\n .option('--max-loops <n>', 'Maximum loop iterations (default: 50)')\n .option('--max-budget <usd>', 'Maximum budget in USD (default: 2x estimated)')\n .option('--no-telemetry', 'Disable telemetry submission for this run')\n .option('--model <model>', 'Override AI model (default: spec\\'s min_model)')\n .option('--dry-run', 'Validate and show config without executing')\n .option('--resume <run-id>', 'Resume a previous run from where it left off')\n .option('--output <dir>', 'Custom output directory for run artifacts')\n .action(async (pathOrId: string, opts) => {\n try {\n await handleRun(pathOrId, opts);\n } catch (err) {\n console.error(chalk.red(`Run failed: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n } else if (errCode === String(EXIT_CODES.NETWORK_ERROR)) {\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import type { RunReport } from '@specmarket/shared';\nimport type { Id } from '@specmarket/convex/dataModel';\nimport { loadCredentials } from './auth.js';\nimport { loadConfig } from './config.js';\nimport { getConvexClient } from './convex-client.js';\nimport { api } from '@specmarket/convex/api';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:telemetry');\n\n/**\n * Submits run telemetry to the Convex backend.\n *\n * Privacy guarantees enforced here:\n * 1. Only submits if user is authenticated AND has explicitly opted in (telemetry=true).\n * 2. Never transmits source code — only metadata (tokens, cost, time, status, etc.).\n * 3. Submission failures are silently logged and never block CLI operation.\n * 4. --no-telemetry flag overrides config for a single run.\n *\n * @returns true if telemetry was submitted, false if skipped or failed\n */\nexport async function submitTelemetry(\n report: RunReport,\n opts: { noTelemetry?: boolean } = {}\n): Promise<boolean> {\n // Hard override: --no-telemetry flag\n if (opts.noTelemetry) {\n debug('Telemetry disabled via --no-telemetry flag');\n return false;\n }\n\n // Must be authenticated\n const creds = await loadCredentials();\n if (!creds) {\n debug('Skipping telemetry: not authenticated');\n return false;\n }\n\n // Must have opted in\n const config = await loadConfig();\n if (!config.telemetry) {\n debug('Skipping telemetry: user has not opted in (telemetry=false)');\n return false;\n }\n\n // specId is required to submit telemetry (must be a registry spec)\n if (!report.specId) {\n debug('Skipping telemetry: no specId (local-only run)');\n return false;\n }\n\n try {\n const client = await getConvexClient(creds.token);\n\n await client.mutation(api.runs.submit, {\n specId: report.specId as Id<'specs'>,\n specVersion: report.specVersion,\n model: report.model,\n runner: report.runner,\n loopCount: report.loopCount,\n totalTokens: report.totalTokens,\n totalCostUsd: report.totalCostUsd,\n totalTimeMinutes: report.totalTimeMinutes,\n status: report.status,\n successCriteriaResults: report.successCriteriaResults,\n os: report.os,\n nodeVersion: report.nodeVersion,\n cliVersion: report.cliVersion,\n completedAt: Date.now(),\n });\n\n debug('Telemetry submitted successfully for run %s', report.runId);\n return true;\n } catch (err) {\n // Telemetry failures MUST NOT block CLI operation\n debug('Telemetry submission failed (non-fatal): %O', err);\n return false;\n }\n}\n\n/**\n * Prompts the user once to opt in to telemetry.\n * Stores the choice in config so we don't ask again.\n * Called on the first `specmarket run` by an authenticated user.\n */\nexport async function promptTelemetryOptIn(): Promise<boolean> {\n const config = await loadConfig();\n\n if (config.telemetryPrompted) {\n return config.telemetry ?? false;\n }\n\n // Dynamic import to avoid loading inquirer in all code paths\n const { default: inquirer } = await import('inquirer');\n\n const { optIn } = await inquirer.prompt<{ optIn: boolean }>([\n {\n type: 'confirm',\n name: 'optIn',\n message:\n 'Help improve SpecMarket by submitting anonymous run metadata (tokens, cost, status)? No source code is ever sent.',\n default: false,\n },\n ]);\n\n const { saveConfig } = await import('./config.js');\n await saveConfig({ ...config, telemetry: optIn, telemetryPrompted: true });\n\n return optIn;\n}\n","import { spawn } from 'child_process';\nimport { mkdir, writeFile, readFile, access } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { homedir } from 'os';\nimport { randomUUID } from 'crypto';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { RunReport, LoopIteration, SuccessCriterionResult } from '@specmarket/shared';\nimport {\n CONFIG_PATHS,\n RUN_DEFAULTS,\n EXIT_CODES,\n RUNNER_ID,\n} from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:runner');\nconst execAsync = promisify(exec);\n\n/**\n * Pre-flight check: Verifies that Claude CLI is installed before attempting to run a spec.\n * Throws an error with installation instructions if claude is not found.\n */\nexport async function checkClaudeCliInstalled(): Promise<void> {\n try {\n // Use 'which claude' to check if claude is in PATH\n await execAsync('which claude');\n } catch {\n throw new Error(\n `Claude CLI is not installed or not in your PATH.\\n\\n` +\n `Installation instructions:\\n` +\n ` npm install -g @anthropic-ai/claude-code\\n\\n` +\n `Or visit: https://www.anthropic.com/claude-code\\n`\n );\n }\n}\n\nexport interface RunOptions {\n maxLoops?: number;\n maxBudgetUsd?: number;\n model?: string;\n dryRun?: boolean;\n resumeRunId?: string;\n outputDir?: string;\n cliVersion: string;\n}\n\nexport interface RunResult {\n report: RunReport;\n outputDir: string;\n}\n\n/**\n * Orchestrates the Ralph Loop — the core spec execution engine.\n *\n * The loop:\n * 1. Creates a sandboxed working directory under ~/.specmarket/runs/<run-id>/\n * 2. Copies spec files into the working directory\n * 3. Initializes git for diff tracking\n * 4. Executes: `cat PROMPT.md | claude --print` in a loop\n * 5. After each loop: captures tokens, duration, git diff\n * 6. Checks for completion conditions:\n * - SUCCESS: TASKS.md empty + tests pass + all SUCCESS_CRITERIA.md criteria met\n * - STALL: 3 consecutive loops with no git diff\n * - FAILURE: 10 consecutive loops with same failing output\n * - BUDGET: total tokens > 2x estimated_tokens\n * 7. Writes run-report.json on completion\n *\n * SECURITY: Always prints sandboxing recommendation before starting.\n */\nexport async function runSpec(\n specDir: string,\n specYaml: {\n name: string;\n version: string;\n estimatedTokens: number;\n estimatedCostUsd: number;\n estimatedTimeMinutes: number;\n runner: string;\n minModel: string;\n },\n opts: RunOptions,\n onProgress?: (iteration: LoopIteration) => void\n): Promise<RunResult> {\n const maxLoops = opts.maxLoops ?? RUN_DEFAULTS.MAX_LOOPS;\n const budgetTokens =\n (opts.maxBudgetUsd\n ? (opts.maxBudgetUsd / specYaml.estimatedCostUsd) * specYaml.estimatedTokens\n : specYaml.estimatedTokens * RUN_DEFAULTS.BUDGET_MULTIPLIER);\n\n const runId = opts.resumeRunId ?? randomUUID();\n const runsBaseDir = join(homedir(), CONFIG_PATHS.RUNS_DIR);\n const runDir = opts.outputDir ?? join(runsBaseDir, runId);\n\n await mkdir(runDir, { recursive: true });\n debug('Run directory: %s', runDir);\n\n if (opts.dryRun) {\n debug('Dry run mode — skipping execution');\n const report: RunReport = {\n runId,\n specVersion: specYaml.version,\n model: opts.model ?? specYaml.minModel,\n runner: specYaml.runner,\n loopCount: 0,\n totalTokens: 0,\n totalCostUsd: 0,\n totalTimeMinutes: 0,\n status: 'user_cancelled',\n successCriteriaResults: [],\n os: process.platform,\n nodeVersion: process.version,\n cliVersion: opts.cliVersion,\n };\n return { report, outputDir: runDir };\n }\n\n const isResuming = opts.resumeRunId !== undefined;\n let startIteration = 1;\n let totalTokens = 0;\n\n if (isResuming) {\n // When resuming, preserve the existing working directory — do NOT re-copy\n // spec files or re-initialize git, as that would clobber AI-generated work\n // from the previous session.\n const existingReport = await loadExistingReport(runDir);\n if (existingReport) {\n startIteration = existingReport.loopCount + 1;\n totalTokens = existingReport.totalTokens;\n debug('Resuming from iteration %d with %d tokens carried over', startIteration, totalTokens);\n }\n } else {\n // Fresh run: copy spec files and initialize git for diff tracking\n await copySpecFiles(specDir, runDir);\n await initGit(runDir);\n }\n\n const startTime = Date.now();\n const iterations: LoopIteration[] = [];\n let consecutiveNoChange = 0;\n let lastOutput = '';\n let consecutiveSameOutput = 0;\n\n let finalStatus: RunReport['status'] = 'failure';\n let successCriteriaResults: SuccessCriterionResult[] = [];\n\n for (let i = startIteration; i <= maxLoops; i++) {\n debug('Starting loop iteration %d/%d', i, maxLoops);\n\n const iterStart = Date.now();\n\n // Execute: cat PROMPT.md | claude --print\n const result = await executeClaudeLoop(runDir, opts.model);\n\n const iterDuration = Date.now() - iterStart;\n const tokensThisLoop = parseTokensFromOutput(result.stdout);\n totalTokens += tokensThisLoop;\n\n // Capture git diff\n const gitDiff = await getGitDiff(runDir);\n\n const iteration: LoopIteration = {\n iteration: i,\n tokens: tokensThisLoop,\n durationMs: iterDuration,\n exitCode: result.exitCode,\n gitDiff,\n stdoutTail: result.stdout.slice(-2000),\n };\n iterations.push(iteration);\n onProgress?.(iteration);\n\n // Persist iteration data\n await writeFile(\n join(runDir, `iteration-${i}.json`),\n JSON.stringify(iteration, null, 2)\n );\n\n // Stage all changes for next diff\n await stageAllChanges(runDir);\n\n // ---- Completion detection ----\n\n // BUDGET check\n if (totalTokens > budgetTokens) {\n debug('Budget exceeded: %d tokens > %d limit', totalTokens, budgetTokens);\n finalStatus = 'budget_exceeded';\n break;\n }\n\n // STALL check: 3 loops with no git diff\n if (gitDiff.trim() === '') {\n consecutiveNoChange++;\n debug('No changes in iteration %d (%d consecutive)', i, consecutiveNoChange);\n if (consecutiveNoChange >= RUN_DEFAULTS.STALL_THRESHOLD) {\n debug('Stall detected after %d loops', consecutiveNoChange);\n finalStatus = 'stall';\n break;\n }\n } else {\n consecutiveNoChange = 0;\n }\n\n // FAILURE check: 10 loops with same output\n const currentOutputHash = hashString(result.stdout.slice(-500));\n if (currentOutputHash === lastOutput) {\n consecutiveSameOutput++;\n if (consecutiveSameOutput >= RUN_DEFAULTS.FAILURE_THRESHOLD) {\n debug('Failure detected: same output for %d loops', consecutiveSameOutput);\n finalStatus = 'failure';\n break;\n }\n } else {\n consecutiveSameOutput = 0;\n lastOutput = currentOutputHash;\n }\n\n // SUCCESS check\n const completionCheck = await checkCompletion(runDir);\n if (completionCheck.isComplete) {\n debug('Success criteria met at iteration %d', i);\n successCriteriaResults = completionCheck.results;\n finalStatus = 'success';\n break;\n }\n\n // Update partial success criteria results for reporting\n successCriteriaResults = completionCheck.results;\n }\n\n // If we exhausted all loops without a status, mark as failure\n if (finalStatus === 'failure' && successCriteriaResults.length === 0) {\n successCriteriaResults = await evaluateSuccessCriteria(runDir).catch(() => []);\n }\n\n const totalTimeMinutes = (Date.now() - startTime) / 60000;\n const costPerToken = specYaml.estimatedCostUsd / specYaml.estimatedTokens;\n const totalCostUsd = totalTokens * costPerToken;\n\n const report: RunReport = {\n runId,\n specVersion: specYaml.version,\n model: opts.model ?? specYaml.minModel,\n runner: specYaml.runner,\n loopCount: iterations.length,\n totalTokens,\n totalCostUsd,\n totalTimeMinutes,\n status: finalStatus,\n successCriteriaResults,\n os: process.platform,\n nodeVersion: process.version,\n cliVersion: opts.cliVersion,\n };\n\n await writeFile(\n join(runDir, 'run-report.json'),\n JSON.stringify(report, null, 2)\n );\n\n debug('Run complete: %s (status=%s, loops=%d)', runId, finalStatus, iterations.length);\n\n return { report, outputDir: runDir };\n}\n\n// ---- Internal helpers ----\n\nasync function copySpecFiles(srcDir: string, destDir: string): Promise<void> {\n const { cp } = await import('fs/promises');\n await cp(srcDir, join(destDir, 'spec'), { recursive: true });\n // Also copy directly to destDir so PROMPT.md is at root\n await cp(srcDir, destDir, { recursive: true, force: false });\n debug('Spec files copied from %s to %s', srcDir, destDir);\n}\n\nasync function initGit(dir: string): Promise<void> {\n try {\n await execAsync('git init && git add -A && git commit -m \"initial spec state\" --allow-empty', {\n cwd: dir,\n });\n debug('Git initialized in %s', dir);\n } catch (err) {\n debug('Git init failed (non-fatal): %O', err);\n }\n}\n\nasync function stageAllChanges(dir: string): Promise<void> {\n try {\n await execAsync('git add -A', { cwd: dir });\n } catch {\n // Non-fatal\n }\n}\n\nasync function getGitDiff(dir: string): Promise<string> {\n try {\n const { stdout } = await execAsync('git diff HEAD --stat', { cwd: dir });\n return stdout;\n } catch {\n return '';\n }\n}\n\ninterface ExecuteResult {\n stdout: string;\n exitCode: number;\n}\n\nasync function executeClaudeLoop(dir: string, model?: string): Promise<ExecuteResult> {\n return new Promise((resolve) => {\n const args = ['--print', '--output-format', 'json'];\n if (model) {\n args.push('--model', model);\n }\n\n // Execute: cat PROMPT.md | claude --print --output-format json\n // Using --output-format json gives us structured output with token usage metadata.\n const proc = spawn('sh', ['-c', `cat PROMPT.md | claude ${args.join(' ')}`], {\n cwd: dir,\n stdio: ['inherit', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n proc.stderr?.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n // Write stderr to process stderr for visibility\n process.stderr.write(chunk);\n });\n\n proc.on('close', (code) => {\n resolve({ stdout, exitCode: code ?? 0 });\n });\n\n proc.on('error', (err) => {\n debug('claude spawn error: %O', err);\n resolve({ stdout: '', exitCode: 1 });\n });\n });\n}\n\n/**\n * Extracts token count from Claude Code's output.\n *\n * Strategy (in priority order):\n * 1. Parse JSON output format (claude --output-format json) which contains\n * structured metadata including token counts in the response.\n * 2. Match known text patterns from Claude Code's output (total_tokens, etc.)\n * 3. Estimate from output length as a last-resort heuristic (~4 chars per token).\n *\n * Returns 0 only if the output is empty (no meaningful work was done).\n */\nfunction parseTokensFromOutput(output: string): number {\n if (!output || output.trim().length === 0) return 0;\n\n // Strategy 1: Parse JSON output format from claude --output-format json\n // Claude Code JSON output may contain token usage info in the response metadata.\n try {\n // The output might be a single JSON object or newline-delimited JSON\n const lines = output.trim().split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) continue;\n try {\n const parsed = JSON.parse(trimmed);\n\n // Check for various JSON structures Claude Code might emit\n if (typeof parsed === 'object' && parsed !== null) {\n // Direct token fields\n if (typeof parsed.total_tokens === 'number') return parsed.total_tokens;\n if (typeof parsed.totalTokens === 'number') return parsed.totalTokens;\n\n // Nested in usage object\n if (parsed.usage?.total_tokens) return parsed.usage.total_tokens;\n if (parsed.usage?.totalTokens) return parsed.usage.totalTokens;\n\n // Nested in result/metadata\n if (parsed.result?.usage?.total_tokens) return parsed.result.usage.total_tokens;\n if (parsed.metadata?.total_tokens) return parsed.metadata.total_tokens;\n\n // Sum of input + output tokens\n const input = parsed.usage?.input_tokens ?? parsed.usage?.prompt_tokens ?? 0;\n const output_tokens = parsed.usage?.output_tokens ?? parsed.usage?.completion_tokens ?? 0;\n if (input > 0 || output_tokens > 0) return input + output_tokens;\n\n // Cost-based estimation (if cost is reported but not tokens)\n // Haiku: ~$0.25/MTok input, $1.25/MTok output → avg ~$0.75/MTok\n // Sonnet: ~$3/MTok input, $15/MTok output → avg ~$9/MTok\n if (typeof parsed.cost_usd === 'number' && parsed.cost_usd > 0) {\n return Math.round(parsed.cost_usd / 0.000009); // Assume Sonnet pricing\n }\n }\n } catch {\n // Not valid JSON, skip this line\n }\n }\n } catch {\n // JSON parsing failed entirely, try text patterns\n }\n\n // Strategy 2: Regex patterns for text-based output\n const patterns = [\n /total[_\\s]tokens?[:\\s]+(\\d[\\d,]*)/i,\n /\"total_tokens\"[:\\s]+(\\d[\\d,]*)/,\n /\"totalTokens\"[:\\s]+(\\d[\\d,]*)/,\n /tokens?\\s*used[:\\s]+(\\d[\\d,]*)/i,\n /input[_\\s]tokens?[:\\s]+(\\d[\\d,]*).*output[_\\s]tokens?[:\\s]+(\\d[\\d,]*)/i,\n /prompt[_\\s]tokens?[:\\s]+(\\d[\\d,]*).*completion[_\\s]tokens?[:\\s]+(\\d[\\d,]*)/i,\n ];\n\n for (const pattern of patterns) {\n const match = output.match(pattern);\n if (match) {\n // Some patterns capture two groups (input + output)\n if (match[2]) {\n return parseIntComma(match[1]) + parseIntComma(match[2]);\n }\n if (match[1]) {\n return parseIntComma(match[1]);\n }\n }\n }\n\n // Strategy 3: Estimate from output length\n // Rough heuristic: ~4 characters per token for English text\n // This is imprecise but better than returning 0 (which breaks budget tracking)\n const estimatedTokens = Math.ceil(output.length / 4);\n debug(\n 'parseTokensFromOutput: no explicit token count found, estimating %d from %d chars',\n estimatedTokens,\n output.length\n );\n return estimatedTokens;\n}\n\n/** Parse an integer that might have comma separators (e.g. \"12,345\") */\nfunction parseIntComma(s: string): number {\n return parseInt(s.replace(/,/g, ''), 10) || 0;\n}\n\ninterface CompletionCheck {\n isComplete: boolean;\n results: SuccessCriterionResult[];\n}\n\nasync function checkCompletion(dir: string): Promise<CompletionCheck> {\n // Check 1: TASKS.md should be empty or have only checked items\n const fixPlanEmpty = await isFixPlanEmpty(dir);\n if (!fixPlanEmpty) {\n return {\n isComplete: false,\n results: await evaluateSuccessCriteria(dir).catch(() => []),\n };\n }\n\n // Check 2: Run test suite if detectable\n const testsPass = await runTests(dir);\n if (!testsPass) {\n return {\n isComplete: false,\n results: await evaluateSuccessCriteria(dir).catch(() => []),\n };\n }\n\n // Check 3: Evaluate SUCCESS_CRITERIA.md\n const criteriaResults = await evaluateSuccessCriteria(dir);\n const allPassed = criteriaResults.every((r) => r.passed);\n\n return {\n isComplete: allPassed,\n results: criteriaResults,\n };\n}\n\nasync function isFixPlanEmpty(dir: string): Promise<boolean> {\n try {\n const content = await readFile(join(dir, 'TASKS.md'), 'utf-8');\n // Consider empty if: no unchecked items (- [ ] lines)\n const hasUncheckedItems = /^- \\[ \\]/m.test(content);\n return !hasUncheckedItems;\n } catch {\n // No TASKS.md = considered empty\n return true;\n }\n}\n\nasync function runTests(dir: string): Promise<boolean> {\n // Try to detect and run tests using known test runner config files.\n // Exit code is the primary failure signal; output regex is a fallback.\n const testRunners = [\n { file: 'package.json', cmd: 'npm test -- --run 2>&1' },\n { file: 'vitest.config.ts', cmd: 'npx vitest run 2>&1' },\n { file: 'pytest.ini', cmd: 'python -m pytest --tb=no -q 2>&1' },\n { file: 'Makefile', cmd: 'make test 2>&1' },\n ];\n\n for (const runner of testRunners) {\n try {\n await access(join(dir, runner.file));\n } catch {\n continue; // Config file doesn't exist — try next runner\n }\n\n try {\n const { stdout, stderr } = await execAsync(runner.cmd, {\n cwd: dir,\n timeout: 120000,\n });\n // Exit code 0 — check output as secondary signal\n const combined = stdout + stderr;\n const hasFailed = /\\d+ failed|\\d+ error/i.test(combined);\n return !hasFailed;\n } catch (err: unknown) {\n // Non-zero exit code means tests failed\n if (err && typeof err === 'object' && 'code' in err && typeof err.code === 'number') {\n return false;\n }\n // Timeout or other execution error — skip to next runner\n continue;\n }\n }\n\n // No test runner found — assume passing\n return true;\n}\n\nasync function evaluateSuccessCriteria(dir: string): Promise<SuccessCriterionResult[]> {\n try {\n const content = await readFile(join(dir, 'SUCCESS_CRITERIA.md'), 'utf-8');\n const lines = content.split('\\n');\n const results: SuccessCriterionResult[] = [];\n\n for (const line of lines) {\n // Match markdown checkboxes: - [x] criterion (passed) or - [ ] criterion (not passed)\n const checkedMatch = line.match(/^-\\s+\\[x\\]\\s+(.+)/i);\n const uncheckedMatch = line.match(/^-\\s+\\[\\s\\]\\s+(.+)/);\n\n if (checkedMatch?.[1]) {\n results.push({ criterion: checkedMatch[1].trim(), passed: true });\n } else if (uncheckedMatch?.[1]) {\n results.push({ criterion: uncheckedMatch[1].trim(), passed: false });\n }\n }\n\n return results;\n } catch {\n return [];\n }\n}\n\nasync function loadExistingReport(dir: string): Promise<RunReport | null> {\n try {\n const raw = await readFile(join(dir, 'run-report.json'), 'utf-8');\n return JSON.parse(raw) as RunReport;\n } catch {\n return null;\n }\n}\n\nfunction hashString(s: string): string {\n let hash = 0;\n for (let i = 0; i < s.length; i++) {\n const char = s.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return String(hash);\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Searches the SpecMarket registry with full-text search and rich filtering.\n *\n * No authentication required.\n * Displays results in a table: name, description, replaces, success rate, avg cost, rating.\n *\n * Supported filters (all passed through to the Convex specs.search query):\n * - outputType: exact match on spec output type\n * - tags: OR semantics — spec must have at least one matching tag\n * - primaryStack: exact match on tech stack\n * - replacesSaas: case-insensitive substring match on the SaaS name\n * - minSuccessRate: minimum success rate (0-100, converted to 0-1 for backend)\n * - maxCost: maximum one-time build cost in USD\n * - maxMonthlyCost: maximum monthly infrastructure cost in USD\n * - serviceCategory: required infrastructure service categories (AND semantics)\n * - freeTierOnly: only show specs runnable on free-tier infrastructure\n * - limit: max results (default 20, max 50)\n */\nexport async function handleSearch(\n query: string,\n opts: {\n outputType?: string;\n tag?: string[];\n primaryStack?: string;\n replacesSaas?: string;\n minSuccessRate?: string;\n maxCost?: string;\n maxMonthlyCost?: string;\n serviceCategory?: string[];\n freeTierOnly?: boolean;\n limit?: string;\n }\n): Promise<void> {\n const client = await getConvexClient();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n\n const spinner = (await import('ora')).default('Searching...').start();\n\n try {\n // Build search params, converting CLI values to backend types\n const searchParams: Record<string, unknown> = {\n query,\n limit: opts.limit ? parseInt(opts.limit, 10) : 20,\n };\n\n if (opts.outputType) {\n searchParams.outputType = opts.outputType;\n }\n if (opts.tag && opts.tag.length > 0) {\n searchParams.tags = opts.tag;\n }\n if (opts.primaryStack) {\n searchParams.primaryStack = opts.primaryStack;\n }\n if (opts.replacesSaas) {\n searchParams.replacesSaas = opts.replacesSaas;\n }\n if (opts.minSuccessRate) {\n // CLI accepts 0-100 (e.g. \"80\" for 80%), backend expects 0-1\n const rate = parseFloat(opts.minSuccessRate);\n if (isNaN(rate) || rate < 0 || rate > 100) {\n spinner.fail(chalk.red('--min-success-rate must be between 0 and 100'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n searchParams.minSuccessRate = rate / 100;\n }\n if (opts.maxCost) {\n const cost = parseFloat(opts.maxCost);\n if (isNaN(cost) || cost < 0) {\n spinner.fail(chalk.red('--max-cost must be a non-negative number'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n searchParams.maxEstimatedCostUsd = cost;\n }\n if (opts.maxMonthlyCost) {\n const cost = parseFloat(opts.maxMonthlyCost);\n if (isNaN(cost) || cost < 0) {\n spinner.fail(chalk.red('--max-monthly-cost must be a non-negative number'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n searchParams.maxMonthlyCostUsd = cost;\n }\n if (opts.serviceCategory && opts.serviceCategory.length > 0) {\n searchParams.serviceCategories = opts.serviceCategory;\n }\n if (opts.freeTierOnly) {\n searchParams.freeTierOnly = true;\n }\n\n const results = await client.query(api.specs.search, searchParams);\n\n spinner.stop();\n\n if (results.length === 0) {\n console.log(chalk.gray(`No specs found for \"${query}\"`));\n return;\n }\n\n console.log(chalk.bold(`\\nFound ${results.length} spec(s) for \"${query}\":\\n`));\n\n const table = new Table({\n head: [\n chalk.cyan('Name'),\n chalk.cyan('Description'),\n chalk.cyan('Replaces'),\n chalk.cyan('Success'),\n chalk.cyan('Avg Cost'),\n chalk.cyan('Rating'),\n ],\n style: { compact: true },\n colWidths: [25, 35, 15, 9, 10, 8],\n wordWrap: true,\n });\n\n for (const spec of results) {\n table.push([\n chalk.bold(spec.scopedName),\n spec.description.slice(0, 80),\n spec.replacesSaas ?? '—',\n spec.successRate > 0\n ? `${(spec.successRate * 100).toFixed(0)}%`\n : chalk.gray('N/A'),\n spec.avgCostUsd > 0 ? `$${spec.avgCostUsd.toFixed(2)}` : chalk.gray('N/A'),\n spec.communityRating > 0\n ? `${spec.communityRating.toFixed(1)}★`\n : chalk.gray('N/A'),\n ]);\n }\n\n console.log(table.toString());\n console.log(chalk.gray(`\\nRun ${chalk.cyan('specmarket info <spec-id>')} for detailed information.`));\n } catch (err) {\n spinner.fail(chalk.red(`Search failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\nexport function createSearchCommand(): Command {\n return new Command('search')\n .description('Search the SpecMarket registry for specs')\n .argument('<query>', 'Search query')\n .option(\n '-t, --output-type <type>',\n 'Filter by output type (web-app, cli-tool, api-service, library, mobile-app)'\n )\n .option(\n '--tag <tag>',\n 'Filter by tag (repeatable, OR logic)',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\n '--primary-stack <stack>',\n 'Filter by tech stack (nextjs-typescript, astro-typescript, python-fastapi, go, rust, other)'\n )\n .option(\n '--replaces-saas <name>',\n 'Filter by SaaS product being replaced (substring match)'\n )\n .option(\n '--min-success-rate <percent>',\n 'Minimum success rate (0-100)'\n )\n .option(\n '--max-cost <usd>',\n 'Maximum one-time build cost in USD'\n )\n .option(\n '--max-monthly-cost <usd>',\n 'Maximum monthly infrastructure cost in USD'\n )\n .option(\n '--service-category <category>',\n 'Required infrastructure category (repeatable, AND logic)',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\n '--free-tier-only',\n 'Only show specs runnable on free-tier infrastructure'\n )\n .option('-l, --limit <n>', 'Maximum results to show (default: 20)')\n .action(async (query: string, opts) => {\n try {\n await handleSearch(query, opts);\n } catch (err) {\n console.error(chalk.red(`Search failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Displays detailed information about a spec from the registry.\n * Includes: metrics, recent runs, creator profile, versions, forks, infrastructure summary.\n */\nexport async function handleInfo(specId: string): Promise<void> {\n const client = await getConvexClient();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n\n const spinner = (await import('ora')).default(`Loading info for ${specId}...`).start();\n\n try {\n // Determine if it's a scoped name or an ID\n const isScopedName = specId.startsWith('@') || specId.includes('/');\n\n const [spec, stats, versionsResult] = await Promise.all([\n client.query(api.specs.get, isScopedName ? { scopedName: specId } : { specId }),\n client.query(api.runs.getStats, { specId: specId as any }).catch(() => null),\n client.query(api.specs.getVersions, { specId: specId as any, paginationOpts: { numItems: 25, cursor: null } }).catch(() => ({ page: [] })),\n ]);\n const versions = versionsResult.page;\n\n // Fetch collaboration data (best-effort — don't fail if these aren't available)\n let openIssueCount = 0;\n let maintainers: Array<{ user: { username: string } | null }> = [];\n let commentCount = 0;\n\n if (spec) {\n const [issuesResult, maintainersResult, commentsResult] = await Promise.all([\n client\n .query(api.issues.list, {\n specId: spec._id,\n status: 'open' as const,\n paginationOpts: { numItems: 1, cursor: null },\n })\n .catch(() => null),\n client\n .query(api.specMaintainers.list, { specId: spec._id })\n .catch(() => []),\n client\n .query(api.comments.list, {\n targetType: 'spec' as const,\n targetId: spec._id,\n paginationOpts: { numItems: 1, cursor: null },\n })\n .catch(() => null),\n ]);\n\n // issues.list returns paginated results — use page length as approximation\n // For accurate count we'd need a dedicated count query, but this shows \"at least N\"\n if (issuesResult) {\n openIssueCount = issuesResult.page.length;\n if (!issuesResult.isDone && openIssueCount > 0) {\n // There are more pages — indicate \"N+\"\n openIssueCount = -1; // sentinel for \"many\"\n }\n }\n maintainers = maintainersResult;\n if (commentsResult) {\n commentCount = commentsResult.page.length;\n if (!commentsResult.isDone && commentCount > 0) {\n commentCount = -1; // sentinel for \"many\"\n }\n }\n }\n\n spinner.stop();\n\n if (!spec) {\n console.log(chalk.red(`Spec not found: ${specId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Get author profile\n const author = await client\n .query(api.users.getProfile, { userId: spec.authorId })\n .catch(() => null);\n\n console.log('');\n console.log(chalk.bold(`${spec.displayName} ${chalk.gray(spec.scopedName)}`));\n console.log(chalk.gray('─'.repeat(60)));\n console.log(spec.description);\n console.log('');\n\n if (spec.replacesSaas) {\n console.log(\n `${chalk.bold('Replaces:')} ${spec.replacesSaas}${spec.replacesPricing ? ` (${spec.replacesPricing})` : ''}`\n );\n }\n\n console.log(`${chalk.bold('Output Type:')} ${spec.outputType}`);\n console.log(`${chalk.bold('Stack:')} ${spec.primaryStack}`);\n console.log(`${chalk.bold('Version:')} ${spec.currentVersion}`);\n console.log(`${chalk.bold('Runner:')} ${spec.runner} (min: ${spec.minModel})`);\n console.log(`${chalk.bold('Status:')} ${spec.status}`);\n if (spec.tags.length > 0) {\n console.log(`${chalk.bold('Tags:')} ${spec.tags.join(', ')}`);\n }\n\n console.log('');\n console.log(chalk.bold('Estimates:'));\n console.log(` Tokens: ~${spec.estimatedTokens.toLocaleString()}`);\n console.log(` Cost: ~$${spec.estimatedCostUsd.toFixed(2)}`);\n console.log(` Time: ~${spec.estimatedTimeMinutes} minutes`);\n\n console.log('');\n console.log(chalk.bold('Community Metrics:'));\n console.log(\n ` Total Runs: ${spec.totalRuns.toLocaleString()} (${spec.successfulRuns} successful)`\n );\n console.log(\n ` Success Rate: ${spec.totalRuns > 0 ? (spec.successRate * 100).toFixed(1) + '%' : 'N/A'}`\n );\n console.log(\n ` Avg Cost: ${spec.avgCostUsd > 0 ? '$' + spec.avgCostUsd.toFixed(2) : 'N/A'}`\n );\n console.log(\n ` Community Rating: ${spec.communityRating > 0 ? spec.communityRating.toFixed(1) + '/5 (' + spec.ratingCount + ' ratings)' : 'No ratings yet'}`\n );\n console.log(` Forks: ${spec.forkCount}`);\n\n if (spec.forkedFromId) {\n console.log(chalk.gray(` (Forked from v${spec.forkedFromVersion})`));\n }\n\n // Collaboration info\n const issueDisplay =\n openIssueCount === -1 ? 'many' : String(openIssueCount);\n const commentDisplay =\n commentCount === -1 ? 'many' : String(commentCount);\n console.log(\n ` Open Issues: ${issueDisplay}`\n );\n console.log(\n ` Comments: ${commentDisplay}`\n );\n if (maintainers.length > 0) {\n const names = maintainers\n .filter((m) => m.user)\n .map((m) => `@${m.user!.username}`)\n .join(', ');\n console.log(` Maintainers: ${names}`);\n }\n\n if (author) {\n console.log('');\n console.log(chalk.bold('Creator:'));\n console.log(` @${author.username} (${author.displayName})`);\n if (author.bio) console.log(` ${author.bio}`);\n if (author.githubUrl) console.log(` GitHub: ${author.githubUrl}`);\n }\n\n // Infrastructure summary\n if (spec.infrastructure) {\n const infra = spec.infrastructure;\n console.log('');\n console.log(chalk.bold('Infrastructure:'));\n console.log(\n ` Monthly Cost: Free tier $${infra.monthlyCost.freeTierUsd}/mo → Production $${infra.monthlyCost.productionUsd}/mo`\n );\n if (infra.setupTimeMinutes) {\n console.log(` Setup Time: ~${infra.setupTimeMinutes} minutes`);\n }\n if (infra.deploymentTargets && infra.deploymentTargets.length > 0) {\n console.log(\n ` Deploy to: ${infra.deploymentTargets.map((t: { name: string; notes?: string }) => t.notes ? `${t.name} (${t.notes})` : t.name).join(', ')}`\n );\n }\n if (infra.services.length > 0) {\n console.log(` Services:`);\n for (const svc of infra.services) {\n const defaultProvider = svc.defaultProvider\n ? ` (default: ${svc.defaultProvider})`\n : '';\n const required = svc.required ? '' : ' [optional]';\n console.log(\n ` • ${svc.name} (${svc.category})${required} — ${svc.purpose}${defaultProvider}`\n );\n }\n }\n if (infra.userProvided.length > 0) {\n console.log(` User-provided: ${infra.userProvided.join(', ')}`);\n }\n }\n\n // Version history\n if (versions.length > 0) {\n console.log('');\n console.log(chalk.bold(`Versions (${versions.length}):`));\n for (const v of versions.slice(0, 5)) {\n const date = new Date(v.publishedAt).toLocaleDateString();\n console.log(` v${v.version} — ${date}${v.changelog ? ': ' + v.changelog.slice(0, 60) : ''}`);\n }\n if (versions.length > 5) {\n console.log(chalk.gray(` ... and ${versions.length - 5} more`));\n }\n }\n\n // Run stats summary\n if (stats && stats.totalRuns > 0) {\n console.log('');\n console.log(chalk.bold('Run Statistics:'));\n if (stats.modelBreakdown.length > 0) {\n const topModel = stats.modelBreakdown.sort((a: any, b: any) => b.count - a.count)[0];\n console.log(\n ` Most used model: ${topModel.model} (${(topModel.percentage * 100).toFixed(0)}% of runs)`\n );\n }\n console.log(\n ` Cost range: $${stats.costDistribution.min.toFixed(2)} - $${stats.costDistribution.max.toFixed(2)} (median $${stats.costDistribution.p50.toFixed(2)})`\n );\n }\n\n console.log('');\n console.log(\n chalk.cyan(`Run this spec: ${chalk.bold(`specmarket run ${spec.scopedName}`)}`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to load spec info: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\nexport function createInfoCommand(): Command {\n return new Command('info')\n .description('Show detailed information about a spec')\n .argument('<spec-id>', 'Spec scoped name (@user/name) or document ID')\n .action(async (specId: string) => {\n try {\n await handleInfo(specId);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { readFile } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { createWriteStream } from 'fs';\nimport { specYamlSchema, EXIT_CODES, transformInfrastructure } from '@specmarket/shared';\nimport { validateSpec } from './validate.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\n\n/**\n * Publishes a spec to the SpecMarket registry.\n *\n * Flow:\n * 1. Require authentication\n * 2. Validate spec (exit 1 if invalid)\n * 3. Check for name conflicts via specs.get\n * 4. Zip the spec directory using archiver\n * 5. Upload zip to Convex file storage via generateUploadUrl\n * 6. Call specs.publish mutation with all metadata + changelog\n * 7. Show success message with URL\n */\nexport async function handlePublish(specPath: string, opts: { changelog?: string } = {}): Promise<void> {\n const creds = await requireAuth();\n const dir = resolve(specPath);\n\n const spinner = ora('Validating spec...').start();\n\n try {\n // Validate\n const validation = await validateSpec(dir);\n if (!validation.valid) {\n spinner.fail(chalk.red('Spec validation failed:'));\n for (const err of validation.errors) {\n console.log(chalk.red(` ✗ ${err}`));\n }\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n if (validation.warnings.length > 0) {\n spinner.warn(chalk.yellow(`Validation passed with ${validation.warnings.length} warning(s)`));\n } else {\n spinner.succeed('Spec validated');\n }\n\n // Load spec.yaml\n spinner.start('Reading spec metadata...');\n const specYamlContent = await readFile(join(dir, 'spec.yaml'), 'utf-8');\n const specYamlRaw = parseYaml(specYamlContent);\n const specYaml = specYamlSchema.parse(specYamlRaw);\n spinner.succeed(`Loaded spec: ${specYaml.display_name} v${specYaml.version}`);\n\n // Get Convex client\n const client = await getConvexClient(creds.token);\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error('Could not load Convex API bindings. Is CONVEX_URL configured?');\n }\n\n // Zip the spec directory\n spinner.start('Creating spec archive...');\n const zipPath = await createSpecZip(dir);\n spinner.succeed('Spec archive created');\n\n // Upload to Convex storage via the generateUploadUrl mutation\n spinner.start('Uploading spec to registry...');\n const uploadUrl: string = await client.mutation(api.specs.generateUploadUrl, {});\n\n const zipContent = await readFile(zipPath);\n const uploadResponse = await fetch(uploadUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/zip' },\n body: zipContent,\n });\n\n if (!uploadResponse.ok) {\n throw new Error(`Upload failed: ${uploadResponse.statusText}`);\n }\n\n const { storageId } = await uploadResponse.json() as { storageId: string };\n spinner.succeed('Spec uploaded');\n\n // Publish to registry\n spinner.start('Publishing to registry...');\n\n const readme = await readFile(join(dir, 'SPEC.md'), 'utf-8').catch(() => undefined);\n\n const publishResult = await client.mutation(api.specs.publish, {\n slug: specYaml.name,\n displayName: specYaml.display_name,\n description: specYaml.description,\n replacesSaas: specYaml.replaces_saas,\n replacesPricing: specYaml.replaces_pricing,\n tags: specYaml.tags,\n outputType: specYaml.output_type,\n primaryStack: specYaml.primary_stack,\n version: specYaml.version,\n specStorageId: storageId,\n readme,\n runner: specYaml.runner,\n minModel: specYaml.min_model,\n estimatedTokens: specYaml.estimated_tokens,\n estimatedCostUsd: specYaml.estimated_cost_usd,\n estimatedTimeMinutes: specYaml.estimated_time_minutes,\n infrastructure: specYaml.infrastructure\n ? transformInfrastructure(specYaml.infrastructure)\n : undefined,\n changelog: opts.changelog,\n });\n\n spinner.succeed(\n chalk.green(\n publishResult.created\n ? `Published successfully!`\n : `Updated successfully!`\n )\n );\n\n console.log('');\n console.log(chalk.bold('Published:'));\n console.log(` Spec ID: ${chalk.gray(publishResult.specId)}`);\n console.log(` Version: ${specYaml.version}`);\n console.log(` Run it: ${chalk.cyan(`specmarket run @${creds.username}/${specYaml.name}`)}`);\n\n // Cleanup temp zip\n const { unlink } = await import('fs/promises');\n await unlink(zipPath).catch(() => {});\n } catch (err) {\n spinner.fail(chalk.red(`Publish failed: ${(err as Error).message}`));\n throw err;\n }\n}\n\nasync function createSpecZip(dir: string): Promise<string> {\n const { tmpdir } = await import('os');\n const { randomUUID } = await import('crypto');\n const zipPath = join(tmpdir(), `spec-${randomUUID()}.zip`);\n\n const archiver = (await import('archiver')).default;\n const output = createWriteStream(zipPath);\n const archive = archiver('zip', { zlib: { level: 9 } });\n\n await new Promise<void>((resolve, reject) => {\n output.on('close', resolve);\n archive.on('error', reject);\n\n archive.pipe(output);\n archive.glob('**/*', {\n cwd: dir,\n ignore: ['node_modules/**', 'dist/**', '.git/**', '*.tsbuildinfo'],\n });\n archive.finalize();\n });\n\n return zipPath;\n}\n\nexport function createPublishCommand(): Command {\n return new Command('publish')\n .description('Publish a spec to the SpecMarket registry (requires login)')\n .argument('<path>', 'Path to the spec directory')\n .option('-c, --changelog <message>', 'Changelog message describing what changed in this version')\n .action(async (specPath: string, opts: { changelog?: string }) => {\n try {\n await handlePublish(specPath, opts);\n } catch (err) {\n console.error(chalk.red(`Publish failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { mkdir, writeFile, readFile } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport { requireAuth } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Forks a published spec to a local directory and records the fork in Convex.\n *\n * Flow:\n * 1. Require authentication\n * 2. Fetch spec metadata via specs.get\n * 3. Download the spec zip via specs.download\n * 4. Extract to local directory\n * 5. Update spec.yaml with forked_from_id and forked_from_version\n * 6. Call specs.fork mutation to record the fork relationship\n */\nexport async function handleFork(\n specId: string,\n targetPath?: string\n): Promise<void> {\n const creds = await requireAuth();\n const spinner = ora('Loading spec info...').start();\n\n try {\n const client = await getConvexClient(creds.token);\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error('Could not load Convex API bindings.');\n }\n\n // Determine if scopedName or ID\n const isScopedName = specId.startsWith('@') || specId.includes('/');\n\n // Fetch spec metadata\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: specId } : { specId }\n );\n\n if (!spec) {\n spinner.fail(chalk.red(`Spec not found: ${specId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n spinner.text = `Downloading ${spec.displayName}...`;\n\n // Download the spec zip\n const { url } = await client.action(api.specs.download, {\n specId: spec._id,\n });\n\n const targetDir = resolve(targetPath ?? spec.slug);\n\n spinner.text = `Extracting to ${targetDir}...`;\n\n // Download and extract\n await downloadAndExtract(url, targetDir);\n\n // Update spec.yaml to record fork relationship\n const specYamlPath = join(targetDir, 'spec.yaml');\n const specYamlContent = await readFile(specYamlPath, 'utf-8');\n const specYamlData = parseYaml(specYamlContent) as Record<string, unknown>;\n\n specYamlData['forked_from_id'] = spec._id;\n specYamlData['forked_from_version'] = spec.currentVersion;\n // Reset version for the fork\n specYamlData['version'] = '1.0.0';\n\n await writeFile(specYamlPath, stringifyYaml(specYamlData));\n\n // Record fork in Convex (but we need a storage ID for the forked content)\n // The fork mutation in Convex requires a specStorageId\n // For now, we record the fork intent locally and note it needs to be published\n spinner.succeed(\n chalk.green(`Forked ${chalk.bold(spec.scopedName)} to ${chalk.bold(targetDir)}`)\n );\n\n console.log('');\n console.log(chalk.bold('Fork created locally:'));\n console.log(` Source: ${spec.scopedName} @ v${spec.currentVersion}`);\n console.log(` Local path: ${targetDir}`);\n console.log(` Fork version: 1.0.0`);\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Customize the spec in ${chalk.cyan(targetDir)}`);\n console.log(` 2. ${chalk.cyan(`specmarket validate ${targetDir}`)} to validate changes`);\n console.log(` 3. ${chalk.cyan(`specmarket publish ${targetDir}`)} to publish your fork`);\n console.log('');\n console.log(chalk.gray('(Publishing will record the fork relationship on the platform)'));\n } catch (err) {\n spinner.fail(chalk.red(`Fork failed: ${(err as Error).message}`));\n throw err;\n }\n}\n\nasync function downloadAndExtract(url: string, targetDir: string): Promise<void> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Download failed: ${response.statusText}`);\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n\n // Write zip to temp file then extract\n const { tmpdir } = await import('os');\n const { randomUUID } = await import('crypto');\n const zipPath = join(tmpdir(), `fork-${randomUUID()}.zip`);\n\n const { writeFile: writeFileFn, unlink } = await import('fs/promises');\n await writeFileFn(zipPath, buffer);\n\n await mkdir(targetDir, { recursive: true });\n\n // Extract using unzip (cross-platform via node:child_process)\n const { execAsync } = await import('../lib/exec.js');\n await execAsync(`unzip -q \"${zipPath}\" -d \"${targetDir}\"`);\n await unlink(zipPath).catch(() => {});\n}\n\nexport function createForkCommand(): Command {\n return new Command('fork')\n .description('Fork a published spec to a local directory')\n .argument('<spec-id>', 'Spec scoped name (@user/name) or document ID')\n .argument('[path]', 'Target local directory (defaults to spec slug)')\n .action(async (specId: string, targetPath: string | undefined) => {\n try {\n await handleFork(specId, targetPath);\n } catch (err) {\n console.error(chalk.red(`Fork failed: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { readFile } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { CONFIG_PATHS, EXIT_CODES } from '@specmarket/shared';\nimport { loadCredentials } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport type { RunReport } from '@specmarket/shared';\n\n/**\n * Displays a run report.\n *\n * Priority:\n * 1. Local run artifacts at ~/.specmarket/runs/<run-id>/run-report.json\n * 2. If authenticated, fetch from Convex platform via runs.getById\n *\n * Displays: status, loops, tokens, cost, time, success criteria results, metadata.\n */\nexport async function handleReport(runId: string): Promise<void> {\n // Try local first\n const localPath = join(homedir(), CONFIG_PATHS.RUNS_DIR, runId, 'run-report.json');\n let report: RunReport | null = null;\n let source: 'local' | 'platform' = 'local';\n\n try {\n const raw = await readFile(localPath, 'utf-8');\n report = JSON.parse(raw) as RunReport;\n source = 'local';\n } catch {\n // Not found locally — try platform\n const creds = await loadCredentials();\n if (!creds) {\n console.error(\n chalk.red(\n `Run report not found locally at ~/.specmarket/runs/${runId}/. ` +\n `Log in with \\`specmarket login\\` to fetch from the platform.`\n )\n );\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n\n try {\n const client = await getConvexClient(creds.token);\n const api = (await import('@specmarket/convex/api')).api;\n const run = await client.query(api.runs.getById, { runId: runId as any });\n\n if (!run) {\n console.error(chalk.red(`Run not found: ${runId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Map Convex run document to RunReport interface\n report = {\n runId: run._id,\n specId: run.specId,\n specVersion: run.specVersion,\n model: run.model,\n runner: run.runner,\n loopCount: run.loopCount,\n totalTokens: run.totalTokens,\n totalCostUsd: run.totalCostUsd,\n totalTimeMinutes: run.totalTimeMinutes,\n status: run.status,\n successCriteriaResults: run.successCriteriaResults,\n os: run.os,\n nodeVersion: run.nodeVersion,\n cliVersion: run.cliVersion,\n };\n source = 'platform';\n } catch (err) {\n console.error(chalk.red(`Failed to fetch run from platform: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n }\n\n if (!report) {\n console.error(chalk.red(`Run not found: ${runId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Display report\n const statusColor =\n report.status === 'success'\n ? chalk.green\n : report.status === 'stall' || report.status === 'budget_exceeded'\n ? chalk.yellow\n : chalk.red;\n\n console.log('');\n console.log(chalk.bold(`Run Report ${chalk.gray(`[${source}]`)}`));\n console.log(chalk.gray('─'.repeat(50)));\n console.log(`${chalk.bold('Run ID:')} ${report.runId}`);\n console.log(`${chalk.bold('Status:')} ${statusColor(report.status.toUpperCase())}`);\n if (report.specId) {\n console.log(`${chalk.bold('Spec:')} ${report.specId}`);\n }\n console.log(`${chalk.bold('Version:')} ${report.specVersion}`);\n console.log(`${chalk.bold('Model:')} ${report.model}`);\n console.log(`${chalk.bold('Loops:')} ${report.loopCount}`);\n console.log(`${chalk.bold('Tokens:')} ${report.totalTokens.toLocaleString()}`);\n console.log(`${chalk.bold('Cost:')} $${report.totalCostUsd.toFixed(4)}`);\n console.log(`${chalk.bold('Time:')} ${report.totalTimeMinutes.toFixed(1)} minutes`);\n console.log(`${chalk.bold('CLI:')} v${report.cliVersion}`);\n\n if (report.os || report.nodeVersion) {\n console.log(`${chalk.bold('System:')} ${[report.os, report.nodeVersion].filter(Boolean).join(' / ')}`);\n }\n\n if (report.successCriteriaResults.length > 0) {\n console.log('');\n console.log(chalk.bold('Success Criteria:'));\n const passed = report.successCriteriaResults.filter((r) => r.passed).length;\n const total = report.successCriteriaResults.length;\n console.log(chalk.gray(` ${passed}/${total} criteria passed`));\n for (const criterion of report.successCriteriaResults) {\n const icon = criterion.passed ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${icon} ${criterion.criterion}`);\n if (criterion.details) {\n console.log(chalk.gray(` ${criterion.details}`));\n }\n }\n }\n\n if (source === 'local') {\n console.log('');\n console.log(\n chalk.gray(\n `Full artifacts: ~/.specmarket/runs/${runId}/`\n )\n );\n }\n}\n\nexport function createReportCommand(): Command {\n return new Command('report')\n .description('Display a run report (local or from platform)')\n .argument('<run-id>', 'Run ID (local UUID or Convex document ID)')\n .action(async (runId: string) => {\n try {\n await handleReport(runId);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadConfig, saveConfig } from '../lib/config.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\nimport type { CliConfig } from '@specmarket/shared';\n\n/**\n * CLI configuration management.\n *\n * Subcommands:\n * - config set telemetry true|false\n * - config set default-model <model>\n * - config get <key>\n * - config list\n * - config delete-telemetry (SECURITY.md: delete all user telemetry data from platform)\n */\n\nexport async function handleConfigSet(\n key: string,\n value: string\n): Promise<void> {\n const config = await loadConfig();\n\n switch (key) {\n case 'telemetry': {\n if (value !== 'true' && value !== 'false') {\n console.error(chalk.red('telemetry must be \"true\" or \"false\"'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n config.telemetry = value === 'true';\n await saveConfig(config);\n console.log(\n chalk.green(\n `Telemetry ${config.telemetry ? chalk.bold('enabled') : chalk.bold('disabled')}.`\n )\n );\n if (config.telemetry) {\n console.log(\n chalk.gray(\n 'Run metadata (tokens, cost, status) will be submitted after authenticated runs. No source code is ever sent.'\n )\n );\n }\n break;\n }\n\n case 'default-model': {\n config.defaultModel = value;\n await saveConfig(config);\n console.log(chalk.green(`Default model set to: ${chalk.bold(value)}`));\n break;\n }\n\n case 'convex-url': {\n config.convexUrl = value;\n await saveConfig(config);\n console.log(chalk.green(`Convex URL set to: ${chalk.bold(value)}`));\n break;\n }\n\n default:\n console.error(\n chalk.red(\n `Unknown config key: \"${key}\". Valid keys: telemetry, default-model, convex-url`\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n}\n\nexport async function handleConfigGet(key: string): Promise<void> {\n const config = await loadConfig();\n const value = (config as Record<string, unknown>)[key];\n\n if (value === undefined) {\n console.log(chalk.gray(`${key}: (not set)`));\n } else {\n console.log(`${key}: ${chalk.bold(String(value))}`);\n }\n}\n\nexport async function handleConfigList(): Promise<void> {\n const config = await loadConfig();\n\n console.log(chalk.bold('Current configuration:'));\n console.log(` telemetry: ${config.telemetry ?? chalk.gray('(not set, default: false)')}`);\n console.log(\n ` default-model: ${config.defaultModel ?? chalk.gray('(not set, uses spec min_model)')}`\n );\n console.log(\n ` convex-url: ${config.convexUrl ?? chalk.gray('(not set, uses CONVEX_URL env or default)')}`\n );\n console.log('');\n console.log(chalk.gray('Config file: ~/.specmarket/config.json'));\n}\n\nexport async function handleDeleteTelemetry(): Promise<void> {\n const creds = await requireAuth();\n\n const { default: inquirer } = await import('inquirer');\n\n const { confirm } = await inquirer.prompt<{ confirm: boolean }>([\n {\n type: 'confirm',\n name: 'confirm',\n message:\n chalk.yellow(\n 'This will permanently delete ALL your run telemetry data from the SpecMarket platform. Are you sure?'\n ),\n default: false,\n },\n ]);\n\n if (!confirm) {\n console.log(chalk.gray('Cancelled.'));\n return;\n }\n\n const client = await getConvexClient(creds.token);\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error('Could not load Convex API bindings.');\n }\n\n const spinner = (await import('ora')).default('Deleting telemetry data...').start();\n\n try {\n const result = await client.mutation(api.runs.deleteForUser, {});\n spinner.succeed(\n chalk.green(`Deleted ${result.deleted} run report(s) from the platform.`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to delete telemetry: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\nexport function createConfigCommand(): Command {\n const configCmd = new Command('config').description(\n 'Manage CLI configuration at ~/.specmarket/config.json'\n );\n\n configCmd\n .command('set <key> <value>')\n .description('Set a configuration value (keys: telemetry, default-model)')\n .action(async (key: string, value: string) => {\n try {\n await handleConfigSet(key, value);\n } catch (err) {\n console.error(chalk.red(`Config error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n configCmd\n .command('get <key>')\n .description('Get a configuration value')\n .action(async (key: string) => {\n try {\n await handleConfigGet(key);\n } catch (err) {\n console.error(chalk.red(`Config error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n configCmd\n .command('list')\n .description('List all configuration values')\n .action(async () => {\n try {\n await handleConfigList();\n } catch (err) {\n console.error(chalk.red(`Config error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n configCmd\n .command('delete-telemetry')\n .description('Permanently delete all your run telemetry data from the platform')\n .action(async () => {\n try {\n await handleDeleteTelemetry();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n return configCmd;\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Loads the Convex API module. Exits on failure.\n */\nasync function loadApi(): Promise<any> {\n try {\n return (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Resolves a spec identifier (scoped name or ID) to a spec document.\n * Exits with VALIDATION_ERROR if not found.\n */\nasync function resolveSpec(client: any, api: any, specRef: string): Promise<any> {\n const isScopedName = specRef.startsWith('@') || specRef.includes('/');\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: specRef } : { specId: specRef }\n );\n if (!spec) {\n console.error(chalk.red(`Spec not found: ${specRef}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n return spec;\n}\n\n/**\n * Formats a relative time string from a timestamp (e.g., \"3 days ago\").\n */\nfunction relativeTime(timestamp: number): string {\n const diff = Date.now() - timestamp;\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ago`;\n if (hours > 0) return `${hours}h ago`;\n if (minutes > 0) return `${minutes}m ago`;\n return 'just now';\n}\n\n/**\n * Lists open issues for a spec in table format.\n * Public endpoint — no auth required.\n *\n * Flags: --status open|closed|all, --label <label>\n */\nexport async function handleIssuesList(\n specRef: string,\n opts: { status?: string; label?: string }\n): Promise<void> {\n const api = await loadApi();\n const client = await getConvexClient();\n const spinner = (await import('ora')).default('Loading issues...').start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const statusFilter =\n opts.status === 'all' ? undefined : (opts.status as 'open' | 'closed') ?? 'open';\n\n const result = await client.query(api.issues.list, {\n specId: spec._id,\n status: statusFilter,\n paginationOpts: { numItems: 50, cursor: null },\n });\n\n spinner.stop();\n\n let issues = result.page;\n\n // Client-side label filter (backend doesn't support it directly)\n if (opts.label) {\n const label = opts.label.toLowerCase();\n issues = issues.filter((i: any) =>\n i.labels.some((l: string) => l.toLowerCase() === label)\n );\n }\n\n if (issues.length === 0) {\n const statusLabel = statusFilter ?? 'any';\n console.log(chalk.gray(`No ${statusLabel} issues for ${spec.scopedName}`));\n return;\n }\n\n console.log(\n chalk.bold(`\\n${issues.length} issue(s) for ${spec.scopedName}:\\n`)\n );\n\n const table = new Table({\n head: [\n chalk.cyan('#'),\n chalk.cyan('Title'),\n chalk.cyan('Author'),\n chalk.cyan('Age'),\n chalk.cyan('Labels'),\n ],\n style: { compact: true },\n colWidths: [6, 40, 16, 10, 20],\n wordWrap: true,\n });\n\n for (const issue of issues) {\n const statusIcon = issue.status === 'open' ? chalk.green('●') : chalk.gray('○');\n table.push([\n `${statusIcon} ${issue.number}`,\n issue.title.slice(0, 60),\n issue.author ? `@${issue.author.username}` : chalk.gray('unknown'),\n relativeTime(issue.createdAt),\n issue.labels.length > 0 ? issue.labels.join(', ') : chalk.gray('—'),\n ]);\n }\n\n console.log(table.toString());\n console.log(\n chalk.gray(\n `\\nView: ${chalk.cyan(`specmarket issues ${specRef} <number>`)}`\n )\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to load issues: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Creates a new issue interactively (prompts for title and body).\n * Requires authentication.\n */\nexport async function handleIssuesCreate(specRef: string): Promise<void> {\n const creds = await requireAuth();\n const api = await loadApi();\n const client = await getConvexClient(creds.token);\n\n const spec = await resolveSpec(client, api, specRef);\n\n const { default: inquirer } = await import('inquirer');\n\n const answers = await inquirer.prompt<{ title: string; body: string }>([\n {\n type: 'input',\n name: 'title',\n message: 'Issue title:',\n validate: (v: string) => v.trim().length > 0 || 'Title cannot be empty',\n },\n {\n type: 'editor',\n name: 'body',\n message: 'Issue body (markdown):',\n validate: (v: string) => v.trim().length > 0 || 'Body cannot be empty',\n },\n ]);\n\n const spinner = (await import('ora')).default('Creating issue...').start();\n\n try {\n const result = await client.mutation(api.issues.create, {\n specId: spec._id,\n title: answers.title.trim(),\n body: answers.body.trim(),\n labels: [],\n });\n\n spinner.succeed(\n chalk.green(`Issue #${result.number} created on ${spec.scopedName}`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to create issue: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Displays a single issue with detail and recent comments.\n * Public endpoint — no auth required.\n */\nexport async function handleIssuesView(\n specRef: string,\n issueNumber: number\n): Promise<void> {\n const api = await loadApi();\n const client = await getConvexClient();\n const spinner = (await import('ora')).default(`Loading issue #${issueNumber}...`).start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n\n if (!issue) {\n spinner.fail(chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Fetch recent comments\n const commentsResult = await client.query(api.comments.list, {\n targetType: 'issue',\n targetId: issue._id,\n paginationOpts: { numItems: 10, cursor: null },\n });\n\n spinner.stop();\n\n const statusBadge =\n issue.status === 'open'\n ? chalk.green.bold(' OPEN ')\n : chalk.gray.bold(' CLOSED ');\n\n console.log('');\n console.log(\n `${statusBadge} ${chalk.bold(`#${issue.number}: ${issue.title}`)}`\n );\n console.log(chalk.gray('─'.repeat(60)));\n console.log(\n `${chalk.bold('Author:')} ${issue.author ? `@${issue.author.username}` : 'unknown'} ${chalk.bold('Created:')} ${new Date(issue.createdAt).toLocaleDateString()}`\n );\n if (issue.labels.length > 0) {\n console.log(`${chalk.bold('Labels:')} ${issue.labels.join(', ')}`);\n }\n if (issue.closedAt) {\n console.log(\n `${chalk.bold('Closed:')} ${new Date(issue.closedAt).toLocaleDateString()}`\n );\n }\n console.log('');\n console.log(issue.body);\n console.log('');\n\n // Comments\n if (commentsResult.page.length > 0) {\n console.log(\n chalk.bold(`Comments (${issue.commentCount}):`)\n );\n console.log(chalk.gray('─'.repeat(40)));\n\n for (const comment of commentsResult.page) {\n const author = comment.author\n ? `@${comment.author.username}`\n : 'unknown';\n const edited = comment.editedAt ? chalk.gray(' (edited)') : '';\n console.log(\n ` ${chalk.bold(author)} — ${relativeTime(comment.createdAt)}${edited}`\n );\n console.log(` ${comment.body}`);\n\n if (comment.replies && comment.replies.length > 0) {\n for (const reply of comment.replies) {\n const replyAuthor = reply.author\n ? `@${reply.author.username}`\n : 'unknown';\n const replyEdited = reply.editedAt ? chalk.gray(' (edited)') : '';\n console.log(\n ` ${chalk.bold(replyAuthor)} — ${relativeTime(reply.createdAt)}${replyEdited}`\n );\n console.log(` ${reply.body}`);\n }\n }\n console.log('');\n }\n } else {\n console.log(chalk.gray('No comments yet.'));\n }\n } catch (err) {\n spinner.fail(\n chalk.red(`Failed to load issue: ${(err as Error).message}`)\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Closes an issue. Requires authentication.\n * Authorized: issue author, spec author, or spec maintainer.\n */\nexport async function handleIssuesClose(\n specRef: string,\n issueNumber: number\n): Promise<void> {\n const creds = await requireAuth();\n const api = await loadApi();\n const client = await getConvexClient(creds.token);\n const spinner = (await import('ora')).default(`Closing issue #${issueNumber}...`).start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n\n if (!issue) {\n spinner.fail(chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n await client.mutation(api.issues.close, {\n issueId: issue._id,\n });\n\n spinner.succeed(\n chalk.green(`Issue #${issueNumber} closed on ${spec.scopedName}`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to close issue: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Reopens a closed issue. Requires authentication.\n * Authorized: issue author, spec author, or spec maintainer.\n */\nexport async function handleIssuesReopen(\n specRef: string,\n issueNumber: number\n): Promise<void> {\n const creds = await requireAuth();\n const api = await loadApi();\n const client = await getConvexClient(creds.token);\n const spinner = (await import('ora')).default(`Reopening issue #${issueNumber}...`).start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n\n if (!issue) {\n spinner.fail(chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n await client.mutation(api.issues.reopen, {\n issueId: issue._id,\n });\n\n spinner.succeed(\n chalk.green(`Issue #${issueNumber} reopened on ${spec.scopedName}`)\n );\n } catch (err) {\n spinner.fail(\n chalk.red(`Failed to reopen issue: ${(err as Error).message}`)\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Creates the `specmarket issues` command with subcommands.\n *\n * Usage:\n * specmarket issues @user/spec — list open issues\n * specmarket issues @user/spec create — create issue\n * specmarket issues @user/spec <number> — view issue\n * specmarket issues @user/spec <number> close — close issue\n * specmarket issues @user/spec <number> reopen — reopen issue\n */\nexport function createIssuesCommand(): Command {\n return new Command('issues')\n .description('Manage issues on a spec')\n .argument('<spec-id>', 'Spec scoped name (@user/name) or document ID')\n .argument('[action-or-number]', 'Issue number or \"create\"')\n .argument('[action]', '\"close\" or \"reopen\" (with issue number)')\n .option(\n '-s, --status <status>',\n 'Filter by status: open, closed, all (default: open)'\n )\n .option('--label <label>', 'Filter by label')\n .action(\n async (\n specId: string,\n actionOrNumber: string | undefined,\n action: string | undefined,\n opts: { status?: string; label?: string }\n ) => {\n try {\n if (!actionOrNumber) {\n // specmarket issues @user/spec → list\n await handleIssuesList(specId, opts);\n } else if (actionOrNumber === 'create') {\n // specmarket issues @user/spec create → create\n await handleIssuesCreate(specId);\n } else {\n const issueNumber = parseInt(actionOrNumber, 10);\n if (isNaN(issueNumber) || issueNumber < 1) {\n console.error(\n chalk.red(\n `Invalid issue number or action: \"${actionOrNumber}\". ` +\n 'Use a number or \"create\".'\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n if (!action) {\n // specmarket issues @user/spec 3 → view\n await handleIssuesView(specId, issueNumber);\n } else if (action === 'close') {\n // specmarket issues @user/spec 3 close → close\n await handleIssuesClose(specId, issueNumber);\n } else if (action === 'reopen') {\n // specmarket issues @user/spec 3 reopen → reopen\n await handleIssuesReopen(specId, issueNumber);\n } else {\n console.error(\n chalk.red(\n `Unknown action: \"${action}\". Use \"close\" or \"reopen\".`\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n }\n } catch (err) {\n const error = err as NodeJS.ErrnoException;\n if (error.code === String(EXIT_CODES.AUTH_ERROR)) {\n console.error(chalk.red(error.message));\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n console.error(chalk.red(`Error: ${error.message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n }\n );\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Posts a comment on a spec, issue, or bounty.\n *\n * Target reference formats:\n * - spec: @user/spec or specId\n * - issue: @user/spec#3 (scoped name + issue number)\n * - bounty: bountyId\n *\n * Requires authentication.\n */\nexport async function handleComment(\n targetType: string,\n targetRef: string,\n body: string,\n opts: { reply?: string }\n): Promise<void> {\n const creds = await requireAuth();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n\n const client = await getConvexClient(creds.token);\n const spinner = (await import('ora')).default('Posting comment...').start();\n\n try {\n let resolvedTargetType: 'spec' | 'bounty' | 'issue';\n let resolvedTargetId: string;\n\n if (targetType === 'spec') {\n resolvedTargetType = 'spec';\n const isScopedName = targetRef.startsWith('@') || targetRef.includes('/');\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: targetRef } : { specId: targetRef }\n );\n if (!spec) {\n spinner.fail(chalk.red(`Spec not found: ${targetRef}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n resolvedTargetId = spec._id;\n } else if (targetType === 'issue') {\n resolvedTargetType = 'issue';\n // Parse @user/spec#3 format\n const hashIndex = targetRef.lastIndexOf('#');\n if (hashIndex === -1) {\n spinner.fail(\n chalk.red(\n 'Invalid issue reference. Use format: @user/spec#<number>'\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n const specRef = targetRef.slice(0, hashIndex);\n const issueNumber = parseInt(targetRef.slice(hashIndex + 1), 10);\n\n if (isNaN(issueNumber) || issueNumber < 1) {\n spinner.fail(\n chalk.red(`Invalid issue number in \"${targetRef}\". Use format: @user/spec#<number>`)\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Resolve spec\n const isScopedName = specRef.startsWith('@') || specRef.includes('/');\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: specRef } : { specId: specRef }\n );\n if (!spec) {\n spinner.fail(chalk.red(`Spec not found: ${specRef}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Resolve issue\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n if (!issue) {\n spinner.fail(\n chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`)\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n resolvedTargetId = issue._id;\n } else if (targetType === 'bounty') {\n resolvedTargetType = 'bounty';\n resolvedTargetId = targetRef;\n } else {\n spinner.fail(\n chalk.red(\n `Invalid target type: \"${targetType}\". Use \"spec\", \"issue\", or \"bounty\".`\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n const args: Record<string, unknown> = {\n targetType: resolvedTargetType,\n targetId: resolvedTargetId,\n body: body.trim(),\n };\n\n if (opts.reply) {\n args.parentId = opts.reply;\n }\n\n await client.mutation(api.comments.create, args);\n\n spinner.succeed(chalk.green(`Comment posted on ${targetType} ${targetRef}`));\n } catch (err) {\n spinner.fail(chalk.red(`Failed to post comment: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Creates the `specmarket comment` command.\n *\n * Usage:\n * specmarket comment spec @user/spec \"Great spec!\"\n * specmarket comment issue @user/spec#3 \"I can reproduce this\"\n * specmarket comment bounty <bounty-id> \"I'm working on this\"\n * --reply <comment-id> Reply to a specific comment (threading)\n */\nexport function createCommentCommand(): Command {\n return new Command('comment')\n .description('Post a comment on a spec, issue, or bounty (requires login)')\n .argument(\n '<target-type>',\n 'Target type: spec, issue, or bounty'\n )\n .argument(\n '<target-ref>',\n 'Target reference (e.g., @user/spec, @user/spec#3, bounty-id)'\n )\n .argument('<body>', 'Comment body text')\n .option(\n '--reply <comment-id>',\n 'Reply to a specific comment (threading)'\n )\n .action(\n async (\n targetType: string,\n targetRef: string,\n body: string,\n opts: { reply?: string }\n ) => {\n try {\n await handleComment(targetType, targetRef, body, opts);\n } catch (err) {\n const error = err as NodeJS.ErrnoException;\n if (error.code === String(EXIT_CODES.AUTH_ERROR)) {\n console.error(chalk.red(error.message));\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n console.error(chalk.red(`Error: ${error.message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n }\n );\n}\n"],"mappings":"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","names":["createDebug","debug","createDebug","debug","api","resolve","Command","chalk","chalk","Command","Command","chalk","chalk","api","Command","Command","chalk","ora","mkdir","writeFile","join","createDebug","debug","answers","ora","mkdir","join","writeFile","chalk","Command","Command","chalk","readFile","readdir","access","join","resolve","parseYaml","readFile","join","join","readFile","readdir","join","readFile","resolve","access","parseYaml","Command","chalk","Command","chalk","ora","readFile","mkdir","join","resolve","parseYaml","createDebug","debug","saveConfig","mkdir","writeFile","readFile","access","join","homedir","createDebug","debug","join","homedir","mkdir","report","writeFile","resolve","readFile","access","createDebug","debug","chalk","readFile","join","parseYaml","ora","resolve","access","api","randomUUID","mkdir","execAsync","unlink","Command","Command","chalk","api","chalk","Command","Command","chalk","api","chalk","Command","Command","chalk","ora","readFile","join","resolve","parseYaml","resolve","ora","chalk","readFile","join","parseYaml","api","unlink","randomUUID","Command","Command","chalk","ora","mkdir","writeFile","readFile","join","resolve","parseYaml","ora","api","chalk","resolve","join","readFile","parseYaml","writeFile","randomUUID","writeFileFn","unlink","mkdir","execAsync","Command","Command","chalk","readFile","join","homedir","join","homedir","readFile","chalk","api","Command","Command","chalk","chalk","api","Command","Command","chalk","Table","chalk","api","Table","Command","Command","chalk","api","chalk","Command","createRequire","_require"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/lib/auth.ts","../src/lib/convex-client.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/commands/init.ts","../src/lib/format-detection.ts","../src/commands/validate.ts","../src/commands/run.ts","../src/lib/telemetry.ts","../src/lib/ralph-loop.ts","../src/lib/meta-instructions.ts","../src/commands/search.ts","../src/commands/info.ts","../src/commands/publish.ts","../src/commands/fork.ts","../src/commands/report.ts","../src/commands/config.ts","../src/commands/issues.ts","../src/commands/comment.ts"],"sourcesContent":["/**\n * SpecMarket CLI — Entry Point\n *\n * Registers all commands and sets up the Commander.js program.\n * Commands are registered from separate files for testability.\n */\nimport { program } from 'commander';\nimport { EXIT_CODES } from '@specmarket/shared';\nimport { createLoginCommand } from './commands/login.js';\nimport { createLogoutCommand } from './commands/logout.js';\nimport { createWhoamiCommand } from './commands/whoami.js';\nimport { createInitCommand } from './commands/init.js';\nimport { createValidateCommand } from './commands/validate.js';\nimport { createRunCommand } from './commands/run.js';\nimport { createSearchCommand } from './commands/search.js';\nimport { createInfoCommand } from './commands/info.js';\nimport { createPublishCommand } from './commands/publish.js';\nimport { createForkCommand } from './commands/fork.js';\nimport { createReportCommand } from './commands/report.js';\nimport { createConfigCommand } from './commands/config.js';\nimport { createIssuesCommand } from './commands/issues.js';\nimport { createCommentCommand } from './commands/comment.js';\nimport { createRequire } from 'module';\n\n// Dynamically read version from package.json so it stays in sync with npm publishes\nconst _require = createRequire(import.meta.url);\nconst { version: VERSION } = _require('../package.json');\n\nprogram\n .name('specmarket')\n .description(\n 'SpecMarket CLI — discover, validate, run, and publish AI specs\\n\\n' +\n 'Modes:\\n' +\n ' Authenticated: run `specmarket login` for telemetry and registry access\\n' +\n ' Anonymous: validate and run specs locally with no network calls'\n )\n .version(VERSION, '-v, --version', 'Print version number')\n .addHelpText(\n 'after',\n '\\nExamples:\\n' +\n ' $ specmarket init Create a new spec\\n' +\n ' $ specmarket validate ./my-spec Validate a spec\\n' +\n ' $ specmarket run ./my-spec Execute a spec locally\\n' +\n ' $ specmarket run @user/my-spec Run a registry spec\\n' +\n ' $ specmarket search \"notion clone\" Search the registry\\n' +\n ' $ specmarket info @user/my-spec View spec details\\n' +\n ' $ specmarket publish ./my-spec Publish to registry\\n' +\n ' $ specmarket login Authenticate\\n'\n );\n\n// Auth commands\nprogram.addCommand(createLoginCommand());\nprogram.addCommand(createLogoutCommand());\nprogram.addCommand(createWhoamiCommand());\n\n// Spec lifecycle\nprogram.addCommand(createInitCommand());\nprogram.addCommand(createValidateCommand());\nprogram.addCommand(createRunCommand());\n\n// Registry\nprogram.addCommand(createSearchCommand());\nprogram.addCommand(createInfoCommand());\nprogram.addCommand(createPublishCommand());\nprogram.addCommand(createForkCommand());\n\n// Collaboration\nprogram.addCommand(createIssuesCommand());\nprogram.addCommand(createCommentCommand());\n\n// Reporting & config\nprogram.addCommand(createReportCommand());\nprogram.addCommand(createConfigCommand());\n\n// Parse and execute\nprogram.parseAsync(process.argv).catch((err: Error) => {\n console.error(`Fatal error: ${err.message}`);\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n } else if (errCode === String(EXIT_CODES.NETWORK_ERROR)) {\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n});\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { EXIT_CODES, TOKEN_EXPIRY_MS, DEFAULT_WEB_URL } from '@specmarket/shared';\nimport { saveCredentials, loadCredentials } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport type { Credentials } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:auth');\n\n/** Maximum time to wait for device code approval before timing out */\nconst DEVICE_CODE_TIMEOUT_MS = 10 * 60 * 1000;\n\n/**\n * Handles the login flow.\n *\n * Two modes:\n * 1. --token <jwt>: Direct token injection (CI/headless use case)\n * 2. Interactive: Device code auth flow — generates a code, opens browser,\n * polls backend until the user approves the device on the web app.\n *\n * The device code flow works in headless/SSH environments because the user\n * can visit the URL on any device (phone, another computer) to authenticate.\n *\n * Tokens are stored in ~/.specmarket/credentials.json with 0600 permissions.\n */\nexport async function handleLogin(opts: { token?: string }): Promise<void> {\n // Already logged in?\n const existing = await loadCredentials();\n if (existing) {\n console.log(\n chalk.yellow(\n `Already logged in as ${chalk.bold(existing.username ?? 'unknown')}. ` +\n `Run ${chalk.cyan('specmarket logout')} first to switch accounts.`\n )\n );\n return;\n }\n\n if (opts.token) {\n await handleTokenLogin(opts.token);\n return;\n }\n\n await handleDeviceCodeLogin();\n}\n\nasync function handleTokenLogin(token: string): Promise<void> {\n const spinner = ora('Validating token...').start();\n\n try {\n const client = await getConvexClient(token);\n // Validate token by calling getMe\n const { api } = await import('@specmarket/convex/api').catch(() => ({\n api: null,\n }));\n\n let username: string | undefined;\n let userId: string | undefined;\n\n if (api) {\n try {\n const me = await client.query(api.users.getMe, {});\n username = me?.username;\n userId = me?._id;\n } catch {\n // API might not be reachable in dev\n debug('Could not validate token via getMe query');\n }\n }\n\n const creds: Credentials = {\n token,\n expiresAt: Date.now() + TOKEN_EXPIRY_MS,\n username,\n userId,\n };\n\n await saveCredentials(creds);\n\n spinner.succeed(\n chalk.green(\n `Logged in${username ? ` as ${chalk.bold(username)}` : ''}. Token stored in ~/.specmarket/credentials.json`\n )\n );\n } catch (err) {\n spinner.fail(chalk.red('Failed to validate token.'));\n throw err;\n }\n}\n\n/**\n * Implements the device-code auth flow:\n * 1. Call auth.createDeviceCode mutation to generate a code\n * 2. Display the code and URL to the user\n * 3. Attempt to open the browser\n * 4. Poll auth.checkDeviceCode every 2 seconds\n * 5. On approval: store the returned token\n * 6. On expiry/timeout: show error\n */\nasync function handleDeviceCodeLogin(): Promise<void> {\n const webUrl = DEFAULT_WEB_URL;\n const client = await getConvexClient();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n // Fallback: if API bindings unavailable, show manual instructions\n console.log(chalk.cyan('\\nSpecMarket Login'));\n console.log(chalk.gray('─────────────────────────────────────'));\n console.log('');\n console.log('To authenticate, visit the SpecMarket web app and copy your API token:');\n console.log('');\n console.log(chalk.bold(` ${webUrl}/settings/tokens`));\n console.log('');\n console.log('Then run:');\n console.log(chalk.cyan(' specmarket login --token <your-token>'));\n console.log('');\n console.log(chalk.gray('Alternatively, set SPECMARKET_TOKEN in your environment.'));\n return;\n }\n\n // Step 1: Generate device code\n const spinner = ora('Generating device code...').start();\n let deviceCode: { code: string; expiresAt: number; pollIntervalMs: number };\n\n try {\n deviceCode = await client.mutation(api.auth.createDeviceCode, {});\n } catch (err) {\n spinner.fail(chalk.red('Failed to generate device code. Is the backend reachable?'));\n debug('createDeviceCode failed: %O', err);\n // Fallback to manual instructions\n console.log('');\n console.log('You can authenticate manually:');\n console.log(chalk.cyan(' specmarket login --token <your-token>'));\n return;\n }\n\n spinner.stop();\n\n // Step 2: Display the code and URL\n const deviceUrl = `${webUrl}/device`;\n console.log('');\n console.log(chalk.cyan('SpecMarket Login'));\n console.log(chalk.gray('─────────────────────────────────────'));\n console.log('');\n console.log(` Visit: ${chalk.bold(deviceUrl)}`);\n console.log(` Code: ${chalk.bold.cyan(deviceCode.code)}`);\n console.log('');\n console.log(chalk.gray(' Log in on the web and enter the code above to authorize this device.'));\n console.log(chalk.gray(` Code expires in 10 minutes.`));\n console.log('');\n\n // Step 3: Try to open browser\n try {\n const open = (await import('open')).default;\n await open(deviceUrl);\n debug('Opened browser to %s', deviceUrl);\n } catch {\n debug('Could not open browser (headless environment)');\n }\n\n // Step 4: Poll for approval\n const pollSpinner = ora('Waiting for authorization...').start();\n const startTime = Date.now();\n const pollInterval = deviceCode.pollIntervalMs || 2000;\n\n while (Date.now() - startTime < DEVICE_CODE_TIMEOUT_MS) {\n await sleep(pollInterval);\n\n try {\n const result = await client.query(api.auth.checkDeviceCode, {\n code: deviceCode.code,\n });\n\n if (result.status === 'approved') {\n // Success!\n const creds: Credentials = {\n token: result.token,\n expiresAt: Date.now() + TOKEN_EXPIRY_MS,\n username: result.username,\n userId: result.userId,\n };\n\n await saveCredentials(creds);\n\n pollSpinner.succeed(\n chalk.green(\n `Logged in as ${chalk.bold(result.username ?? 'unknown')}. Token stored in ~/.specmarket/credentials.json`\n )\n );\n return;\n }\n\n if (result.status === 'expired') {\n pollSpinner.fail(chalk.red('Device code expired. Please try again.'));\n return;\n }\n\n // Still pending — continue polling\n } catch (err) {\n debug('Poll error (non-fatal): %O', err);\n // Network hiccup — keep polling\n }\n }\n\n pollSpinner.fail(chalk.red('Login timed out. Please try again.'));\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function createLoginCommand(): Command {\n return new Command('login')\n .description('Authenticate with SpecMarket')\n .option('--token <token>', 'Use a pre-existing token (for CI/headless environments)')\n .action(async (opts) => {\n try {\n await handleLogin(opts);\n } catch (err) {\n console.error(chalk.red(`Login failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n });\n}\n","import { readFile, writeFile, unlink, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type { Credentials } from '@specmarket/shared';\nimport { CONFIG_PATHS, TOKEN_EXPIRY_MS, EXIT_CODES } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:auth');\n\nfunction getCredentialsPath(): string {\n return join(homedir(), CONFIG_PATHS.CREDENTIALS);\n}\n\nfunction getConfigDir(): string {\n return join(homedir(), CONFIG_PATHS.DIR);\n}\n\n/**\n * Loads stored credentials from ~/.specmarket/credentials.json.\n * Returns null if the file doesn't exist, is malformed, or the token is expired.\n */\nexport async function loadCredentials(): Promise<Credentials | null> {\n try {\n const raw = await readFile(getCredentialsPath(), 'utf-8');\n const creds = JSON.parse(raw) as Credentials;\n\n if (!creds.token) {\n debug('Credentials file exists but has no token');\n return null;\n }\n\n // Check expiry\n if (creds.expiresAt && Date.now() > creds.expiresAt) {\n debug('Credentials expired at %d', creds.expiresAt);\n await clearCredentials();\n return null;\n }\n\n debug('Credentials loaded for user %s', creds.username ?? 'unknown');\n return creds;\n } catch {\n debug('No credentials file found');\n return null;\n }\n}\n\n/**\n * Saves credentials to ~/.specmarket/credentials.json.\n * Creates the directory if it doesn't exist.\n */\nexport async function saveCredentials(creds: Credentials): Promise<void> {\n await mkdir(getConfigDir(), { recursive: true });\n await writeFile(\n getCredentialsPath(),\n JSON.stringify(creds, null, 2),\n { encoding: 'utf-8', mode: 0o600 } // 600 = owner read/write only\n );\n debug('Credentials saved for user %s', creds.username ?? 'unknown');\n}\n\n/**\n * Deletes the credentials file (logout).\n */\nexport async function clearCredentials(): Promise<void> {\n try {\n await unlink(getCredentialsPath());\n debug('Credentials cleared');\n } catch {\n debug('No credentials file to clear');\n }\n}\n\n/**\n * Returns credentials if authenticated, or throws with exit code 5.\n * Use this in commands that require authentication.\n */\nexport async function requireAuth(): Promise<Credentials> {\n const creds = await loadCredentials();\n if (!creds) {\n const err = new Error(\n 'Not authenticated. Run `specmarket login` to authenticate.'\n );\n (err as NodeJS.ErrnoException).code = String(EXIT_CODES.AUTH_ERROR);\n throw err;\n }\n return creds;\n}\n\n/**\n * Returns true if the user is currently authenticated with a valid token.\n */\nexport async function isAuthenticated(): Promise<boolean> {\n const creds = await loadCredentials();\n return creds !== null;\n}\n","import { ConvexHttpClient } from 'convex/browser';\nimport { loadConfig } from './config.js';\nimport { DEFAULT_CONVEX_URL } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:convex');\n\n/**\n * Returns a ConvexHttpClient configured with the deployment URL and optional auth token.\n * The URL is resolved from (in priority order):\n * 1. CONVEX_URL environment variable\n * 2. config.json convexUrl field\n * 3. DEFAULT_CONVEX_URL constant\n *\n * If a token is provided, it's set as the auth token for authenticated mutations.\n */\nexport async function getConvexClient(token?: string): Promise<ConvexHttpClient> {\n const config = await loadConfig();\n const url =\n process.env['CONVEX_URL'] ??\n config.convexUrl ??\n DEFAULT_CONVEX_URL;\n\n if (url.includes('placeholder.convex.cloud')) {\n throw new Error(\n 'CONVEX_URL is not configured. Set the CONVEX_URL environment variable or run `specmarket config set convexUrl <url>`.'\n );\n }\n\n debug('Creating Convex client for URL: %s', url);\n const client = new ConvexHttpClient(url);\n\n if (token) {\n client.setAuth(token);\n debug('Convex client authenticated');\n }\n\n return client;\n}\n\n/**\n * Returns an authenticated ConvexHttpClient using stored credentials.\n * Returns unauthenticated client if no credentials exist.\n */\nexport async function getAuthenticatedClient(token?: string): Promise<ConvexHttpClient> {\n return getConvexClient(token);\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { clearCredentials, loadCredentials } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Clears stored credentials from ~/.specmarket/credentials.json.\n */\nexport async function handleLogout(): Promise<void> {\n const creds = await loadCredentials();\n if (!creds) {\n console.log(chalk.yellow('You are not currently logged in.'));\n return;\n }\n\n await clearCredentials();\n console.log(\n chalk.green(\n `Logged out${creds.username ? ` (was: ${chalk.bold(creds.username)})` : ''}. Credentials cleared.`\n )\n );\n}\n\nexport function createLogoutCommand(): Command {\n return new Command('logout')\n .description('Log out from SpecMarket and clear stored credentials')\n .action(async () => {\n try {\n await handleLogout();\n } catch (err) {\n console.error(chalk.red(`Logout failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadCredentials } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Displays the currently authenticated user, or \"not logged in\".\n */\nexport async function handleWhoami(): Promise<void> {\n const creds = await loadCredentials();\n if (!creds) {\n console.log(chalk.gray('Not logged in. Run `specmarket login` to authenticate.'));\n return;\n }\n\n // Try to fetch fresh profile from Convex\n try {\n const { api } = await import('@specmarket/convex/api');\n const client = await getConvexClient(creds.token);\n const me = await client.query(api.users.getMe, {});\n\n if (me) {\n console.log(chalk.green('Authenticated as:'));\n console.log(` ${chalk.bold('Username:')} @${me.username}`);\n console.log(` ${chalk.bold('Display Name:')} ${me.displayName}`);\n console.log(` ${chalk.bold('Role:')} ${me.role}`);\n console.log(` ${chalk.bold('Specs Published:')} ${me.totalSpecsPublished}`);\n console.log(` ${chalk.bold('Reputation Score:')} ${me.reputationScore}`);\n if (creds.expiresAt) {\n const expiresIn = Math.floor((creds.expiresAt - Date.now()) / 1000 / 60 / 60 / 24);\n console.log(` ${chalk.bold('Token Expires In:')} ${expiresIn} days`);\n }\n return;\n }\n } catch {\n // Convex unavailable — fall back to cached info\n }\n\n // Fall back to cached credential info\n console.log(chalk.green('Authenticated (cached):'));\n console.log(` ${chalk.bold('Username:')} @${creds.username ?? 'unknown'}`);\n if (creds.expiresAt) {\n const expiresDate = new Date(creds.expiresAt).toLocaleDateString();\n console.log(` ${chalk.bold('Token Expires:')} ${expiresDate}`);\n }\n}\n\nexport function createWhoamiCommand(): Command {\n return new Command('whoami')\n .description('Show the currently authenticated user')\n .action(async () => {\n try {\n await handleWhoami();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { mkdir, writeFile, readdir } from 'fs/promises';\nimport { join, resolve, basename } from 'path';\nimport { EXIT_CODES, SIDECAR_FILENAME } from '@specmarket/shared';\nimport createDebug from 'debug';\nimport { detectSpecFormat, fileExists, directoryExists } from '../lib/format-detection.js';\n\nconst debug = createDebug('specmarket:cli');\n\ntype MetadataData = {\n displayName: string;\n description: string;\n replacesSaas?: string;\n outputType: string;\n primaryStack: string;\n};\n\n/** Build specmarket.yaml for any spec format (single source of truth for validate/publish) */\nfunction buildSpecmarketYaml(data: MetadataData & { specFormat: string }): string {\n return `# SpecMarket metadata (required for validate/publish)\n# Single source of truth for format and marketplace fields.\n# Your existing spec files (Spec Kit, BMAD, Ralph, etc.) are not modified.\n\nspec_format: ${data.specFormat}\ndisplay_name: \"${data.displayName.replace(/\"/g, '\\\\\"')}\"\ndescription: \"${data.description.replace(/\"/g, '\\\\\"')}\"\noutput_type: ${data.outputType}\nprimary_stack: ${data.primaryStack}\n${data.replacesSaas ? `replaces_saas: \"${data.replacesSaas.replace(/\"/g, '\\\\\"')}\"` : '# replaces_saas: \"ProductName\"'}\n# replaces_pricing: \"$0-16/mo\"\ntags: []\nestimated_tokens: 50000\nestimated_cost_usd: 2.50\nestimated_time_minutes: 30\n`;\n}\n\n/** specmarket.yaml for new SpecMarket (classic) specs */\nconst SPECMARKET_YAML_TEMPLATE = (data: {\n displayName: string;\n replacesSaas?: string;\n outputType: string;\n primaryStack: string;\n}) => buildSpecmarketYaml({\n ...data,\n specFormat: 'specmarket',\n description: `A ${data.outputType} spec${data.replacesSaas ? ` that replaces ${data.replacesSaas}` : ''}.`,\n});\n\nconst SPEC_YAML_TEMPLATE = (data: {\n name: string;\n displayName: string;\n replacesSaas?: string;\n outputType: string;\n primaryStack: string;\n}) => `# SpecMarket Spec Configuration\n# See: https://specmarket.dev/docs/spec-yaml\n\nname: ${data.name}\ndisplay_name: \"${data.displayName}\"\ndescription: \"A ${data.outputType} spec${data.replacesSaas ? ` that replaces ${data.replacesSaas}` : ''}.\"\n${data.replacesSaas ? `replaces_saas: \"${data.replacesSaas}\"` : '# replaces_saas: \"SaaSProductName\"'}\n# replaces_pricing: \"$0-16/mo\"\n\noutput_type: ${data.outputType}\nprimary_stack: ${data.primaryStack}\nversion: \"1.0.0\"\nrunner: claude\nmin_model: \"claude-opus-4-5\"\n\nestimated_tokens: 50000\nestimated_cost_usd: 2.50\nestimated_time_minutes: 30\n\ntags: []\n\ninfrastructure:\n monthly_cost:\n free_tier_usd: 0\n production_usd: 0\n services: []\n # Example service:\n # - category: database\n # name: PostgreSQL\n # purpose: Primary data store\n # required: true\n # providers:\n # - name: Neon\n # free_tier: true\n # paid_starts_usd: 19\n # default_provider: Neon\n # setup_notes: Run migrations with \\`npm run db:push\\`\n user_provided: []\n setup_time_minutes: 15\n deployment_targets:\n - name: Vercel\n notes: Recommended for Next.js and Astro apps\n - name: Railway\n notes: General-purpose cloud hosting\n`;\n\nconst PROMPT_MD_TEMPLATE = (data: { displayName: string }) => `# ${data.displayName}\n\nYou are building ${data.displayName}. Read SPEC.md for full requirements.\n\n## Your Task\n\nRead the requirements in SPEC.md and implement the application step by step.\n\n## Process\n\n1. Read SPEC.md completely before writing any code\n2. Check TASKS.md for outstanding items\n3. Implement features, run tests, iterate\n4. Update TASKS.md as you complete items\n5. Verify SUCCESS_CRITERIA.md criteria are met\n\n## Rules\n\n- Follow stdlib/STACK.md for technology choices\n- Write tests for all business logic\n- Do not skip steps or take shortcuts\n- Update TASKS.md after each significant change\n`;\n\nconst SPEC_MD_TEMPLATE = (data: { displayName: string }) => `# ${data.displayName} — Specification\n\n## Overview\n\nDescribe what this application does and why it's useful.\n\n## Core Features\n\n- Feature 1: Description\n- Feature 2: Description\n- Feature 3: Description\n\n## Data Model\n\nDescribe the key entities and their relationships.\n\n## API / Interface\n\nDescribe the public interface (routes, commands, exports).\n\n## Non-Goals\n\nWhat this spec explicitly does NOT build.\n`;\n\nconst SUCCESS_CRITERIA_TEMPLATE = `# Success Criteria\n\nThe implementation is complete when ALL of the following are true:\n\n- [ ] Application builds without errors\n- [ ] All tests pass\n- [ ] Core feature 1 works end-to-end\n- [ ] Core feature 2 works end-to-end\n- [ ] README.md documents setup and usage\n`;\n\nconst STACK_MD_TEMPLATE = (primaryStack: string) => `# Stack Requirements\n\n## Primary Stack\n\n${primaryStack}\n\n## Required Tools\n\n- Node.js >= 20\n- pnpm (preferred) or npm\n\n## Code Style\n\n- TypeScript strict mode, no \\`any\\`\n- ESM modules\n- Functional components (React)\n- Async/await over callbacks\n\n## Testing\n\n- Vitest for unit tests\n- Playwright for E2E (optional)\n`;\n\nconst TASKS_MD_TEMPLATE = (displayName: string) => `# Tasks\n\n> This file tracks outstanding work. Update it after each change.\n> All items checked = implementation complete.\n\n## Phase 1: ${displayName} — Initial Implementation\n\n- [ ] Set up project structure and dependencies\n- [ ] Implement core data model\n- [ ] Implement core business logic\n- [ ] Write unit tests\n- [ ] Implement UI/interface\n- [ ] Write integration tests\n- [ ] Update README.md\n\n## Discovered Issues\n`;\n\n/** Prompt for marketplace metadata only (used when adding sidecar to existing spec) */\nasync function promptMetadataOnly(defaultDisplayName?: string): Promise<MetadataData> {\n const { default: inquirer } = await import('inquirer');\n const answers = await inquirer.prompt<{\n displayName: string;\n description: string;\n replacesSaas: string;\n outputType: string;\n primaryStack: string;\n }>([\n {\n type: 'input',\n name: 'displayName',\n message: 'Display name for the marketplace:',\n default: defaultDisplayName ?? 'My Spec',\n },\n {\n type: 'input',\n name: 'description',\n message: 'Short description (min 10 characters):',\n default: 'A spec ready to validate and publish on SpecMarket.',\n validate: (v: string) => (v.length >= 10 ? true : 'Description must be at least 10 characters'),\n },\n {\n type: 'input',\n name: 'replacesSaas',\n message: 'What SaaS product does this replace? (optional, Enter to skip):',\n default: '',\n },\n {\n type: 'list',\n name: 'outputType',\n message: 'Output type:',\n choices: [\n { name: 'Web Application', value: 'web-app' },\n { name: 'CLI Tool', value: 'cli-tool' },\n { name: 'API Service', value: 'api-service' },\n { name: 'Library/Package', value: 'library' },\n { name: 'Mobile App', value: 'mobile-app' },\n ],\n },\n {\n type: 'list',\n name: 'primaryStack',\n message: 'Primary stack:',\n choices: [\n { name: 'Next.js + TypeScript', value: 'nextjs-typescript' },\n { name: 'Astro + TypeScript', value: 'astro-typescript' },\n { name: 'Python + FastAPI', value: 'python-fastapi' },\n { name: 'Go', value: 'go' },\n { name: 'Rust', value: 'rust' },\n { name: 'Other', value: 'other' },\n ],\n },\n ]);\n return {\n displayName: answers.displayName,\n description: answers.description,\n replacesSaas: answers.replacesSaas || undefined,\n outputType: answers.outputType,\n primaryStack: answers.primaryStack,\n };\n}\n\n/** Returns true if directory exists and has at least one file (not just subdirs). */\nasync function dirHasFiles(dir: string): Promise<boolean> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.some((e) => e.isFile());\n } catch {\n return false;\n }\n}\n\nexport async function handleInit(opts: {\n name?: string;\n path?: string;\n from?: string;\n}): Promise<void> {\n const { default: inquirer } = await import('inquirer');\n\n // --from: strict import-only mode. Errors if directory doesn't exist or has no spec files.\n if (opts.from !== undefined && opts.from !== '') {\n const targetDir = resolve(opts.from);\n\n const dirExists = await directoryExists(targetDir);\n if (!dirExists) {\n console.error(chalk.red(`Directory not found: ${targetDir}`));\n console.error(chalk.gray('--from requires an existing spec directory. Run specmarket init (no flags) to create a new spec from scratch.'));\n process.exit(EXIT_CODES.INVALID_SPEC);\n }\n\n const hasAnyFiles = await dirHasFiles(targetDir);\n if (!hasAnyFiles) {\n console.error(chalk.red(`Directory is empty: ${targetDir}`));\n console.error(chalk.gray('--from requires a directory with spec files (Spec Kit, BMAD, Ralph, or custom markdown). Run specmarket init to create a new spec.'));\n process.exit(EXIT_CODES.INVALID_SPEC);\n }\n\n const sidecarPath = join(targetDir, SIDECAR_FILENAME);\n if (await fileExists(sidecarPath)) {\n console.log(chalk.yellow(`${SIDECAR_FILENAME} already exists in this directory.`));\n console.log(chalk.gray('Run specmarket validate to check your spec, then specmarket publish to publish.'));\n return;\n }\n\n const detection = await detectSpecFormat(targetDir);\n const formatLabel =\n detection.format === 'specmarket'\n ? 'SpecMarket (spec.yaml + PROMPT.md + …)'\n : detection.format === 'speckit'\n ? 'Spec Kit'\n : detection.format === 'bmad'\n ? 'BMAD'\n : detection.format === 'ralph'\n ? 'Ralph'\n : 'custom markdown';\n console.log(chalk.gray(`Detected ${formatLabel} spec. Adding SpecMarket metadata only; your files will not be modified.`));\n console.log('');\n\n const metadata = await promptMetadataOnly(basename(targetDir));\n const yaml = buildSpecmarketYaml({ ...metadata, specFormat: detection.format });\n await writeFile(sidecarPath, yaml);\n\n console.log('');\n console.log(chalk.green(`Added ${SIDECAR_FILENAME} to ${targetDir}`));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Run ${chalk.cyan('specmarket validate')} to check your spec`);\n console.log(` 2. Run ${chalk.cyan('specmarket publish')} to publish to the marketplace`);\n console.log(` 3. Run ${chalk.cyan('specmarket run')} to execute the spec locally`);\n return;\n }\n\n // When -p/--path is set, we're initializing in an existing directory (safe add-sidecar flow)\n if (opts.path !== undefined && opts.path !== '') {\n const targetDir = resolve(opts.path);\n await mkdir(targetDir, { recursive: true });\n\n const sidecarPath = join(targetDir, SIDECAR_FILENAME);\n if (await fileExists(sidecarPath)) {\n console.log(chalk.yellow(`${SIDECAR_FILENAME} already exists in this directory.`));\n console.log(chalk.gray('Run specmarket validate to check your spec, then specmarket publish to publish.'));\n return;\n }\n\n const detection = await detectSpecFormat(targetDir);\n const hasAnyFiles = await dirHasFiles(targetDir);\n\n if (hasAnyFiles && detection.format !== 'custom') {\n // Recognized format (specmarket, speckit, bmad, ralph): add sidecar only, no overwrites\n const formatLabel =\n detection.format === 'specmarket'\n ? 'SpecMarket (spec.yaml + PROMPT.md + …)'\n : detection.format === 'speckit'\n ? 'Spec Kit'\n : detection.format === 'bmad'\n ? 'BMAD'\n : detection.format === 'ralph'\n ? 'Ralph'\n : detection.format;\n console.log(chalk.gray(`Detected ${formatLabel} spec. Adding SpecMarket metadata only; your files will not be modified.`));\n console.log('');\n\n const metadata = await promptMetadataOnly(basename(targetDir));\n const yaml = buildSpecmarketYaml({\n ...metadata,\n specFormat: detection.format,\n });\n await writeFile(sidecarPath, yaml);\n\n console.log('');\n console.log(chalk.green(`Added ${SIDECAR_FILENAME} to ${targetDir}`));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Run ${chalk.cyan('specmarket validate')} to check your spec`);\n console.log(` 2. Run ${chalk.cyan('specmarket publish')} to publish to the marketplace`);\n console.log(` 3. Run ${chalk.cyan('specmarket run')} to execute the spec locally`);\n return;\n }\n\n if (hasAnyFiles && detection.format === 'custom') {\n // Custom (e.g. random .md): still add sidecar so they can validate/publish\n console.log(chalk.gray('Detected markdown spec. Adding SpecMarket metadata only; your files will not be modified.'));\n console.log('');\n const metadata = await promptMetadataOnly(basename(targetDir));\n const yaml = buildSpecmarketYaml({\n ...metadata,\n specFormat: 'custom',\n });\n await writeFile(sidecarPath, yaml);\n console.log('');\n console.log(chalk.green(`Added ${SIDECAR_FILENAME} to ${targetDir}`));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Run ${chalk.cyan('specmarket validate')} to check your spec`);\n console.log(` 2. Run ${chalk.cyan('specmarket publish')} to publish to the marketplace`);\n return;\n }\n\n // Empty directory: offer to create from scratch\n console.log(chalk.gray('Directory is empty or has no recognized spec format.'));\n const { createNew } = await inquirer.prompt<{ createNew: boolean }>([\n {\n type: 'confirm',\n name: 'createNew',\n message: 'Create a new SpecMarket spec from scratch here?',\n default: true,\n },\n ]);\n if (!createNew) {\n console.log(chalk.gray('Exiting. Add spec files (e.g. Spec Kit, BMAD) and run specmarket init -p . again.'));\n return;\n }\n const spinner = ora(`Creating spec at ${targetDir}...`).start();\n const fullAnswers = await inquirer.prompt<{\n name: string;\n displayName: string;\n replacesSaas: string;\n outputType: string;\n primaryStack: string;\n }>([\n { type: 'input', name: 'name', message: 'Spec name (lowercase, hyphens only):', default: opts.name ?? (basename(targetDir) || 'my-spec'), validate: (v: string) => /^[a-z0-9-]+$/.test(v) || 'Must be lowercase alphanumeric with hyphens' },\n { type: 'input', name: 'displayName', message: 'Display name:', default: (a: { name: string }) => a.name.split('-').map((w) => w[0]?.toUpperCase() + w.slice(1)).join(' ') },\n { type: 'input', name: 'replacesSaas', message: 'What SaaS product does this replace? (optional):', default: '' },\n { type: 'list', name: 'outputType', message: 'Output type:', choices: [\n { name: 'Web Application', value: 'web-app' },\n { name: 'CLI Tool', value: 'cli-tool' },\n { name: 'API Service', value: 'api-service' },\n { name: 'Library/Package', value: 'library' },\n { name: 'Mobile App', value: 'mobile-app' },\n ]},\n { type: 'list', name: 'primaryStack', message: 'Primary stack:', choices: [\n { name: 'Next.js + TypeScript', value: 'nextjs-typescript' },\n { name: 'Astro + TypeScript', value: 'astro-typescript' },\n { name: 'Python + FastAPI', value: 'python-fastapi' },\n { name: 'Go', value: 'go' },\n { name: 'Rust', value: 'rust' },\n { name: 'Other', value: 'other' },\n ]},\n ]);\n const data = {\n name: fullAnswers.name,\n displayName: fullAnswers.displayName,\n replacesSaas: fullAnswers.replacesSaas || undefined,\n outputType: fullAnswers.outputType,\n primaryStack: fullAnswers.primaryStack,\n };\n await mkdir(join(targetDir, 'stdlib'), { recursive: true });\n await Promise.all([\n writeFile(sidecarPath, SPECMARKET_YAML_TEMPLATE(data)),\n writeFile(join(targetDir, 'spec.yaml'), SPEC_YAML_TEMPLATE(data)),\n writeFile(join(targetDir, 'PROMPT.md'), PROMPT_MD_TEMPLATE(data)),\n writeFile(join(targetDir, 'SPEC.md'), SPEC_MD_TEMPLATE(data)),\n writeFile(join(targetDir, 'SUCCESS_CRITERIA.md'), SUCCESS_CRITERIA_TEMPLATE),\n writeFile(join(targetDir, 'stdlib', 'STACK.md'), STACK_MD_TEMPLATE(fullAnswers.primaryStack)),\n writeFile(join(targetDir, 'TASKS.md'), TASKS_MD_TEMPLATE(fullAnswers.displayName)),\n ]);\n spinner.succeed(chalk.green(`Spec created at ${targetDir}`));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Edit ${chalk.cyan('SPEC.md')} with your application requirements`);\n console.log(` 2. Edit ${chalk.cyan('SUCCESS_CRITERIA.md')} with pass/fail criteria`);\n console.log(` 3. Run ${chalk.cyan('specmarket validate')} then ${chalk.cyan('specmarket run')}`);\n return;\n }\n\n // No path: create new directory (or add sidecar if that directory already exists with content)\n const answers = await inquirer.prompt<{\n name: string;\n displayName: string;\n replacesSaas: string;\n outputType: string;\n primaryStack: string;\n }>([\n {\n type: 'input',\n name: 'name',\n message: 'Spec name (lowercase, hyphens only):',\n default: opts.name ?? 'my-spec',\n validate: (v: string) =>\n /^[a-z0-9-]+$/.test(v) || 'Must be lowercase alphanumeric with hyphens',\n },\n {\n type: 'input',\n name: 'displayName',\n message: 'Display name:',\n default: (ans: { name: string }) =>\n ans.name.split('-').map((w) => w[0]?.toUpperCase() + w.slice(1)).join(' '),\n },\n {\n type: 'input',\n name: 'replacesSaas',\n message: 'What SaaS product does this replace? (optional, press Enter to skip):',\n default: '',\n },\n {\n type: 'list',\n name: 'outputType',\n message: 'Output type:',\n choices: [\n { name: 'Web Application', value: 'web-app' },\n { name: 'CLI Tool', value: 'cli-tool' },\n { name: 'API Service', value: 'api-service' },\n { name: 'Library/Package', value: 'library' },\n { name: 'Mobile App', value: 'mobile-app' },\n ],\n },\n {\n type: 'list',\n name: 'primaryStack',\n message: 'Primary stack:',\n choices: [\n { name: 'Next.js + TypeScript', value: 'nextjs-typescript' },\n { name: 'Astro + TypeScript', value: 'astro-typescript' },\n { name: 'Python + FastAPI', value: 'python-fastapi' },\n { name: 'Go', value: 'go' },\n { name: 'Rust', value: 'rust' },\n { name: 'Other', value: 'other' },\n ],\n },\n ]);\n\n const targetDir = resolve(answers.name);\n const spinner = ora(`Creating spec directory at ${targetDir}...`).start();\n\n try {\n await mkdir(targetDir, { recursive: true });\n\n const sidecarPath = join(targetDir, SIDECAR_FILENAME);\n if (await fileExists(sidecarPath)) {\n spinner.stop();\n console.log(chalk.yellow(`${SIDECAR_FILENAME} already exists in ${targetDir}.`));\n console.log(chalk.gray('Run specmarket validate to check your spec, then specmarket publish to publish.'));\n return;\n }\n\n const hasFiles = await dirHasFiles(targetDir);\n if (hasFiles) {\n const detection = await detectSpecFormat(targetDir);\n spinner.stop();\n console.log(chalk.gray(`Directory already has files (detected: ${detection.format}). Adding ${SIDECAR_FILENAME} only; no files overwritten.`));\n const metadata: MetadataData = {\n displayName: answers.displayName,\n description: `A ${answers.outputType} spec${answers.replacesSaas ? ` that replaces ${answers.replacesSaas}` : ''}.`,\n replacesSaas: answers.replacesSaas || undefined,\n outputType: answers.outputType,\n primaryStack: answers.primaryStack,\n };\n const yaml = buildSpecmarketYaml({ ...metadata, specFormat: detection.format });\n await writeFile(sidecarPath, yaml);\n console.log('');\n console.log(chalk.green(`Added ${SIDECAR_FILENAME} to ${targetDir}`));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Run ${chalk.cyan('specmarket validate')} to check your spec`);\n console.log(` 2. Run ${chalk.cyan('specmarket publish')} to publish to the marketplace`);\n return;\n }\n\n await mkdir(join(targetDir, 'stdlib'), { recursive: true });\n const data = {\n name: answers.name,\n displayName: answers.displayName,\n replacesSaas: answers.replacesSaas || undefined,\n outputType: answers.outputType,\n primaryStack: answers.primaryStack,\n };\n\n await Promise.all([\n writeFile(sidecarPath, SPECMARKET_YAML_TEMPLATE(data)),\n writeFile(join(targetDir, 'spec.yaml'), SPEC_YAML_TEMPLATE(data)),\n writeFile(join(targetDir, 'PROMPT.md'), PROMPT_MD_TEMPLATE(data)),\n writeFile(join(targetDir, 'SPEC.md'), SPEC_MD_TEMPLATE(data)),\n writeFile(join(targetDir, 'SUCCESS_CRITERIA.md'), SUCCESS_CRITERIA_TEMPLATE),\n writeFile(join(targetDir, 'stdlib', 'STACK.md'), STACK_MD_TEMPLATE(answers.primaryStack)),\n writeFile(join(targetDir, 'TASKS.md'), TASKS_MD_TEMPLATE(answers.displayName)),\n ]);\n\n spinner.succeed(chalk.green(`Spec created at ${targetDir}`));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. ${chalk.cyan(`cd ${answers.name}`)}`);\n console.log(` 2. Edit ${chalk.cyan('SPEC.md')} with your application requirements`);\n console.log(` 3. Edit ${chalk.cyan('SUCCESS_CRITERIA.md')} with specific pass/fail criteria`);\n console.log(` 4. Run ${chalk.cyan('specmarket validate')} to check your spec`);\n console.log(` 5. Run ${chalk.cyan('specmarket run')} to execute the spec`);\n } catch (err) {\n spinner.fail(chalk.red(`Failed to create spec: ${(err as Error).message}`));\n throw err;\n }\n}\n\nexport function createInitCommand(): Command {\n return new Command('init')\n .description(\n 'Create a new SpecMarket spec or add specmarket.yaml to an existing spec (Spec Kit, BMAD, Ralph). Use -p . to init in current directory without overwriting existing files.'\n )\n .option('-n, --name <name>', 'Spec name (skip prompt)')\n .option('-p, --path <path>', 'Target directory (e.g. . or ./my-spec). When set, detects existing format and adds only specmarket.yaml if present; no files overwritten.')\n .option('--from <path>', 'Import an existing spec directory (Spec Kit, BMAD, Ralph, or custom markdown). Detects format and adds specmarket.yaml metadata sidecar without modifying original files. Errors if the directory is missing or empty.')\n .action(async (opts) => {\n try {\n await handleInit(opts);\n } catch (err) {\n console.error(chalk.red(`Init failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { readFile, readdir, access } from 'fs/promises';\nimport { join } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { SIDECAR_FILENAME } from '@specmarket/shared';\nimport type { FormatDetectionResult } from '@specmarket/shared';\n\n/** Check if a file exists and is readable. */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Check if a directory exists and is readable. */\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n await access(dirPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Check if directory contains any story-*.md files (BMAD pattern). */\nexport async function hasStoryFiles(dir: string): Promise<boolean> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.some(\n (e) => e.isFile() && e.name.startsWith('story-') && e.name.endsWith('.md')\n );\n } catch {\n return false;\n }\n}\n\n/** Check if directory (non-recursive) or subdirs contain any .md files. */\nexport async function hasMarkdownFiles(dir: string): Promise<boolean> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.md')) return true;\n if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {\n const found = await hasMarkdownFiles(join(dir, entry.name));\n if (found) return true;\n }\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/** Read and parse specmarket.yaml; return spec_format if valid, else null. */\nexport async function tryReadSidecar(\n dir: string\n): Promise<{ spec_format: string } | null> {\n const path = join(dir, SIDECAR_FILENAME);\n if (!(await fileExists(path))) return null;\n try {\n const raw = await readFile(path, 'utf-8');\n const parsed = parseYaml(raw) as unknown;\n if (parsed && typeof parsed === 'object' && 'spec_format' in parsed) {\n const fmt = (parsed as { spec_format: unknown }).spec_format;\n if (typeof fmt === 'string' && fmt.length > 0) return { spec_format: fmt };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Detect spec format for a directory. Priority:\n * 1. Sidecar specmarket.yaml with spec_format → use that value, high confidence\n * 2. specmarket: spec.yaml + PROMPT.md + SUCCESS_CRITERIA.md\n * 3. speckit: spec.md + (plan.md | tasks.md) + .specify/ directory\n * 4. bmad: prd.md + (architecture.md | story-*.md)\n * 5. ralph: prd.json with userStories[] array\n * 6. custom: any .md files → low confidence\n * 7. Fallback: custom, low confidence\n */\nexport async function detectSpecFormat(dir: string): Promise<FormatDetectionResult> {\n const sidecar = await tryReadSidecar(dir);\n if (sidecar) {\n return {\n format: sidecar.spec_format,\n detectedBy: 'sidecar',\n confidence: 'high',\n };\n }\n\n const hasSpecYaml = await fileExists(join(dir, 'spec.yaml'));\n const hasPromptMd = await fileExists(join(dir, 'PROMPT.md'));\n const hasSuccessCriteria = await fileExists(join(dir, 'SUCCESS_CRITERIA.md'));\n if (hasSpecYaml && hasPromptMd && hasSuccessCriteria) {\n return {\n format: 'specmarket',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n if (hasPromptMd && hasSuccessCriteria) {\n return {\n format: 'specmarket',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n\n const hasSpecMd = await fileExists(join(dir, 'spec.md'));\n const hasPlanMd = await fileExists(join(dir, 'plan.md'));\n const hasTasksMd = await fileExists(join(dir, 'tasks.md'));\n if (hasSpecMd && (hasPlanMd || hasTasksMd)) {\n return {\n format: 'speckit',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n if (hasSpecMd) {\n return {\n format: 'speckit',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n\n const hasPrdMd = await fileExists(join(dir, 'prd.md'));\n const hasArchitectureMd = await fileExists(join(dir, 'architecture.md'));\n const storyFiles = await hasStoryFiles(dir);\n if (hasPrdMd && (hasArchitectureMd || storyFiles)) {\n return {\n format: 'bmad',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n\n const prdJsonPath = join(dir, 'prd.json');\n if (await fileExists(prdJsonPath)) {\n try {\n const raw = await readFile(prdJsonPath, 'utf-8');\n const data = JSON.parse(raw) as unknown;\n if (data && typeof data === 'object') {\n return {\n format: 'ralph',\n detectedBy: 'heuristic',\n confidence: 'high',\n };\n }\n } catch {\n // not valid JSON\n }\n }\n\n if (await hasMarkdownFiles(dir)) {\n return {\n format: 'custom',\n detectedBy: 'heuristic',\n confidence: 'low',\n };\n }\n\n return {\n format: 'custom',\n detectedBy: 'heuristic',\n confidence: 'low',\n };\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { readFile, readdir, access } from 'fs/promises';\nimport { join, resolve, relative, normalize } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport {\n specYamlSchema,\n specmarketSidecarSchema,\n EXIT_CODES,\n REQUIRED_SPEC_FILES,\n REQUIRED_STDLIB_FILES,\n SIDECAR_FILENAME,\n} from '@specmarket/shared';\nimport type { ValidationResult } from '@specmarket/shared';\nimport {\n fileExists,\n directoryExists,\n hasStoryFiles,\n hasMarkdownFiles,\n} from '../lib/format-detection.js';\n\n/**\n * Recursively collects file paths relative to baseDir, filtered by extension.\n */\nasync function collectFiles(\n currentDir: string,\n baseDir: string,\n extensions: Set<string>\n): Promise<string[]> {\n const results: string[] = [];\n try {\n const entries = await readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = join(currentDir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n const subFiles = await collectFiles(fullPath, baseDir, extensions);\n results.push(...subFiles);\n } else if (entry.isFile()) {\n const ext = entry.name.includes('.') ? '.' + entry.name.split('.').pop()! : '';\n if (extensions.has(ext)) {\n results.push(relative(baseDir, fullPath));\n }\n }\n }\n } catch {\n // Directory unreadable\n }\n return results;\n}\n\n/**\n * Scans all Markdown/YAML files in the spec directory for relative file\n * references (Markdown links) and detects cycles in the reference graph.\n */\nexport async function detectCircularReferences(dir: string): Promise<string[]> {\n const textExtensions = new Set(['.md', '.yaml', '.yml']);\n const files = await collectFiles(dir, dir, textExtensions);\n const graph = new Map<string, Set<string>>();\n const linkPattern = /\\[(?:[^\\]]*)\\]\\(([^)]+)\\)/g;\n\n for (const file of files) {\n const refs = new Set<string>();\n try {\n const content = await readFile(join(dir, file), 'utf-8');\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(content)) !== null) {\n const target = match[1]!;\n if (\n target.startsWith('http://') ||\n target.startsWith('https://') ||\n target.startsWith('#') ||\n target.startsWith('mailto:')\n ) {\n continue;\n }\n const targetPath = target.split('#')[0]!;\n if (!targetPath) continue;\n const fileDir = join(dir, file, '..');\n const resolvedTarget = normalize(relative(dir, resolve(fileDir, targetPath)));\n if (!resolvedTarget.startsWith('..') && files.includes(resolvedTarget)) {\n refs.add(resolvedTarget);\n }\n }\n } catch {\n // skip\n }\n graph.set(file, refs);\n }\n\n const WHITE = 0,\n GRAY = 1,\n BLACK = 2;\n const color = new Map<string, number>();\n const parent = new Map<string, string | null>();\n const cycles: string[] = [];\n\n for (const f of files) {\n color.set(f, WHITE);\n }\n\n function dfs(node: string): void {\n color.set(node, GRAY);\n const neighbors = graph.get(node) ?? new Set();\n for (const neighbor of neighbors) {\n if (color.get(neighbor) === GRAY) {\n const cyclePath: string[] = [neighbor, node];\n let curr = node;\n while (curr !== neighbor) {\n const p = parent.get(curr);\n if (!p || p === neighbor) break;\n cyclePath.push(p);\n curr = p;\n }\n cyclePath.reverse();\n cycles.push(cyclePath.join(' -> '));\n } else if (color.get(neighbor) === WHITE) {\n parent.set(neighbor, node);\n dfs(neighbor);\n }\n }\n color.set(node, BLACK);\n }\n\n for (const f of files) {\n if (color.get(f) === WHITE) {\n parent.set(f, null);\n dfs(f);\n }\n }\n\n return cycles;\n}\n\n/**\n * Content validation when spec_format is \"specmarket\" (spec.yaml + PROMPT.md + SPEC.md + SUCCESS_CRITERIA.md + stdlib).\n * Pushes to errors/warnings.\n */\nasync function validateSpecmarketContent(\n dir: string,\n errors: string[],\n warnings: string[]\n): Promise<void> {\n for (const file of REQUIRED_SPEC_FILES) {\n const filePath = join(dir, file);\n try {\n await access(filePath);\n const content = await readFile(filePath, 'utf-8');\n if (content.trim().length === 0) {\n errors.push(`${file} exists but is empty`);\n }\n } catch {\n errors.push(`Required file missing: ${file}`);\n }\n }\n\n const stdlibDir = join(dir, 'stdlib');\n for (const file of REQUIRED_STDLIB_FILES) {\n const filePath = join(stdlibDir, file);\n try {\n await access(filePath);\n const content = await readFile(filePath, 'utf-8');\n if (content.trim().length === 0) {\n errors.push(`stdlib/${file} exists but is empty`);\n }\n } catch {\n errors.push(`Required file missing: stdlib/${file}`);\n }\n }\n\n let specYaml: unknown = null;\n const specYamlPath = join(dir, 'spec.yaml');\n try {\n const raw = await readFile(specYamlPath, 'utf-8');\n specYaml = parseYaml(raw);\n } catch (err) {\n errors.push(`spec.yaml: Failed to parse YAML: ${(err as Error).message}`);\n return;\n }\n\n const parseResult = specYamlSchema.safeParse(specYaml);\n if (!parseResult.success) {\n for (const issue of parseResult.error.issues) {\n errors.push(`spec.yaml: ${issue.path.join('.')} — ${issue.message}`);\n }\n return;\n }\n\n const parsed = parseResult.data;\n\n try {\n const criteriaContent = await readFile(join(dir, 'SUCCESS_CRITERIA.md'), 'utf-8');\n const hasCriterion = /^- \\[[ x]\\]/m.test(criteriaContent);\n if (!hasCriterion) {\n errors.push(\n 'SUCCESS_CRITERIA.md: Must contain at least one criterion in format: - [ ] criterion text'\n );\n }\n } catch {\n // Already caught in required files check\n }\n\n const cycles = await detectCircularReferences(dir);\n for (const cycle of cycles) {\n errors.push(`Circular reference detected: ${cycle}`);\n }\n\n if (parsed.infrastructure) {\n const infra = parsed.infrastructure;\n if (\n ['web-app', 'api-service', 'mobile-app'].includes(parsed.output_type) &&\n infra.services.length === 0\n ) {\n warnings.push(\n `${parsed.output_type} should typically define infrastructure services (database, auth, etc.)`\n );\n }\n if (!infra.setup_time_minutes) {\n warnings.push('infrastructure.setup_time_minutes is not set');\n }\n for (const service of infra.services) {\n if (service.default_provider) {\n const providerNames = service.providers.map((p) => p.name);\n if (!providerNames.includes(service.default_provider)) {\n errors.push(\n `infrastructure.services[${service.name}].default_provider \"${service.default_provider}\" ` +\n `does not match any defined provider (${providerNames.join(', ')})`\n );\n }\n }\n }\n } else {\n if (['web-app', 'api-service', 'mobile-app'].includes(parsed.output_type)) {\n warnings.push(\n 'No infrastructure block defined. Consider adding infrastructure.services for database, auth, etc.'\n );\n }\n }\n\n if (parsed.estimated_tokens < 1000) {\n warnings.push(\n `estimated_tokens (${parsed.estimated_tokens}) seems very low. Most specs use 10,000+.`\n );\n }\n if (parsed.estimated_tokens > 10_000_000) {\n warnings.push(`estimated_tokens (${parsed.estimated_tokens}) seems very high.`);\n }\n if (parsed.estimated_cost_usd < 0.01) {\n warnings.push(\n `estimated_cost_usd ($${parsed.estimated_cost_usd}) seems very low.`\n );\n }\n if (parsed.estimated_time_minutes < 1) {\n warnings.push(\n `estimated_time_minutes (${parsed.estimated_time_minutes}) seems unrealistically low.`\n );\n }\n}\n\n/**\n * Validates a spec directory. Single standard: specmarket.yaml is required for every spec.\n * Format and metadata come from the sidecar; format-specific content checks run based on spec_format.\n */\nexport async function validateSpec(specPath: string): Promise<ValidationResult> {\n const dir = resolve(specPath);\n const errors: string[] = [];\n const warnings: string[] = [];\n let format: string | undefined;\n let formatDetectedBy: 'sidecar' | 'heuristic' | undefined = 'sidecar';\n\n // Universal: directory non-empty\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n const hasAnyFile = entries.some((e) => e.isFile());\n if (!hasAnyFile) {\n errors.push('Directory is empty or has no readable files');\n }\n } catch {\n errors.push('Directory is empty or unreadable');\n }\n\n const sidecarPath = join(dir, SIDECAR_FILENAME);\n const sidecarExists = await fileExists(sidecarPath);\n\n if (!sidecarExists) {\n errors.push(`${SIDECAR_FILENAME} is required for all specs (single source of truth for format and metadata)`);\n } else {\n try {\n const raw = await readFile(sidecarPath, 'utf-8');\n const parsed = parseYaml(raw) as unknown;\n const sidecarResult = specmarketSidecarSchema.safeParse(parsed);\n if (!sidecarResult.success) {\n for (const issue of sidecarResult.error.issues) {\n errors.push(\n `${SIDECAR_FILENAME}: ${issue.path.join('.')} — ${issue.message}`\n );\n }\n } else {\n const sidecar = sidecarResult.data;\n format = sidecar.spec_format;\n\n if (sidecar.estimated_tokens !== undefined) {\n if (sidecar.estimated_tokens < 1000) {\n warnings.push(\n `estimated_tokens (${sidecar.estimated_tokens}) seems very low.`\n );\n }\n if (sidecar.estimated_tokens > 10_000_000) {\n warnings.push(`estimated_tokens (${sidecar.estimated_tokens}) seems very high.`);\n }\n }\n if (sidecar.estimated_cost_usd !== undefined && sidecar.estimated_cost_usd < 0.01) {\n warnings.push(\n `estimated_cost_usd ($${sidecar.estimated_cost_usd}) seems very low.`\n );\n }\n if (\n sidecar.estimated_time_minutes !== undefined &&\n sidecar.estimated_time_minutes < 1\n ) {\n warnings.push(\n `estimated_time_minutes (${sidecar.estimated_time_minutes}) seems unrealistically low.`\n );\n }\n\n // Format-specific content validation (based on sidecar.spec_format)\n switch (format) {\n case 'specmarket':\n await validateSpecmarketContent(dir, errors, warnings);\n break;\n case 'speckit': {\n const hasSpecMd = await fileExists(join(dir, 'spec.md'));\n const hasTasksMd = await fileExists(join(dir, 'tasks.md'));\n const hasPlanMd = await fileExists(join(dir, 'plan.md'));\n const hasSpecifyDir = await directoryExists(join(dir, '.specify'));\n if (!hasSpecMd) errors.push('speckit format requires spec.md');\n if (!hasTasksMd && !hasPlanMd) errors.push('speckit format requires tasks.md or plan.md');\n if (!hasSpecifyDir) warnings.push('speckit format: .specify/ directory is recommended');\n break;\n }\n case 'bmad': {\n const hasPrdMd = await fileExists(join(dir, 'prd.md'));\n const hasStory = await hasStoryFiles(dir);\n if (!hasPrdMd && !hasStory) errors.push('bmad format requires prd.md or story-*.md files');\n const hasArch = await fileExists(join(dir, 'architecture.md'));\n if (!hasArch) warnings.push('bmad format: architecture.md is recommended');\n break;\n }\n case 'ralph': {\n const prdPath = join(dir, 'prd.json');\n if (!(await fileExists(prdPath))) {\n errors.push('ralph format requires prd.json');\n break;\n }\n try {\n const raw = await readFile(prdPath, 'utf-8');\n const data = JSON.parse(raw) as unknown;\n if (\n !data ||\n typeof data !== 'object' ||\n !('userStories' in data) ||\n !Array.isArray((data as { userStories: unknown }).userStories)\n ) {\n errors.push('ralph format: prd.json must have userStories array');\n }\n } catch {\n errors.push('ralph format: prd.json must be valid JSON with userStories array');\n }\n break;\n }\n case 'custom':\n default: {\n const hasMd = await hasMarkdownFiles(dir);\n if (!hasMd) {\n errors.push('custom format requires at least one .md file');\n break;\n }\n const textExtensions = new Set(['.md']);\n const mdFiles = await collectFiles(dir, dir, textExtensions);\n let hasSubstantialMd = false;\n for (const f of mdFiles) {\n try {\n const content = await readFile(join(dir, f), 'utf-8');\n if (content.length > 100) {\n hasSubstantialMd = true;\n break;\n }\n } catch {\n // skip\n }\n }\n if (!hasSubstantialMd) {\n errors.push('custom format requires at least one .md file larger than 100 bytes');\n }\n break;\n }\n }\n }\n } catch (err) {\n errors.push(\n `${SIDECAR_FILENAME}: Failed to read or parse: ${(err as Error).message}`\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n format,\n formatDetectedBy,\n };\n}\n\nexport function createValidateCommand(): Command {\n return new Command('validate')\n .description('Validate a spec directory for completeness and schema compliance')\n .argument('[path]', 'Path to the spec directory (defaults to current directory)', '.')\n .action(async (specPath: string) => {\n try {\n const result = await validateSpec(specPath);\n\n if (result.format !== undefined) {\n console.log(chalk.gray(`Format: ${result.format}`));\n }\n\n if (result.warnings.length > 0) {\n console.log(chalk.yellow('\\nWarnings:'));\n for (const warning of result.warnings) {\n console.log(chalk.yellow(` ⚠ ${warning}`));\n }\n }\n\n if (result.errors.length > 0) {\n console.log(chalk.red('\\nErrors:'));\n for (const error of result.errors) {\n console.log(chalk.red(` ✗ ${error}`));\n }\n console.log(\n chalk.red(`\\nValidation failed with ${result.errors.length} error(s).`)\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n console.log(\n chalk.green(\n `\\n✓ Spec is valid${result.warnings.length > 0 ? ` (${result.warnings.length} warning(s))` : ''}`\n )\n );\n } catch (err) {\n console.error(chalk.red(`Validation error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { readFile, mkdir, writeFile as writeFileFn } from 'fs/promises';\nimport { join, resolve, isAbsolute } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { specYamlSchema, EXIT_CODES, KNOWN_HARNESSES } from '@specmarket/shared';\nimport { validateSpec } from './validate.js';\nimport { loadCredentials, isAuthenticated } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { submitTelemetry, promptTelemetryOptIn } from '../lib/telemetry.js';\nimport { runSpec, checkClaudeCliInstalled } from '../lib/ralph-loop.js';\nimport type { LoopIteration } from '@specmarket/shared';\nimport createDebug from 'debug';\nimport { createRequire } from 'module';\n\nconst debug = createDebug('specmarket:cli');\n\n// Dynamically read version from package.json (at runtime, bundled into dist/index.js)\nconst _require = createRequire(import.meta.url);\nconst CLI_VERSION: string = _require('../package.json').version;\n\n/**\n * Core run command handler.\n *\n * Accepts either:\n * - A local path: ./my-spec, /path/to/spec, .\n * - A registry ID: my-spec, @user/my-spec, @user/my-spec@1.2.0\n *\n * Flow:\n * 1. Resolve spec (download from registry if needed)\n * 2. Validate spec (exit 1 on validation error)\n * 3. Print sandboxing warning (ALWAYS)\n * 4. If authenticated + telemetry opted in: prompt once if never asked\n * 5. Execute Ralph Loop\n * 6. Submit telemetry if opted in\n * 7. Print run summary\n */\nexport async function handleRun(\n specPathOrId: string,\n opts: {\n maxLoops?: string;\n maxBudget?: string;\n noTelemetry?: boolean;\n model?: string;\n dryRun?: boolean;\n resume?: string;\n output?: string;\n harness?: string;\n workdir?: string;\n }\n): Promise<void> {\n // Resolve spec directory (and registry spec ID if downloaded from registry)\n const { specDir, registrySpecId } = await resolveSpecPath(specPathOrId);\n\n // Validate before running\n console.log(chalk.gray('Validating spec...'));\n const validation = await validateSpec(specDir);\n\n if (!validation.valid) {\n console.log(chalk.red('\\nSpec validation failed:'));\n for (const err of validation.errors) {\n console.log(chalk.red(` ✗ ${err}`));\n }\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n if (validation.warnings.length > 0) {\n for (const warning of validation.warnings) {\n console.log(chalk.yellow(` ⚠ ${warning}`));\n }\n }\n\n // Load spec.yaml\n const specYamlContent = await readFile(join(specDir, 'spec.yaml'), 'utf-8');\n const specYamlRaw = parseYaml(specYamlContent);\n const specYaml = specYamlSchema.parse(specYamlRaw);\n\n // ALWAYS print sandboxing warning (SECURITY requirement)\n console.log('');\n console.log(chalk.yellow('⚠ SECURITY WARNING'));\n console.log(chalk.yellow('─────────────────────────────────────────────────────────'));\n console.log(chalk.yellow(' AI-generated code will be executed in your environment.'));\n console.log(chalk.yellow(' It is STRONGLY RECOMMENDED to run specs in an isolated'));\n console.log(chalk.yellow(' environment:'));\n console.log(chalk.yellow(' • Docker container'));\n console.log(chalk.yellow(' • Virtual machine or cloud sandbox'));\n console.log(chalk.yellow(' • Dedicated non-root user account'));\n console.log(chalk.yellow(' NEVER run specs as root or with admin privileges.'));\n console.log(chalk.yellow('─────────────────────────────────────────────────────────'));\n console.log('');\n\n // Telemetry opt-in prompt (first run for authenticated users)\n const authed = await isAuthenticated();\n if (authed && !opts.noTelemetry) {\n await promptTelemetryOptIn();\n }\n\n // Validate --harness value\n if (opts.harness && !(KNOWN_HARNESSES as readonly string[]).includes(opts.harness)) {\n console.log(chalk.red(`\\n✗ Unknown harness \"${opts.harness}\". Supported: ${KNOWN_HARNESSES.join(', ')}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Pre-flight check: Ensure the selected harness CLI is installed\n try {\n await checkClaudeCliInstalled(opts.harness);\n } catch (err) {\n console.log(chalk.red(`\\n✗ ${(err as Error).message}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n const maxLoops = opts.maxLoops ? parseInt(opts.maxLoops, 10) : undefined;\n const maxBudget = opts.maxBudget ? parseFloat(opts.maxBudget) : undefined;\n\n const harness = opts.harness ?? 'claude-code';\n console.log(chalk.cyan(`\\nRunning spec: ${chalk.bold(specYaml.display_name)}`));\n console.log(chalk.gray(` Version: ${specYaml.version}`));\n console.log(chalk.gray(` Model: ${opts.model ?? specYaml.min_model}`));\n console.log(chalk.gray(` Harness: ${harness}`));\n if (opts.workdir) {\n console.log(chalk.gray(` Working dir: ${opts.workdir}`));\n }\n console.log(chalk.gray(` Max loops: ${maxLoops ?? 50}`));\n console.log(chalk.gray(` Estimated tokens: ${specYaml.estimated_tokens.toLocaleString()}`));\n console.log(chalk.gray(` Estimated cost: $${specYaml.estimated_cost_usd.toFixed(2)}`));\n\n // Set up steering input: collect lines from stdin and queue them for injection\n // at the next iteration boundary. Works when stdin is a TTY (interactive) or\n // a pipe (scripted input). Non-blocking — the run continues regardless.\n const steeringQueue: string[] = [];\n let steeringInputBuffer = '';\n const steeringDataHandler = (chunk: Buffer | string): void => {\n const data = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');\n steeringInputBuffer += data;\n const lines = steeringInputBuffer.split('\\n');\n steeringInputBuffer = lines.pop() ?? '';\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed) {\n steeringQueue.push(trimmed);\n // Write to stderr so it doesn't overwrite the spinner on stdout\n process.stderr.write(\n `\\n${chalk.cyan('[steering]')} Queued: \"${trimmed.length > 60 ? trimmed.slice(0, 60) + '…' : trimmed}\"\\n`\n );\n }\n }\n };\n\n if (!opts.dryRun) {\n process.stdin.setEncoding('utf-8');\n process.stdin.resume();\n process.stdin.on('data', steeringDataHandler);\n console.log(chalk.gray(' Tip: Type a message + Enter to steer the agent mid-run.'));\n }\n console.log('');\n\n const spinner = ora({ text: 'Starting loop iteration 1...', spinner: 'dots' }).start();\n\n try {\n const result = await runSpec(\n specDir,\n {\n name: specYaml.name,\n version: specYaml.version,\n estimatedTokens: specYaml.estimated_tokens,\n estimatedCostUsd: specYaml.estimated_cost_usd,\n estimatedTimeMinutes: specYaml.estimated_time_minutes,\n runner: specYaml.runner,\n minModel: specYaml.min_model,\n },\n {\n maxLoops,\n maxBudgetUsd: maxBudget,\n model: opts.model,\n dryRun: opts.dryRun,\n resumeRunId: opts.resume,\n outputDir: opts.output,\n harness: opts.harness,\n workdir: opts.workdir,\n cliVersion: CLI_VERSION,\n steeringQueue,\n },\n (iteration: LoopIteration) => {\n spinner.text = `Loop ${iteration.iteration}: ${iteration.tokens.toLocaleString()} tokens, ${(iteration.durationMs / 1000).toFixed(1)}s`;\n }\n );\n\n // Stop collecting steering input now that the run is complete\n process.stdin.removeListener('data', steeringDataHandler);\n process.stdin.pause();\n\n const { report } = result;\n const statusColor =\n report.status === 'success'\n ? chalk.green\n : report.status === 'stall' || report.status === 'budget_exceeded'\n ? chalk.yellow\n : chalk.red;\n\n spinner.stop();\n console.log('');\n console.log(chalk.bold('Run Complete'));\n console.log('─────────────────────────────────');\n console.log(` Status: ${statusColor(report.status.toUpperCase())}`);\n console.log(` Loops: ${report.loopCount}`);\n console.log(` Tokens: ${report.totalTokens.toLocaleString()}`);\n console.log(` Cost: $${report.totalCostUsd.toFixed(4)}`);\n console.log(` Time: ${report.totalTimeMinutes.toFixed(1)} minutes`);\n if (report.steeringActionCount && report.steeringActionCount > 0) {\n console.log(` Steering Actions: ${report.steeringActionCount}`);\n }\n console.log(` Run ID: ${chalk.gray(report.runId)}`);\n console.log(` Output: ${chalk.gray(result.outputDir)}`);\n\n if (report.successCriteriaResults.length > 0) {\n console.log('');\n console.log(chalk.bold('Success Criteria:'));\n for (const criterion of report.successCriteriaResults) {\n const icon = criterion.passed ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${icon} ${criterion.criterion}`);\n }\n }\n\n // Submit telemetry (non-blocking)\n // Priority: registry spec ID (from download) > forked_from_id (from spec.yaml) > undefined (local run)\n const resolvedSpecId = registrySpecId ?? specYaml.forked_from_id ?? undefined;\n const telemetrySubmitted = await submitTelemetry(\n { ...report, specId: resolvedSpecId },\n { noTelemetry: opts.noTelemetry }\n );\n if (telemetrySubmitted) {\n console.log(chalk.gray('\\n Telemetry submitted to SpecMarket platform.'));\n }\n\n if (report.status === 'budget_exceeded') {\n process.exit(EXIT_CODES.BUDGET_EXCEEDED);\n } else if (report.status === 'failure' || report.status === 'stall') {\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n } catch (err) {\n spinner.fail(chalk.red(`Run failed: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n } else if (errCode === String(EXIT_CODES.NETWORK_ERROR)) {\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n}\n\n/**\n * Result from resolveSpecPath: the local directory containing the spec,\n * and optionally the Convex document ID of the registry spec (for telemetry attribution).\n */\ninterface ResolvedSpec {\n specDir: string;\n registrySpecId?: string;\n}\n\n/**\n * Resolves a spec path-or-ID to a local directory.\n *\n * Accepts:\n * - Local paths: ./my-spec, ../specs/foo, /absolute/path, .\n * - Registry IDs: @user/name, @user/name@1.2.0, bare-name\n *\n * For registry IDs: calls specs.download to get a signed URL, downloads the zip,\n * extracts it to a temp directory, and returns the temp directory path along with\n * the spec's Convex document ID for telemetry attribution.\n */\nasync function resolveSpecPath(pathOrId: string): Promise<ResolvedSpec> {\n // Explicit local paths: ./ ../ / or bare \".\"\n if (\n pathOrId.startsWith('./') ||\n pathOrId.startsWith('../') ||\n isAbsolute(pathOrId) ||\n pathOrId === '.'\n ) {\n return { specDir: resolve(pathOrId) };\n }\n\n // Check if it's a registry reference: @user/name, @user/name@version, or bare name with no /\n const registryPattern = /^(@[\\w-]+\\/[\\w-]+(?:@[\\d.]+)?)$|^([\\w-]+)$/;\n const match = pathOrId.match(registryPattern);\n\n if (!match) {\n // Not a registry pattern, treat as local path\n debug('Treating %s as local path (no registry pattern match)', pathOrId);\n return { specDir: resolve(pathOrId) };\n }\n\n // Check if it exists as a local directory first\n const { access } = await import('fs/promises');\n const localPath = resolve(pathOrId);\n try {\n await access(localPath);\n debug('Found local directory %s — using as local spec', localPath);\n return { specDir: localPath };\n } catch {\n // Not a local directory — treat as registry ID\n }\n\n debug('Resolving registry ID: %s', pathOrId);\n\n // Parse @user/name@version format\n let scopedName: string | undefined;\n let version: string | undefined;\n\n if (pathOrId.startsWith('@')) {\n // @user/name or @user/name@1.2.0\n const versionSep = pathOrId.lastIndexOf('@', pathOrId.length - 1);\n // Check that the second @ (version separator) is after the scope @\n if (versionSep > 0 && pathOrId.indexOf('@') !== versionSep) {\n scopedName = pathOrId.slice(0, versionSep);\n version = pathOrId.slice(versionSep + 1);\n } else {\n scopedName = pathOrId;\n }\n } else {\n // Bare name — will search by slug\n scopedName = undefined;\n }\n\n // Get Convex client (auth optional for download)\n const creds = await loadCredentials();\n const client = await getConvexClient(creds?.token);\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error(\n `Registry spec \"${pathOrId}\" requested but Convex API bindings not available. ` +\n `Use a local path instead, or configure CONVEX_URL.`\n );\n }\n\n // Fetch spec metadata to resolve bare names to scopedName\n let registrySpecId: string | undefined;\n if (!scopedName) {\n // Bare name: search for it (take first result)\n const results = await client.query(api.specs.search, {\n query: pathOrId,\n limit: 1,\n });\n if (results.length === 0) {\n throw new Error(\n `Spec \"${pathOrId}\" not found in registry and does not exist as a local directory.`\n );\n }\n scopedName = results[0].scopedName;\n registrySpecId = results[0]._id;\n debug('Resolved bare name \"%s\" to %s (id: %s)', pathOrId, scopedName, registrySpecId);\n }\n\n // Fetch the spec document to get its Convex ID (needed for telemetry attribution)\n if (!registrySpecId && scopedName) {\n try {\n const specDoc = await client.query(api.specs.get, { scopedName });\n if (specDoc) {\n registrySpecId = specDoc._id;\n debug('Resolved scopedName \"%s\" to spec ID %s', scopedName, registrySpecId);\n }\n } catch (err) {\n debug('Failed to resolve spec ID for %s (non-fatal): %O', scopedName, err);\n }\n }\n\n // Download the spec zip\n const downloadArgs: { scopedName?: string; version?: string } = { scopedName };\n if (version) downloadArgs.version = version;\n\n const { url, version: resolvedVersion } = await client.action(\n api.specs.download,\n downloadArgs\n );\n debug('Got download URL for %s@%s', scopedName, resolvedVersion);\n\n // Download and extract to temp directory\n const { tmpdir } = await import('os');\n const { randomUUID } = await import('crypto');\n const tempDir = join(tmpdir(), `specmarket-${randomUUID()}`);\n await mkdir(tempDir, { recursive: true });\n\n let response: Response;\n try {\n response = await fetch(url);\n } catch (fetchErr) {\n const err = new Error(`Network error downloading spec: ${(fetchErr as Error).message}`);\n (err as NodeJS.ErrnoException).code = String(EXIT_CODES.NETWORK_ERROR);\n throw err;\n }\n if (!response.ok) {\n const exitCode = response.status === 401 || response.status === 403\n ? EXIT_CODES.AUTH_ERROR\n : EXIT_CODES.NETWORK_ERROR;\n const err = new Error(`Failed to download spec: ${response.statusText}`);\n (err as NodeJS.ErrnoException).code = String(exitCode);\n throw err;\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const zipPath = join(tempDir, 'spec.zip');\n await writeFileFn(zipPath, buffer);\n\n // Extract zip\n const { execAsync } = await import('../lib/exec.js');\n await execAsync(`unzip -q \"${zipPath}\" -d \"${tempDir}\"`);\n\n // Clean up zip file\n const { unlink } = await import('fs/promises');\n await unlink(zipPath).catch(() => {});\n\n debug('Registry spec extracted to %s', tempDir);\n console.log(chalk.gray(`Downloaded ${scopedName}@${resolvedVersion} to temporary directory`));\n\n return { specDir: tempDir, registrySpecId };\n}\n\nexport function createRunCommand(): Command {\n return new Command('run')\n .description('Execute a spec locally using the Ralph Loop')\n .argument('[path-or-id]', 'Local path to spec directory or registry ID (@user/name[@version])', '.')\n .option('--max-loops <n>', 'Maximum loop iterations (default: 50)')\n .option('--max-budget <usd>', 'Maximum budget in USD (default: 2x estimated)')\n .option('--no-telemetry', 'Disable telemetry submission for this run')\n .option('--model <model>', 'Override AI model (default: spec\\'s min_model)')\n .option('--dry-run', 'Validate and show config without executing')\n .option('--resume <run-id>', 'Resume a previous run from where it left off')\n .option('--output <dir>', 'Custom output directory for run artifacts')\n .option(\n '--harness <harness>',\n `Agentic harness to use (default: claude-code). One of: ${KNOWN_HARNESSES.join(', ')}`\n )\n .option(\n '--workdir <dir>',\n 'Run in an existing directory instead of a fresh sandbox (spec files not copied)'\n )\n .action(async (pathOrId: string, opts) => {\n try {\n await handleRun(pathOrId, opts);\n } catch (err) {\n console.error(chalk.red(`Run failed: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n } else if (errCode === String(EXIT_CODES.NETWORK_ERROR)) {\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import type { RunReport } from '@specmarket/shared';\nimport type { Id } from '@specmarket/convex/dataModel';\nimport { loadCredentials } from './auth.js';\nimport { loadConfig } from './config.js';\nimport { getConvexClient } from './convex-client.js';\nimport { api } from '@specmarket/convex/api';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:telemetry');\n\n/**\n * Submits run telemetry to the Convex backend.\n *\n * Privacy guarantees enforced here:\n * 1. Only submits if user is authenticated AND has explicitly opted in (telemetry=true).\n * 2. Never transmits source code — only metadata (tokens, cost, time, status, etc.).\n * 3. Submission failures are silently logged and never block CLI operation.\n * 4. --no-telemetry flag overrides config for a single run.\n *\n * @returns true if telemetry was submitted, false if skipped or failed\n */\nexport async function submitTelemetry(\n report: RunReport,\n opts: { noTelemetry?: boolean } = {}\n): Promise<boolean> {\n // Hard override: --no-telemetry flag\n if (opts.noTelemetry) {\n debug('Telemetry disabled via --no-telemetry flag');\n return false;\n }\n\n // Must be authenticated\n const creds = await loadCredentials();\n if (!creds) {\n debug('Skipping telemetry: not authenticated');\n return false;\n }\n\n // Must have opted in\n const config = await loadConfig();\n if (!config.telemetry) {\n debug('Skipping telemetry: user has not opted in (telemetry=false)');\n return false;\n }\n\n // specId is required to submit telemetry (must be a registry spec)\n if (!report.specId) {\n debug('Skipping telemetry: no specId (local-only run)');\n return false;\n }\n\n try {\n const client = await getConvexClient(creds.token);\n\n await client.mutation(api.runs.submit, {\n specId: report.specId as Id<'specs'>,\n specVersion: report.specVersion,\n model: report.model,\n runner: report.runner,\n harness: report.harness,\n specFormat: report.specFormat,\n environmentType: report.environmentType,\n steeringActionCount: report.steeringActionCount,\n isPureRun: report.isPureRun,\n loopCount: report.loopCount,\n totalTokens: report.totalTokens,\n totalCostUsd: report.totalCostUsd,\n totalTimeMinutes: report.totalTimeMinutes,\n status: report.status,\n successCriteriaResults: report.successCriteriaResults,\n os: report.os,\n nodeVersion: report.nodeVersion,\n cliVersion: report.cliVersion,\n completedAt: Date.now(),\n });\n\n debug('Telemetry submitted successfully for run %s', report.runId);\n return true;\n } catch (err) {\n // Telemetry failures MUST NOT block CLI operation\n debug('Telemetry submission failed (non-fatal): %O', err);\n return false;\n }\n}\n\n/**\n * Prompts the user once to opt in to telemetry.\n * Stores the choice in config so we don't ask again.\n * Called on the first `specmarket run` by an authenticated user.\n */\nexport async function promptTelemetryOptIn(): Promise<boolean> {\n const config = await loadConfig();\n\n if (config.telemetryPrompted) {\n return config.telemetry ?? false;\n }\n\n // Dynamic import to avoid loading inquirer in all code paths\n const { default: inquirer } = await import('inquirer');\n\n const { optIn } = await inquirer.prompt<{ optIn: boolean }>([\n {\n type: 'confirm',\n name: 'optIn',\n message:\n 'Help improve SpecMarket by submitting anonymous run metadata (tokens, cost, status)? No source code is ever sent.',\n default: false,\n },\n ]);\n\n const { saveConfig } = await import('./config.js');\n await saveConfig({ ...config, telemetry: optIn, telemetryPrompted: true });\n\n return optIn;\n}\n","import { spawn } from 'child_process';\nimport { mkdir, writeFile, readFile, access } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { homedir } from 'os';\nimport { randomUUID } from 'crypto';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { RunReport, LoopIteration, SuccessCriterionResult } from '@specmarket/shared';\nimport {\n CONFIG_PATHS,\n RUN_DEFAULTS,\n EXIT_CODES,\n RUNNER_ID,\n MODEL_COST_PER_TOKEN,\n DEFAULT_HARNESS,\n} from '@specmarket/shared';\nimport createDebug from 'debug';\nimport { generateMetaInstructions, META_INSTRUCTION_FILENAME } from './meta-instructions.js';\nimport { detectSpecFormat } from './format-detection.js';\n\nconst debug = createDebug('specmarket:runner');\nconst execAsync = promisify(exec);\n\n/**\n * Pre-flight check: Verifies that the selected harness CLI is installed.\n * Throws an error with installation instructions if the binary is not found.\n *\n * @param harness - The harness to check. Defaults to 'claude-code'.\n */\nexport async function checkClaudeCliInstalled(harness?: string): Promise<void> {\n const h = harness ?? DEFAULT_HARNESS;\n const binaryName = HARNESS_BINARY[h] ?? 'claude';\n try {\n await execAsync(`which ${binaryName}`);\n } catch {\n const installHint = HARNESS_INSTALL_HINT[h] ?? `Install ${binaryName} and ensure it is in your PATH.`;\n throw new Error(\n `Harness \"${h}\" binary \"${binaryName}\" is not installed or not in your PATH.\\n\\n` +\n `${installHint}\\n`\n );\n }\n}\n\n/** CLI binary name for each harness */\nconst HARNESS_BINARY: Record<string, string> = {\n 'claude-code': 'claude',\n 'codex': 'codex',\n 'opencode': 'opencode',\n};\n\n/** Install hints for each harness */\nconst HARNESS_INSTALL_HINT: Record<string, string> = {\n 'claude-code':\n 'Installation instructions:\\n npm install -g @anthropic-ai/claude-code\\n\\nOr visit: https://www.anthropic.com/claude-code',\n 'codex':\n 'Installation instructions:\\n npm install -g @openai/codex\\n\\nOr visit: https://github.com/openai/codex',\n 'opencode':\n 'Installation instructions:\\n npm install -g opencode-ai\\n\\nOr visit: https://opencode.ai',\n};\n\n/**\n * A single steering action logged during the run.\n * Written to `steering-log.json` in the run directory on completion.\n */\nexport interface SteeringEntry {\n /** ISO-8601 timestamp when the message was injected */\n timestamp: string;\n /** User-provided steering content */\n content: string;\n}\n\nexport interface RunOptions {\n maxLoops?: number;\n maxBudgetUsd?: number;\n model?: string;\n dryRun?: boolean;\n resumeRunId?: string;\n outputDir?: string;\n cliVersion: string;\n /** Spec format override. When omitted, auto-detected from specDir. */\n specFormat?: string;\n /**\n * Agentic harness to use for execution.\n * One of: 'claude-code' (default), 'codex', 'opencode'.\n */\n harness?: string;\n /**\n * Existing working directory to run in instead of a fresh sandbox.\n * When set, spec files are NOT copied — the agent operates directly on this directory.\n * Enables `environmentType: 'existing'` in the run report.\n */\n workdir?: string;\n /**\n * Shared queue for steering messages typed by the user during the run.\n * The caller pushes messages here; the runner drains the queue before each\n * harness execution and injects the messages into the meta-instructions file.\n * Each drained message increments `steeringActionCount` in the run report.\n */\n steeringQueue?: string[];\n}\n\nexport interface RunResult {\n report: RunReport;\n outputDir: string;\n}\n\n/**\n * Orchestrates the Ralph Loop — the core spec execution engine.\n *\n * The loop:\n * 1. Creates a sandboxed working directory under ~/.specmarket/runs/<run-id>/\n * 2. Copies spec files into the working directory\n * 3. Detects spec format (specmarket | speckit | bmad | ralph | custom) and generates\n * `.specmarket-runner.md` — format-aware meta-instructions for the AI agent.\n * 4. Initializes git for diff tracking\n * 5. Executes: `cat .specmarket-runner.md | claude --print` in a loop.\n * The meta-instructions tell the agent which files to read, how to find tasks,\n * how to mark completion, and when the run is done — regardless of spec format.\n * 6. After each loop: captures tokens, duration, git diff\n * 7. Checks for completion conditions:\n * - SUCCESS: TASKS.md empty + tests pass + all SUCCESS_CRITERIA.md criteria met\n * - STALL: 3 consecutive loops with no git diff\n * - FAILURE: 10 consecutive loops with same failing output\n * - BUDGET: total tokens > 2x estimated_tokens\n * 8. Writes run-report.json on completion\n *\n * SECURITY: Always prints sandboxing recommendation before starting.\n */\nexport async function runSpec(\n specDir: string,\n specYaml: {\n name: string;\n version: string;\n estimatedTokens: number;\n estimatedCostUsd: number;\n estimatedTimeMinutes: number;\n runner: string;\n minModel: string;\n },\n opts: RunOptions,\n onProgress?: (iteration: LoopIteration) => void\n): Promise<RunResult> {\n const maxLoops = opts.maxLoops ?? RUN_DEFAULTS.MAX_LOOPS;\n const budgetTokens =\n (opts.maxBudgetUsd\n ? (opts.maxBudgetUsd / specYaml.estimatedCostUsd) * specYaml.estimatedTokens\n : specYaml.estimatedTokens * RUN_DEFAULTS.BUDGET_MULTIPLIER);\n\n const harness = opts.harness ?? DEFAULT_HARNESS;\n const runId = opts.resumeRunId ?? randomUUID();\n const runsBaseDir = join(homedir(), CONFIG_PATHS.RUNS_DIR);\n\n // --workdir: run in the caller-provided existing directory (no file copying).\n // Without --workdir: create a fresh sandbox under ~/.specmarket/runs/<run-id>/.\n const usingWorkdir = opts.workdir !== undefined;\n const runDir = opts.workdir ?? opts.outputDir ?? join(runsBaseDir, runId);\n const environmentType: 'fresh' | 'existing' = usingWorkdir ? 'existing' : 'fresh';\n\n if (!usingWorkdir) {\n await mkdir(runDir, { recursive: true });\n }\n debug('Run directory: %s (environmentType=%s, harness=%s)', runDir, environmentType, harness);\n\n if (opts.dryRun) {\n debug('Dry run mode — skipping execution');\n const report: RunReport = {\n runId,\n specVersion: specYaml.version,\n model: opts.model ?? specYaml.minModel,\n runner: specYaml.runner,\n harness,\n specFormat: opts.specFormat,\n environmentType,\n steeringActionCount: 0,\n isPureRun: false,\n loopCount: 0,\n totalTokens: 0,\n totalCostUsd: 0,\n totalTimeMinutes: 0,\n status: 'user_cancelled',\n successCriteriaResults: [],\n os: process.platform,\n nodeVersion: process.version,\n cliVersion: opts.cliVersion,\n };\n return { report, outputDir: runDir };\n }\n\n const isResuming = opts.resumeRunId !== undefined;\n let startIteration = 1;\n let totalTokens = 0;\n\n if (isResuming) {\n // When resuming, preserve the existing working directory — do NOT re-copy\n // spec files or re-initialize git, as that would clobber AI-generated work\n // from the previous session.\n const existingReport = await loadExistingReport(runDir);\n if (existingReport) {\n startIteration = existingReport.loopCount + 1;\n totalTokens = existingReport.totalTokens;\n debug('Resuming from iteration %d with %d tokens carried over', startIteration, totalTokens);\n }\n // Ensure meta-instructions exist in the run dir (may be missing for runs\n // created before this feature was added).\n await ensureMetaInstructions(specDir, runDir, opts.specFormat);\n } else if (usingWorkdir) {\n // --workdir: the directory already has the spec files. Just generate/refresh\n // the meta-instructions so the agent knows what format it is working with.\n await ensureMetaInstructions(specDir, runDir, opts.specFormat);\n // Initialize git if not already a repo (best-effort — may be an existing git repo)\n await initGit(runDir);\n } else {\n // Fresh run: copy spec files, generate meta-instructions, initialize git.\n await copySpecFiles(specDir, runDir);\n await ensureMetaInstructions(specDir, runDir, opts.specFormat);\n await initGit(runDir);\n }\n\n const startTime = Date.now();\n const iterations: LoopIteration[] = [];\n let consecutiveNoChange = 0;\n let lastOutput = '';\n let consecutiveSameOutput = 0;\n const steeringLog: SteeringEntry[] = [];\n let steeringActionCount = 0;\n /**\n * Counts how many times the post-task test phase has detected failures after\n * all TASKS.md items were checked. When this reaches TEST_PHASE_MAX_ITERATIONS,\n * the run is declared a failure — the agent could not fix the tests.\n */\n let testPhaseAttempts = 0;\n\n let finalStatus: RunReport['status'] = 'failure';\n let successCriteriaResults: SuccessCriterionResult[] = [];\n\n for (let i = startIteration; i <= maxLoops; i++) {\n debug('Starting loop iteration %d/%d', i, maxLoops);\n\n const iterStart = Date.now();\n\n // Drain steering queue and inject any pending messages before this iteration.\n // Messages are appended to the meta-instructions file so the harness sees them.\n const pendingMessages = opts.steeringQueue ? opts.steeringQueue.splice(0) : [];\n if (pendingMessages.length > 0) {\n await injectSteeringMessages(runDir, pendingMessages, steeringLog);\n steeringActionCount += pendingMessages.length;\n debug('Injected %d steering message(s); total steeringActionCount=%d', pendingMessages.length, steeringActionCount);\n }\n\n // Execute via the selected harness\n const result = await executeHarness(runDir, harness, opts.model);\n\n const iterDuration = Date.now() - iterStart;\n const activeModel = opts.model ?? specYaml.minModel;\n const tokensThisLoop = parseTokensFromOutput(result.stdout, activeModel);\n totalTokens += tokensThisLoop;\n\n // Capture git diff\n const gitDiff = await getGitDiff(runDir);\n\n const iteration: LoopIteration = {\n iteration: i,\n tokens: tokensThisLoop,\n durationMs: iterDuration,\n exitCode: result.exitCode,\n gitDiff,\n stdoutTail: result.stdout.slice(-2000),\n };\n iterations.push(iteration);\n onProgress?.(iteration);\n\n // Persist iteration data\n await writeFile(\n join(runDir, `iteration-${i}.json`),\n JSON.stringify(iteration, null, 2)\n );\n\n // Stage all changes for next diff\n await stageAllChanges(runDir);\n\n // ---- Completion detection ----\n\n // BUDGET check\n if (totalTokens > budgetTokens) {\n debug('Budget exceeded: %d tokens > %d limit', totalTokens, budgetTokens);\n finalStatus = 'budget_exceeded';\n break;\n }\n\n // STALL check: 3 loops with no git diff\n if (gitDiff.trim() === '') {\n consecutiveNoChange++;\n debug('No changes in iteration %d (%d consecutive)', i, consecutiveNoChange);\n if (consecutiveNoChange >= RUN_DEFAULTS.STALL_THRESHOLD) {\n debug('Stall detected after %d loops', consecutiveNoChange);\n finalStatus = 'stall';\n break;\n }\n } else {\n consecutiveNoChange = 0;\n }\n\n // FAILURE check: 10 loops with same output\n const currentOutputHash = hashString(result.stdout.slice(-500));\n if (currentOutputHash === lastOutput) {\n consecutiveSameOutput++;\n if (consecutiveSameOutput >= RUN_DEFAULTS.FAILURE_THRESHOLD) {\n debug('Failure detected: same output for %d loops', consecutiveSameOutput);\n finalStatus = 'failure';\n break;\n }\n } else {\n consecutiveSameOutput = 0;\n lastOutput = currentOutputHash;\n }\n\n // ---- Post-task test phase ----\n //\n // When all TASKS.md items are checked, the runner takes over test execution:\n // 1. Run the test suite and capture output.\n // 2. If tests fail: write specific fix tasks to TASKS.md and TEST_FAILURES.md,\n // then continue the main loop so the agent can address them.\n // 3. If tests pass: check SUCCESS_CRITERIA.md — if all met, declare success.\n //\n // This creates a test→fix→retest cycle driven by the runner, ensuring the\n // agent only receives passing runs when everything is actually green.\n const tasksComplete = await isFixPlanEmpty(runDir);\n if (tasksComplete) {\n const testResult = await runTestsWithOutput(runDir);\n\n if (!testResult.passed) {\n testPhaseAttempts++;\n debug(\n 'Post-task test phase attempt %d/%d: tests failing, writing fix tasks',\n testPhaseAttempts,\n RUN_DEFAULTS.TEST_PHASE_MAX_ITERATIONS\n );\n\n if (testPhaseAttempts >= RUN_DEFAULTS.TEST_PHASE_MAX_ITERATIONS) {\n debug(\n 'Test phase exceeded max iterations (%d), declaring failure',\n RUN_DEFAULTS.TEST_PHASE_MAX_ITERATIONS\n );\n successCriteriaResults = await evaluateSuccessCriteria(runDir).catch(() => []);\n finalStatus = 'failure';\n break;\n }\n\n // Write actionable fix tasks so the next harness iteration has specific work.\n await writeTestFixTasks(runDir, testResult.output);\n await stageAllChanges(runDir);\n successCriteriaResults = await evaluateSuccessCriteria(runDir).catch(() => []);\n // Continue main loop — the harness will pick up the new fix tasks.\n } else {\n // Tests pass — evaluate SUCCESS_CRITERIA.md for the final gate.\n const criteriaResults = await evaluateSuccessCriteria(runDir);\n successCriteriaResults = criteriaResults;\n\n if (criteriaResults.every((r) => r.passed)) {\n debug('All tasks done, tests pass, criteria met at iteration %d', i);\n finalStatus = 'success';\n break;\n }\n\n // Success criteria not yet all checked — continue loop.\n // The agent must update SUCCESS_CRITERIA.md as criteria are satisfied.\n debug(\n 'Tests pass but not all criteria met at iteration %d; continuing',\n i\n );\n }\n } else {\n // Tasks still pending — update partial results for reporting.\n successCriteriaResults = await evaluateSuccessCriteria(runDir).catch(() => []);\n }\n }\n\n // If we exhausted all loops without a status, mark as failure\n if (finalStatus === 'failure' && successCriteriaResults.length === 0) {\n successCriteriaResults = await evaluateSuccessCriteria(runDir).catch(() => []);\n }\n\n // Persist steering log if any steering actions occurred during this run\n if (steeringLog.length > 0) {\n await writeFile(\n join(runDir, 'steering-log.json'),\n JSON.stringify(steeringLog, null, 2),\n 'utf-8'\n );\n debug('Steering log written (%d entries)', steeringLog.length);\n }\n\n const totalTimeMinutes = (Date.now() - startTime) / 60000;\n const costPerToken = specYaml.estimatedCostUsd / specYaml.estimatedTokens;\n const totalCostUsd = totalTokens * costPerToken;\n\n // Auto-detect specFormat from the run directory when not provided explicitly\n const detectedSpecFormat =\n opts.specFormat ?? (await detectSpecFormat(runDir)).format;\n\n const report: RunReport = {\n runId,\n specVersion: specYaml.version,\n model: opts.model ?? specYaml.minModel,\n runner: specYaml.runner,\n harness,\n specFormat: detectedSpecFormat,\n environmentType,\n steeringActionCount,\n isPureRun: finalStatus === 'success' && steeringActionCount === 0,\n loopCount: iterations.length,\n totalTokens,\n totalCostUsd,\n totalTimeMinutes,\n status: finalStatus,\n successCriteriaResults,\n os: process.platform,\n nodeVersion: process.version,\n cliVersion: opts.cliVersion,\n };\n\n await writeFile(\n join(runDir, 'run-report.json'),\n JSON.stringify(report, null, 2)\n );\n\n debug('Run complete: %s (status=%s, loops=%d)', runId, finalStatus, iterations.length);\n\n return { report, outputDir: runDir };\n}\n\n// ---- Internal helpers ----\n\n/**\n * Detects the spec format from specDir and writes `.specmarket-runner.md` to runDir.\n *\n * Idempotent: if the file already exists in runDir it is overwritten so that\n * the instructions stay consistent with the detected format.\n *\n * @param specDir - Source spec directory (used for format detection + sidecar data)\n * @param runDir - Sandboxed run directory where the file is written\n * @param formatOverride - Optional pre-detected format (skips detection when provided)\n */\nexport async function ensureMetaInstructions(\n specDir: string,\n runDir: string,\n formatOverride?: string\n): Promise<void> {\n const format = formatOverride ?? (await detectSpecFormat(specDir)).format;\n debug('Generating meta-instructions for format=%s', format);\n const content = await generateMetaInstructions(specDir, format);\n await writeFile(join(runDir, META_INSTRUCTION_FILENAME), content, 'utf-8');\n debug('Meta-instructions written to %s/%s', runDir, META_INSTRUCTION_FILENAME);\n}\n\n/**\n * Injects pending steering messages into the meta-instructions file for the\n * current run directory.\n *\n * A \"## Steering Input\" section is appended to `.specmarket-runner.md` so the\n * agent reads the user's guidance on its next harness invocation. Each call\n * appends a timestamped section — messages accumulate across iterations so the\n * agent retains the full steering history.\n *\n * Side effects:\n * - Modifies `.specmarket-runner.md` in runDir (appends steering section)\n * - Pushes `SteeringEntry` objects into `steeringLog`\n *\n * @param runDir - Active run directory containing the meta-instructions file\n * @param messages - Steering messages to inject (already spliced from the queue)\n * @param steeringLog - Mutable array collecting all steering entries for this run\n */\nexport async function injectSteeringMessages(\n runDir: string,\n messages: string[],\n steeringLog: SteeringEntry[]\n): Promise<void> {\n if (messages.length === 0) return;\n\n const timestamp = new Date().toISOString();\n const entries: SteeringEntry[] = messages.map((content) => ({ timestamp, content }));\n steeringLog.push(...entries);\n\n const steeringSection = [\n '',\n `## Steering Input (injected at ${timestamp})`,\n '',\n 'The user has provided the following steering instructions. Incorporate them into your current work:',\n '',\n ...messages.map((m) => `> ${m}`),\n '',\n ].join('\\n');\n\n const metaPath = join(runDir, META_INSTRUCTION_FILENAME);\n try {\n const existing = await readFile(metaPath, 'utf-8');\n await writeFile(metaPath, existing + steeringSection, 'utf-8');\n } catch {\n // Meta-instructions file missing — create it with just the steering section\n await writeFile(metaPath, steeringSection, 'utf-8');\n }\n\n debug('injectSteeringMessages: appended %d message(s) to %s', messages.length, META_INSTRUCTION_FILENAME);\n}\n\nasync function copySpecFiles(srcDir: string, destDir: string): Promise<void> {\n const { cp } = await import('fs/promises');\n await cp(srcDir, join(destDir, 'spec'), { recursive: true });\n // Also copy directly to destDir so spec files are accessible at the root\n // of the run directory alongside the generated meta-instructions.\n await cp(srcDir, destDir, { recursive: true, force: false });\n debug('Spec files copied from %s to %s', srcDir, destDir);\n}\n\nasync function initGit(dir: string): Promise<void> {\n try {\n await execAsync('git init && git add -A && git commit -m \"initial spec state\" --allow-empty', {\n cwd: dir,\n });\n debug('Git initialized in %s', dir);\n } catch (err) {\n debug('Git init failed (non-fatal): %O', err);\n }\n}\n\nasync function stageAllChanges(dir: string): Promise<void> {\n try {\n await execAsync('git add -A', { cwd: dir });\n } catch {\n // Non-fatal\n }\n}\n\nasync function getGitDiff(dir: string): Promise<string> {\n try {\n const { stdout } = await execAsync('git diff HEAD --stat', { cwd: dir });\n return stdout;\n } catch {\n return '';\n }\n}\n\ninterface ExecuteResult {\n stdout: string;\n exitCode: number;\n}\n\n/**\n * Builds the shell command string for the given harness.\n *\n * All harnesses receive the same meta-instructions file via stdin so they\n * know what format they are working with and what tasks to execute.\n *\n * - claude-code: `cat .specmarket-runner.md | claude --print --output-format json [--model <m>]`\n * - codex: `cat .specmarket-runner.md | codex`\n * - opencode: `cat .specmarket-runner.md | opencode`\n */\nfunction buildHarnessCommand(harness: string, model?: string): string {\n switch (harness) {\n case 'claude-code': {\n const args = ['--print', '--output-format', 'json'];\n if (model) args.push('--model', model);\n return `cat ${META_INSTRUCTION_FILENAME} | claude ${args.join(' ')}`;\n }\n case 'codex':\n // Codex CLI reads from stdin; model selection is via OPENAI_MODEL env or its own flags\n return `cat ${META_INSTRUCTION_FILENAME} | codex`;\n case 'opencode':\n // opencode reads from stdin\n return `cat ${META_INSTRUCTION_FILENAME} | opencode`;\n default:\n // Unknown harness — fall back to claude-code behaviour\n debug('Unknown harness \"%s\" — falling back to claude-code', harness);\n return `cat ${META_INSTRUCTION_FILENAME} | claude --print --output-format json`;\n }\n}\n\n/**\n * Executes a single loop iteration via the specified harness.\n *\n * The meta-instructions file (`.specmarket-runner.md`) is piped into the harness\n * binary as stdin. The harness is expected to read the instructions, perform the\n * requested work inside the run directory, and exit with code 0 on success.\n */\nasync function executeHarness(dir: string, harness: string, model?: string): Promise<ExecuteResult> {\n const cmd = buildHarnessCommand(harness, model);\n debug('executeHarness: %s (harness=%s)', cmd, harness);\n\n return new Promise((resolve) => {\n const proc = spawn('sh', ['-c', cmd], {\n cwd: dir,\n // stdin is 'ignore': the harness reads its instructions from the meta-instructions file\n // via `cat .specmarket-runner.md | <harness>`, not from parent stdin.\n // Keeping stdin detached from the parent lets the CLI read steering messages\n // from process.stdin without conflict.\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n proc.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n proc.stderr?.on('data', (chunk: Buffer) => {\n // Write stderr to process stderr for visibility\n process.stderr.write(chunk);\n });\n\n proc.on('close', (code) => {\n resolve({ stdout, exitCode: code ?? 0 });\n });\n\n proc.on('error', (err) => {\n debug('%s spawn error: %O', harness, err);\n resolve({ stdout: '', exitCode: 1 });\n });\n });\n}\n\n/**\n * Extracts token count from Claude Code's output.\n *\n * Strategy (in priority order):\n * 1. Parse JSON output format (claude --output-format json) which contains\n * structured metadata including token counts or cost_usd in the response.\n * When only cost_usd is available (typical for Claude Code CLI), token count\n * is estimated using model-aware pricing constants from MODEL_COST_PER_TOKEN.\n * This estimate may deviate ±30% from the actual count depending on the\n * input/output token ratio for that specific run.\n * 2. Match known text patterns from Claude Code's output (total_tokens, etc.)\n * 3. Estimate from output length as a last-resort heuristic (~4 chars per token).\n *\n * @param output - Raw stdout from the Claude CLI invocation\n * @param model - Model identifier (e.g. \"claude-haiku-4-5\", \"claude-opus-4-6\").\n * Used to select the correct pricing tier for cost→token estimation.\n * Defaults to Sonnet-tier pricing if omitted or unrecognised.\n *\n * Returns 0 only if the output is empty (no meaningful work was done).\n */\nexport function parseTokensFromOutput(output: string, model?: string): number {\n if (!output || output.trim().length === 0) return 0;\n\n // Resolve cost-per-token for this model (case-insensitive substring match)\n const modelLower = (model ?? '').toLowerCase();\n const costPerToken = modelLower.includes('haiku')\n ? MODEL_COST_PER_TOKEN.haiku\n : modelLower.includes('opus')\n ? MODEL_COST_PER_TOKEN.opus\n : MODEL_COST_PER_TOKEN.default;\n\n // Strategy 1: Parse JSON output format from claude --output-format json\n // Claude Code JSON output may contain token usage info in the response metadata.\n try {\n // The output might be a single JSON object or newline-delimited JSON\n const lines = output.trim().split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) continue;\n try {\n const parsed = JSON.parse(trimmed);\n\n // Check for various JSON structures Claude Code might emit\n if (typeof parsed === 'object' && parsed !== null) {\n // Direct token fields\n if (typeof parsed.total_tokens === 'number') return parsed.total_tokens;\n if (typeof parsed.totalTokens === 'number') return parsed.totalTokens;\n\n // Nested in usage object\n if (parsed.usage?.total_tokens) return parsed.usage.total_tokens;\n if (parsed.usage?.totalTokens) return parsed.usage.totalTokens;\n\n // Nested in result/metadata\n if (parsed.result?.usage?.total_tokens) return parsed.result.usage.total_tokens;\n if (parsed.metadata?.total_tokens) return parsed.metadata.total_tokens;\n\n // Sum of input + output tokens\n const input = parsed.usage?.input_tokens ?? parsed.usage?.prompt_tokens ?? 0;\n const output_tokens = parsed.usage?.output_tokens ?? parsed.usage?.completion_tokens ?? 0;\n if (input > 0 || output_tokens > 0) return input + output_tokens;\n\n // Cost-based estimation: Claude Code CLI typically reports cost_usd but not\n // raw token counts. Use model-aware pricing for the best estimate.\n if (typeof parsed.cost_usd === 'number' && parsed.cost_usd > 0) {\n debug(\n 'parseTokensFromOutput: using cost_usd=%f with model=%s (costPerToken=%e)',\n parsed.cost_usd,\n model ?? 'unknown',\n costPerToken\n );\n return Math.round(parsed.cost_usd / costPerToken);\n }\n }\n } catch {\n // Not valid JSON, skip this line\n }\n }\n } catch {\n // JSON parsing failed entirely, try text patterns\n }\n\n // Strategy 2: Regex patterns for text-based output\n const patterns = [\n /total[_\\s]tokens?[:\\s]+(\\d[\\d,]*)/i,\n /\"total_tokens\"[:\\s]+(\\d[\\d,]*)/,\n /\"totalTokens\"[:\\s]+(\\d[\\d,]*)/,\n /tokens?\\s*used[:\\s]+(\\d[\\d,]*)/i,\n /input[_\\s]tokens?[:\\s]+(\\d[\\d,]*).*output[_\\s]tokens?[:\\s]+(\\d[\\d,]*)/i,\n /prompt[_\\s]tokens?[:\\s]+(\\d[\\d,]*).*completion[_\\s]tokens?[:\\s]+(\\d[\\d,]*)/i,\n ];\n\n for (const pattern of patterns) {\n const match = output.match(pattern);\n if (match) {\n // Some patterns capture two groups (input + output)\n if (match[2]) {\n return parseIntComma(match[1]) + parseIntComma(match[2]);\n }\n if (match[1]) {\n return parseIntComma(match[1]);\n }\n }\n }\n\n // Strategy 3: Estimate from output length\n // Rough heuristic: ~4 characters per token for English text.\n // This is imprecise but better than returning 0 (which breaks budget tracking).\n const estimatedTokens = Math.ceil(output.length / 4);\n debug(\n 'parseTokensFromOutput: no explicit token count found, estimating %d from %d chars',\n estimatedTokens,\n output.length\n );\n return estimatedTokens;\n}\n\n/** Parse an integer that might have comma separators (e.g. \"12,345\") */\nfunction parseIntComma(s: string): number {\n return parseInt(s.replace(/,/g, ''), 10) || 0;\n}\n\nasync function isFixPlanEmpty(dir: string): Promise<boolean> {\n try {\n const content = await readFile(join(dir, 'TASKS.md'), 'utf-8');\n // Consider empty if: no unchecked items (- [ ] lines)\n const hasUncheckedItems = /^- \\[ \\]/m.test(content);\n return !hasUncheckedItems;\n } catch {\n // No TASKS.md = considered empty\n return true;\n }\n}\n\n/**\n * Runs the test suite in `dir` and captures the raw output.\n *\n * Probes for known test runner config files in priority order; skips to the\n * next runner on spawn or timeout errors. Returns `{ passed: true, output: '' }`\n * when no test runner is detected (cannot verify — assume passing).\n *\n * The raw `output` is used by `writeTestFixTasks` to extract failure details\n * and write them as actionable fix tasks for the agent.\n */\nexport async function runTestsWithOutput(dir: string): Promise<{ passed: boolean; output: string }> {\n const testRunners = [\n { file: 'package.json', cmd: 'npm test -- --run 2>&1' },\n { file: 'vitest.config.ts', cmd: 'npx vitest run 2>&1' },\n { file: 'pytest.ini', cmd: 'python -m pytest --tb=short -q 2>&1' },\n { file: 'Makefile', cmd: 'make test 2>&1' },\n ];\n\n for (const runner of testRunners) {\n try {\n await access(join(dir, runner.file));\n } catch {\n continue; // Config file doesn't exist — try next runner\n }\n\n try {\n const { stdout, stderr } = await execAsync(runner.cmd, {\n cwd: dir,\n timeout: 120000,\n });\n const combined = stdout + stderr;\n const hasFailed = /\\d+ failed|\\d+ error/i.test(combined);\n return { passed: !hasFailed, output: combined };\n } catch (err: unknown) {\n if (err && typeof err === 'object') {\n const execErr = err as { code?: number; signal?: string; stdout?: string; stderr?: string };\n if (typeof execErr.code === 'number' && execErr.signal == null) {\n // Process exited with a non-zero exit code — genuine test failures.\n const combined = (execErr.stdout ?? '') + (execErr.stderr ?? '');\n return { passed: false, output: combined };\n }\n }\n // Timeout or spawn error — skip to next runner\n continue;\n }\n }\n\n // No test runner detected — assume passing\n return { passed: true, output: '' };\n}\n\n/**\n * Extract a short list of failing test identifiers from raw test runner output.\n *\n * Supports:\n * - Vitest/Jest: \"FAIL src/foo.test.ts\" file-level failures\n * - Vitest/Jest: \"× test name\" / \"✗ test name\" individual test failures\n * - Pytest: \"FAILED tests/foo.py::test_name\"\n * - Generic: \"N failed\" summary line (fallback)\n *\n * Returns at most 10 entries. When specific failures cannot be parsed, returns\n * a single generic entry directing the agent to TEST_FAILURES.md.\n */\nexport function extractTestFailures(output: string): string[] {\n const failures: string[] = [];\n\n // Vitest/Jest: \"FAIL src/foo.test.ts\" (file-level failure)\n const failFileMatches = output.match(/^FAIL\\s+\\S+/gm) ?? [];\n for (const m of failFileMatches) {\n const name = m.replace(/^FAIL\\s+/, '').trim();\n if (name && !failures.includes(name)) failures.push(name);\n }\n\n // Vitest/Jest: individual test \"× test name\" or \"✗ test name\" or \"✕ test name\"\n const failTestMatches = output.match(/^[\\s]*[×✗✕]\\s+(.+)/gm) ?? [];\n for (const m of failTestMatches) {\n const name = m.replace(/^[\\s]*[×✗✕]\\s+/, '').trim();\n if (name && !failures.includes(name)) failures.push(name);\n }\n\n // Pytest: \"FAILED tests/foo.py::test_bar\"\n const pytestMatches = output.match(/^FAILED\\s+\\S+/gm) ?? [];\n for (const m of pytestMatches) {\n const name = m.replace(/^FAILED\\s+/, '').trim();\n if (name && !failures.includes(name)) failures.push(name);\n }\n\n // Generic fallback when specific test names couldn't be parsed\n if (failures.length === 0) {\n const summaryMatch = output.match(/(\\d+)\\s+failed/i);\n if (summaryMatch) {\n failures.push(`${summaryMatch[1]} test(s) failed — see TEST_FAILURES.md for details`);\n }\n }\n\n return failures.slice(0, 10);\n}\n\n/**\n * Write test failures as actionable fix tasks into TASKS.md after the runner\n * detects that all implementation tasks are done but tests are still failing.\n *\n * Side effects:\n * - Writes `TEST_FAILURES.md` with the full test output for agent reference.\n * - Appends (or replaces) a \"## Test Failures (Auto-Generated)\" section in\n * `TASKS.md` containing one `- [ ] Fix: <name>` item per failing test.\n * Any previous auto-generated section is replaced to avoid duplication.\n *\n * The agent will see TASKS.md has unchecked items, read TEST_FAILURES.md for\n * context, and work to resolve each failure before marking them `[x]`.\n */\nexport async function writeTestFixTasks(dir: string, testOutput: string): Promise<void> {\n // Always write the full output to TEST_FAILURES.md so the agent has context.\n await writeFile(\n join(dir, 'TEST_FAILURES.md'),\n [\n '# Test Failures',\n '',\n '> Auto-generated by SpecMarket runner. Delete this file when all tests pass.',\n '',\n '## Raw Test Output',\n '',\n '```',\n testOutput.slice(0, 8000),\n '```',\n ].join('\\n'),\n 'utf-8'\n );\n\n const failures = extractTestFailures(testOutput);\n if (failures.length === 0) return;\n\n const testFixSection = [\n '',\n '## Test Failures (Auto-Generated)',\n '> These tasks were created by the runner after detecting test failures.',\n '> Fix each failing test, then delete this section and TEST_FAILURES.md.',\n '',\n ...failures.map((f) => `- [ ] Fix: ${f}`),\n ].join('\\n');\n\n try {\n const existing = await readFile(join(dir, 'TASKS.md'), 'utf-8');\n // Replace any previous auto-generated section to avoid duplication.\n const withoutPrevious = existing.replace(\n /\\n## Test Failures \\(Auto-Generated\\)[\\s\\S]*/,\n ''\n );\n await writeFile(join(dir, 'TASKS.md'), withoutPrevious + testFixSection, 'utf-8');\n } catch {\n // TASKS.md doesn't exist — create it.\n await writeFile(join(dir, 'TASKS.md'), `# Tasks${testFixSection}`, 'utf-8');\n }\n}\n\nasync function evaluateSuccessCriteria(dir: string): Promise<SuccessCriterionResult[]> {\n try {\n const content = await readFile(join(dir, 'SUCCESS_CRITERIA.md'), 'utf-8');\n const lines = content.split('\\n');\n const results: SuccessCriterionResult[] = [];\n\n for (const line of lines) {\n // Match markdown checkboxes: - [x] criterion (passed) or - [ ] criterion (not passed)\n const checkedMatch = line.match(/^-\\s+\\[x\\]\\s+(.+)/i);\n const uncheckedMatch = line.match(/^-\\s+\\[\\s\\]\\s+(.+)/);\n\n if (checkedMatch?.[1]) {\n results.push({ criterion: checkedMatch[1].trim(), passed: true });\n } else if (uncheckedMatch?.[1]) {\n results.push({ criterion: uncheckedMatch[1].trim(), passed: false });\n }\n }\n\n return results;\n } catch {\n return [];\n }\n}\n\nasync function loadExistingReport(dir: string): Promise<RunReport | null> {\n try {\n const raw = await readFile(join(dir, 'run-report.json'), 'utf-8');\n return JSON.parse(raw) as RunReport;\n } catch {\n return null;\n }\n}\n\nfunction hashString(s: string): string {\n let hash = 0;\n for (let i = 0; i < s.length; i++) {\n const char = s.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return String(hash);\n}\n","import { readFile, readdir } from 'fs/promises';\nimport { join } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { fileExists, directoryExists } from './format-detection.js';\nimport { SIDECAR_FILENAME } from '@specmarket/shared';\n\n/** Filename for generated meta-instructions in the run directory */\nexport const META_INSTRUCTION_FILENAME = '.specmarket-runner.md';\n\ninterface SidecarData {\n display_name?: string;\n description?: string;\n spec_format?: string;\n}\n\n/** Read display_name and description from specmarket.yaml if present */\nasync function readSidecarData(dir: string): Promise<SidecarData> {\n const sidecarPath = join(dir, SIDECAR_FILENAME);\n if (!(await fileExists(sidecarPath))) return {};\n try {\n const raw = await readFile(sidecarPath, 'utf-8');\n const parsed = parseYaml(raw) as unknown;\n if (parsed && typeof parsed === 'object') {\n const d = parsed as Record<string, unknown>;\n return {\n display_name: typeof d['display_name'] === 'string' ? d['display_name'] : undefined,\n description: typeof d['description'] === 'string' ? d['description'] : undefined,\n spec_format: typeof d['spec_format'] === 'string' ? d['spec_format'] : undefined,\n };\n }\n } catch {\n // Non-fatal — proceed without sidecar data\n }\n return {};\n}\n\n/**\n * Return a numerically-sorted list of story-*.md filenames in the directory.\n *\n * Uses numeric sort so story-10.md follows story-9.md, not story-1.md.\n * Extracts the leading number from the filename stem (e.g. \"story-02\" → 2).\n * Files without a parseable number sort after numbered files, then lexicographically.\n */\nasync function listStoryFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries\n .filter((e) => e.isFile() && e.name.startsWith('story-') && e.name.endsWith('.md'))\n .map((e) => e.name)\n .sort((a, b) => {\n const numA = parseInt(a.replace(/^story-(\\d+).*/, '$1'), 10);\n const numB = parseInt(b.replace(/^story-(\\d+).*/, '$1'), 10);\n if (!isNaN(numA) && !isNaN(numB)) return numA - numB;\n if (!isNaN(numA)) return -1;\n if (!isNaN(numB)) return 1;\n return a.localeCompare(b);\n });\n } catch {\n return [];\n }\n}\n\n/** Return files from the candidates list that actually exist in dir */\nasync function presentFiles(dir: string, candidates: string[]): Promise<string[]> {\n const found: string[] = [];\n for (const f of candidates) {\n if (await fileExists(join(dir, f))) found.push(f);\n }\n return found;\n}\n\n/** Shared preamble block */\nfunction preamble(sidecar: SidecarData): string {\n const lines: string[] = [\n '# SpecMarket Runner Instructions',\n '',\n 'You are an AI coding agent executing a software specification.',\n 'Read this file carefully before starting work. Follow the instructions exactly.',\n ];\n if (sidecar.display_name) {\n lines.push('', `**Spec:** ${sidecar.display_name}`);\n }\n if (sidecar.description) {\n lines.push(`**Description:** ${sidecar.description}`);\n }\n return lines.join('\\n');\n}\n\n/** Shared testing section */\nfunction testingSection(): string {\n return [\n '## Running Tests',\n '',\n 'After completing each major task, run the test suite:',\n '',\n '- `package.json` present → `npm test -- --run` (or `npx vitest run` if vitest is configured)',\n '- `pytest.ini` or `pyproject.toml` present → `python -m pytest`',\n '- `Makefile` with `test` target → `make test`',\n '- No test runner found → verify functionality manually by running the application',\n '',\n 'Fix all test failures before proceeding to the next task.',\n ].join('\\n');\n}\n\n/** Shared completion reminder */\nfunction completionReminder(): string {\n return [\n '## Important Reminders',\n '',\n '- Only mark a task complete when you have **fully implemented and tested** it.',\n '- Do not skip tasks. Do not leave stubs or placeholders.',\n '- If you discover a blocking issue, note it in the relevant task file and continue with other tasks if possible.',\n '- Run the full test suite one final time before declaring the spec complete.',\n ].join('\\n');\n}\n\n// ── Format-specific generators ──────────────────────────────────────────────\n\n/**\n * Generate meta-instructions for the native `specmarket` format.\n *\n * Layout: spec.yaml + PROMPT.md + SPEC.md + SUCCESS_CRITERIA.md + stdlib/\n * Tasks tracked in TASKS.md (or implicitly via SUCCESS_CRITERIA.md checkboxes).\n */\nasync function generateSpecmarketInstructions(\n dir: string,\n sidecar: SidecarData\n): Promise<string> {\n const coreFiles = await presentFiles(dir, [\n 'PROMPT.md',\n 'SPEC.md',\n 'SUCCESS_CRITERIA.md',\n 'TASKS.md',\n 'spec.yaml',\n 'stdlib/STACK.md',\n 'stdlib/PATTERNS.md',\n 'stdlib/SECURITY.md',\n ]);\n\n const fileList = coreFiles.length > 0\n ? coreFiles.map((f) => `- \\`${f}\\``).join('\\n')\n : '- *(no standard spec files found — inspect directory contents)*';\n\n // Build reading order prose only for files that are actually present\n const readingOrderParts: string[] = [];\n if (coreFiles.includes('PROMPT.md')) {\n readingOrderParts.push('`PROMPT.md` for the high-level goal');\n }\n if (coreFiles.includes('SPEC.md')) {\n readingOrderParts.push('`SPEC.md` for full requirements');\n }\n if (coreFiles.includes('SUCCESS_CRITERIA.md')) {\n readingOrderParts.push('`SUCCESS_CRITERIA.md` to understand exactly what \"done\" means');\n }\n const readingOrder = readingOrderParts.length > 0\n ? `Start with ${readingOrderParts.join(', then ')}.`\n : 'Read all available files to understand the spec requirements.';\n const stackNote = coreFiles.some((f) => f.startsWith('stdlib/'))\n ? '\\nRead `stdlib/STACK.md` for technology and coding standards before writing any code.'\n : '';\n\n return [\n preamble(sidecar),\n '',\n '## Spec Format: SpecMarket (Native)',\n '',\n '## Files to Read First',\n '',\n fileList,\n '',\n readingOrder + stackNote,\n '',\n '## Finding Tasks',\n '',\n 'Tasks are tracked in `TASKS.md` using this format:',\n '',\n '```',\n '- [ ] Incomplete task',\n '- [x] Completed task',\n '```',\n '',\n coreFiles.includes('SPEC.md')\n ? 'If `TASKS.md` does not exist, derive tasks from `SPEC.md` and `SUCCESS_CRITERIA.md`.'\n : 'If `TASKS.md` does not exist, derive tasks from the available spec files.',\n 'Work through tasks from top to bottom. Complete each fully before moving to the next.',\n '',\n '## Marking Tasks Complete',\n '',\n 'When a task is done, update `TASKS.md`:',\n '- Change `- [ ]` to `- [x]` for the completed task.',\n '',\n '## Completion Criteria',\n '',\n 'The run is complete when ALL of the following are true:',\n '',\n '1. **All tasks checked** — No `- [ ]` lines remain in `TASKS.md`.',\n '2. **Tests pass** — Run the test suite; all tests green.',\n '3. **Success criteria met** — Every criterion in `SUCCESS_CRITERIA.md` is checked `- [x]`.',\n ' Update each criterion in `SUCCESS_CRITERIA.md` as it is satisfied.',\n '',\n testingSection(),\n '',\n completionReminder(),\n ].join('\\n');\n}\n\n/**\n * Generate meta-instructions for the `speckit` format.\n *\n * Layout: spec.md + tasks.md (or plan.md) + optional .specify/\n * Tasks tracked in tasks.md or plan.md.\n */\nasync function generateSpeckitInstructions(\n dir: string,\n sidecar: SidecarData\n): Promise<string> {\n const hasTasksMd = await fileExists(join(dir, 'tasks.md'));\n const hasPlanMd = await fileExists(join(dir, 'plan.md'));\n const hasSpecifyDir = await directoryExists(join(dir, '.specify'));\n\n const taskFile = hasTasksMd ? 'tasks.md' : hasPlanMd ? 'plan.md' : 'tasks.md';\n\n const knownFiles = await presentFiles(dir, [\n 'spec.md',\n 'tasks.md',\n 'plan.md',\n 'requirements.md',\n 'README.md',\n ]);\n\n const fileList = knownFiles.length > 0\n ? knownFiles.map((f) => `- \\`${f}\\``).join('\\n')\n : '- `spec.md` — primary specification';\n\n const specifyNote = hasSpecifyDir\n ? '\\nThe `.specify/` directory contains additional context files. Read them for implementation details.\\n'\n : '';\n\n return [\n preamble(sidecar),\n '',\n '## Spec Format: Spec Kit',\n '',\n '## Files to Read First',\n '',\n fileList,\n specifyNote,\n 'Start with `spec.md` for the full specification.',\n `Then read \\`${taskFile}\\` to find your task list.`,\n '',\n '## Finding Tasks',\n '',\n `Tasks are listed in \\`${taskFile}\\`. Look for checkbox items:`,\n '',\n '```',\n '- [ ] Incomplete task',\n '- [x] Completed task',\n '```',\n '',\n 'If the task file uses numbered lists or headings instead of checkboxes,',\n 'treat each actionable item as a task. Work through them in order.',\n '',\n '## Marking Tasks Complete',\n '',\n `When a task is done, update \\`${taskFile}\\`:`,\n '- Change `- [ ]` to `- [x]` for the completed task.',\n '- If using a different format, add `[DONE]` next to the completed item.',\n '',\n '## Completion Criteria',\n '',\n 'The run is complete when:',\n '',\n `1. **All tasks checked** — No unchecked \\`- [ ]\\` items remain in \\`${taskFile}\\`.`,\n '2. **Tests pass** — Run the test suite; all tests green.',\n '3. **Spec satisfied** — Implementation matches all requirements in `spec.md`.',\n '',\n testingSection(),\n '',\n completionReminder(),\n ].join('\\n');\n}\n\n/**\n * Generate meta-instructions for the `bmad` format (BMAD Method).\n *\n * Layout: prd.md + architecture.md + story-*.md files.\n * Each story-*.md is a user story with acceptance criteria.\n */\nasync function generateBmadInstructions(\n dir: string,\n sidecar: SidecarData\n): Promise<string> {\n const storyFiles = await listStoryFiles(dir);\n const coreFiles = await presentFiles(dir, ['prd.md', 'architecture.md', 'epic.md']);\n\n const coreFileList = coreFiles.map((f) => `- \\`${f}\\``).join('\\n') || '- *(no core files found)*';\n\n const storySection = storyFiles.length > 0\n ? [\n '**Story files found:**',\n ...storyFiles.map((f) => `- \\`${f}\\``),\n ].join('\\n')\n : '*(No story-*.md files found — check prd.md for tasks)*';\n\n return [\n preamble(sidecar),\n '',\n '## Spec Format: BMAD Method',\n '',\n '## Files to Read First',\n '',\n coreFileList,\n '',\n 'Start with `prd.md` for product requirements. Read `architecture.md` for technical design.',\n 'Then read each story file in order.',\n '',\n '## Finding Tasks',\n '',\n 'Work is organized as user stories in `story-*.md` files:',\n '',\n storySection,\n '',\n 'Each story file contains:',\n '- Story description and goal',\n '- Acceptance criteria (what must be true for the story to be complete)',\n '- Technical notes',\n '',\n 'If no story files exist, derive tasks from `prd.md`.',\n '',\n '## Marking Tasks Complete',\n '',\n 'For each story:',\n '1. Implement everything required by the acceptance criteria.',\n '2. Mark each acceptance criterion as met in the story file by checking it: `- [ ]` → `- [x]`.',\n '3. Add a `## Status: Done` line at the top of the story file when all criteria are met.',\n '',\n 'If working from `prd.md` directly, add a `Done:` checklist section as you complete items.',\n '',\n '## Completion Criteria',\n '',\n 'The run is complete when:',\n '',\n '1. **All stories done** — Every `story-*.md` has `Status: Done` and all acceptance criteria checked.',\n ' (Or: all tasks in `prd.md` implemented if no story files.)',\n '2. **Tests pass** — Run the test suite; all tests green.',\n '3. **Architecture followed** — Implementation matches the design in `architecture.md`.',\n '',\n testingSection(),\n '',\n completionReminder(),\n ].join('\\n');\n}\n\n/**\n * Generate meta-instructions for the `ralph` format.\n *\n * Layout: prd.json with userStories[] array.\n * Each user story is an atomic unit of work.\n */\nasync function generateRalphInstructions(\n dir: string,\n sidecar: SidecarData\n): Promise<string> {\n // Try to read user story titles from prd.json for a concrete task list\n let userStoryList = '';\n try {\n const raw = await readFile(join(dir, 'prd.json'), 'utf-8');\n const data = JSON.parse(raw) as unknown;\n if (\n data &&\n typeof data === 'object' &&\n 'userStories' in data &&\n Array.isArray((data as { userStories: unknown[] }).userStories)\n ) {\n const stories = (data as { userStories: Array<Record<string, unknown>> }).userStories;\n const titles = stories\n .map((s, i) => {\n const title =\n typeof s['title'] === 'string'\n ? s['title']\n : typeof s['name'] === 'string'\n ? s['name']\n : `Story ${i + 1}`;\n return `- [ ] ${title}`;\n })\n .join('\\n');\n userStoryList = titles\n ? `\\n**User stories in prd.json:**\\n\\n${titles}\\n`\n : '';\n }\n } catch {\n // Non-fatal — prd.json may be unreadable at generation time\n }\n\n const extraFiles = await presentFiles(dir, [\n 'architecture.md',\n 'README.md',\n 'CONTRIBUTING.md',\n ]);\n const extraFileList = extraFiles.length > 0\n ? '\\n**Additional files:**\\n' + extraFiles.map((f) => `- \\`${f}\\``).join('\\n')\n : '';\n\n return [\n preamble(sidecar),\n '',\n '## Spec Format: Ralph',\n '',\n '## Files to Read First',\n '',\n '- `prd.json` — Product requirements document with user stories',\n extraFileList,\n '',\n 'Read `prd.json` carefully. The `userStories` array defines all the work to be done.',\n '',\n '## Finding Tasks',\n '',\n 'Open `prd.json` and read the `userStories` array. Each entry is a task.',\n userStoryList,\n 'Each user story typically has:',\n '- `title` or `name` — what to build',\n '- `description` or `details` — how to build it',\n '- `acceptanceCriteria` — what must be true for the story to be complete',\n '',\n '## Marking Tasks Complete',\n '',\n 'Ralph format does not have a built-in task-tracking file.',\n 'Create a `PROGRESS.md` file in the working directory and track progress there:',\n '',\n '```markdown',\n '# Progress',\n '',\n '- [x] Story title (completed)',\n '- [ ] Next story title',\n '```',\n '',\n 'Update `PROGRESS.md` as you complete each user story.',\n '',\n '## Completion Criteria',\n '',\n 'The run is complete when:',\n '',\n '1. **All user stories implemented** — Every story in `prd.json` has a working implementation.',\n '2. **All acceptance criteria met** — Verify each story\\'s `acceptanceCriteria` is satisfied.',\n '3. **Tests pass** — Run the test suite; all tests green.',\n '4. **PROGRESS.md updated** — All stories checked `[x]` in `PROGRESS.md`.',\n '',\n testingSection(),\n '',\n completionReminder(),\n ].join('\\n');\n}\n\n/**\n * Generate meta-instructions for `custom` format specs.\n *\n * Layout: arbitrary markdown files — no fixed structure.\n * Agent must discover tasks from whatever is present.\n */\nasync function generateCustomInstructions(\n dir: string,\n sidecar: SidecarData\n): Promise<string> {\n // Enumerate markdown files at top level (non-recursive for brevity)\n let mdFiles: string[] = [];\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n mdFiles = entries\n .filter((e) => e.isFile() && e.name.endsWith('.md'))\n .map((e) => e.name)\n .sort();\n } catch {\n // Ignore\n }\n\n const mdFileList = mdFiles.length > 0\n ? mdFiles.map((f) => `- \\`${f}\\``).join('\\n')\n : '- *(no .md files found at top level)*';\n\n return [\n preamble(sidecar),\n '',\n '## Spec Format: Custom',\n '',\n '## Files to Read First',\n '',\n 'Markdown files found in this spec:',\n '',\n mdFileList,\n '',\n 'Read all markdown files to understand the full scope of work.',\n 'Look for a README, specification, or requirements document as your primary source of truth.',\n '',\n '## Finding Tasks',\n '',\n 'This spec uses a custom format. Scan all markdown files for:',\n '',\n '1. **Checkbox items**: `- [ ] task description` — these are explicit tasks',\n '2. **Numbered lists**: actionable steps in requirements documents',\n '3. **Heading-based sections**: major features or modules to implement',\n '',\n 'If you find a file that looks like a task list (TASKS.md, TODO.md, checklist.md, etc.), use it.',\n '',\n '## Marking Tasks Complete',\n '',\n 'If the spec has checkboxes (`- [ ]`), update them to `- [x]` as you complete tasks.',\n '',\n 'If the spec has no checkboxes, create a `PROGRESS.md` file to track progress:',\n '',\n '```markdown',\n '# Progress',\n '',\n '- [x] Task or feature completed',\n '- [ ] Next task',\n '```',\n '',\n '## Completion Criteria',\n '',\n 'The run is complete when:',\n '',\n '1. **All tasks done** — All checkbox items checked, or all items in `PROGRESS.md` checked.',\n '2. **Tests pass** — Run the test suite; all tests green.',\n '3. **Requirements satisfied** — Implementation matches all requirements found in the spec files.',\n '',\n testingSection(),\n '',\n completionReminder(),\n ].join('\\n');\n}\n\n// ── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Generate format-aware meta-instructions for the AI agent executing a spec.\n *\n * Returns the full markdown content for `.specmarket-runner.md`.\n * The content tells the agent: which files to read, how to find tasks,\n * how to mark completion, how to run tests, and when the run is done.\n *\n * @param specDir - Path to the spec source directory (may differ from runDir)\n * @param format - Detected spec format (specmarket | speckit | bmad | ralph | custom | any string)\n */\nexport async function generateMetaInstructions(\n specDir: string,\n format: string\n): Promise<string> {\n const sidecar = await readSidecarData(specDir);\n\n switch (format) {\n case 'specmarket':\n return generateSpecmarketInstructions(specDir, sidecar);\n case 'speckit':\n return generateSpeckitInstructions(specDir, sidecar);\n case 'bmad':\n return generateBmadInstructions(specDir, sidecar);\n case 'ralph':\n return generateRalphInstructions(specDir, sidecar);\n case 'custom':\n default:\n return generateCustomInstructions(specDir, sidecar);\n }\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Searches the SpecMarket registry with full-text search and rich filtering.\n *\n * No authentication required.\n * Displays results in a table: name, description, replaces, success rate, avg cost, rating.\n *\n * Supported filters (all passed through to the Convex specs.search query):\n * - outputType: exact match on spec output type\n * - tags: OR semantics — spec must have at least one matching tag\n * - primaryStack: exact match on tech stack\n * - replacesSaas: case-insensitive substring match on the SaaS name\n * - minSuccessRate: minimum success rate (0-100, converted to 0-1 for backend)\n * - maxCost: maximum one-time build cost in USD\n * - maxMonthlyCost: maximum monthly infrastructure cost in USD\n * - serviceCategory: required infrastructure service categories (AND semantics)\n * - freeTierOnly: only show specs runnable on free-tier infrastructure\n * - limit: max results (default 20, max 50)\n */\nexport async function handleSearch(\n query: string,\n opts: {\n outputType?: string;\n tag?: string[];\n primaryStack?: string;\n replacesSaas?: string;\n minSuccessRate?: string;\n maxCost?: string;\n maxMonthlyCost?: string;\n serviceCategory?: string[];\n freeTierOnly?: boolean;\n limit?: string;\n }\n): Promise<void> {\n const client = await getConvexClient();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n\n const spinner = (await import('ora')).default('Searching...').start();\n\n try {\n // Build search params, converting CLI values to backend types\n const searchParams: Record<string, unknown> = {\n query,\n limit: opts.limit ? parseInt(opts.limit, 10) : 20,\n };\n\n if (opts.outputType) {\n searchParams.outputType = opts.outputType;\n }\n if (opts.tag && opts.tag.length > 0) {\n searchParams.tags = opts.tag;\n }\n if (opts.primaryStack) {\n searchParams.primaryStack = opts.primaryStack;\n }\n if (opts.replacesSaas) {\n searchParams.replacesSaas = opts.replacesSaas;\n }\n if (opts.minSuccessRate) {\n // CLI accepts 0-100 (e.g. \"80\" for 80%), backend expects 0-1\n const rate = parseFloat(opts.minSuccessRate);\n if (isNaN(rate) || rate < 0 || rate > 100) {\n spinner.fail(chalk.red('--min-success-rate must be between 0 and 100'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n searchParams.minSuccessRate = rate / 100;\n }\n if (opts.maxCost) {\n const cost = parseFloat(opts.maxCost);\n if (isNaN(cost) || cost < 0) {\n spinner.fail(chalk.red('--max-cost must be a non-negative number'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n searchParams.maxEstimatedCostUsd = cost;\n }\n if (opts.maxMonthlyCost) {\n const cost = parseFloat(opts.maxMonthlyCost);\n if (isNaN(cost) || cost < 0) {\n spinner.fail(chalk.red('--max-monthly-cost must be a non-negative number'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n searchParams.maxMonthlyCostUsd = cost;\n }\n if (opts.serviceCategory && opts.serviceCategory.length > 0) {\n searchParams.serviceCategories = opts.serviceCategory;\n }\n if (opts.freeTierOnly) {\n searchParams.freeTierOnly = true;\n }\n\n const results = await client.query(api.specs.search, searchParams);\n\n spinner.stop();\n\n if (results.length === 0) {\n console.log(chalk.gray(`No specs found for \"${query}\"`));\n return;\n }\n\n console.log(chalk.bold(`\\nFound ${results.length} spec(s) for \"${query}\":\\n`));\n\n const table = new Table({\n head: [\n chalk.cyan('Name'),\n chalk.cyan('Description'),\n chalk.cyan('Replaces'),\n chalk.cyan('Success'),\n chalk.cyan('Avg Cost'),\n chalk.cyan('Rating'),\n ],\n style: { compact: true },\n colWidths: [25, 35, 15, 9, 10, 8],\n wordWrap: true,\n });\n\n for (const spec of results) {\n table.push([\n chalk.bold(spec.scopedName),\n spec.description.slice(0, 80),\n spec.replacesSaas ?? '—',\n spec.successRate > 0\n ? `${(spec.successRate * 100).toFixed(0)}%`\n : chalk.gray('N/A'),\n spec.avgCostUsd > 0 ? `$${spec.avgCostUsd.toFixed(2)}` : chalk.gray('N/A'),\n spec.communityRating > 0\n ? `${spec.communityRating.toFixed(1)}★`\n : chalk.gray('N/A'),\n ]);\n }\n\n console.log(table.toString());\n console.log(chalk.gray(`\\nRun ${chalk.cyan('specmarket info <spec-id>')} for detailed information.`));\n } catch (err) {\n spinner.fail(chalk.red(`Search failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\nexport function createSearchCommand(): Command {\n return new Command('search')\n .description('Search the SpecMarket registry for specs')\n .argument('<query>', 'Search query')\n .option(\n '-t, --output-type <type>',\n 'Filter by output type (web-app, cli-tool, api-service, library, mobile-app)'\n )\n .option(\n '--tag <tag>',\n 'Filter by tag (repeatable, OR logic)',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\n '--primary-stack <stack>',\n 'Filter by tech stack (nextjs-typescript, astro-typescript, python-fastapi, go, rust, other)'\n )\n .option(\n '--replaces-saas <name>',\n 'Filter by SaaS product being replaced (substring match)'\n )\n .option(\n '--min-success-rate <percent>',\n 'Minimum success rate (0-100)'\n )\n .option(\n '--max-cost <usd>',\n 'Maximum one-time build cost in USD'\n )\n .option(\n '--max-monthly-cost <usd>',\n 'Maximum monthly infrastructure cost in USD'\n )\n .option(\n '--service-category <category>',\n 'Required infrastructure category (repeatable, AND logic)',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\n '--free-tier-only',\n 'Only show specs runnable on free-tier infrastructure'\n )\n .option('-l, --limit <n>', 'Maximum results to show (default: 20)')\n .action(async (query: string, opts) => {\n try {\n await handleSearch(query, opts);\n } catch (err) {\n console.error(chalk.red(`Search failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Displays detailed information about a spec from the registry.\n * Includes: metrics, recent runs, creator profile, versions, forks, infrastructure summary.\n */\nexport async function handleInfo(specId: string): Promise<void> {\n const client = await getConvexClient();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n\n const spinner = (await import('ora')).default(`Loading info for ${specId}...`).start();\n\n try {\n // Determine if it's a scoped name or an ID\n const isScopedName = specId.startsWith('@') || specId.includes('/');\n\n const [spec, stats, versionsResult] = await Promise.all([\n client.query(api.specs.get, isScopedName ? { scopedName: specId } : { specId }),\n client.query(api.runs.getStats, { specId: specId as any }).catch(() => null),\n client.query(api.specs.getVersions, { specId: specId as any, paginationOpts: { numItems: 25, cursor: null } }).catch(() => ({ page: [] })),\n ]);\n const versions = versionsResult.page;\n\n // Fetch collaboration data (best-effort — don't fail if these aren't available)\n let openIssueCount = 0;\n let maintainers: Array<{ user: { username: string } | null }> = [];\n let commentCount = 0;\n\n if (spec) {\n const [issuesResult, maintainersResult, commentsResult] = await Promise.all([\n client\n .query(api.issues.list, {\n specId: spec._id,\n status: 'open' as const,\n paginationOpts: { numItems: 1, cursor: null },\n })\n .catch(() => null),\n client\n .query(api.specMaintainers.list, { specId: spec._id })\n .catch(() => []),\n client\n .query(api.comments.list, {\n targetType: 'spec' as const,\n targetId: spec._id,\n paginationOpts: { numItems: 1, cursor: null },\n })\n .catch(() => null),\n ]);\n\n // issues.list returns paginated results — use page length as approximation\n // For accurate count we'd need a dedicated count query, but this shows \"at least N\"\n if (issuesResult) {\n openIssueCount = issuesResult.page.length;\n if (!issuesResult.isDone && openIssueCount > 0) {\n // There are more pages — indicate \"N+\"\n openIssueCount = -1; // sentinel for \"many\"\n }\n }\n maintainers = maintainersResult;\n if (commentsResult) {\n commentCount = commentsResult.page.length;\n if (!commentsResult.isDone && commentCount > 0) {\n commentCount = -1; // sentinel for \"many\"\n }\n }\n }\n\n spinner.stop();\n\n if (!spec) {\n console.log(chalk.red(`Spec not found: ${specId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Get author profile\n const author = await client\n .query(api.users.getProfile, { userId: spec.authorId })\n .catch(() => null);\n\n console.log('');\n console.log(chalk.bold(`${spec.displayName} ${chalk.gray(spec.scopedName)}`));\n console.log(chalk.gray('─'.repeat(60)));\n console.log(spec.description);\n console.log('');\n\n if (spec.replacesSaas) {\n console.log(\n `${chalk.bold('Replaces:')} ${spec.replacesSaas}${spec.replacesPricing ? ` (${spec.replacesPricing})` : ''}`\n );\n }\n\n console.log(`${chalk.bold('Output Type:')} ${spec.outputType}`);\n console.log(`${chalk.bold('Stack:')} ${spec.primaryStack}`);\n console.log(`${chalk.bold('Version:')} ${spec.currentVersion}`);\n console.log(`${chalk.bold('Runner:')} ${spec.runner} (min: ${spec.minModel})`);\n console.log(`${chalk.bold('Status:')} ${spec.status}`);\n if (spec.tags.length > 0) {\n console.log(`${chalk.bold('Tags:')} ${spec.tags.join(', ')}`);\n }\n\n console.log('');\n console.log(chalk.bold('Estimates:'));\n console.log(` Tokens: ~${spec.estimatedTokens.toLocaleString()}`);\n console.log(` Cost: ~$${spec.estimatedCostUsd.toFixed(2)}`);\n console.log(` Time: ~${spec.estimatedTimeMinutes} minutes`);\n\n console.log('');\n console.log(chalk.bold('Community Metrics:'));\n console.log(\n ` Total Runs: ${spec.totalRuns.toLocaleString()} (${spec.successfulRuns} successful)`\n );\n console.log(\n ` Success Rate: ${spec.totalRuns > 0 ? (spec.successRate * 100).toFixed(1) + '%' : 'N/A'}`\n );\n console.log(\n ` Avg Cost: ${spec.avgCostUsd > 0 ? '$' + spec.avgCostUsd.toFixed(2) : 'N/A'}`\n );\n console.log(\n ` Community Rating: ${spec.communityRating > 0 ? spec.communityRating.toFixed(1) + '/5 (' + spec.ratingCount + ' ratings)' : 'No ratings yet'}`\n );\n console.log(` Forks: ${spec.forkCount}`);\n\n if (spec.forkedFromId) {\n console.log(chalk.gray(` (Forked from v${spec.forkedFromVersion})`));\n }\n\n // Collaboration info\n const issueDisplay =\n openIssueCount === -1 ? 'many' : String(openIssueCount);\n const commentDisplay =\n commentCount === -1 ? 'many' : String(commentCount);\n console.log(\n ` Open Issues: ${issueDisplay}`\n );\n console.log(\n ` Comments: ${commentDisplay}`\n );\n if (maintainers.length > 0) {\n const names = maintainers\n .filter((m) => m.user)\n .map((m) => `@${m.user!.username}`)\n .join(', ');\n console.log(` Maintainers: ${names}`);\n }\n\n if (author) {\n console.log('');\n console.log(chalk.bold('Creator:'));\n console.log(` @${author.username} (${author.displayName})`);\n if (author.bio) console.log(` ${author.bio}`);\n if (author.githubUrl) console.log(` GitHub: ${author.githubUrl}`);\n }\n\n // Infrastructure summary\n if (spec.infrastructure) {\n const infra = spec.infrastructure;\n console.log('');\n console.log(chalk.bold('Infrastructure:'));\n console.log(\n ` Monthly Cost: Free tier $${infra.monthlyCost.freeTierUsd}/mo → Production $${infra.monthlyCost.productionUsd}/mo`\n );\n if (infra.setupTimeMinutes) {\n console.log(` Setup Time: ~${infra.setupTimeMinutes} minutes`);\n }\n if (infra.deploymentTargets && infra.deploymentTargets.length > 0) {\n console.log(\n ` Deploy to: ${infra.deploymentTargets.map((t: { name: string; notes?: string }) => t.notes ? `${t.name} (${t.notes})` : t.name).join(', ')}`\n );\n }\n if (infra.services.length > 0) {\n console.log(` Services:`);\n for (const svc of infra.services) {\n const defaultProvider = svc.defaultProvider\n ? ` (default: ${svc.defaultProvider})`\n : '';\n const required = svc.required ? '' : ' [optional]';\n console.log(\n ` • ${svc.name} (${svc.category})${required} — ${svc.purpose}${defaultProvider}`\n );\n }\n }\n if (infra.userProvided.length > 0) {\n console.log(` User-provided: ${infra.userProvided.join(', ')}`);\n }\n }\n\n // Version history\n if (versions.length > 0) {\n console.log('');\n console.log(chalk.bold(`Versions (${versions.length}):`));\n for (const v of versions.slice(0, 5)) {\n const date = new Date(v.publishedAt).toLocaleDateString();\n console.log(` v${v.version} — ${date}${v.changelog ? ': ' + v.changelog.slice(0, 60) : ''}`);\n }\n if (versions.length > 5) {\n console.log(chalk.gray(` ... and ${versions.length - 5} more`));\n }\n }\n\n // Run stats summary\n if (stats && stats.totalRuns > 0) {\n console.log('');\n console.log(chalk.bold('Run Statistics:'));\n if (stats.modelBreakdown.length > 0) {\n const topModel = stats.modelBreakdown.sort((a: any, b: any) => b.count - a.count)[0];\n console.log(\n ` Most used model: ${topModel.model} (${(topModel.percentage * 100).toFixed(0)}% of runs)`\n );\n }\n console.log(\n ` Cost range: $${stats.costDistribution.min.toFixed(2)} - $${stats.costDistribution.max.toFixed(2)} (median $${stats.costDistribution.p50.toFixed(2)})`\n );\n }\n\n console.log('');\n console.log(\n chalk.cyan(`Run this spec: ${chalk.bold(`specmarket run ${spec.scopedName}`)}`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to load spec info: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\nexport function createInfoCommand(): Command {\n return new Command('info')\n .description('Show detailed information about a spec')\n .argument('<spec-id>', 'Spec scoped name (@user/name) or document ID')\n .action(async (specId: string) => {\n try {\n await handleInfo(specId);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { readFile } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { createWriteStream } from 'fs';\nimport { specYamlSchema, EXIT_CODES, transformInfrastructure } from '@specmarket/shared';\nimport { validateSpec } from './validate.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\n\n/**\n * Publishes a spec to the SpecMarket registry.\n *\n * Flow:\n * 1. Require authentication\n * 2. Validate spec (exit 1 if invalid)\n * 3. Check for name conflicts via specs.get\n * 4. Zip the spec directory using archiver\n * 5. Upload zip to Convex file storage via generateUploadUrl\n * 6. Call specs.publish mutation with all metadata + changelog\n * 7. Show success message with URL\n */\nexport async function handlePublish(specPath: string, opts: { changelog?: string } = {}): Promise<void> {\n const creds = await requireAuth();\n const dir = resolve(specPath);\n\n const spinner = ora('Validating spec...').start();\n\n try {\n // Validate\n const validation = await validateSpec(dir);\n if (!validation.valid) {\n spinner.fail(chalk.red('Spec validation failed:'));\n for (const err of validation.errors) {\n console.log(chalk.red(` ✗ ${err}`));\n }\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n if (validation.warnings.length > 0) {\n spinner.warn(chalk.yellow(`Validation passed with ${validation.warnings.length} warning(s)`));\n } else {\n spinner.succeed('Spec validated');\n }\n\n // Load spec.yaml\n spinner.start('Reading spec metadata...');\n const specYamlContent = await readFile(join(dir, 'spec.yaml'), 'utf-8');\n const specYamlRaw = parseYaml(specYamlContent);\n const specYaml = specYamlSchema.parse(specYamlRaw);\n spinner.succeed(`Loaded spec: ${specYaml.display_name} v${specYaml.version}`);\n\n // Get Convex client\n const client = await getConvexClient(creds.token);\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error('Could not load Convex API bindings. Is CONVEX_URL configured?');\n }\n\n // Zip the spec directory\n spinner.start('Creating spec archive...');\n const zipPath = await createSpecZip(dir);\n spinner.succeed('Spec archive created');\n\n // Upload to Convex storage via the generateUploadUrl mutation\n spinner.start('Uploading spec to registry...');\n const uploadUrl: string = await client.mutation(api.specs.generateUploadUrl, {});\n\n const zipContent = await readFile(zipPath);\n const uploadResponse = await fetch(uploadUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/zip' },\n body: zipContent,\n });\n\n if (!uploadResponse.ok) {\n throw new Error(`Upload failed: ${uploadResponse.statusText}`);\n }\n\n const { storageId } = await uploadResponse.json() as { storageId: string };\n spinner.succeed('Spec uploaded');\n\n // Publish to registry\n spinner.start('Publishing to registry...');\n\n const readme = await readFile(join(dir, 'SPEC.md'), 'utf-8').catch(() => undefined);\n\n const publishResult = await client.mutation(api.specs.publish, {\n slug: specYaml.name,\n displayName: specYaml.display_name,\n description: specYaml.description,\n replacesSaas: specYaml.replaces_saas,\n replacesPricing: specYaml.replaces_pricing,\n tags: specYaml.tags,\n outputType: specYaml.output_type,\n primaryStack: specYaml.primary_stack,\n version: specYaml.version,\n specStorageId: storageId,\n readme,\n runner: specYaml.runner,\n specFormat: validation.format,\n minModel: specYaml.min_model,\n estimatedTokens: specYaml.estimated_tokens,\n estimatedCostUsd: specYaml.estimated_cost_usd,\n estimatedTimeMinutes: specYaml.estimated_time_minutes,\n infrastructure: specYaml.infrastructure\n ? transformInfrastructure(specYaml.infrastructure)\n : undefined,\n changelog: opts.changelog,\n });\n\n spinner.succeed(\n chalk.green(\n publishResult.created\n ? `Published successfully!`\n : `Updated successfully!`\n )\n );\n\n console.log('');\n console.log(chalk.bold('Published:'));\n console.log(` Spec ID: ${chalk.gray(publishResult.specId)}`);\n console.log(` Version: ${specYaml.version}`);\n console.log(` Run it: ${chalk.cyan(`specmarket run @${creds.username}/${specYaml.name}`)}`);\n\n // Cleanup temp zip\n const { unlink } = await import('fs/promises');\n await unlink(zipPath).catch(() => {});\n } catch (err) {\n spinner.fail(chalk.red(`Publish failed: ${(err as Error).message}`));\n throw err;\n }\n}\n\nasync function createSpecZip(dir: string): Promise<string> {\n const { tmpdir } = await import('os');\n const { randomUUID } = await import('crypto');\n const zipPath = join(tmpdir(), `spec-${randomUUID()}.zip`);\n\n const archiver = (await import('archiver')).default;\n const output = createWriteStream(zipPath);\n const archive = archiver('zip', { zlib: { level: 9 } });\n\n await new Promise<void>((resolve, reject) => {\n output.on('close', resolve);\n archive.on('error', reject);\n\n archive.pipe(output);\n archive.glob('**/*', {\n cwd: dir,\n ignore: ['node_modules/**', 'dist/**', '.git/**', '*.tsbuildinfo'],\n });\n archive.finalize();\n });\n\n return zipPath;\n}\n\nexport function createPublishCommand(): Command {\n return new Command('publish')\n .description('Publish a spec to the SpecMarket registry (requires login)')\n .argument('<path>', 'Path to the spec directory')\n .option('-c, --changelog <message>', 'Changelog message describing what changed in this version')\n .action(async (specPath: string, opts: { changelog?: string }) => {\n try {\n await handlePublish(specPath, opts);\n } catch (err) {\n console.error(chalk.red(`Publish failed: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { mkdir, writeFile, readFile } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport { requireAuth } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Forks a published spec to a local directory and records the fork in Convex.\n *\n * Flow:\n * 1. Require authentication\n * 2. Fetch spec metadata via specs.get\n * 3. Download the spec zip via specs.download\n * 4. Extract to local directory\n * 5. Update spec.yaml with forked_from_id and forked_from_version\n * 6. Call specs.fork mutation to record the fork relationship\n */\nexport async function handleFork(\n specId: string,\n targetPath?: string\n): Promise<void> {\n const creds = await requireAuth();\n const spinner = ora('Loading spec info...').start();\n\n try {\n const client = await getConvexClient(creds.token);\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error('Could not load Convex API bindings.');\n }\n\n // Determine if scopedName or ID\n const isScopedName = specId.startsWith('@') || specId.includes('/');\n\n // Fetch spec metadata\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: specId } : { specId }\n );\n\n if (!spec) {\n spinner.fail(chalk.red(`Spec not found: ${specId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n spinner.text = `Downloading ${spec.displayName}...`;\n\n // Download the spec zip\n const { url } = await client.action(api.specs.download, {\n specId: spec._id,\n });\n\n const targetDir = resolve(targetPath ?? spec.slug);\n\n spinner.text = `Extracting to ${targetDir}...`;\n\n // Download and extract\n await downloadAndExtract(url, targetDir);\n\n // Update spec.yaml to record fork relationship\n const specYamlPath = join(targetDir, 'spec.yaml');\n const specYamlContent = await readFile(specYamlPath, 'utf-8');\n const specYamlData = parseYaml(specYamlContent) as Record<string, unknown>;\n\n specYamlData['forked_from_id'] = spec._id;\n specYamlData['forked_from_version'] = spec.currentVersion;\n // Reset version for the fork\n specYamlData['version'] = '1.0.0';\n\n await writeFile(specYamlPath, stringifyYaml(specYamlData));\n\n // Record fork in Convex (but we need a storage ID for the forked content)\n // The fork mutation in Convex requires a specStorageId\n // For now, we record the fork intent locally and note it needs to be published\n spinner.succeed(\n chalk.green(`Forked ${chalk.bold(spec.scopedName)} to ${chalk.bold(targetDir)}`)\n );\n\n console.log('');\n console.log(chalk.bold('Fork created locally:'));\n console.log(` Source: ${spec.scopedName} @ v${spec.currentVersion}`);\n console.log(` Local path: ${targetDir}`);\n console.log(` Fork version: 1.0.0`);\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Customize the spec in ${chalk.cyan(targetDir)}`);\n console.log(` 2. ${chalk.cyan(`specmarket validate ${targetDir}`)} to validate changes`);\n console.log(` 3. ${chalk.cyan(`specmarket publish ${targetDir}`)} to publish your fork`);\n console.log('');\n console.log(chalk.gray('(Publishing will record the fork relationship on the platform)'));\n } catch (err) {\n spinner.fail(chalk.red(`Fork failed: ${(err as Error).message}`));\n throw err;\n }\n}\n\nasync function downloadAndExtract(url: string, targetDir: string): Promise<void> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Download failed: ${response.statusText}`);\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n\n // Write zip to temp file then extract\n const { tmpdir } = await import('os');\n const { randomUUID } = await import('crypto');\n const zipPath = join(tmpdir(), `fork-${randomUUID()}.zip`);\n\n const { writeFile: writeFileFn, unlink } = await import('fs/promises');\n await writeFileFn(zipPath, buffer);\n\n await mkdir(targetDir, { recursive: true });\n\n // Extract using unzip (cross-platform via node:child_process)\n const { execAsync } = await import('../lib/exec.js');\n await execAsync(`unzip -q \"${zipPath}\" -d \"${targetDir}\"`);\n await unlink(zipPath).catch(() => {});\n}\n\nexport function createForkCommand(): Command {\n return new Command('fork')\n .description('Fork a published spec to a local directory')\n .argument('<spec-id>', 'Spec scoped name (@user/name) or document ID')\n .argument('[path]', 'Target local directory (defaults to spec slug)')\n .action(async (specId: string, targetPath: string | undefined) => {\n try {\n await handleFork(specId, targetPath);\n } catch (err) {\n console.error(chalk.red(`Fork failed: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { readFile } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { CONFIG_PATHS, EXIT_CODES } from '@specmarket/shared';\nimport { loadCredentials } from '../lib/auth.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport type { RunReport } from '@specmarket/shared';\n\n/**\n * Displays a run report.\n *\n * Priority:\n * 1. Local run artifacts at ~/.specmarket/runs/<run-id>/run-report.json\n * 2. If authenticated, fetch from Convex platform via runs.getById\n *\n * Displays: status, loops, tokens, cost, time, success criteria results, metadata.\n */\nexport async function handleReport(runId: string): Promise<void> {\n // Try local first\n const localPath = join(homedir(), CONFIG_PATHS.RUNS_DIR, runId, 'run-report.json');\n let report: RunReport | null = null;\n let source: 'local' | 'platform' = 'local';\n\n try {\n const raw = await readFile(localPath, 'utf-8');\n report = JSON.parse(raw) as RunReport;\n source = 'local';\n } catch {\n // Not found locally — try platform\n const creds = await loadCredentials();\n if (!creds) {\n console.error(\n chalk.red(\n `Run report not found locally at ~/.specmarket/runs/${runId}/. ` +\n `Log in with \\`specmarket login\\` to fetch from the platform.`\n )\n );\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n\n try {\n const client = await getConvexClient(creds.token);\n const api = (await import('@specmarket/convex/api')).api;\n const run = await client.query(api.runs.getById, { runId: runId as any });\n\n if (!run) {\n console.error(chalk.red(`Run not found: ${runId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Map Convex run document to RunReport interface\n report = {\n runId: run._id,\n specId: run.specId,\n specVersion: run.specVersion,\n model: run.model,\n runner: run.runner,\n loopCount: run.loopCount,\n totalTokens: run.totalTokens,\n totalCostUsd: run.totalCostUsd,\n totalTimeMinutes: run.totalTimeMinutes,\n status: run.status,\n successCriteriaResults: run.successCriteriaResults,\n os: run.os,\n nodeVersion: run.nodeVersion,\n cliVersion: run.cliVersion,\n };\n source = 'platform';\n } catch (err) {\n console.error(chalk.red(`Failed to fetch run from platform: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n }\n\n if (!report) {\n console.error(chalk.red(`Run not found: ${runId}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Display report\n const statusColor =\n report.status === 'success'\n ? chalk.green\n : report.status === 'stall' || report.status === 'budget_exceeded'\n ? chalk.yellow\n : chalk.red;\n\n console.log('');\n console.log(chalk.bold(`Run Report ${chalk.gray(`[${source}]`)}`));\n console.log(chalk.gray('─'.repeat(50)));\n console.log(`${chalk.bold('Run ID:')} ${report.runId}`);\n console.log(`${chalk.bold('Status:')} ${statusColor(report.status.toUpperCase())}`);\n if (report.specId) {\n console.log(`${chalk.bold('Spec:')} ${report.specId}`);\n }\n console.log(`${chalk.bold('Version:')} ${report.specVersion}`);\n console.log(`${chalk.bold('Model:')} ${report.model}`);\n console.log(`${chalk.bold('Loops:')} ${report.loopCount}`);\n console.log(`${chalk.bold('Tokens:')} ${report.totalTokens.toLocaleString()}`);\n console.log(`${chalk.bold('Cost:')} $${report.totalCostUsd.toFixed(4)}`);\n console.log(`${chalk.bold('Time:')} ${report.totalTimeMinutes.toFixed(1)} minutes`);\n console.log(`${chalk.bold('CLI:')} v${report.cliVersion}`);\n\n if (report.os || report.nodeVersion) {\n console.log(`${chalk.bold('System:')} ${[report.os, report.nodeVersion].filter(Boolean).join(' / ')}`);\n }\n\n if (report.successCriteriaResults.length > 0) {\n console.log('');\n console.log(chalk.bold('Success Criteria:'));\n const passed = report.successCriteriaResults.filter((r) => r.passed).length;\n const total = report.successCriteriaResults.length;\n console.log(chalk.gray(` ${passed}/${total} criteria passed`));\n for (const criterion of report.successCriteriaResults) {\n const icon = criterion.passed ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${icon} ${criterion.criterion}`);\n if (criterion.details) {\n console.log(chalk.gray(` ${criterion.details}`));\n }\n }\n }\n\n if (source === 'local') {\n console.log('');\n console.log(\n chalk.gray(\n `Full artifacts: ~/.specmarket/runs/${runId}/`\n )\n );\n }\n}\n\nexport function createReportCommand(): Command {\n return new Command('report')\n .description('Display a run report (local or from platform)')\n .argument('<run-id>', 'Run ID (local UUID or Convex document ID)')\n .action(async (runId: string) => {\n try {\n await handleReport(runId);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadConfig, saveConfig } from '../lib/config.js';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\nimport type { CliConfig } from '@specmarket/shared';\n\n/**\n * CLI configuration management.\n *\n * Subcommands:\n * - config set telemetry true|false\n * - config set default-model <model>\n * - config get <key>\n * - config list\n * - config delete-telemetry (SECURITY.md: delete all user telemetry data from platform)\n */\n\nexport async function handleConfigSet(\n key: string,\n value: string\n): Promise<void> {\n const config = await loadConfig();\n\n switch (key) {\n case 'telemetry': {\n if (value !== 'true' && value !== 'false') {\n console.error(chalk.red('telemetry must be \"true\" or \"false\"'));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n config.telemetry = value === 'true';\n await saveConfig(config);\n console.log(\n chalk.green(\n `Telemetry ${config.telemetry ? chalk.bold('enabled') : chalk.bold('disabled')}.`\n )\n );\n if (config.telemetry) {\n console.log(\n chalk.gray(\n 'Run metadata (tokens, cost, status) will be submitted after authenticated runs. No source code is ever sent.'\n )\n );\n }\n break;\n }\n\n case 'default-model': {\n config.defaultModel = value;\n await saveConfig(config);\n console.log(chalk.green(`Default model set to: ${chalk.bold(value)}`));\n break;\n }\n\n case 'convex-url': {\n config.convexUrl = value;\n await saveConfig(config);\n console.log(chalk.green(`Convex URL set to: ${chalk.bold(value)}`));\n break;\n }\n\n default:\n console.error(\n chalk.red(\n `Unknown config key: \"${key}\". Valid keys: telemetry, default-model, convex-url`\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n}\n\nexport async function handleConfigGet(key: string): Promise<void> {\n const config = await loadConfig();\n const value = (config as Record<string, unknown>)[key];\n\n if (value === undefined) {\n console.log(chalk.gray(`${key}: (not set)`));\n } else {\n console.log(`${key}: ${chalk.bold(String(value))}`);\n }\n}\n\nexport async function handleConfigList(): Promise<void> {\n const config = await loadConfig();\n\n console.log(chalk.bold('Current configuration:'));\n console.log(` telemetry: ${config.telemetry ?? chalk.gray('(not set, default: false)')}`);\n console.log(\n ` default-model: ${config.defaultModel ?? chalk.gray('(not set, uses spec min_model)')}`\n );\n console.log(\n ` convex-url: ${config.convexUrl ?? chalk.gray('(not set, uses CONVEX_URL env or default)')}`\n );\n console.log('');\n console.log(chalk.gray('Config file: ~/.specmarket/config.json'));\n}\n\nexport async function handleDeleteTelemetry(): Promise<void> {\n const creds = await requireAuth();\n\n const { default: inquirer } = await import('inquirer');\n\n const { confirm } = await inquirer.prompt<{ confirm: boolean }>([\n {\n type: 'confirm',\n name: 'confirm',\n message:\n chalk.yellow(\n 'This will permanently delete ALL your run telemetry data from the SpecMarket platform. Are you sure?'\n ),\n default: false,\n },\n ]);\n\n if (!confirm) {\n console.log(chalk.gray('Cancelled.'));\n return;\n }\n\n const client = await getConvexClient(creds.token);\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n throw new Error('Could not load Convex API bindings.');\n }\n\n const spinner = (await import('ora')).default('Deleting telemetry data...').start();\n\n try {\n const result = await client.mutation(api.runs.deleteForUser, {});\n spinner.succeed(\n chalk.green(`Deleted ${result.deleted} run report(s) from the platform.`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to delete telemetry: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\nexport function createConfigCommand(): Command {\n const configCmd = new Command('config').description(\n 'Manage CLI configuration at ~/.specmarket/config.json'\n );\n\n configCmd\n .command('set <key> <value>')\n .description('Set a configuration value (keys: telemetry, default-model)')\n .action(async (key: string, value: string) => {\n try {\n await handleConfigSet(key, value);\n } catch (err) {\n console.error(chalk.red(`Config error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n configCmd\n .command('get <key>')\n .description('Get a configuration value')\n .action(async (key: string) => {\n try {\n await handleConfigGet(key);\n } catch (err) {\n console.error(chalk.red(`Config error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n configCmd\n .command('list')\n .description('List all configuration values')\n .action(async () => {\n try {\n await handleConfigList();\n } catch (err) {\n console.error(chalk.red(`Config error: ${(err as Error).message}`));\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n configCmd\n .command('delete-telemetry')\n .description('Permanently delete all your run telemetry data from the platform')\n .action(async () => {\n try {\n await handleDeleteTelemetry();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode === String(EXIT_CODES.AUTH_ERROR)) {\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n process.exit(EXIT_CODES.RUNTIME_ERROR);\n }\n });\n\n return configCmd;\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Loads the Convex API module. Exits on failure.\n */\nasync function loadApi(): Promise<any> {\n try {\n return (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Resolves a spec identifier (scoped name or ID) to a spec document.\n * Exits with VALIDATION_ERROR if not found.\n */\nasync function resolveSpec(client: any, api: any, specRef: string): Promise<any> {\n const isScopedName = specRef.startsWith('@') || specRef.includes('/');\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: specRef } : { specId: specRef }\n );\n if (!spec) {\n console.error(chalk.red(`Spec not found: ${specRef}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n return spec;\n}\n\n/**\n * Formats a relative time string from a timestamp (e.g., \"3 days ago\").\n */\nfunction relativeTime(timestamp: number): string {\n const diff = Date.now() - timestamp;\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ago`;\n if (hours > 0) return `${hours}h ago`;\n if (minutes > 0) return `${minutes}m ago`;\n return 'just now';\n}\n\n/**\n * Lists open issues for a spec in table format.\n * Public endpoint — no auth required.\n *\n * Flags: --status open|closed|all, --label <label>\n */\nexport async function handleIssuesList(\n specRef: string,\n opts: { status?: string; label?: string }\n): Promise<void> {\n const api = await loadApi();\n const client = await getConvexClient();\n const spinner = (await import('ora')).default('Loading issues...').start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const statusFilter =\n opts.status === 'all' ? undefined : (opts.status as 'open' | 'closed') ?? 'open';\n\n const result = await client.query(api.issues.list, {\n specId: spec._id,\n status: statusFilter,\n labels: opts.label ? [opts.label] : undefined,\n paginationOpts: { numItems: 50, cursor: null },\n });\n\n spinner.stop();\n\n const issues = result.page;\n\n if (issues.length === 0) {\n const statusLabel = statusFilter ?? 'any';\n console.log(chalk.gray(`No ${statusLabel} issues for ${spec.scopedName}`));\n return;\n }\n\n console.log(\n chalk.bold(`\\n${issues.length} issue(s) for ${spec.scopedName}:\\n`)\n );\n\n const table = new Table({\n head: [\n chalk.cyan('#'),\n chalk.cyan('Title'),\n chalk.cyan('Author'),\n chalk.cyan('Age'),\n chalk.cyan('Labels'),\n ],\n style: { compact: true },\n colWidths: [6, 40, 16, 10, 20],\n wordWrap: true,\n });\n\n for (const issue of issues) {\n const statusIcon = issue.status === 'open' ? chalk.green('●') : chalk.gray('○');\n table.push([\n `${statusIcon} ${issue.number}`,\n issue.title.slice(0, 60),\n issue.author ? `@${issue.author.username}` : chalk.gray('unknown'),\n relativeTime(issue.createdAt),\n issue.labels.length > 0 ? issue.labels.join(', ') : chalk.gray('—'),\n ]);\n }\n\n console.log(table.toString());\n console.log(\n chalk.gray(\n `\\nView: ${chalk.cyan(`specmarket issues ${specRef} <number>`)}`\n )\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to load issues: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Creates a new issue interactively (prompts for title and body).\n * Requires authentication.\n */\nexport async function handleIssuesCreate(specRef: string): Promise<void> {\n const creds = await requireAuth();\n const api = await loadApi();\n const client = await getConvexClient(creds.token);\n\n const spec = await resolveSpec(client, api, specRef);\n\n const { default: inquirer } = await import('inquirer');\n\n const answers = await inquirer.prompt<{ title: string; body: string }>([\n {\n type: 'input',\n name: 'title',\n message: 'Issue title:',\n validate: (v: string) => v.trim().length > 0 || 'Title cannot be empty',\n },\n {\n type: 'editor',\n name: 'body',\n message: 'Issue body (markdown):',\n validate: (v: string) => v.trim().length > 0 || 'Body cannot be empty',\n },\n ]);\n\n const spinner = (await import('ora')).default('Creating issue...').start();\n\n try {\n const result = await client.mutation(api.issues.create, {\n specId: spec._id,\n title: answers.title.trim(),\n body: answers.body.trim(),\n labels: [],\n });\n\n spinner.succeed(\n chalk.green(`Issue #${result.number} created on ${spec.scopedName}`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to create issue: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Displays a single issue with detail and recent comments.\n * Public endpoint — no auth required.\n */\nexport async function handleIssuesView(\n specRef: string,\n issueNumber: number\n): Promise<void> {\n const api = await loadApi();\n const client = await getConvexClient();\n const spinner = (await import('ora')).default(`Loading issue #${issueNumber}...`).start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n\n if (!issue) {\n spinner.fail(chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Fetch recent comments\n const commentsResult = await client.query(api.comments.list, {\n targetType: 'issue',\n targetId: issue._id,\n paginationOpts: { numItems: 10, cursor: null },\n });\n\n spinner.stop();\n\n const statusBadge =\n issue.status === 'open'\n ? chalk.green.bold(' OPEN ')\n : chalk.gray.bold(' CLOSED ');\n\n console.log('');\n console.log(\n `${statusBadge} ${chalk.bold(`#${issue.number}: ${issue.title}`)}`\n );\n console.log(chalk.gray('─'.repeat(60)));\n console.log(\n `${chalk.bold('Author:')} ${issue.author ? `@${issue.author.username}` : 'unknown'} ${chalk.bold('Created:')} ${new Date(issue.createdAt).toLocaleDateString()}`\n );\n if (issue.labels.length > 0) {\n console.log(`${chalk.bold('Labels:')} ${issue.labels.join(', ')}`);\n }\n if (issue.closedAt) {\n console.log(\n `${chalk.bold('Closed:')} ${new Date(issue.closedAt).toLocaleDateString()}`\n );\n }\n console.log('');\n console.log(issue.body);\n console.log('');\n\n // Comments\n if (commentsResult.page.length > 0) {\n console.log(\n chalk.bold(`Comments (${issue.commentCount}):`)\n );\n console.log(chalk.gray('─'.repeat(40)));\n\n for (const comment of commentsResult.page) {\n const author = comment.author\n ? `@${comment.author.username}`\n : 'unknown';\n const edited = comment.editedAt ? chalk.gray(' (edited)') : '';\n console.log(\n ` ${chalk.bold(author)} — ${relativeTime(comment.createdAt)}${edited}`\n );\n console.log(` ${comment.body}`);\n\n if (comment.replies && comment.replies.length > 0) {\n for (const reply of comment.replies) {\n const replyAuthor = reply.author\n ? `@${reply.author.username}`\n : 'unknown';\n const replyEdited = reply.editedAt ? chalk.gray(' (edited)') : '';\n console.log(\n ` ${chalk.bold(replyAuthor)} — ${relativeTime(reply.createdAt)}${replyEdited}`\n );\n console.log(` ${reply.body}`);\n }\n }\n console.log('');\n }\n } else {\n console.log(chalk.gray('No comments yet.'));\n }\n } catch (err) {\n spinner.fail(\n chalk.red(`Failed to load issue: ${(err as Error).message}`)\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Closes an issue. Requires authentication.\n * Authorized: issue author, spec author, or spec maintainer.\n */\nexport async function handleIssuesClose(\n specRef: string,\n issueNumber: number\n): Promise<void> {\n const creds = await requireAuth();\n const api = await loadApi();\n const client = await getConvexClient(creds.token);\n const spinner = (await import('ora')).default(`Closing issue #${issueNumber}...`).start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n\n if (!issue) {\n spinner.fail(chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n await client.mutation(api.issues.close, {\n issueId: issue._id,\n });\n\n spinner.succeed(\n chalk.green(`Issue #${issueNumber} closed on ${spec.scopedName}`)\n );\n } catch (err) {\n spinner.fail(chalk.red(`Failed to close issue: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Reopens a closed issue. Requires authentication.\n * Authorized: issue author, spec author, or spec maintainer.\n */\nexport async function handleIssuesReopen(\n specRef: string,\n issueNumber: number\n): Promise<void> {\n const creds = await requireAuth();\n const api = await loadApi();\n const client = await getConvexClient(creds.token);\n const spinner = (await import('ora')).default(`Reopening issue #${issueNumber}...`).start();\n\n try {\n const spec = await resolveSpec(client, api, specRef);\n\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n\n if (!issue) {\n spinner.fail(chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n await client.mutation(api.issues.reopen, {\n issueId: issue._id,\n });\n\n spinner.succeed(\n chalk.green(`Issue #${issueNumber} reopened on ${spec.scopedName}`)\n );\n } catch (err) {\n spinner.fail(\n chalk.red(`Failed to reopen issue: ${(err as Error).message}`)\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Creates the `specmarket issues` command with subcommands.\n *\n * Usage:\n * specmarket issues @user/spec — list open issues\n * specmarket issues @user/spec create — create issue\n * specmarket issues @user/spec <number> — view issue\n * specmarket issues @user/spec <number> close — close issue\n * specmarket issues @user/spec <number> reopen — reopen issue\n */\nexport function createIssuesCommand(): Command {\n return new Command('issues')\n .description('Manage issues on a spec')\n .argument('<spec-id>', 'Spec scoped name (@user/name) or document ID')\n .argument('[action-or-number]', 'Issue number or \"create\"')\n .argument('[action]', '\"close\" or \"reopen\" (with issue number)')\n .option(\n '-s, --status <status>',\n 'Filter by status: open, closed, all (default: open)'\n )\n .option('--label <label>', 'Filter by label')\n .action(\n async (\n specId: string,\n actionOrNumber: string | undefined,\n action: string | undefined,\n opts: { status?: string; label?: string }\n ) => {\n try {\n if (!actionOrNumber) {\n // specmarket issues @user/spec → list\n await handleIssuesList(specId, opts);\n } else if (actionOrNumber === 'create') {\n // specmarket issues @user/spec create → create\n await handleIssuesCreate(specId);\n } else {\n const issueNumber = parseInt(actionOrNumber, 10);\n if (isNaN(issueNumber) || issueNumber < 1) {\n console.error(\n chalk.red(\n `Invalid issue number or action: \"${actionOrNumber}\". ` +\n 'Use a number or \"create\".'\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n if (!action) {\n // specmarket issues @user/spec 3 → view\n await handleIssuesView(specId, issueNumber);\n } else if (action === 'close') {\n // specmarket issues @user/spec 3 close → close\n await handleIssuesClose(specId, issueNumber);\n } else if (action === 'reopen') {\n // specmarket issues @user/spec 3 reopen → reopen\n await handleIssuesReopen(specId, issueNumber);\n } else {\n console.error(\n chalk.red(\n `Unknown action: \"${action}\". Use \"close\" or \"reopen\".`\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n }\n } catch (err) {\n const error = err as NodeJS.ErrnoException;\n if (error.code === String(EXIT_CODES.AUTH_ERROR)) {\n console.error(chalk.red(error.message));\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n console.error(chalk.red(`Error: ${error.message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n }\n );\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { getConvexClient } from '../lib/convex-client.js';\nimport { requireAuth } from '../lib/auth.js';\nimport { EXIT_CODES } from '@specmarket/shared';\n\n/**\n * Posts a comment on a spec, issue, or bounty.\n *\n * Target reference formats:\n * - spec: @user/spec or specId\n * - issue: @user/spec#3 (scoped name + issue number)\n * - bounty: bountyId\n *\n * Requires authentication.\n */\nexport async function handleComment(\n targetType: string,\n targetRef: string,\n body: string,\n opts: { reply?: string }\n): Promise<void> {\n const creds = await requireAuth();\n\n let api: any;\n try {\n api = (await import('@specmarket/convex/api')).api;\n } catch {\n console.error(\n chalk.red('Error: Could not load Convex API bindings. Is CONVEX_URL configured?')\n );\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n\n const client = await getConvexClient(creds.token);\n const spinner = (await import('ora')).default('Posting comment...').start();\n\n try {\n let resolvedTargetType: 'spec' | 'bounty' | 'issue';\n let resolvedTargetId: string;\n\n if (targetType === 'spec') {\n resolvedTargetType = 'spec';\n const isScopedName = targetRef.startsWith('@') || targetRef.includes('/');\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: targetRef } : { specId: targetRef }\n );\n if (!spec) {\n spinner.fail(chalk.red(`Spec not found: ${targetRef}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n resolvedTargetId = spec._id;\n } else if (targetType === 'issue') {\n resolvedTargetType = 'issue';\n // Parse @user/spec#3 format\n const hashIndex = targetRef.lastIndexOf('#');\n if (hashIndex === -1) {\n spinner.fail(\n chalk.red(\n 'Invalid issue reference. Use format: @user/spec#<number>'\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n const specRef = targetRef.slice(0, hashIndex);\n const issueNumber = parseInt(targetRef.slice(hashIndex + 1), 10);\n\n if (isNaN(issueNumber) || issueNumber < 1) {\n spinner.fail(\n chalk.red(`Invalid issue number in \"${targetRef}\". Use format: @user/spec#<number>`)\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Resolve spec\n const isScopedName = specRef.startsWith('@') || specRef.includes('/');\n const spec = await client.query(\n api.specs.get,\n isScopedName ? { scopedName: specRef } : { specId: specRef }\n );\n if (!spec) {\n spinner.fail(chalk.red(`Spec not found: ${specRef}`));\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n // Resolve issue\n const issue = await client.query(api.issues.get, {\n specId: spec._id,\n number: issueNumber,\n });\n if (!issue) {\n spinner.fail(\n chalk.red(`Issue #${issueNumber} not found on ${spec.scopedName}`)\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n resolvedTargetId = issue._id;\n } else if (targetType === 'bounty') {\n resolvedTargetType = 'bounty';\n resolvedTargetId = targetRef;\n } else {\n spinner.fail(\n chalk.red(\n `Invalid target type: \"${targetType}\". Use \"spec\", \"issue\", or \"bounty\".`\n )\n );\n process.exit(EXIT_CODES.VALIDATION_ERROR);\n }\n\n const args: Record<string, unknown> = {\n targetType: resolvedTargetType,\n targetId: resolvedTargetId,\n body: body.trim(),\n };\n\n if (opts.reply) {\n args.parentId = opts.reply;\n }\n\n await client.mutation(api.comments.create, args);\n\n spinner.succeed(chalk.green(`Comment posted on ${targetType} ${targetRef}`));\n } catch (err) {\n spinner.fail(chalk.red(`Failed to post comment: ${(err as Error).message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n}\n\n/**\n * Creates the `specmarket comment` command.\n *\n * Usage:\n * specmarket comment spec @user/spec \"Great spec!\"\n * specmarket comment issue @user/spec#3 \"I can reproduce this\"\n * specmarket comment bounty <bounty-id> \"I'm working on this\"\n * --reply <comment-id> Reply to a specific comment (threading)\n */\nexport function createCommentCommand(): Command {\n return new Command('comment')\n .description('Post a comment on a spec, issue, or bounty (requires login)')\n .argument(\n '<target-type>',\n 'Target type: spec, issue, or bounty'\n )\n .argument(\n '<target-ref>',\n 'Target reference (e.g., @user/spec, @user/spec#3, bounty-id)'\n )\n .argument('<body>', 'Comment body text')\n .option(\n '--reply <comment-id>',\n 'Reply to a specific comment (threading)'\n )\n .action(\n async (\n targetType: string,\n targetRef: string,\n body: string,\n opts: { reply?: string }\n ) => {\n try {\n await handleComment(targetType, targetRef, body, opts);\n } catch (err) {\n const error = err as NodeJS.ErrnoException;\n if (error.code === String(EXIT_CODES.AUTH_ERROR)) {\n console.error(chalk.red(error.message));\n process.exit(EXIT_CODES.AUTH_ERROR);\n }\n console.error(chalk.red(`Error: ${error.message}`));\n process.exit(EXIT_CODES.NETWORK_ERROR);\n }\n }\n );\n}\n"],"mappings":"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","names":["createDebug","debug","createDebug","debug","api","resolve","Command","chalk","chalk","Command","Command","chalk","chalk","api","Command","Command","chalk","ora","mkdir","writeFile","readdir","join","createDebug","readFile","join","join","readFile","debug","createDebug","readdir","targetDir","chalk","join","writeFile","mkdir","spinner","ora","Command","Command","chalk","readFile","readdir","access","join","resolve","parseYaml","readdir","join","readFile","resolve","access","parseYaml","raw","Command","chalk","Command","chalk","ora","readFile","mkdir","join","resolve","parseYaml","createDebug","debug","saveConfig","mkdir","writeFile","readFile","access","join","homedir","createDebug","readFile","readdir","join","parseYaml","join","readFile","parseYaml","readdir","debug","createDebug","join","homedir","mkdir","report","writeFile","readFile","resolve","access","createDebug","debug","chalk","readFile","join","parseYaml","ora","resolve","access","api","randomUUID","mkdir","execAsync","unlink","Command","Command","chalk","api","chalk","Command","Command","chalk","api","chalk","Command","Command","chalk","ora","readFile","join","resolve","parseYaml","resolve","ora","chalk","readFile","join","parseYaml","api","unlink","randomUUID","Command","Command","chalk","ora","mkdir","writeFile","readFile","join","resolve","parseYaml","ora","api","chalk","resolve","join","readFile","parseYaml","writeFile","randomUUID","writeFileFn","unlink","mkdir","execAsync","Command","Command","chalk","readFile","join","homedir","join","homedir","readFile","chalk","api","Command","Command","chalk","chalk","api","Command","Command","chalk","Table","chalk","api","Table","Command","Command","chalk","api","chalk","Command","createRequire","_require"]}