@specmarket/cli 0.0.3 → 0.0.5

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/README.md +1 -1
  3. package/dist/api-GIDUNUXG.js +0 -0
  4. package/dist/{chunk-MS2DYACY.js → chunk-DLEMNRTH.js} +19 -2
  5. package/dist/chunk-DLEMNRTH.js.map +1 -0
  6. package/dist/chunk-JEUDDJP7.js +0 -0
  7. package/dist/{config-R5KWZSJP.js → config-OAU6SJLC.js} +2 -2
  8. package/dist/exec-K3BOXX3C.js +0 -0
  9. package/dist/index.js +980 -181
  10. package/dist/index.js.map +1 -1
  11. package/package.json +21 -15
  12. package/src/commands/comment.test.ts +211 -0
  13. package/src/commands/comment.ts +176 -0
  14. package/src/commands/fork.test.ts +163 -0
  15. package/src/commands/info.test.ts +192 -0
  16. package/src/commands/info.ts +66 -2
  17. package/src/commands/init.test.ts +106 -0
  18. package/src/commands/init.ts +12 -10
  19. package/src/commands/issues.test.ts +377 -0
  20. package/src/commands/issues.ts +443 -0
  21. package/src/commands/login.test.ts +99 -0
  22. package/src/commands/logout.test.ts +54 -0
  23. package/src/commands/publish.test.ts +146 -0
  24. package/src/commands/report.test.ts +181 -0
  25. package/src/commands/run.test.ts +213 -0
  26. package/src/commands/run.ts +10 -2
  27. package/src/commands/search.test.ts +147 -0
  28. package/src/commands/validate.test.ts +129 -2
  29. package/src/commands/validate.ts +333 -192
  30. package/src/commands/whoami.test.ts +106 -0
  31. package/src/index.ts +6 -0
  32. package/src/lib/convex-client.ts +6 -2
  33. package/src/lib/format-detection.test.ts +223 -0
  34. package/src/lib/format-detection.ts +172 -0
  35. package/src/lib/ralph-loop.ts +49 -20
  36. package/src/lib/telemetry.ts +2 -1
  37. package/dist/chunk-MS2DYACY.js.map +0 -1
  38. /package/dist/{config-R5KWZSJP.js.map → config-OAU6SJLC.js.map} +0 -0
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/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"],"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 { 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// 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\nlet _client: ConvexHttpClient | null = null;\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 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-code\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 fix_plan.md for outstanding items\n3. Implement features, run tests, iterate\n4. Update fix_plan.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 fix_plan.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 FIX_PLAN_TEMPLATE = (displayName: string) => `# Fix Plan\n\n> This file tracks outstanding work. Update it after each change.\n> Empty = implementation complete.\n\n## ${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\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, 'fix_plan.md'), FIX_PLAN_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 ${answers.name}`)} to check your spec`);\n console.log(` 5. Run ${chalk.cyan(`specmarket run ${answers.name}`)} 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, stat } from 'fs/promises';\nimport { join, resolve, relative, normalize } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport {\n specYamlSchema,\n EXIT_CODES,\n REQUIRED_SPEC_FILES,\n REQUIRED_STDLIB_FILES,\n} from '@specmarket/shared';\nimport type { ValidationResult } from '@specmarket/shared';\n\n/**\n * Validates a spec directory for completeness and schema compliance.\n *\n * Checks (errors):\n * - spec.yaml parses and conforms to Zod schema\n * - Required files exist and are non-empty: PROMPT.md, SPEC.md, SUCCESS_CRITERIA.md\n * - stdlib/ directory with STACK.md\n * - SUCCESS_CRITERIA.md has at least one criterion\n * - No circular references between spec files (Markdown link cycles)\n * - Infrastructure block validates (if present)\n *\n * Checks (warnings):\n * - Web-app/api-service/mobile-app with no infrastructure services\n * - Missing setup_time_minutes\n * - Token/cost/time estimates seem unreasonably low or high\n *\n * Exported as a testable function separate from the CLI command wrapper.\n */\nexport async function validateSpec(specPath: string): Promise<ValidationResult> {\n const dir = resolve(specPath);\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check required files exist and are non-empty\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 // Check stdlib directory\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 // Parse and validate spec.yaml\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 { valid: false, errors, warnings };\n }\n\n const parseResult = specYamlSchema.safeParse(specYaml);\n if (!parseResult.success) {\n for (const issue of parseResult.error.issues) {\n errors.push(\n `spec.yaml: ${issue.path.join('.')} — ${issue.message}`\n );\n }\n } else {\n const parsed = parseResult.data;\n\n // Check SUCCESS_CRITERIA.md has at least one criterion\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 // Check for circular references between spec files\n const cycles = await detectCircularReferences(dir);\n for (const cycle of cycles) {\n errors.push(`Circular reference detected: ${cycle}`);\n }\n\n // Infrastructure validation warnings\n if (parsed.infrastructure) {\n const infra = parsed.infrastructure;\n\n // Warn if web/api/mobile apps have no services\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\n if (!infra.setup_time_minutes) {\n warnings.push('infrastructure.setup_time_minutes is not set');\n }\n\n // Validate defaultProvider matches a defined provider name\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 // Estimate sanity checks\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(\n `estimated_tokens (${parsed.estimated_tokens}) seems very high.`\n );\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 return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\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 *\n * Returns an array of cycle descriptions (empty if no cycles found).\n * Uses DFS with coloring (white/gray/black) for cycle detection.\n */\nexport async function detectCircularReferences(dir: string): Promise<string[]> {\n // Collect all text files in the spec directory (md, yaml, yml)\n const textExtensions = new Set(['.md', '.yaml', '.yml']);\n const files = await collectFiles(dir, dir, textExtensions);\n\n // Build adjacency list: file -> files it references via Markdown links\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 // Skip external URLs, anchors, and mailto\n if (target.startsWith('http://') || target.startsWith('https://') ||\n target.startsWith('#') || target.startsWith('mailto:')) {\n continue;\n }\n // Strip anchor fragments (e.g., \"./SPEC.md#section\" -> \"./SPEC.md\")\n const targetPath = target.split('#')[0]!;\n if (!targetPath) continue;\n\n // Resolve relative to the file's directory\n const fileDir = join(dir, file, '..');\n const resolvedTarget = normalize(relative(dir, resolve(fileDir, targetPath)));\n\n // Only track references to files within the spec directory\n if (!resolvedTarget.startsWith('..') && files.includes(resolvedTarget)) {\n refs.add(resolvedTarget);\n }\n }\n } catch {\n // File unreadable — skip\n }\n graph.set(file, refs);\n }\n\n // DFS cycle detection\n const WHITE = 0, GRAY = 1, 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 // Found a cycle — reconstruct the path\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 * 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 // Skip hidden directories and node_modules\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\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')\n .action(async (specPath: string) => {\n try {\n const result = await validateSpec(specPath);\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 } 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 } 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 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 { 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 any,\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 { execSync, 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\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-code --print` in a loop\n * 5. After each loop: captures tokens, duration, git diff\n * 6. Checks for completion conditions:\n * - SUCCESS: fix_plan.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-code --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-code --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-code ${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-code 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-code --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-code --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: fix_plan.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, 'fix_plan.md'), 'utf-8');\n // Consider empty if: no unchecked items (- [ ] lines)\n const hasUncheckedItems = /^- \\[ \\]/m.test(content);\n return !hasUncheckedItems;\n } catch {\n // No fix_plan.md = considered empty\n return true;\n }\n}\n\nasync function runTests(dir: string): Promise<boolean> {\n // Try to detect and run tests\n const testRunners = [\n { file: 'package.json', cmd: 'npm test -- --run 2>&1 || true' },\n { file: 'vitest.config.ts', cmd: 'npx vitest run 2>&1 || true' },\n { file: 'pytest.ini', cmd: 'python -m pytest --tb=no -q 2>&1 || true' },\n { file: 'Makefile', cmd: 'make test 2>&1 || true' },\n ];\n\n for (const runner of testRunners) {\n try {\n await access(join(dir, runner.file));\n const { stdout, stderr } = await execAsync(runner.cmd, {\n cwd: dir,\n timeout: 120000,\n });\n const combined = stdout + stderr;\n // Heuristic: \"failed\" or \"error\" in output means tests failed\n const hasFailed = /\\d+ failed|\\d+ error|FAILED|ERROR/i.test(combined);\n return !hasFailed;\n } catch {\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, versions] = 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 }).catch(() => []),\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 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"],"mappings":"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","names":["createDebug","debug","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","join","resolve","resolve","join","readFile","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","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/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"]}