@cardor/agent-harness-kit 2.3.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -1
- package/dist/agent-templates/builder.md +4 -4
- package/dist/agent-templates/consultant.md +6 -3
- package/dist/agent-templates/explorer.md +3 -1
- package/dist/agent-templates/lead.md +4 -4
- package/dist/agent-templates/reviewer.md +5 -3
- package/dist/{chunk-URMVLD2S.js → chunk-LURM3C4M.js} +2 -2
- package/dist/{chunk-JTACLEGM.js → chunk-TWG3KVZQ.js} +73 -4
- package/dist/chunk-TWG3KVZQ.js.map +1 -0
- package/dist/cli.js +223 -12
- package/dist/cli.js.map +1 -1
- package/dist/{db-L3AADJF5.js → db-3B2W2EBA.js} +2 -2
- package/dist/{mysql-AUPKARWA.js → mysql-ZU3T7DWV.js} +3 -3
- package/dist/{postgres-BB4GY4PN.js → postgres-H5TLXDTW.js} +4 -4
- package/dist/postgres-H5TLXDTW.js.map +1 -0
- package/dist/skills/ahk-test/SKILL.md +61 -0
- package/dist/{sqlite-5OWKTUUZ.js → sqlite-UDXCFIEN.js} +4 -4
- package/dist/sqlite-UDXCFIEN.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-JTACLEGM.js.map +0 -1
- package/dist/postgres-BB4GY4PN.js.map +0 -1
- package/dist/sqlite-5OWKTUUZ.js.map +0 -1
- /package/dist/{chunk-URMVLD2S.js.map → chunk-LURM3C4M.js.map} +0 -0
- /package/dist/{db-L3AADJF5.js.map → db-3B2W2EBA.js.map} +0 -0
- /package/dist/{mysql-AUPKARWA.js.map → mysql-ZU3T7DWV.js.map} +0 -0
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/build.ts","../src/core/materializer/claude-code.ts","../src/utils/file.ts","../src/core/materializer/detect-package-manager.ts","../src/core/local-install-guard.ts","../src/core/package-data.ts","../src/core/materializer/mcp-merge.ts","../src/core/materializer/scaffold-utils.ts","../src/core/materializer/templates.ts","../src/core/materializer/agent-restrictions.ts","../src/core/materializer/codex-cli.ts","../src/core/materializer/grok.ts","../src/core/materializer/opencode.ts","../src/core/materializer/index.ts","../src/commands/claude-model-prompt.ts","../src/commands/codex-model-prompt.ts","../src/commands/dashboard.ts","../src/core/dashboard-server.ts","../src/core/port-utils.ts","../src/commands/doctor.ts","../src/core/doctor.ts","../src/commands/export.ts","../src/commands/health.ts","../src/commands/init.ts","../src/schema/init.ts","../src/schema/task.ts","../src/utils/form.ts","../src/commands/init-helpers.ts","../src/commands/migrate.ts","../src/commands/migrate-storage.ts","../src/commands/models.ts","../src/commands/reset.ts","../src/core/mcp-server.ts","../src/core/permissions-check.ts","../src/commands/serve.ts","../src/commands/status.ts","../src/commands/sync.ts","../src/commands/task/add.ts","../src/commands/task/done.ts","../src/commands/task/edit.ts","../src/commands/task/list.ts","../src/core/path-probe.ts","../src/core/update-check.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from 'commander'\nimport pc from 'picocolors'\n\nimport { runBuild } from '@/commands/build'\nimport { runDashboard } from '@/commands/dashboard'\nimport { runDoctor } from '@/commands/doctor'\nimport { runExport } from '@/commands/export'\nimport { runHealth } from '@/commands/health'\nimport { runInit } from '@/commands/init'\nimport { runMigrate } from '@/commands/migrate'\nimport { runMigrateStorage } from '@/commands/migrate-storage'\nimport { runModels } from '@/commands/models'\nimport { runReset } from '@/commands/reset'\nimport { runServe } from '@/commands/serve'\nimport { runStatus } from '@/commands/status'\nimport { runSync } from '@/commands/sync'\nimport { runTaskAdd, runTaskDone, runTaskEdit, runTaskList } from '@/commands/task/index'\nimport { isLocalInstallSatisfied, printLocalInstallWarning } from '@/core/local-install-guard'\nimport { pkg } from '@/core/package-data'\nimport { isExecutableOnPath, printMissingGlobalBinaryWarning } from '@/core/path-probe'\nimport { checkForUpdate, printUpdateMessage } from '@/core/update-check'\n\nconst cwd = process.cwd()\n\n/**\n * Strict CLI-boundary coercion for `--port`. Shared by every command that\n * accepts a port so the validation (and the user-facing error) is identical\n * everywhere. Rejects anything that is not a base-10 integer in 1..65535:\n * - non-numeric ('abc'), empty/whitespace, and trailing garbage ('4242abc')\n * are refused (plain `parseInt` would silently accept '4242abc' as 4242),\n * - out-of-range values (0, negatives, 65536+) are refused.\n * Throwing commander's `InvalidArgumentError` makes commander print a clean\n * `error: option '--port <port>' argument '<val>' is invalid. …` and exit\n * non-zero with no stack trace.\n */\nfunction parsePort(raw: string): number {\n const trimmed = raw.trim()\n const rangeHint = 'must be an integer between 1 and 65535'\n if (!/^\\d+$/.test(trimmed)) {\n throw new InvalidArgumentError(`--port ${rangeHint} (received \"${raw}\").`)\n }\n const port = Number(trimmed)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new InvalidArgumentError(`--port ${rangeHint} (received \"${raw}\").`)\n }\n return port\n}\n\nconst updateCheck = checkForUpdate(pkg.version)\n\nconst program = new Command()\n\nprogram\n .name('ahk')\n .description('agent-harness-kit — CLI scaffolding for multi-agent harness systems')\n .version(pkg.version, '-v, --version')\n\n// ─── init ─────────────────────────────────────────────────────────────────────\nprogram\n .command('init')\n .description('Scaffold a harness interactively in the current directory')\n .option('--name <name>', 'Project name (skip prompt)')\n .option('--provider <provider>', 'AI provider: claude-code | opencode | codex-cli | grok-cli (skip prompt)')\n .option('--docs <path>', 'Docs folder path (skip prompt)')\n .option('--tasks <adapter>', 'Task adapter: local | jira | linear (skip prompt)')\n .option('--storage-scope <scope>', 'Storage scope: local | global (skip prompt)')\n .action(async (opts) => {\n await runInit(cwd, opts)\n })\n\n// ─── build ────────────────────────────────────────────────────────────────────\nprogram\n .command('build')\n .description('Regenerate AGENTS.md and provider files from agent-harness-kit.config.ts')\n .option('--watch', 'Rebuild on config changes')\n .option('--sync', 'Sync tools: frontmatter in existing .claude/agents/*.md to match current permission constants')\n .option(\n '--force',\n 'Regenerate agent files that already exist, DESTROYING your customizations (a backup is written first). ' +\n 'Without this flag, build only creates agent files that are missing and never modifies existing ones.',\n )\n .action(async (opts) => {\n await runBuild(cwd, opts)\n })\n\n// ─── health ───────────────────────────────────────────────────────────────────\nprogram\n .command('health')\n .description('Run health.sh and report result')\n .action(async () => {\n await runHealth(cwd)\n })\n\n// ─── status ───────────────────────────────────────────────────────────────────\nprogram\n .command('status')\n .description('Show task table and active actions')\n .option('--json', 'Output as JSON')\n .action(async (opts) => {\n await runStatus(cwd, opts)\n })\n\n// ─── sync ─────────────────────────────────────────────────────────────────────\nprogram\n .command('sync')\n .description('Sync feature_list.json ↔ SQLite')\n .option('--dry-run', 'Show what would change without applying')\n .option('--direction <direction>', 'in | out | both (default: both)')\n .action(async (opts) => {\n await runSync(cwd, { dryRun: opts['dry-run'], direction: opts.direction })\n })\n\n// ─── serve ────────────────────────────────────────────────────────────────────\nprogram\n .command('serve')\n .description('Start the MCP server (stdio)')\n .option('--port <port>', 'Port hint stored in config (default: 3742)', parsePort)\n .action(async (opts) => {\n await runServe(cwd, { port: opts.port })\n })\n\n// ─── task ─────────────────────────────────────────────────────────────────────\nconst task = program.command('task').description('Manage tasks')\n\ntask\n .command('add')\n .description('Add a task interactively')\n .action(async () => {\n await runTaskAdd(cwd)\n })\n\ntask\n .command('list')\n .description('List tasks')\n .option('--status <status>', 'Filter by status: pending | in_progress | done | blocked')\n .option('--archived', 'Show only archived tasks')\n .option('--include-archived', 'Include archived tasks in the list')\n .option('--json', 'Output as JSON')\n .action(async (opts) => {\n await runTaskList(cwd, opts)\n })\n\ntask\n .command('done <id|slug>')\n .description('Mark a task as done')\n .action(async (idOrSlug: string) => {\n await runTaskDone(cwd, idOrSlug)\n })\n\ntask\n .command('edit')\n .description('Edit a task interactively')\n .action(async () => {\n await runTaskEdit(cwd)\n })\n\n// ─── dashboard ────────────────────────────────────────────────────────────────\nprogram\n .command('dashboard')\n .description('Open web dashboard to visualize harness data')\n .option('-p, --port <port>', 'Port to listen on', parsePort, 4242)\n .option('--no-open', 'Do not open browser automatically')\n .action(async (opts: { port: number; open: boolean }) => {\n await runDashboard(cwd, { port: opts.port, open: opts.open })\n })\n\n// ─── migrate ──────────────────────────────────────────────────────────────────\n// `ahk migrate` is a pure router (no options/action of its own — commander\n// does not reliably support an identical flag declared on both a parent\n// command and its subcommand, see the argv rewrite below) with two\n// subcommands:\n// - `migrate provider --to <x>` — migrate provider-specific scaffold files.\n// - `migrate storage [--force] [--dry-run]` — migrate harness DB storage\n// (local↔global scope, sqlite↔postgres/mysql). See migrate-storage.ts.\n// `ahk migrate --to <x>` (no subcommand) and bare `ahk migrate` are kept as\n// backward-compatible aliases for `migrate provider [--to <x>]` — see the\n// argv rewrite just before `program.parse()` below.\nconst migrate = program\n .command('migrate')\n .description('Migrate provider files to a different provider, or migrate harness storage (see subcommands)')\n\nmigrate\n .command('provider')\n .description('Migrate provider-specific files to a different provider')\n .option('--to <provider>', 'Target provider: claude-code | opencode | codex-cli | grok-cli')\n .action(async (opts) => {\n await runMigrate(cwd, opts)\n })\n\nmigrate\n .command('storage')\n .description(\n 'Migrate harness DB storage between local/global scope or sqlite/postgres/mysql, based on agent-harness-kit.config.ts vs the real current state',\n )\n .option('--force', 'Required to overwrite a non-empty destination (a backup is written first)')\n .option('--dry-run', 'Preview what would migrate without applying any changes')\n .action(async (opts) => {\n try {\n await runMigrateStorage(cwd, { force: opts.force, dryRun: opts['dry-run'] })\n } catch (err) {\n console.error(pc.red(`✗ ${err instanceof Error ? err.message : String(err)}`))\n process.exit(1)\n }\n })\n\n// ─── export ───────────────────────────────────────────────────────────────────\nprogram\n .command('export')\n .description('Export the database')\n .option('--sql', 'SQL dump')\n .option('--json', 'JSON export of tasks and actions')\n .option('--output <path>', 'Output file path (default: stdout)')\n .action(async (opts) => {\n await runExport(cwd, opts)\n })\n\n\n// ─── reset ────────────────────────────────────────────────────────────────────\nprogram\n .command('reset')\n .description('Reset/clear harness data (DB, feature list, agent files)')\n .option('--force', 'Skip confirmation prompts')\n .option('--provider <claude-code|opencode|codex-cli|grok-cli>', 'Reset agent MD files for specified provider')\n .action(async (opts) => {\n await runReset(cwd, opts)\n })\n\n// ─── doctor ───────────────────────────────────────────────────────────────────\nprogram\n .command('doctor')\n .description('Check lib version, agent files, and harness skills sync status')\n .action(async () => {\n await runDoctor(cwd)\n })\n\n// ─── models ───────────────────────────────────────────────────────────────────\nprogram\n .command('models')\n .description('Re-prompt per-role Claude Code models and regenerate .claude/agents/*.md (claude-code projects only)')\n .action(async () => {\n await runModels(cwd)\n })\n\n// Prints a non-blocking warning (but not for --version/--help, which\n// commander handles without invoking actions) when the package is only\n// installed globally and not available in the project's local\n// node_modules. This is purely informational — the command continues\n// its normal flow regardless of the check's result.\nprogram.hook('preAction', () => {\n if (!isLocalInstallSatisfied(cwd)) {\n printLocalInstallWarning()\n // Global-install path only: the generated MCP config launches the bare\n // `ahk serve` command, so warn early (never block) if `ahk` is not\n // resolvable on PATH and would therefore fail later at spawn time.\n if (!isExecutableOnPath('ahk')) {\n printMissingGlobalBinaryWarning()\n }\n }\n})\n\nprogram.hook('postAction', async () => {\n const update = await updateCheck\n if (update) printUpdateMessage(update)\n})\n\n// ─── backward-compat argv rewrite for `ahk migrate` ────────────────────────\n// Bare `ahk migrate` and `ahk migrate --to <x>` (no subcommand token) must\n// keep working exactly as before subcommands were introduced — rewrite them\n// to `ahk migrate provider [--to <x>]` before commander parses argv.\n// `ahk migrate provider ...` and `ahk migrate storage ...` are untouched.\nfunction rewriteLegacyMigrateArgv(argv: string[]): string[] {\n const migrateIdx = argv.indexOf('migrate')\n if (migrateIdx === -1) return argv\n const next = argv[migrateIdx + 1]\n const isLegacyForm = next === undefined || next === '--to'\n if (!isLegacyForm) return argv\n const rewritten = [...argv]\n rewritten.splice(migrateIdx + 1, 0, 'provider')\n return rewritten\n}\n\nprogram.parse(rewriteLegacyMigrateArgv(process.argv))\n","import { watch } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { getMaterializer } from '@/core/materializer/index'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\nimport { promptCodexAgentModels } from './codex-model-prompt'\n\nimport type { AgentName } from '@/core/materializer/agent-restrictions'\nimport type { CodexAgentModelChoice } from '@/types'\n\ninterface BuildOptions {\n watch?: boolean\n sync?: boolean\n force?: boolean\n}\n\nexport async function runBuild(cwd: string, opts: BuildOptions): Promise<void> {\n await buildOnce(cwd, opts.force)\n\n if (opts.sync) {\n p.log.step('Syncing agent permissions...')\n const config = await loadConfig(cwd)\n const materializer = getMaterializer(config.provider)\n await materializer.syncPermissions(cwd)\n }\n\n if (opts.watch) {\n p.log.info(`Watching agent-harness-kit.config.ts for changes...`)\n watch(cwd, { recursive: false }, async (_, filename) => {\n if (filename?.startsWith('agent-harness-kit.config')) {\n p.log.step('Config changed — rebuilding...')\n // Deliberately never forced: an automatic rebuild triggered by a file\n // watcher must not destroy agent-file customizations behind the user's\n // back. --force is a one-shot, explicitly requested operation.\n await buildOnce(cwd, false)\n }\n })\n // Keep process alive\n await new Promise(() => { })\n }\n}\n\nasync function buildOnce(cwd: string, force?: boolean): Promise<void> {\n // Load config OUTSIDE any spinner: when --force is set on a claude-code\n // project, the per-role model prompt below needs the provider (from config)\n // before it can decide whether to run, and an interactive p.select cannot\n // render while a p.spinner is active. Loading config is fast (no spinner\n // needed for it in practice), so it moved out of the spinner-wrapped block\n // that used to say \"Loading config...\".\n let config: Awaited<ReturnType<typeof loadConfig>>\n try {\n config = await loadConfig(cwd)\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n\n // Claude Code only, and only when --force is set: re-run the same per-role\n // model prompt `ahk init` and `ahk models` use, before regenerating agent\n // files. Must happen BEFORE the spinner below starts.\n let claudeAgentModels: Partial<Record<AgentName, string>> | undefined\n if (force && config.provider === 'claude-code') {\n claudeAgentModels = await promptClaudeAgentModels(config.provider)\n }\n\n // Codex CLI only, and only when --force is set: mirror the claude-code\n // branch above with the same per-role model + reasoning-effort prompt\n // `ahk init` uses. Must also happen BEFORE the spinner below starts.\n let codexAgentModels: Partial<Record<AgentName, CodexAgentModelChoice>> | undefined\n if (force && config.provider === 'codex-cli') {\n codexAgentModels = await promptCodexAgentModels(config.provider)\n }\n\n const spinner = p.spinner()\n spinner.start('Rebuilding files...')\n\n try {\n const materializer = getMaterializer(config.provider)\n const report = await materializer.build(config, cwd, { force, claudeAgentModels, codexAgentModels })\n spinner.stop(pc.green('Build complete'))\n\n // ── Config-derived files (AGENTS.md, and CLAUDE.md for claude-code) ──\n // Report the ACTUAL per-file outcome rather than a static line. Files that\n // are up to date (created / already current / config propagated) are\n // announced quietly; hand-edited files are called out LOUDLY so a user who\n // expects config to propagate is not left thinking it silently did.\n const d = report.derived\n const upToDate = [...d.created, ...d.current, ...d.propagated]\n if (upToDate.length > 0) {\n p.log.success(upToDate.join(', '))\n }\n if (d.propagated.length > 0) {\n p.log.info(`Propagated config changes to ${d.propagated.length} generated file(s):\\n ${d.propagated.join('\\n ')}`)\n }\n if (d.overwritten.length > 0) {\n p.log.warn(\n pc.yellow(\n `--force REGENERATED ${d.overwritten.length} hand-edited generated file(s), discarding your edits:\\n ` +\n d.overwritten.join('\\n '),\n ),\n )\n if (d.backupDir) {\n p.log.info(pc.yellow(` Previous content backed up → ${d.backupDir}`))\n }\n }\n if (d.preserved.length > 0) {\n // The anti-\"silently stale\" guard: these files diverge from the current\n // config but were hand-edited, so build left them alone. Say so loudly.\n p.log.warn(\n pc.yellow(\n `Left ${d.preserved.length} hand-edited generated file(s) UNTOUCHED — your edits are safe:\\n ` +\n d.preserved.join('\\n ') +\n `\\n These no longer match the current config. Re-run with --force to regenerate them\\n ` +\n `(this DESTROYS your edits; a backup is written first).`,\n ),\n )\n }\n\n p.log.success(`Agent definitions (${config.provider})`)\n p.log.success('MCP config')\n\n const { created, overwritten, preserved, backupDir } = report.agents\n\n if (created.length > 0) {\n p.log.info(`Created ${created.length} missing agent file(s):\\n ${created.join('\\n ')}`)\n }\n\n if (overwritten.length > 0) {\n // Name every file that lost its customizations. A count alone would not\n // let the user tell which of their edits are now only in the backup.\n p.log.warn(\n pc.yellow(\n `--force REGENERATED ${overwritten.length} existing agent file(s), discarding any customizations:\\n ` +\n overwritten.join('\\n '),\n ),\n )\n if (backupDir) {\n p.log.info(pc.yellow(` Previous content backed up → ${backupDir}`))\n }\n }\n\n if (preserved.length > 0) {\n // Without this, a user who edited a template and expects `build` to pick\n // up an upstream improvement gets silence and assumes it was applied.\n p.log.info(\n `Left ${preserved.length} existing agent file(s) untouched — agent files are yours to edit.\\n ` +\n `Re-run with --force to regenerate them from the packaged templates (this DESTROYS your edits;\\n ` +\n `a backup is written first).`,\n )\n }\n } catch (err) {\n spinner.stop(pc.red('Build failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n","import { existsSync } from 'fs'\nimport { join } from 'path'\n\nimport { write } from '@/utils/file'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport {\n mergeClaudeMcpJson,\n mergeClaudeSettingsJson,\n mergeClaudeSettingsLocalJson,\n} from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport {\n agentBuilder,\n agentConsultant,\n agentExplorer,\n agentLead,\n agentReviewer,\n agentsMd,\n claudeMd,\n HEALTH_SH,\n translateFrontmatterForClaudeCode,\n} from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** The set of agent files this provider owns, with their generated content.\n * Single definition shared by `scaffold()` and `build()` — the two used to\n * duplicate this list, which is how `build()` kept overwriting user edits\n * long after `scaffold()` had been fixed to preserve them.\n *\n * `modelsByRole` is optional, collected via `promptClaudeAgentModels`\n * (Claude Code only). It is populated by `scaffold()` (from `ahk init`'s\n * per-role model prompt), and can also be threaded into `build()` via\n * `BuildMaterializerOptions.claudeAgentModels` — which happens when\n * `ahk build --force` re-runs the prompt, and always when `ahk models`\n * calls this directly to regenerate just the 5 agent files. A plain\n * `ahk build` (no `--force`) never collects models, so `build()`'s default\n * call still passes no second argument here, and existing agent files are\n * left untouched regardless (see `writeAgentFiles`'s user-ownership policy).\n * Exported so `ahk models` (src/commands/models.ts) can build the entry\n * list itself and hand it to `writeAgentFiles`. */\nexport function claudeAgentFiles(\n config: HarnessConfig,\n modelsByRole?: ScaffoldOptions['claudeAgentModels']\n): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.claude/agents/lead.md', content: translateFrontmatterForClaudeCode(agentLead({ projectName }), 'lead', { model: modelsByRole?.lead }) },\n { relPath: '.claude/agents/explorer.md', content: translateFrontmatterForClaudeCode(agentExplorer({ projectName }), 'explorer', { model: modelsByRole?.explorer }) },\n { relPath: '.claude/agents/consultant.md', content: translateFrontmatterForClaudeCode(agentConsultant({ projectName }), 'consultant', { model: modelsByRole?.consultant }) },\n { relPath: '.claude/agents/builder.md', content: translateFrontmatterForClaudeCode(agentBuilder({ projectName }), 'builder', { model: modelsByRole?.builder }) },\n { relPath: '.claude/agents/reviewer.md', content: translateFrontmatterForClaudeCode(agentReviewer({ projectName }), 'reviewer', { model: modelsByRole?.reviewer }) },\n ]\n}\n\nexport class ClaudeCodeMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd, claudeAgentModels } = opts\n\n // AGENTS.md and CLAUDE.md — fresh project, write unconditionally, but STAMP\n // the provenance marker so the first `ahk build` recognizes these as our own\n // output and keeps propagating config changes (a markerless file would be\n // treated as human-edited and frozen from day one).\n write(cwd, 'AGENTS.md', stampGenerated(agentsMd(config)))\n write(cwd, 'CLAUDE.md', stampGenerated(claudeMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write(cwd, 'health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold.\n // It is accumulable user data (the \"human-editable task seed list\"), so it\n // is reconciled via the DB round-trip in init.ts (syncFromFeatureList →\n // writeFeatureList) rather than written unconditionally here — which used\n // to clobber a hand-written backlog and mis-path the file to the project\n // root instead of .harness/.\n\n // .harness/current.md placeholder — scope='global' — current.md lives\n // under ~/.harness/dbs/<projectId>/ (see resolveGlobalStorageDir in\n // db.ts), not in the project tree, and `markdownFallback.path` doesn't\n // exist on GlobalStorageConfig at all. Skip for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n cwd,\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .claude/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, claudeAgentFiles(config, claudeAgentModels))\n\n // .mcp.json — MERGE, never overwrite whole file. Detect the project's\n // package manager fresh from cwd so the spawned command matches npm/pnpm/yarn.\n mergeClaudeMcpJson(join(cwd, '.mcp.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n // .claude/settings.json — set `agent: \"lead\"` (the official Claude Code default-agent field)\n mergeClaudeSettingsJson(join(cwd, '.claude/settings.json'))\n // .claude/settings.local.json — merge MCP tool permissions\n mergeClaudeSettingsLocalJson(join(cwd, '.claude/settings.local.json'))\n\n // .gitignore additions\n appendGitignore(cwd)\n writeSkills(cwd, '.claude/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md and CLAUDE.md are DERIVED FROM CONFIG. Reconcile against the\n // provenance marker: untouched files propagate config changes automatically,\n // hand-edited files are preserved (and reported), --force regenerates them\n // after backing up. See reconcileGeneratedFiles in scaffold-utils.\n const derived = reconcileGeneratedFiles(\n cwd,\n [\n { relPath: 'AGENTS.md', content: agentsMd(config) },\n { relPath: 'CLAUDE.md', content: claudeMd(config) },\n ],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n // Agent files are USER-OWNED. Without --force they are created when\n // missing and never touched again; --force regenerates them, backing up\n // the previous content first. `opts.claudeAgentModels` is only ever set\n // when the caller (currently `ahk build --force`, see build.ts) collected\n // fresh per-role models via `promptClaudeAgentModels` — a plain build\n // never sets it, so this is `undefined` (no model line) exactly as before.\n const agents = writeAgentFiles(cwd, claudeAgentFiles(config, opts.claudeAgentModels), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // MCP config: always merge. Re-detecting the package manager on every\n // build means a stale/hardcoded command self-corrects the next time the\n // user runs `ahk build`, even if they switched package managers after\n // the initial `ahk init` — no separate migration flag needed.\n mergeClaudeMcpJson(join(cwd, '.mcp.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n mergeClaudeSettingsJson(join(cwd, '.claude/settings.json'))\n mergeClaudeSettingsLocalJson(join(cwd, '.claude/settings.local.json'))\n writeSkills(cwd, '.claude/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n // Migration from claude-code is handled by the target materializer\n }\n\n /**\n * No-op by design.\n *\n * This used to rewrite the `tools:` frontmatter block of every agent file,\n * re-injecting the canonical `mcp__agent-harness-kit__*` allowlist. Agent\n * files no longer declare `tools` at all: they inherit the full tool set\n * (Task and every MCP tool included) and express restrictions as a\n * `disallowedTools` denylist instead.\n *\n * Keeping the old rewrite alive would be actively harmful — on a project\n * upgraded from an older version, whose agent files still carry a legacy\n * `tools:` block, it would re-inject the allowlist and silently undo the\n * migration on exactly the files that most need it. Run `ahk build` to\n * regenerate agent files in the current shape.\n */\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Agent files inherit tools and declare a disallowedTools denylist —')\n console.log(' there is no permission allowlist to sync. Run `ahk build` to regenerate them.')\n }\n}\n","import { mkdirSync, writeFileSync } from 'fs'\nimport { join, resolve } from 'path'\n\nexport const write = (cwd: string, relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport { hasRealLocalInstall } from '@/core/local-install-guard'\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn-classic' | 'yarn-berry' | 'bun'\n\n/**\n * Detects the package manager used by the project at `cwd`.\n *\n * Priority:\n * 1. The `packageManager` field in `package.json` (e.g. `\"yarn@3.6.0\"`,\n * `\"pnpm@8.15.0\"`) — the most reliable signal when present, since it's an\n * explicit declaration (Corepack-compatible) rather than a guess.\n * 2. Lockfile heuristics — `pnpm-lock.yaml` → pnpm, `bun.lockb`/`bun.lock` →\n * bun, `yarn.lock` → yarn (distinguishing classic vs berry via the\n * presence of `.yarnrc.yml`, which only exists in Yarn Berry projects),\n * `package-lock.json` → npm.\n * 3. Fallback: `npm`.\n */\nexport function detectPackageManager(cwd: string): PackageManager {\n const fromField = detectFromPackageManagerField(cwd)\n if (fromField) return fromField\n\n if (existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm'\n if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) return 'bun'\n if (existsSync(join(cwd, 'yarn.lock'))) {\n return existsSync(join(cwd, '.yarnrc.yml')) ? 'yarn-berry' : 'yarn-classic'\n }\n if (existsSync(join(cwd, 'package-lock.json'))) return 'npm'\n\n return 'npm'\n}\n\nfunction detectFromPackageManagerField(cwd: string): PackageManager | null {\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) return null\n\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))\n const field = pkg?.packageManager\n if (typeof field !== 'string' || !field.trim()) return null\n\n // Format: \"<name>@<version>[+hash]\" (Corepack convention)\n const match = field.match(/^([a-z]+)@(\\d+)/i)\n if (!match) return null\n\n const [, rawName, majorStr] = match\n const name = rawName.toLowerCase()\n const major = Number(majorStr)\n\n switch (name) {\n case 'npm':\n return 'npm'\n case 'pnpm':\n return 'pnpm'\n case 'bun':\n return 'bun'\n case 'yarn':\n return major >= 2 ? 'yarn-berry' : 'yarn-classic'\n default:\n return null\n }\n } catch {\n return null\n }\n}\n\n/**\n * Returns the full command-line tokens for spawning the MCP server.\n *\n * When the package is genuinely installed locally in the project at `cwd`\n * (see {@link hasRealLocalInstall}), the command is mediated by the\n * project's package manager so the pinned local version is the one that runs:\n *\n * | Manager | Tokens |\n * | ------------ | ---------------------------------------------------- |\n * | npm | `npx --no ahk serve --port <port>` |\n * | pnpm | `pnpm exec ahk serve --port <port>` |\n * | yarn classic | `yarn run ahk serve --port <port>` |\n * | yarn berry | `yarn run ahk serve --port <port>` |\n * | bun | `bunx --no-install ahk serve --port <port>` |\n *\n * When there is no real local install, the package manager has nothing to\n * resolve and every one of those commands would fail. In that case the\n * binary from the global install is invoked directly, regardless of `pm`:\n *\n * | (no real local install) | `ahk serve --port <port>` |\n *\n * This deliberately uses {@link hasRealLocalInstall} rather than\n * {@link isLocalInstallSatisfied}: self-dev repos (where `cwd` IS this\n * package's own root) are treated as \"no local install\" here, even though\n * `isLocalInstallSatisfied` — used elsewhere for the non-blocking install\n * warning — still reports self-dev as satisfied. There is no real\n * node_modules entry for a package manager to mediate through in self-dev,\n * so self-dev gets the same bare global command form as any other project\n * with no local install.\n *\n * `cwd` is required on purpose: it must be the project root being configured,\n * never a process-wide default. Defaulting it to `process.cwd()` would make\n * the result depend on where the process happens to be running from.\n *\n * Callers split this into `command`/`args` (Claude Code, Codex CLI) or use\n * the array as-is (OpenCode, whose `mcp.<name>.command` field is a single\n * array rather than a separate command/args pair).\n */\nexport function getMcpCommandParts(pm: PackageManager, port: number, cwd: string): string[] {\n const portStr = String(port)\n\n // No real local install → the package manager cannot resolve `ahk`; call\n // the globally installed binary directly. This intentionally excludes the\n // self-dev shortcut (see JSDoc above).\n if (!hasRealLocalInstall(cwd)) {\n return ['ahk', 'serve', '--port', portStr]\n }\n\n switch (pm) {\n case 'pnpm':\n return ['pnpm', 'exec', 'ahk', 'serve', '--port', portStr]\n case 'yarn-classic':\n case 'yarn-berry':\n return ['yarn', 'run', 'ahk', 'serve', '--port', portStr]\n case 'bun':\n return ['bunx', '--no-install', 'ahk', 'serve', '--port', portStr]\n case 'npm':\n default:\n return ['npx', '--no', 'ahk', 'serve', '--port', portStr]\n }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { pkg } from '@/core/package-data'\n\n/**\n * Determines whether `@cardor/agent-harness-kit` is available as a local\n * dependency of the project at `cwd` (see {@link hasRealLocalInstall}), OR\n * whether `cwd` IS the package itself (self-dev case, e.g. working inside\n * this repo) — either is treated as \"satisfied\" here.\n *\n * This is the self-dev-inclusive, general-purpose check. It powers the\n * non-blocking install warning (`cli.ts`'s `preAction` hook) and the config\n * file format decision (`detectConfigExtension` in `init-helpers.ts`), where\n * self-dev genuinely behaves like a satisfied local install for those\n * purposes. Callers that need to distinguish a *real* local install from the\n * self-dev shortcut (e.g. `getMcpCommandParts`, which must not mediate\n * through a package manager that has nothing to resolve in self-dev) should\n * call {@link hasRealLocalInstall} directly instead.\n *\n * The generated config no longer needs the package resolvable at runtime\n * (`import type` is erased at compile time, and the .mjs/.cjs templates\n * don't import the package at all), so this check is no longer required\n * for `loadConfig(cwd)` to succeed. It is kept as a non-blocking warning\n * so a team/CI can still pin an explicit local version of the CLI for\n * reproducibility — the command always continues regardless of the result.\n */\nexport function isLocalInstallSatisfied(cwd: string): boolean {\n // Self-dev case: cwd is the agent-harness-kit repo itself, so there is\n // no (and should be no) node_modules/@cardor/agent-harness-kit entry.\n const selfPkgPath = join(cwd, 'package.json')\n if (existsSync(selfPkgPath)) {\n try {\n const selfPkg = JSON.parse(readFileSync(selfPkgPath, 'utf8'))\n if (selfPkg?.name === pkg.name) return true\n } catch {\n // Malformed package.json — ignore and fall through to the real-install check.\n }\n }\n\n return hasRealLocalInstall(cwd)\n}\n\n/**\n * Determines whether `@cardor/agent-harness-kit` is available as a *real*\n * local dependency of the project at `cwd` — a node_modules entry, or (for\n * Yarn Berry PnP, which never creates node_modules) a declared dependency\n * detected via the PnP loader files. Deliberately excludes the self-dev\n * shortcut (`cwd` being the package's own repo): in self-dev there is no\n * actual local install for a package manager to mediate through, so this\n * returns `false` there even though {@link isLocalInstallSatisfied} returns\n * `true`.\n *\n * Use this when the caller's decision hinges on there being something a\n * package manager can genuinely resolve — e.g. `getMcpCommandParts`, which\n * picks between a package-manager-mediated command and the bare global\n * binary. Use {@link isLocalInstallSatisfied} for general-purpose\n * \"is this project set up with the package available\" checks that should\n * treat self-dev the same as a real local install.\n */\nexport function hasRealLocalInstall(cwd: string): boolean {\n const [scope, name] = pkg.name.split('/')\n const localPath = pkg.name.startsWith('@') ? join(cwd, 'node_modules', scope, name) : join(cwd, 'node_modules', pkg.name)\n\n if (existsSync(localPath)) return true\n\n // Yarn Berry with Plug'n'Play (PnP) never creates a node_modules directory\n // at all, so the check above always fails there even when the package IS\n // correctly declared and resolvable via the PnP loader. Detect PnP via its\n // generated loader files and fall back to checking that the package is\n // declared as a dependency in package.json — the only signal available\n // without depending on a node_modules layout PnP intentionally omits.\n const isPnp = existsSync(join(cwd, '.pnp.cjs')) || existsSync(join(cwd, '.pnp.loader.mjs'))\n if (isPnp) {\n const pkgPath = join(cwd, 'package.json')\n if (existsSync(pkgPath)) {\n try {\n const projectPkg = JSON.parse(readFileSync(pkgPath, 'utf8'))\n const deps = {\n ...((projectPkg?.dependencies as Record<string, unknown>) ?? {}),\n ...((projectPkg?.devDependencies as Record<string, unknown>) ?? {}),\n }\n if (Object.prototype.hasOwnProperty.call(deps, pkg.name)) return true\n } catch {\n // Malformed package.json — ignore and fall through to false.\n }\n }\n }\n\n return false\n}\n\n/**\n * Prints a non-blocking warning recommending a local install, with the\n * exact command to fix it. This is informational only — the command\n * continues to run either way. A local install is no longer required for\n * config loading to work; it is still recommended so the version of the\n * package used stays reproducible and pinned across your team and CI,\n * instead of drifting with whatever is installed globally on each machine.\n */\nexport function printLocalInstallWarning(): void {\n console.error(pc.yellow(`⚠ ${pkg.name} is not installed locally in this project.`))\n console.error(pc.dim(' This is only a recommendation for reproducibility: pinning a local'))\n console.error(pc.dim(' version keeps behavior consistent across your team and CI, instead of'))\n console.error(pc.dim(' drifting with whatever version is installed globally on each machine.'))\n console.error(pc.dim(` Run: npm install --save-dev ${pkg.name}`))\n console.error(pc.dim(' (or the equivalent for your package manager: pnpm add -D, yarn add --dev, bun add -d)'))\n}\n","import { existsSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst require = createRequire(import.meta.url)\n\n// Resolved at runtime relative to the compiled file location:\n// - local dev (compiled): dist/core/package-data.js → ../../package.json (repo root)\n// - installed: node_modules/@cardor/agent-harness-kit/dist/core/package-data.js → ../../package.json (package root)\n// - local dev (running .ts directly via tsx, e.g. tests): src/core/package-data.ts → ../../package.json (repo root)\nconst here = dirname(fileURLToPath(import.meta.url))\nconst candidates = [join(here, '..', '..', 'package.json'), join(here, '..', 'package.json')]\nconst pkgPath = candidates.find((p) => existsSync(p)) ?? candidates[0]\n\nexport const pkg = require(pkgPath) as { version: string; name: string }\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\n\nimport { getMcpCommandParts } from './detect-package-manager'\n\nimport type { PackageManager } from './detect-package-manager'\n\n// ─── Claude Code ──────────────────────────────────────────────────────────────\n\nexport function mergeClaudeMcpJson(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n const folderPath = dirname(filePath)\n if (!existsSync(folderPath)) {\n mkdirSync(folderPath, { recursive: true })\n }\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // Unreadable JSON — start fresh to avoid corrupt state\n }\n }\n\n const [command, ...args] = getMcpCommandParts(pm, port, cwd)\n\n const merged = {\n ...existing,\n mcpServers: {\n ...((existing.mcpServers as Record<string, unknown>) ?? {}),\n 'agent-harness-kit': {\n type: 'stdio',\n command,\n args,\n },\n },\n }\n\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// Write `agent: \"lead\"` to .claude/settings.json — the correct Claude Code field\n// for setting which subagent runs as the main session thread.\nexport function mergeClaudeSettingsJson(filePath: string): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // start fresh\n }\n }\n\n const merged = {\n ...existing,\n agent: 'lead',\n }\n\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// Merge MCP tool permissions into .claude/settings.local.json\nexport const MCP_CLAUDE_PERMISSIONS_LEAD = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_add',\n 'mcp__agent-harness-kit__tasks_update',\n 'mcp__agent-harness-kit__tasks_edit',\n 'mcp__agent-harness-kit__tasks_archive',\n 'mcp__agent-harness-kit__tasks_unarchive',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_EXPLORER = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_BUILDER = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_add',\n 'mcp__agent-harness-kit__tasks_update',\n 'mcp__agent-harness-kit__tasks_edit',\n 'mcp__agent-harness-kit__tasks_archive',\n 'mcp__agent-harness-kit__tasks_unarchive',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_REVIEWER = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_add',\n 'mcp__agent-harness-kit__tasks_update',\n 'mcp__agent-harness-kit__tasks_edit',\n 'mcp__agent-harness-kit__tasks_archive',\n 'mcp__agent-harness-kit__tasks_unarchive',\n 'mcp__agent-harness-kit__tasks_acceptance_update',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_CONSULTANT = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__deps_snapshot',\n 'mcp__agent-harness-kit__deps_check',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n] as const\n\n// Full union — used by mergeClaudeSettingsLocalJson for project-wide settings\nexport const MCP_CLAUDE_PERMISSIONS = [\n ...new Set([\n ...MCP_CLAUDE_PERMISSIONS_LEAD,\n ...MCP_CLAUDE_PERMISSIONS_EXPLORER,\n ...MCP_CLAUDE_PERMISSIONS_BUILDER,\n ...MCP_CLAUDE_PERMISSIONS_REVIEWER,\n ...MCP_CLAUDE_PERMISSIONS_CONSULTANT,\n ]),\n]\n\nexport function mergeClaudeSettingsLocalJson(filePath: string): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // start fresh\n }\n }\n\n const existingPermissions = (existing.permissions as Record<string, unknown>) ?? {}\n const existingAllow = (existingPermissions.allow as string[]) ?? []\n const existingServers = (existing.enabledMcpjsonServers as string[]) ?? []\n\n const mergedAllow = Array.from(new Set([...existingAllow, ...MCP_CLAUDE_PERMISSIONS]))\n const mergedServers = Array.from(new Set([...existingServers, 'agent-harness-kit']))\n\n const merged = {\n ...existing,\n permissions: {\n ...existingPermissions,\n allow: mergedAllow,\n },\n enabledMcpjsonServers: mergedServers,\n }\n\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// ─── OpenCode ─────────────────────────────────────────────────────────────────\n\nexport function mergeOpencodeJson(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n const folderPath = dirname(filePath)\n if (!existsSync(folderPath)) {\n mkdirSync(folderPath, { recursive: true })\n }\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // start fresh\n }\n }\n\n const existingMcp = (existing.mcp as Record<string, unknown>) ?? {}\n\n const merged = {\n ...existing,\n default_agent: 'lead',\n compaction: existing.compaction ?? { auto: true, prune: true, reserved: 10000 },\n permission: existing.permission ?? { write: 'ask' },\n mcp: {\n ...existingMcp,\n 'agent-harness-kit': {\n enabled: true,\n type: 'local',\n // OpenCode's mcp.<name>.command field is a single array (unlike\n // Claude/Codex, which split command/args) — pass the full token list.\n command: getMcpCommandParts(pm, port, cwd),\n },\n },\n }\n\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// ─── Codex CLI ────────────────────────────────────────────────────────────────\n\nfunction mergeTomlSection(content: string, sectionName: string, sectionBody: string): string {\n const lines = content.split('\\n')\n const header = `[${sectionName}]`\n\n const startIdx = lines.findIndex((l) => l.trim() === header)\n\n if (startIdx === -1) {\n const trimmed = content.trimEnd()\n return trimmed + (trimmed ? '\\n\\n' : '') + header + '\\n' + sectionBody.trimEnd() + '\\n'\n }\n\n // Find where the section ends: next line starting with `[` or EOF\n let endIdx = lines.length\n for (let i = startIdx + 1; i < lines.length; i++) {\n if (/^\\[/.test(lines[i])) {\n endIdx = i\n break\n }\n }\n\n const newLines = [\n ...lines.slice(0, startIdx),\n header,\n ...sectionBody.trimEnd().split('\\n'),\n '',\n ...lines.slice(endIdx),\n ]\n\n return newLines.join('\\n')\n}\n\n/**\n * Inserts a bare top-level `key = \"value\"` into a TOML document's preamble\n * (the region before the first `[section]` header), ONLY if that exact key is\n * not already present there. Never overwrites — once written, the value is\n * the user's, and re-running this must be a no-op that preserves their edit.\n *\n * A sibling to `mergeTomlSection` above, not a modification of it — that\n * helper is shared with the Grok path and only ever merges bracketed section\n * bodies. It appends an absent section at EOF, which is exactly the trap this\n * helper exists to avoid for bare top-level keys: TOML scalars belong to\n * whichever `[section]` header precedes them, so appending `model = \"...\"` at\n * EOF would silently land inside `[mcp_servers.agent-harness-kit]` and\n * corrupt that server's config (its struct almost certainly denies unknown\n * fields) instead of being a harmless top-level default.\n */\nexport function ensureTomlTopLevelKey(content: string, key: string, value: string): string {\n // Guard against `''.split('\\n')` → `['']`, which would otherwise insert a\n // spurious leading blank line into a brand-new file.\n const lines = content.length > 0 ? content.split('\\n') : []\n const firstSectionIdx = lines.findIndex((l) => /^\\s*\\[/.test(l))\n const preambleEnd = firstSectionIdx === -1 ? lines.length : firstSectionIdx\n\n // Anchored with `\\s*=` immediately after `key` so `model` never matches a\n // `model_reasoning_effort = ...` line (and vice versa) — the two keys share\n // a prefix, and a loose `.includes()`-style check would collide them.\n const keyRe = new RegExp(`^\\\\s*${key}\\\\s*=`)\n const alreadyPresent = lines.slice(0, preambleEnd).some((l) => keyRe.test(l))\n if (alreadyPresent) return content\n\n const newLines = [...lines]\n newLines.splice(preambleEnd, 0, `${key} = ${JSON.stringify(value)}`)\n return newLines.join('\\n')\n}\n\nexport function mergeCodexConfigToml(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let content = ''\n if (existsSync(filePath)) {\n content = readFileSync(filePath, 'utf8')\n }\n\n const [command, ...args] = getMcpCommandParts(pm, port, cwd)\n\n const sectionBody = [\n `command = ${JSON.stringify(command)}`,\n `args = ${JSON.stringify(args)}`,\n 'default_tools_approval_mode = \"approve\"',\n ].join('\\n')\n\n // Top-level defaults — written into the preamble, before any [section]\n // header. Merge-safe: only written once, a user's hand-edit is preserved\n // forever across re-runs (see `ensureTomlTopLevelKey`).\n content = ensureTomlTopLevelKey(content, 'model', 'gpt-5.6-terra')\n content = ensureTomlTopLevelKey(content, 'model_reasoning_effort', 'medium')\n content = ensureTomlTopLevelKey(content, 'sandbox_mode', 'danger-full-access')\n\n content = mergeTomlSection(content, 'mcp_servers.agent-harness-kit', sectionBody)\n\n writeFileSync(filePath, content, 'utf8')\n}\n\n// ─── Grok Build ───────────────────────────────────────────────────────────────\n\n/**\n * Writes/merges `.grok/config.toml`'s `[mcp_servers.agent-harness-kit]`\n * section. Follows `mergeCodexConfigToml`'s pattern above exactly, reusing the\n * already-generic `mergeTomlSection` helper — chosen (task #76 consultant\n * decision) over relying on `.mcp.json` compatibility, because that file is\n * written exclusively by Claude Code's materializer (a Grok-only project would\n * have none), and because Grok's own `.mcp.json` read is conditional on an\n * interactive Claude-import prompt that can also be disabled entirely via\n * `[compat.claude] mcps = false`.\n *\n * Unlike Codex's section, no `default_tools_approval_mode` key is emitted —\n * that key is Codex-specific, and Grok's own documented MCP TOML schema\n * (07-mcp-servers.md) does not call for it for a straightforward always-on\n * local stdio server. Kept minimal (`command`/`args` only) to match the\n * project's existing minimal-emission style and reduce drift surface on\n * re-merge.\n */\nexport function mergeGrokConfigToml(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let content = ''\n if (existsSync(filePath)) {\n content = readFileSync(filePath, 'utf8')\n }\n\n const [command, ...args] = getMcpCommandParts(pm, port, cwd)\n\n const sectionBody = [\n `command = ${JSON.stringify(command)}`,\n `args = ${JSON.stringify(args)}`,\n ].join('\\n')\n\n content = mergeTomlSection(content, 'mcp_servers.agent-harness-kit', sectionBody)\n\n writeFileSync(filePath, content, 'utf8')\n}\n","import { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { GITIGNORE_ENTRIES } from './templates'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n/* NOTE: the single-file `writeAgentFile()` was folded into `writeAgentFiles()`\n * below. Keeping both would have left two competing write policies in the same\n * module — and two policies is how this bug happened in the first place: the\n * batch call sites in `scaffold()` and `build()` drifted apart until\n * claude-code's `build()` was writing unconditionally while every other site\n * preserved. One helper, one policy. */\n\nexport interface AgentFileEntry {\n relPath: string\n content: string\n}\n\nexport interface WriteAgentFilesOptions {\n /** Overwrite files that already exist, destroying any customization.\n * Existing files are backed up to `backupRoot` FIRST. */\n force?: boolean\n /** Absolute directory under which the pre-overwrite backup is written.\n * Required when `force` is set and any file would actually be overwritten. */\n backupRoot?: string\n}\n\nexport interface WriteAgentFilesResult {\n /** Files that did not exist and were written. */\n created: string[]\n /** Files that existed and were overwritten (only possible with `force`). */\n overwritten: string[]\n /** Files that existed and were left untouched (no `force`). */\n preserved: string[]\n /** Absolute path of the backup directory, when one was written. */\n backupDir?: string\n}\n\n/**\n * Writes a batch of agent files under a single, explicit ownership policy.\n *\n * Agent files are USER-OWNED: the generator creates them when missing and\n * never touches them again. That is the whole point — a dev may edit the role\n * prompt, the model line, or the restriction fields, and a later `ahk build`\n * must not silently revert that work.\n *\n * `force` is the only escape hatch, and it is destructive: it regenerates every\n * file from the packaged template, discarding customizations. Because it is the\n * ONLY way to pick up template improvements, it must not destroy without a net\n * — so, following the `migrate storage --force` precedent, every file about to\n * be overwritten is copied to a timestamped backup directory BEFORE anything is\n * written, and a backup failure aborts the whole batch without touching a\n * single file.\n *\n * This helper exists because the same write policy was previously duplicated\n * across `scaffold()` and `build()` in all three materializers (six sites).\n * That duplication is exactly why `claude-code.ts` kept an unconditional write\n * in `build()` long after the other two providers had been fixed.\n */\nexport function writeAgentFiles(\n cwd: string,\n entries: AgentFileEntry[],\n opts: WriteAgentFilesOptions = {},\n): WriteAgentFilesResult {\n const result: WriteAgentFilesResult = { created: [], overwritten: [], preserved: [] }\n\n const existing = entries.filter((e) => existsSync(join(cwd, e.relPath)))\n\n // Back up BEFORE any write. If this throws, nothing has been touched yet.\n if (opts.force && existing.length > 0) {\n if (!opts.backupRoot) {\n throw new Error(\n 'writeAgentFiles: force is set and existing agent files would be overwritten, ' +\n 'but no backupRoot was provided. Refusing to overwrite without a backup.',\n )\n }\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const backupDir = join(opts.backupRoot, `agents-${stamp}`)\n try {\n for (const entry of existing) {\n const dest = join(backupDir, entry.relPath)\n mkdirSync(resolve(dest, '..'), { recursive: true })\n writeFileSync(dest, readFileSync(join(cwd, entry.relPath), 'utf8'), 'utf8')\n }\n } catch (err) {\n throw new Error(\n `Could not back up existing agent files to ${backupDir} ` +\n `(${err instanceof Error ? err.message : String(err)}). ` +\n `Aborting WITHOUT overwriting anything — no agent file was modified.`,\n )\n }\n result.backupDir = backupDir\n }\n\n for (const entry of entries) {\n const abs = join(cwd, entry.relPath)\n const exists = existsSync(abs)\n\n if (exists && !opts.force) {\n result.preserved.push(entry.relPath)\n continue\n }\n\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, entry.content, 'utf8')\n if (exists) result.overwritten.push(entry.relPath)\n else result.created.push(entry.relPath)\n }\n\n return result\n}\n\n/* ─── Config-derived files (AGENTS.md / CLAUDE.md) ────────────────────────────\n *\n * These differ from the user-owned agent files above: they are DERIVED FROM\n * CONFIG, so a config change legitimately SHOULD flow into them — a plain\n * create-if-missing policy would freeze them at their first-generated version.\n * But `ahk build` must never silently destroy a hand-edit either. Both cannot\n * be satisfied by content alone, so each generated file carries an out-of-body\n * provenance fingerprint: a trailing HTML comment holding the sha256 of the\n * EXACT body bytes we wrote. On the next build we recompute the hash of the\n * on-disk body and route:\n *\n * - file missing -> CREATE (stamp a marker)\n * - on-disk body == freshly generated body -> CURRENT (no-op)\n * - marker present AND its hash matches the on-disk\n * body, but the body differs from generated -> PROPAGATE (our own prior\n * output, made stale only by a config change — overwrite, no backup)\n * - marker absent OR hash mismatch -> PRESERVE (a human edited\n * the body after we wrote it, or it predates the fingerprint) + report\n * - --force over a PRESERVE file -> back up FIRST (fail-safe,\n * exactly like writeAgentFiles), then regenerate with a fresh marker.\n *\n * The linchpin safety property: the hash is over the EXACT bytes with NO\n * normalization. Any human change — even one space or a CRLF rewrite — makes\n * the hash mismatch and routes to PRESERVE. Misclassification can therefore\n * only ever OVER-preserve (harmless, self-announcing), never silently overwrite\n * a human edit. Do NOT trim or normalize the body before hashing.\n */\n\nconst GENERATED_MARKER_RE = /^([\\s\\S]*)\\n<!-- ahk:generated ([0-9a-f]{64}) -->\\n?$/\n\nfunction bodyFingerprint(body: string): string {\n return createHash('sha256').update(body, 'utf8').digest('hex')\n}\n\n/**\n * Wraps a freshly generated body with its provenance marker. The hash is over\n * the EXACT body bytes and is computed BEFORE the marker is appended, so a\n * round-trip of our own output re-hashes equal. Exported so `scaffold()` (which\n * writes unconditionally on a fresh project) stamps the SAME marker — without\n * it, the very first build would see a markerless file, classify it as\n * human-edited, and freeze config propagation from day one.\n */\nexport function stampGenerated(body: string): string {\n return `${body}\\n<!-- ahk:generated ${bodyFingerprint(body)} -->\\n`\n}\n\n/** Parses a stamped file back into its body and recorded hash. Returns null when\n * the file has no recognizable trailing marker (markerless, or a human appended\n * content after the marker). The split is byte-exact: `body` is precisely the\n * bytes that precede the `\\n<marker>\\n` we wrote. */\nfunction readStamp(fileContent: string): { body: string; hash: string } | null {\n const m = GENERATED_MARKER_RE.exec(fileContent)\n if (!m) return null\n return { body: m[1], hash: m[2] }\n}\n\n/** What happened to a single config-derived file during a build. */\nexport type DerivedFileOutcome = 'created' | 'current' | 'propagated' | 'preserved' | 'overwritten'\n\nexport interface ReconcileResult {\n /** Files that did not exist and were written with a fresh marker. */\n created: string[]\n /** Files already byte-identical to the generated body — left untouched. */\n current: string[]\n /** Files that were provably our own prior output, made stale by a config\n * change, and overwritten to propagate that change (no backup — our bytes). */\n propagated: string[]\n /** Files a human edited (or that predate the marker), left untouched. */\n preserved: string[]\n /** Files overwritten by `--force` despite being human-edited (backed up first). */\n overwritten: string[]\n /** Absolute path of the backup directory, when one was written. */\n backupDir?: string\n}\n\ninterface ReconcileOptions {\n /** Regenerate PRESERVE files (human-edited), destroying their edits. The\n * previous content is backed up FIRST; a backup failure aborts everything. */\n force?: boolean\n /** Absolute directory under which the pre-overwrite backup is written.\n * Required when `force` overwrites at least one human-edited file. */\n backupRoot?: string\n}\n\n/**\n * Reconciles a batch of config-derived files against what is on disk using the\n * provenance-fingerprint policy documented above. Mirrors `writeAgentFiles`'\n * fail-safe backup: everything a `--force` run would overwrite is copied to a\n * timestamped backup directory BEFORE a single byte is written, and a backup\n * failure aborts the whole batch without touching anything.\n */\nexport function reconcileGeneratedFiles(\n cwd: string,\n entries: AgentFileEntry[],\n opts: ReconcileOptions = {},\n): ReconcileResult {\n const result: ReconcileResult = {\n created: [],\n current: [],\n propagated: [],\n preserved: [],\n overwritten: [],\n }\n\n type Action = 'create' | 'current' | 'propagate' | 'preserve' | 'overwrite'\n const plans: { entry: AgentFileEntry; action: Action }[] = []\n const toBackup: AgentFileEntry[] = []\n\n for (const entry of entries) {\n const abs = join(cwd, entry.relPath)\n\n if (!existsSync(abs)) {\n plans.push({ entry, action: 'create' })\n continue\n }\n\n const onDisk = readFileSync(abs, 'utf8')\n const stamp = readStamp(onDisk)\n const onDiskBody = stamp ? stamp.body : onDisk\n\n if (onDiskBody === entry.content) {\n // Idempotent: byte-identical to the generated body. No-op, and do not even\n // rewrite the marker (holds true whether or not one is present).\n plans.push({ entry, action: 'current' })\n continue\n }\n\n // Body differs from generated. Is it provably our own prior output?\n if (stamp && stamp.hash === bodyFingerprint(stamp.body)) {\n // Marker matches the on-disk body byte-for-byte → the ONLY reason it\n // differs from `generated` is a config change. Safe to propagate.\n plans.push({ entry, action: 'propagate' })\n continue\n }\n\n // Markerless, or the marker's hash no longer matches the body → a human\n // touched it. Preserve unless the user explicitly asked to regenerate.\n if (opts.force) {\n plans.push({ entry, action: 'overwrite' })\n toBackup.push(entry)\n } else {\n plans.push({ entry, action: 'preserve' })\n }\n }\n\n // Fail-safe backup BEFORE any write. If this throws, nothing has been touched.\n if (toBackup.length > 0) {\n if (!opts.backupRoot) {\n throw new Error(\n 'reconcileGeneratedFiles: force is set and hand-edited generated files would be ' +\n 'overwritten, but no backupRoot was provided. Refusing to overwrite without a backup.',\n )\n }\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const backupDir = join(opts.backupRoot, `derived-${stamp}`)\n try {\n for (const entry of toBackup) {\n const dest = join(backupDir, entry.relPath)\n mkdirSync(resolve(dest, '..'), { recursive: true })\n writeFileSync(dest, readFileSync(join(cwd, entry.relPath), 'utf8'), 'utf8')\n }\n } catch (err) {\n throw new Error(\n `Could not back up existing generated files to ${backupDir} ` +\n `(${err instanceof Error ? err.message : String(err)}). ` +\n `Aborting WITHOUT overwriting anything — no file was modified.`,\n )\n }\n result.backupDir = backupDir\n }\n\n for (const { entry, action } of plans) {\n const abs = join(cwd, entry.relPath)\n switch (action) {\n case 'current':\n result.current.push(entry.relPath)\n break\n case 'preserve':\n result.preserved.push(entry.relPath)\n break\n case 'create':\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, stampGenerated(entry.content), 'utf8')\n result.created.push(entry.relPath)\n break\n case 'propagate':\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, stampGenerated(entry.content), 'utf8')\n result.propagated.push(entry.relPath)\n break\n case 'overwrite':\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, stampGenerated(entry.content), 'utf8')\n result.overwritten.push(entry.relPath)\n break\n }\n }\n\n return result\n}\n\nexport function appendGitignore(cwd: string): void {\n const giPath = join(cwd, '.gitignore')\n const existing = existsSync(giPath) ? readFileSync(giPath, 'utf8') : ''\n\n const toAdd = GITIGNORE_ENTRIES.split('\\n')\n .filter((line) => line && !existing.includes(line))\n .join('\\n')\n\n if (toAdd.trim()) {\n writeFileSync(giPath, existing + (existing.endsWith('\\n') ? '' : '\\n') + toAdd + '\\n', 'utf8')\n }\n}\n\nexport function slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 64)\n}\n\nexport function writeSkills(cwd: string, skillsDir: string): void {\n const skillNames = ['ahk-ask', 'ahk-consultant', 'ahk-triage', 'ahk-review']\n for (const skillName of skillNames) {\n const src = join(__dirname, 'skills', skillName, 'SKILL.md')\n const destDir = join(cwd, skillsDir, skillName)\n const dest = join(destDir, 'SKILL.md')\n mkdirSync(destDir, { recursive: true })\n writeFileSync(dest, readFileSync(src, 'utf8'), 'utf8')\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport {\n claudeDisallowedTools,\n codexRestrictionNotice,\n codexSandboxMode,\n grokToolsAllowlist,\n opencodePermissions,\n} from './agent-restrictions'\n\nimport type { AgentName } from './agent-restrictions'\nimport type { CodexAgentModelChoice, HarnessConfig } from '@/types'\n\n// ─── Agent template loader ────────────────────────────────────────────────────\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst TEMPLATES_DIR = join(__dirname, 'agent-templates')\n\n/**\n * Load an agent template file and interpolate {{variables}}.\n * Variables are replaced using a simple {{key}} pattern.\n */\nfunction loadAgentTemplate(\n name: 'lead' | 'explorer' | 'consultant' | 'builder' | 'reviewer',\n vars: Record<string, string> = {}\n): string {\n const raw = readFileSync(join(TEMPLATES_DIR, `${name}.md`), 'utf8')\n return raw.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? `{{${key}}}`)\n}\n\n// ─── health.sh — exits 1 until the dev implements it ─────────────────────────\n\nexport const HEALTH_SH = `#!/usr/bin/env bash\n# health.sh — project health check for agent-harness-kit\n#\n# This script must exit 0 when the project is healthy.\n# Agents will run this before making codebase changes.\n#\n# TODO: implement your project's health checks below.\n# Examples:\n# npm test\n# docker compose ps | grep -q \"running\"\n# psql -c \"SELECT 1\" > /dev/null 2>&1\n#\n# Until you implement it, this script intentionally exits 1\n# so agents know the environment is not verified.\n\necho \"health.sh not implemented yet.\"\necho \"Edit this file with your project's health checks.\"\necho \"It must exit 0 for agents to start working.\"\nexit 1\n`\n\n// ─── AGENTS.md template ───────────────────────────────────────────────────────\n\nexport function agentsMd(config: HarnessConfig): string {\n const { name, description, docsPath } = config.project\n const port = config.tools.mcp.port\n\n return `# AGENTS.md — ${name}\n\n> **Read this file first.** It is the navigation map for every AI agent working in this repository.\n\n## Project\n\n**${name}** — ${description}\n\n## Health check (run before making codebase changes)\n\n\\`\\`\\`bash\nbash health.sh\n\\`\\`\\`\n\nIf it exits non-zero, stop and report the issue. Do not proceed with codebase changes until health is green.\n\n## Harness data (source of truth)\n\n| File | Purpose |\n|------|---------|\n| \\`.harness/harness.db\\` | SQLite: all tasks, actions, file changes, tool calls |\n| \\`.harness/current.md\\` | Markdown fallback — read this if MCP server is unavailable |\n| \\`.harness/feature_list.json\\` | Human-editable task seed list |\n\n## MCP tools (preferred)\n\nThe harness exposes tools via MCP server on port ${port}. Use these instead of reading files directly.\n\n\\`\\`\\`\nactions.start taskId agent → start an action, returns a numeric actionId\nactions.write actionId section text → record a section (result, blockers, ...)\nactions.record_tool actionId calls[] → batch-log tool calls to the Tools dashboard (array, min 1)\nactions.record_file actionId files[] → batch-log file touches to the Files dashboard (array, min 1)\nactions.complete actionId summary → close the action\nactions.get taskId → full action history for a task\ntasks.add title [slug] [description] [acceptance] → create a new task from natural language\ntasks.get [status] → list tasks (pending | in_progress | done | blocked)\ntasks.claim id → atomically claim a pending task\ntasks.update id status → change task status\ntasks.acceptance.update criterionId → mark an acceptance criterion as met\ndocs.search query → search ${docsPath} for relevant content\n\\`\\`\\`\n\n## Workflow\n\n\\`\\`\\`\n1. INIT\n - Assess user intent: only run health.sh if changes are needed\n - tasks.get('in_progress') → resume if something is in progress\n - tasks.get('pending') → pick lowest id\n\n2. WORK (lead → explorer → consultant → builder → reviewer)\n - Each agent calls actions.start(taskId, agentName) → numeric actionId\n - Accumulate tool calls / file touches as you work; flush periodically (every few calls or at a phase boundary) via actions.record_tool(actionId, calls: [...]) and actions.record_file(actionId, files: [...]) — both are batch-only, even a single entry goes through as a one-element array\n - Closes with actions.complete(actionId, summary)\n\n3. CLOSE\n - tasks.update(taskId, 'done')\n - Run health.sh (if changes were made) → must be green before closing\n\\`\\`\\`\n\n## Agent roles\n\n| Agent | Responsibility |\n|-------|---------------|\n| lead | Decomposes the task into a plan, assigns sub-agents |\n| explorer | Reads and maps relevant code, never writes |\n| consultant | Technical advisor, runs after explorer, before builder. Never writes code. |\n| builder | Implements the plan, writes files |\n| reviewer | Verifies acceptance criteria, approves or blocks |\n\n## What to read\n\n\\`\\`\\`\nAlways: .harness/current.md (or MCP tasks.get)\nIf implementing: ${docsPath}/\nIf orchestrating: Agent definition files in your provider's agents directory\n\\`\\`\\`\n`\n}\n\n// ─── CLAUDE.md template (Claude Code provider) ───────────────────────────────\n\nexport function claudeMd(config: HarnessConfig): string {\n const { name, description, docsPath } = config.project\n const port = config.tools.mcp.port\n\n return `# CLAUDE.md — ${name}\n\n> **Read this file first.** It is the navigation map for every AI agent working in this repository.\n\n## Project\n\n**${name}** — ${description}\n\n## Health check (run before making codebase changes)\n\n\\`\\`\\`bash\nbash health.sh\n\\`\\`\\`\n\nIf it exits non-zero, stop and report the issue. Do not proceed with codebase changes until health is green.\n\n## Harness data (source of truth)\n\n| File | Purpose |\n|------|---------|\n| \\`.harness/harness.db\\` | SQLite: all tasks, actions, file changes, tool calls |\n| \\`.harness/current.md\\` | Markdown fallback — read this if MCP server is unavailable |\n| \\`.harness/feature_list.json\\` | Human-editable task seed list |\n\n## MCP tools (preferred)\n\nThe harness exposes tools via MCP server on port ${port}. Use these instead of reading files directly.\n\n\\`\\`\\`\nactions.start taskId agent → start an action, returns a numeric actionId\nactions.write actionId section text → record a section (result, blockers, ...)\nactions.record_tool actionId calls[] → batch-log tool calls to the Tools dashboard (array, min 1)\nactions.record_file actionId files[] → batch-log file touches to the Files dashboard (array, min 1)\nactions.complete actionId summary → close the action\nactions.get taskId → full action history for a task\ntasks.add title [slug] [description] [acceptance] → create a new task from natural language\ntasks.get [status] → list tasks (pending | in_progress | done | blocked)\ntasks.claim id → atomically claim a pending task\ntasks.update id status → change task status\ntasks.acceptance.update criterionId → mark an acceptance criterion as met\ndocs.search query → search ${docsPath} for relevant content\n\\`\\`\\`\n\n## Workflow\n\n\\`\\`\\`\n1. INIT\n - Assess user intent: only run health.sh if changes are needed\n - tasks.get('in_progress') → resume if something is in progress\n - tasks.get('pending') → pick lowest id\n - No pending tasks? → ask user, infer fields, call tasks.add, then tasks.claim\n\n2. WORK (lead → explorer → consultant → builder → reviewer)\n - Each agent calls actions.start(taskId, agentName) → numeric actionId\n - Accumulate tool calls / file touches as you work; flush periodically (every few calls or at a phase boundary) via actions.record_tool(actionId, calls: [...]) and actions.record_file(actionId, files: [...]) — both are batch-only, even a single entry goes through as a one-element array\n - Closes with actions.complete(actionId, summary)\n\n3. CLOSE\n - tasks.update(taskId, 'done')\n - Run health.sh (if changes were made) → must be green before closing\n\\`\\`\\`\n\n## Agent roles\n\n| Agent | Responsibility |\n|-------|---------------|\n| lead | Decomposes the task into a plan, assigns sub-agents |\n| explorer | Reads and maps relevant code, never writes |\n| consultant | Technical advisor, runs after explorer, before builder. Never writes code. |\n| builder | Implements the plan, writes files |\n| reviewer | Verifies acceptance criteria, approves or blocks |\n\n## What to read\n\n\\`\\`\\`\nAlways: .harness/current.md (or MCP tasks.get)\nIf implementing: ${docsPath}/\nIf orchestrating: Agent definition files in .claude/agents/\n\\`\\`\\`\n`\n}\n\n// ─── agent-harness-kit.config.ts template ───────────────────────────────────────────\n\ninterface ConfigTemplateParams {\n name: string\n description: string\n provider: string\n docsPath: string\n tasksAdapter: string\n port: number\n scope: 'local' | 'global'\n projectId: string\n}\n\n/**\n * Shared body of the config object literal, reused across the .ts/.mjs/.cjs\n * templates below. Returns the inner fields only (no wrapping braces) so\n * each variant can control its own import/export shape around it.\n */\nfunction configObjectBody(params: ConfigTemplateParams): string {\n const isGlobal = params.scope === 'global'\n\n // scope='global' — the sqlite file and current.md fallback both live under\n // ~/.harness/dbs/<projectId>/ (see resolveGlobalStorageDir in db.ts), so\n // there is no local path to declare for either. Emitting a `sqlitePath`\n // (local-only field) or `markdownFallback.path` for this scope would be\n // silently ignored at runtime — omit them entirely for this scope.\n const markdownFallbackLine = isGlobal\n ? `markdownFallback: { enabled: true },`\n : `markdownFallback: { enabled: true, path: '.harness/current.md' },`\n\n return ` project: {\n name: ${JSON.stringify(params.name)},\n description: ${JSON.stringify(params.description)},\n docsPath: '${params.docsPath}',\n },\n\n provider: '${params.provider}',\n\n // There is no 'agents' key. Agent files are yours: edit the role prompt and\n // the 'model:' frontmatter line directly in the generated file. 'ahk build'\n // creates them when missing and never overwrites them — use\n // 'ahk build --force' to regenerate them from the packaged templates.\n // What each role may NOT do is enforced per-tool inside those files\n // (disallowedTools / permission.edit / sandbox_mode); see\n // src/core/materializer/agent-restrictions.ts.\n\n // SQLite (default). Switch to postgres/mysql by changing database.type.\n // database: { type: 'postgres', connectionString: process.env.DATABASE_URL },\n // database: { type: 'mysql', connectionString: process.env.DATABASE_URL },\n database: { type: 'sqlite' },\n\n storage: {\n dir: '.harness',\n tasks: { adapter: '${params.tasksAdapter}' },\n sections: {\n toolsUsed: true,\n filesModified: true,\n result: true,\n blockers: true,\n nextSteps: false,\n },\n ${markdownFallbackLine}\n // 'local' — DB lives in .harness/ (project-relative). 'global' — DB lives\n // under ~/.harness/dbs/<projectId>/, outside the project tree.\n scope: '${params.scope}',\n projectId: '${params.projectId}',\n },\n\n health: {\n scriptPath: './health.sh',\n required: true,\n },\n\n tools: {\n mcp: { enabled: true, port: ${params.port} },\n scripts: { enabled: true, outputDir: './.harness/scripts' },\n },\n`\n}\n\n/**\n * Structural twin of `configObjectBody()` above, as a real object instead of a\n * source string. `configObjectBody` has to stay a hand-formatted string because\n * its explanatory comments are part of what makes the generated .ts/.mjs/.cjs\n * config readable — JSON has no comments, so the JSON variant cannot reuse it.\n *\n * The two are therefore maintained in parallel, and the drift that invites is\n * pinned by a test asserting that the parsed .ts body and this object are\n * deep-equal. Any field added to one and not the other fails that test.\n *\n * Deliberately contains no `$schema` key: no JSON Schema for HarnessConfig is\n * published or shipped with the package today, and pointing at a URL that does\n * not resolve would trade a type error for a fetch error.\n */\nfunction configObject(params: ConfigTemplateParams): Record<string, unknown> {\n const isGlobal = params.scope === 'global'\n\n return {\n project: {\n name: params.name,\n description: params.description,\n docsPath: params.docsPath,\n },\n provider: params.provider,\n // There is no 'agents' key here either — it was removed from the config\n // entirely, so the JSON variant must not reintroduce it.\n database: { type: 'sqlite' },\n storage: {\n dir: '.harness',\n tasks: { adapter: params.tasksAdapter },\n sections: {\n toolsUsed: true,\n filesModified: true,\n result: true,\n blockers: true,\n nextSteps: false,\n },\n // Same scope rule as configObjectBody(): 'global' has no local path to\n // declare, so markdownFallback.path is omitted for it.\n markdownFallback: isGlobal ? { enabled: true } : { enabled: true, path: '.harness/current.md' },\n scope: params.scope,\n projectId: params.projectId,\n },\n health: {\n scriptPath: './health.sh',\n required: true,\n },\n tools: {\n mcp: { enabled: true, port: params.port },\n scripts: { enabled: true, outputDir: './.harness/scripts' },\n },\n }\n}\n\n/**\n * JSON config: emitted when the package is NOT installed locally in the project\n * (see detectConfigExtension). Plain data — no import, no type annotation, no\n * reference to '@cardor/agent-harness-kit' of any kind — so an editor and a\n * `tsc --noEmit` have nothing to resolve and report zero errors. That is the\n * whole point of this variant: the .ts template's `import type` is erased at\n * runtime, but it still red-underlines in an editor that cannot resolve the\n * package.\n *\n * Cost of the trade: no autocompletion. JSON.stringify handles all quoting and\n * escaping, so descriptions containing quotes or apostrophes are safe by\n * construction rather than by careful template authoring.\n */\nexport function configJson(params: ConfigTemplateParams): string {\n return JSON.stringify(configObject(params), null, 2) + '\\n'\n}\n\n/** Exported for the drift test that compares this shape against the parsed\n * .ts/.mjs/.cjs config body. Not part of the public API. */\nexport const __configObjectForTests = configObject\n\n/**\n * TypeScript config: uses `import type` (type-only, erased at compile time)\n * instead of a value import of `defineHarness`. This means `loadConfig()`\n * (via jiti) never needs to resolve `@cardor/agent-harness-kit` as a real\n * module at runtime just to load the config — only the type is referenced,\n * which TypeScript strips entirely. `defineHarness()` itself is unaffected\n * and remains available for anyone who prefers to import and call it\n * manually; `loadConfig()` supports both shapes (see config.ts).\n */\nexport function configTs(params: ConfigTemplateParams): string {\n return `import type { HarnessConfig } from '@cardor/agent-harness-kit'\n\nconst config: HarnessConfig = {\n${configObjectBody(params)}}\n\nexport default config\n`\n}\n\n/**\n * .mjs config: plain JavaScript has no compile-time type checking, so there\n * is no benefit to importing anything from the package here — not even a\n * type. The object is exported as-is via ESM `export default`.\n */\nexport function configMjs(params: ConfigTemplateParams): string {\n return `const config = {\n${configObjectBody(params)}}\n\nexport default config\n`\n}\n\n/**\n * .cjs config: same reasoning as configMjs — plain JS, no types to import.\n * Exported via CommonJS `module.exports`, which `loadConfig()` already\n * handles through its `mod.default ?? mod` fallback.\n */\nexport function configCjs(params: ConfigTemplateParams): string {\n return `const config = {\n${configObjectBody(params)}}\n\nmodule.exports = config\n`\n}\n\n// ─── Agent definition templates (loaded from agent-templates/*.md) ─────────────\n\nexport function agentLead(vars: { projectName: string }): string {\n return loadAgentTemplate('lead', vars)\n}\n\nexport function agentExplorer(vars: { projectName: string }): string {\n return loadAgentTemplate('explorer', vars)\n}\n\nexport function agentBuilder(vars: { projectName: string }): string {\n return loadAgentTemplate('builder', vars)\n}\n\nexport function agentConsultant(vars: { projectName: string }): string {\n return loadAgentTemplate('consultant', vars)\n}\n\nexport function agentReviewer(vars: { projectName: string }): string {\n return loadAgentTemplate('reviewer', vars)\n}\n\n// Note: agentLead/agentExplorer/agentConsultant/agentBuilder/agentReviewer above produce the\n// raw markdown template (frontmatter without `model:` and without any permission fields).\n// No `model:` line is ever injected, by any provider: the per-agent `model` config was removed\n// along with the whole `agents` key, and the generated agent file is user-owned, so the model is\n// set by editing the file's frontmatter directly. Each provider applies its own default when no\n// model line is present. Permission/restriction fields ARE added downstream by each provider's\n// translator, driven by AGENT_RESTRICTIONS in ./agent-restrictions.ts, which is the single source\n// of truth for what a role may not do.\n\n// ─── feature_list.json initial seed ──────────────────────────────────────────\n\nexport function featureListJson(\n tasks: { slug: string; title: string; description?: string; acceptance?: string[] }[]\n): string {\n return JSON.stringify(tasks, null, 2) + '\\n'\n}\n\n// ─── Codex CLI agent TOML helpers ────────────────────────────────────────────\n\nfunction stripFrontmatter(md: string): { description: string; body: string } {\n const parts = md.split(/^---\\s*$/m)\n if (parts.length < 3) return { description: '', body: md }\n\n const frontmatter = parts[1]\n const body = parts.slice(2).join('---').replace(/^\\n/, '')\n\n let description = ''\n // YAML folded scalar: `description: >\\n line1\\n line2`\n const foldedMatch = frontmatter.match(/^description:\\s*[>|]\\s*\\n((?:[ \\t]+[^\\n]*\\n?)*)/m)\n if (foldedMatch) {\n description = foldedMatch[1]\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean)\n .join(' ')\n } else {\n const inlineMatch = frontmatter.match(/^description:\\s*(.+)$/m)\n if (inlineMatch) description = inlineMatch[1].trim()\n }\n\n return { description, body }\n}\n\n/**\n * No `model` / `model_reasoning_effort` line is emitted unless `opts` supplies\n * one. The generated file is user-owned, so by default the model is set by\n * editing those lines directly in `.codex/agents/<role>.toml`; omitting them\n * here lets Codex apply its own default, which is what the old 'inherit'\n * option meant. `opts` is the one caller-controlled exception — it is how\n * `ahk init`'s per-role Codex model+effort prompt (`promptCodexAgentModels`)\n * applies a user's actual answer, mirroring `translateFrontmatterForClaudeCode`'s\n * `opts.model` for Claude Code.\n *\n * Both fields are guarded against empty strings: Codex's per-agent-role file\n * format uses `#[serde(deny_unknown_fields)]`, so a malformed key takes the\n * WHOLE role file offline, and its reasoning-effort parser explicitly rejects\n * an empty string (every other unrecognized value is silently accepted as a\n * custom effort, but `\"\"` is the one hard error) — so a line is only ever\n * emitted for a genuinely non-empty value.\n */\nfunction toCodexToml(\n tomlName: string,\n agentName: AgentName,\n description: string,\n body: string,\n opts?: CodexAgentModelChoice\n): string {\n // TOML multiline basic strings end at `\"\"\"` — escape any that appear in content\n const safe = (s: string) => s.replace(/\"\"\"/g, '\"\"\\\\u0022')\n\n // Codex has no per-agent tool denylist. As of task #83, all roles run with\n // sandbox_mode = \"danger-full-access\" (deliberate, user-chosen project\n // configuration) — sandbox_mode is no longer an enforcement mechanism for\n // the no-write roles, so the restriction is restated in prose inside\n // developer_instructions, which is now the ONLY enforcement for those roles.\n const sandboxMode = codexSandboxMode(agentName)\n const notice = codexRestrictionNotice(agentName)\n const instructions = notice ? `${body.trimEnd()}\\n\\n---\\n\\n${notice}` : body.trimEnd()\n\n const modelLines: string[] = []\n if (opts?.model) modelLines.push(`model = \"${opts.model}\"`)\n if (opts?.effort) modelLines.push(`model_reasoning_effort = \"${opts.effort}\"`)\n const modelBlock = modelLines.length > 0 ? `${modelLines.join('\\n')}\\n` : ''\n\n return `name = \"${tomlName}\"\nsandbox_mode = \"${sandboxMode}\"\n${modelBlock}\ndescription = \"\"\"\n${safe(description)}\n\"\"\"\n\ndeveloper_instructions = \"\"\"\n${safe(instructions)}\n\"\"\"\n`\n}\n\nexport function agentLeadToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('lead', vars))\n return toCodexToml('lead', 'lead', description, body, opts)\n}\n\nexport function agentLeadAsDefaultToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('lead', vars))\n return toCodexToml('default', 'lead', description, body, opts)\n}\n\nexport function agentExplorerToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('explorer', vars))\n return toCodexToml('explorer', 'explorer', description, body, opts)\n}\n\nexport function agentBuilderToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('builder', vars))\n return toCodexToml('builder', 'builder', description, body, opts)\n}\n\nexport function agentReviewerToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('reviewer', vars))\n return toCodexToml('reviewer', 'reviewer', description, body, opts)\n}\n\nexport function agentConsultantToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('consultant', vars))\n return toCodexToml('consultant', 'consultant', description, body, opts)\n}\n\n// ─── Claude Code frontmatter translation ─────────────────────────────────────\n\n/**\n * Removes a `tools:` (or `disallowedTools:`) YAML block sequence from the\n * frontmatter, if present. Used to normalise a template before re-emitting the\n * provider-native permission shape, so translation stays idempotent even when\n * fed already-translated content.\n */\nfunction stripFrontmatterBlockSequence(md: string, key: string): string {\n const re = new RegExp(`^${key}:\\\\n(?: - [^\\\\n]+\\\\n)+`, 'm')\n return md.replace(re, '')\n}\n\n/**\n * Appends a YAML block sequence (one ` - value` per line) to the end of the\n * frontmatter, just before its closing `---`. Block sequence — not the inline\n * comma form shown in some upstream docs — for consistency with the rest of the\n * agent files in this repo.\n */\nfunction appendFrontmatterBlockSequence(md: string, key: string, values: string[]): string {\n if (values.length === 0) return md\n const block = `${key}:\\n${values.map((v) => ` - ${v}`).join('\\n')}\\n`\n return md.replace(/^---\\n([\\s\\S]*?)^---\\n/m, (_m, body: string) => `---\\n${body}${block}---\\n`)\n}\n\n/**\n * Appends a single scalar key (e.g. `model: opus`) to the end of the\n * frontmatter, just before its closing `---`. Only used where the caller has\n * already guarded that the frontmatter does not carry a hand-authored value\n * for this key — this function does not check for an existing line itself.\n */\nfunction appendFrontmatterScalar(md: string, key: string, value: string): string {\n const block = `${key}: ${value}\\n`\n return md.replace(/^---\\n([\\s\\S]*?)^---\\n/m, (_m, body: string) => `---\\n${body}${block}---\\n`)\n}\n\n/**\n * Appends a nested YAML mapping (e.g. `permission:\\n edit: deny`) to the end of\n * the frontmatter, just before its closing `---`.\n */\nfunction appendFrontmatterMapping(md: string, key: string, entries: Record<string, string>): string {\n const keys = Object.keys(entries)\n if (keys.length === 0) return md\n const block = `${key}:\\n${keys.map((k) => ` ${k}: ${entries[k]}`).join('\\n')}\\n`\n return md.replace(/^---\\n([\\s\\S]*?)^---\\n/m, (_m, body: string) => `---\\n${body}${block}---\\n`)\n}\n\n/**\n * Translates a template's frontmatter into the Claude Code agent shape.\n *\n * `tools` is deliberately OMITTED: a Claude Code sub-agent with no `tools` key\n * inherits the full tool set, which includes `Task` and every `mcp__*` tool from\n * the connected servers. That inheritance replaces the explicit Task + MCP tool\n * injection this function used to perform — enumerating them was both redundant\n * and the reason `ahk doctor` reported hand-edited agent files as \"outdated\".\n *\n * Restrictions are expressed as a denylist via `disallowedTools`, which Claude\n * Code applies before `tools`.\n *\n * No `model:` line is emitted by default. Those generated files are\n * user-owned, so their model is normally set by editing the frontmatter\n * directly; with no line emitted, Claude Code applies its own default — the\n * behaviour the old 'inherit' option described.\n *\n * `opts.model` is the one caller-controlled exception: when the value is\n * provided and is not 'inherit', a `model: <value>` line is injected for\n * whichever `agentName` is passed in. This is how `ahk init`'s per-role model\n * prompt (Claude Code only) applies a user's choice to a role's generated\n * `.claude/agents/<role>.md` at scaffold time — it writes straight into this\n * function's output, never into config. Omitting `opts` (or passing 'inherit')\n * keeps the contract byte-identical to the no-model-line default.\n */\nexport function translateFrontmatterForClaudeCode(\n md: string,\n agentName: AgentName,\n opts?: { model?: string }\n): string {\n let result = stripFrontmatterBlockSequence(md, 'tools')\n result = stripFrontmatterBlockSequence(result, 'disallowedTools')\n if (opts?.model && opts.model !== 'inherit') {\n result = appendFrontmatterScalar(result, 'model', opts.model)\n }\n return appendFrontmatterBlockSequence(result, 'disallowedTools', claudeDisallowedTools(agentName))\n}\n\n// ─── OpenCode frontmatter translation ────────────────────────────────────────\n\n/**\n * Translates a template's frontmatter into the OpenCode agent shape.\n *\n * The `tools: { read: true, ... }` dict this function used to emit is\n * deprecated upstream in favour of `permission`, so no `tools` key is written\n * at all — the agent inherits the default tool set. Restrictions are expressed\n * as `permission` entries with `allow | ask | deny` values.\n *\n * Only ONE key is emitted for the no-write case: OpenCode has no separate\n * `write` permission — `edit` already covers write/patch/edit.\n *\n * Note on MCP tools: under OpenCode they are named `<server>_<tool>` with no\n * `mcp__` prefix, so Claude Code patterns must never be ported here verbatim.\n * Nothing in the current restriction set targets MCP tools, so none are emitted.\n */\nexport function translateFrontmatterForOpenCode(md: string, agentName: AgentName): string {\n let result = stripFrontmatterBlockSequence(md, 'tools')\n result = stripFrontmatterBlockSequence(result, 'disallowedTools')\n return appendFrontmatterMapping(result, 'permission', opencodePermissions(agentName))\n}\n\n// ─── Grok Build frontmatter translation ──────────────────────────────────────\n\n/**\n * Translates a template's frontmatter into the Grok Build agent shape.\n *\n * Grok Build's format is markdown + YAML frontmatter, like Claude Code and\n * OpenCode (unlike Codex's TOML), so this reuses the same generic\n * block-sequence helpers `translateFrontmatterForClaudeCode` uses — structural\n * twin to `translateFrontmatterForOpenCode` above.\n *\n * Unlike Claude's `disallowedTools` (a denylist), Grok's `tools:` field is an\n * ALLOWLIST: `grokToolsAllowlist()` returns the full set of permitted tool\n * names for 'no-write' roles, or `[]` for the unrestricted 'none' role (which\n * `appendFrontmatterBlockSequence` turns into an omitted `tools:` key,\n * inheriting every tool — matching Claude/OpenCode's \"inherit all\" behaviour\n * for `builder`).\n */\nexport function translateFrontmatterForGrok(md: string, agentName: AgentName): string {\n let result = stripFrontmatterBlockSequence(md, 'tools')\n result = stripFrontmatterBlockSequence(result, 'disallowedTools')\n return appendFrontmatterBlockSequence(result, 'tools', grokToolsAllowlist(agentName))\n}\n\n// ─── .gitignore additions ─────────────────────────────────────────────────────\n\nexport const GITIGNORE_ENTRIES = `\n# agent-harness-kit\n.harness/harness.db\n.harness/harness.db-shm\n.harness/harness.db-wal\n.harness/current.md\n`\n","/**\n * Internal, provider-agnostic model of what each role is *not* allowed to do.\n *\n * This is deliberately a tiny closed vocabulary rather than a literal list of\n * tool names: the three supported providers do not share a permission model,\n * so a single \"denylist of tools\" cannot be translated verbatim to all of them.\n * Each provider's materializer translates the restriction below into its own\n * native semantics:\n *\n * restriction | Claude Code | OpenCode | Codex CLI | Grok Build\n * --------------|------------------------------|--------------------------|-------------------------------|---------------------------------\n * 'none' | omit `tools` (inherit all) | omit `permission` | sandbox_mode=\"danger-full-access\" | omit `tools` (inherit all)\n * 'no-write' | disallowedTools: Write, Edit | permission: { edit: deny } | sandbox_mode=\"danger-full-access\" (enforced by prose only — see below) | tools: <allowlist, no Write/Edit>\n *\n * Notes on the asymmetries this abstraction hides:\n * - OpenCode has NO separate `write` permission. Its `edit` permission is\n * documented as \"file modifications including write/patch\", so a single\n * `edit: deny` covers Write + Edit + patch. Emitting two keys would be wrong.\n * - Codex CLI has no per-agent tool denylist at all, and as of task #83 it\n * also has no OS-level sandbox: by deliberate, user-chosen project\n * configuration, ALL 5 roles run with `sandbox_mode = \"danger-full-access\"`\n * (fully unsandboxed), including the 'no-write' roles. `restrictionFor()`\n * is intentionally ignored by `codexSandboxMode()` for this reason. The\n * no-write restriction for those roles under Codex is therefore enforced\n * ENTIRELY by the prose restated in `developer_instructions`\n * (`CODEX_READ_ONLY_NOTICE`) — there is no technical enforcement left. See\n * README.md for the documented tradeoff.\n * - Grok Build's `tools:` frontmatter field is the INVERSE shape of Claude's:\n * an ALLOWLIST, not a denylist. There is no way to say \"everything except\n * Write/Edit\" — the no-write role must enumerate every tool it IS allowed.\n * The allowlist below (PascalCase tool-class names, matching the vocabulary\n * Grok's own permission-rule engine enforces against, plus the two MCP\n * discovery meta-tools `search_tool`/`use_tool`) was resolved by the task\n * #76 consultant advisory after the docs turned out to use two competing\n * naming conventions with no single reconciling reference page. Bash is\n * included deliberately, consistent with Claude/OpenCode's existing\n * no-write scope (a tool-visibility restriction, not an OS sandbox like\n * Codex's) — see `grokToolsAllowlist` below.\n */\n\nexport type AgentName = 'lead' | 'explorer' | 'consultant' | 'builder' | 'reviewer'\n\nexport type AgentRestriction = 'none' | 'no-write'\n\nexport const AGENT_RESTRICTIONS: Record<AgentName, AgentRestriction> = {\n lead: 'no-write',\n explorer: 'no-write',\n consultant: 'no-write',\n builder: 'none',\n reviewer: 'no-write',\n}\n\nexport function restrictionFor(agentName: AgentName): AgentRestriction {\n return AGENT_RESTRICTIONS[agentName] ?? 'no-write'\n}\n\n// ─── Claude Code ─────────────────────────────────────────────────────────────\n\n/**\n * Tool names Claude Code should refuse for this role. An empty array means the\n * agent inherits everything (including `Task` and all `mcp__*` tools) — which is\n * exactly why `tools` is omitted entirely rather than enumerated.\n */\nexport function claudeDisallowedTools(agentName: AgentName): string[] {\n return restrictionFor(agentName) === 'no-write' ? ['Write', 'Edit'] : []\n}\n\n// ─── OpenCode ────────────────────────────────────────────────────────────────\n\n/**\n * OpenCode `permission` entries for this role. The legacy `tools: { x: false }`\n * dict is deprecated upstream in favour of `permission`, so nothing is emitted\n * for the unrestricted case.\n */\nexport function opencodePermissions(agentName: AgentName): Record<string, 'allow' | 'ask' | 'deny'> {\n return restrictionFor(agentName) === 'no-write' ? { edit: 'deny' } : {}\n}\n\n// ─── Codex CLI ───────────────────────────────────────────────────────────────\n\nexport type CodexSandboxMode = 'workspace-write' | 'read-only' | 'danger-full-access'\n\n/**\n * All 5 Codex roles run fully unsandboxed by deliberate, user-chosen project\n * configuration (task #83) — `restrictionFor()` is intentionally NOT consulted\n * here. This removes the only OS-level enforcement Codex CLI had for the\n * no-write roles; see `CODEX_READ_ONLY_NOTICE` below for the prose-only\n * backstop that replaces it, and README.md for the documented tradeoff.\n */\nexport function codexSandboxMode(_agentName: AgentName): CodexSandboxMode {\n return 'danger-full-access'\n}\n\n/**\n * Prose restated inside `developer_instructions`. Since sandbox_mode is now\n * `danger-full-access` for every role (task #83, user-chosen), this notice is\n * no longer a redundant backstop to an OS sandbox — it is the ONLY thing\n * enforcing the no-write restriction for lead/explorer/consultant/reviewer\n * under Codex CLI. A violation will not be technically rejected by anything;\n * it will silently corrupt the harness's audit trail and workflow guarantees.\n */\nexport const CODEX_READ_ONLY_NOTICE = `## Tool restrictions (enforced by instruction only — NOT by the sandbox)\n\nThis agent runs UNSANDBOXED: \\`sandbox_mode = \"danger-full-access\"\\`. There is no OS-level write protection. This is a deliberate project configuration choice, not an oversight.\n\nYou MUST NOT create, modify, or delete any file: no \\`Write\\`, no \\`Edit\\`, no \\`apply_patch\\`, and no shell command that writes to disk (\\`>\\`, \\`tee\\`, \\`sed -i\\`, \\`mv\\`, \\`rm\\`, ...). This restriction is enforced ONLY by you following this instruction — nothing will technically block or reject the call.\n\nIf you find yourself about to perform a write, STOP. Do not perform it. Report it as a blocker instead. Treat this as a hard rule: breaking it will not fail loudly, it will silently break the harness's audit trail and workflow guarantees.`\n\nexport function codexRestrictionNotice(agentName: AgentName): string {\n return restrictionFor(agentName) === 'no-write' ? CODEX_READ_ONLY_NOTICE : ''\n}\n\n// ─── Grok Build ──────────────────────────────────────────────────────────────\n\n/**\n * Tool allowlist for Grok Build's `tools:` frontmatter field.\n *\n * Unlike Claude Code's `disallowedTools`/OpenCode's `permission` (both\n * denylist-shaped), Grok Build's `tools:` field is an ALLOWLIST: an agent may\n * only call tools named in this list, so \"no-write\" must enumerate everything\n * it IS allowed rather than the two things it isn't.\n *\n * Names are PascalCase tool-class names (`Bash`, `Read`, `NotebookRead`,\n * `Grep`, `Glob`, `WebFetch`, `WebSearch`) plus the two MCP discovery\n * meta-tools (`search_tool`, `use_tool`) that have no PascalCase form\n * documented anywhere in Grok Build's docs. This is Convention A per the task\n * #76 consultant advisory: Grok's own permission-rule engine\n * (22-permissions-and-safety.md \"Tool Names\") only recognizes these names, so\n * they are not just best-evidence but the only reading under which the\n * frontmatter allowlist and the permission-rule engine can refer to the same\n * tool. `Bash` is included even for 'no-write' roles — matching the existing\n * precedent that Claude's `disallowedTools: ['Write','Edit']` and OpenCode's\n * `edit: deny` both already leave Bash fully permitted for a tool-visibility\n * restriction (as opposed to Codex's OS-level sandbox).\n *\n * Returns `[]` for the 'none' role (builder) so the caller's\n * `appendFrontmatterBlockSequence` no-ops and `tools:` is omitted entirely,\n * inheriting every tool — the same \"empty array means inherit everything\"\n * contract `claudeDisallowedTools` already uses.\n */\nexport function grokToolsAllowlist(agentName: AgentName): string[] {\n return restrictionFor(agentName) === 'no-write'\n ? ['Bash', 'Read', 'NotebookRead', 'Grep', 'Glob', 'WebFetch', 'WebSearch', 'search_tool', 'use_tool']\n : []\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport { mergeCodexConfigToml } from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport {\n agentBuilderToml,\n agentConsultantToml,\n agentExplorerToml,\n agentLeadAsDefaultToml,\n agentLeadToml,\n agentReviewerToml,\n agentsMd,\n HEALTH_SH,\n} from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** Agent files this provider owns. Shared by `scaffold()` and `build()`.\n *\n * `default.toml` is included deliberately. It is a shim that overrides Codex's\n * built-in `default` agent so `lead` runs when no agent is selected, but it is\n * still an agent file the user may edit, so it follows the same user-owned\n * policy as the five roles: created when missing, regenerated only with\n * --force.\n *\n * `modelsByRole` is optional, collected via `promptCodexAgentModels` (Codex\n * CLI only). It is populated by `scaffold()` (from `ahk init`'s per-role\n * model+effort prompt), and can also be threaded into `build()` via\n * `BuildMaterializerOptions.codexAgentModels`. A plain `ahk build` (no\n * `--force`) never collects models, so `build()`'s default call still passes\n * no second argument here, and existing agent files are left untouched\n * regardless (see `writeAgentFiles`'s user-ownership policy). Exported —\n * mirroring `claude-code.ts`'s exported `claudeAgentFiles` — so it can be\n * tested directly with an explicit map, without mocking `@clack/prompts`. */\nexport function codexAgentFiles(\n config: HarnessConfig,\n modelsByRole?: ScaffoldOptions['codexAgentModels']\n): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.codex/agents/lead.toml', content: agentLeadToml({ projectName }, modelsByRole?.lead) },\n { relPath: '.codex/agents/explorer.toml', content: agentExplorerToml({ projectName }, modelsByRole?.explorer) },\n { relPath: '.codex/agents/consultant.toml', content: agentConsultantToml({ projectName }, modelsByRole?.consultant) },\n { relPath: '.codex/agents/builder.toml', content: agentBuilderToml({ projectName }, modelsByRole?.builder) },\n { relPath: '.codex/agents/reviewer.toml', content: agentReviewerToml({ projectName }, modelsByRole?.reviewer) },\n { relPath: '.codex/agents/default.toml', content: agentLeadAsDefaultToml({ projectName }, modelsByRole?.lead) },\n ]\n}\n\nexport class CodexCliMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd, codexAgentModels } = opts\n\n const write = (relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n }\n\n // AGENTS.md — fresh project, write unconditionally, but STAMP the provenance\n // marker so the first `ahk build` recognizes it as our own output (a\n // markerless file would look human-edited and freeze config propagation).\n write('AGENTS.md', stampGenerated(agentsMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write('health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold — it\n // is accumulable user data reconciled via the DB round-trip in init.ts, so\n // the scaffold no longer writes it (which used to clobber a hand-written\n // backlog).\n\n // scope='global' — current.md lives under ~/.harness/dbs/<projectId>/\n // (see resolveGlobalStorageDir in db.ts), not in the project tree, and\n // `markdownFallback.path` doesn't exist on GlobalStorageConfig at all.\n // Skip the local placeholder entirely for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .codex/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, codexAgentFiles(config, codexAgentModels))\n\n // .codex/config.toml — MERGE, never overwrite whole file. Detect the\n // project's package manager fresh from cwd so the spawned command matches npm/pnpm/yarn.\n mergeCodexConfigToml(join(cwd, '.codex/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n\n appendGitignore(cwd)\n writeSkills(cwd, '.agents/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md is DERIVED FROM CONFIG. Reconcile against the provenance marker:\n // untouched files propagate config changes, hand-edited files are preserved\n // (and reported), --force regenerates after backing up.\n const derived = reconcileGeneratedFiles(\n cwd,\n [{ relPath: 'AGENTS.md', content: agentsMd(config) }],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n const agents = writeAgentFiles(cwd, codexAgentFiles(config, opts.codexAgentModels), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // Re-detecting on every build self-corrects the command if the user\n // switched package managers since `ahk init` — no migration flag needed.\n mergeCodexConfigToml(join(cwd, '.codex/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n writeSkills(cwd, '.agents/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n }\n\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Permissions sync not needed for codex-cli — skipping')\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport { mergeGrokConfigToml } from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport { agentBuilder, agentConsultant, agentExplorer, agentLead, agentReviewer, agentsMd, HEALTH_SH, translateFrontmatterForGrok } from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** Agent files this provider owns. Shared by `scaffold()` and `build()`.\n *\n * Grok Build's format is markdown + YAML frontmatter, like Claude Code and\n * OpenCode (unlike Codex's TOML), so agent files land at\n * `.grok/agents/<role>.md` with `translateFrontmatterForGrok` applying the\n * provider-native `tools:` allowlist per role. */\nfunction grokAgentFiles(config: HarnessConfig): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.grok/agents/lead.md', content: translateFrontmatterForGrok(agentLead({ projectName }), 'lead') },\n { relPath: '.grok/agents/explorer.md', content: translateFrontmatterForGrok(agentExplorer({ projectName }), 'explorer') },\n { relPath: '.grok/agents/consultant.md', content: translateFrontmatterForGrok(agentConsultant({ projectName }), 'consultant') },\n { relPath: '.grok/agents/builder.md', content: translateFrontmatterForGrok(agentBuilder({ projectName }), 'builder') },\n { relPath: '.grok/agents/reviewer.md', content: translateFrontmatterForGrok(agentReviewer({ projectName }), 'reviewer') },\n ]\n}\n\nexport class GrokMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd } = opts\n\n const write = (relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n }\n\n // AGENTS.md — fresh project, write unconditionally, but STAMP the provenance\n // marker so the first `ahk build` recognizes it as our own output (a\n // markerless file would look human-edited and freeze config propagation).\n // Grok Build, like OpenCode and Codex CLI, gets no second CLAUDE.md-\n // equivalent file — AGENTS.md is the sole provider-agnostic navigation doc.\n write('AGENTS.md', stampGenerated(agentsMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write('health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold — it\n // is accumulable user data reconciled via the DB round-trip in init.ts, so\n // the scaffold no longer writes it (which used to clobber a hand-written\n // backlog).\n\n // scope='global' — current.md lives under ~/.harness/dbs/<projectId>/\n // (see resolveGlobalStorageDir in db.ts), not in the project tree, and\n // `markdownFallback.path` doesn't exist on GlobalStorageConfig at all.\n // Skip the local placeholder entirely for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .grok/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, grokAgentFiles(config))\n\n // .grok/config.toml — MERGE, never overwrite whole file. Native TOML MCP\n // config (task #76 consultant decision — see mergeGrokConfigToml's doc\n // comment for why `.mcp.json` compatibility was rejected). Detect the\n // project's package manager fresh from cwd so the spawned command matches\n // npm/pnpm/yarn.\n mergeGrokConfigToml(join(cwd, '.grok/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n\n appendGitignore(cwd)\n\n // .grok/skills/ — provider-namespaced (task #76 consultant decision: matches\n // Grok Build's own native skill-discovery path, and 2 of 3 existing\n // providers — Claude, OpenCode — already namespace their skills dir).\n writeSkills(cwd, '.grok/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md is DERIVED FROM CONFIG. Reconcile against the provenance marker:\n // untouched files propagate config changes, hand-edited files are preserved\n // (and reported), --force regenerates after backing up.\n const derived = reconcileGeneratedFiles(\n cwd,\n [{ relPath: 'AGENTS.md', content: agentsMd(config) }],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n const agents = writeAgentFiles(cwd, grokAgentFiles(config), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // Re-detecting on every build self-corrects the command if the user\n // switched package managers since `ahk init` — no migration flag needed.\n mergeGrokConfigToml(join(cwd, '.grok/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n writeSkills(cwd, '.grok/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n }\n\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Permissions sync not needed for grok-cli — skipping')\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport { mergeOpencodeJson } from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport { agentBuilder, agentConsultant, agentExplorer, agentLead, agentReviewer, agentsMd, HEALTH_SH, translateFrontmatterForOpenCode } from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** Agent files this provider owns. Shared by `scaffold()` and `build()`. */\nfunction opencodeAgentFiles(config: HarnessConfig): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.opencode/agents/lead.md', content: translateFrontmatterForOpenCode(agentLead({ projectName }), 'lead') },\n { relPath: '.opencode/agents/explorer.md', content: translateFrontmatterForOpenCode(agentExplorer({ projectName }), 'explorer') },\n { relPath: '.opencode/agents/consultant.md', content: translateFrontmatterForOpenCode(agentConsultant({ projectName }), 'consultant') },\n { relPath: '.opencode/agents/builder.md', content: translateFrontmatterForOpenCode(agentBuilder({ projectName }), 'builder') },\n { relPath: '.opencode/agents/reviewer.md', content: translateFrontmatterForOpenCode(agentReviewer({ projectName }), 'reviewer') },\n ]\n}\n\nexport class OpenCodeMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd } = opts\n\n const write = (relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n }\n\n // AGENTS.md — fresh project, write unconditionally, but STAMP the provenance\n // marker so the first `ahk build` recognizes it as our own output (a\n // markerless file would look human-edited and freeze config propagation).\n write('AGENTS.md', stampGenerated(agentsMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write('health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold — it\n // is accumulable user data reconciled via the DB round-trip in init.ts, so\n // the scaffold no longer writes it (which used to clobber a hand-written\n // backlog).\n\n // scope='global' — current.md lives under ~/.harness/dbs/<projectId>/\n // (see resolveGlobalStorageDir in db.ts), not in the project tree, and\n // `markdownFallback.path` doesn't exist on GlobalStorageConfig at all.\n // Skip the local placeholder entirely for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .opencode/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, opencodeAgentFiles(config))\n\n // opencode.json — MERGE, never overwrite whole file. Detect the project's\n // package manager fresh from cwd so the spawned command matches npm/pnpm/yarn.\n mergeOpencodeJson(join(cwd, 'opencode.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n\n appendGitignore(cwd)\n writeSkills(cwd, '.opencode/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md is DERIVED FROM CONFIG. Reconcile against the provenance marker:\n // untouched files propagate config changes, hand-edited files are preserved\n // (and reported), --force regenerates after backing up.\n const derived = reconcileGeneratedFiles(\n cwd,\n [{ relPath: 'AGENTS.md', content: agentsMd(config) }],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n const agents = writeAgentFiles(cwd, opencodeAgentFiles(config), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // Re-detecting on every build self-corrects the command if the user\n // switched package managers since `ahk init` — no migration flag needed.\n mergeOpencodeJson(join(cwd, 'opencode.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n writeSkills(cwd, '.opencode/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n }\n\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Permissions sync not needed for opencode — skipping')\n }\n}\n\n","import { ClaudeCodeMaterializer } from './claude-code'\nimport { CodexCliMaterializer } from './codex-cli'\nimport { GrokMaterializer } from './grok'\nimport { OpenCodeMaterializer } from './opencode'\n\nimport type { ReconcileResult, WriteAgentFilesResult } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\nexport interface BuildMaterializerOptions {\n /** Regenerate agent files that already exist, DESTROYING any customization.\n * A backup of the previous content is written first; if the backup fails,\n * nothing is overwritten. */\n force?: boolean\n /** Claude Code only: per-role model choice collected via\n * `promptClaudeAgentModels`, keyed by `AgentName`. Threaded into\n * `ClaudeCodeMaterializer.build()` to inject a `model:` frontmatter line\n * when regenerating agent files (currently only reachable via\n * `ahk build --force`, which re-runs the prompt). Same shape as\n * `ScaffoldOptions['claudeAgentModels']` — reused verbatim rather than\n * redeclared. Purely additive and optional: `opencode.ts`, `codex-cli.ts`,\n * and `grok.ts` share the identical `build()` signature and simply never\n * read this field. */\n claudeAgentModels?: ScaffoldOptions['claudeAgentModels']\n /** Codex CLI only: per-role model + reasoning-effort choice collected via\n * `promptCodexAgentModels`, keyed by `AgentName`. Same shape as\n * `ScaffoldOptions['codexAgentModels']` — reused verbatim rather than\n * redeclared. Purely additive and optional: `claude-code.ts`, `opencode.ts`,\n * and `grok.ts` share the identical `build()` signature and simply never\n * read this field — this cuts both ways, since `codex-cli.ts` likewise\n * never reads `claudeAgentModels`. */\n codexAgentModels?: ScaffoldOptions['codexAgentModels']\n}\n\nexport interface BuildReport {\n /** What happened to the provider's agent files during this build. */\n agents: WriteAgentFilesResult\n /** What happened to the config-derived files (AGENTS.md, and CLAUDE.md for\n * claude-code) during this build. Untouched files propagate config changes\n * automatically; hand-edited files are preserved and reported. */\n derived: ReconcileResult\n}\n\nexport interface Materializer {\n scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void>\n build(config: HarnessConfig, cwd: string, opts?: BuildMaterializerOptions): Promise<BuildReport>\n migrate(config: HarnessConfig, to: Provider, cwd: string): Promise<void>\n syncPermissions(cwd: string): Promise<void>\n}\n\nexport function getMaterializer(provider: Provider): Materializer {\n switch (provider) {\n case 'claude-code':\n return new ClaudeCodeMaterializer()\n case 'opencode':\n return new OpenCodeMaterializer()\n case 'codex-cli':\n return new CodexCliMaterializer()\n case 'grok-cli':\n return new GrokMaterializer()\n default:\n throw new Error(`Unknown provider: ${provider as string}`)\n }\n}\n","import * as p from '@clack/prompts'\n\nimport type { AgentName } from '@/core/materializer/agent-restrictions'\nimport type { Provider } from '@/types'\n\nconst AGENT_LABELS: { key: AgentName; label: string }[] = [\n { key: 'lead', label: 'Lead' },\n { key: 'explorer', label: 'Explorer' },\n { key: 'consultant', label: 'Consultant' },\n { key: 'builder', label: 'Builder' },\n { key: 'reviewer', label: 'Reviewer' },\n]\n\n/**\n * Claude Code only: prompt once per generated role (lead, explorer,\n * consultant, builder, reviewer) for a model preference, defaulting to\n * 'inherit' (no override). The choice is meant to be written straight into\n * that role's generated `.claude/agents/<role>.md` frontmatter — never into\n * config.\n *\n * Shared by three call sites that all need the identical prompt loop and\n * cancel-handling: `ahk init`'s one-time scaffold, `ahk models`, and\n * `ahk build --force` (claude-code only). Extracted from `runInit` so the\n * loop is defined once instead of triplicated.\n *\n * Returns `{}` immediately for any other provider, so call sites don't need\n * their own provider guard before calling this.\n */\nexport async function promptClaudeAgentModels(\n provider: Provider\n): Promise<Partial<Record<AgentName, string>>> {\n const claudeAgentModels: Partial<Record<AgentName, string>> = {}\n if (provider !== 'claude-code') return claudeAgentModels\n\n for (const agent of AGENT_LABELS) {\n const val = await p.select({\n message: `Model for ${agent.label}`,\n options: [\n { value: 'inherit', label: 'inherit (default)' },\n { value: 'haiku', label: 'haiku' },\n { value: 'sonnet', label: 'sonnet' },\n { value: 'opus', label: 'opus' },\n { value: 'fable', label: 'fable' },\n ],\n initialValue: 'inherit',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n claudeAgentModels[agent.key] = val as string\n }\n\n return claudeAgentModels\n}\n","import * as p from '@clack/prompts'\n\nimport type { AgentName } from '@/core/materializer/agent-restrictions'\nimport type { CodexAgentModelChoice, Provider } from '@/types'\n\nconst AGENT_LABELS: { key: AgentName; label: string }[] = [\n { key: 'lead', label: 'Lead' },\n { key: 'explorer', label: 'Explorer' },\n { key: 'consultant', label: 'Consultant' },\n { key: 'builder', label: 'Builder' },\n { key: 'reviewer', label: 'Reviewer' },\n]\n\n// Verified against Codex CLI's own Rust source (see task #81 consultant\n// advisory for citations): `codex-rs/skills/src/assets/samples/openai-docs/\n// references/latest-model.md` lists these 7 slugs. Six are corroborated by\n// repo-wide code-search hits; `gpt-5.3-codex-spark` has none, but the user\n// explicitly confirmed keeping it (they trust the live picker over a\n// public-repo grep). This is a plain string list, not a TS literal union —\n// model catalogs go stale fast, and a hardcoded compile-time union would\n// turn a stale entry into a hard error for someone hand-editing a newer\n// model into their TOML.\nconst CODEX_MODEL_CHOICES = [\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n 'gpt-5.6-luna',\n 'gpt-5.5',\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.3-codex-spark',\n] as const\n\n// Intersection of Codex's real `ReasoningEffort` wire enum\n// (`codex-rs/protocol/src/openai_models.rs`: none|minimal|low|medium|high|\n// xhigh|max|ultra|Custom) and the whitelist its own per-agent-role-file\n// writer accepts (`codex-rs/external-agent-migration/src/subagents.rs`,\n// `map_agent_reasoning_effort`, which also rewrites max→xhigh and drops\n// ultra). `none` is deliberately excluded from this picker — it disables\n// reasoning entirely, a footgun for a lead/reviewer role; a user who wants\n// it can still hand-edit the TOML.\nconst CODEX_EFFORT_CHOICES = ['minimal', 'low', 'medium', 'high', 'xhigh'] as const\n\n/**\n * Codex CLI only: prompt once per generated role (lead, explorer, consultant,\n * builder, reviewer) for a model AND a reasoning-effort preference. Both\n * choices are written straight into that role's generated\n * `.codex/agents/<role>.toml` (`model = \"...\"` / `model_reasoning_effort =\n * \"...\"` lines) — never into config.toml, which carries its own separate\n * top-level default (see `ensureTomlTopLevelKey` in mcp-merge.ts).\n *\n * Mirrors `promptClaudeAgentModels` (claude-model-prompt.ts) in shape and\n * cancel-handling. Returns `{}` immediately for any other provider, so call\n * sites (currently only `ahk init`) don't need their own provider guard\n * before calling this — and no other provider's init can ever hang on these\n * prompts.\n */\nexport async function promptCodexAgentModels(\n provider: Provider\n): Promise<Partial<Record<AgentName, CodexAgentModelChoice>>> {\n const codexAgentModels: Partial<Record<AgentName, CodexAgentModelChoice>> = {}\n if (provider !== 'codex-cli') return codexAgentModels\n\n for (const agent of AGENT_LABELS) {\n const modelVal = await p.select({\n message: `Model for ${agent.label}`,\n options: CODEX_MODEL_CHOICES.map((value) => ({ value, label: value })),\n initialValue: 'gpt-5.6-terra',\n })\n if (p.isCancel(modelVal)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n\n const effortVal = await p.select({\n message: `Reasoning effort for ${agent.label}`,\n options: CODEX_EFFORT_CHOICES.map((value) => ({ value, label: value })),\n initialValue: 'medium',\n })\n if (p.isCancel(effortVal)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n\n codexAgentModels[agent.key] = {\n model: modelVal as string,\n effort: effortVal as CodexAgentModelChoice['effort'],\n }\n }\n\n return codexAgentModels\n}\n","import { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { startDashboardServer } from '@/core/dashboard-server'\nimport { openDB, resolveSqlitePath } from '@/core/db'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\ninterface DashboardOptions {\n port: number\n open: boolean\n}\n\nexport async function runDashboard(cwd: string, opts: DashboardOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n const dbPath = config.database.type === 'sqlite' ? resolveSqlitePath(config, cwd, homedir()) : null\n const staticPath = join(__dirname, 'dashboard-dist')\n\n const { url } = await startDashboardServer(db, dbPath, staticPath, opts.port)\n\n console.log(pc.green(`✓`) + ` Dashboard running at ${pc.bold(pc.cyan(url))}`)\n console.log(pc.dim(` WebSocket live updates enabled`))\n console.log(pc.dim(` Press Ctrl+C to stop`))\n\n if (opts.open) {\n const { default: open } = await import('open')\n await open(url)\n }\n\n process.on('SIGINT', () => {\n process.exit(0)\n })\n\n // Keep process alive until SIGINT\n await new Promise<void>(() => { })\n}\n","import { watch } from 'node:fs'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { extname, join } from 'node:path'\nimport { serve } from '@hono/node-server'\nimport { Hono } from 'hono'\nimport { WebSocketServer } from 'ws'\n\nimport { DASHBOARD_BIND_HOST, findFreePort } from './port-utils'\n\nimport type { HarnessDB } from './db'\nimport type { EventEmitter } from 'node:events'\nimport type { IncomingMessage } from 'node:http'\nimport type { Socket } from 'node:net'\n\n// ─── Static file serving ──────────────────────────────────────────────────────\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n}\n\nfunction fileResponse(filePath: string): Response {\n const content = readFileSync(filePath)\n const mime = MIME[extname(filePath)] ?? 'application/octet-stream'\n return new Response(content, {\n headers: { 'Content-Type': mime, 'Cache-Control': 'no-cache' },\n })\n}\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\n/**\n * Resolve once the server has actually bound, or reject with an actionable\n * message if the bind fails.\n *\n * `@hono/node-server`'s `serve()` returns synchronously before the bind\n * settles and attaches no `'error'` listener, so a failed bind lands as an\n * unhandled `'error'` event that terminates the process. Awaiting this turns\n * that crash into a rejected promise the caller can report, and also closes the\n * TOCTOU window between the free-port probe and the real bind.\n */\n/**\n * The subset of `http.Server` this helper needs: the `EventEmitter` surface for\n * the one-shot `'error'`/`'listening'` race, plus `close()` so a failed bind can\n * release the handle. `@hono/node-server`'s `serve()` return (`Server`,\n * `Http2Server`, or `Http2SecureServer`) and a bare `node:http` server both\n * satisfy this, so widening the parameter to it breaks no caller.\n */\ntype ClosableServer = EventEmitter & {\n close: (callback?: (err?: Error) => void) => void\n}\n\nexport function awaitServerListening(server: ClosableServer, port: number): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n // Best-effort teardown so a failed bind never leaves the http.Server handle\n // dangling. The server may never have bound (close() then reports\n // ERR_SERVER_NOT_RUNNING): pass a noop callback so that error is delivered to\n // the callback rather than re-emitted as an unhandled 'error' event, and\n // guard any synchronous throw. This must never mask the original\n // bind-failure rejection below, nor settle the promise a second time — the\n // one-shot onError has already been removed by the time it fires, so close()\n // cannot re-enter it.\n const closeQuietly = () => {\n try {\n server.close(() => {\n // swallow ERR_SERVER_NOT_RUNNING / any close error — best-effort\n })\n } catch {\n // handle was never open; nothing to release\n }\n }\n const onError = (err: NodeJS.ErrnoException) => {\n server.off('listening', onListening)\n closeQuietly()\n if (err.code === 'EADDRINUSE') {\n reject(\n new Error(\n `Port ${port} was taken by another process while starting the dashboard. Please retry, or pick a different port with --port.`\n )\n )\n return\n }\n reject(new Error(`Failed to start the dashboard on port ${port}: ${err.message}`))\n }\n const onListening = () => {\n server.off('error', onError)\n resolve()\n }\n server.once('error', onError)\n server.once('listening', onListening)\n })\n}\n\nexport interface DashboardServerResult {\n url: string\n close: () => void\n}\n\nexport async function startDashboardServer(\n db: HarnessDB,\n dbPath: string | null,\n staticPath: string,\n port: number\n): Promise<DashboardServerResult> {\n const app = new Hono()\n const { tasks, actions, stats } = db\n\n // ─── CORS ─────────────────────────────────────────────────────────────────\n app.use('/api/*', async (c, next) => {\n await next()\n c.res.headers.set('Access-Control-Allow-Origin', '*')\n })\n\n // ─── Stats overview ───────────────────────────────────────────────────────\n app.get('/api/stats', async (c) => {\n await db.reconnect()\n const summary = await tasks.getStatusSummary()\n const byStatus: Record<string, number> = { pending: 0, in_progress: 0, done: 0, blocked: 0 }\n for (const { status, total } of summary) byStatus[status] = total\n const counts = await stats.getCounts()\n return c.json({ byStatus, ...counts })\n })\n\n // ─── Meta ─────────────────────────────────────────────────────────────────\n app.get('/api/meta', (c) => {\n return c.json({ ok: true })\n })\n\n // ─── Tasks list ───────────────────────────────────────────────────────────\n app.get('/api/tasks', async (c) => {\n await db.reconnect()\n const includeArchived = c.req.query('includeArchived') === 'true'\n return c.json(await tasks.getAllWithAcceptanceCounts(includeArchived))\n })\n\n // ─── Task detail ──────────────────────────────────────────────────────────\n app.get('/api/tasks/:id', async (c) => {\n await db.reconnect()\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n\n const acceptance = await tasks.getAcceptance(id)\n const taskActions = await actions.getWithDetails(id)\n return c.json({ ...task, acceptance, actions: taskActions })\n })\n\n // ─── Task update (PATCH) ────────────────────────────────────────────────\n app.patch('/api/tasks/:id', async (c) => {\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n\n const body = await c.req.json()\n const updateParams: { title?: string; description?: string | null; slug?: string } = {}\n if (body.title !== undefined) updateParams.title = body.title\n if (body.description !== undefined) updateParams.description = body.description\n\n await db.updateTask(id, updateParams)\n\n if (body.acceptance !== undefined && Array.isArray(body.acceptance)) {\n await db.updateTaskAcceptance(\n id,\n body.acceptance.map((a: string) => a.trim()).filter(Boolean)\n )\n }\n\n const updated = await tasks.getById(id)\n const acceptance = await tasks.getAcceptance(id)\n const taskActions = await actions.getWithDetails(id)\n return c.json({ ...updated, acceptance, actions: taskActions })\n })\n\n // ─── Archive task ─────────────────────────────────────────────────────────\n app.patch('/api/tasks/:id/archive', async (c) => {\n await db.reconnect()\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n const updated = await db.archiveTask(id)\n return c.json(updated)\n })\n\n // ─── Unarchive task ──────────────────────────────────────────────────────\n app.patch('/api/tasks/:id/unarchive', async (c) => {\n await db.reconnect()\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n const updated = await db.unarchiveTask(id)\n return c.json(updated)\n })\n\n // ─── Tools top ────────────────────────────────────────────────────────────\n app.get('/api/tools/top', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '20')\n return c.json(await actions.getTopTools(limit))\n })\n\n // ─── Tools recent ─────────────────────────────────────────────────────────\n app.get('/api/tools/recent', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '50')\n return c.json(await stats.getRecentTools(limit))\n })\n\n // ─── Files top ────────────────────────────────────────────────────────────\n app.get('/api/files/top', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '20')\n return c.json(await stats.getTopFiles(limit))\n })\n\n // ─── Files recent ─────────────────────────────────────────────────────────\n app.get('/api/files/recent', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '50')\n return c.json(await stats.getRecentFiles(limit))\n })\n\n // ─── Agents stats ─────────────────────────────────────────────────────────\n app.get('/api/agents/stats', async (c) => {\n await db.reconnect()\n return c.json(await stats.getAgentStats())\n })\n\n // ─── Timeline ─────────────────────────────────────────────────────────────\n app.get('/api/timeline', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '50')\n return c.json(await stats.getTimeline(limit))\n })\n\n // ─── Static SPA ───────────────────────────────────────────────────────────\n app.get('/*', (c) => {\n const urlPath = c.req.path\n if (urlPath !== '/') {\n const candidate = join(staticPath, urlPath)\n if (existsSync(candidate)) {\n try {\n return fileResponse(candidate)\n } catch {\n /* fall through */\n }\n }\n }\n return fileResponse(join(staticPath, 'index.html'))\n })\n\n // ─── Start HTTP server ────────────────────────────────────────────────────\n // The probe and the real bind MUST use the same host, otherwise the probe can\n // report an occupied port as free (see DASHBOARD_BIND_HOST).\n const resolvedPort = await findFreePort(port, { host: DASHBOARD_BIND_HOST })\n if (resolvedPort !== port) {\n console.log(`Port ${port} in use, using ${resolvedPort}`)\n }\n\n const httpServer = serve({\n fetch: app.fetch,\n port: resolvedPort,\n hostname: DASHBOARD_BIND_HOST,\n })\n\n // serve() returns before the bind settles and attaches no 'error' listener,\n // so an EADDRINUSE would otherwise surface as an unhandled event that kills\n // the process *after* the caller already printed a success banner. Wait for\n // the bind to resolve one way or the other before returning.\n await awaitServerListening(httpServer, resolvedPort)\n\n // Keep a handler attached for the server's lifetime so a later runtime error\n // is reported rather than crashing the process as an unhandled event.\n httpServer.on('error', (err: NodeJS.ErrnoException) => {\n console.error(`Dashboard server error: ${err.message}`)\n })\n\n // ─── WebSocket ────────────────────────────────────────────────────────────\n const wss = new WebSocketServer({ noServer: true })\n\n httpServer.on('upgrade', (req: IncomingMessage, socket: Socket, head: Buffer) => {\n if (req.url === '/ws') {\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit('connection', ws, req)\n })\n } else {\n socket.destroy()\n }\n })\n\n // ─── DB file watcher → broadcast update ──────────────────────────────────\n let debounce: ReturnType<typeof setTimeout>\n\n const broadcast = () => {\n clearTimeout(debounce)\n debounce = setTimeout(() => {\n for (const client of wss.clients) {\n if (client.readyState === 1) {\n client.send(JSON.stringify({ type: 'update' }))\n }\n }\n }, 150)\n }\n\n // SQLite only — no file to watch for Postgres/MySQL\n let watcher: ReturnType<typeof watch> | null = null\n if (dbPath) {\n const walPath = `${dbPath}-wal`\n const watchTarget = existsSync(walPath) ? walPath : dbPath\n watcher = watch(watchTarget, broadcast)\n }\n\n return {\n url: `http://localhost:${resolvedPort}`,\n close: () => {\n clearTimeout(debounce)\n watcher?.close()\n wss.close()\n httpServer.close()\n },\n }\n}\n","import { createServer } from 'node:net'\n\n/**\n * The host the dashboard binds to — the single source of truth shared by the\n * availability probe (`isPortFree`) and the real HTTP bind in\n * `startDashboardServer`.\n *\n * `undefined` means \"the Node default wildcard\": `::` on dual-stack hosts,\n * `0.0.0.0` on IPv4-only hosts. This is exactly what `@hono/node-server`'s\n * `serve()` binds when no `hostname` is supplied, so probe and bind cannot\n * disagree.\n *\n * Why not a literal like '127.0.0.1' or '::'?\n * - '127.0.0.1' was the original bug: a socket held on '::' does not block a\n * fresh 127.0.0.1 bind on macOS, so the probe reported occupied ports free,\n * the fallback never fired, and serve() then died on EADDRINUSE.\n * - A hardcoded '::' would fail with EADDRNOTAVAIL on IPv4-only hosts, making\n * every port look occupied.\n * Deferring to the platform default keeps probe and bind identical on every\n * platform. Both consumers must read this constant — never inline a host.\n */\nexport const DASHBOARD_BIND_HOST: string | undefined = undefined\n\nexport interface FindFreePortOptions {\n /** How many consecutive ports to try before giving up. */\n maxAttempts?: number\n /** Host to probe. Must match the host the caller will actually bind to. */\n host?: string\n}\n\n/**\n * Probe whether `port` can be bound on `host`.\n *\n * The host argument is required-by-convention: callers must pass the same host\n * they intend to bind on, otherwise the probe answers a different question than\n * the one being asked.\n */\nexport function isPortFree(port: number, host: string | undefined = DASHBOARD_BIND_HOST): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer()\n server.once('error', () => resolve(false))\n server.once('listening', () => {\n server.close(() => resolve(true))\n })\n server.listen(port, host)\n })\n}\n\nexport async function findFreePort(start: number, options: FindFreePortOptions = {}): Promise<number> {\n const { maxAttempts = 10, host = DASHBOARD_BIND_HOST } = options\n\n // Guard the boundary. `start` MUST be a number: the loop below computes\n // `start + i`, which silently becomes string concatenation if a string slips\n // through ('4242' + 0 === '42420'), producing a nonsense probe port and no\n // usable error. Commander hands `--port` over as a string (cli.ts:135), so\n // the sole caller coerces it (cli.ts:138). This check makes that contract\n // enforced rather than merely observed — if the coercion is ever removed,\n // the failure is loud and immediate instead of a bizarre port number.\n if (typeof start !== 'number' || !Number.isInteger(start)) {\n throw new Error(\n `findFreePort requires an integer port number, received ${typeof start} ${JSON.stringify(start)}. ` +\n `The port must be coerced to a number before it reaches here (commander supplies --port as a string).`\n )\n }\n\n for (let i = 0; i < maxAttempts; i++) {\n const port = start + i\n if (await isPortFree(port, host)) return port\n }\n\n throw new Error(\n `Could not find a free port after ${maxAttempts} attempts (tried ${start}-${start + maxAttempts - 1}). Please free a port and try again.`\n )\n}\n","import pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { getDoctorStatus } from '@/core/doctor'\n\nimport type { AgentStatus, SkillStatus } from '@/core/doctor'\n\n// ─── Formatting helpers ───────────────────────────────────────────────────────\n\nfunction ok(label: string, detail: string): void {\n console.log(` ${pc.cyan(label.padEnd(16))}${pc.green('[✓]')} ${detail}`)\n}\n\nfunction warn(label: string, detail: string, hint?: string): void {\n console.log(` ${pc.cyan(label.padEnd(16))}${pc.yellow('[!]')} ${detail}`)\n if (hint) {\n console.log(` ${''.padEnd(16)} ${pc.dim(hint)}`)\n }\n}\n\nfunction neutral(label: string, detail: string): void {\n console.log(` ${pc.cyan(label.padEnd(16))}${pc.dim('[~]')} ${detail}`)\n}\n\n// ─── Section formatters ───────────────────────────────────────────────────────\n\nfunction printLibSection(lib: { current: string; latest: string | null; outdated: boolean }): void {\n if (lib.latest === null) {\n neutral('lib version', `${lib.current} (unknown — could not reach npm registry)`)\n } else if (lib.outdated) {\n warn(\n 'lib version',\n `${lib.current} → ${lib.latest} available`,\n `run: npm i @cardor/agent-harness-kit@latest && ahk build`\n )\n } else {\n ok('lib version', `${lib.current} (up to date)`)\n }\n}\n\nfunction printAgentsSection(agents: AgentStatus[]): void {\n if (agents.length === 0) {\n warn('agent files', 'no config found — run: ahk init')\n return\n }\n\n // Existence only — a customised agent file is a supported state, not drift.\n const missing = agents.filter((a) => a.status === 'missing')\n\n if (missing.length === 0) {\n ok('agent files', 'all present')\n return\n }\n\n for (const agent of missing) {\n warn('agent files', `${agent.name} missing`, 'run: ahk build')\n }\n}\n\nfunction printSkillsSection(skills: SkillStatus[]): void {\n if (skills.length === 0) {\n warn('harness skills', 'no config found — run: ahk init')\n return\n }\n\n const issues = skills.filter((s) => s.status !== 'ok')\n if (issues.length === 0) {\n ok('harness skills', 'all present and up to date')\n return\n }\n\n for (const skill of issues) {\n const detail =\n skill.status === 'missing' ? `${skill.name} missing` : `${skill.name} outdated`\n warn('harness skills', detail, 'run: ahk build')\n }\n}\n\n// ─── Main command ─────────────────────────────────────────────────────────────\n\nexport async function runDoctor(cwd: string): Promise<void> {\n // Check for config first so we can give a helpful upfront message\n let configFound = true\n try {\n await loadConfig(cwd)\n } catch {\n configFound = false\n }\n\n console.log('')\n console.log(pc.bold(`● ahk doctor ` + '─'.repeat(44)))\n console.log('')\n\n const status = await getDoctorStatus(cwd)\n\n printLibSection(status.lib)\n\n if (!configFound) {\n console.log('')\n warn('config', 'no agent-harness-kit.config found', 'run: ahk init')\n console.log('')\n return\n }\n\n console.log('')\n printAgentsSection(status.agents)\n\n console.log('')\n printSkillsSection(status.skills)\n\n console.log('')\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { loadConfig } from '@/core/config'\nimport { pkg } from '@/core/package-data'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface LibStatus {\n current: string\n latest: string | null // null = couldn't fetch (offline)\n outdated: boolean\n}\n\n/**\n * Agent files are checked for EXISTENCE ONLY — there is deliberately no\n * 'outdated' state. Agent definitions are meant to be customised freely (body\n * and frontmatter alike), so comparing them against the packaged template would\n * flag every intentional edit as drift. Skills keep their content comparison;\n * they are not a customisation surface.\n */\nexport interface AgentStatus {\n name: string\n status: 'ok' | 'missing'\n}\n\nexport interface SkillStatus {\n name: string\n status: 'ok' | 'missing' | 'outdated'\n}\n\nexport interface DoctorStatus {\n lib: LibStatus\n agents: AgentStatus[]\n skills: SkillStatus[]\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`\nconst TIMEOUT_MS = 2000\nconst LIB_VERSION_CACHE_TTL_MS = 5 * 60 * 1000 // 5 minutes\nconst AGENT_NAMES = ['lead', 'explorer', 'consultant', 'builder', 'reviewer'] as const\nexport type AgentName = (typeof AGENT_NAMES)[number]\nconst SKILL_NAMES = ['ahk-ask', 'ahk-consultant', 'ahk-triage', 'ahk-review'] as const\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n// ─── Lib version check ────────────────────────────────────────────────────────\n\n// In-memory TTL cache for the npm registry lookup only. Agent/skill file checks\n// are local and cheap, so they are intentionally NOT cached — only the network\n// call to the npm registry benefits from memoization.\nlet libVersionCache: { status: LibStatus; fetchedAt: number } | null = null\n\n/** Clears the in-memory lib version cache. Exposed for tests only. */\nexport function __resetLibVersionCacheForTests(): void {\n libVersionCache = null\n}\n\nasync function checkLibVersion(): Promise<LibStatus> {\n const current = pkg.version\n\n if (libVersionCache && Date.now() - libVersionCache.fetchedAt < LIB_VERSION_CACHE_TTL_MS) {\n // Cache is keyed to the running process's current version. If somehow the\n // running version changed (unlikely mid-process), fall through to refetch.\n if (libVersionCache.status.current === current) {\n return libVersionCache.status\n }\n }\n\n try {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), TIMEOUT_MS)\n\n const res = await fetch(REGISTRY_URL, { signal: controller.signal })\n clearTimeout(timer)\n\n const data = (await res.json()) as { version: string }\n const latest = data.version\n const outdated = isNewer(latest, current)\n const status: LibStatus = { current, latest, outdated }\n libVersionCache = { status, fetchedAt: Date.now() }\n return status\n } catch {\n const status: LibStatus = { current, latest: null, outdated: false }\n // Cache the offline result too, so repeated calls within the TTL don't\n // keep retrying a network call that just timed out/failed.\n libVersionCache = { status, fetchedAt: Date.now() }\n return status\n }\n}\n\nfunction isNewer(latest: string, current: string): boolean {\n const toNum = (v: string) => v.split('.').map(Number)\n const [lMaj, lMin, lPat] = toNum(latest)\n const [cMaj, cMin, cPat] = toNum(current)\n if (lMaj !== cMaj) return lMaj > cMaj\n if (lMin !== cMin) return lMin > cMin\n return lPat > cPat\n}\n\n// ─── Agent file check ─────────────────────────────────────────────────────────\n\nfunction getProviderAgentInfo(provider: string): {\n agentsDir: string\n ext: string\n} {\n switch (provider) {\n case 'claude-code':\n return { agentsDir: '.claude/agents', ext: '.md' }\n case 'opencode':\n return { agentsDir: '.opencode/agents', ext: '.md' }\n case 'codex-cli':\n return { agentsDir: '.codex/agents', ext: '.toml' }\n case 'grok-cli':\n return { agentsDir: '.grok/agents', ext: '.md' }\n default:\n return { agentsDir: '.claude/agents', ext: '.md' }\n }\n}\n\n// Root-based existence check — shared by both the project-local (cwd) and\n// global (homeDir) checks. Callers resolve `agentsRoot` to an absolute\n// directory; this function never derives paths on its own.\n//\n// Existence is the ONLY signal. The file's contents are never read, so any\n// hand-editing of an agent definition is invisible here by design.\nfunction checkAgentFilesAtRoot(agentsRoot: string, ext: string): AgentStatus[] {\n return AGENT_NAMES.map((name) => {\n const filePath = join(agentsRoot, `${name}${ext}`)\n return { name, status: existsSync(filePath) ? ('ok' as const) : ('missing' as const) }\n })\n}\n\nfunction checkAgentFiles(cwd: string, provider: string): AgentStatus[] {\n const { agentsDir, ext } = getProviderAgentInfo(provider)\n return checkAgentFilesAtRoot(join(cwd, agentsDir), ext)\n}\n\n// ─── Skill check ─────────────────────────────────────────────────────────────\n\nfunction getProviderSkillsDir(provider: string): string {\n switch (provider) {\n case 'claude-code':\n return '.claude/skills'\n case 'opencode':\n return '.opencode/skills'\n case 'codex-cli':\n return '.agents/skills'\n case 'grok-cli':\n return '.grok/skills'\n default:\n return '.claude/skills'\n }\n}\n\n// Root-based comparison — shared by both the project-local (cwd) and global\n// (homeDir) checks. `skillsRoot` is an absolute directory already resolved\n// by the caller.\nfunction checkSkillsAtRoot(skillsRoot: string): SkillStatus[] {\n // Skills are in src/core/materializer/skills/ — at runtime dist/core/materializer/skills/\n const skillSourceBase = join(__dirname, 'skills')\n\n return SKILL_NAMES.map((name) => {\n const livePath = join(skillsRoot, name, 'SKILL.md')\n const sourcePath = join(skillSourceBase, name, 'SKILL.md')\n\n if (!existsSync(livePath)) {\n return { name, status: 'missing' as const }\n }\n\n try {\n const live = readFileSync(livePath, 'utf8')\n const source = readFileSync(sourcePath, 'utf8')\n return { name, status: live === source ? 'ok' : 'outdated' }\n } catch {\n return { name, status: 'outdated' as const }\n }\n })\n}\n\nfunction checkSkills(cwd: string, provider: string): SkillStatus[] {\n const skillsDir = getProviderSkillsDir(provider)\n return checkSkillsAtRoot(join(cwd, skillsDir))\n}\n\n// ─── Main export ──────────────────────────────────────────────────────────────\n\nexport async function getDoctorStatus(cwd: string): Promise<DoctorStatus> {\n const lib = await checkLibVersion()\n\n let config\n try {\n config = await loadConfig(cwd)\n } catch {\n // Config not found — return minimal status with empty agent/skill checks\n return {\n lib,\n agents: [],\n skills: [],\n }\n }\n\n const provider = config.provider\n\n const agents = checkAgentFiles(cwd, provider)\n const skills = checkSkills(cwd, provider)\n\n return { lib, agents, skills }\n}\n","import { writeFileSync } from 'node:fs'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\ninterface ExportOptions {\n sql?: boolean\n json?: boolean\n output?: string\n}\n\nexport async function runExport(cwd: string, opts: ExportOptions): Promise<void> {\n if (!opts.sql && !opts.json) {\n console.error(pc.red('Specify --sql or --json'))\n process.exit(1)\n }\n\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n if (opts.json) {\n const data = await db.exportJson()\n const out = JSON.stringify(data, null, 2) + '\\n'\n if (opts.output) {\n writeFileSync(opts.output, out, 'utf8')\n console.log(pc.green(`✓ Exported JSON → ${opts.output}`))\n } else {\n process.stdout.write(out)\n }\n }\n\n if (opts.sql) {\n console.error(pc.dim('SQL dump requires direct SQLite access — use: sqlite3 .harness/harness.db .dump'))\n process.exit(1)\n }\n } finally {\n await db.close()\n }\n}\n","import { spawnSync } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { resolveSqlitePath } from '@/core/db'\n\nimport type { HarnessConfig } from '@/types'\n\nfunction checkLine(label: string | null, ok: boolean, message: string, indent = 0): void {\n const prefix = label ? pc.cyan(`[${label}] `) : ' '.repeat(indent)\n const icon = ok ? pc.green('✓') : pc.red('✗')\n console.log(prefix + icon + ' ' + (ok ? pc.green(message) : pc.red(message)))\n}\n\nexport async function runHealth(cwd: string): Promise<void> {\n let config\n try {\n config = await loadConfig(cwd)\n } catch {\n console.error(pc.red('✗ No config found. Run: ahk init'))\n process.exit(1)\n }\n\n let allOk = true\n\n // ─── [checking DB] ──────────────────────────────────────────────────────────\n let dbOk: boolean\n if (config.database.type === 'sqlite') {\n const dbPath = resolveSqlitePath(config, cwd, homedir())\n dbOk = existsSync(dbPath)\n checkLine('checking DB', dbOk, `${dbPath} reachable`)\n } else {\n // For remote DBs we can't check the file — assume reachable (openDB will fail fast if not)\n dbOk = true\n checkLine('checking DB', true, `${config.database.type}://${config.database.connectionString.replace(/:[^:@]*@/, ':***@')} configured`)\n }\n if (!dbOk) allOk = false\n\n // ─── [checking agents] ──────────────────────────────────────────────────────\n const providerFiles = getProviderHealthFiles(config.provider)\n const agentsDir = providerFiles.agentsDir\n const agentNames = ['lead', 'explorer', 'consultant', 'builder', 'reviewer']\n\n const agentsLabelWidth = '[checking agents] '.length\n for (let i = 0; i < agentNames.length; i++) {\n const name = agentNames[i]\n const agentPath = join(cwd, agentsDir, `${name}${providerFiles.agentExtension}`)\n const ok = existsSync(agentPath)\n checkLine(\n i === 0 ? 'checking agents' : null,\n ok,\n `${name}${providerFiles.agentExtension} present`,\n agentsLabelWidth,\n )\n if (!ok) allOk = false\n }\n\n // ─── [checking MCP] ─────────────────────────────────────────────────────────\n if (config.tools.mcp.enabled) {\n const mcpFile = providerFiles.mcpFile\n const mcpPath = resolve(cwd, mcpFile)\n const mcpOk = existsSync(mcpPath)\n checkLine('checking MCP', mcpOk, `${mcpFile} valid`)\n if (!mcpOk) allOk = false\n }\n\n if (!allOk) {\n console.log('')\n console.error(pc.red('✗ Harness checks failed — fix the above before running health.sh'))\n process.exit(1)\n }\n\n // ─── Run health.sh ──────────────────────────────────────────────────────────\n const scriptPath = resolve(cwd, config.health.scriptPath)\n\n if (!existsSync(scriptPath)) {\n console.error(pc.red(`✗ health.sh not found: ${scriptPath}`))\n console.error(' Run ahk init first.')\n process.exit(1)\n }\n\n const result = spawnSync('bash', [scriptPath], {\n cwd,\n stdio: 'inherit',\n encoding: 'utf8',\n })\n\n if (result.error) {\n console.error(pc.red(`✗ Failed to run health.sh: ${result.error.message}`))\n process.exit(1)\n }\n\n if (result.status === 0) {\n console.log(pc.green('✓ Health check passed'))\n process.exit(0)\n } else {\n console.error(pc.red(`✗ Health check failed (exit ${result.status ?? 'unknown'})`))\n process.exit(result.status ?? 1)\n }\n}\n\nfunction getProviderHealthFiles(provider: HarnessConfig['provider']): {\n agentsDir: string\n agentExtension: '.md' | '.toml'\n mcpFile: string\n} {\n switch (provider) {\n case 'claude-code':\n return { agentsDir: '.claude/agents', agentExtension: '.md', mcpFile: '.mcp.json' }\n case 'opencode':\n return { agentsDir: '.opencode/agents', agentExtension: '.md', mcpFile: 'opencode.json' }\n case 'codex-cli':\n return { agentsDir: '.codex/agents', agentExtension: '.toml', mcpFile: '.codex/config.toml' }\n case 'grok-cli':\n return { agentsDir: '.grok/agents', agentExtension: '.md', mcpFile: '.grok/config.toml' }\n default:\n throw new Error(`Unknown provider: ${provider as string}`)\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { findConfigFile } from '@/core/config'\nimport { type HarnessDB, openDB } from '@/core/db'\nimport { getMaterializer } from '@/core/materializer/index'\nimport { slugify } from '@/core/materializer/scaffold-utils'\nimport { configCjs, configJson, configMjs, configTs } from '@/core/materializer/templates'\nimport { initDescriptionSchema, initDocsSchema, initNameSchema } from '@/schema/init'\nimport { taskDescriptionSchema, taskTitleSchema } from '@/schema/task'\nimport { cliFormWithRetry } from '@/utils/form'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\nimport { promptCodexAgentModels } from './codex-model-prompt'\nimport {\n applyConfigDefaults,\n detectConfigExtension,\n drawBox,\n printWelcomeMessage,\n readProjectNameFromPackageJson,\n} from './init-helpers'\n\nimport type { Provider } from '@/types'\n\ninterface InitOptions {\n name?: string\n provider?: string\n docs?: string\n tasks?: string\n storageScope?: string\n}\n\n/**\n * Reconcile `.harness/feature_list.json` — the \"human-editable task seed list\".\n *\n * This file is accumulable user data, so init MERGES rather than overwrites:\n * any hand-written backlog is absorbed into the DB (dedup by slug) alongside the\n * optional firstTask, then the canonical file is re-emitted. This is the same\n * round-trip `ahk sync both` performs, so init and sync agree on what the file\n * means. Merge is non-destructive by construction: it never destroys an existing\n * backlog and never drops a supplied firstTask.\n *\n * A malformed feature_list.json is still the user's data: it is left\n * byte-for-byte intact (never overwritten, never a process.exit), a supplied\n * firstTask is still seeded into the DB, and `parseFailed` is returned so the\n * caller can warn.\n */\nexport async function reconcileFeatureList(\n db: HarnessDB,\n installDir: string,\n storageDir: string,\n firstTask?: { title: string; description?: string; acceptance?: string[] }\n): Promise<{ parseFailed: boolean }> {\n const featureListPath = join(installDir, storageDir, 'feature_list.json')\n\n let existingSeeds: { slug: string; title: string; description?: string; acceptance?: string[] }[] = []\n let parseFailed = false\n if (existsSync(featureListPath)) {\n try {\n const parsed = JSON.parse(readFileSync(featureListPath, 'utf8'))\n if (!Array.isArray(parsed)) throw new Error('feature_list.json is not a JSON array')\n existingSeeds = parsed\n } catch {\n parseFailed = true\n }\n }\n\n const firstTaskSeed = firstTask\n ? {\n slug: slugify(firstTask.title),\n title: firstTask.title,\n description: firstTask.description,\n acceptance: firstTask.acceptance,\n }\n : undefined\n\n if (parseFailed) {\n // Do NOT touch the malformed file. Still seed the supplied firstTask into\n // the DB so it is not dropped.\n if (firstTaskSeed) await db.syncFromFeatureList([firstTaskSeed])\n } else {\n const seeds = firstTaskSeed ? [...existingSeeds, firstTaskSeed] : existingSeeds\n // Single dedup-by-slug merge (absorbs backlog + firstTask, collapses a\n // firstTask whose slug already exists), then re-emit the canonical file.\n await db.syncFromFeatureList(seeds)\n await db.writeFeatureList(installDir)\n }\n\n return { parseFailed }\n}\n\nexport async function runInit(cwd: string, flags: InitOptions): Promise<void> {\n const existingConfig = findConfigFile(cwd)\n if (existingConfig) {\n console.log(\n pc.yellow('⚠') +\n ' ' +\n pc.bold('Project already initialized.') +\n pc.dim(` (${existingConfig})`)\n )\n console.log()\n console.log(pc.dim('Suggested next steps:'))\n console.log(\n ' ' +\n pc.cyan('ahk build') +\n pc.dim(' — re-sync agent files after updating the library')\n )\n console.log(' ' + pc.cyan('ahk build --sync') + pc.dim(' — also sync agent permissions'))\n console.log(\n ' ' + pc.cyan('ahk reset') + pc.dim(' — wipe and re-initialize from scratch')\n )\n console.log(' ' + pc.cyan('ahk dashboard') + pc.dim(' — open the harness dashboard'))\n process.exit(0)\n }\n\n const detectedName = flags.name ?? readProjectNameFromPackageJson(cwd)\n const projectName = detectedName || 'my-project'\n printWelcomeMessage(projectName)\n\n // ─── Project name ────────────────────────────────────────────────────────\n let name: string\n if (flags.name) {\n name = flags.name\n } else {\n name = await cliFormWithRetry(async () => {\n const val = await p.text({\n message: 'Project name',\n placeholder: 'my-app',\n ...(detectedName && { initialValue: detectedName }),\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n return val as string\n }, initNameSchema)\n }\n\n // ─── Description ─────────────────────────────────────────────────────────\n const description = await cliFormWithRetry(async () => {\n const val = await p.text({\n message: 'Short description (shown to agents as context)',\n placeholder: 'A REST API for managing notes',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n return val as string\n }, initDescriptionSchema)\n\n // ─── Provider ─────────────────────────────────────────────────────────────\n let provider: Provider\n if (flags.provider && ['claude-code', 'opencode', 'codex-cli', 'grok-cli'].includes(flags.provider)) {\n provider = flags.provider as Provider\n } else {\n const val = await p.select({\n message: 'AI provider',\n options: [\n { value: 'opencode', label: 'OpenCode' },\n { value: 'claude-code', label: 'Claude Code' },\n { value: 'codex-cli', label: 'Codex CLI' },\n { value: 'grok-cli', label: 'Grok CLI' },\n ],\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n provider = val satisfies Provider\n }\n\n // Claude Code only: prompt once per generated role (lead, explorer,\n // consultant, builder, reviewer) for a model preference, defaulting to\n // 'inherit' (no override). The choice is written straight into that role's\n // generated `.claude/agents/<role>.md` frontmatter at scaffold time — never\n // into config (the old `config.agents.<role>.model` mechanism stays\n // removed). OpenCode is unaffected — it has no closed model enum to prompt\n // against.\n //\n // The prompt loop itself lives in `promptClaudeAgentModels` (shared with\n // `ahk models` and `ahk build --force`, which also re-run it to update an\n // existing project's agent files — see claude-code.ts).\n const claudeAgentModels = await promptClaudeAgentModels(provider)\n\n // Codex CLI only: prompt once per generated role for a model AND a\n // reasoning-effort preference. Both choices are written straight into that\n // role's generated `.codex/agents/<role>.toml` at scaffold time — never\n // into config.toml, which carries its own separate top-level default (see\n // `ensureTomlTopLevelKey` in mcp-merge.ts). OpenCode and Grok Build are\n // unaffected — same rationale as above.\n //\n // The prompt loop itself lives in `promptCodexAgentModels`\n // (codex-model-prompt.ts), mirroring `promptClaudeAgentModels`'s shape and\n // cancel-handling.\n const codexAgentModels = await promptCodexAgentModels(provider)\n\n // ─── Docs path ────────────────────────────────────────────────────────────\n let docsPath: string\n if (flags.docs) {\n docsPath = flags.docs\n } else {\n docsPath = await cliFormWithRetry(async () => {\n const val = await p.text({\n message: 'Docs folder path (agents will search here)',\n initialValue: './docs',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n return val as string\n }, initDocsSchema)\n }\n\n // ─── Storage scope ────────────────────────────────────────────────────────\n let storageScope: 'local' | 'global'\n if (flags.storageScope && ['local', 'global'].includes(flags.storageScope)) {\n storageScope = flags.storageScope as 'local' | 'global'\n } else {\n const val = await p.select({\n message: 'Storage scope',\n options: [\n { value: 'local', label: 'Local — .harness/harness.db lives in this project' },\n {\n value: 'global',\n label: 'Global — DB lives under ~/.harness/dbs/<projectId>/, outside the project',\n },\n ],\n initialValue: 'local',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n storageScope = val as 'local' | 'global'\n }\n\n // ─── Task adapter ─────────────────────────────────────────────────────────\n let tasksAdapter: string\n if (flags.tasks && ['local', 'jira', 'linear'].includes(flags.tasks)) {\n tasksAdapter = flags.tasks\n } else {\n const val = await p.select({\n message: 'Task adapter',\n options: [\n { value: 'local', label: 'Local (feature_list.json)' },\n { value: 'jira', label: 'Jira (coming soon)' },\n { value: 'linear', label: 'Linear (coming soon)' },\n ],\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n tasksAdapter = val as string\n }\n\n // ─── Optional first task ──────────────────────────────────────────────────\n const addFirstTask = await p.confirm({ message: 'Add your first task now?', initialValue: false })\n if (p.isCancel(addFirstTask)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n\n let firstTask: { title: string; description: string; acceptance: string[] } | undefined\n\n if (addFirstTask) {\n const taskTitle = await cliFormWithRetry(async () => {\n const val = await p.text({ message: 'Task title' })\n if (p.isCancel(val)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n return (val as string).trim()\n }, taskTitleSchema)\n\n const taskDesc = await cliFormWithRetry(async () => {\n const val = await p.text({ message: 'Task description', placeholder: 'What and why' })\n if (p.isCancel(val)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n return (val as string).trim()\n }, taskDescriptionSchema)\n\n const acceptance: string[] = []\n p.log.info('Acceptance criteria — one per line, empty line to finish')\n while (true) {\n const criterionVal = await p.text({\n message: '>',\n placeholder: 'Criterion (or press Enter to finish)',\n })\n if (p.isCancel(criterionVal) || !criterionVal || !(criterionVal as string).trim()) break\n acceptance.push((criterionVal as string).trim())\n }\n\n firstTask = { title: taskTitle, description: taskDesc, acceptance }\n }\n\n // ─── Scaffold ─────────────────────────────────────────────────────────────\n let configExt: 'json' | 'ts' | 'mjs' | 'cjs' = 'ts'\n let featureListParseFailedPath: string | null = null\n const spinner = p.spinner()\n spinner.start('Scaffolding...')\n\n try {\n const config = applyConfigDefaults({\n name,\n description,\n provider,\n docsPath,\n tasksAdapter,\n scope: storageScope,\n })\n const materializer = getMaterializer(provider)\n\n const installDir = cwd\n\n configExt = detectConfigExtension(cwd)\n const configFileName = `agent-harness-kit.config.${configExt}`\n const templateFn =\n configExt === 'json'\n ? configJson\n : configExt === 'ts'\n ? configTs\n : configExt === 'mjs'\n ? configMjs\n : configCjs\n const configContent = templateFn({\n name,\n description,\n provider,\n docsPath,\n tasksAdapter,\n port: config.tools.mcp.port,\n scope: config.storage.scope,\n projectId: config.storage.projectId,\n })\n writeFileSync(join(installDir, configFileName), configContent, 'utf8')\n\n // Create .harness dir (always project-local, regardless of storage scope —\n // this is where health.sh, scripts, and storage-state.json live)\n mkdirSync(join(installDir, config.storage.dir), { recursive: true })\n\n // Initialize SQLite DB (scope-aware: local → .harness/harness.db, global → ~/.harness/dbs/<projectId>/harness.db)\n const db = await openDB(config, installDir)\n\n // Always write .harness/storage-state.json — reflects the REAL current\n // storage state (project-local regardless of scope). Consumed by the\n // future `ahk migrate storage` command.\n await db.writeStorageState(installDir)\n\n // Scaffold provider-specific files\n await materializer.scaffold(config, { cwd: installDir, firstTask, claudeAgentModels, codexAgentModels })\n\n // Reconcile .harness/feature_list.json — the \"human-editable task seed\n // list\". Owned by init (not the scaffold), and MERGED rather than\n // overwritten. See reconcileFeatureList for the full contract.\n const { parseFailed } = await reconcileFeatureList(db, installDir, config.storage.dir, firstTask)\n if (parseFailed) {\n featureListParseFailedPath = join(config.storage.dir, 'feature_list.json')\n }\n\n await db.close()\n spinner.stop('')\n } catch (err) {\n spinner.stop('Failed')\n p.log.error(err instanceof Error ? err.message : String(err))\n throw err\n }\n\n if (featureListParseFailedPath) {\n console.log(\n pc.yellow('⚠') +\n ' Existing ' +\n pc.bold(featureListParseFailedPath) +\n ' is not valid JSON — left untouched. Fix it and run `ahk sync`.'\n )\n }\n\n console.log(pc.green('✓ Scaffolded harness in current directory'))\n\n // ─── Summary ─────────────────────────────────────────────────────────────-\n const PROVIDER_SUMMARY_INFO: Record<Provider, { agentsDir: string; mcpFile: string }> = {\n 'claude-code': { agentsDir: '.claude/agents/', mcpFile: '.mcp.json' },\n opencode: { agentsDir: '.opencode/agents/', mcpFile: './opencode.json' },\n 'codex-cli': { agentsDir: '.codex/agents/', mcpFile: '.codex/config.toml' },\n 'grok-cli': { agentsDir: '.grok/agents/', mcpFile: '.grok/config.toml' },\n }\n const { agentsDir, mcpFile } = PROVIDER_SUMMARY_INFO[provider]\n\n console.log('')\n console.log(pc.green(`✓ agent-harness-kit.config.${configExt}`))\n console.log(pc.green('✓ AGENTS.md'))\n console.log(pc.green('✓ health.sh'))\n console.log(\n pc.green(\n storageScope === 'global'\n ? '✓ ~/.harness/dbs/<projectId>/harness.db'\n : '✓ .harness/harness.db'\n )\n )\n console.log(\n pc.green(\n storageScope === 'global'\n ? '✓ ~/.harness/dbs/<projectId>/current.md'\n : '✓ .harness/current.md'\n )\n )\n console.log(pc.green('✓ .harness/storage-state.json'))\n console.log(pc.green(`✓ ${agentsDir}lead.md`))\n console.log(pc.green(`✓ ${agentsDir}explorer.md`))\n console.log(pc.green(`✓ ${agentsDir}builder.md`))\n console.log(pc.green(`✓ ${agentsDir}reviewer.md`))\n console.log(pc.green(`✓ ${mcpFile}`))\n console.log(pc.green('✓ .gitignore entries added'))\n\n console.log('')\n console.log(pc.cyan('→') + ` Edit ${pc.cyan('health.sh')} with your project checks`)\n console.log(pc.cyan('→') + ` ${pc.cyan('ahk task add')} to queue work for agents`)\n console.log(\n pc.cyan('→') +\n ` Enrich your docs with knowledge graphs: ${pc.cyan('https://github.com/safishamsi/graphify')}`\n )\n\n const recommendations: string[] = [\n ` Give a try to Heimdall MCP: Transparent proxy that traces every MCP tool call with OpenTelemetry. `,\n ` Learn more: ${pc.cyan('https://github.com/enmanuelmag/heimdall-mcp')} `,\n ]\n\n console.log('')\n drawBox(recommendations)\n}\n","\nimport * as v from 'valibot'\n\nexport const initNameSchema = v\n .pipe(\n v.string(),\n v.nonEmpty('Project name is required'),\n v.minLength(3, 'Project name must be at least 3 characters'),\n v.maxLength(50, 'Project name must be at most 50 characters'),\n v.trim(),\n )\n\nexport const initDescriptionSchema = v\n .pipe(\n v.string(),\n v.nonEmpty('Description is required'),\n v.maxLength(300, 'Description must be at most 300 characters'),\n v.trim(),\n )\n\nexport const initDocsSchema = v\n .pipe(\n v.string(),\n v.nonEmpty('Docs folder path is required'),\n v.regex(/^[\\w\\-./]+$/, 'Docs folder path can only contain letters, numbers, dashes, underscores, dots, and slashes'),\n v.trim(),\n )","import * as v from 'valibot'\n\nexport const taskTitleSchema = v.pipe(\n v.string(),\n v.nonEmpty('Task title is required'),\n v.minLength(3, 'Task title must be at least 3 characters'),\n v.maxLength(100, 'Task title must be at most 100 characters'),\n)\n\nexport const taskDescriptionSchema = v.pipe(\n v.string(),\n v.nonEmpty('Description is required'),\n)\n","import * as p from '@clack/prompts'\nimport * as v from 'valibot'\n\n\nexport const cliFormWithRetry = async <T>(\n formFn: () => Promise<T>,\n schema: v.GenericSchema,\n): Promise<T> => {\n while (true) {\n const res = await formFn()\n const result = v.safeParse(schema, res)\n\n if (result.success) return result.output as T\n\n const messages = result.issues.map((i) => i.message).join(', ')\n p.log.error(messages)\n p.log.info('Please try again.\\n')\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { isLocalInstallSatisfied } from '@/core/local-install-guard'\n\nimport type { HarnessConfig, Provider } from '@/types'\n\n/**\n * Read the `name` field from a `package.json` in the given directory.\n * Returns `null` if the file doesn't exist, is malformed, or lacks a valid `name`.\n */\nexport function readProjectNameFromPackageJson(cwd: string): string | null {\n try {\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) return null\n const content = readFileSync(pkgPath, 'utf8')\n const pkg = JSON.parse(content)\n const name = pkg?.name\n if (typeof name === 'string' && name.trim()) return name.trim()\n return null\n } catch {\n return null\n }\n}\n\n/**\n * Chooses the config file format for `ahk init`.\n *\n * A local install of the package is the PRECONDITION, checked before anything\n * else: without it, the project cannot resolve '@cardor/agent-harness-kit', so\n * a .ts config's `import type` — and any editor autocompletion that depends on\n * it — resolves to nothing and the user sees a red-underlined, apparently\n * broken project. JSON has nothing to resolve, so it is correct by\n * construction there.\n *\n * Only once the package IS installed locally do we fall through to the\n * pre-existing project-type detection (tsconfig.json / package.json type),\n * whose behavior is unchanged.\n */\nexport function detectConfigExtension(cwd: string): 'json' | 'ts' | 'mjs' | 'cjs' {\n if (!isLocalInstallSatisfied(cwd)) return 'json'\n try {\n if (existsSync(join(cwd, 'tsconfig.json'))) return 'ts'\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) return 'mjs'\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))\n if (pkg?.type === 'module') return 'mjs'\n } catch {}\n return 'mjs'\n}\n\nexport function applyConfigDefaults(params: {\n name: string\n description: string\n provider: Provider\n docsPath: string\n tasksAdapter: string\n /** Storage scope chosen during init. Defaults to 'local' for backward compat. */\n scope?: 'local' | 'global'\n /** Reuse an existing projectId (e.g. re-running init logic). If omitted, a\n * fresh UUID is generated — NEVER derive it from the project path/hash. */\n projectId?: string\n}): HarnessConfig {\n const scope = params.scope ?? 'local'\n const projectId = params.projectId ?? randomUUID()\n const baseStorage = {\n dir: '.harness',\n tasks: { adapter: params.tasksAdapter as 'local' },\n sections: {\n toolsUsed: true,\n filesModified: true,\n result: true,\n blockers: true,\n nextSteps: false,\n },\n }\n const storage: HarnessConfig['storage'] =\n scope === 'global'\n ? { ...baseStorage, markdownFallback: { enabled: true }, scope: 'global', projectId }\n : { ...baseStorage, markdownFallback: { enabled: true, path: '.harness/current.md' }, scope: 'local', projectId }\n\n return {\n provider: params.provider,\n project: {\n name: params.name,\n description: params.description,\n docsPath: params.docsPath,\n agentsMd: './AGENTS.md',\n },\n // No `agents` key: per-agent settings (model, role instructions) live in\n // the generated agent file, which is user-owned. This object is the runtime\n // twin of the config body emitted by configObjectBody() in templates.ts —\n // drift between the two is the bug this pairing has to keep out.\n database: { type: 'sqlite' as const },\n storage,\n health: {\n scriptPath: './health.sh',\n required: true,\n },\n tools: {\n mcp: { enabled: true, port: 3742 },\n scripts: { enabled: true, outputDir: './.harness/scripts' },\n },\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n\n/** Strip ANSI escape codes for width calculation */\nfunction stripAnsi(str: string): string {\n return str.replace(/\\x1B\\[[0-9;]*m/g, '')\n}\n\n\n/** Draw a bordered box matching printUpdateMessage() style */\nexport function drawBox(lines: string[]): void {\n // Calculate max content width (excluding ANSI codes)\n const width = Math.max(...lines.map((l) => stripAnsi(l).length))\n const border = '─'.repeat(width)\n\n console.log(pc.yellow(`┌${border}┐`))\n for (const line of lines) {\n const pad = width - stripAnsi(line).length\n const padStr = pad > 0 ? ' '.repeat(pad) : ''\n console.log(pc.yellow('│') + line + padStr + pc.yellow('│'))\n }\n console.log(pc.yellow(`└${border}┘`))\n}\n\n/**\n * Print a pretty welcome message when user executes the init command.\n * Styled to match the existing printUpdateMessage() aesthetic.\n */\nexport function printWelcomeMessage(projectName: string): void {\n const sep = '─'.repeat(38)\n\n // Build lines with embedded ANSI codes for width calculation\n const lines: string[] = [\n ` ${pc.bold(pc.white('agent-harness-kit'))} `,\n ` ${pc.gray('—')} harness scaffolding ${pc.gray('—')} `,\n ` ${pc.gray(sep)} `,\n ` ${pc.bold('Project:')} ${projectName || '—'} `,\n ` ${pc.bold('Status:')} ${pc.green('ready to configure')} `,\n ` ${pc.gray(sep)} `,\n ` ${pc.gray('Next steps:')} `,\n ` ${pc.gray('→')} ${pc.gray('Set up your AI provider config')} `,\n ` ${pc.gray('→')} ${pc.gray('Run your health check to verify')} `,\n ` ${pc.gray('→')} ${pc.gray('Start adding tasks for your agents')} `,\n ]\n\n console.log()\n drawBox(lines)\n console.log()\n}\n","import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { getMaterializer } from '@/core/materializer/index'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\nimport { promptCodexAgentModels } from './codex-model-prompt'\n\nimport type { Provider } from '@/types'\n\ninterface MigrateOptions {\n to?: string\n}\n\nexport async function runMigrate(cwd: string, opts: MigrateOptions): Promise<void> {\n const config = await loadConfig(cwd)\n\n let target: Provider\n if (opts.to && ['claude-code', 'opencode', 'codex-cli', 'grok-cli'].includes(opts.to)) {\n target = opts.to as Provider\n } else {\n const val = await p.select({\n message: 'Migrate to provider',\n options: [\n { value: 'claude-code', label: 'Claude Code' },\n { value: 'opencode', label: 'OpenCode' },\n { value: 'codex-cli', label: 'Codex CLI' },\n { value: 'grok-cli', label: 'Grok CLI' },\n ],\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n target = val as Provider\n }\n\n if (target === config.provider) {\n console.log(pc.dim(`Already on ${target} — nothing to migrate.`))\n return\n }\n\n // Re-run the same per-role model prompt `ahk init` and `ahk build --force`\n // use, scoped to whichever provider we're migrating to. Both helpers\n // self-guard on the provider argument, so calling both unconditionally is\n // safe — only the target's own questions actually appear. Must happen\n // BEFORE the spinner below starts: an interactive p.select cannot render\n // while a p.spinner is active.\n const claudeAgentModels = await promptClaudeAgentModels(target)\n const codexAgentModels = await promptCodexAgentModels(target)\n\n const spinner = p.spinner()\n spinner.start(`Migrating from ${config.provider} to ${target}...`)\n\n try {\n // Scaffold the new provider's files\n const targetMaterializer = getMaterializer(target)\n await targetMaterializer.build(config, cwd, { claudeAgentModels, codexAgentModels })\n\n spinner.stop(pc.green(`Migrated to ${target}`))\n p.log.warn(`Update agent-harness-kit.config.ts: set provider: '${target}'`)\n p.log.warn(`Then run: ahk build`)\n } catch (err) {\n spinner.stop(pc.red('Migration failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n","import { copyFileSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport {\n DEFAULT_MARKDOWN_PATH,\n DEFAULT_SQLITE_PATH,\n type FullExport,\n getRowCounts,\n isEmptyDatabase,\n openDB,\n readStorageStateFile,\n resolveGlobalStorageDir,\n resolveSqlitePathForScope,\n} from '@/core/db'\n\nimport type { DatabaseConfig, HarnessConfig } from '@/types'\n\nexport interface MigrateStorageOptions {\n force?: boolean\n dryRun?: boolean\n}\n\ntype DbType = DatabaseConfig['type']\n\nfunction log(msg: string): void {\n console.log(msg)\n}\n\n/** Aborts the current migration by throwing — callers (the CLI action\n * handler) are responsible for printing the message and exiting non-zero.\n * Throwing (rather than calling process.exit here) keeps this module\n * testable without killing the test process. */\nfunction fail(msg: string): never {\n throw new Error(msg)\n}\n\n/** The relative markdown-fallback path to use as the base for\n * `currentMdPathForScope()` below. Mirrors `defaultSqlitePathForConfig()` —\n * `LocalStorageConfig.markdownFallback.path` only exists (and only means\n * anything) when `config.storage.scope === 'local'`; for a config CURRENTLY\n * in scope='global' there's no field to read a custom path from, so this\n * always falls back to `DEFAULT_MARKDOWN_PATH` in that case. */\nfunction defaultMarkdownPathForConfig(config: HarnessConfig): string {\n return config.storage.scope === 'local' ? config.storage.markdownFallback.path : DEFAULT_MARKDOWN_PATH\n}\n\n/** Physical location of a project's harness `current.md`, following the same\n * scope convention `HarnessDB.regenerateCurrentMd()` uses. */\nfunction currentMdPathForScope(scope: 'local' | 'global', config: HarnessConfig, cwd: string, homeDir: string): string {\n return scope === 'global'\n ? join(resolveGlobalStorageDir(config, homeDir), 'current.md')\n : resolve(cwd, defaultMarkdownPathForConfig(config))\n}\n\n/** The relative sqlite path override to use as the base for\n * `resolveSqlitePathForScope()` calls in this file. `LocalStorageConfig.sqlitePath`\n * only exists (and only means anything) when `config.storage.scope ===\n * 'local'` — for a config CURRENTLY in scope='global', there is no field to\n * read a custom local filename from at all, so this always falls back to\n * `DEFAULT_SQLITE_PATH` in that case.\n *\n * Known UX tradeoff (accepted, see task #56 consultant advisory): a custom\n * local sqlite filename (`storage.sqlitePath`) does NOT survive a\n * global -> local round trip — migrating back to local always lands at\n * `DEFAULT_SQLITE_PATH` unless the user re-sets `storage.sqlitePath`\n * afterward. This is a deliberate consequence of making `sqlitePath`\n * local-only in the type system (see StorageConfig in src/types.ts) rather\n * than leaving it unenforceable across scopes. */\nfunction defaultSqlitePathForConfig(config: HarnessConfig): string {\n return config.storage.scope === 'local' && config.database.type === 'sqlite'\n ? (config.storage.sqlitePath ?? DEFAULT_SQLITE_PATH)\n : DEFAULT_SQLITE_PATH\n}\n\n/** Backs up the destination's current content (all 6 tables, via\n * exportJson()) to a local JSON file BEFORE any destructive `--force`\n * overwrite. Aborts the whole command (throws) if the backup can't be\n * written — fail-safe, per task #47 consultant advisory point 2. */\nasync function backupDestination(cwd: string, storageDir: string, data: FullExport): Promise<string> {\n const backupsDir = resolve(cwd, storageDir, 'backups')\n const path = join(backupsDir, `pre-migrate-${new Date().toISOString().replace(/[:.]/g, '-')}.json`)\n try {\n mkdirSync(backupsDir, { recursive: true })\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n', 'utf8')\n } catch (err) {\n throw new Error(\n `Could not write destination backup to ${path} (${err instanceof Error ? err.message : String(err)}). ` +\n `Aborting migration WITHOUT touching the destination — nothing was overwritten.`,\n )\n }\n return path\n}\n\n/** Copies a sqlite `.db` file (plus WAL/SHM sidecars if present) to a new\n * path, verifying the copy exists before returning. Does not delete the\n * original — caller decides when it's safe to remove it. */\nfunction copySqliteFile(srcPath: string, destPath: string): void {\n mkdirSync(dirname(destPath), { recursive: true })\n copyFileSync(srcPath, destPath)\n for (const suffix of ['-wal', '-shm']) {\n if (existsSync(`${srcPath}${suffix}`)) {\n copyFileSync(`${srcPath}${suffix}`, `${destPath}${suffix}`)\n }\n }\n if (!existsSync(destPath)) {\n throw new Error(`Copy verification failed: ${destPath} does not exist after copy.`)\n }\n}\n\nexport async function runMigrateStorage(\n cwd: string,\n opts: MigrateStorageOptions,\n homeDir: string = homedir(),\n): Promise<void> {\n const config = await loadConfig(cwd)\n const storageDir = config.storage.dir\n const state = readStorageStateFile(cwd, storageDir)\n\n // ── Case: storage-state.json is missing ──────────────────────────────────\n // NEVER treat this as \"destination empty, safe to migrate\". Probe the real\n // content at both sqlite candidate locations (local + global default\n // paths) before deciding anything. See task #47 consultant advisory pt.6.\n let realScope: 'local' | 'global'\n let realDbType: DbType\n\n if (!state) {\n const defaultSqlitePath = defaultSqlitePathForConfig(config)\n const localPath = resolveSqlitePathForScope('local', defaultSqlitePath, cwd, config, homeDir)\n const globalPath = resolveSqlitePathForScope('global', defaultSqlitePath, cwd, config, homeDir)\n\n const localCount = await probeTaskCount(localPath)\n const globalCount = await probeTaskCount(globalPath)\n\n if (localCount > 0 && globalCount > 0) {\n fail(\n `storage-state.json is missing and BOTH candidate locations have data — ` +\n `local (${localPath}): ${localCount} task(s); global (${globalPath}): ${globalCount} task(s). ` +\n `Refusing to guess which one is authoritative. Resolve manually (inspect both databases) ` +\n `or delete the one that should be discarded, then re-run this command.`,\n )\n }\n\n if (localCount === 0 && globalCount === 0) {\n // Nothing exists anywhere yet — nothing to migrate. Just record the\n // current (desired) state so future runs have a storage-state.json.\n const db = await openDB(config, cwd, homeDir)\n try {\n await db.writeStorageState(cwd)\n } finally {\n await db.close()\n }\n log(pc.dim('storage-state.json was missing; no data found at either candidate location. Nothing to migrate — state recorded.'))\n return\n }\n\n // Exactly one candidate has data — self-heal: treat it as the real\n // (source) location without requiring --force, since this isn't a\n // blind guess (only one plausible source exists).\n realScope = localCount > 0 ? 'local' : 'global'\n realDbType = 'sqlite'\n log(\n pc.yellow(\n `storage-state.json was missing. Detected real data at ${realScope} sqlite location ` +\n `(${realScope === 'local' ? localPath : globalPath}) — using it as the migration source.`,\n ),\n )\n } else {\n realScope = state.scope\n realDbType = state.dbType\n }\n\n const desiredScope = config.storage.scope\n const desiredDbType = config.database.type\n\n // ── Case 1: everything matches — nothing to migrate ──────────────────────\n if (realScope === desiredScope && realDbType === desiredDbType) {\n log(pc.green(`✓ Storage already matches config (scope=${desiredScope}, database=${desiredDbType}) — nothing to migrate.`))\n return\n }\n\n // ── Unsupported direction: source was a remote DB ─────────────────────────\n // storage-state.json intentionally never stores connection strings/creds,\n // so we cannot auto-reconnect to a previous remote database. Out of scope\n // for this command — fail safe rather than guess.\n if (realDbType !== 'sqlite') {\n fail(\n `Cannot auto-locate the previous ${realDbType} database — storage-state.json does not retain connection ` +\n `credentials for security. Manually run \"ahk export --json\" while still connected to the old database ` +\n `(with the old config), then adjust agent-harness-kit.config.ts and re-import. This direction is out of scope for \"ahk migrate storage\".`,\n )\n }\n\n // ── Case: scope changes but dbType stays sqlite → move files directly ────\n if (desiredDbType === 'sqlite' && realDbType === 'sqlite') {\n return migrateScopeOnly(cwd, config, homeDir, realScope, desiredScope, opts)\n }\n\n // ── Case: dbType changes (sqlite -> postgres/mysql, or vice versa is\n // unsupported above) → full export/import through a transaction ──────\n return migrateAcrossDbType(cwd, config, homeDir, realScope, opts)\n}\n\n/** Returns the number of rows in `tasks` at `dbPath`, or 0 if the file\n * doesn't exist. Never creates the file (existence is checked first) —\n * probing must not have side effects. */\nasync function probeTaskCount(dbPath: string): Promise<number> {\n if (!existsSync(dbPath)) return 0\n const { SQLiteDriver } = await import('@/core/drivers/sqlite')\n const driver = new SQLiteDriver(dbPath)\n try {\n await driver.ensureSchema()\n const counts = await getRowCounts(driver)\n return counts.tasks\n } finally {\n await driver.close()\n }\n}\n\n// ─── Case: local <-> global, same engine (sqlite) ──────────────────────────\n\nasync function migrateScopeOnly(\n cwd: string,\n config: HarnessConfig,\n homeDir: string,\n fromScope: 'local' | 'global',\n toScope: 'local' | 'global',\n opts: MigrateStorageOptions,\n): Promise<void> {\n const sqlitePath = defaultSqlitePathForConfig(config)\n const srcDb = resolveSqlitePathForScope(fromScope, sqlitePath, cwd, config, homeDir)\n const destDb = resolveSqlitePathForScope(toScope, sqlitePath, cwd, config, homeDir)\n const srcMd = currentMdPathForScope(fromScope, config, cwd, homeDir)\n const destMd = currentMdPathForScope(toScope, config, cwd, homeDir)\n\n if (!existsSync(srcDb)) {\n fail(`Source database not found at ${srcDb} (expected ${fromScope} scope) — nothing to move.`)\n }\n\n const destExists = existsSync(destDb)\n if (destExists) {\n const { SQLiteDriver } = await import('@/core/drivers/sqlite')\n const destDriver = new SQLiteDriver(destDb)\n let destEmpty: boolean\n try {\n await destDriver.ensureSchema()\n destEmpty = await isEmptyDatabase(destDriver)\n } finally {\n await destDriver.close()\n }\n if (!destEmpty && !opts.force) {\n fail(\n `Destination (${toScope}, ${destDb}) already has data. Re-run with --force to overwrite it ` +\n `(a backup of the destination will be written first).`,\n )\n }\n if (!destEmpty && opts.force) {\n // Back up destination content before overwriting.\n const { SQLiteDriver: Driver } = await import('@/core/drivers/sqlite')\n const backupDriver = new Driver(destDb)\n let data: FullExport\n try {\n await backupDriver.ensureSchema()\n const { HarnessDB } = await import('@/core/db')\n // `config` is passed unmodified (not re-scoped to `toScope`) — safe\n // because exportJson() only queries `backupDriver`'s tables and never\n // reads `this.config.storage` at all. Re-scoping here would also no\n // longer type-check cleanly against the StorageConfig discriminated\n // union (task #56) since `sqlitePath` only exists on the 'local'\n // branch.\n const tmpDb = new HarnessDB(backupDriver, config, homeDir)\n data = await tmpDb.exportJson()\n } finally {\n await backupDriver.close()\n }\n const backupPath = await backupDestination(cwd, config.storage.dir, data)\n log(pc.yellow(` Backed up existing destination data → ${backupPath}`))\n }\n }\n\n if (opts.dryRun) {\n log(pc.dim(`[dry-run] Would copy ${srcDb} → ${destDb} (scope ${fromScope} → ${toScope}), and move current.md.`))\n return\n }\n\n copySqliteFile(srcDb, destDb)\n log(pc.green(`✓ Copied database ${srcDb} → ${destDb}`))\n\n if (existsSync(srcMd)) {\n mkdirSync(dirname(destMd), { recursive: true })\n copyFileSync(srcMd, destMd)\n log(pc.green(`✓ Copied current.md ${srcMd} → ${destMd}`))\n }\n\n // Only remove the source AFTER the copy is verified in place.\n rmSync(srcDb, { force: true })\n rmSync(`${srcDb}-wal`, { force: true })\n rmSync(`${srcDb}-shm`, { force: true })\n if (existsSync(srcMd) && srcMd !== destMd) rmSync(srcMd, { force: true })\n\n // Write storage-state ONLY after the move is confirmed successful.\n const db = await openDB(config, cwd, homeDir)\n try {\n await db.writeStorageState(cwd)\n } finally {\n await db.close()\n }\n\n log(pc.green(`✓ Storage migrated: scope ${fromScope} → ${toScope}`))\n}\n\n// ─── Case: database engine changes (sqlite -> postgres/mysql) ─────────────\n\nasync function migrateAcrossDbType(\n cwd: string,\n config: HarnessConfig,\n homeDir: string,\n sourceScope: 'local' | 'global',\n opts: MigrateStorageOptions,\n): Promise<void> {\n const sqlitePath = defaultSqlitePathForConfig(config)\n const srcPath = resolveSqlitePathForScope(sourceScope, sqlitePath, cwd, config, homeDir)\n if (!existsSync(srcPath)) {\n fail(`Source sqlite database not found at ${srcPath} (expected ${sourceScope} scope) — nothing to migrate.`)\n }\n\n const { SQLiteDriver } = await import('@/core/drivers/sqlite')\n const srcDriver = new SQLiteDriver(srcPath)\n let sourceData: FullExport\n let sourceCounts: Awaited<ReturnType<typeof getRowCounts>>\n try {\n await srcDriver.ensureSchema()\n sourceCounts = await getRowCounts(srcDriver)\n const { HarnessDB } = await import('@/core/db')\n // `config` is passed unmodified (not re-scoped/re-typed to sqlite) — safe\n // because exportJson() only queries `srcDriver`'s tables and never reads\n // `this.config` at all. See the identical comment above in\n // migrateScopeOnly() for why re-scoping isn't attempted here anymore.\n const srcDb = new HarnessDB(srcDriver, config, homeDir)\n sourceData = await srcDb.exportJson()\n } finally {\n await srcDriver.close()\n }\n\n // Fail fast: connect to destination before touching anything else.\n let destDb\n try {\n destDb = await openDB(config, cwd, homeDir)\n } catch (err) {\n fail(`Could not connect to destination (${config.database.type}): ${err instanceof Error ? err.message : String(err)}. Verify database configuration.`)\n }\n\n try {\n const destCounts = await destDb.getRowCounts()\n const destEmpty = Object.values(destCounts).every((n) => n === 0)\n const sourceEmpty = Object.values(sourceCounts).every((n) => n === 0)\n\n if (!destEmpty) {\n if (!opts.force) {\n const bothHaveData = !sourceEmpty\n fail(\n bothHaveData\n ? `Both source (${sourceCounts.tasks} task(s)) and destination (${config.database.type}, ${destCounts.tasks} task(s)) ` +\n `have data that DIVERGE — this is not a first-time migration. Refusing to auto-merge. ` +\n `Review both manually, or re-run with --force to overwrite the destination (a JSON backup will be written first).`\n : `Destination (${config.database.type}) already has data (${destCounts.tasks} task(s)). ` +\n `Re-run with --force to overwrite it (a backup of the destination will be written first).`,\n )\n }\n }\n\n if (opts.dryRun) {\n log(\n pc.dim(\n `[dry-run] Would migrate ${sourceCounts.tasks} task(s) from sqlite (${sourceScope}, ${srcPath}) ` +\n `to ${config.database.type}${destEmpty ? '' : ' (destination has data — would back up first, then overwrite)'}.`,\n ),\n )\n return\n }\n\n let backupPath: string | null = null\n if (!destEmpty && opts.force) {\n const currentDestData = await destDb.exportJson()\n backupPath = await backupDestination(cwd, config.storage.dir, currentDestData)\n log(pc.yellow(` Backed up existing destination data → ${backupPath}`))\n }\n\n // Single transaction covers the entire import (and truncate, if any).\n // storage-state is written ONLY after this resolves without throwing.\n await destDb.importFullExport(sourceData, config.database.type, { truncateFirst: !destEmpty })\n\n await destDb.writeStorageState(cwd)\n\n log(\n pc.green(\n `✓ Migrated ${sourceData.tasks.length} task(s), ${sourceData.actions.length} action(s) ` +\n `from sqlite (${sourceScope}) → ${config.database.type}.`,\n ),\n )\n if (backupPath) log(pc.dim(` Destination backup: ${backupPath}`))\n log(pc.yellow(` Note: the original sqlite file at ${srcPath} was NOT deleted — remove it manually once you've verified the migration.`))\n } finally {\n await destDb.close()\n }\n}\n","import { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { claudeAgentFiles } from '@/core/materializer/claude-code'\nimport { writeAgentFiles } from '@/core/materializer/scaffold-utils'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\n\nimport type { HarnessConfig, Provider } from '@/types'\n\n/**\n * Resolves what `ahk models` should do, WITHOUT touching the interactive\n * prompt layer. Kept separate from `runModels` so the no-config-found and\n * non-claude-code no-op branches are testable directly — mirrors the\n * separation `getDoctorStatus`/`runDoctor` already have in doctor.ts. No test\n * in this repo mocks `@clack/prompts`; everything downstream of a resolved\n * `ModelsContext` is exercised at the pure-function level instead (see\n * `claudeAgentFiles` / `writeAgentFiles` tests).\n */\nexport type ModelsContext =\n | { ok: true; config: HarnessConfig }\n | { ok: false; reason: 'no-config' }\n | { ok: false; reason: 'not-claude-code'; provider: Provider }\n\nexport async function resolveModelsContext(cwd: string): Promise<ModelsContext> {\n let config: HarnessConfig\n try {\n config = await loadConfig(cwd)\n } catch {\n return { ok: false, reason: 'no-config' }\n }\n\n if (config.provider !== 'claude-code') {\n return { ok: false, reason: 'not-claude-code', provider: config.provider }\n }\n\n return { ok: true, config }\n}\n\n/**\n * `ahk models` — Claude Code only. Re-runs the same per-role model prompt\n * `ahk init` uses and regenerates ONLY the 5 `.claude/agents/*.md` files with\n * the freshly-collected models, backing up the previous content first (same\n * `writeAgentFiles(..., { force: true, backupRoot })` call shape `ahk build\n * --force` already uses). Scope is strictly the 5 agent files' model line —\n * AGENTS.md, CLAUDE.md, .mcp.json, .claude/settings.json, config, docs path,\n * storage scope, and the task adapter are never touched.\n */\nexport async function runModels(cwd: string): Promise<void> {\n const ctx = await resolveModelsContext(cwd)\n\n if (!ctx.ok) {\n if (ctx.reason === 'no-config') {\n // Mirrors runDoctor's no-config-found handling in doctor.ts.\n console.log('')\n console.log(` ${pc.cyan('config'.padEnd(16))}${pc.yellow('[!]')} no agent-harness-kit.config found`)\n console.log(` ${''.padEnd(16)} ${pc.dim('run: ahk init')}`)\n console.log('')\n return\n }\n\n console.log(\n pc.dim(\n `ahk models only applies to Claude Code projects (this project uses '${ctx.provider}') — nothing to do.`\n )\n )\n return\n }\n\n const { config } = ctx\n const claudeAgentModels = await promptClaudeAgentModels(config.provider)\n\n const agents = writeAgentFiles(cwd, claudeAgentFiles(config, claudeAgentModels), {\n force: true,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n console.log('')\n if (agents.overwritten.length > 0) {\n console.log(pc.green(`✓ Regenerated ${agents.overwritten.length} agent file(s) with updated models:`))\n for (const file of agents.overwritten) console.log(pc.green(` ✓ ${file}`))\n if (agents.backupDir) {\n console.log(pc.dim(` Previous content backed up → ${agents.backupDir}`))\n }\n }\n if (agents.created.length > 0) {\n console.log(pc.green(`✓ Created ${agents.created.length} missing agent file(s):`))\n for (const file of agents.created) console.log(pc.green(` ✓ ${file}`))\n }\n console.log('')\n}\n","import { existsSync, readdirSync, rmSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { resolveSqlitePath } from '@/core/db'\n\nimport type { Provider } from '@/types'\n\ninterface ResetOptions {\n force?: boolean\n provider?: Provider\n}\n\n// Map of agent role names to their generated filenames (extension varies by provider)\nconst AGENT_MD_FILES = ['lead', 'explorer', 'consultant', 'builder', 'reviewer']\n\nconst PROVIDER_AGENT_DIRS: Record<Provider, string> = {\n 'claude-code': '.claude/agents',\n opencode: '.opencode/agents',\n 'codex-cli': '.codex/agents',\n 'grok-cli': '.grok/agents',\n}\n\n// codex-cli agent files are TOML (see codex-cli.ts materializer); every other\n// provider generates markdown + YAML frontmatter.\nconst PROVIDER_AGENT_EXT: Record<Provider, string> = {\n 'claude-code': '.md',\n opencode: '.md',\n 'codex-cli': '.toml',\n 'grok-cli': '.md',\n}\n\nasync function resetAgentMds(cwd: string, provider: Provider): Promise<void> {\n const agentDir = PROVIDER_AGENT_DIRS[provider]\n const agentDirPath = resolve(cwd, agentDir)\n const agentExt = PROVIDER_AGENT_EXT[provider]\n\n if (!existsSync(agentDirPath)) {\n console.log(pc.yellow(` Skipping agent files — directory not found: ${agentDirPath}`))\n return\n }\n\n // Collect existing agent files for this provider's extension\n const existingFiles: string[] = []\n try {\n const files = readdirSync(agentDirPath)\n for (const f of files) {\n if (f.endsWith(agentExt) && AGENT_MD_FILES.includes(f.replace(agentExt, ''))) {\n existingFiles.push(f)\n }\n }\n } catch {\n // Directory doesn't exist or can't be read\n console.log(pc.yellow(` Skipping agent files — ${agentDirPath} is not readable`))\n return\n }\n\n if (existingFiles.length === 0) {\n console.log(pc.yellow(` No agent MD files found in ${agentDir}/`))\n return\n }\n\n // Confirm removal of each agent MD file\n for (const file of existingFiles) {\n const confirm = await p.confirm({\n message: `Remove ${file}?`,\n initialValue: true,\n })\n if (p.isCancel(confirm)) {\n console.log(pc.red(' Cancelled by user.'))\n return\n }\n if (confirm) {\n try {\n const filePath = join(agentDirPath, file)\n rmSync(filePath, { force: true })\n console.log(pc.green(` Removed ${file}`))\n } catch {\n console.error(pc.red(` Failed to remove ${file}`))\n }\n } else {\n console.log(pc.cyan(` Skipped ${file}`))\n }\n }\n}\n\nexport async function runReset(cwd: string, opts: ResetOptions): Promise<void> {\n let config\n try {\n config = await loadConfig(cwd)\n } catch {\n console.error(pc.red('✗ No agent-harness-kit.config found. Run: ahk init'))\n process.exit(1)\n }\n\n const storageDir = config.storage.dir || '.harness'\n const dbPath = config.database.type === 'sqlite' ? resolveSqlitePath(config, cwd, homedir()) : null\n const featureListPath = resolve(cwd, storageDir, 'feature_list.json')\n\n let resetDb = false\n let resetFeatureList = false\n let resetAgentMdsFlag = false\n\n // ─── Determine what to reset ────────────────────────────────────────────────\n\n // Reset DB? (SQLite only — remote DBs are not reset by this command)\n if (dbPath && existsSync(dbPath)) {\n if (opts.force) {\n resetDb = true\n } else {\n if (config.database.type !== 'sqlite') {\n console.log(pc.yellow(` Skipping DB reset — database type \"${config.database.type}\" is not managed by this command.`))\n resetDb = false\n } else {\n const confirm = await p.confirm({\n message: `Delete database (${dbPath})?`,\n initialValue: true,\n })\n if (p.isCancel(confirm)) {\n console.log(pc.red(' Cancelled by user.'))\n return\n }\n resetDb = confirm\n }\n }\n } else if (!dbPath) {\n console.log(pc.dim(` Skipping DB reset — remote ${config.database.type} database is not managed by this command.`))\n }\n\n // Reset feature_list.json?\n if (existsSync(featureListPath)) {\n if (opts.force) {\n resetFeatureList = true\n } else {\n const confirm = await p.confirm({\n message: `Delete feature list (${storageDir}/feature_list.json)?`,\n initialValue: true,\n })\n if (p.isCancel(confirm)) {\n console.log(pc.red(' Cancelled by user.'))\n return\n }\n resetFeatureList = confirm\n }\n }\n\n // Reset agent MD files?\n if (opts.provider) {\n resetAgentMdsFlag = true\n }\n\n // ─── Perform resets ─────────────────────────────────────────────────\n if (resetDb && dbPath) {\n try {\n rmSync(dbPath, { force: true })\n rmSync(`${dbPath}-wal`, { force: true }) // also remove WAL file if it exists (only for SQLite)\n rmSync(`${dbPath}-shm`, { force: true }) // also remove SHM file if it exists (only for SQLite)\n console.log(pc.green(` ✓ Removed ${dbPath}`))\n } catch {\n console.error(pc.red(` ✗ Failed to remove ${dbPath}`))\n }\n }\n\n if (resetFeatureList) {\n try {\n rmSync(featureListPath, { force: true })\n console.log(pc.green(` ✓ Removed ${storageDir}/feature_list.json`))\n // = true\n } catch {\n console.error(pc.red(` ✗ Failed to remove ${featureListPath}`))\n }\n }\n\n if (resetAgentMdsFlag) {\n console.log('')\n await resetAgentMds(cwd, opts.provider || 'claude-code')\n }\n\n if (!resetDb && !resetFeatureList && !resetAgentMdsFlag) {\n console.log(pc.yellow(' Nothing to reset (all items missing or skipped).'))\n return\n }\n\n // ─── Summary ────────────────────────────────────────────────────────\n console.log('')\n console.log(pc.green('✓ Reset complete. Run \"ahk init\" to scaffold a fresh harness.'))\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { Server } from '@modelcontextprotocol/sdk/server'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js'\n\nimport { type HarnessDB, openDB } from './db'\nimport { getDoctorStatus } from './doctor'\nimport { slugify } from './materializer/scaffold-utils'\nimport { checkPermissionsSync } from './permissions-check'\n\nimport type { ActionFileRow, AgentName, HarnessConfig, TaskStatus } from '@/types'\n\nconst VERSION = '0.1.0'\n\n// ─── Tool schemas ─────────────────────────────────────────────────────────────\n\nconst TOOLS = [\n {\n name: 'actions.start',\n description: 'Start a new action for a task. Returns an actionId.',\n inputSchema: {\n type: 'object',\n properties: {\n taskId: { type: 'number', description: 'The task ID from tasks.get' },\n agent: {\n type: 'string',\n description: 'Agent name: lead | explorer | builder | reviewer | custom:<name>',\n },\n },\n required: ['taskId', 'agent'],\n },\n },\n {\n name: 'actions.write',\n description:\n 'Record a section in an action. Standard sections: result, tools_used, blockers, next_steps.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId returned by actions.start' },\n sectionType: {\n type: 'string',\n description:\n 'Section name: result | tools_used | blockers | next_steps | <custom>. Do NOT use files_modified to track files — it is stored as plain text only. Use actions.record_file instead.',\n },\n content: {\n type: 'string',\n description:\n \"Content for this section. No length limit; avoid padding — it costs shared context for other agents.\",\n },\n },\n required: ['actionId', 'sectionType', 'content'],\n },\n },\n {\n name: 'actions.complete',\n description: 'Close an action with a one-line summary.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId of the action to close' },\n summary: { type: 'string', description: 'One-line summary of what was done' },\n },\n required: ['actionId', 'summary'],\n },\n },\n {\n name: 'actions.get',\n description: 'Get the full action history for a task (all agents, all sections).',\n inputSchema: {\n type: 'object',\n properties: {\n taskId: { type: 'number', description: 'Task ID' },\n },\n required: ['taskId'],\n },\n },\n {\n name: 'tasks.get',\n description: 'List tasks, optionally filtered by status. Excludes archived tasks by default.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'done', 'blocked'],\n description: 'Filter by status (omit for all tasks)',\n },\n includeArchived: {\n type: 'boolean',\n description: 'If true, include archived tasks in results',\n },\n },\n },\n },\n {\n name: 'tasks.claim',\n description:\n 'Atomically claim a pending task. Returns task_already_claimed if another agent got it first.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to claim' },\n agent: { type: 'string', description: 'Your agent name' },\n },\n required: ['id', 'agent'],\n },\n },\n {\n name: 'tasks.update',\n description: 'Change the status of a task.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID' },\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'done', 'blocked'],\n },\n },\n required: ['id', 'status'],\n },\n },\n {\n name: 'docs.search',\n description: 'Search the project docs folder for content matching a query.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Search terms' },\n },\n required: ['query'],\n },\n },\n {\n name: 'actions.record_file',\n description:\n 'Record one or more files touched during an action, atomically (all-or-nothing). This is the only way to populate the files-touched count shown in the dashboard. Batch every file from a step of work into a single call — a single-element array is correct when only one file was touched.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId returned by actions.start' },\n files: {\n type: 'array',\n minItems: 1,\n description: 'Files touched, recorded atomically in one transaction.',\n items: {\n type: 'object',\n properties: {\n filePath: { type: 'string', description: 'Absolute or repo-relative path of the file' },\n operation: {\n type: 'string',\n enum: ['read', 'created', 'modified', 'deleted'],\n description: 'What was done to the file',\n },\n notes: { type: 'string', description: 'Optional short note about the change' },\n },\n required: ['filePath', 'operation'],\n },\n },\n },\n required: ['actionId', 'files'],\n },\n },\n {\n name: 'tasks.acceptance.update',\n description: 'Mark an acceptance criterion as met. Use the criterion id from tasks.get.',\n inputSchema: {\n type: 'object',\n properties: {\n criterionId: {\n type: 'number',\n description: 'The id of the acceptance criterion to mark as met',\n },\n },\n required: ['criterionId'],\n },\n },\n {\n name: 'tasks.acceptance.get',\n description:\n 'Given a taskId, returns all acceptance criteria for that task with their id, task_id, criterion text, and met status. Use the returned id values to call tasks.acceptance_update(criterionId).',\n inputSchema: {\n type: 'object',\n properties: {\n taskId: { type: 'number', description: 'Task ID' },\n },\n required: ['taskId'],\n },\n },\n {\n name: 'tasks.add',\n description:\n 'Create a new task in the harness. Use this when the user describes work in natural language. Infer slug, title, description, and acceptance criteria from the conversation. Ask for missing critical info before calling.',\n inputSchema: {\n type: 'object',\n properties: {\n title: { type: 'string', description: 'Short human-readable title for the task' },\n slug: {\n type: 'string',\n description:\n 'URL-safe identifier (lowercase, hyphens). Auto-derived from title if omitted.',\n },\n description: {\n type: 'string',\n description:\n 'Longer description of the task goal. No length limit; avoid padding — it costs shared context for other agents.',\n },\n acceptance: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'List of acceptance criteria (plain sentences). No length limit; avoid padding — it costs shared context for other agents.',\n },\n },\n required: ['title'],\n },\n },\n {\n name: 'actions.record_tool',\n description:\n 'Record one or more tool calls made during an action, atomically (all-or-nothing). This is the only way to populate the Tools dashboard. Batch every tool call from a step of work into a single call — a single-element array is correct when only one call was made.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId returned by actions.start' },\n calls: {\n type: 'array',\n minItems: 1,\n description: 'Tool calls made, recorded atomically in one transaction.',\n items: {\n type: 'object',\n properties: {\n toolName: {\n type: 'string',\n description: 'Name of the tool that was called (e.g. Read, Bash, Edit)',\n },\n argsJson: {\n type: 'string',\n description: 'Optional JSON string of the arguments passed to the tool',\n },\n resultSummary: {\n type: 'string',\n description: 'Optional short summary of the tool result',\n },\n },\n required: ['toolName'],\n },\n },\n },\n required: ['actionId', 'calls'],\n },\n },\n {\n name: 'tasks.edit',\n description:\n 'Edit an existing task (title, description, acceptance criteria). Omitted fields keep their current values.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to edit' },\n title: { type: 'string', description: 'New title (optional)' },\n description: { type: 'string', description: 'New description (optional, null to clear)' },\n acceptance: {\n type: 'array',\n items: { type: 'string' },\n description: 'New acceptance criteria list (optional, null to keep existing)',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'tasks.archive',\n description:\n 'Archive a task. Archived tasks are hidden from default views (CLI and dashboard).',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to archive' },\n },\n required: ['id'],\n },\n },\n {\n name: 'tasks.unarchive',\n description: 'Unarchive a previously archived task, restoring it to default views.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to unarchive' },\n },\n required: ['id'],\n },\n },\n {\n name: 'permissions.check',\n description:\n 'Check that a .claude/agents/*.md definition file exists for every role. Returns { in_sync, agents } where each agent is { ok } or { ok: false, reason: \"missing_file\" }. Agent file CONTENTS are never inspected — they are meant to be customised freely — so this never reports drift, only absence. Run `ahk build` to restore a missing file.',\n inputSchema: { type: 'object', properties: {}, required: [] },\n },\n {\n name: 'deps.snapshot',\n description: 'Snapshot current package.json dependencies to .harness/deps-lock.json',\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\n },\n {\n name: 'deps.check',\n description: 'Compare current package.json against .harness/deps-lock.json and report changes',\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\n },\n {\n name: 'ahk.doctor',\n description:\n 'Check lib version, agent files, and harness skills sync status. Returns structured JSON.',\n inputSchema: { type: 'object', properties: {}, required: [] },\n },\n] as const\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\nexport async function startMcpServer(config: HarnessConfig, cwd: string): Promise<void> {\n const db = await openDB(config, cwd)\n const docsPath = resolve(cwd, config.project.docsPath)\n\n const server = new Server(\n { name: 'agent-harness-kit', version: VERSION },\n { capabilities: { tools: {} } }\n )\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }))\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params\n const a = (args ?? {}) as Record<string, unknown>\n\n try {\n const result = await dispatch(name, a, db, docsPath, cwd, config)\n return result\n } catch (err) {\n return ok(`Error: ${err instanceof Error ? err.message : String(err)}`, true)\n }\n })\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n\n// ─── Dispatch ─────────────────────────────────────────────────────────────────\n\nasync function dispatch(\n name: string,\n args: Record<string, unknown>,\n db: HarnessDB,\n docsPath: string,\n cwd: string,\n config: HarnessConfig\n): Promise<CallToolResult> {\n switch (name) {\n case 'actions.start': {\n const taskId = num(args, 'taskId')\n const agent = str(args, 'agent') as AgentName\n const action = await db.startAction(taskId, agent)\n return ok(JSON.stringify({ actionId: action.id }))\n }\n\n case 'actions.write': {\n const actionId = num(args, 'actionId')\n const sectionType = str(args, 'sectionType')\n const content = str(args, 'content')\n await db.writeSection(actionId, sectionType, content)\n return ok(JSON.stringify({ recorded: true }))\n }\n\n case 'actions.complete': {\n const actionId = num(args, 'actionId')\n const summary = str(args, 'summary')\n const action = await db.completeAction(actionId, summary)\n return ok(JSON.stringify({ status: action.status, completedAt: action.completed_at }))\n }\n\n case 'actions.get': {\n const taskId = num(args, 'taskId')\n const actions = await db.getActionsForTask(taskId)\n const full = await Promise.all(\n actions.map(async (a) => {\n const sections = await db.getActionSections(a.id)\n return {\n id: a.id,\n agent: a.agent,\n status: a.status,\n created_at: a.created_at,\n completed_at: a.completed_at,\n summary: a.summary,\n sections: sections.map((s) => ({\n id: s.id,\n section_type: s.section_type,\n content: s.content,\n created_at: s.created_at,\n })),\n }\n })\n )\n return ok(JSON.stringify(full))\n }\n\n case 'tasks.get': {\n const status = args['status'] as string | undefined\n const includeArchived = args['includeArchived'] as boolean | undefined\n const tasks = status\n ? await db.getTasks(status as TaskStatus, includeArchived ?? false)\n : await db.getTasks(undefined, includeArchived ?? false)\n return ok(JSON.stringify(tasks))\n }\n\n case 'tasks.claim': {\n const id = num(args, 'id')\n const agent = str(args, 'agent')\n const task = await db.claimTask(id, agent)\n if (!task) {\n return ok(JSON.stringify({ error: 'task_already_claimed', taskId: id }))\n }\n return ok(JSON.stringify(task))\n }\n\n case 'tasks.add': {\n const title = str(args, 'title')\n const slug = (args['slug'] as string | undefined) ?? slugify(title)\n const description = args['description'] as string | undefined\n const acceptance = args['acceptance'] as string[] | undefined\n const task = await db.addTask({ slug, title, description, acceptance })\n return ok(JSON.stringify(task))\n }\n\n case 'tasks.update': {\n const id = num(args, 'id')\n const status = str(args, 'status') as TaskStatus\n if (status === 'done') {\n await db.closeOrphanedActions(id)\n }\n const task = await db.updateTaskStatus(id, status)\n return ok(JSON.stringify(task))\n }\n\n case 'docs.search': {\n const query = str(args, 'query')\n const results = searchDocs(docsPath, query)\n return ok(JSON.stringify(results))\n }\n\n case 'actions.record_file': {\n const actionId = num(args, 'actionId')\n const files = nonEmptyArray(args, 'files').map((f) => ({\n filePath: str(f, 'filePath'),\n operation: str(f, 'operation') as ActionFileRow['operation'],\n notes: f['notes'] as string | undefined,\n }))\n const recorded = await db.recordFiles(actionId, files)\n return ok(JSON.stringify({ recorded }))\n }\n\n case 'tasks.acceptance.update': {\n const criterionId = num(args, 'criterionId')\n await db.markAcceptanceMet(criterionId)\n return ok(JSON.stringify({ criterionId, met: true }))\n }\n\n case 'tasks.acceptance.get': {\n const taskId = num(args, 'taskId')\n const criteria = await db.getTaskAcceptance(taskId)\n return ok(JSON.stringify(criteria))\n }\n\n case 'actions.record_tool': {\n const actionId = num(args, 'actionId')\n const calls = nonEmptyArray(args, 'calls').map((c) => ({\n toolName: str(c, 'toolName'),\n argsJson: c['argsJson'] as string | undefined,\n resultSummary: c['resultSummary'] as string | undefined,\n }))\n const recorded = await db.recordTools(actionId, calls)\n return ok(JSON.stringify({ recorded }))\n }\n\n case 'tasks.edit': {\n const id = num(args, 'id')\n const title = args['title'] as string | undefined\n const description = args['description'] as string | null | undefined\n const acceptance = args['acceptance'] as string[] | null | undefined\n\n const task = await db.getTaskById(id)\n if (!task) return ok(JSON.stringify({ error: 'Task not found', taskId: id }), true)\n\n await db.updateTask(id, {\n title,\n description: description !== undefined ? description : undefined,\n })\n if (acceptance !== undefined && acceptance !== null) {\n await db.updateTaskAcceptance(id, acceptance)\n }\n const updated = await db.getTaskById(id)\n return ok(JSON.stringify(updated))\n }\n\n case 'tasks.archive': {\n const id = num(args, 'id')\n const task = await db.archiveTask(id)\n return ok(JSON.stringify(task))\n }\n\n case 'tasks.unarchive': {\n const id = num(args, 'id')\n const task = await db.unarchiveTask(id)\n return ok(JSON.stringify(task))\n }\n\n case 'permissions.check': {\n const result = checkPermissionsSync(cwd, config)\n return ok(JSON.stringify(result))\n }\n\n case 'deps.snapshot': {\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) {\n return ok('package.json not found in project root', true)\n }\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n const snapshot = {\n capturedAt: new Date().toISOString(),\n dependencies: pkg.dependencies ?? {},\n devDependencies: pkg.devDependencies ?? {},\n }\n const harnessDir = join(cwd, '.harness')\n mkdirSync(harnessDir, { recursive: true })\n writeFileSync(join(harnessDir, 'deps-lock.json'), JSON.stringify(snapshot, null, 2), 'utf8')\n return ok(\n JSON.stringify({\n message: 'Snapshot saved to .harness/deps-lock.json',\n capturedAt: snapshot.capturedAt,\n })\n )\n }\n\n case 'deps.check': {\n const pkgPath = join(cwd, 'package.json')\n const lockPath = join(cwd, '.harness', 'deps-lock.json')\n if (!existsSync(pkgPath)) {\n return ok('package.json not found in project root', true)\n }\n if (!existsSync(lockPath)) {\n return ok(\n JSON.stringify({\n status: 'no-snapshot',\n message: 'No deps-lock.json found. Run deps.snapshot first to establish a baseline.',\n })\n )\n }\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n const lock = JSON.parse(readFileSync(lockPath, 'utf8')) as {\n capturedAt: string\n dependencies: Record<string, string>\n devDependencies: Record<string, string>\n }\n const current = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n const previous = { ...(lock.dependencies ?? {}), ...(lock.devDependencies ?? {}) }\n\n const added: string[] = []\n const removed: string[] = []\n const majorBumps: Array<{ name: string; from: string; to: string }> = []\n\n for (const [name, version] of Object.entries(current)) {\n if (!(name in previous)) {\n added.push(`${name}@${version}`)\n } else {\n const prevMajor = parseInt(\n previous[name].replace(/^[\\^~>=v]/, '').split('.')[0] ?? '0',\n 10\n )\n const curMajor = parseInt(version.replace(/^[\\^~>=v]/, '').split('.')[0] ?? '0', 10)\n if (!isNaN(prevMajor) && !isNaN(curMajor) && curMajor > prevMajor) {\n majorBumps.push({ name, from: previous[name], to: version })\n }\n }\n }\n for (const depName of Object.keys(previous)) {\n if (!(depName in current)) {\n removed.push(depName)\n }\n }\n\n const significant = added.length > 0 || removed.length > 0 || majorBumps.length > 0\n const advisory = significant\n ? 'Significant dependency changes detected. Consider running `pnpx autoskills` (or `npx autoskills` if pnpm is unavailable) to refresh agent skills. Clearing stale skills before re-running is recommended.'\n : 'No significant dependency changes detected.'\n\n return ok(\n JSON.stringify({\n significant,\n added,\n removed,\n majorBumps,\n advisory,\n snapshotDate: lock.capturedAt,\n })\n )\n }\n\n case 'ahk.doctor': {\n const status = await getDoctorStatus(cwd)\n const result = {\n lib: { current: status.lib.current, latest: status.lib.latest, outdated: status.lib.outdated },\n // Agents are existence-checked only — there is no `outdated` bucket.\n // Hand-edited agent definitions are supported and must not be flagged.\n agents: {\n missing: status.agents.filter((a) => a.status === 'missing').map((a) => a.name),\n ok: status.agents.filter((a) => a.status === 'ok').map((a) => a.name),\n },\n skills: {\n missing: status.skills.filter((s) => s.status === 'missing').map((s) => s.name),\n outdated: status.skills.filter((s) => s.status === 'outdated').map((s) => s.name),\n ok: status.skills.filter((s) => s.status === 'ok').map((s) => s.name),\n },\n }\n return ok(JSON.stringify(result))\n }\n\n default:\n return ok(`Unknown tool: ${name}`, true)\n }\n}\n\n// ─── docs.search implementation ───────────────────────────────────────────────\n\ninterface DocSnippet {\n file: string\n line: number\n text: string\n}\n\nfunction searchDocs(docsPath: string, query: string, maxResults = 10): DocSnippet[] {\n const terms = query.toLowerCase().split(/\\s+/).filter(Boolean)\n const results: DocSnippet[] = []\n\n try {\n const files = collectMarkdownFiles(docsPath)\n for (const file of files) {\n if (results.length >= maxResults) break\n try {\n const content = readFileSync(file, 'utf8')\n const lines = content.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const lower = lines[i].toLowerCase()\n if (terms.every((t) => lower.includes(t))) {\n results.push({\n file: file.replace(docsPath + '/', ''),\n line: i + 1,\n text: lines[i].trim(),\n })\n if (results.length >= maxResults) break\n }\n }\n } catch {\n // skip unreadable files\n }\n }\n } catch {\n return [{ file: '', line: 0, text: `docs path not found: ${docsPath}` }]\n }\n\n return results\n}\n\nfunction collectMarkdownFiles(dir: string): string[] {\n const files: string[] = []\n try {\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry)\n const stat = statSync(full)\n if (stat.isDirectory()) {\n files.push(...collectMarkdownFiles(full))\n } else if (entry.endsWith('.md') || entry.endsWith('.txt')) {\n files.push(full)\n }\n }\n } catch {\n // directory may not exist yet\n }\n return files\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction ok(text: string, isError = false): CallToolResult {\n return { content: [{ type: 'text' as const, text }], isError }\n}\n\nfunction str(args: Record<string, unknown>, key: string): string {\n const v = args[key]\n if (typeof v !== 'string') throw new Error(`${key} must be a string`)\n return v\n}\n\nfunction num(args: Record<string, unknown>, key: string): number {\n const v = args[key]\n if (typeof v !== 'number') throw new Error(`${key} must be a number`)\n return v\n}\n\n/** Validates that `args[key]` is a non-empty array of plain objects, as\n * required by the batch-only shapes of actions.record_file/record_tool\n * (task #74) — the single-entry top-level shape is no longer accepted, so\n * every entry must be pulled from this array via str()/num() on each item. */\nfunction nonEmptyArray(args: Record<string, unknown>, key: string): Record<string, unknown>[] {\n const v = args[key]\n if (!Array.isArray(v) || v.length === 0) {\n throw new Error(`${key} must be a non-empty array`)\n }\n for (const item of v) {\n if (typeof item !== 'object' || item === null) {\n throw new Error(`${key} entries must be objects`)\n }\n }\n return v as Record<string, unknown>[]\n}\n","import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { HarnessConfig } from '@/types'\n\nexport type AgentName = 'lead' | 'explorer' | 'consultant' | 'builder' | 'reviewer'\n\nexport interface AgentSyncResult {\n ok: boolean\n /** Only reason an agent can be out of sync now: its definition file is absent. */\n reason?: 'missing_file'\n}\n\nexport interface SyncCheckResult {\n in_sync: boolean\n agents?: Record<AgentName, AgentSyncResult>\n}\n\nconst AGENTS: AgentName[] = ['lead', 'explorer', 'consultant', 'builder', 'reviewer']\n\n/**\n * Verifies that each role's agent definition file exists.\n *\n * This used to parse the `tools:` frontmatter block and diff it against a\n * canonical list of `mcp__agent-harness-kit__*` tools. That premise no longer\n * holds: agent files intentionally omit `tools` so the agent inherits the full\n * tool set (including every MCP tool) from the session, and restrictions are\n * expressed as a `disallowedTools` denylist instead. With no allowlist in the\n * file, there is nothing to diff — every agent would have reported as missing\n * all of its tools.\n *\n * Agent file contents are user-customisable and are never inspected here.\n */\nexport function checkPermissionsSync(cwd: string, config: HarnessConfig): SyncCheckResult {\n if (config.provider !== 'claude-code') {\n return { in_sync: true }\n }\n\n const agents = {} as Record<AgentName, AgentSyncResult>\n let in_sync = true\n\n for (const agent of AGENTS) {\n const filePath = join(cwd, '.claude', 'agents', `${agent}.md`)\n const exists = existsSync(filePath)\n if (!exists) in_sync = false\n agents[agent] = exists ? { ok: true } : { ok: false, reason: 'missing_file' }\n }\n\n return { in_sync, agents }\n}\n","import { loadConfig } from '@/core/config'\nimport { startMcpServer } from '@/core/mcp-server'\nimport { checkPermissionsSync } from '@/core/permissions-check'\n\ninterface ServeOptions {\n port?: number\n}\n\nexport async function runServe(cwd: string, opts: ServeOptions): Promise<void> {\n const config = await loadConfig(cwd)\n\n if (opts.port) {\n config.tools.mcp.port = opts.port\n }\n\n // MCP server runs on stdio — do not write to stdout after this point.\n // Stderr is used for diagnostics.\n process.stderr.write(`[agent-harness-kit] MCP server starting (stdio)\\n`)\n\n const syncResult = checkPermissionsSync(cwd, config)\n if (!syncResult.in_sync && syncResult.agents) {\n const affected = Object.entries(syncResult.agents)\n .filter(([, r]) => !r.ok)\n .map(([name]) => name)\n .join(', ')\n process.stderr.write(`[agent-harness-kit] Agent definition files missing: ${affected}. Run: ahk build\\n`)\n }\n\n await startMcpServer(config, cwd)\n}\n","import Table from 'cli-table3'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\ninterface StatusOptions {\n json?: boolean\n}\n\nconst STATUS_COLOR: Record<string, (s: string) => string> = {\n pending: (s) => pc.dim(s),\n in_progress: (s) => pc.cyan(s),\n done: (s) => pc.green(s),\n blocked: (s) => pc.red(s),\n}\n\nexport async function runStatus(cwd: string, opts: StatusOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n const tasks = await db.getTasks()\n const summary = await db.getStatusSummary()\n\n if (opts.json) {\n const actions = await Promise.all(\n tasks.map(async (t) => ({\n ...t,\n actions: await db.getActionsForTask(t.id),\n acceptance: await db.getTaskAcceptance(t.id),\n })),\n )\n const archivedCount = (await db.getArchivedTasks()).length\n console.log(JSON.stringify({ tasks: actions, summary, archivedCount }, null, 2))\n return\n }\n\n if (tasks.length === 0) {\n console.log(pc.dim('No tasks yet. Run: ahk task add'))\n return\n }\n\n const table = new Table({\n head: ['ID', 'Slug', 'Title', 'Status', 'Assigned', 'Started'].map((h) => pc.bold(h)),\n style: { head: [], border: [] },\n })\n\n for (const t of tasks) {\n const colorFn = STATUS_COLOR[t.status] ?? ((s: string) => s)\n table.push([\n String(t.id),\n t.slug,\n t.title.slice(0, 40),\n colorFn(t.status),\n t.assigned_to ?? '—',\n t.started_at ? t.started_at.slice(0, 10) : '—',\n ])\n }\n\n console.log(table.toString())\n\n // Active actions\n const inProgress = tasks.filter((t) => t.status === 'in_progress')\n if (inProgress.length > 0) {\n console.log('')\n console.log(pc.bold('Active actions:'))\n for (const t of inProgress) {\n const actions = await db.getActionsForTask(t.id)\n const active = actions.filter((a) => a.status === 'in_progress')\n for (const a of active) {\n console.log(` ${pc.cyan(a.agent.padEnd(10))} → task #${t.id} ${t.slug}`)\n }\n }\n }\n\n // Summary line\n console.log('')\n const parts = summary.map((s) => {\n const fn = STATUS_COLOR[s.status] ?? ((x: string) => x)\n return `${fn(s.status)}: ${s.total}`\n })\n console.log(pc.dim('Tasks — ') + parts.join(pc.dim(' | ')))\n\n const archivedTasks = await db.getArchivedTasks()\n if (archivedTasks.length > 0) {\n console.log(pc.dim(`${archivedTasks.length} archived (use \\`ahk task list --archived\\` to view)`))\n }\n } finally {\n await db.close()\n }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\nimport type { TaskSeed } from '@/types'\n\ninterface SyncOptions {\n dryRun?: boolean\n direction?: 'in' | 'out' | 'both'\n}\n\nexport async function runSync(cwd: string, opts: SyncOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const direction = opts.direction ?? 'both'\n const featureListPath = resolve(join(cwd, config.storage.dir, 'feature_list.json'))\n\n const db = await openDB(config, cwd)\n\n try {\n if (direction === 'in' || direction === 'both') {\n await syncIn(featureListPath, db, opts.dryRun ?? false)\n }\n\n if (direction === 'out' || direction === 'both') {\n await syncOut(db, cwd, opts.dryRun ?? false)\n }\n } finally {\n await db.close()\n }\n}\n\nasync function syncIn(\n featureListPath: string,\n db: Awaited<ReturnType<typeof openDB>>,\n dryRun: boolean\n): Promise<void> {\n if (!existsSync(featureListPath)) {\n console.log(pc.dim(`feature_list.json not found at ${featureListPath} — skipping in-sync`))\n return\n }\n\n let seeds: TaskSeed[]\n try {\n seeds = JSON.parse(readFileSync(featureListPath, 'utf8')) as TaskSeed[]\n } catch (err) {\n console.error(pc.red(`Failed to parse feature_list.json: ${err}`))\n process.exit(1)\n }\n\n if (dryRun) {\n console.log(pc.bold('Dry run — in-sync (feature_list.json → SQLite):'))\n for (const t of seeds) {\n const existing = await db.getTaskBySlug(t.slug)\n console.log(` ${existing ? pc.dim('skip') : pc.green('add ')} ${t.slug}`)\n }\n return\n }\n\n const result = await db.syncFromFeatureList(seeds)\n console.log(pc.green(`✓ In-sync: ${result.added} added, ${result.skipped} already existed`))\n}\n\nasync function syncOut(\n db: Awaited<ReturnType<typeof openDB>>,\n cwd: string,\n dryRun: boolean\n): Promise<void> {\n if (dryRun) {\n const tasks = await db.getTasks()\n console.log(pc.bold('Dry run — out-sync (SQLite → feature_list.json):'))\n console.log(` ${tasks.length} tasks would be written`)\n return\n }\n\n await db.writeFeatureList(cwd)\n console.log(pc.green('✓ Out-sync: feature_list.json updated'))\n}\n","import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\nimport { slugify } from '@/core/materializer/scaffold-utils'\nimport { taskDescriptionSchema, taskTitleSchema } from '@/schema/task'\nimport { cliFormWithRetry } from '@/utils/form'\n\nexport async function runTaskAdd(cwd: string): Promise<void> {\n p.intro(pc.bold('agent-harness-kit — add task'))\n\n const title = await cliFormWithRetry(\n async () => {\n const val = await p.text({ message: 'Task title' })\n if (p.isCancel(val)) { p.cancel('Cancelled.'); process.exit(0) }\n return (val as string).trim()\n },\n taskTitleSchema,\n )\n\n const description = await cliFormWithRetry(\n async () => {\n const val = await p.text({\n message: 'Description (what and why)',\n placeholder: 'Describe the task in more detail, including any relevant context or instructions for the agents.',\n })\n if (p.isCancel(val)) { p.cancel('Cancelled.'); process.exit(0) }\n return (val as string).trim()\n },\n taskDescriptionSchema,\n )\n\n const acceptance: string[] = []\n p.log.info('Acceptance criteria — one per line, empty line to finish')\n while (true) {\n const val = await p.text({ message: '>', placeholder: 'Criterion (or press Enter to finish)' })\n if (p.isCancel(val) || !val || !(val as string).trim()) break\n acceptance.push((val as string).trim())\n }\n\n const spinner = p.spinner()\n spinner.start('Saving...')\n\n try {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n const slug = slugify(title)\n const task = await db.addTask({ slug, title, description: description || undefined, acceptance })\n await db.writeFeatureList(cwd)\n await db.close()\n\n spinner.stop('')\n console.log(pc.green(`✓ Task #${task.id} added — ${task.slug} (pending)`))\n console.log(pc.cyan('→') + ' ' + pc.cyan('ahk status') + ' to see all tasks')\n } catch (err) {\n spinner.stop(pc.red('Failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n\n","import { spawnSync } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\nexport async function runTaskDone(cwd: string, idOrSlug: string): Promise<void> {\n const config = await loadConfig(cwd)\n\n // Run health check first if required\n if (config.health.required) {\n const scriptPath = resolve(cwd, config.health.scriptPath)\n if (existsSync(scriptPath)) {\n const result = spawnSync('bash', [scriptPath], { cwd, stdio: 'pipe', encoding: 'utf8' })\n if (result.status !== 0) {\n console.error(pc.red('✗ Health check failed — cannot mark task as done.'))\n if (result.stdout) console.error(result.stdout)\n if (result.stderr) console.error(result.stderr)\n process.exit(1)\n }\n }\n }\n\n const db = await openDB(config, cwd)\n\n try {\n const parsed = parseInt(idOrSlug, 10)\n const isId = !isNaN(parsed)\n const task = isId ? await db.getTaskById(parsed) : await db.getTaskBySlug(idOrSlug)\n\n if (!task) {\n console.error(pc.red(`Task not found: ${idOrSlug}`))\n process.exit(1)\n }\n\n if (task.status === 'done') {\n console.log(pc.dim(`Task #${task.id} is already done.`))\n return\n }\n\n await db.updateTaskStatus(task.id, 'done')\n await db.writeFeatureList(cwd)\n\n console.log(pc.green(`✓ Task #${task.id} — ${task.slug} marked as done`))\n } finally {\n await db.close()\n }\n}\n","import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\nimport { slugify } from '@/core/materializer/scaffold-utils'\n\nexport async function runTaskEdit(cwd: string): Promise<void> {\n p.intro(pc.bold('agent-harness-kit — edit task'))\n\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n // 1. Get all non-done tasks\n const allTasks = await db.getTasks()\n const activeTasks = allTasks.filter(t => t.status !== 'done')\n\n if (activeTasks.length === 0) {\n p.log.error('No active tasks to edit.')\n return\n }\n\n // 2. Let user select a task\n const taskId = await p.select({\n message: 'Select a task to edit',\n options: activeTasks.map(t => ({\n label: `#${t.id} — ${t.title} (${t.slug})`,\n value: t.id,\n })),\n })\n if (p.isCancel(taskId)) { p.cancel('Cancelled.'); process.exit(0) }\n\n const task = await db.getTaskById(taskId as number)\n if (!task) { p.log.error('Task not found'); process.exit(1) }\n\n // 3. Edit title\n const title = await p.text({\n message: 'Title',\n initialValue: task.title,\n })\n if (p.isCancel(title)) { p.cancel('Cancelled.'); process.exit(0) }\n\n // 4. Edit description\n const description = await p.text({\n message: 'Description (what and why)',\n initialValue: task.description ?? '',\n })\n if (p.isCancel(description)) { p.cancel('Cancelled.'); process.exit(0) }\n\n // 5. Edit acceptance criteria\n const currentAcceptance = await db.getTaskAcceptance(task.id)\n const newAcceptance: string[] = []\n\n p.log.info('Acceptance criteria — edit each, empty to delete. Add new ones at the end.')\n\n // Edit existing criteria\n for (let i = 0; i < currentAcceptance.length; i++) {\n const ac = currentAcceptance[i]\n const val = await p.text({\n message: `#${i + 1}/${currentAcceptance.length}`,\n initialValue: ac.criterion,\n defaultValue: '',\n })\n if (p.isCancel(val)) { p.cancel('Cancelled.'); process.exit(0) }\n const trimmed = (val as string).trim()\n if (trimmed !== '') {\n newAcceptance.push(trimmed)\n }\n // If empty, the criterion is deleted (not pushed)\n }\n\n // Add new criteria\n while (true) {\n const val = await p.text({ message: 'New acceptance criterion', placeholder: '(press Enter to finish)' })\n if (p.isCancel(val) || !val || !(val as string).trim()) break\n newAcceptance.push((val as string).trim())\n }\n\n // 6. Save\n const spinner = p.spinner()\n spinner.start('Saving...')\n\n try {\n const newSlug = slugify(title as string)\n await db.updateTask(task.id, {\n title: title as string,\n description: (description as string).trim() || undefined,\n slug: newSlug,\n })\n await db.updateTaskAcceptance(task.id, newAcceptance)\n await db.writeFeatureList(cwd)\n\n spinner.stop('')\n console.log(pc.green(`✓ Task #${task.id} updated — ${newSlug}`))\n } catch (err) {\n spinner.stop(pc.red('Failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n } finally {\n await db.close()\n }\n}\n","import Table from 'cli-table3'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\nimport type { TaskStatus } from '@/types'\n\ninterface TaskListOptions {\n status?: string\n json?: boolean\n archived?: boolean\n includeArchived?: boolean\n}\n\nconst STATUS_COLOR: Record<string, (s: string) => string> = {\n pending: (s) => pc.dim(s),\n in_progress: (s) => pc.cyan(s),\n done: (s) => pc.green(s),\n blocked: (s) => pc.red(s),\n}\n\nexport async function runTaskList(cwd: string, opts: TaskListOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n const validStatuses: TaskStatus[] = ['pending', 'in_progress', 'done', 'blocked']\n const filterStatus =\n opts.status && validStatuses.includes(opts.status as TaskStatus)\n ? (opts.status as TaskStatus)\n : undefined\n\n const tasks = opts.archived\n ? await db.getArchivedTasks()\n : filterStatus\n ? await db.getTasks(filterStatus, opts.includeArchived ?? false)\n : await db.getTasks(undefined, opts.includeArchived ?? false)\n\n if (opts.json) {\n console.log(JSON.stringify(tasks, null, 2))\n return\n }\n\n if (tasks.length === 0) {\n let msg = 'No tasks'\n if (filterStatus) msg += ` with status: ${filterStatus}`\n if (opts.archived) msg += ' (archived)'\n console.log(pc.dim(msg + '.'))\n return\n }\n\n const table = new Table({\n head: ['ID', 'Slug', 'Title', 'Status'].map((h) => pc.bold(h)),\n style: { head: [], border: [] },\n })\n\n for (const t of tasks) {\n const colorFn = STATUS_COLOR[t.status] ?? ((s: string) => s)\n table.push([String(t.id), t.slug, t.title.slice(0, 50), colorFn(t.status)])\n }\n\n console.log(table.toString())\n\n if (!opts.archived && !opts.includeArchived) {\n const archivedTasks = await db.getArchivedTasks()\n if (archivedTasks.length > 0) {\n console.log(pc.dim(`${archivedTasks.length} archived task${archivedTasks.length !== 1 ? 's' : ''} (use --archived to view)`))\n }\n }\n } finally {\n await db.close()\n }\n}\n","import { accessSync, constants, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { pkg } from '@/core/package-data'\n\n/**\n * Fallback Windows executable extensions, used when `PATHEXT` is not set.\n * Mirrors the platform default (`.COM;.EXE;.BAT;.CMD`) — npm global installs\n * create an `ahk.cmd` shim (plus `ahk.ps1` and a bare shell script), never a\n * bare `ahk.exe`, so `.CMD` in particular must be covered.\n */\nconst DEFAULT_PATHEXT = ['.COM', '.EXE', '.BAT', '.CMD']\n\nexport interface ResolveOnPathOptions {\n /** PATH string to search. Defaults to `process.env.PATH`. */\n pathValue?: string\n /** PATHEXT string (Windows only). Defaults to `process.env.PATHEXT`. */\n pathext?: string\n /** Platform to resolve for. Defaults to `process.platform`. */\n platform?: NodeJS.Platform\n /**\n * POSIX executability probe for a candidate absolute path. Defaults to an\n * `fs.accessSync(p, X_OK)` check. Injectable for deterministic testing.\n */\n isExecutable?: (filePath: string) => boolean\n}\n\n/** Default POSIX executability check: file exists AND has an execute bit. */\nfunction defaultIsExecutable(filePath: string): boolean {\n try {\n accessSync(filePath, constants.X_OK)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Normalizes a `PATHEXT` value into a list of lowercased extensions each\n * beginning with a dot (e.g. `['.com', '.exe', '.bat', '.cmd']`). Falls back\n * to {@link DEFAULT_PATHEXT} when `pathext` is missing or blank.\n */\nfunction normalizeExts(pathext: string | undefined): string[] {\n const raw = pathext && pathext.trim().length > 0 ? pathext : DEFAULT_PATHEXT.join(';')\n return raw\n .split(';')\n .map((ext) => ext.trim().toLowerCase())\n .filter((ext) => ext.length > 0)\n .map((ext) => (ext.startsWith('.') ? ext : `.${ext}`))\n}\n\n/**\n * Pure, cross-platform \"is `name` resolvable as an executable on PATH?\" check.\n *\n * All environment inputs (PATH, PATHEXT, platform) are injectable so BOTH the\n * win32 and POSIX code paths are testable on any CI regardless of the host OS\n * (`process.platform` cannot be reassigned in a test).\n *\n * Behavior:\n * - Splits `pathValue` on the platform-appropriate delimiter (`;` on win32,\n * `:` elsewhere) and skips empty segments.\n * - win32: a candidate matches (case-insensitively) if a directory entry\n * equals the bare `name` or `name` + any `PATHEXT` extension. This is why\n * an `ahk.cmd` shim resolves for the bare name `ahk`.\n * - POSIX: a candidate matches if `join(dir, name)` exists AND is executable.\n * - An undefined/empty `pathValue` returns `false` and never throws; a\n * malformed or inaccessible directory is skipped rather than thrown.\n */\nexport function resolveOnPath(name: string, options: ResolveOnPathOptions = {}): boolean {\n const {\n pathValue = process.env.PATH,\n pathext = process.env.PATHEXT,\n platform = process.platform,\n isExecutable = defaultIsExecutable,\n } = options\n\n if (!pathValue) return false\n\n const isWindows = platform === 'win32'\n const sep = isWindows ? ';' : ':'\n const dirs = pathValue.split(sep).filter((dir) => dir.length > 0)\n if (dirs.length === 0) return false\n\n if (isWindows) {\n const lowerName = name.toLowerCase()\n // Candidate filenames (lowercased): the bare name (in case the caller\n // passed one that already includes an extension) plus name + each ext.\n const candidates = new Set<string>([lowerName, ...normalizeExts(pathext).map((ext) => `${lowerName}${ext}`)])\n for (const dir of dirs) {\n let entries: string[]\n try {\n entries = readdirSync(dir)\n } catch {\n // Missing/inaccessible directory on PATH — skip it, never throw.\n continue\n }\n for (const entry of entries) {\n if (candidates.has(entry.toLowerCase())) return true\n }\n }\n return false\n }\n\n for (const dir of dirs) {\n try {\n if (isExecutable(join(dir, name))) return true\n } catch {\n // Inaccessible entry — skip it, never throw.\n continue\n }\n }\n return false\n}\n\n/**\n * Thin wrapper over {@link resolveOnPath} that reads the real\n * `process.env.PATH`/`PATHEXT` and `process.platform`. Returns whether `name`\n * is resolvable as an executable on the current machine's PATH.\n */\nexport function isExecutableOnPath(name: string): boolean {\n return resolveOnPath(name)\n}\n\n/**\n * Non-blocking warning emitted at config-generation time when the project has\n * no local install AND the bare `ahk` binary is not resolvable on PATH. On the\n * global-install path the generated MCP config launches `ahk serve` directly,\n * so without `ahk` on PATH that config would fail later at spawn time. This\n * moves the failure earlier and makes it actionable. Modeled on\n * `printLocalInstallWarning()`: yellow ⚠ header + dim guidance + exact install\n * commands, all to stderr. Never calls `process.exit`; never changes the exit\n * code.\n */\nexport function printMissingGlobalBinaryWarning(): void {\n console.error(pc.yellow('⚠ `ahk` was not found on your PATH.'))\n console.error(pc.dim(' Your project has no local install, so the generated MCP config launches'))\n console.error(pc.dim(' `ahk serve` directly. Without `ahk` on your PATH, starting the MCP server'))\n console.error(pc.dim(' from that config will fail. This is only a warning — the command continues.'))\n console.error(pc.dim(` Run: npm i -g ${pkg.name} (install globally)`))\n console.error(pc.dim(` or: npm install --save-dev ${pkg.name} (install locally in this project)`))\n}\n","// src/core/update-check.ts\nimport pc from 'picocolors'\n\nimport { drawBox } from '@/commands/init-helpers'\n\nimport { pkg } from './package-data'\n\nconst REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`\nconst TIMEOUT_MS = 2500\n\ninterface UpdateInfo {\n current: string\n latest: string\n}\n\nexport function checkForUpdate(currentVersion: string): Promise<UpdateInfo | null> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => resolve(null), TIMEOUT_MS)\n\n fetch(REGISTRY_URL)\n .then((res) => res.json())\n .then((data) => {\n clearTimeout(timer)\n const latest = (data as { version: string }).version\n resolve(isNewer(latest, currentVersion) ? { current: currentVersion, latest } : null)\n })\n .catch(() => {\n clearTimeout(timer)\n resolve(null)\n })\n })\n}\n\nexport function printUpdateMessage({ current, latest }: UpdateInfo): void {\n const lines = [\n ` Update available ${pc.dim(current)} → ${pc.green(latest)} `,\n ` Run: ${pc.cyan(`pnpm i ${pkg.name}@${latest}`)} `,\n ]\n\n drawBox(lines)\n}\n\nfunction isNewer(latest: string, current: string): boolean {\n const toNum = (v: string) => v.split('.').map(Number)\n const [lMaj, lMin, lPat] = toNum(latest)\n const [cMaj, cMin, cPat] = toNum(current)\n\n if (lMaj !== cMaj) return lMaj > cMaj\n if (lMin !== cMin) return lMin > cMin\n\n return lPat > cPat\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,4BAA4B;AAC9C,OAAOA,UAAQ;;;ACDf,SAAS,aAAa;AACtB,YAAYC,QAAO;AACnB,OAAOC,SAAQ;;;ACFf,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,aAAY;;;ACDrB,SAAS,WAAW,qBAAqB;AACzC,SAAS,MAAM,eAAe;AAEvB,IAAM,QAAQ,CAACC,MAAa,SAAiB,SAAiB,SAAkB;AACrF,QAAM,MAAM,KAAKA,MAAK,OAAO;AAC7B,YAAU,QAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,gBAAc,KAAK,SAAS,EAAE,UAAU,QAAQ,KAAK,CAAC;AACxD;;;ACPA,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,QAAAC,aAAY;;;ACDrB,SAAS,cAAAC,aAAY,oBAAoB;AACzC,SAAS,QAAAC,aAAY;AACrB,OAAO,QAAQ;;;ACFf,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,SAAS,QAAAC,aAAY;AAC9B,SAAS,qBAAqB;AAE9B,IAAMC,WAAU,cAAc,YAAY,GAAG;AAM7C,IAAM,OAAO,QAAQ,cAAc,YAAY,GAAG,CAAC;AACnD,IAAM,aAAa,CAACD,MAAK,MAAM,MAAM,MAAM,cAAc,GAAGA,MAAK,MAAM,MAAM,cAAc,CAAC;AAC5F,IAAM,UAAU,WAAW,KAAK,CAACE,QAAM,WAAWA,GAAC,CAAC,KAAK,WAAW,CAAC;AAE9D,IAAM,MAAMD,SAAQ,OAAO;;;ADa3B,SAAS,wBAAwBE,MAAsB;AAG5D,QAAM,cAAcC,MAAKD,MAAK,cAAc;AAC5C,MAAIE,YAAW,WAAW,GAAG;AAC3B,QAAI;AACF,YAAM,UAAU,KAAK,MAAM,aAAa,aAAa,MAAM,CAAC;AAC5D,UAAI,SAAS,SAAS,IAAI,KAAM,QAAO;AAAA,IACzC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,oBAAoBF,IAAG;AAChC;AAmBO,SAAS,oBAAoBA,MAAsB;AACxD,QAAM,CAAC,OAAO,IAAI,IAAI,IAAI,KAAK,MAAM,GAAG;AACxC,QAAM,YAAY,IAAI,KAAK,WAAW,GAAG,IAAIC,MAAKD,MAAK,gBAAgB,OAAO,IAAI,IAAIC,MAAKD,MAAK,gBAAgB,IAAI,IAAI;AAExH,MAAIE,YAAW,SAAS,EAAG,QAAO;AAQlC,QAAM,QAAQA,YAAWD,MAAKD,MAAK,UAAU,CAAC,KAAKE,YAAWD,MAAKD,MAAK,iBAAiB,CAAC;AAC1F,MAAI,OAAO;AACT,UAAMG,WAAUF,MAAKD,MAAK,cAAc;AACxC,QAAIE,YAAWC,QAAO,GAAG;AACvB,UAAI;AACF,cAAM,aAAa,KAAK,MAAM,aAAaA,UAAS,MAAM,CAAC;AAC3D,cAAM,OAAO;AAAA,UACX,GAAK,YAAY,gBAA4C,CAAC;AAAA,UAC9D,GAAK,YAAY,mBAA+C,CAAC;AAAA,QACnE;AACA,YAAI,OAAO,UAAU,eAAe,KAAK,MAAM,IAAI,IAAI,EAAG,QAAO;AAAA,MACnE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAUO,SAAS,2BAAiC;AAC/C,UAAQ,MAAM,GAAG,OAAO,UAAK,IAAI,IAAI,4CAA4C,CAAC;AAClF,UAAQ,MAAM,GAAG,IAAI,sEAAsE,CAAC;AAC5F,UAAQ,MAAM,GAAG,IAAI,yEAAyE,CAAC;AAC/F,UAAQ,MAAM,GAAG,IAAI,yEAAyE,CAAC;AAC/F,UAAQ,MAAM,GAAG,IAAI,iCAAiC,IAAI,IAAI,EAAE,CAAC;AACjE,UAAQ,MAAM,GAAG,IAAI,yFAAyF,CAAC;AACjH;;;ADxFO,SAAS,qBAAqBC,MAA6B;AAChE,QAAM,YAAY,8BAA8BA,IAAG;AACnD,MAAI,UAAW,QAAO;AAEtB,MAAIC,YAAWC,MAAKF,MAAK,gBAAgB,CAAC,EAAG,QAAO;AACpD,MAAIC,YAAWC,MAAKF,MAAK,WAAW,CAAC,KAAKC,YAAWC,MAAKF,MAAK,UAAU,CAAC,EAAG,QAAO;AACpF,MAAIC,YAAWC,MAAKF,MAAK,WAAW,CAAC,GAAG;AACtC,WAAOC,YAAWC,MAAKF,MAAK,aAAa,CAAC,IAAI,eAAe;AAAA,EAC/D;AACA,MAAIC,YAAWC,MAAKF,MAAK,mBAAmB,CAAC,EAAG,QAAO;AAEvD,SAAO;AACT;AAEA,SAAS,8BAA8BA,MAAoC;AACzE,QAAMG,WAAUD,MAAKF,MAAK,cAAc;AACxC,MAAI,CAACC,YAAWE,QAAO,EAAG,QAAO;AAEjC,MAAI;AACF,UAAMC,OAAM,KAAK,MAAMC,cAAaF,UAAS,MAAM,CAAC;AACpD,UAAM,QAAQC,MAAK;AACnB,QAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,EAAG,QAAO;AAGvD,UAAM,QAAQ,MAAM,MAAM,kBAAkB;AAC5C,QAAI,CAAC,MAAO,QAAO;AAEnB,UAAM,CAAC,EAAE,SAAS,QAAQ,IAAI;AAC9B,UAAM,OAAO,QAAQ,YAAY;AACjC,UAAM,QAAQ,OAAO,QAAQ;AAE7B,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO,SAAS,IAAI,eAAe;AAAA,MACrC;AACE,eAAO;AAAA,IACX;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAwCO,SAAS,mBAAmB,IAAoB,MAAcJ,MAAuB;AAC1F,QAAM,UAAU,OAAO,IAAI;AAK3B,MAAI,CAAC,oBAAoBA,IAAG,GAAG;AAC7B,WAAO,CAAC,OAAO,SAAS,UAAU,OAAO;AAAA,EAC3C;AAEA,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,aAAO,CAAC,QAAQ,QAAQ,OAAO,SAAS,UAAU,OAAO;AAAA,IAC3D,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC,QAAQ,OAAO,OAAO,SAAS,UAAU,OAAO;AAAA,IAC1D,KAAK;AACH,aAAO,CAAC,QAAQ,gBAAgB,OAAO,SAAS,UAAU,OAAO;AAAA,IACnE,KAAK;AAAA,IACL;AACE,aAAO,CAAC,OAAO,QAAQ,OAAO,SAAS,UAAU,OAAO;AAAA,EAC5D;AACF;;;AGhIA,SAAS,cAAAM,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AACnE,SAAS,WAAAC,gBAAe;AAQjB,SAAS,mBACd,UACA,MACAC,MACA,KAAqB,OACf;AACN,QAAM,aAAaC,SAAQ,QAAQ;AACnC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,IAAAC,WAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AAEA,MAAI,WAAoC,CAAC;AACzC,MAAID,YAAW,QAAQ,GAAG;AACxB,QAAI;AACF,iBAAW,KAAK,MAAME,cAAa,UAAU,MAAM,CAAC;AAAA,IACtD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,CAAC,SAAS,GAAG,IAAI,IAAI,mBAAmB,IAAI,MAAMJ,IAAG;AAE3D,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,YAAY;AAAA,MACV,GAAK,SAAS,cAA0C,CAAC;AAAA,MACzD,qBAAqB;AAAA,QACnB,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAAG,WAAUF,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,EAAAI,eAAc,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE;AAIO,SAAS,wBAAwB,UAAwB;AAC9D,EAAAF,WAAUF,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAEhD,MAAI,WAAoC,CAAC;AACzC,MAAIC,YAAW,QAAQ,GAAG;AACxB,QAAI;AACF,iBAAW,KAAK,MAAME,cAAa,UAAU,MAAM,CAAC;AAAA,IACtD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,OAAO;AAAA,EACT;AAEA,EAAAC,eAAc,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE;AAGO,IAAM,8BAA8B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,iCAAiC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,oCAAoC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,yBAAyB;AAAA,EACpC,GAAG,oBAAI,IAAI;AAAA,IACT,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACH;AAEO,SAAS,6BAA6B,UAAwB;AACnE,EAAAF,WAAUF,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAEhD,MAAI,WAAoC,CAAC;AACzC,MAAIC,YAAW,QAAQ,GAAG;AACxB,QAAI;AACF,iBAAW,KAAK,MAAME,cAAa,UAAU,MAAM,CAAC;AAAA,IACtD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,sBAAuB,SAAS,eAA2C,CAAC;AAClF,QAAM,gBAAiB,oBAAoB,SAAsB,CAAC;AAClE,QAAM,kBAAmB,SAAS,yBAAsC,CAAC;AAEzE,QAAM,cAAc,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,eAAe,GAAG,sBAAsB,CAAC,CAAC;AACrF,QAAM,gBAAgB,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,iBAAiB,mBAAmB,CAAC,CAAC;AAEnF,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,aAAa;AAAA,MACX,GAAG;AAAA,MACH,OAAO;AAAA,IACT;AAAA,IACA,uBAAuB;AAAA,EACzB;AAEA,EAAAC,eAAc,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE;AAIO,SAAS,kBACd,UACA,MACAL,MACA,KAAqB,OACf;AACN,QAAM,aAAaC,SAAQ,QAAQ;AACnC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,IAAAC,WAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AAEA,MAAI,WAAoC,CAAC;AACzC,MAAID,YAAW,QAAQ,GAAG;AACxB,QAAI;AACF,iBAAW,KAAK,MAAME,cAAa,UAAU,MAAM,CAAC;AAAA,IACtD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,cAAe,SAAS,OAAmC,CAAC;AAElE,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,eAAe;AAAA,IACf,YAAY,SAAS,cAAc,EAAE,MAAM,MAAM,OAAO,MAAM,UAAU,IAAM;AAAA,IAC9E,YAAY,SAAS,cAAc,EAAE,OAAO,MAAM;AAAA,IAClD,KAAK;AAAA,MACH,GAAG;AAAA,MACH,qBAAqB;AAAA,QACnB,SAAS;AAAA,QACT,MAAM;AAAA;AAAA;AAAA,QAGN,SAAS,mBAAmB,IAAI,MAAMJ,IAAG;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,EAAAK,eAAc,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AACxE;AAIA,SAAS,iBAAiB,SAAiB,aAAqB,aAA6B;AAC3F,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,SAAS,IAAI,WAAW;AAE9B,QAAM,WAAW,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,MAAM,MAAM;AAE3D,MAAI,aAAa,IAAI;AACnB,UAAM,UAAU,QAAQ,QAAQ;AAChC,WAAO,WAAW,UAAU,SAAS,MAAM,SAAS,OAAO,YAAY,QAAQ,IAAI;AAAA,EACrF;AAGA,MAAI,SAAS,MAAM;AACnB,WAAS,IAAI,WAAW,GAAG,IAAI,MAAM,QAAQ,KAAK;AAChD,QAAI,MAAM,KAAK,MAAM,CAAC,CAAC,GAAG;AACxB,eAAS;AACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW;AAAA,IACf,GAAG,MAAM,MAAM,GAAG,QAAQ;AAAA,IAC1B;AAAA,IACA,GAAG,YAAY,QAAQ,EAAE,MAAM,IAAI;AAAA,IACnC;AAAA,IACA,GAAG,MAAM,MAAM,MAAM;AAAA,EACvB;AAEA,SAAO,SAAS,KAAK,IAAI;AAC3B;AAiBO,SAAS,sBAAsB,SAAiB,KAAa,OAAuB;AAGzF,QAAM,QAAQ,QAAQ,SAAS,IAAI,QAAQ,MAAM,IAAI,IAAI,CAAC;AAC1D,QAAM,kBAAkB,MAAM,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC,CAAC;AAC/D,QAAM,cAAc,oBAAoB,KAAK,MAAM,SAAS;AAK5D,QAAM,QAAQ,IAAI,OAAO,QAAQ,GAAG,OAAO;AAC3C,QAAM,iBAAiB,MAAM,MAAM,GAAG,WAAW,EAAE,KAAK,CAAC,MAAM,MAAM,KAAK,CAAC,CAAC;AAC5E,MAAI,eAAgB,QAAO;AAE3B,QAAM,WAAW,CAAC,GAAG,KAAK;AAC1B,WAAS,OAAO,aAAa,GAAG,GAAG,GAAG,MAAM,KAAK,UAAU,KAAK,CAAC,EAAE;AACnE,SAAO,SAAS,KAAK,IAAI;AAC3B;AAEO,SAAS,qBACd,UACA,MACAL,MACA,KAAqB,OACf;AACN,EAAAG,WAAUF,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAEhD,MAAI,UAAU;AACd,MAAIC,YAAW,QAAQ,GAAG;AACxB,cAAUE,cAAa,UAAU,MAAM;AAAA,EACzC;AAEA,QAAM,CAAC,SAAS,GAAG,IAAI,IAAI,mBAAmB,IAAI,MAAMJ,IAAG;AAE3D,QAAM,cAAc;AAAA,IAClB,aAAa,KAAK,UAAU,OAAO,CAAC;AAAA,IACpC,UAAU,KAAK,UAAU,IAAI,CAAC;AAAA,IAC9B;AAAA,EACF,EAAE,KAAK,IAAI;AAKX,YAAU,sBAAsB,SAAS,SAAS,eAAe;AACjE,YAAU,sBAAsB,SAAS,0BAA0B,QAAQ;AAC3E,YAAU,sBAAsB,SAAS,gBAAgB,oBAAoB;AAE7E,YAAU,iBAAiB,SAAS,iCAAiC,WAAW;AAEhF,EAAAK,eAAc,UAAU,SAAS,MAAM;AACzC;AAqBO,SAAS,oBACd,UACA,MACAL,MACA,KAAqB,OACf;AACN,EAAAG,WAAUF,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAEhD,MAAI,UAAU;AACd,MAAIC,YAAW,QAAQ,GAAG;AACxB,cAAUE,cAAa,UAAU,MAAM;AAAA,EACzC;AAEA,QAAM,CAAC,SAAS,GAAG,IAAI,IAAI,mBAAmB,IAAI,MAAMJ,IAAG;AAE3D,QAAM,cAAc;AAAA,IAClB,aAAa,KAAK,UAAU,OAAO,CAAC;AAAA,IACpC,UAAU,KAAK,UAAU,IAAI,CAAC;AAAA,EAChC,EAAE,KAAK,IAAI;AAEX,YAAU,iBAAiB,SAAS,iCAAiC,WAAW;AAEhF,EAAAK,eAAc,UAAU,SAAS,MAAM;AACzC;;;AClYA,SAAS,kBAAkB;AAC3B,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AACnE,SAAS,WAAAC,UAAS,QAAAC,OAAM,WAAAC,gBAAe;AACvC,SAAS,iBAAAC,sBAAqB;;;ACH9B,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAC9B,SAAS,iBAAAC,sBAAqB;;;AC0CvB,IAAM,qBAA0D;AAAA,EACrE,MAAM;AAAA,EACN,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,UAAU;AACZ;AAEO,SAAS,eAAe,WAAwC;AACrE,SAAO,mBAAmB,SAAS,KAAK;AAC1C;AASO,SAAS,sBAAsB,WAAgC;AACpE,SAAO,eAAe,SAAS,MAAM,aAAa,CAAC,SAAS,MAAM,IAAI,CAAC;AACzE;AASO,SAAS,oBAAoB,WAAgE;AAClG,SAAO,eAAe,SAAS,MAAM,aAAa,EAAE,MAAM,OAAO,IAAI,CAAC;AACxE;AAaO,SAAS,iBAAiB,YAAyC;AACxE,SAAO;AACT;AAUO,IAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ/B,SAAS,uBAAuB,WAA8B;AACnE,SAAO,eAAe,SAAS,MAAM,aAAa,yBAAyB;AAC7E;AA8BO,SAAS,mBAAmB,WAAgC;AACjE,SAAO,eAAe,SAAS,MAAM,aACjC,CAAC,QAAQ,QAAQ,gBAAgB,QAAQ,QAAQ,YAAY,aAAa,eAAe,UAAU,IACnG,CAAC;AACP;;;ADhIA,IAAM,YAAYC,SAAQC,eAAc,YAAY,GAAG,CAAC;AACxD,IAAM,gBAAgBC,MAAK,WAAW,iBAAiB;AAMvD,SAAS,kBACP,MACA,OAA+B,CAAC,GACxB;AACR,QAAM,MAAMC,cAAaD,MAAK,eAAe,GAAG,IAAI,KAAK,GAAG,MAAM;AAClE,SAAO,IAAI,QAAQ,kBAAkB,CAAC,GAAG,QAAgB,KAAK,GAAG,KAAK,KAAK,GAAG,IAAI;AACpF;AAIO,IAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBlB,SAAS,SAAS,QAA+B;AACtD,QAAM,EAAE,MAAM,aAAa,SAAS,IAAI,OAAO;AAC/C,QAAM,OAAO,OAAO,MAAM,IAAI;AAE9B,SAAO,sBAAiB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAM1B,IAAI,aAAQ,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mDAoBwB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4EAcgB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAmC5D,QAAQ;AAAA;AAAA;AAAA;AAI3B;AAIO,SAAS,SAAS,QAA+B;AACtD,QAAM,EAAE,MAAM,aAAa,SAAS,IAAI,OAAO;AAC/C,QAAM,OAAO,OAAO,MAAM,IAAI;AAE9B,SAAO,sBAAiB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAM1B,IAAI,aAAQ,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mDAoBwB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4EAcgB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAoC5D,QAAQ;AAAA;AAAA;AAAA;AAI3B;AAoBA,SAAS,iBAAiB,QAAsC;AAC9D,QAAM,WAAW,OAAO,UAAU;AAOlC,QAAM,uBAAuB,WACzB,yCACA;AAEJ,SAAO;AAAA,YACG,KAAK,UAAU,OAAO,IAAI,CAAC;AAAA,mBACpB,KAAK,UAAU,OAAO,WAAW,CAAC;AAAA,iBACpC,OAAO,QAAQ;AAAA;AAAA;AAAA,eAGjB,OAAO,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAiBJ,OAAO,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQvC,oBAAoB;AAAA;AAAA;AAAA,kBAGR,OAAO,KAAK;AAAA,kBACZ,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCASI,OAAO,IAAI;AAAA;AAAA;AAAA;AAIjD;AAgBA,SAAS,aAAa,QAAuD;AAC3E,QAAM,WAAW,OAAO,UAAU;AAElC,SAAO;AAAA,IACL,SAAS;AAAA,MACP,MAAM,OAAO;AAAA,MACb,aAAa,OAAO;AAAA,MACpB,UAAU,OAAO;AAAA,IACnB;AAAA,IACA,UAAU,OAAO;AAAA;AAAA;AAAA,IAGjB,UAAU,EAAE,MAAM,SAAS;AAAA,IAC3B,SAAS;AAAA,MACP,KAAK;AAAA,MACL,OAAO,EAAE,SAAS,OAAO,aAAa;AAAA,MACtC,UAAU;AAAA,QACR,WAAW;AAAA,QACX,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,WAAW;AAAA,MACb;AAAA;AAAA;AAAA,MAGA,kBAAkB,WAAW,EAAE,SAAS,KAAK,IAAI,EAAE,SAAS,MAAM,MAAM,sBAAsB;AAAA,MAC9F,OAAO,OAAO;AAAA,MACd,WAAW,OAAO;AAAA,IACpB;AAAA,IACA,QAAQ;AAAA,MACN,YAAY;AAAA,MACZ,UAAU;AAAA,IACZ;AAAA,IACA,OAAO;AAAA,MACL,KAAK,EAAE,SAAS,MAAM,MAAM,OAAO,KAAK;AAAA,MACxC,SAAS,EAAE,SAAS,MAAM,WAAW,qBAAqB;AAAA,IAC5D;AAAA,EACF;AACF;AAeO,SAAS,WAAW,QAAsC;AAC/D,SAAO,KAAK,UAAU,aAAa,MAAM,GAAG,MAAM,CAAC,IAAI;AACzD;AAeO,SAAS,SAAS,QAAsC;AAC7D,SAAO;AAAA;AAAA;AAAA,EAGP,iBAAiB,MAAM,CAAC;AAAA;AAAA;AAAA;AAI1B;AAOO,SAAS,UAAU,QAAsC;AAC9D,SAAO;AAAA,EACP,iBAAiB,MAAM,CAAC;AAAA;AAAA;AAAA;AAI1B;AAOO,SAAS,UAAU,QAAsC;AAC9D,SAAO;AAAA,EACP,iBAAiB,MAAM,CAAC;AAAA;AAAA;AAAA;AAI1B;AAIO,SAAS,UAAU,MAAuC;AAC/D,SAAO,kBAAkB,QAAQ,IAAI;AACvC;AAEO,SAAS,cAAc,MAAuC;AACnE,SAAO,kBAAkB,YAAY,IAAI;AAC3C;AAEO,SAAS,aAAa,MAAuC;AAClE,SAAO,kBAAkB,WAAW,IAAI;AAC1C;AAEO,SAAS,gBAAgB,MAAuC;AACrE,SAAO,kBAAkB,cAAc,IAAI;AAC7C;AAEO,SAAS,cAAc,MAAuC;AACnE,SAAO,kBAAkB,YAAY,IAAI;AAC3C;AAqBA,SAAS,iBAAiB,IAAmD;AAC3E,QAAM,QAAQ,GAAG,MAAM,WAAW;AAClC,MAAI,MAAM,SAAS,EAAG,QAAO,EAAE,aAAa,IAAI,MAAM,GAAG;AAEzD,QAAM,cAAc,MAAM,CAAC;AAC3B,QAAM,OAAO,MAAM,MAAM,CAAC,EAAE,KAAK,KAAK,EAAE,QAAQ,OAAO,EAAE;AAEzD,MAAI,cAAc;AAElB,QAAM,cAAc,YAAY,MAAM,kDAAkD;AACxF,MAAI,aAAa;AACf,kBAAc,YAAY,CAAC,EACxB,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,EACb,OAAO;AACL,UAAM,cAAc,YAAY,MAAM,wBAAwB;AAC9D,QAAI,YAAa,eAAc,YAAY,CAAC,EAAE,KAAK;AAAA,EACrD;AAEA,SAAO,EAAE,aAAa,KAAK;AAC7B;AAmBA,SAAS,YACP,UACA,WACA,aACA,MACA,MACQ;AAER,QAAM,OAAO,CAAC,MAAc,EAAE,QAAQ,QAAQ,WAAW;AAOzD,QAAM,cAAc,iBAAiB,SAAS;AAC9C,QAAM,SAAS,uBAAuB,SAAS;AAC/C,QAAM,eAAe,SAAS,GAAG,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,EAAc,MAAM,KAAK,KAAK,QAAQ;AAErF,QAAM,aAAuB,CAAC;AAC9B,MAAI,MAAM,MAAO,YAAW,KAAK,YAAY,KAAK,KAAK,GAAG;AAC1D,MAAI,MAAM,OAAQ,YAAW,KAAK,6BAA6B,KAAK,MAAM,GAAG;AAC7E,QAAM,aAAa,WAAW,SAAS,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC;AAAA,IAAO;AAE1E,SAAO,WAAW,QAAQ;AAAA,kBACV,WAAW;AAAA,EAC3B,UAAU;AAAA;AAAA,EAEV,KAAK,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA,EAIjB,KAAK,YAAY,CAAC;AAAA;AAAA;AAGpB;AAEO,SAAS,cAAc,MAA+B,MAAsC;AACjG,QAAM,EAAE,aAAa,KAAK,IAAI,iBAAiB,kBAAkB,QAAQ,IAAI,CAAC;AAC9E,SAAO,YAAY,QAAQ,QAAQ,aAAa,MAAM,IAAI;AAC5D;AAEO,SAAS,uBAAuB,MAA+B,MAAsC;AAC1G,QAAM,EAAE,aAAa,KAAK,IAAI,iBAAiB,kBAAkB,QAAQ,IAAI,CAAC;AAC9E,SAAO,YAAY,WAAW,QAAQ,aAAa,MAAM,IAAI;AAC/D;AAEO,SAAS,kBAAkB,MAA+B,MAAsC;AACrG,QAAM,EAAE,aAAa,KAAK,IAAI,iBAAiB,kBAAkB,YAAY,IAAI,CAAC;AAClF,SAAO,YAAY,YAAY,YAAY,aAAa,MAAM,IAAI;AACpE;AAEO,SAAS,iBAAiB,MAA+B,MAAsC;AACpG,QAAM,EAAE,aAAa,KAAK,IAAI,iBAAiB,kBAAkB,WAAW,IAAI,CAAC;AACjF,SAAO,YAAY,WAAW,WAAW,aAAa,MAAM,IAAI;AAClE;AAEO,SAAS,kBAAkB,MAA+B,MAAsC;AACrG,QAAM,EAAE,aAAa,KAAK,IAAI,iBAAiB,kBAAkB,YAAY,IAAI,CAAC;AAClF,SAAO,YAAY,YAAY,YAAY,aAAa,MAAM,IAAI;AACpE;AAEO,SAAS,oBAAoB,MAA+B,MAAsC;AACvG,QAAM,EAAE,aAAa,KAAK,IAAI,iBAAiB,kBAAkB,cAAc,IAAI,CAAC;AACpF,SAAO,YAAY,cAAc,cAAc,aAAa,MAAM,IAAI;AACxE;AAUA,SAAS,8BAA8B,IAAY,KAAqB;AACtE,QAAM,KAAK,IAAI,OAAO,IAAI,GAAG,2BAA2B,GAAG;AAC3D,SAAO,GAAG,QAAQ,IAAI,EAAE;AAC1B;AAQA,SAAS,+BAA+B,IAAY,KAAa,QAA0B;AACzF,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,QAAQ,GAAG,GAAG;AAAA,EAAM,OAAO,IAAI,CAACE,OAAM,OAAOA,EAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAClE,SAAO,GAAG,QAAQ,2BAA2B,CAAC,IAAI,SAAiB;AAAA,EAAQ,IAAI,GAAG,KAAK;AAAA,CAAO;AAChG;AAQA,SAAS,wBAAwB,IAAY,KAAa,OAAuB;AAC/E,QAAM,QAAQ,GAAG,GAAG,KAAK,KAAK;AAAA;AAC9B,SAAO,GAAG,QAAQ,2BAA2B,CAAC,IAAI,SAAiB;AAAA,EAAQ,IAAI,GAAG,KAAK;AAAA,CAAO;AAChG;AAMA,SAAS,yBAAyB,IAAY,KAAa,SAAyC;AAClG,QAAM,OAAO,OAAO,KAAK,OAAO;AAChC,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,QAAM,QAAQ,GAAG,GAAG;AAAA,EAAM,KAAK,IAAI,CAAC,MAAM,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAC7E,SAAO,GAAG,QAAQ,2BAA2B,CAAC,IAAI,SAAiB;AAAA,EAAQ,IAAI,GAAG,KAAK;AAAA,CAAO;AAChG;AA2BO,SAAS,kCACd,IACA,WACA,MACQ;AACR,MAAI,SAAS,8BAA8B,IAAI,OAAO;AACtD,WAAS,8BAA8B,QAAQ,iBAAiB;AAChE,MAAI,MAAM,SAAS,KAAK,UAAU,WAAW;AAC3C,aAAS,wBAAwB,QAAQ,SAAS,KAAK,KAAK;AAAA,EAC9D;AACA,SAAO,+BAA+B,QAAQ,mBAAmB,sBAAsB,SAAS,CAAC;AACnG;AAmBO,SAAS,gCAAgC,IAAY,WAA8B;AACxF,MAAI,SAAS,8BAA8B,IAAI,OAAO;AACtD,WAAS,8BAA8B,QAAQ,iBAAiB;AAChE,SAAO,yBAAyB,QAAQ,cAAc,oBAAoB,SAAS,CAAC;AACtF;AAmBO,SAAS,4BAA4B,IAAY,WAA8B;AACpF,MAAI,SAAS,8BAA8B,IAAI,OAAO;AACtD,WAAS,8BAA8B,QAAQ,iBAAiB;AAChE,SAAO,+BAA+B,QAAQ,SAAS,mBAAmB,SAAS,CAAC;AACtF;AAIO,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ADjsBjC,IAAMC,aAAYC,SAAQC,eAAc,YAAY,GAAG,CAAC;AAuDjD,SAAS,gBACdC,MACA,SACA,OAA+B,CAAC,GACT;AACvB,QAAM,SAAgC,EAAE,SAAS,CAAC,GAAG,aAAa,CAAC,GAAG,WAAW,CAAC,EAAE;AAEpF,QAAM,WAAW,QAAQ,OAAO,CAAC,MAAMC,YAAWC,MAAKF,MAAK,EAAE,OAAO,CAAC,CAAC;AAGvE,MAAI,KAAK,SAAS,SAAS,SAAS,GAAG;AACrC,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AACA,UAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,UAAM,YAAYE,MAAK,KAAK,YAAY,UAAU,KAAK,EAAE;AACzD,QAAI;AACF,iBAAW,SAAS,UAAU;AAC5B,cAAM,OAAOA,MAAK,WAAW,MAAM,OAAO;AAC1C,QAAAC,WAAUC,SAAQ,MAAM,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,QAAAC,eAAc,MAAMC,cAAaJ,MAAKF,MAAK,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM;AAAA,MAC5E;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,6CAA6C,SAAS,KAChD,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAExD;AAAA,IACF;AACA,WAAO,YAAY;AAAA,EACrB;AAEA,aAAW,SAAS,SAAS;AAC3B,UAAM,MAAME,MAAKF,MAAK,MAAM,OAAO;AACnC,UAAM,SAASC,YAAW,GAAG;AAE7B,QAAI,UAAU,CAAC,KAAK,OAAO;AACzB,aAAO,UAAU,KAAK,MAAM,OAAO;AACnC;AAAA,IACF;AAEA,IAAAE,WAAUC,SAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,IAAAC,eAAc,KAAK,MAAM,SAAS,MAAM;AACxC,QAAI,OAAQ,QAAO,YAAY,KAAK,MAAM,OAAO;AAAA,QAC5C,QAAO,QAAQ,KAAK,MAAM,OAAO;AAAA,EACxC;AAEA,SAAO;AACT;AA8BA,IAAM,sBAAsB;AAE5B,SAAS,gBAAgB,MAAsB;AAC7C,SAAO,WAAW,QAAQ,EAAE,OAAO,MAAM,MAAM,EAAE,OAAO,KAAK;AAC/D;AAUO,SAAS,eAAe,MAAsB;AACnD,SAAO,GAAG,IAAI;AAAA,qBAAwB,gBAAgB,IAAI,CAAC;AAAA;AAC7D;AAMA,SAAS,UAAU,aAA4D;AAC7E,QAAM,IAAI,oBAAoB,KAAK,WAAW;AAC9C,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE;AAClC;AAqCO,SAAS,wBACdL,MACA,SACA,OAAyB,CAAC,GACT;AACjB,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,YAAY,CAAC;AAAA,IACb,WAAW,CAAC;AAAA,IACZ,aAAa,CAAC;AAAA,EAChB;AAGA,QAAM,QAAqD,CAAC;AAC5D,QAAM,WAA6B,CAAC;AAEpC,aAAW,SAAS,SAAS;AAC3B,UAAM,MAAME,MAAKF,MAAK,MAAM,OAAO;AAEnC,QAAI,CAACC,YAAW,GAAG,GAAG;AACpB,YAAM,KAAK,EAAE,OAAO,QAAQ,SAAS,CAAC;AACtC;AAAA,IACF;AAEA,UAAM,SAASK,cAAa,KAAK,MAAM;AACvC,UAAM,QAAQ,UAAU,MAAM;AAC9B,UAAM,aAAa,QAAQ,MAAM,OAAO;AAExC,QAAI,eAAe,MAAM,SAAS;AAGhC,YAAM,KAAK,EAAE,OAAO,QAAQ,UAAU,CAAC;AACvC;AAAA,IACF;AAGA,QAAI,SAAS,MAAM,SAAS,gBAAgB,MAAM,IAAI,GAAG;AAGvD,YAAM,KAAK,EAAE,OAAO,QAAQ,YAAY,CAAC;AACzC;AAAA,IACF;AAIA,QAAI,KAAK,OAAO;AACd,YAAM,KAAK,EAAE,OAAO,QAAQ,YAAY,CAAC;AACzC,eAAS,KAAK,KAAK;AAAA,IACrB,OAAO;AACL,YAAM,KAAK,EAAE,OAAO,QAAQ,WAAW,CAAC;AAAA,IAC1C;AAAA,EACF;AAGA,MAAI,SAAS,SAAS,GAAG;AACvB,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AACA,UAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC3D,UAAM,YAAYJ,MAAK,KAAK,YAAY,WAAW,KAAK,EAAE;AAC1D,QAAI;AACF,iBAAW,SAAS,UAAU;AAC5B,cAAM,OAAOA,MAAK,WAAW,MAAM,OAAO;AAC1C,QAAAC,WAAUC,SAAQ,MAAM,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,QAAAC,eAAc,MAAMC,cAAaJ,MAAKF,MAAK,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM;AAAA,MAC5E;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,iDAAiD,SAAS,KACpD,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAExD;AAAA,IACF;AACA,WAAO,YAAY;AAAA,EACrB;AAEA,aAAW,EAAE,OAAO,OAAO,KAAK,OAAO;AACrC,UAAM,MAAME,MAAKF,MAAK,MAAM,OAAO;AACnC,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO,QAAQ,KAAK,MAAM,OAAO;AACjC;AAAA,MACF,KAAK;AACH,eAAO,UAAU,KAAK,MAAM,OAAO;AACnC;AAAA,MACF,KAAK;AACH,QAAAG,WAAUC,SAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,QAAAC,eAAc,KAAK,eAAe,MAAM,OAAO,GAAG,MAAM;AACxD,eAAO,QAAQ,KAAK,MAAM,OAAO;AACjC;AAAA,MACF,KAAK;AACH,QAAAF,WAAUC,SAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,QAAAC,eAAc,KAAK,eAAe,MAAM,OAAO,GAAG,MAAM;AACxD,eAAO,WAAW,KAAK,MAAM,OAAO;AACpC;AAAA,MACF,KAAK;AACH,QAAAF,WAAUC,SAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,QAAAC,eAAc,KAAK,eAAe,MAAM,OAAO,GAAG,MAAM;AACxD,eAAO,YAAY,KAAK,MAAM,OAAO;AACrC;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,gBAAgBL,MAAmB;AACjD,QAAM,SAASE,MAAKF,MAAK,YAAY;AACrC,QAAM,WAAWC,YAAW,MAAM,IAAIK,cAAa,QAAQ,MAAM,IAAI;AAErE,QAAM,QAAQ,kBAAkB,MAAM,IAAI,EACvC,OAAO,CAAC,SAAS,QAAQ,CAAC,SAAS,SAAS,IAAI,CAAC,EACjD,KAAK,IAAI;AAEZ,MAAI,MAAM,KAAK,GAAG;AAChB,IAAAD,eAAc,QAAQ,YAAY,SAAS,SAAS,IAAI,IAAI,KAAK,QAAQ,QAAQ,MAAM,MAAM;AAAA,EAC/F;AACF;AAEO,SAAS,QAAQ,OAAuB;AAC7C,SAAO,MACJ,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE,EACtB,MAAM,GAAG,EAAE;AAChB;AAEO,SAAS,YAAYL,MAAa,WAAyB;AAChE,QAAM,aAAa,CAAC,WAAW,kBAAkB,cAAc,YAAY;AAC3E,aAAW,aAAa,YAAY;AAClC,UAAM,MAAME,MAAKL,YAAW,UAAU,WAAW,UAAU;AAC3D,UAAM,UAAUK,MAAKF,MAAK,WAAW,SAAS;AAC9C,UAAM,OAAOE,MAAK,SAAS,UAAU;AACrC,IAAAC,WAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC,IAAAE,eAAc,MAAMC,cAAa,KAAK,MAAM,GAAG,MAAM;AAAA,EACvD;AACF;;;AN9SO,SAAS,iBACd,QACA,cACkB;AAClB,QAAM,cAAc,OAAO,QAAQ;AACnC,SAAO;AAAA,IACL,EAAE,SAAS,0BAA0B,SAAS,kCAAkC,UAAU,EAAE,YAAY,CAAC,GAAG,QAAQ,EAAE,OAAO,cAAc,KAAK,CAAC,EAAE;AAAA,IACnJ,EAAE,SAAS,8BAA8B,SAAS,kCAAkC,cAAc,EAAE,YAAY,CAAC,GAAG,YAAY,EAAE,OAAO,cAAc,SAAS,CAAC,EAAE;AAAA,IACnK,EAAE,SAAS,gCAAgC,SAAS,kCAAkC,gBAAgB,EAAE,YAAY,CAAC,GAAG,cAAc,EAAE,OAAO,cAAc,WAAW,CAAC,EAAE;AAAA,IAC3K,EAAE,SAAS,6BAA6B,SAAS,kCAAkC,aAAa,EAAE,YAAY,CAAC,GAAG,WAAW,EAAE,OAAO,cAAc,QAAQ,CAAC,EAAE;AAAA,IAC/J,EAAE,SAAS,8BAA8B,SAAS,kCAAkC,cAAc,EAAE,YAAY,CAAC,GAAG,YAAY,EAAE,OAAO,cAAc,SAAS,CAAC,EAAE;AAAA,EACrK;AACF;AAEO,IAAM,yBAAN,MAAqD;AAAA,EAC1D,MAAM,SAAS,QAAuB,MAAsC;AAC1E,UAAM,EAAE,KAAAC,MAAK,kBAAkB,IAAI;AAMnC,UAAMA,MAAK,aAAa,eAAe,SAAS,MAAM,CAAC,CAAC;AACxD,UAAMA,MAAK,aAAa,eAAe,SAAS,MAAM,CAAC,CAAC;AAGxD,QAAI,CAACC,YAAWC,MAAKF,MAAK,WAAW,CAAC,GAAG;AACvC,YAAMA,MAAK,aAAa,WAAW,GAAK;AAAA,IAC1C;AAaA,QAAI,OAAO,QAAQ,UAAU,WAAW,CAACC,YAAWC,MAAKF,MAAK,OAAO,QAAQ,iBAAiB,IAAI,CAAC,GAAG;AACpG;AAAA,QACEA;AAAA,QACA,OAAO,QAAQ,iBAAiB;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MACF;AAAA,IACF;AAGA,oBAAgBA,MAAK,iBAAiB,QAAQ,iBAAiB,CAAC;AAIhE,uBAAmBE,MAAKF,MAAK,WAAW,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AAEhG,4BAAwBE,MAAKF,MAAK,uBAAuB,CAAC;AAE1D,iCAA6BE,MAAKF,MAAK,6BAA6B,CAAC;AAGrE,oBAAgBA,IAAG;AACnB,gBAAYA,MAAK,gBAAgB;AAAA,EACnC;AAAA,EAEA,MAAM,MAAM,QAAuBA,MAAa,OAAiC,CAAC,GAAyB;AAKzG,UAAM,UAAU;AAAA,MACdA;AAAA,MACA;AAAA,QACE,EAAE,SAAS,aAAa,SAAS,SAAS,MAAM,EAAE;AAAA,QAClD,EAAE,SAAS,aAAa,SAAS,SAAS,MAAM,EAAE;AAAA,MACpD;AAAA,MACA,EAAE,OAAO,KAAK,OAAO,YAAYE,MAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS,EAAE;AAAA,IAC5E;AAQA,UAAM,SAAS,gBAAgBA,MAAK,iBAAiB,QAAQ,KAAK,iBAAiB,GAAG;AAAA,MACpF,OAAO,KAAK;AAAA,MACZ,YAAYE,MAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,IACrD,CAAC;AAMD,uBAAmBE,MAAKF,MAAK,WAAW,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AAChG,4BAAwBE,MAAKF,MAAK,uBAAuB,CAAC;AAC1D,iCAA6BE,MAAKF,MAAK,6BAA6B,CAAC;AACrE,gBAAYA,MAAK,gBAAgB;AAEjC,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AAAA,EAEA,MAAM,QAAQ,QAAuB,KAAe,MAA6B;AAC/E,SAAK;AAAA,EAEP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,gBAAgB,MAA6B;AACjD,YAAQ,IAAI,2EAAsE;AAClF,YAAQ,IAAI,iFAAiF;AAAA,EAC/F;AACF;;;AS1KA,SAAS,cAAAG,aAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAqCvB,SAAS,gBACd,QACA,cACkB;AAClB,QAAM,cAAc,OAAO,QAAQ;AACnC,SAAO;AAAA,IACL,EAAE,SAAS,2BAA2B,SAAS,cAAc,EAAE,YAAY,GAAG,cAAc,IAAI,EAAE;AAAA,IAClG,EAAE,SAAS,+BAA+B,SAAS,kBAAkB,EAAE,YAAY,GAAG,cAAc,QAAQ,EAAE;AAAA,IAC9G,EAAE,SAAS,iCAAiC,SAAS,oBAAoB,EAAE,YAAY,GAAG,cAAc,UAAU,EAAE;AAAA,IACpH,EAAE,SAAS,8BAA8B,SAAS,iBAAiB,EAAE,YAAY,GAAG,cAAc,OAAO,EAAE;AAAA,IAC3G,EAAE,SAAS,+BAA+B,SAAS,kBAAkB,EAAE,YAAY,GAAG,cAAc,QAAQ,EAAE;AAAA,IAC9G,EAAE,SAAS,8BAA8B,SAAS,uBAAuB,EAAE,YAAY,GAAG,cAAc,IAAI,EAAE;AAAA,EAChH;AACF;AAEO,IAAM,uBAAN,MAAmD;AAAA,EACxD,MAAM,SAAS,QAAuB,MAAsC;AAC1E,UAAM,EAAE,KAAAC,MAAK,iBAAiB,IAAI;AAElC,UAAMC,SAAQ,CAAC,SAAiB,SAAiB,SAAkB;AACjE,YAAM,MAAMC,MAAKF,MAAK,OAAO;AAC7B,MAAAG,WAAUC,SAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,MAAAC,eAAc,KAAK,SAAS,EAAE,UAAU,QAAQ,KAAK,CAAC;AAAA,IACxD;AAKA,IAAAJ,OAAM,aAAa,eAAe,SAAS,MAAM,CAAC,CAAC;AAGnD,QAAI,CAACK,YAAWJ,MAAKF,MAAK,WAAW,CAAC,GAAG;AACvC,MAAAC,OAAM,aAAa,WAAW,GAAK;AAAA,IACrC;AAWA,QAAI,OAAO,QAAQ,UAAU,WAAW,CAACK,YAAWJ,MAAKF,MAAK,OAAO,QAAQ,iBAAiB,IAAI,CAAC,GAAG;AACpG,MAAAC;AAAA,QACE,OAAO,QAAQ,iBAAiB;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MACF;AAAA,IACF;AAGA,oBAAgBD,MAAK,gBAAgB,QAAQ,gBAAgB,CAAC;AAI9D,yBAAqBE,MAAKF,MAAK,oBAAoB,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AAE3G,oBAAgBA,IAAG;AACnB,gBAAYA,MAAK,gBAAgB;AAAA,EACnC;AAAA,EAEA,MAAM,MAAM,QAAuBA,MAAa,OAAiC,CAAC,GAAyB;AAIzG,UAAM,UAAU;AAAA,MACdA;AAAA,MACA,CAAC,EAAE,SAAS,aAAa,SAAS,SAAS,MAAM,EAAE,CAAC;AAAA,MACpD,EAAE,OAAO,KAAK,OAAO,YAAYE,MAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS,EAAE;AAAA,IAC5E;AAEA,UAAM,SAAS,gBAAgBA,MAAK,gBAAgB,QAAQ,KAAK,gBAAgB,GAAG;AAAA,MAClF,OAAO,KAAK;AAAA,MACZ,YAAYE,MAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,IACrD,CAAC;AAID,yBAAqBE,MAAKF,MAAK,oBAAoB,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AAC3G,gBAAYA,MAAK,gBAAgB;AAEjC,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AAAA,EAEA,MAAM,QAAQ,QAAuB,KAAe,MAA6B;AAC/E,SAAK;AAAA,EACP;AAAA,EAEA,MAAM,gBAAgB,MAA6B;AACjD,YAAQ,IAAI,6DAAwD;AAAA,EACtE;AACF;;;AClIA,SAAS,cAAAO,aAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAiB9B,SAAS,eAAe,QAAyC;AAC/D,QAAM,cAAc,OAAO,QAAQ;AACnC,SAAO;AAAA,IACL,EAAE,SAAS,wBAAwB,SAAS,4BAA4B,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,EAAE;AAAA,IAC5G,EAAE,SAAS,4BAA4B,SAAS,4BAA4B,cAAc,EAAE,YAAY,CAAC,GAAG,UAAU,EAAE;AAAA,IACxH,EAAE,SAAS,8BAA8B,SAAS,4BAA4B,gBAAgB,EAAE,YAAY,CAAC,GAAG,YAAY,EAAE;AAAA,IAC9H,EAAE,SAAS,2BAA2B,SAAS,4BAA4B,aAAa,EAAE,YAAY,CAAC,GAAG,SAAS,EAAE;AAAA,IACrH,EAAE,SAAS,4BAA4B,SAAS,4BAA4B,cAAc,EAAE,YAAY,CAAC,GAAG,UAAU,EAAE;AAAA,EAC1H;AACF;AAEO,IAAM,mBAAN,MAA+C;AAAA,EACpD,MAAM,SAAS,QAAuB,MAAsC;AAC1E,UAAM,EAAE,KAAAC,KAAI,IAAI;AAEhB,UAAMC,SAAQ,CAAC,SAAiB,SAAiB,SAAkB;AACjE,YAAM,MAAMC,MAAKF,MAAK,OAAO;AAC7B,MAAAG,WAAUC,SAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,MAAAC,eAAc,KAAK,SAAS,EAAE,UAAU,QAAQ,KAAK,CAAC;AAAA,IACxD;AAOA,IAAAJ,OAAM,aAAa,eAAe,SAAS,MAAM,CAAC,CAAC;AAGnD,QAAI,CAACK,YAAWJ,MAAKF,MAAK,WAAW,CAAC,GAAG;AACvC,MAAAC,OAAM,aAAa,WAAW,GAAK;AAAA,IACrC;AAWA,QAAI,OAAO,QAAQ,UAAU,WAAW,CAACK,YAAWJ,MAAKF,MAAK,OAAO,QAAQ,iBAAiB,IAAI,CAAC,GAAG;AACpG,MAAAC;AAAA,QACE,OAAO,QAAQ,iBAAiB;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MACF;AAAA,IACF;AAGA,oBAAgBD,MAAK,eAAe,MAAM,CAAC;AAO3C,wBAAoBE,MAAKF,MAAK,mBAAmB,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AAEzG,oBAAgBA,IAAG;AAKnB,gBAAYA,MAAK,cAAc;AAAA,EACjC;AAAA,EAEA,MAAM,MAAM,QAAuBA,MAAa,OAAiC,CAAC,GAAyB;AAIzG,UAAM,UAAU;AAAA,MACdA;AAAA,MACA,CAAC,EAAE,SAAS,aAAa,SAAS,SAAS,MAAM,EAAE,CAAC;AAAA,MACpD,EAAE,OAAO,KAAK,OAAO,YAAYE,MAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS,EAAE;AAAA,IAC5E;AAEA,UAAM,SAAS,gBAAgBA,MAAK,eAAe,MAAM,GAAG;AAAA,MAC1D,OAAO,KAAK;AAAA,MACZ,YAAYE,MAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,IACrD,CAAC;AAID,wBAAoBE,MAAKF,MAAK,mBAAmB,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AACzG,gBAAYA,MAAK,cAAc;AAE/B,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AAAA,EAEA,MAAM,QAAQ,QAAuB,KAAe,MAA6B;AAC/E,SAAK;AAAA,EACP;AAAA,EAEA,MAAM,gBAAgB,MAA6B;AACjD,YAAQ,IAAI,4DAAuD;AAAA,EACrE;AACF;;;ACnHA,SAAS,cAAAO,aAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAY9B,SAAS,mBAAmB,QAAyC;AACnE,QAAM,cAAc,OAAO,QAAQ;AACnC,SAAO;AAAA,IACL,EAAE,SAAS,4BAA4B,SAAS,gCAAgC,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,EAAE;AAAA,IACpH,EAAE,SAAS,gCAAgC,SAAS,gCAAgC,cAAc,EAAE,YAAY,CAAC,GAAG,UAAU,EAAE;AAAA,IAChI,EAAE,SAAS,kCAAkC,SAAS,gCAAgC,gBAAgB,EAAE,YAAY,CAAC,GAAG,YAAY,EAAE;AAAA,IACtI,EAAE,SAAS,+BAA+B,SAAS,gCAAgC,aAAa,EAAE,YAAY,CAAC,GAAG,SAAS,EAAE;AAAA,IAC7H,EAAE,SAAS,gCAAgC,SAAS,gCAAgC,cAAc,EAAE,YAAY,CAAC,GAAG,UAAU,EAAE;AAAA,EAClI;AACF;AAEO,IAAM,uBAAN,MAAmD;AAAA,EACxD,MAAM,SAAS,QAAuB,MAAsC;AAC1E,UAAM,EAAE,KAAAC,KAAI,IAAI;AAEhB,UAAMC,SAAQ,CAAC,SAAiB,SAAiB,SAAkB;AACjE,YAAM,MAAMC,OAAKF,MAAK,OAAO;AAC7B,MAAAG,WAAUC,SAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD,MAAAC,eAAc,KAAK,SAAS,EAAE,UAAU,QAAQ,KAAK,CAAC;AAAA,IACxD;AAKA,IAAAJ,OAAM,aAAa,eAAe,SAAS,MAAM,CAAC,CAAC;AAGnD,QAAI,CAACK,YAAWJ,OAAKF,MAAK,WAAW,CAAC,GAAG;AACvC,MAAAC,OAAM,aAAa,WAAW,GAAK;AAAA,IACrC;AAWA,QAAI,OAAO,QAAQ,UAAU,WAAW,CAACK,YAAWJ,OAAKF,MAAK,OAAO,QAAQ,iBAAiB,IAAI,CAAC,GAAG;AACpG,MAAAC;AAAA,QACE,OAAO,QAAQ,iBAAiB;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MACF;AAAA,IACF;AAGA,oBAAgBD,MAAK,mBAAmB,MAAM,CAAC;AAI/C,sBAAkBE,OAAKF,MAAK,eAAe,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AAEnG,oBAAgBA,IAAG;AACnB,gBAAYA,MAAK,kBAAkB;AAAA,EACrC;AAAA,EAEA,MAAM,MAAM,QAAuBA,MAAa,OAAiC,CAAC,GAAyB;AAIzG,UAAM,UAAU;AAAA,MACdA;AAAA,MACA,CAAC,EAAE,SAAS,aAAa,SAAS,SAAS,MAAM,EAAE,CAAC;AAAA,MACpD,EAAE,OAAO,KAAK,OAAO,YAAYE,OAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS,EAAE;AAAA,IAC5E;AAEA,UAAM,SAAS,gBAAgBA,MAAK,mBAAmB,MAAM,GAAG;AAAA,MAC9D,OAAO,KAAK;AAAA,MACZ,YAAYE,OAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,IACrD,CAAC;AAID,sBAAkBE,OAAKF,MAAK,eAAe,GAAG,OAAO,MAAM,IAAI,MAAMA,MAAK,qBAAqBA,IAAG,CAAC;AACnG,gBAAYA,MAAK,kBAAkB;AAEnC,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AAAA,EAEA,MAAM,QAAQ,QAAuB,KAAe,MAA6B;AAC/E,SAAK;AAAA,EACP;AAAA,EAEA,MAAM,gBAAgB,MAA6B;AACjD,YAAQ,IAAI,4DAAuD;AAAA,EACrE;AACF;;;ACpDO,SAAS,gBAAgB,UAAkC;AAChE,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,IAAI,uBAAuB;AAAA,IACpC,KAAK;AACH,aAAO,IAAI,qBAAqB;AAAA,IAClC,KAAK;AACH,aAAO,IAAI,qBAAqB;AAAA,IAClC,KAAK;AACH,aAAO,IAAI,iBAAiB;AAAA,IAC9B;AACE,YAAM,IAAI,MAAM,qBAAqB,QAAkB,EAAE;AAAA,EAC7D;AACF;;;AC9DA,YAAY,OAAO;AAKnB,IAAM,eAAoD;AAAA,EACxD,EAAE,KAAK,QAAQ,OAAO,OAAO;AAAA,EAC7B,EAAE,KAAK,YAAY,OAAO,WAAW;AAAA,EACrC,EAAE,KAAK,cAAc,OAAO,aAAa;AAAA,EACzC,EAAE,KAAK,WAAW,OAAO,UAAU;AAAA,EACnC,EAAE,KAAK,YAAY,OAAO,WAAW;AACvC;AAiBA,eAAsB,wBACpB,UAC6C;AAC7C,QAAM,oBAAwD,CAAC;AAC/D,MAAI,aAAa,cAAe,QAAO;AAEvC,aAAW,SAAS,cAAc;AAChC,UAAM,MAAM,MAAQ,SAAO;AAAA,MACzB,SAAS,aAAa,MAAM,KAAK;AAAA,MACjC,SAAS;AAAA,QACP,EAAE,OAAO,WAAW,OAAO,oBAAoB;AAAA,QAC/C,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,QACjC,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,QACnC,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,MACnC;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AACD,QAAM,WAAS,GAAG,GAAG;AACnB,MAAE,SAAO,YAAY;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,sBAAkB,MAAM,GAAG,IAAI;AAAA,EACjC;AAEA,SAAO;AACT;;;ACtDA,YAAYO,QAAO;AAKnB,IAAMC,gBAAoD;AAAA,EACxD,EAAE,KAAK,QAAQ,OAAO,OAAO;AAAA,EAC7B,EAAE,KAAK,YAAY,OAAO,WAAW;AAAA,EACrC,EAAE,KAAK,cAAc,OAAO,aAAa;AAAA,EACzC,EAAE,KAAK,WAAW,OAAO,UAAU;AAAA,EACnC,EAAE,KAAK,YAAY,OAAO,WAAW;AACvC;AAWA,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUA,IAAM,uBAAuB,CAAC,WAAW,OAAO,UAAU,QAAQ,OAAO;AAgBzE,eAAsB,uBACpB,UAC4D;AAC5D,QAAM,mBAAsE,CAAC;AAC7E,MAAI,aAAa,YAAa,QAAO;AAErC,aAAW,SAASA,eAAc;AAChC,UAAM,WAAW,MAAQ,UAAO;AAAA,MAC9B,SAAS,aAAa,MAAM,KAAK;AAAA,MACjC,SAAS,oBAAoB,IAAI,CAAC,WAAW,EAAE,OAAO,OAAO,MAAM,EAAE;AAAA,MACrE,cAAc;AAAA,IAChB,CAAC;AACD,QAAM,YAAS,QAAQ,GAAG;AACxB,MAAE,UAAO,YAAY;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,YAAY,MAAQ,UAAO;AAAA,MAC/B,SAAS,wBAAwB,MAAM,KAAK;AAAA,MAC5C,SAAS,qBAAqB,IAAI,CAAC,WAAW,EAAE,OAAO,OAAO,MAAM,EAAE;AAAA,MACtE,cAAc;AAAA,IAChB,CAAC;AACD,QAAM,YAAS,SAAS,GAAG;AACzB,MAAE,UAAO,YAAY;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,qBAAiB,MAAM,GAAG,IAAI;AAAA,MAC5B,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AACT;;;AfvEA,eAAsB,SAASC,MAAa,MAAmC;AAC7E,QAAM,UAAUA,MAAK,KAAK,KAAK;AAE/B,MAAI,KAAK,MAAM;AACb,IAAE,OAAI,KAAK,8BAA8B;AACzC,UAAM,SAAS,MAAM,WAAWA,IAAG;AACnC,UAAM,eAAe,gBAAgB,OAAO,QAAQ;AACpD,UAAM,aAAa,gBAAgBA,IAAG;AAAA,EACxC;AAEA,MAAI,KAAK,OAAO;AACd,IAAE,OAAI,KAAK,qDAAqD;AAChE,UAAMA,MAAK,EAAE,WAAW,MAAM,GAAG,OAAO,GAAG,aAAa;AACtD,UAAI,UAAU,WAAW,0BAA0B,GAAG;AACpD,QAAE,OAAI,KAAK,qCAAgC;AAI3C,cAAM,UAAUA,MAAK,KAAK;AAAA,MAC5B;AAAA,IACF,CAAC;AAED,UAAM,IAAI,QAAQ,MAAM;AAAA,IAAE,CAAC;AAAA,EAC7B;AACF;AAEA,eAAe,UAAUA,MAAa,OAAgC;AAOpE,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAWA,IAAG;AAAA,EAC/B,SAAS,KAAK;AACZ,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAKA,MAAI;AACJ,MAAI,SAAS,OAAO,aAAa,eAAe;AAC9C,wBAAoB,MAAM,wBAAwB,OAAO,QAAQ;AAAA,EACnE;AAKA,MAAI;AACJ,MAAI,SAAS,OAAO,aAAa,aAAa;AAC5C,uBAAmB,MAAM,uBAAuB,OAAO,QAAQ;AAAA,EACjE;AAEA,QAAMC,WAAY,WAAQ;AAC1B,EAAAA,SAAQ,MAAM,qBAAqB;AAEnC,MAAI;AACF,UAAM,eAAe,gBAAgB,OAAO,QAAQ;AACpD,UAAM,SAAS,MAAM,aAAa,MAAM,QAAQD,MAAK,EAAE,OAAO,mBAAmB,iBAAiB,CAAC;AACnG,IAAAC,SAAQ,KAAKC,IAAG,MAAM,gBAAgB,CAAC;AAOvC,UAAM,IAAI,OAAO;AACjB,UAAM,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,SAAS,GAAG,EAAE,UAAU;AAC7D,QAAI,SAAS,SAAS,GAAG;AACvB,MAAE,OAAI,QAAQ,SAAS,KAAK,IAAI,CAAC;AAAA,IACnC;AACA,QAAI,EAAE,WAAW,SAAS,GAAG;AAC3B,MAAE,OAAI,KAAK,gCAAgC,EAAE,WAAW,MAAM;AAAA,IAA0B,EAAE,WAAW,KAAK,MAAM,CAAC,EAAE;AAAA,IACrH;AACA,QAAI,EAAE,YAAY,SAAS,GAAG;AAC5B,MAAE,OAAI;AAAA,QACJA,IAAG;AAAA,UACD,uBAAuB,EAAE,YAAY,MAAM;AAAA,MACzC,EAAE,YAAY,KAAK,MAAM;AAAA,QAC7B;AAAA,MACF;AACA,UAAI,EAAE,WAAW;AACf,QAAE,OAAI,KAAKA,IAAG,OAAO,uCAAkC,EAAE,SAAS,EAAE,CAAC;AAAA,MACvE;AAAA,IACF;AACA,QAAI,EAAE,UAAU,SAAS,GAAG;AAG1B,MAAE,OAAI;AAAA,QACJA,IAAG;AAAA,UACD,QAAQ,EAAE,UAAU,MAAM;AAAA,MACxB,EAAE,UAAU,KAAK,MAAM,IACvB;AAAA;AAAA;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AAEA,IAAE,OAAI,QAAQ,sBAAsB,OAAO,QAAQ,GAAG;AACtD,IAAE,OAAI,QAAQ,YAAY;AAE1B,UAAM,EAAE,SAAS,aAAa,WAAW,UAAU,IAAI,OAAO;AAE9D,QAAI,QAAQ,SAAS,GAAG;AACtB,MAAE,OAAI,KAAK,WAAW,QAAQ,MAAM;AAAA,IAA8B,QAAQ,KAAK,MAAM,CAAC,EAAE;AAAA,IAC1F;AAEA,QAAI,YAAY,SAAS,GAAG;AAG1B,MAAE,OAAI;AAAA,QACJA,IAAG;AAAA,UACD,uBAAuB,YAAY,MAAM;AAAA,MACvC,YAAY,KAAK,MAAM;AAAA,QAC3B;AAAA,MACF;AACA,UAAI,WAAW;AACb,QAAE,OAAI,KAAKA,IAAG,OAAO,uCAAkC,SAAS,EAAE,CAAC;AAAA,MACrE;AAAA,IACF;AAEA,QAAI,UAAU,SAAS,GAAG;AAGxB,MAAE,OAAI;AAAA,QACJ,QAAQ,UAAU,MAAM;AAAA;AAAA;AAAA,MAG1B;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,IAAAD,SAAQ,KAAKC,IAAG,IAAI,cAAc,CAAC;AACnC,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AgB9JA,SAAS,eAAe;AACxB,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,iBAAAC,sBAAqB;AAC9B,OAAOC,SAAQ;;;ACHf,SAAS,SAAAC,cAAa;AACtB,SAAS,cAAAC,cAAY,gBAAAC,qBAAoB;AACzC,SAAS,SAAS,QAAAC,cAAY;AAC9B,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,uBAAuB;;;ACLhC,SAAS,oBAAoB;AAqBtB,IAAM,sBAA0C;AAgBhD,SAAS,WAAW,MAAc,OAA2B,qBAAuC;AACzG,SAAO,IAAI,QAAQ,CAACC,cAAY;AAC9B,UAAM,SAAS,aAAa;AAC5B,WAAO,KAAK,SAAS,MAAMA,UAAQ,KAAK,CAAC;AACzC,WAAO,KAAK,aAAa,MAAM;AAC7B,aAAO,MAAM,MAAMA,UAAQ,IAAI,CAAC;AAAA,IAClC,CAAC;AACD,WAAO,OAAO,MAAM,IAAI;AAAA,EAC1B,CAAC;AACH;AAEA,eAAsB,aAAa,OAAe,UAA+B,CAAC,GAAoB;AACpG,QAAM,EAAE,cAAc,IAAI,OAAO,oBAAoB,IAAI;AASzD,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,UAAU,KAAK,GAAG;AACzD,UAAM,IAAI;AAAA,MACR,0DAA0D,OAAO,KAAK,IAAI,KAAK,UAAU,KAAK,CAAC;AAAA,IAEjG;AAAA,EACF;AAEA,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,UAAM,OAAO,QAAQ;AACrB,QAAI,MAAM,WAAW,MAAM,IAAI,EAAG,QAAO;AAAA,EAC3C;AAEA,QAAM,IAAI;AAAA,IACR,oCAAoC,WAAW,oBAAoB,KAAK,IAAI,QAAQ,cAAc,CAAC;AAAA,EACrG;AACF;;;ADzDA,IAAM,OAA+B;AAAA,EACnC,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AACV;AAEA,SAAS,aAAa,UAA4B;AAChD,QAAM,UAAUC,cAAa,QAAQ;AACrC,QAAM,OAAO,KAAK,QAAQ,QAAQ,CAAC,KAAK;AACxC,SAAO,IAAI,SAAS,SAAS;AAAA,IAC3B,SAAS,EAAE,gBAAgB,MAAM,iBAAiB,WAAW;AAAA,EAC/D,CAAC;AACH;AAyBO,SAAS,qBAAqB,QAAwB,MAA6B;AACxF,SAAO,IAAI,QAAc,CAACC,WAAS,WAAW;AAS5C,UAAM,eAAe,MAAM;AACzB,UAAI;AACF,eAAO,MAAM,MAAM;AAAA,QAEnB,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,UAAU,CAAC,QAA+B;AAC9C,aAAO,IAAI,aAAa,WAAW;AACnC,mBAAa;AACb,UAAI,IAAI,SAAS,cAAc;AAC7B;AAAA,UACE,IAAI;AAAA,YACF,QAAQ,IAAI;AAAA,UACd;AAAA,QACF;AACA;AAAA,MACF;AACA,aAAO,IAAI,MAAM,yCAAyC,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;AAAA,IACnF;AACA,UAAM,cAAc,MAAM;AACxB,aAAO,IAAI,SAAS,OAAO;AAC3B,MAAAA,UAAQ;AAAA,IACV;AACA,WAAO,KAAK,SAAS,OAAO;AAC5B,WAAO,KAAK,aAAa,WAAW;AAAA,EACtC,CAAC;AACH;AAOA,eAAsB,qBACpB,IACA,QACA,YACA,MACgC;AAChC,QAAM,MAAM,IAAI,KAAK;AACrB,QAAM,EAAE,OAAO,SAAS,MAAM,IAAI;AAGlC,MAAI,IAAI,UAAU,OAAO,GAAG,SAAS;AACnC,UAAM,KAAK;AACX,MAAE,IAAI,QAAQ,IAAI,+BAA+B,GAAG;AAAA,EACtD,CAAC;AAGD,MAAI,IAAI,cAAc,OAAO,MAAM;AACjC,UAAM,GAAG,UAAU;AACnB,UAAM,UAAU,MAAM,MAAM,iBAAiB;AAC7C,UAAM,WAAmC,EAAE,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,EAAE;AAC3F,eAAW,EAAE,QAAQ,MAAM,KAAK,QAAS,UAAS,MAAM,IAAI;AAC5D,UAAM,SAAS,MAAM,MAAM,UAAU;AACrC,WAAO,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;AAAA,EACvC,CAAC;AAGD,MAAI,IAAI,aAAa,CAAC,MAAM;AAC1B,WAAO,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,EAC5B,CAAC;AAGD,MAAI,IAAI,cAAc,OAAO,MAAM;AACjC,UAAM,GAAG,UAAU;AACnB,UAAM,kBAAkB,EAAE,IAAI,MAAM,iBAAiB,MAAM;AAC3D,WAAO,EAAE,KAAK,MAAM,MAAM,2BAA2B,eAAe,CAAC;AAAA,EACvE,CAAC;AAGD,MAAI,IAAI,kBAAkB,OAAO,MAAM;AACrC,UAAM,GAAG,UAAU;AACnB,UAAM,KAAK,SAAS,EAAE,IAAI,MAAM,IAAI,CAAC;AACrC,UAAMC,QAAO,MAAM,MAAM,QAAQ,EAAE;AACnC,QAAI,CAACA,MAAM,QAAO,EAAE,KAAK,EAAE,OAAO,YAAY,GAAG,GAAG;AAEpD,UAAM,aAAa,MAAM,MAAM,cAAc,EAAE;AAC/C,UAAM,cAAc,MAAM,QAAQ,eAAe,EAAE;AACnD,WAAO,EAAE,KAAK,EAAE,GAAGA,OAAM,YAAY,SAAS,YAAY,CAAC;AAAA,EAC7D,CAAC;AAGD,MAAI,MAAM,kBAAkB,OAAO,MAAM;AACvC,UAAM,KAAK,SAAS,EAAE,IAAI,MAAM,IAAI,CAAC;AACrC,UAAMA,QAAO,MAAM,MAAM,QAAQ,EAAE;AACnC,QAAI,CAACA,MAAM,QAAO,EAAE,KAAK,EAAE,OAAO,YAAY,GAAG,GAAG;AAEpD,UAAM,OAAO,MAAM,EAAE,IAAI,KAAK;AAC9B,UAAM,eAA+E,CAAC;AACtF,QAAI,KAAK,UAAU,OAAW,cAAa,QAAQ,KAAK;AACxD,QAAI,KAAK,gBAAgB,OAAW,cAAa,cAAc,KAAK;AAEpE,UAAM,GAAG,WAAW,IAAI,YAAY;AAEpC,QAAI,KAAK,eAAe,UAAa,MAAM,QAAQ,KAAK,UAAU,GAAG;AACnE,YAAM,GAAG;AAAA,QACP;AAAA,QACA,KAAK,WAAW,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,MAC7D;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,MAAM,QAAQ,EAAE;AACtC,UAAM,aAAa,MAAM,MAAM,cAAc,EAAE;AAC/C,UAAM,cAAc,MAAM,QAAQ,eAAe,EAAE;AACnD,WAAO,EAAE,KAAK,EAAE,GAAG,SAAS,YAAY,SAAS,YAAY,CAAC;AAAA,EAChE,CAAC;AAGD,MAAI,MAAM,0BAA0B,OAAO,MAAM;AAC/C,UAAM,GAAG,UAAU;AACnB,UAAM,KAAK,SAAS,EAAE,IAAI,MAAM,IAAI,CAAC;AACrC,UAAMA,QAAO,MAAM,MAAM,QAAQ,EAAE;AACnC,QAAI,CAACA,MAAM,QAAO,EAAE,KAAK,EAAE,OAAO,YAAY,GAAG,GAAG;AACpD,UAAM,UAAU,MAAM,GAAG,YAAY,EAAE;AACvC,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,CAAC;AAGD,MAAI,MAAM,4BAA4B,OAAO,MAAM;AACjD,UAAM,GAAG,UAAU;AACnB,UAAM,KAAK,SAAS,EAAE,IAAI,MAAM,IAAI,CAAC;AACrC,UAAMA,QAAO,MAAM,MAAM,QAAQ,EAAE;AACnC,QAAI,CAACA,MAAM,QAAO,EAAE,KAAK,EAAE,OAAO,YAAY,GAAG,GAAG;AACpD,UAAM,UAAU,MAAM,GAAG,cAAc,EAAE;AACzC,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,CAAC;AAGD,MAAI,IAAI,kBAAkB,OAAO,MAAM;AACrC,UAAM,GAAG,UAAU;AACnB,UAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AACnD,WAAO,EAAE,KAAK,MAAM,QAAQ,YAAY,KAAK,CAAC;AAAA,EAChD,CAAC;AAGD,MAAI,IAAI,qBAAqB,OAAO,MAAM;AACxC,UAAM,GAAG,UAAU;AACnB,UAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AACnD,WAAO,EAAE,KAAK,MAAM,MAAM,eAAe,KAAK,CAAC;AAAA,EACjD,CAAC;AAGD,MAAI,IAAI,kBAAkB,OAAO,MAAM;AACrC,UAAM,GAAG,UAAU;AACnB,UAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AACnD,WAAO,EAAE,KAAK,MAAM,MAAM,YAAY,KAAK,CAAC;AAAA,EAC9C,CAAC;AAGD,MAAI,IAAI,qBAAqB,OAAO,MAAM;AACxC,UAAM,GAAG,UAAU;AACnB,UAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AACnD,WAAO,EAAE,KAAK,MAAM,MAAM,eAAe,KAAK,CAAC;AAAA,EACjD,CAAC;AAGD,MAAI,IAAI,qBAAqB,OAAO,MAAM;AACxC,UAAM,GAAG,UAAU;AACnB,WAAO,EAAE,KAAK,MAAM,MAAM,cAAc,CAAC;AAAA,EAC3C,CAAC;AAGD,MAAI,IAAI,iBAAiB,OAAO,MAAM;AACpC,UAAM,GAAG,UAAU;AACnB,UAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AACnD,WAAO,EAAE,KAAK,MAAM,MAAM,YAAY,KAAK,CAAC;AAAA,EAC9C,CAAC;AAGD,MAAI,IAAI,MAAM,CAAC,MAAM;AACnB,UAAM,UAAU,EAAE,IAAI;AACtB,QAAI,YAAY,KAAK;AACnB,YAAM,YAAYC,OAAK,YAAY,OAAO;AAC1C,UAAIC,aAAW,SAAS,GAAG;AACzB,YAAI;AACF,iBAAO,aAAa,SAAS;AAAA,QAC/B,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AACA,WAAO,aAAaD,OAAK,YAAY,YAAY,CAAC;AAAA,EACpD,CAAC;AAKD,QAAM,eAAe,MAAM,aAAa,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC3E,MAAI,iBAAiB,MAAM;AACzB,YAAQ,IAAI,QAAQ,IAAI,kBAAkB,YAAY,EAAE;AAAA,EAC1D;AAEA,QAAM,aAAa,MAAM;AAAA,IACvB,OAAO,IAAI;AAAA,IACX,MAAM;AAAA,IACN,UAAU;AAAA,EACZ,CAAC;AAMD,QAAM,qBAAqB,YAAY,YAAY;AAInD,aAAW,GAAG,SAAS,CAAC,QAA+B;AACrD,YAAQ,MAAM,2BAA2B,IAAI,OAAO,EAAE;AAAA,EACxD,CAAC;AAGD,QAAM,MAAM,IAAI,gBAAgB,EAAE,UAAU,KAAK,CAAC;AAElD,aAAW,GAAG,WAAW,CAAC,KAAsB,QAAgB,SAAiB;AAC/E,QAAI,IAAI,QAAQ,OAAO;AACrB,UAAI,cAAc,KAAK,QAAQ,MAAM,CAAC,OAAO;AAC3C,YAAI,KAAK,cAAc,IAAI,GAAG;AAAA,MAChC,CAAC;AAAA,IACH,OAAO;AACL,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF,CAAC;AAGD,MAAI;AAEJ,QAAM,YAAY,MAAM;AACtB,iBAAa,QAAQ;AACrB,eAAW,WAAW,MAAM;AAC1B,iBAAW,UAAU,IAAI,SAAS;AAChC,YAAI,OAAO,eAAe,GAAG;AAC3B,iBAAO,KAAK,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC,CAAC;AAAA,QAChD;AAAA,MACF;AAAA,IACF,GAAG,GAAG;AAAA,EACR;AAGA,MAAI,UAA2C;AAC/C,MAAI,QAAQ;AACV,UAAM,UAAU,GAAG,MAAM;AACzB,UAAM,cAAcC,aAAW,OAAO,IAAI,UAAU;AACpD,cAAUC,OAAM,aAAa,SAAS;AAAA,EACxC;AAEA,SAAO;AAAA,IACL,KAAK,oBAAoB,YAAY;AAAA,IACrC,OAAO,MAAM;AACX,mBAAa,QAAQ;AACrB,eAAS,MAAM;AACf,UAAI,MAAM;AACV,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF;AACF;;;ADhUA,IAAMC,aAAYC,SAAQC,eAAc,YAAY,GAAG,CAAC;AAOxD,eAAsB,aAAaC,MAAa,MAAuC;AACrF,QAAM,SAAS,MAAM,WAAWA,IAAG;AACnC,QAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AACnC,QAAM,SAAS,OAAO,SAAS,SAAS,WAAW,kBAAkB,QAAQA,MAAK,QAAQ,CAAC,IAAI;AAC/F,QAAM,aAAaC,OAAKJ,YAAW,gBAAgB;AAEnD,QAAM,EAAE,IAAI,IAAI,MAAM,qBAAqB,IAAI,QAAQ,YAAY,KAAK,IAAI;AAE5E,UAAQ,IAAIK,IAAG,MAAM,QAAG,IAAI,yBAAyBA,IAAG,KAAKA,IAAG,KAAK,GAAG,CAAC,CAAC,EAAE;AAC5E,UAAQ,IAAIA,IAAG,IAAI,kCAAkC,CAAC;AACtD,UAAQ,IAAIA,IAAG,IAAI,wBAAwB,CAAC;AAE5C,MAAI,KAAK,MAAM;AACb,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,OAAO,MAAM;AAC7C,UAAM,KAAK,GAAG;AAAA,EAChB;AAEA,UAAQ,GAAG,UAAU,MAAM;AACzB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAGD,QAAM,IAAI,QAAc,MAAM;AAAA,EAAE,CAAC;AACnC;;;AGvCA,OAAOC,SAAQ;;;ACAf,SAAS,cAAAC,cAAY,gBAAAC,qBAAoB;AACzC,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,iBAAAC,sBAAqB;AAsC9B,IAAM,eAAe,8BAA8B,IAAI,IAAI;AAC3D,IAAM,aAAa;AACnB,IAAM,2BAA2B,IAAI,KAAK;AAC1C,IAAM,cAAc,CAAC,QAAQ,YAAY,cAAc,WAAW,UAAU;AAE5E,IAAM,cAAc,CAAC,WAAW,kBAAkB,cAAc,YAAY;AAE5E,IAAMC,aAAYC,SAAQC,eAAc,YAAY,GAAG,CAAC;AAOxD,IAAI,kBAAmE;AAOvE,eAAe,kBAAsC;AACnD,QAAM,UAAU,IAAI;AAEpB,MAAI,mBAAmB,KAAK,IAAI,IAAI,gBAAgB,YAAY,0BAA0B;AAGxF,QAAI,gBAAgB,OAAO,YAAY,SAAS;AAC9C,aAAO,gBAAgB;AAAA,IACzB;AAAA,EACF;AAEA,MAAI;AACF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,UAAU;AAE7D,UAAM,MAAM,MAAM,MAAM,cAAc,EAAE,QAAQ,WAAW,OAAO,CAAC;AACnE,iBAAa,KAAK;AAElB,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,UAAM,SAAS,KAAK;AACpB,UAAM,WAAW,QAAQ,QAAQ,OAAO;AACxC,UAAM,SAAoB,EAAE,SAAS,QAAQ,SAAS;AACtD,sBAAkB,EAAE,QAAQ,WAAW,KAAK,IAAI,EAAE;AAClD,WAAO;AAAA,EACT,QAAQ;AACN,UAAM,SAAoB,EAAE,SAAS,QAAQ,MAAM,UAAU,MAAM;AAGnE,sBAAkB,EAAE,QAAQ,WAAW,KAAK,IAAI,EAAE;AAClD,WAAO;AAAA,EACT;AACF;AAEA,SAAS,QAAQ,QAAgB,SAA0B;AACzD,QAAM,QAAQ,CAACC,OAAcA,GAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AACpD,QAAM,CAAC,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM;AACvC,QAAM,CAAC,MAAM,MAAM,IAAI,IAAI,MAAM,OAAO;AACxC,MAAI,SAAS,KAAM,QAAO,OAAO;AACjC,MAAI,SAAS,KAAM,QAAO,OAAO;AACjC,SAAO,OAAO;AAChB;AAIA,SAAS,qBAAqB,UAG5B;AACA,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,EAAE,WAAW,kBAAkB,KAAK,MAAM;AAAA,IACnD,KAAK;AACH,aAAO,EAAE,WAAW,oBAAoB,KAAK,MAAM;AAAA,IACrD,KAAK;AACH,aAAO,EAAE,WAAW,iBAAiB,KAAK,QAAQ;AAAA,IACpD,KAAK;AACH,aAAO,EAAE,WAAW,gBAAgB,KAAK,MAAM;AAAA,IACjD;AACE,aAAO,EAAE,WAAW,kBAAkB,KAAK,MAAM;AAAA,EACrD;AACF;AAQA,SAAS,sBAAsB,YAAoB,KAA4B;AAC7E,SAAO,YAAY,IAAI,CAAC,SAAS;AAC/B,UAAM,WAAWC,OAAK,YAAY,GAAG,IAAI,GAAG,GAAG,EAAE;AACjD,WAAO,EAAE,MAAM,QAAQC,aAAW,QAAQ,IAAK,OAAkB,UAAoB;AAAA,EACvF,CAAC;AACH;AAEA,SAAS,gBAAgBC,MAAa,UAAiC;AACrE,QAAM,EAAE,WAAW,IAAI,IAAI,qBAAqB,QAAQ;AACxD,SAAO,sBAAsBF,OAAKE,MAAK,SAAS,GAAG,GAAG;AACxD;AAIA,SAAS,qBAAqB,UAA0B;AACtD,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKA,SAAS,kBAAkB,YAAmC;AAE5D,QAAM,kBAAkBF,OAAKG,YAAW,QAAQ;AAEhD,SAAO,YAAY,IAAI,CAAC,SAAS;AAC/B,UAAM,WAAWH,OAAK,YAAY,MAAM,UAAU;AAClD,UAAM,aAAaA,OAAK,iBAAiB,MAAM,UAAU;AAEzD,QAAI,CAACC,aAAW,QAAQ,GAAG;AACzB,aAAO,EAAE,MAAM,QAAQ,UAAmB;AAAA,IAC5C;AAEA,QAAI;AACF,YAAM,OAAOG,cAAa,UAAU,MAAM;AAC1C,YAAM,SAASA,cAAa,YAAY,MAAM;AAC9C,aAAO,EAAE,MAAM,QAAQ,SAAS,SAAS,OAAO,WAAW;AAAA,IAC7D,QAAQ;AACN,aAAO,EAAE,MAAM,QAAQ,WAAoB;AAAA,IAC7C;AAAA,EACF,CAAC;AACH;AAEA,SAAS,YAAYF,MAAa,UAAiC;AACjE,QAAM,YAAY,qBAAqB,QAAQ;AAC/C,SAAO,kBAAkBF,OAAKE,MAAK,SAAS,CAAC;AAC/C;AAIA,eAAsB,gBAAgBA,MAAoC;AACxE,QAAM,MAAM,MAAM,gBAAgB;AAElC,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAWA,IAAG;AAAA,EAC/B,QAAQ;AAEN,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,QAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAEA,QAAM,WAAW,OAAO;AAExB,QAAM,SAAS,gBAAgBA,MAAK,QAAQ;AAC5C,QAAM,SAAS,YAAYA,MAAK,QAAQ;AAExC,SAAO,EAAE,KAAK,QAAQ,OAAO;AAC/B;;;AD1MA,SAAS,GAAG,OAAe,QAAsB;AAC/C,UAAQ,IAAI,KAAKG,IAAG,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,GAAGA,IAAG,MAAM,UAAK,CAAC,IAAI,MAAM,EAAE;AAC1E;AAEA,SAAS,KAAK,OAAe,QAAgB,MAAqB;AAChE,UAAQ,IAAI,KAAKA,IAAG,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,GAAGA,IAAG,OAAO,KAAK,CAAC,IAAI,MAAM,EAAE;AACzE,MAAI,MAAM;AACR,YAAQ,IAAI,KAAK,GAAG,OAAO,EAAE,CAAC,OAAOA,IAAG,IAAI,IAAI,CAAC,EAAE;AAAA,EACrD;AACF;AAEA,SAAS,QAAQ,OAAe,QAAsB;AACpD,UAAQ,IAAI,KAAKA,IAAG,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,GAAGA,IAAG,IAAI,KAAK,CAAC,IAAI,MAAM,EAAE;AACxE;AAIA,SAAS,gBAAgB,KAA0E;AACjG,MAAI,IAAI,WAAW,MAAM;AACvB,YAAQ,eAAe,GAAG,IAAI,OAAO,gDAA2C;AAAA,EAClF,WAAW,IAAI,UAAU;AACvB;AAAA,MACE;AAAA,MACA,GAAG,IAAI,OAAO,WAAM,IAAI,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,EACF,OAAO;AACL,OAAG,eAAe,GAAG,IAAI,OAAO,eAAe;AAAA,EACjD;AACF;AAEA,SAAS,mBAAmB,QAA6B;AACvD,MAAI,OAAO,WAAW,GAAG;AACvB,SAAK,eAAe,sCAAiC;AACrD;AAAA,EACF;AAGA,QAAM,UAAU,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAE3D,MAAI,QAAQ,WAAW,GAAG;AACxB,OAAG,eAAe,aAAa;AAC/B;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,SAAK,eAAe,GAAG,MAAM,IAAI,YAAY,gBAAgB;AAAA,EAC/D;AACF;AAEA,SAAS,mBAAmB,QAA6B;AACvD,MAAI,OAAO,WAAW,GAAG;AACvB,SAAK,kBAAkB,sCAAiC;AACxD;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI;AACrD,MAAI,OAAO,WAAW,GAAG;AACvB,OAAG,kBAAkB,4BAA4B;AACjD;AAAA,EACF;AAEA,aAAW,SAAS,QAAQ;AAC1B,UAAM,SACJ,MAAM,WAAW,YAAY,GAAG,MAAM,IAAI,aAAa,GAAG,MAAM,IAAI;AACtE,SAAK,kBAAkB,QAAQ,gBAAgB;AAAA,EACjD;AACF;AAIA,eAAsB,UAAUC,MAA4B;AAE1D,MAAI,cAAc;AAClB,MAAI;AACF,UAAM,WAAWA,IAAG;AAAA,EACtB,QAAQ;AACN,kBAAc;AAAA,EAChB;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAID,IAAG,KAAK,uBAAkB,SAAI,OAAO,EAAE,CAAC,CAAC;AACrD,UAAQ,IAAI,EAAE;AAEd,QAAM,SAAS,MAAM,gBAAgBC,IAAG;AAExC,kBAAgB,OAAO,GAAG;AAE1B,MAAI,CAAC,aAAa;AAChB,YAAQ,IAAI,EAAE;AACd,SAAK,UAAU,qCAAqC,eAAe;AACnE,YAAQ,IAAI,EAAE;AACd;AAAA,EACF;AAEA,UAAQ,IAAI,EAAE;AACd,qBAAmB,OAAO,MAAM;AAEhC,UAAQ,IAAI,EAAE;AACd,qBAAmB,OAAO,MAAM;AAEhC,UAAQ,IAAI,EAAE;AAChB;;;AE/GA,SAAS,iBAAAC,sBAAqB;AAC9B,OAAOC,SAAQ;AAWf,eAAsB,UAAUC,MAAa,MAAoC;AAC/E,MAAI,CAAC,KAAK,OAAO,CAAC,KAAK,MAAM;AAC3B,YAAQ,MAAMC,IAAG,IAAI,yBAAyB,CAAC;AAC/C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,MAAM,WAAWD,IAAG;AACnC,QAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AAEnC,MAAI;AACF,QAAI,KAAK,MAAM;AACb,YAAM,OAAO,MAAM,GAAG,WAAW;AACjC,YAAM,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI;AAC5C,UAAI,KAAK,QAAQ;AACf,QAAAE,eAAc,KAAK,QAAQ,KAAK,MAAM;AACtC,gBAAQ,IAAID,IAAG,MAAM,+BAAqB,KAAK,MAAM,EAAE,CAAC;AAAA,MAC1D,OAAO;AACL,gBAAQ,OAAO,MAAM,GAAG;AAAA,MAC1B;AAAA,IACF;AAEA,QAAI,KAAK,KAAK;AACZ,cAAQ,MAAMA,IAAG,IAAI,sFAAiF,CAAC;AACvG,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,UAAE;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AACF;;;ACxCA,SAAS,iBAAiB;AAC1B,SAAS,cAAAE,oBAAkB;AAC3B,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAC9B,OAAOC,SAAQ;AAOf,SAAS,UAAU,OAAsBC,KAAa,SAAiB,SAAS,GAAS;AACvF,QAAM,SAAS,QAAQC,IAAG,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,MAAM;AACjE,QAAM,OAAOD,MAAKC,IAAG,MAAM,QAAG,IAAIA,IAAG,IAAI,QAAG;AAC5C,UAAQ,IAAI,SAAS,OAAO,OAAOD,MAAKC,IAAG,MAAM,OAAO,IAAIA,IAAG,IAAI,OAAO,EAAE;AAC9E;AAEA,eAAsB,UAAUC,MAA4B;AAC1D,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAWA,IAAG;AAAA,EAC/B,QAAQ;AACN,YAAQ,MAAMD,IAAG,IAAI,uCAAkC,CAAC;AACxD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,QAAQ;AAGZ,MAAI;AACJ,MAAI,OAAO,SAAS,SAAS,UAAU;AACrC,UAAM,SAAS,kBAAkB,QAAQC,MAAKC,SAAQ,CAAC;AACvD,WAAOC,aAAW,MAAM;AACxB,cAAU,eAAe,MAAM,GAAG,MAAM,YAAY;AAAA,EACtD,OAAO;AAEL,WAAO;AACP,cAAU,eAAe,MAAM,GAAG,OAAO,SAAS,IAAI,MAAM,OAAO,SAAS,iBAAiB,QAAQ,YAAY,OAAO,CAAC,aAAa;AAAA,EACxI;AACA,MAAI,CAAC,KAAM,SAAQ;AAGnB,QAAM,gBAAgB,uBAAuB,OAAO,QAAQ;AAC5D,QAAM,YAAY,cAAc;AAChC,QAAM,aAAa,CAAC,QAAQ,YAAY,cAAc,WAAW,UAAU;AAE3E,QAAM,mBAAmB,qBAAqB;AAC9C,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,OAAO,WAAW,CAAC;AACzB,UAAM,YAAYC,OAAKH,MAAK,WAAW,GAAG,IAAI,GAAG,cAAc,cAAc,EAAE;AAC/E,UAAMF,MAAKI,aAAW,SAAS;AAC/B;AAAA,MACE,MAAM,IAAI,oBAAoB;AAAA,MAC9BJ;AAAA,MACA,GAAG,IAAI,GAAG,cAAc,cAAc;AAAA,MACtC;AAAA,IACF;AACA,QAAI,CAACA,IAAI,SAAQ;AAAA,EACnB;AAGA,MAAI,OAAO,MAAM,IAAI,SAAS;AAC5B,UAAM,UAAU,cAAc;AAC9B,UAAM,UAAUM,SAAQJ,MAAK,OAAO;AACpC,UAAM,QAAQE,aAAW,OAAO;AAChC,cAAU,gBAAgB,OAAO,GAAG,OAAO,QAAQ;AACnD,QAAI,CAAC,MAAO,SAAQ;AAAA,EACtB;AAEA,MAAI,CAAC,OAAO;AACV,YAAQ,IAAI,EAAE;AACd,YAAQ,MAAMH,IAAG,IAAI,4EAAkE,CAAC;AACxF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,aAAaK,SAAQJ,MAAK,OAAO,OAAO,UAAU;AAExD,MAAI,CAACE,aAAW,UAAU,GAAG;AAC3B,YAAQ,MAAMH,IAAG,IAAI,+BAA0B,UAAU,EAAE,CAAC;AAC5D,YAAQ,MAAM,uBAAuB;AACrC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,UAAU,QAAQ,CAAC,UAAU,GAAG;AAAA,IAC7C,KAAAC;AAAA,IACA,OAAO;AAAA,IACP,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,OAAO,OAAO;AAChB,YAAQ,MAAMD,IAAG,IAAI,mCAA8B,OAAO,MAAM,OAAO,EAAE,CAAC;AAC1E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAIA,IAAG,MAAM,4BAAuB,CAAC;AAC7C,YAAQ,KAAK,CAAC;AAAA,EAChB,OAAO;AACL,YAAQ,MAAMA,IAAG,IAAI,oCAA+B,OAAO,UAAU,SAAS,GAAG,CAAC;AAClF,YAAQ,KAAK,OAAO,UAAU,CAAC;AAAA,EACjC;AACF;AAEA,SAAS,uBAAuB,UAI9B;AACA,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,EAAE,WAAW,kBAAkB,gBAAgB,OAAO,SAAS,YAAY;AAAA,IACpF,KAAK;AACH,aAAO,EAAE,WAAW,oBAAoB,gBAAgB,OAAO,SAAS,gBAAgB;AAAA,IAC1F,KAAK;AACH,aAAO,EAAE,WAAW,iBAAiB,gBAAgB,SAAS,SAAS,qBAAqB;AAAA,IAC9F,KAAK;AACH,aAAO,EAAE,WAAW,gBAAgB,gBAAgB,OAAO,SAAS,oBAAoB;AAAA,IAC1F;AACE,YAAM,IAAI,MAAM,qBAAqB,QAAkB,EAAE;AAAA,EAC7D;AACF;;;ACzHA,SAAS,cAAAM,cAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AACnE,SAAS,QAAAC,cAAY;AACrB,YAAYC,QAAO;AACnB,OAAOC,SAAQ;;;ACFf,YAAY,OAAO;AAEZ,IAAM,iBACV;AAAA,EACG,SAAO;AAAA,EACP,WAAS,0BAA0B;AAAA,EACnC,YAAU,GAAG,4CAA4C;AAAA,EACzD,YAAU,IAAI,4CAA4C;AAAA,EAC1D,OAAK;AACT;AAEK,IAAM,wBACV;AAAA,EACG,SAAO;AAAA,EACP,WAAS,yBAAyB;AAAA,EAClC,YAAU,KAAK,4CAA4C;AAAA,EAC3D,OAAK;AACT;AAEK,IAAM,iBACV;AAAA,EACG,SAAO;AAAA,EACP,WAAS,8BAA8B;AAAA,EACvC,QAAM,eAAe,4FAA4F;AAAA,EACjH,OAAK;AACT;;;AC1BF,YAAYC,QAAO;AAEZ,IAAM,kBAAoB;AAAA,EAC7B,UAAO;AAAA,EACP,YAAS,wBAAwB;AAAA,EACjC,aAAU,GAAG,0CAA0C;AAAA,EACvD,aAAU,KAAK,2CAA2C;AAC9D;AAEO,IAAM,wBAA0B;AAAA,EACnC,UAAO;AAAA,EACP,YAAS,yBAAyB;AACtC;;;ACZA,YAAYC,QAAO;AACnB,YAAYC,QAAO;AAGZ,IAAM,mBAAmB,OAC9B,QACA,WACe;AACf,SAAO,MAAM;AACX,UAAM,MAAM,MAAM,OAAO;AACzB,UAAM,SAAW,aAAU,QAAQ,GAAG;AAEtC,QAAI,OAAO,QAAS,QAAO,OAAO;AAElC,UAAM,WAAW,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI;AAC9D,IAAE,OAAI,MAAM,QAAQ;AACpB,IAAE,OAAI,KAAK,qBAAqB;AAAA,EAClC;AACF;;;AClBA,SAAS,kBAAkB;AAC3B,SAAS,cAAAC,cAAY,gBAAAC,qBAAoB;AACzC,SAAS,QAAAC,cAAY;AACrB,OAAOC,SAAQ;AAUR,SAAS,+BAA+BC,MAA4B;AACzE,MAAI;AACF,UAAMC,WAAUC,OAAKF,MAAK,cAAc;AACxC,QAAI,CAACG,aAAWF,QAAO,EAAG,QAAO;AACjC,UAAM,UAAUG,cAAaH,UAAS,MAAM;AAC5C,UAAMI,OAAM,KAAK,MAAM,OAAO;AAC9B,UAAM,OAAOA,MAAK;AAClB,QAAI,OAAO,SAAS,YAAY,KAAK,KAAK,EAAG,QAAO,KAAK,KAAK;AAC9D,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAgBO,SAAS,sBAAsBL,MAA4C;AAChF,MAAI,CAAC,wBAAwBA,IAAG,EAAG,QAAO;AAC1C,MAAI;AACF,QAAIG,aAAWD,OAAKF,MAAK,eAAe,CAAC,EAAG,QAAO;AACnD,UAAMC,WAAUC,OAAKF,MAAK,cAAc;AACxC,QAAI,CAACG,aAAWF,QAAO,EAAG,QAAO;AACjC,UAAMI,OAAM,KAAK,MAAMD,cAAaH,UAAS,MAAM,CAAC;AACpD,QAAII,MAAK,SAAS,SAAU,QAAO;AAAA,EACrC,QAAQ;AAAA,EAAC;AACT,SAAO;AACT;AAEO,SAAS,oBAAoB,QAWlB;AAChB,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,YAAY,OAAO,aAAa,WAAW;AACjD,QAAM,cAAc;AAAA,IAClB,KAAK;AAAA,IACL,OAAO,EAAE,SAAS,OAAO,aAAwB;AAAA,IACjD,UAAU;AAAA,MACR,WAAW;AAAA,MACX,eAAe;AAAA,MACf,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,EACF;AACA,QAAM,UACJ,UAAU,WACN,EAAE,GAAG,aAAa,kBAAkB,EAAE,SAAS,KAAK,GAAG,OAAO,UAAU,UAAU,IAClF,EAAE,GAAG,aAAa,kBAAkB,EAAE,SAAS,MAAM,MAAM,sBAAsB,GAAG,OAAO,SAAS,UAAU;AAEpH,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,SAAS;AAAA,MACP,MAAM,OAAO;AAAA,MACb,aAAa,OAAO;AAAA,MACpB,UAAU,OAAO;AAAA,MACjB,UAAU;AAAA,IACZ;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA,QAAQ;AAAA,MACN,YAAY;AAAA,MACZ,UAAU;AAAA,IACZ;AAAA,IACA,OAAO;AAAA,MACL,KAAK,EAAE,SAAS,MAAM,MAAM,KAAK;AAAA,MACjC,SAAS,EAAE,SAAS,MAAM,WAAW,qBAAqB;AAAA,IAC5D;AAAA,EACF;AACF;AAKA,SAAS,UAAUC,MAAqB;AACtC,SAAOA,KAAI,QAAQ,mBAAmB,EAAE;AAC1C;AAIO,SAAS,QAAQ,OAAuB;AAE7C,QAAM,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,EAAE,MAAM,CAAC;AAC/D,QAAM,SAAS,SAAI,OAAO,KAAK;AAE/B,UAAQ,IAAIC,IAAG,OAAO,SAAI,MAAM,QAAG,CAAC;AACpC,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,QAAQ,UAAU,IAAI,EAAE;AACpC,UAAM,SAAS,MAAM,IAAI,IAAI,OAAO,GAAG,IAAI;AAC3C,YAAQ,IAAIA,IAAG,OAAO,QAAG,IAAI,OAAO,SAASA,IAAG,OAAO,QAAG,CAAC;AAAA,EAC7D;AACA,UAAQ,IAAIA,IAAG,OAAO,SAAI,MAAM,QAAG,CAAC;AACtC;AAMO,SAAS,oBAAoB,aAA2B;AAC7D,QAAM,MAAM,SAAI,OAAO,EAAE;AAGzB,QAAM,QAAkB;AAAA,IACtB,KAAKA,IAAG,KAAKA,IAAG,MAAM,mBAAmB,CAAC,CAAC;AAAA,IAC3C,KAAKA,IAAG,KAAK,QAAG,CAAC,wBAAwBA,IAAG,KAAK,QAAG,CAAC;AAAA,IACrD,KAAKA,IAAG,KAAK,GAAG,CAAC;AAAA,IACjB,KAAKA,IAAG,KAAK,UAAU,CAAC,KAAK,eAAe,QAAG;AAAA,IAC/C,KAAKA,IAAG,KAAK,SAAS,CAAC,MAAMA,IAAG,MAAM,oBAAoB,CAAC;AAAA,IAC3D,KAAKA,IAAG,KAAK,GAAG,CAAC;AAAA,IACjB,KAAKA,IAAG,KAAK,aAAa,CAAC;AAAA,IAC3B,KAAKA,IAAG,KAAK,QAAG,CAAC,IAAIA,IAAG,KAAK,gCAAgC,CAAC;AAAA,IAC9D,KAAKA,IAAG,KAAK,QAAG,CAAC,IAAIA,IAAG,KAAK,iCAAiC,CAAC;AAAA,IAC/D,KAAKA,IAAG,KAAK,QAAG,CAAC,IAAIA,IAAG,KAAK,oCAAoC,CAAC;AAAA,EACpE;AAEA,UAAQ,IAAI;AACZ,UAAQ,KAAK;AACb,UAAQ,IAAI;AACd;;;AJ1GA,eAAsB,qBACpB,IACA,YACA,YACA,WACmC;AACnC,QAAM,kBAAkBC,OAAK,YAAY,YAAY,mBAAmB;AAExE,MAAI,gBAAgG,CAAC;AACrG,MAAI,cAAc;AAClB,MAAIC,aAAW,eAAe,GAAG;AAC/B,QAAI;AACF,YAAM,SAAS,KAAK,MAAMC,cAAa,iBAAiB,MAAM,CAAC;AAC/D,UAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,OAAM,IAAI,MAAM,uCAAuC;AACnF,sBAAgB;AAAA,IAClB,QAAQ;AACN,oBAAc;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,gBAAgB,YAClB;AAAA,IACE,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC7B,OAAO,UAAU;AAAA,IACjB,aAAa,UAAU;AAAA,IACvB,YAAY,UAAU;AAAA,EACxB,IACA;AAEJ,MAAI,aAAa;AAGf,QAAI,cAAe,OAAM,GAAG,oBAAoB,CAAC,aAAa,CAAC;AAAA,EACjE,OAAO;AACL,UAAM,QAAQ,gBAAgB,CAAC,GAAG,eAAe,aAAa,IAAI;AAGlE,UAAM,GAAG,oBAAoB,KAAK;AAClC,UAAM,GAAG,iBAAiB,UAAU;AAAA,EACtC;AAEA,SAAO,EAAE,YAAY;AACvB;AAEA,eAAsB,QAAQC,MAAa,OAAmC;AAC5E,QAAM,iBAAiB,eAAeA,IAAG;AACzC,MAAI,gBAAgB;AAClB,YAAQ;AAAA,MACNC,IAAG,OAAO,QAAG,IACX,MACAA,IAAG,KAAK,8BAA8B,IACtCA,IAAG,IAAI,KAAK,cAAc,GAAG;AAAA,IACjC;AACA,YAAQ,IAAI;AACZ,YAAQ,IAAIA,IAAG,IAAI,uBAAuB,CAAC;AAC3C,YAAQ;AAAA,MACN,OACEA,IAAG,KAAK,WAAW,IACnBA,IAAG,IAAI,gEAA2D;AAAA,IACtE;AACA,YAAQ,IAAI,OAAOA,IAAG,KAAK,kBAAkB,IAAIA,IAAG,IAAI,sCAAiC,CAAC;AAC1F,YAAQ;AAAA,MACN,OAAOA,IAAG,KAAK,WAAW,IAAIA,IAAG,IAAI,qDAAgD;AAAA,IACvF;AACA,YAAQ,IAAI,OAAOA,IAAG,KAAK,eAAe,IAAIA,IAAG,IAAI,4CAAuC,CAAC;AAC7F,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,eAAe,MAAM,QAAQ,+BAA+BD,IAAG;AACrE,QAAM,cAAc,gBAAgB;AACpC,sBAAoB,WAAW;AAG/B,MAAI;AACJ,MAAI,MAAM,MAAM;AACd,WAAO,MAAM;AAAA,EACf,OAAO;AACL,WAAO,MAAM,iBAAiB,YAAY;AACxC,YAAM,MAAM,MAAQ,QAAK;AAAA,QACvB,SAAS;AAAA,QACT,aAAa;AAAA,QACb,GAAI,gBAAgB,EAAE,cAAc,aAAa;AAAA,MACnD,CAAC;AACD,UAAM,YAAS,GAAG,GAAG;AACnB,QAAE,UAAO,YAAY;AACrB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,aAAO;AAAA,IACT,GAAG,cAAc;AAAA,EACnB;AAGA,QAAM,cAAc,MAAM,iBAAiB,YAAY;AACrD,UAAM,MAAM,MAAQ,QAAK;AAAA,MACvB,SAAS;AAAA,MACT,aAAa;AAAA,IACf,CAAC;AACD,QAAM,YAAS,GAAG,GAAG;AACnB,MAAE,UAAO,YAAY;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,WAAO;AAAA,EACT,GAAG,qBAAqB;AAGxB,MAAI;AACJ,MAAI,MAAM,YAAY,CAAC,eAAe,YAAY,aAAa,UAAU,EAAE,SAAS,MAAM,QAAQ,GAAG;AACnG,eAAW,MAAM;AAAA,EACnB,OAAO;AACL,UAAM,MAAM,MAAQ,UAAO;AAAA,MACzB,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,QACvC,EAAE,OAAO,eAAe,OAAO,cAAc;AAAA,QAC7C,EAAE,OAAO,aAAa,OAAO,YAAY;AAAA,QACzC,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,MACzC;AAAA,IACF,CAAC;AACD,QAAM,YAAS,GAAG,GAAG;AACnB,MAAE,UAAO,YAAY;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,eAAW;AAAA,EACb;AAaA,QAAM,oBAAoB,MAAM,wBAAwB,QAAQ;AAYhE,QAAM,mBAAmB,MAAM,uBAAuB,QAAQ;AAG9D,MAAI;AACJ,MAAI,MAAM,MAAM;AACd,eAAW,MAAM;AAAA,EACnB,OAAO;AACL,eAAW,MAAM,iBAAiB,YAAY;AAC5C,YAAM,MAAM,MAAQ,QAAK;AAAA,QACvB,SAAS;AAAA,QACT,cAAc;AAAA,MAChB,CAAC;AACD,UAAM,YAAS,GAAG,GAAG;AACnB,QAAE,UAAO,YAAY;AACrB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,aAAO;AAAA,IACT,GAAG,cAAc;AAAA,EACnB;AAGA,MAAI;AACJ,MAAI,MAAM,gBAAgB,CAAC,SAAS,QAAQ,EAAE,SAAS,MAAM,YAAY,GAAG;AAC1E,mBAAe,MAAM;AAAA,EACvB,OAAO;AACL,UAAM,MAAM,MAAQ,UAAO;AAAA,MACzB,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,OAAO,SAAS,OAAO,yDAAoD;AAAA,QAC7E;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AACD,QAAM,YAAS,GAAG,GAAG;AACnB,MAAE,UAAO,YAAY;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,mBAAe;AAAA,EACjB;AAGA,MAAI;AACJ,MAAI,MAAM,SAAS,CAAC,SAAS,QAAQ,QAAQ,EAAE,SAAS,MAAM,KAAK,GAAG;AACpE,mBAAe,MAAM;AAAA,EACvB,OAAO;AACL,UAAM,MAAM,MAAQ,UAAO;AAAA,MACzB,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,OAAO,SAAS,OAAO,4BAA4B;AAAA,QACrD,EAAE,OAAO,QAAQ,OAAO,qBAAqB;AAAA,QAC7C,EAAE,OAAO,UAAU,OAAO,uBAAuB;AAAA,MACnD;AAAA,IACF,CAAC;AACD,QAAM,YAAS,GAAG,GAAG;AACnB,MAAE,UAAO,WAAW;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,mBAAe;AAAA,EACjB;AAGA,QAAM,eAAe,MAAQ,WAAQ,EAAE,SAAS,4BAA4B,cAAc,MAAM,CAAC;AACjG,MAAM,YAAS,YAAY,GAAG;AAC5B,IAAE,UAAO,WAAW;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AAEJ,MAAI,cAAc;AAChB,UAAM,YAAY,MAAM,iBAAiB,YAAY;AACnD,YAAM,MAAM,MAAQ,QAAK,EAAE,SAAS,aAAa,CAAC;AAClD,UAAM,YAAS,GAAG,GAAG;AACnB,QAAE,UAAO,WAAW;AACpB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,aAAQ,IAAe,KAAK;AAAA,IAC9B,GAAG,eAAe;AAElB,UAAM,WAAW,MAAM,iBAAiB,YAAY;AAClD,YAAM,MAAM,MAAQ,QAAK,EAAE,SAAS,oBAAoB,aAAa,eAAe,CAAC;AACrF,UAAM,YAAS,GAAG,GAAG;AACnB,QAAE,UAAO,WAAW;AACpB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,aAAQ,IAAe,KAAK;AAAA,IAC9B,GAAG,qBAAqB;AAExB,UAAM,aAAuB,CAAC;AAC9B,IAAE,OAAI,KAAK,+DAA0D;AACrE,WAAO,MAAM;AACX,YAAM,eAAe,MAAQ,QAAK;AAAA,QAChC,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC;AACD,UAAM,YAAS,YAAY,KAAK,CAAC,gBAAgB,CAAE,aAAwB,KAAK,EAAG;AACnF,iBAAW,KAAM,aAAwB,KAAK,CAAC;AAAA,IACjD;AAEA,gBAAY,EAAE,OAAO,WAAW,aAAa,UAAU,WAAW;AAAA,EACpE;AAGA,MAAI,YAA2C;AAC/C,MAAI,6BAA4C;AAChD,QAAME,WAAY,WAAQ;AAC1B,EAAAA,SAAQ,MAAM,gBAAgB;AAE9B,MAAI;AACF,UAAM,SAAS,oBAAoB;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AACD,UAAM,eAAe,gBAAgB,QAAQ;AAE7C,UAAM,aAAaF;AAEnB,gBAAY,sBAAsBA,IAAG;AACrC,UAAM,iBAAiB,4BAA4B,SAAS;AAC5D,UAAM,aACJ,cAAc,SACV,aACA,cAAc,OACZ,WACA,cAAc,QACZ,YACA;AACV,UAAM,gBAAgB,WAAW;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,OAAO,MAAM,IAAI;AAAA,MACvB,OAAO,OAAO,QAAQ;AAAA,MACtB,WAAW,OAAO,QAAQ;AAAA,IAC5B,CAAC;AACD,IAAAG,eAAcN,OAAK,YAAY,cAAc,GAAG,eAAe,MAAM;AAIrE,IAAAO,WAAUP,OAAK,YAAY,OAAO,QAAQ,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AAGnE,UAAM,KAAK,MAAM,OAAO,QAAQ,UAAU;AAK1C,UAAM,GAAG,kBAAkB,UAAU;AAGrC,UAAM,aAAa,SAAS,QAAQ,EAAE,KAAK,YAAY,WAAW,mBAAmB,iBAAiB,CAAC;AAKvG,UAAM,EAAE,YAAY,IAAI,MAAM,qBAAqB,IAAI,YAAY,OAAO,QAAQ,KAAK,SAAS;AAChG,QAAI,aAAa;AACf,mCAA6BA,OAAK,OAAO,QAAQ,KAAK,mBAAmB;AAAA,IAC3E;AAEA,UAAM,GAAG,MAAM;AACf,IAAAK,SAAQ,KAAK,EAAE;AAAA,EACjB,SAAS,KAAK;AACZ,IAAAA,SAAQ,KAAK,QAAQ;AACrB,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,UAAM;AAAA,EACR;AAEA,MAAI,4BAA4B;AAC9B,YAAQ;AAAA,MACND,IAAG,OAAO,QAAG,IACX,eACAA,IAAG,KAAK,0BAA0B,IAClC;AAAA,IACJ;AAAA,EACF;AAEA,UAAQ,IAAIA,IAAG,MAAM,gDAA2C,CAAC;AAGjE,QAAM,wBAAkF;AAAA,IACtF,eAAe,EAAE,WAAW,mBAAmB,SAAS,YAAY;AAAA,IACpE,UAAU,EAAE,WAAW,qBAAqB,SAAS,kBAAkB;AAAA,IACvE,aAAa,EAAE,WAAW,kBAAkB,SAAS,qBAAqB;AAAA,IAC1E,YAAY,EAAE,WAAW,iBAAiB,SAAS,oBAAoB;AAAA,EACzE;AACA,QAAM,EAAE,WAAW,QAAQ,IAAI,sBAAsB,QAAQ;AAE7D,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,IAAG,MAAM,mCAA8B,SAAS,EAAE,CAAC;AAC/D,UAAQ,IAAIA,IAAG,MAAM,kBAAa,CAAC;AACnC,UAAQ,IAAIA,IAAG,MAAM,kBAAa,CAAC;AACnC,UAAQ;AAAA,IACNA,IAAG;AAAA,MACD,iBAAiB,WACb,iDACA;AAAA,IACN;AAAA,EACF;AACA,UAAQ;AAAA,IACNA,IAAG;AAAA,MACD,iBAAiB,WACb,iDACA;AAAA,IACN;AAAA,EACF;AACA,UAAQ,IAAIA,IAAG,MAAM,oCAA+B,CAAC;AACrD,UAAQ,IAAIA,IAAG,MAAM,UAAK,SAAS,SAAS,CAAC;AAC7C,UAAQ,IAAIA,IAAG,MAAM,UAAK,SAAS,aAAa,CAAC;AACjD,UAAQ,IAAIA,IAAG,MAAM,UAAK,SAAS,YAAY,CAAC;AAChD,UAAQ,IAAIA,IAAG,MAAM,UAAK,SAAS,aAAa,CAAC;AACjD,UAAQ,IAAIA,IAAG,MAAM,UAAK,OAAO,EAAE,CAAC;AACpC,UAAQ,IAAIA,IAAG,MAAM,iCAA4B,CAAC;AAElD,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,IAAG,KAAK,QAAG,IAAI,SAASA,IAAG,KAAK,WAAW,CAAC,2BAA2B;AACnF,UAAQ,IAAIA,IAAG,KAAK,QAAG,IAAI,IAAIA,IAAG,KAAK,cAAc,CAAC,2BAA2B;AACjF,UAAQ;AAAA,IACNA,IAAG,KAAK,QAAG,IACT,4CAA4CA,IAAG,KAAK,wCAAwC,CAAC;AAAA,EACjG;AAEA,QAAM,kBAA4B;AAAA,IAChC;AAAA,IACA,kBAAkBA,IAAG,KAAK,6CAA6C,CAAC;AAAA,EAC1E;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,eAAe;AACzB;;;AKnbA,YAAYI,QAAO;AACnB,OAAOC,SAAQ;AAcf,eAAsB,WAAWC,MAAa,MAAqC;AACjF,QAAM,SAAS,MAAM,WAAWA,IAAG;AAEnC,MAAI;AACJ,MAAI,KAAK,MAAM,CAAC,eAAe,YAAY,aAAa,UAAU,EAAE,SAAS,KAAK,EAAE,GAAG;AACrF,aAAS,KAAK;AAAA,EAChB,OAAO;AACL,UAAM,MAAM,MAAQ,UAAO;AAAA,MACzB,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,OAAO,eAAe,OAAO,cAAc;AAAA,QAC7C,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,QACvC,EAAE,OAAO,aAAa,OAAO,YAAY;AAAA,QACzC,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,MACzC;AAAA,IACF,CAAC;AACD,QAAM,YAAS,GAAG,GAAG;AACnB,MAAE,UAAO,YAAY;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,aAAS;AAAA,EACX;AAEA,MAAI,WAAW,OAAO,UAAU;AAC9B,YAAQ,IAAIC,IAAG,IAAI,cAAc,MAAM,6BAAwB,CAAC;AAChE;AAAA,EACF;AAQA,QAAM,oBAAoB,MAAM,wBAAwB,MAAM;AAC9D,QAAM,mBAAmB,MAAM,uBAAuB,MAAM;AAE5D,QAAMC,WAAY,WAAQ;AAC1B,EAAAA,SAAQ,MAAM,kBAAkB,OAAO,QAAQ,OAAO,MAAM,KAAK;AAEjE,MAAI;AAEF,UAAM,qBAAqB,gBAAgB,MAAM;AACjD,UAAM,mBAAmB,MAAM,QAAQF,MAAK,EAAE,mBAAmB,iBAAiB,CAAC;AAEnF,IAAAE,SAAQ,KAAKD,IAAG,MAAM,eAAe,MAAM,EAAE,CAAC;AAC9C,IAAE,OAAI,KAAK,sDAAsD,MAAM,GAAG;AAC1E,IAAE,OAAI,KAAK,qBAAqB;AAAA,EAClC,SAAS,KAAK;AACZ,IAAAC,SAAQ,KAAKD,IAAG,IAAI,kBAAkB,CAAC;AACvC,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACpEA,SAAS,cAAc,cAAAE,cAAY,aAAAC,YAAW,QAAQ,iBAAAC,sBAAqB;AAC3E,SAAS,WAAAC,gBAAe;AACxB,SAAS,WAAAC,UAAS,QAAAC,QAAM,WAAAC,gBAAe;AACvC,OAAOC,UAAQ;AAwBf,SAASC,KAAI,KAAmB;AAC9B,UAAQ,IAAI,GAAG;AACjB;AAMA,SAAS,KAAK,KAAoB;AAChC,QAAM,IAAI,MAAM,GAAG;AACrB;AAQA,SAAS,6BAA6B,QAA+B;AACnE,SAAO,OAAO,QAAQ,UAAU,UAAU,OAAO,QAAQ,iBAAiB,OAAO;AACnF;AAIA,SAAS,sBAAsB,OAA2B,QAAuBC,MAAa,SAAyB;AACrH,SAAO,UAAU,WACbC,OAAK,wBAAwB,QAAQ,OAAO,GAAG,YAAY,IAC3DC,SAAQF,MAAK,6BAA6B,MAAM,CAAC;AACvD;AAgBA,SAAS,2BAA2B,QAA+B;AACjE,SAAO,OAAO,QAAQ,UAAU,WAAW,OAAO,SAAS,SAAS,WAC/D,OAAO,QAAQ,cAAc,sBAC9B;AACN;AAMA,eAAe,kBAAkBA,MAAa,YAAoB,MAAmC;AACnG,QAAM,aAAaE,SAAQF,MAAK,YAAY,SAAS;AACrD,QAAM,OAAOC,OAAK,YAAY,gBAAe,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG,CAAC,OAAO;AAClG,MAAI;AACF,IAAAE,WAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,IAAAC,eAAc,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,MAAM,MAAM;AAAA,EAClE,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,yCAAyC,IAAI,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAEpG;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,eAAe,SAAiB,UAAwB;AAC/D,EAAAD,WAAUE,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,eAAa,SAAS,QAAQ;AAC9B,aAAW,UAAU,CAAC,QAAQ,MAAM,GAAG;AACrC,QAAIC,aAAW,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG;AACrC,mBAAa,GAAG,OAAO,GAAG,MAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,EAAE;AAAA,IAC5D;AAAA,EACF;AACA,MAAI,CAACA,aAAW,QAAQ,GAAG;AACzB,UAAM,IAAI,MAAM,6BAA6B,QAAQ,6BAA6B;AAAA,EACpF;AACF;AAEA,eAAsB,kBACpBN,MACA,MACA,UAAkBO,SAAQ,GACX;AACf,QAAM,SAAS,MAAM,WAAWP,IAAG;AACnC,QAAM,aAAa,OAAO,QAAQ;AAClC,QAAM,QAAQ,qBAAqBA,MAAK,UAAU;AAMlD,MAAI;AACJ,MAAI;AAEJ,MAAI,CAAC,OAAO;AACV,UAAM,oBAAoB,2BAA2B,MAAM;AAC3D,UAAM,YAAY,0BAA0B,SAAS,mBAAmBA,MAAK,QAAQ,OAAO;AAC5F,UAAM,aAAa,0BAA0B,UAAU,mBAAmBA,MAAK,QAAQ,OAAO;AAE9F,UAAM,aAAa,MAAM,eAAe,SAAS;AACjD,UAAM,cAAc,MAAM,eAAe,UAAU;AAEnD,QAAI,aAAa,KAAK,cAAc,GAAG;AACrC;AAAA,QACE,sFACY,SAAS,MAAM,UAAU,qBAAqB,UAAU,MAAM,WAAW;AAAA,MAGvF;AAAA,IACF;AAEA,QAAI,eAAe,KAAK,gBAAgB,GAAG;AAGzC,YAAM,KAAK,MAAM,OAAO,QAAQA,MAAK,OAAO;AAC5C,UAAI;AACF,cAAM,GAAG,kBAAkBA,IAAG;AAAA,MAChC,UAAE;AACA,cAAM,GAAG,MAAM;AAAA,MACjB;AACA,MAAAD,KAAIS,KAAG,IAAI,uHAAkH,CAAC;AAC9H;AAAA,IACF;AAKA,gBAAY,aAAa,IAAI,UAAU;AACvC,iBAAa;AACb,IAAAT;AAAA,MACES,KAAG;AAAA,QACD,yDAAyD,SAAS,qBAC5D,cAAc,UAAU,YAAY,UAAU;AAAA,MACtD;AAAA,IACF;AAAA,EACF,OAAO;AACL,gBAAY,MAAM;AAClB,iBAAa,MAAM;AAAA,EACrB;AAEA,QAAM,eAAe,OAAO,QAAQ;AACpC,QAAM,gBAAgB,OAAO,SAAS;AAGtC,MAAI,cAAc,gBAAgB,eAAe,eAAe;AAC9D,IAAAT,KAAIS,KAAG,MAAM,gDAA2C,YAAY,cAAc,aAAa,8BAAyB,CAAC;AACzH;AAAA,EACF;AAMA,MAAI,eAAe,UAAU;AAC3B;AAAA,MACE,mCAAmC,UAAU;AAAA,IAG/C;AAAA,EACF;AAGA,MAAI,kBAAkB,YAAY,eAAe,UAAU;AACzD,WAAO,iBAAiBR,MAAK,QAAQ,SAAS,WAAW,cAAc,IAAI;AAAA,EAC7E;AAIA,SAAO,oBAAoBA,MAAK,QAAQ,SAAS,WAAW,IAAI;AAClE;AAKA,eAAe,eAAe,QAAiC;AAC7D,MAAI,CAACM,aAAW,MAAM,EAAG,QAAO;AAChC,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,sBAAuB;AAC7D,QAAM,SAAS,IAAI,aAAa,MAAM;AACtC,MAAI;AACF,UAAM,OAAO,aAAa;AAC1B,UAAM,SAAS,MAAM,aAAa,MAAM;AACxC,WAAO,OAAO;AAAA,EAChB,UAAE;AACA,UAAM,OAAO,MAAM;AAAA,EACrB;AACF;AAIA,eAAe,iBACbN,MACA,QACA,SACA,WACA,SACA,MACe;AACf,QAAM,aAAa,2BAA2B,MAAM;AACpD,QAAM,QAAQ,0BAA0B,WAAW,YAAYA,MAAK,QAAQ,OAAO;AACnF,QAAM,SAAS,0BAA0B,SAAS,YAAYA,MAAK,QAAQ,OAAO;AAClF,QAAM,QAAQ,sBAAsB,WAAW,QAAQA,MAAK,OAAO;AACnE,QAAM,SAAS,sBAAsB,SAAS,QAAQA,MAAK,OAAO;AAElE,MAAI,CAACM,aAAW,KAAK,GAAG;AACtB,SAAK,gCAAgC,KAAK,cAAc,SAAS,iCAA4B;AAAA,EAC/F;AAEA,QAAM,aAAaA,aAAW,MAAM;AACpC,MAAI,YAAY;AACd,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,sBAAuB;AAC7D,UAAM,aAAa,IAAI,aAAa,MAAM;AAC1C,QAAI;AACJ,QAAI;AACF,YAAM,WAAW,aAAa;AAC9B,kBAAY,MAAM,gBAAgB,UAAU;AAAA,IAC9C,UAAE;AACA,YAAM,WAAW,MAAM;AAAA,IACzB;AACA,QAAI,CAAC,aAAa,CAAC,KAAK,OAAO;AAC7B;AAAA,QACE,gBAAgB,OAAO,KAAK,MAAM;AAAA,MAEpC;AAAA,IACF;AACA,QAAI,CAAC,aAAa,KAAK,OAAO;AAE5B,YAAM,EAAE,cAAc,OAAO,IAAI,MAAM,OAAO,sBAAuB;AACrE,YAAM,eAAe,IAAI,OAAO,MAAM;AACtC,UAAI;AACJ,UAAI;AACF,cAAM,aAAa,aAAa;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,OAAO,kBAAW;AAO9C,cAAM,QAAQ,IAAI,UAAU,cAAc,QAAQ,OAAO;AACzD,eAAO,MAAM,MAAM,WAAW;AAAA,MAChC,UAAE;AACA,cAAM,aAAa,MAAM;AAAA,MAC3B;AACA,YAAM,aAAa,MAAM,kBAAkBN,MAAK,OAAO,QAAQ,KAAK,IAAI;AACxE,MAAAD,KAAIS,KAAG,OAAO,gDAA2C,UAAU,EAAE,CAAC;AAAA,IACxE;AAAA,EACF;AAEA,MAAI,KAAK,QAAQ;AACf,IAAAT,KAAIS,KAAG,IAAI,wBAAwB,KAAK,WAAM,MAAM,WAAW,SAAS,WAAM,OAAO,yBAAyB,CAAC;AAC/G;AAAA,EACF;AAEA,iBAAe,OAAO,MAAM;AAC5B,EAAAT,KAAIS,KAAG,MAAM,0BAAqB,KAAK,WAAM,MAAM,EAAE,CAAC;AAEtD,MAAIF,aAAW,KAAK,GAAG;AACrB,IAAAH,WAAUE,SAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,iBAAa,OAAO,MAAM;AAC1B,IAAAN,KAAIS,KAAG,MAAM,4BAAuB,KAAK,WAAM,MAAM,EAAE,CAAC;AAAA,EAC1D;AAGA,SAAO,OAAO,EAAE,OAAO,KAAK,CAAC;AAC7B,SAAO,GAAG,KAAK,QAAQ,EAAE,OAAO,KAAK,CAAC;AACtC,SAAO,GAAG,KAAK,QAAQ,EAAE,OAAO,KAAK,CAAC;AACtC,MAAIF,aAAW,KAAK,KAAK,UAAU,OAAQ,QAAO,OAAO,EAAE,OAAO,KAAK,CAAC;AAGxE,QAAM,KAAK,MAAM,OAAO,QAAQN,MAAK,OAAO;AAC5C,MAAI;AACF,UAAM,GAAG,kBAAkBA,IAAG;AAAA,EAChC,UAAE;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AAEA,EAAAD,KAAIS,KAAG,MAAM,kCAA6B,SAAS,WAAM,OAAO,EAAE,CAAC;AACrE;AAIA,eAAe,oBACbR,MACA,QACA,SACA,aACA,MACe;AACf,QAAM,aAAa,2BAA2B,MAAM;AACpD,QAAM,UAAU,0BAA0B,aAAa,YAAYA,MAAK,QAAQ,OAAO;AACvF,MAAI,CAACM,aAAW,OAAO,GAAG;AACxB,SAAK,uCAAuC,OAAO,cAAc,WAAW,oCAA+B;AAAA,EAC7G;AAEA,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,sBAAuB;AAC7D,QAAM,YAAY,IAAI,aAAa,OAAO;AAC1C,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,aAAa;AAC7B,mBAAe,MAAM,aAAa,SAAS;AAC3C,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,kBAAW;AAK9C,UAAM,QAAQ,IAAI,UAAU,WAAW,QAAQ,OAAO;AACtD,iBAAa,MAAM,MAAM,WAAW;AAAA,EACtC,UAAE;AACA,UAAM,UAAU,MAAM;AAAA,EACxB;AAGA,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,OAAO,QAAQN,MAAK,OAAO;AAAA,EAC5C,SAAS,KAAK;AACZ,SAAK,qCAAqC,OAAO,SAAS,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,kCAAkC;AAAA,EACxJ;AAEA,MAAI;AACF,UAAM,aAAa,MAAM,OAAO,aAAa;AAC7C,UAAM,YAAY,OAAO,OAAO,UAAU,EAAE,MAAM,CAAC,MAAM,MAAM,CAAC;AAChE,UAAM,cAAc,OAAO,OAAO,YAAY,EAAE,MAAM,CAAC,MAAM,MAAM,CAAC;AAEpE,QAAI,CAAC,WAAW;AACd,UAAI,CAAC,KAAK,OAAO;AACf,cAAM,eAAe,CAAC;AACtB;AAAA,UACE,eACI,gBAAgB,aAAa,KAAK,8BAA8B,OAAO,SAAS,IAAI,KAAK,WAAW,KAAK,yNAGzG,gBAAgB,OAAO,SAAS,IAAI,uBAAuB,WAAW,KAAK;AAAA,QAEjF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ;AACf,MAAAD;AAAA,QACES,KAAG;AAAA,UACD,2BAA2B,aAAa,KAAK,yBAAyB,WAAW,KAAK,OAAO,QACrF,OAAO,SAAS,IAAI,GAAG,YAAY,KAAK,oEAA+D;AAAA,QACjH;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,aAA4B;AAChC,QAAI,CAAC,aAAa,KAAK,OAAO;AAC5B,YAAM,kBAAkB,MAAM,OAAO,WAAW;AAChD,mBAAa,MAAM,kBAAkBR,MAAK,OAAO,QAAQ,KAAK,eAAe;AAC7E,MAAAD,KAAIS,KAAG,OAAO,gDAA2C,UAAU,EAAE,CAAC;AAAA,IACxE;AAIA,UAAM,OAAO,iBAAiB,YAAY,OAAO,SAAS,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC;AAE7F,UAAM,OAAO,kBAAkBR,IAAG;AAElC,IAAAD;AAAA,MACES,KAAG;AAAA,QACD,mBAAc,WAAW,MAAM,MAAM,aAAa,WAAW,QAAQ,MAAM,2BACzD,WAAW,YAAO,OAAO,SAAS,IAAI;AAAA,MAC1D;AAAA,IACF;AACA,QAAI,WAAY,CAAAT,KAAIS,KAAG,IAAI,yBAAyB,UAAU,EAAE,CAAC;AACjE,IAAAT,KAAIS,KAAG,OAAO,uCAAuC,OAAO,gFAA2E,CAAC;AAAA,EAC1I,UAAE;AACA,UAAM,OAAO,MAAM;AAAA,EACrB;AACF;;;ACvZA,SAAS,QAAAC,cAAY;AACrB,OAAOC,UAAQ;AAwBf,eAAsB,qBAAqBC,MAAqC;AAC9E,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAWA,IAAG;AAAA,EAC/B,QAAQ;AACN,WAAO,EAAE,IAAI,OAAO,QAAQ,YAAY;AAAA,EAC1C;AAEA,MAAI,OAAO,aAAa,eAAe;AACrC,WAAO,EAAE,IAAI,OAAO,QAAQ,mBAAmB,UAAU,OAAO,SAAS;AAAA,EAC3E;AAEA,SAAO,EAAE,IAAI,MAAM,OAAO;AAC5B;AAWA,eAAsB,UAAUA,MAA4B;AAC1D,QAAM,MAAM,MAAM,qBAAqBA,IAAG;AAE1C,MAAI,CAAC,IAAI,IAAI;AACX,QAAI,IAAI,WAAW,aAAa;AAE9B,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,KAAKC,KAAG,KAAK,SAAS,OAAO,EAAE,CAAC,CAAC,GAAGA,KAAG,OAAO,KAAK,CAAC,oCAAoC;AACpG,cAAQ,IAAI,KAAK,GAAG,OAAO,EAAE,CAAC,OAAOA,KAAG,IAAI,eAAe,CAAC,EAAE;AAC9D,cAAQ,IAAI,EAAE;AACd;AAAA,IACF;AAEA,YAAQ;AAAA,MACNA,KAAG;AAAA,QACD,uEAAuE,IAAI,QAAQ;AAAA,MACrF;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,oBAAoB,MAAM,wBAAwB,OAAO,QAAQ;AAEvE,QAAM,SAAS,gBAAgBD,MAAK,iBAAiB,QAAQ,iBAAiB,GAAG;AAAA,IAC/E,OAAO;AAAA,IACP,YAAYE,OAAKF,MAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,EACrD,CAAC;AAED,UAAQ,IAAI,EAAE;AACd,MAAI,OAAO,YAAY,SAAS,GAAG;AACjC,YAAQ,IAAIC,KAAG,MAAM,sBAAiB,OAAO,YAAY,MAAM,qCAAqC,CAAC;AACrG,eAAW,QAAQ,OAAO,YAAa,SAAQ,IAAIA,KAAG,MAAM,YAAO,IAAI,EAAE,CAAC;AAC1E,QAAI,OAAO,WAAW;AACpB,cAAQ,IAAIA,KAAG,IAAI,uCAAkC,OAAO,SAAS,EAAE,CAAC;AAAA,IAC1E;AAAA,EACF;AACA,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,YAAQ,IAAIA,KAAG,MAAM,kBAAa,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AACjF,eAAW,QAAQ,OAAO,QAAS,SAAQ,IAAIA,KAAG,MAAM,YAAO,IAAI,EAAE,CAAC;AAAA,EACxE;AACA,UAAQ,IAAI,EAAE;AAChB;;;AC3FA,SAAS,cAAAE,cAAY,aAAa,UAAAC,eAAc;AAChD,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAC9B,YAAYC,QAAO;AACnB,OAAOC,UAAQ;AAaf,IAAM,iBAAiB,CAAC,QAAQ,YAAY,cAAc,WAAW,UAAU;AAE/E,IAAM,sBAAgD;AAAA,EACpD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AAAA,EACb,YAAY;AACd;AAIA,IAAM,qBAA+C;AAAA,EACnD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AAAA,EACb,YAAY;AACd;AAEA,eAAe,cAAcC,MAAa,UAAmC;AAC3E,QAAM,WAAW,oBAAoB,QAAQ;AAC7C,QAAM,eAAeC,SAAQD,MAAK,QAAQ;AAC1C,QAAM,WAAW,mBAAmB,QAAQ;AAE5C,MAAI,CAACE,aAAW,YAAY,GAAG;AAC7B,YAAQ,IAAIC,KAAG,OAAO,sDAAiD,YAAY,EAAE,CAAC;AACtF;AAAA,EACF;AAGA,QAAM,gBAA0B,CAAC;AACjC,MAAI;AACF,UAAM,QAAQ,YAAY,YAAY;AACtC,eAAW,KAAK,OAAO;AACrB,UAAI,EAAE,SAAS,QAAQ,KAAK,eAAe,SAAS,EAAE,QAAQ,UAAU,EAAE,CAAC,GAAG;AAC5E,sBAAc,KAAK,CAAC;AAAA,MACtB;AAAA,IACF;AAAA,EACF,QAAQ;AAEN,YAAQ,IAAIA,KAAG,OAAO,iCAA4B,YAAY,kBAAkB,CAAC;AACjF;AAAA,EACF;AAEA,MAAI,cAAc,WAAW,GAAG;AAC9B,YAAQ,IAAIA,KAAG,OAAO,gCAAgC,QAAQ,GAAG,CAAC;AAClE;AAAA,EACF;AAGA,aAAW,QAAQ,eAAe;AAChC,UAAMC,WAAU,MAAQ,WAAQ;AAAA,MAC9B,SAAS,UAAU,IAAI;AAAA,MACvB,cAAc;AAAA,IAChB,CAAC;AACD,QAAM,YAASA,QAAO,GAAG;AACvB,cAAQ,IAAID,KAAG,IAAI,sBAAsB,CAAC;AAC1C;AAAA,IACF;AACA,QAAIC,UAAS;AACX,UAAI;AACF,cAAM,WAAWC,OAAK,cAAc,IAAI;AACxC,QAAAC,QAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAChC,gBAAQ,IAAIH,KAAG,MAAM,aAAa,IAAI,EAAE,CAAC;AAAA,MAC3C,QAAQ;AACN,gBAAQ,MAAMA,KAAG,IAAI,sBAAsB,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF,OAAO;AACL,cAAQ,IAAIA,KAAG,KAAK,aAAa,IAAI,EAAE,CAAC;AAAA,IAC1C;AAAA,EACF;AACF;AAEA,eAAsB,SAASH,MAAa,MAAmC;AAC7E,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAWA,IAAG;AAAA,EAC/B,QAAQ;AACN,YAAQ,MAAMG,KAAG,IAAI,yDAAoD,CAAC;AAC1E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,aAAa,OAAO,QAAQ,OAAO;AACzC,QAAM,SAAS,OAAO,SAAS,SAAS,WAAW,kBAAkB,QAAQH,MAAKO,SAAQ,CAAC,IAAI;AAC/F,QAAM,kBAAkBN,SAAQD,MAAK,YAAY,mBAAmB;AAEpE,MAAI,UAAU;AACd,MAAI,mBAAmB;AACvB,MAAI,oBAAoB;AAKxB,MAAI,UAAUE,aAAW,MAAM,GAAG;AAChC,QAAI,KAAK,OAAO;AACd,gBAAU;AAAA,IACZ,OAAO;AACL,UAAI,OAAO,SAAS,SAAS,UAAU;AACrC,gBAAQ,IAAIC,KAAG,OAAO,6CAAwC,OAAO,SAAS,IAAI,mCAAmC,CAAC;AACtH,kBAAU;AAAA,MACZ,OAAO;AACL,cAAMC,WAAU,MAAQ,WAAQ;AAAA,UAC9B,SAAS,oBAAoB,MAAM;AAAA,UACnC,cAAc;AAAA,QAChB,CAAC;AACD,YAAM,YAASA,QAAO,GAAG;AACvB,kBAAQ,IAAID,KAAG,IAAI,sBAAsB,CAAC;AAC1C;AAAA,QACF;AACA,kBAAUC;AAAA,MACZ;AAAA,IACF;AAAA,EACF,WAAW,CAAC,QAAQ;AAClB,YAAQ,IAAID,KAAG,IAAI,qCAAgC,OAAO,SAAS,IAAI,2CAA2C,CAAC;AAAA,EACrH;AAGA,MAAID,aAAW,eAAe,GAAG;AAC/B,QAAI,KAAK,OAAO;AACd,yBAAmB;AAAA,IACrB,OAAO;AACL,YAAME,WAAU,MAAQ,WAAQ;AAAA,QAC9B,SAAS,wBAAwB,UAAU;AAAA,QAC3C,cAAc;AAAA,MAChB,CAAC;AACD,UAAM,YAASA,QAAO,GAAG;AACvB,gBAAQ,IAAID,KAAG,IAAI,sBAAsB,CAAC;AAC1C;AAAA,MACF;AACA,yBAAmBC;AAAA,IACrB;AAAA,EACF;AAGA,MAAI,KAAK,UAAU;AACjB,wBAAoB;AAAA,EACtB;AAGA,MAAI,WAAW,QAAQ;AACrB,QAAI;AACF,MAAAE,QAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;AAC9B,MAAAA,QAAO,GAAG,MAAM,QAAQ,EAAE,OAAO,KAAK,CAAC;AACvC,MAAAA,QAAO,GAAG,MAAM,QAAQ,EAAE,OAAO,KAAK,CAAC;AACvC,cAAQ,IAAIH,KAAG,MAAM,oBAAe,MAAM,EAAE,CAAC;AAAA,IAC/C,QAAQ;AACN,cAAQ,MAAMA,KAAG,IAAI,6BAAwB,MAAM,EAAE,CAAC;AAAA,IACxD;AAAA,EACF;AAEA,MAAI,kBAAkB;AACpB,QAAI;AACF,MAAAG,QAAO,iBAAiB,EAAE,OAAO,KAAK,CAAC;AACvC,cAAQ,IAAIH,KAAG,MAAM,oBAAe,UAAU,oBAAoB,CAAC;AAAA,IAErE,QAAQ;AACN,cAAQ,MAAMA,KAAG,IAAI,6BAAwB,eAAe,EAAE,CAAC;AAAA,IACjE;AAAA,EACF;AAEA,MAAI,mBAAmB;AACrB,YAAQ,IAAI,EAAE;AACd,UAAM,cAAcH,MAAK,KAAK,YAAY,aAAa;AAAA,EACzD;AAEA,MAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,mBAAmB;AACvD,YAAQ,IAAIG,KAAG,OAAO,oDAAoD,CAAC;AAC3E;AAAA,EACF;AAGA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,KAAG,MAAM,oEAA+D,CAAC;AACvF;;;AC7LA,SAAS,cAAAK,cAAY,aAAAC,YAAW,eAAAC,cAAa,gBAAAC,gBAAc,UAAU,iBAAAC,uBAAqB;AAC1F,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAC9B,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EAEA;AAAA,OACK;;;ACRP,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,QAAAC,cAAY;AAiBrB,IAAM,SAAsB,CAAC,QAAQ,YAAY,cAAc,WAAW,UAAU;AAe7E,SAAS,qBAAqBC,MAAa,QAAwC;AACxF,MAAI,OAAO,aAAa,eAAe;AACrC,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAEA,QAAM,SAAS,CAAC;AAChB,MAAI,UAAU;AAEd,aAAW,SAAS,QAAQ;AAC1B,UAAM,WAAWD,OAAKC,MAAK,WAAW,UAAU,GAAG,KAAK,KAAK;AAC7D,UAAM,SAASF,aAAW,QAAQ;AAClC,QAAI,CAAC,OAAQ,WAAU;AACvB,WAAO,KAAK,IAAI,SAAS,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,OAAO,QAAQ,eAAe;AAAA,EAC9E;AAEA,SAAO,EAAE,SAAS,OAAO;AAC3B;;;ADhCA,IAAM,UAAU;AAIhB,IAAM,QAAQ;AAAA,EACZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,MAAM,UAAU,aAAa,6BAA6B;AAAA,QACpE,OAAO;AAAA,UACL,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,UAAU,OAAO;AAAA,IAC9B;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,QAClF,aAAa;AAAA,UACX,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,MACF;AAAA,MACA,UAAU,CAAC,YAAY,eAAe,SAAS;AAAA,IACjD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU,EAAE,MAAM,UAAU,aAAa,sCAAsC;AAAA,QAC/E,SAAS,EAAE,MAAM,UAAU,aAAa,oCAAoC;AAAA,MAC9E;AAAA,MACA,UAAU,CAAC,YAAY,SAAS;AAAA,IAClC;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,MAAM,UAAU,aAAa,UAAU;AAAA,MACnD;AAAA,MACA,UAAU,CAAC,QAAQ;AAAA,IACrB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM,CAAC,WAAW,eAAe,QAAQ,SAAS;AAAA,UAClD,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,UACf,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU,aAAa,mBAAmB;AAAA,QACtD,OAAO,EAAE,MAAM,UAAU,aAAa,kBAAkB;AAAA,MAC1D;AAAA,MACA,UAAU,CAAC,MAAM,OAAO;AAAA,IAC1B;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU,aAAa,UAAU;AAAA,QAC7C,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM,CAAC,WAAW,eAAe,QAAQ,SAAS;AAAA,QACpD;AAAA,MACF;AAAA,MACA,UAAU,CAAC,MAAM,QAAQ;AAAA,IAC3B;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,aAAa,eAAe;AAAA,MACvD;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,QAClF,OAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,UACV,aAAa;AAAA,UACb,OAAO;AAAA,YACL,MAAM;AAAA,YACN,YAAY;AAAA,cACV,UAAU,EAAE,MAAM,UAAU,aAAa,6CAA6C;AAAA,cACtF,WAAW;AAAA,gBACT,MAAM;AAAA,gBACN,MAAM,CAAC,QAAQ,WAAW,YAAY,SAAS;AAAA,gBAC/C,aAAa;AAAA,cACf;AAAA,cACA,OAAO,EAAE,MAAM,UAAU,aAAa,uCAAuC;AAAA,YAC/E;AAAA,YACA,UAAU,CAAC,YAAY,WAAW;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU,CAAC,YAAY,OAAO;AAAA,IAChC;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,aAAa;AAAA,UACX,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,aAAa;AAAA,IAC1B;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,MAAM,UAAU,aAAa,UAAU;AAAA,MACnD;AAAA,MACA,UAAU,CAAC,QAAQ;AAAA,IACrB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,aAAa,0CAA0C;AAAA,QAChF,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,QACA,aAAa;AAAA,UACX,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,QACA,YAAY;AAAA,UACV,MAAM;AAAA,UACN,OAAO,EAAE,MAAM,SAAS;AAAA,UACxB,aACE;AAAA,QACJ;AAAA,MACF;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,QAClF,OAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,UACV,aAAa;AAAA,UACb,OAAO;AAAA,YACL,MAAM;AAAA,YACN,YAAY;AAAA,cACV,UAAU;AAAA,gBACR,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,cACA,UAAU;AAAA,gBACR,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,cACA,eAAe;AAAA,gBACb,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,YACF;AAAA,YACA,UAAU,CAAC,UAAU;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU,CAAC,YAAY,OAAO;AAAA,IAChC;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU,aAAa,kBAAkB;AAAA,QACrD,OAAO,EAAE,MAAM,UAAU,aAAa,uBAAuB;AAAA,QAC7D,aAAa,EAAE,MAAM,UAAU,aAAa,4CAA4C;AAAA,QACxF,YAAY;AAAA,UACV,MAAM;AAAA,UACN,OAAO,EAAE,MAAM,SAAS;AAAA,UACxB,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,MAC1D;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU,aAAa,uBAAuB;AAAA,MAC5D;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa,EAAE,MAAM,UAAU,YAAY,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,EAC9D;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa,EAAE,MAAM,UAAmB,YAAY,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,EACvE;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa,EAAE,MAAM,UAAmB,YAAY,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,EACvE;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa,EAAE,MAAM,UAAU,YAAY,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,EAC9D;AACF;AAIA,eAAsB,eAAe,QAAuBG,MAA4B;AACtF,QAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AACnC,QAAM,WAAWC,SAAQD,MAAK,OAAO,QAAQ,QAAQ;AAErD,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,qBAAqB,SAAS,QAAQ;AAAA,IAC9C,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAChC;AAEA,SAAO,kBAAkB,wBAAwB,aAAa,EAAE,OAAO,MAAM,EAAE;AAE/E,SAAO,kBAAkB,uBAAuB,OAAO,YAAY;AACjE,UAAM,EAAE,MAAM,WAAW,KAAK,IAAI,QAAQ;AAC1C,UAAM,IAAK,QAAQ,CAAC;AAEpB,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,MAAM,GAAG,IAAI,UAAUA,MAAK,MAAM;AAChE,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,aAAOE,IAAG,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,IAAI,IAAI;AAAA,IAC9E;AAAA,EACF,CAAC;AAED,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAIA,eAAe,SACb,MACA,MACA,IACA,UACAF,MACA,QACyB;AACzB,UAAQ,MAAM;AAAA,IACZ,KAAK,iBAAiB;AACpB,YAAM,SAAS,IAAI,MAAM,QAAQ;AACjC,YAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,YAAM,SAAS,MAAM,GAAG,YAAY,QAAQ,KAAK;AACjD,aAAOE,IAAG,KAAK,UAAU,EAAE,UAAU,OAAO,GAAG,CAAC,CAAC;AAAA,IACnD;AAAA,IAEA,KAAK,iBAAiB;AACpB,YAAM,WAAW,IAAI,MAAM,UAAU;AACrC,YAAM,cAAc,IAAI,MAAM,aAAa;AAC3C,YAAM,UAAU,IAAI,MAAM,SAAS;AACnC,YAAM,GAAG,aAAa,UAAU,aAAa,OAAO;AACpD,aAAOA,IAAG,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC,CAAC;AAAA,IAC9C;AAAA,IAEA,KAAK,oBAAoB;AACvB,YAAM,WAAW,IAAI,MAAM,UAAU;AACrC,YAAM,UAAU,IAAI,MAAM,SAAS;AACnC,YAAM,SAAS,MAAM,GAAG,eAAe,UAAU,OAAO;AACxD,aAAOA,IAAG,KAAK,UAAU,EAAE,QAAQ,OAAO,QAAQ,aAAa,OAAO,aAAa,CAAC,CAAC;AAAA,IACvF;AAAA,IAEA,KAAK,eAAe;AAClB,YAAM,SAAS,IAAI,MAAM,QAAQ;AACjC,YAAM,UAAU,MAAM,GAAG,kBAAkB,MAAM;AACjD,YAAM,OAAO,MAAM,QAAQ;AAAA,QACzB,QAAQ,IAAI,OAAO,MAAM;AACvB,gBAAM,WAAW,MAAM,GAAG,kBAAkB,EAAE,EAAE;AAChD,iBAAO;AAAA,YACL,IAAI,EAAE;AAAA,YACN,OAAO,EAAE;AAAA,YACT,QAAQ,EAAE;AAAA,YACV,YAAY,EAAE;AAAA,YACd,cAAc,EAAE;AAAA,YAChB,SAAS,EAAE;AAAA,YACX,UAAU,SAAS,IAAI,CAAC,OAAO;AAAA,cAC7B,IAAI,EAAE;AAAA,cACN,cAAc,EAAE;AAAA,cAChB,SAAS,EAAE;AAAA,cACX,YAAY,EAAE;AAAA,YAChB,EAAE;AAAA,UACJ;AAAA,QACF,CAAC;AAAA,MACH;AACA,aAAOA,IAAG,KAAK,UAAU,IAAI,CAAC;AAAA,IAChC;AAAA,IAEA,KAAK,aAAa;AAChB,YAAM,SAAS,KAAK,QAAQ;AAC5B,YAAM,kBAAkB,KAAK,iBAAiB;AAC9C,YAAM,QAAQ,SACV,MAAM,GAAG,SAAS,QAAsB,mBAAmB,KAAK,IAChE,MAAM,GAAG,SAAS,QAAW,mBAAmB,KAAK;AACzD,aAAOA,IAAG,KAAK,UAAU,KAAK,CAAC;AAAA,IACjC;AAAA,IAEA,KAAK,eAAe;AAClB,YAAM,KAAK,IAAI,MAAM,IAAI;AACzB,YAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,YAAMC,QAAO,MAAM,GAAG,UAAU,IAAI,KAAK;AACzC,UAAI,CAACA,OAAM;AACT,eAAOD,IAAG,KAAK,UAAU,EAAE,OAAO,wBAAwB,QAAQ,GAAG,CAAC,CAAC;AAAA,MACzE;AACA,aAAOA,IAAG,KAAK,UAAUC,KAAI,CAAC;AAAA,IAChC;AAAA,IAEA,KAAK,aAAa;AAChB,YAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,YAAM,OAAQ,KAAK,MAAM,KAA4B,QAAQ,KAAK;AAClE,YAAM,cAAc,KAAK,aAAa;AACtC,YAAM,aAAa,KAAK,YAAY;AACpC,YAAMA,QAAO,MAAM,GAAG,QAAQ,EAAE,MAAM,OAAO,aAAa,WAAW,CAAC;AACtE,aAAOD,IAAG,KAAK,UAAUC,KAAI,CAAC;AAAA,IAChC;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,KAAK,IAAI,MAAM,IAAI;AACzB,YAAM,SAAS,IAAI,MAAM,QAAQ;AACjC,UAAI,WAAW,QAAQ;AACrB,cAAM,GAAG,qBAAqB,EAAE;AAAA,MAClC;AACA,YAAMA,QAAO,MAAM,GAAG,iBAAiB,IAAI,MAAM;AACjD,aAAOD,IAAG,KAAK,UAAUC,KAAI,CAAC;AAAA,IAChC;AAAA,IAEA,KAAK,eAAe;AAClB,YAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,YAAM,UAAU,WAAW,UAAU,KAAK;AAC1C,aAAOD,IAAG,KAAK,UAAU,OAAO,CAAC;AAAA,IACnC;AAAA,IAEA,KAAK,uBAAuB;AAC1B,YAAM,WAAW,IAAI,MAAM,UAAU;AACrC,YAAM,QAAQ,cAAc,MAAM,OAAO,EAAE,IAAI,CAAC,OAAO;AAAA,QACrD,UAAU,IAAI,GAAG,UAAU;AAAA,QAC3B,WAAW,IAAI,GAAG,WAAW;AAAA,QAC7B,OAAO,EAAE,OAAO;AAAA,MAClB,EAAE;AACF,YAAM,WAAW,MAAM,GAAG,YAAY,UAAU,KAAK;AACrD,aAAOA,IAAG,KAAK,UAAU,EAAE,SAAS,CAAC,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,2BAA2B;AAC9B,YAAM,cAAc,IAAI,MAAM,aAAa;AAC3C,YAAM,GAAG,kBAAkB,WAAW;AACtC,aAAOA,IAAG,KAAK,UAAU,EAAE,aAAa,KAAK,KAAK,CAAC,CAAC;AAAA,IACtD;AAAA,IAEA,KAAK,wBAAwB;AAC3B,YAAM,SAAS,IAAI,MAAM,QAAQ;AACjC,YAAM,WAAW,MAAM,GAAG,kBAAkB,MAAM;AAClD,aAAOA,IAAG,KAAK,UAAU,QAAQ,CAAC;AAAA,IACpC;AAAA,IAEA,KAAK,uBAAuB;AAC1B,YAAM,WAAW,IAAI,MAAM,UAAU;AACrC,YAAM,QAAQ,cAAc,MAAM,OAAO,EAAE,IAAI,CAAC,OAAO;AAAA,QACrD,UAAU,IAAI,GAAG,UAAU;AAAA,QAC3B,UAAU,EAAE,UAAU;AAAA,QACtB,eAAe,EAAE,eAAe;AAAA,MAClC,EAAE;AACF,YAAM,WAAW,MAAM,GAAG,YAAY,UAAU,KAAK;AACrD,aAAOA,IAAG,KAAK,UAAU,EAAE,SAAS,CAAC,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,cAAc;AACjB,YAAM,KAAK,IAAI,MAAM,IAAI;AACzB,YAAM,QAAQ,KAAK,OAAO;AAC1B,YAAM,cAAc,KAAK,aAAa;AACtC,YAAM,aAAa,KAAK,YAAY;AAEpC,YAAMC,QAAO,MAAM,GAAG,YAAY,EAAE;AACpC,UAAI,CAACA,MAAM,QAAOD,IAAG,KAAK,UAAU,EAAE,OAAO,kBAAkB,QAAQ,GAAG,CAAC,GAAG,IAAI;AAElF,YAAM,GAAG,WAAW,IAAI;AAAA,QACtB;AAAA,QACA,aAAa,gBAAgB,SAAY,cAAc;AAAA,MACzD,CAAC;AACD,UAAI,eAAe,UAAa,eAAe,MAAM;AACnD,cAAM,GAAG,qBAAqB,IAAI,UAAU;AAAA,MAC9C;AACA,YAAM,UAAU,MAAM,GAAG,YAAY,EAAE;AACvC,aAAOA,IAAG,KAAK,UAAU,OAAO,CAAC;AAAA,IACnC;AAAA,IAEA,KAAK,iBAAiB;AACpB,YAAM,KAAK,IAAI,MAAM,IAAI;AACzB,YAAMC,QAAO,MAAM,GAAG,YAAY,EAAE;AACpC,aAAOD,IAAG,KAAK,UAAUC,KAAI,CAAC;AAAA,IAChC;AAAA,IAEA,KAAK,mBAAmB;AACtB,YAAM,KAAK,IAAI,MAAM,IAAI;AACzB,YAAMA,QAAO,MAAM,GAAG,cAAc,EAAE;AACtC,aAAOD,IAAG,KAAK,UAAUC,KAAI,CAAC;AAAA,IAChC;AAAA,IAEA,KAAK,qBAAqB;AACxB,YAAM,SAAS,qBAAqBH,MAAK,MAAM;AAC/C,aAAOE,IAAG,KAAK,UAAU,MAAM,CAAC;AAAA,IAClC;AAAA,IAEA,KAAK,iBAAiB;AACpB,YAAME,WAAUC,OAAKL,MAAK,cAAc;AACxC,UAAI,CAACM,aAAWF,QAAO,GAAG;AACxB,eAAOF,IAAG,0CAA0C,IAAI;AAAA,MAC1D;AACA,YAAMK,OAAM,KAAK,MAAMC,eAAaJ,UAAS,MAAM,CAAC;AAIpD,YAAM,WAAW;AAAA,QACf,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,QACnC,cAAcG,KAAI,gBAAgB,CAAC;AAAA,QACnC,iBAAiBA,KAAI,mBAAmB,CAAC;AAAA,MAC3C;AACA,YAAM,aAAaF,OAAKL,MAAK,UAAU;AACvC,MAAAS,WAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,MAAAC,gBAAcL,OAAK,YAAY,gBAAgB,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,MAAM;AAC3F,aAAOH;AAAA,QACL,KAAK,UAAU;AAAA,UACb,SAAS;AAAA,UACT,YAAY,SAAS;AAAA,QACvB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IAEA,KAAK,cAAc;AACjB,YAAME,WAAUC,OAAKL,MAAK,cAAc;AACxC,YAAM,WAAWK,OAAKL,MAAK,YAAY,gBAAgB;AACvD,UAAI,CAACM,aAAWF,QAAO,GAAG;AACxB,eAAOF,IAAG,0CAA0C,IAAI;AAAA,MAC1D;AACA,UAAI,CAACI,aAAW,QAAQ,GAAG;AACzB,eAAOJ;AAAA,UACL,KAAK,UAAU;AAAA,YACb,QAAQ;AAAA,YACR,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AACA,YAAMK,OAAM,KAAK,MAAMC,eAAaJ,UAAS,MAAM,CAAC;AAIpD,YAAM,OAAO,KAAK,MAAMI,eAAa,UAAU,MAAM,CAAC;AAKtD,YAAM,UAAU,EAAE,GAAID,KAAI,gBAAgB,CAAC,GAAI,GAAIA,KAAI,mBAAmB,CAAC,EAAG;AAC9E,YAAM,WAAW,EAAE,GAAI,KAAK,gBAAgB,CAAC,GAAI,GAAI,KAAK,mBAAmB,CAAC,EAAG;AAEjF,YAAM,QAAkB,CAAC;AACzB,YAAM,UAAoB,CAAC;AAC3B,YAAM,aAAgE,CAAC;AAEvE,iBAAW,CAACI,OAAM,OAAO,KAAK,OAAO,QAAQ,OAAO,GAAG;AACrD,YAAI,EAAEA,SAAQ,WAAW;AACvB,gBAAM,KAAK,GAAGA,KAAI,IAAI,OAAO,EAAE;AAAA,QACjC,OAAO;AACL,gBAAM,YAAY;AAAA,YAChB,SAASA,KAAI,EAAE,QAAQ,aAAa,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,YACzD;AAAA,UACF;AACA,gBAAM,WAAW,SAAS,QAAQ,QAAQ,aAAa,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,EAAE;AACnF,cAAI,CAAC,MAAM,SAAS,KAAK,CAAC,MAAM,QAAQ,KAAK,WAAW,WAAW;AACjE,uBAAW,KAAK,EAAE,MAAAA,OAAM,MAAM,SAASA,KAAI,GAAG,IAAI,QAAQ,CAAC;AAAA,UAC7D;AAAA,QACF;AAAA,MACF;AACA,iBAAW,WAAW,OAAO,KAAK,QAAQ,GAAG;AAC3C,YAAI,EAAE,WAAW,UAAU;AACzB,kBAAQ,KAAK,OAAO;AAAA,QACtB;AAAA,MACF;AAEA,YAAM,cAAc,MAAM,SAAS,KAAK,QAAQ,SAAS,KAAK,WAAW,SAAS;AAClF,YAAM,WAAW,cACb,8MACA;AAEJ,aAAOT;AAAA,QACL,KAAK,UAAU;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,cAAc,KAAK;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IAEA,KAAK,cAAc;AACjB,YAAM,SAAS,MAAM,gBAAgBF,IAAG;AACxC,YAAM,SAAS;AAAA,QACb,KAAK,EAAE,SAAS,OAAO,IAAI,SAAS,QAAQ,OAAO,IAAI,QAAQ,UAAU,OAAO,IAAI,SAAS;AAAA;AAAA;AAAA,QAG7F,QAAQ;AAAA,UACN,SAAS,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,UAC9E,IAAI,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,QACtE;AAAA,QACA,QAAQ;AAAA,UACN,SAAS,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,UAC9E,UAAU,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,UAChF,IAAI,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,QACtE;AAAA,MACF;AACA,aAAOE,IAAG,KAAK,UAAU,MAAM,CAAC;AAAA,IAClC;AAAA,IAEA;AACE,aAAOA,IAAG,iBAAiB,IAAI,IAAI,IAAI;AAAA,EAC3C;AACF;AAUA,SAAS,WAAW,UAAkB,OAAe,aAAa,IAAkB;AAClF,QAAM,QAAQ,MAAM,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AAC7D,QAAM,UAAwB,CAAC;AAE/B,MAAI;AACF,UAAM,QAAQ,qBAAqB,QAAQ;AAC3C,eAAW,QAAQ,OAAO;AACxB,UAAI,QAAQ,UAAU,WAAY;AAClC,UAAI;AACF,cAAM,UAAUM,eAAa,MAAM,MAAM;AACzC,cAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,gBAAM,QAAQ,MAAM,CAAC,EAAE,YAAY;AACnC,cAAI,MAAM,MAAM,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG;AACzC,oBAAQ,KAAK;AAAA,cACX,MAAM,KAAK,QAAQ,WAAW,KAAK,EAAE;AAAA,cACrC,MAAM,IAAI;AAAA,cACV,MAAM,MAAM,CAAC,EAAE,KAAK;AAAA,YACtB,CAAC;AACD,gBAAI,QAAQ,UAAU,WAAY;AAAA,UACpC;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO,CAAC,EAAE,MAAM,IAAI,MAAM,GAAG,MAAM,wBAAwB,QAAQ,GAAG,CAAC;AAAA,EACzE;AAEA,SAAO;AACT;AAEA,SAAS,qBAAqB,KAAuB;AACnD,QAAM,QAAkB,CAAC;AACzB,MAAI;AACF,eAAW,SAASI,aAAY,GAAG,GAAG;AACpC,YAAM,OAAOP,OAAK,KAAK,KAAK;AAC5B,YAAM,OAAO,SAAS,IAAI;AAC1B,UAAI,KAAK,YAAY,GAAG;AACtB,cAAM,KAAK,GAAG,qBAAqB,IAAI,CAAC;AAAA,MAC1C,WAAW,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,MAAM,GAAG;AAC1D,cAAM,KAAK,IAAI;AAAA,MACjB;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAIA,SAASH,IAAGW,OAAc,UAAU,OAAuB;AACzD,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAAA,MAAK,CAAC,GAAG,QAAQ;AAC/D;AAEA,SAAS,IAAI,MAA+B,KAAqB;AAC/D,QAAMC,KAAI,KAAK,GAAG;AAClB,MAAI,OAAOA,OAAM,SAAU,OAAM,IAAI,MAAM,GAAG,GAAG,mBAAmB;AACpE,SAAOA;AACT;AAEA,SAAS,IAAI,MAA+B,KAAqB;AAC/D,QAAMA,KAAI,KAAK,GAAG;AAClB,MAAI,OAAOA,OAAM,SAAU,OAAM,IAAI,MAAM,GAAG,GAAG,mBAAmB;AACpE,SAAOA;AACT;AAMA,SAAS,cAAc,MAA+B,KAAwC;AAC5F,QAAMA,KAAI,KAAK,GAAG;AAClB,MAAI,CAAC,MAAM,QAAQA,EAAC,KAAKA,GAAE,WAAW,GAAG;AACvC,UAAM,IAAI,MAAM,GAAG,GAAG,4BAA4B;AAAA,EACpD;AACA,aAAW,QAAQA,IAAG;AACpB,QAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,YAAM,IAAI,MAAM,GAAG,GAAG,0BAA0B;AAAA,IAClD;AAAA,EACF;AACA,SAAOA;AACT;;;AEttBA,eAAsB,SAASC,MAAa,MAAmC;AAC7E,QAAM,SAAS,MAAM,WAAWA,IAAG;AAEnC,MAAI,KAAK,MAAM;AACb,WAAO,MAAM,IAAI,OAAO,KAAK;AAAA,EAC/B;AAIA,UAAQ,OAAO,MAAM;AAAA,CAAmD;AAExE,QAAM,aAAa,qBAAqBA,MAAK,MAAM;AACnD,MAAI,CAAC,WAAW,WAAW,WAAW,QAAQ;AAC5C,UAAM,WAAW,OAAO,QAAQ,WAAW,MAAM,EAC9C,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,EACvB,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI,EACpB,KAAK,IAAI;AACZ,YAAQ,OAAO,MAAM,uDAAuD,QAAQ;AAAA,CAAoB;AAAA,EAC1G;AAEA,QAAM,eAAe,QAAQA,IAAG;AAClC;;;AC7BA,OAAO,WAAW;AAClB,OAAOC,UAAQ;AASf,IAAM,eAAsD;AAAA,EAC1D,SAAS,CAAC,MAAMC,KAAG,IAAI,CAAC;AAAA,EACxB,aAAa,CAAC,MAAMA,KAAG,KAAK,CAAC;AAAA,EAC7B,MAAM,CAAC,MAAMA,KAAG,MAAM,CAAC;AAAA,EACvB,SAAS,CAAC,MAAMA,KAAG,IAAI,CAAC;AAC1B;AAEA,eAAsB,UAAUC,MAAa,MAAoC;AAC/E,QAAM,SAAS,MAAM,WAAWA,IAAG;AACnC,QAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AAEnC,MAAI;AACF,UAAM,QAAQ,MAAM,GAAG,SAAS;AAChC,UAAM,UAAU,MAAM,GAAG,iBAAiB;AAE1C,QAAI,KAAK,MAAM;AACb,YAAM,UAAU,MAAM,QAAQ;AAAA,QAC5B,MAAM,IAAI,OAAO,OAAO;AAAA,UACtB,GAAG;AAAA,UACH,SAAS,MAAM,GAAG,kBAAkB,EAAE,EAAE;AAAA,UACxC,YAAY,MAAM,GAAG,kBAAkB,EAAE,EAAE;AAAA,QAC7C,EAAE;AAAA,MACJ;AACA,YAAM,iBAAiB,MAAM,GAAG,iBAAiB,GAAG;AACpD,cAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,SAAS,SAAS,cAAc,GAAG,MAAM,CAAC,CAAC;AAC/E;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,IAAID,KAAG,IAAI,iCAAiC,CAAC;AACrD;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,MAAM;AAAA,MACtB,MAAM,CAAC,MAAM,QAAQ,SAAS,UAAU,YAAY,SAAS,EAAE,IAAI,CAAC,MAAMA,KAAG,KAAK,CAAC,CAAC;AAAA,MACpF,OAAO,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE;AAAA,IAChC,CAAC;AAED,eAAW,KAAK,OAAO;AACrB,YAAM,UAAU,aAAa,EAAE,MAAM,MAAM,CAAC,MAAc;AAC1D,YAAM,KAAK;AAAA,QACT,OAAO,EAAE,EAAE;AAAA,QACX,EAAE;AAAA,QACF,EAAE,MAAM,MAAM,GAAG,EAAE;AAAA,QACnB,QAAQ,EAAE,MAAM;AAAA,QAChB,EAAE,eAAe;AAAA,QACjB,EAAE,aAAa,EAAE,WAAW,MAAM,GAAG,EAAE,IAAI;AAAA,MAC7C,CAAC;AAAA,IACH;AAEA,YAAQ,IAAI,MAAM,SAAS,CAAC;AAG5B,UAAM,aAAa,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,aAAa;AACjE,QAAI,WAAW,SAAS,GAAG;AACzB,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,KAAG,KAAK,iBAAiB,CAAC;AACtC,iBAAW,KAAK,YAAY;AAC1B,cAAM,UAAU,MAAM,GAAG,kBAAkB,EAAE,EAAE;AAC/C,cAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,aAAa;AAC/D,mBAAW,KAAK,QAAQ;AACtB,kBAAQ,IAAI,KAAKA,KAAG,KAAK,EAAE,MAAM,OAAO,EAAE,CAAC,CAAC,iBAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;AAAA,QAC1E;AAAA,MACF;AAAA,IACF;AAGA,YAAQ,IAAI,EAAE;AACd,UAAM,QAAQ,QAAQ,IAAI,CAAC,MAAM;AAC/B,YAAM,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC,MAAc;AACrD,aAAO,GAAG,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK;AAAA,IACpC,CAAC;AACD,YAAQ,IAAIA,KAAG,IAAI,eAAU,IAAI,MAAM,KAAKA,KAAG,IAAI,KAAK,CAAC,CAAC;AAE1D,UAAM,gBAAgB,MAAM,GAAG,iBAAiB;AAChD,QAAI,cAAc,SAAS,GAAG;AAC5B,cAAQ,IAAIA,KAAG,IAAI,GAAG,cAAc,MAAM,sDAAsD,CAAC;AAAA,IACnG;AAAA,EACF,UAAE;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AACF;;;AC3FA,SAAS,cAAAE,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,QAAAC,QAAM,WAAAC,iBAAe;AAC9B,OAAOC,UAAQ;AAYf,eAAsB,QAAQC,MAAa,MAAkC;AAC3E,QAAM,SAAS,MAAM,WAAWA,IAAG;AACnC,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,kBAAkBC,UAAQC,OAAKF,MAAK,OAAO,QAAQ,KAAK,mBAAmB,CAAC;AAElF,QAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AAEnC,MAAI;AACF,QAAI,cAAc,QAAQ,cAAc,QAAQ;AAC9C,YAAM,OAAO,iBAAiB,IAAI,KAAK,UAAU,KAAK;AAAA,IACxD;AAEA,QAAI,cAAc,SAAS,cAAc,QAAQ;AAC/C,YAAM,QAAQ,IAAIA,MAAK,KAAK,UAAU,KAAK;AAAA,IAC7C;AAAA,EACF,UAAE;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AACF;AAEA,eAAe,OACb,iBACA,IACA,QACe;AACf,MAAI,CAACG,aAAW,eAAe,GAAG;AAChC,YAAQ,IAAIC,KAAG,IAAI,kCAAkC,eAAe,0BAAqB,CAAC;AAC1F;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAMC,eAAa,iBAAiB,MAAM,CAAC;AAAA,EAC1D,SAAS,KAAK;AACZ,YAAQ,MAAMD,KAAG,IAAI,sCAAsC,GAAG,EAAE,CAAC;AACjE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,QAAQ;AACV,YAAQ,IAAIA,KAAG,KAAK,2DAAiD,CAAC;AACtE,eAAW,KAAK,OAAO;AACrB,YAAM,WAAW,MAAM,GAAG,cAAc,EAAE,IAAI;AAC9C,cAAQ,IAAI,KAAK,WAAWA,KAAG,IAAI,MAAM,IAAIA,KAAG,MAAM,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE;AAAA,IAC3E;AACA;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,GAAG,oBAAoB,KAAK;AACjD,UAAQ,IAAIA,KAAG,MAAM,mBAAc,OAAO,KAAK,WAAW,OAAO,OAAO,kBAAkB,CAAC;AAC7F;AAEA,eAAe,QACb,IACAJ,MACA,QACe;AACf,MAAI,QAAQ;AACV,UAAM,QAAQ,MAAM,GAAG,SAAS;AAChC,YAAQ,IAAII,KAAG,KAAK,4DAAkD,CAAC;AACvE,YAAQ,IAAI,KAAK,MAAM,MAAM,yBAAyB;AACtD;AAAA,EACF;AAEA,QAAM,GAAG,iBAAiBJ,IAAG;AAC7B,UAAQ,IAAII,KAAG,MAAM,4CAAuC,CAAC;AAC/D;;;AC/EA,YAAYE,QAAO;AACnB,OAAOC,UAAQ;AAQf,eAAsB,WAAWC,MAA4B;AAC3D,EAAE,SAAMC,KAAG,KAAK,mCAA8B,CAAC;AAE/C,QAAM,QAAQ,MAAM;AAAA,IAClB,YAAY;AACV,YAAM,MAAM,MAAQ,QAAK,EAAE,SAAS,aAAa,CAAC;AAClD,UAAM,YAAS,GAAG,GAAG;AAAE,QAAE,UAAO,YAAY;AAAG,gBAAQ,KAAK,CAAC;AAAA,MAAE;AAC/D,aAAQ,IAAe,KAAK;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,QAAM,cAAc,MAAM;AAAA,IACxB,YAAY;AACV,YAAM,MAAM,MAAQ,QAAK;AAAA,QACvB,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC;AACD,UAAM,YAAS,GAAG,GAAG;AAAE,QAAE,UAAO,YAAY;AAAG,gBAAQ,KAAK,CAAC;AAAA,MAAE;AAC/D,aAAQ,IAAe,KAAK;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,QAAM,aAAuB,CAAC;AAC9B,EAAE,OAAI,KAAK,+DAA0D;AACrE,SAAO,MAAM;AACX,UAAM,MAAM,MAAQ,QAAK,EAAE,SAAS,KAAK,aAAa,uCAAuC,CAAC;AAC9F,QAAM,YAAS,GAAG,KAAK,CAAC,OAAO,CAAE,IAAe,KAAK,EAAG;AACxD,eAAW,KAAM,IAAe,KAAK,CAAC;AAAA,EACxC;AAEA,QAAMC,WAAY,WAAQ;AAC1B,EAAAA,SAAQ,MAAM,WAAW;AAEzB,MAAI;AACF,UAAM,SAAS,MAAM,WAAWF,IAAG;AACnC,UAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AAEnC,UAAM,OAAO,QAAQ,KAAK;AAC1B,UAAMG,QAAO,MAAM,GAAG,QAAQ,EAAE,MAAM,OAAO,aAAa,eAAe,QAAW,WAAW,CAAC;AAChG,UAAM,GAAG,iBAAiBH,IAAG;AAC7B,UAAM,GAAG,MAAM;AAEf,IAAAE,SAAQ,KAAK,EAAE;AACf,YAAQ,IAAID,KAAG,MAAM,gBAAWE,MAAK,EAAE,iBAAYA,MAAK,IAAI,YAAY,CAAC;AACzE,YAAQ,IAAIF,KAAG,KAAK,QAAG,IAAI,MAAMA,KAAG,KAAK,YAAY,IAAI,mBAAmB;AAAA,EAC9E,SAAS,KAAK;AACZ,IAAAC,SAAQ,KAAKD,KAAG,IAAI,QAAQ,CAAC;AAC7B,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AC7DA,SAAS,aAAAG,kBAAiB;AAC1B,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,WAAAC,iBAAe;AACxB,OAAOC,UAAQ;AAKf,eAAsB,YAAYC,MAAa,UAAiC;AAC9E,QAAM,SAAS,MAAM,WAAWA,IAAG;AAGnC,MAAI,OAAO,OAAO,UAAU;AAC1B,UAAM,aAAaC,UAAQD,MAAK,OAAO,OAAO,UAAU;AACxD,QAAIE,aAAW,UAAU,GAAG;AAC1B,YAAM,SAASC,WAAU,QAAQ,CAAC,UAAU,GAAG,EAAE,KAAAH,MAAK,OAAO,QAAQ,UAAU,OAAO,CAAC;AACvF,UAAI,OAAO,WAAW,GAAG;AACvB,gBAAQ,MAAMI,KAAG,IAAI,6DAAmD,CAAC;AACzE,YAAI,OAAO,OAAQ,SAAQ,MAAM,OAAO,MAAM;AAC9C,YAAI,OAAO,OAAQ,SAAQ,MAAM,OAAO,MAAM;AAC9C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,KAAK,MAAM,OAAO,QAAQJ,IAAG;AAEnC,MAAI;AACF,UAAM,SAAS,SAAS,UAAU,EAAE;AACpC,UAAM,OAAO,CAAC,MAAM,MAAM;AAC1B,UAAMK,QAAO,OAAO,MAAM,GAAG,YAAY,MAAM,IAAI,MAAM,GAAG,cAAc,QAAQ;AAElF,QAAI,CAACA,OAAM;AACT,cAAQ,MAAMD,KAAG,IAAI,mBAAmB,QAAQ,EAAE,CAAC;AACnD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAIC,MAAK,WAAW,QAAQ;AAC1B,cAAQ,IAAID,KAAG,IAAI,SAASC,MAAK,EAAE,mBAAmB,CAAC;AACvD;AAAA,IACF;AAEA,UAAM,GAAG,iBAAiBA,MAAK,IAAI,MAAM;AACzC,UAAM,GAAG,iBAAiBL,IAAG;AAE7B,YAAQ,IAAII,KAAG,MAAM,gBAAWC,MAAK,EAAE,WAAMA,MAAK,IAAI,iBAAiB,CAAC;AAAA,EAC1E,UAAE;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AACF;;;ACjDA,YAAYC,QAAO;AACnB,OAAOC,UAAQ;AAMf,eAAsB,YAAYC,MAA4B;AAC5D,EAAE,SAAMC,KAAG,KAAK,oCAA+B,CAAC;AAEhD,QAAM,SAAS,MAAM,WAAWD,IAAG;AACnC,QAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AAEnC,MAAI;AAEF,UAAM,WAAW,MAAM,GAAG,SAAS;AACnC,UAAM,cAAc,SAAS,OAAO,OAAK,EAAE,WAAW,MAAM;AAE5D,QAAI,YAAY,WAAW,GAAG;AAC5B,MAAE,OAAI,MAAM,0BAA0B;AACtC;AAAA,IACF;AAGA,UAAM,SAAS,MAAQ,UAAO;AAAA,MAC5B,SAAS;AAAA,MACT,SAAS,YAAY,IAAI,QAAM;AAAA,QAC7B,OAAO,IAAI,EAAE,EAAE,WAAM,EAAE,KAAK,KAAK,EAAE,IAAI;AAAA,QACvC,OAAO,EAAE;AAAA,MACX,EAAE;AAAA,IACJ,CAAC;AACD,QAAM,YAAS,MAAM,GAAG;AAAE,MAAE,UAAO,YAAY;AAAG,cAAQ,KAAK,CAAC;AAAA,IAAE;AAElE,UAAME,QAAO,MAAM,GAAG,YAAY,MAAgB;AAClD,QAAI,CAACA,OAAM;AAAE,MAAE,OAAI,MAAM,gBAAgB;AAAG,cAAQ,KAAK,CAAC;AAAA,IAAE;AAG5D,UAAM,QAAQ,MAAQ,QAAK;AAAA,MACzB,SAAS;AAAA,MACT,cAAcA,MAAK;AAAA,IACrB,CAAC;AACD,QAAM,YAAS,KAAK,GAAG;AAAE,MAAE,UAAO,YAAY;AAAG,cAAQ,KAAK,CAAC;AAAA,IAAE;AAGjE,UAAM,cAAc,MAAQ,QAAK;AAAA,MAC/B,SAAS;AAAA,MACT,cAAcA,MAAK,eAAe;AAAA,IACpC,CAAC;AACD,QAAM,YAAS,WAAW,GAAG;AAAE,MAAE,UAAO,YAAY;AAAG,cAAQ,KAAK,CAAC;AAAA,IAAE;AAGvE,UAAM,oBAAoB,MAAM,GAAG,kBAAkBA,MAAK,EAAE;AAC5D,UAAM,gBAA0B,CAAC;AAEjC,IAAE,OAAI,KAAK,iFAA4E;AAGvF,aAAS,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAAK;AACjD,YAAM,KAAK,kBAAkB,CAAC;AAC9B,YAAM,MAAM,MAAQ,QAAK;AAAA,QACvB,SAAS,IAAI,IAAI,CAAC,IAAI,kBAAkB,MAAM;AAAA,QAC9C,cAAc,GAAG;AAAA,QACjB,cAAc;AAAA,MAChB,CAAC;AACD,UAAM,YAAS,GAAG,GAAG;AAAE,QAAE,UAAO,YAAY;AAAG,gBAAQ,KAAK,CAAC;AAAA,MAAE;AAC/D,YAAM,UAAW,IAAe,KAAK;AACrC,UAAI,YAAY,IAAI;AAClB,sBAAc,KAAK,OAAO;AAAA,MAC5B;AAAA,IAEF;AAGA,WAAO,MAAM;AACX,YAAM,MAAM,MAAQ,QAAK,EAAE,SAAS,4BAA4B,aAAa,0BAA0B,CAAC;AACxG,UAAM,YAAS,GAAG,KAAK,CAAC,OAAO,CAAE,IAAe,KAAK,EAAG;AACxD,oBAAc,KAAM,IAAe,KAAK,CAAC;AAAA,IAC3C;AAGA,UAAMC,WAAY,WAAQ;AAC1B,IAAAA,SAAQ,MAAM,WAAW;AAEzB,QAAI;AACF,YAAM,UAAU,QAAQ,KAAe;AACvC,YAAM,GAAG,WAAWD,MAAK,IAAI;AAAA,QAC3B;AAAA,QACA,aAAc,YAAuB,KAAK,KAAK;AAAA,QAC/C,MAAM;AAAA,MACR,CAAC;AACD,YAAM,GAAG,qBAAqBA,MAAK,IAAI,aAAa;AACpD,YAAM,GAAG,iBAAiBF,IAAG;AAE7B,MAAAG,SAAQ,KAAK,EAAE;AACf,cAAQ,IAAIF,KAAG,MAAM,gBAAWC,MAAK,EAAE,mBAAc,OAAO,EAAE,CAAC;AAAA,IACjE,SAAS,KAAK;AACZ,MAAAC,SAAQ,KAAKF,KAAG,IAAI,QAAQ,CAAC;AAC7B,MAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,UAAE;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AACF;;;ACvGA,OAAOG,YAAW;AAClB,OAAOC,UAAQ;AAcf,IAAMC,gBAAsD;AAAA,EAC1D,SAAS,CAAC,MAAMC,KAAG,IAAI,CAAC;AAAA,EACxB,aAAa,CAAC,MAAMA,KAAG,KAAK,CAAC;AAAA,EAC7B,MAAM,CAAC,MAAMA,KAAG,MAAM,CAAC;AAAA,EACvB,SAAS,CAAC,MAAMA,KAAG,IAAI,CAAC;AAC1B;AAEA,eAAsB,YAAYC,MAAa,MAAsC;AACnF,QAAM,SAAS,MAAM,WAAWA,IAAG;AACnC,QAAM,KAAK,MAAM,OAAO,QAAQA,IAAG;AAEnC,MAAI;AACF,UAAM,gBAA8B,CAAC,WAAW,eAAe,QAAQ,SAAS;AAChF,UAAM,eACJ,KAAK,UAAU,cAAc,SAAS,KAAK,MAAoB,IAC1D,KAAK,SACN;AAEN,UAAM,QAAQ,KAAK,WACf,MAAM,GAAG,iBAAiB,IAC1B,eACE,MAAM,GAAG,SAAS,cAAc,KAAK,mBAAmB,KAAK,IAC7D,MAAM,GAAG,SAAS,QAAW,KAAK,mBAAmB,KAAK;AAEhE,QAAI,KAAK,MAAM;AACb,cAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAC1C;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,GAAG;AACtB,UAAI,MAAM;AACV,UAAI,aAAc,QAAO,iBAAiB,YAAY;AACtD,UAAI,KAAK,SAAU,QAAO;AAC1B,cAAQ,IAAID,KAAG,IAAI,MAAM,GAAG,CAAC;AAC7B;AAAA,IACF;AAEA,UAAM,QAAQ,IAAIE,OAAM;AAAA,MACtB,MAAM,CAAC,MAAM,QAAQ,SAAS,QAAQ,EAAE,IAAI,CAAC,MAAMF,KAAG,KAAK,CAAC,CAAC;AAAA,MAC7D,OAAO,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE;AAAA,IAChC,CAAC;AAED,eAAW,KAAK,OAAO;AACrB,YAAM,UAAUD,cAAa,EAAE,MAAM,MAAM,CAAC,MAAc;AAC1D,YAAM,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC;AAAA,IAC5E;AAEA,YAAQ,IAAI,MAAM,SAAS,CAAC;AAE5B,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK,iBAAiB;AAC3C,YAAM,gBAAgB,MAAM,GAAG,iBAAiB;AAChD,UAAI,cAAc,SAAS,GAAG;AAC5B,gBAAQ,IAAIC,KAAG,IAAI,GAAG,cAAc,MAAM,iBAAiB,cAAc,WAAW,IAAI,MAAM,EAAE,2BAA2B,CAAC;AAAA,MAC9H;AAAA,IACF;AAAA,EACF,UAAE;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AACF;;;ACzEA,SAAS,YAAY,WAAW,eAAAG,oBAAmB;AACnD,SAAS,QAAAC,cAAY;AACrB,OAAOC,UAAQ;AAUf,IAAM,kBAAkB,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAiBvD,SAAS,oBAAoB,UAA2B;AACtD,MAAI;AACF,eAAW,UAAU,UAAU,IAAI;AACnC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOA,SAAS,cAAc,SAAuC;AAC5D,QAAM,MAAM,WAAW,QAAQ,KAAK,EAAE,SAAS,IAAI,UAAU,gBAAgB,KAAK,GAAG;AACrF,SAAO,IACJ,MAAM,GAAG,EACT,IAAI,CAAC,QAAQ,IAAI,KAAK,EAAE,YAAY,CAAC,EACrC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,EAC9B,IAAI,CAAC,QAAS,IAAI,WAAW,GAAG,IAAI,MAAM,IAAI,GAAG,EAAG;AACzD;AAmBO,SAAS,cAAc,MAAc,UAAgC,CAAC,GAAY;AACvF,QAAM;AAAA,IACJ,YAAY,QAAQ,IAAI;AAAA,IACxB,UAAU,QAAQ,IAAI;AAAA,IACtB,WAAW,QAAQ;AAAA,IACnB,eAAe;AAAA,EACjB,IAAI;AAEJ,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,YAAY,aAAa;AAC/B,QAAM,MAAM,YAAY,MAAM;AAC9B,QAAM,OAAO,UAAU,MAAM,GAAG,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;AAChE,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,MAAI,WAAW;AACb,UAAM,YAAY,KAAK,YAAY;AAGnC,UAAMC,cAAa,oBAAI,IAAY,CAAC,WAAW,GAAG,cAAc,OAAO,EAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,GAAG,GAAG,EAAE,CAAC,CAAC;AAC5G,eAAW,OAAO,MAAM;AACtB,UAAI;AACJ,UAAI;AACF,kBAAUC,aAAY,GAAG;AAAA,MAC3B,QAAQ;AAEN;AAAA,MACF;AACA,iBAAW,SAAS,SAAS;AAC3B,YAAID,YAAW,IAAI,MAAM,YAAY,CAAC,EAAG,QAAO;AAAA,MAClD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,aAAW,OAAO,MAAM;AACtB,QAAI;AACF,UAAI,aAAaE,OAAK,KAAK,IAAI,CAAC,EAAG,QAAO;AAAA,IAC5C,QAAQ;AAEN;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,mBAAmB,MAAuB;AACxD,SAAO,cAAc,IAAI;AAC3B;AAYO,SAAS,kCAAwC;AACtD,UAAQ,MAAMC,KAAG,OAAO,0CAAqC,CAAC;AAC9D,UAAQ,MAAMA,KAAG,IAAI,2EAA2E,CAAC;AACjG,UAAQ,MAAMA,KAAG,IAAI,6EAA6E,CAAC;AACnG,UAAQ,MAAMA,KAAG,IAAI,oFAA+E,CAAC;AACrG,UAAQ,MAAMA,KAAG,IAAI,mBAAmB,IAAI,IAAI,uBAAuB,CAAC;AACxE,UAAQ,MAAMA,KAAG,IAAI,iCAAiC,IAAI,IAAI,sCAAsC,CAAC;AACvG;;;AC5IA,OAAOC,UAAQ;AAMf,IAAMC,gBAAe,8BAA8B,IAAI,IAAI;AAC3D,IAAMC,cAAa;AAOZ,SAAS,eAAe,gBAAoD;AACjF,SAAO,IAAI,QAAQ,CAACC,cAAY;AAC9B,UAAM,QAAQ,WAAW,MAAMA,UAAQ,IAAI,GAAGD,WAAU;AAExD,UAAMD,aAAY,EACf,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EACxB,KAAK,CAAC,SAAS;AACd,mBAAa,KAAK;AAClB,YAAM,SAAU,KAA6B;AAC7C,MAAAE,UAAQC,SAAQ,QAAQ,cAAc,IAAI,EAAE,SAAS,gBAAgB,OAAO,IAAI,IAAI;AAAA,IACtF,CAAC,EACA,MAAM,MAAM;AACX,mBAAa,KAAK;AAClB,MAAAD,UAAQ,IAAI;AAAA,IACd,CAAC;AAAA,EACL,CAAC;AACH;AAEO,SAAS,mBAAmB,EAAE,SAAS,OAAO,GAAqB;AACxE,QAAM,QAAQ;AAAA,IACZ,sBAAsBE,KAAG,IAAI,OAAO,CAAC,WAAMA,KAAG,MAAM,MAAM,CAAC;AAAA,IAC3D,UAAUA,KAAG,KAAK,UAAU,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;AAAA,EACnD;AAEA,UAAQ,KAAK;AACf;AAEA,SAASD,SAAQ,QAAgB,SAA0B;AACzD,QAAM,QAAQ,CAACE,OAAcA,GAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AACpD,QAAM,CAAC,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM;AACvC,QAAM,CAAC,MAAM,MAAM,IAAI,IAAI,MAAM,OAAO;AAExC,MAAI,SAAS,KAAM,QAAO,OAAO;AACjC,MAAI,SAAS,KAAM,QAAO,OAAO;AAEjC,SAAO,OAAO;AAChB;;;A3C7BA,IAAM,MAAM,QAAQ,IAAI;AAaxB,SAAS,UAAU,KAAqB;AACtC,QAAM,UAAU,IAAI,KAAK;AACzB,QAAM,YAAY;AAClB,MAAI,CAAC,QAAQ,KAAK,OAAO,GAAG;AAC1B,UAAM,IAAI,qBAAqB,UAAU,SAAS,eAAe,GAAG,KAAK;AAAA,EAC3E;AACA,QAAM,OAAO,OAAO,OAAO;AAC3B,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AACvD,UAAM,IAAI,qBAAqB,UAAU,SAAS,eAAe,GAAG,KAAK;AAAA,EAC3E;AACA,SAAO;AACT;AAEA,IAAM,cAAc,eAAe,IAAI,OAAO;AAE9C,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,KAAK,EACV,YAAY,0EAAqE,EACjF,QAAQ,IAAI,SAAS,eAAe;AAGvC,QACG,QAAQ,MAAM,EACd,YAAY,2DAA2D,EACvE,OAAO,iBAAiB,4BAA4B,EACpD,OAAO,yBAAyB,0EAA0E,EAC1G,OAAO,iBAAiB,gCAAgC,EACxD,OAAO,qBAAqB,mDAAmD,EAC/E,OAAO,2BAA2B,6CAA6C,EAC/E,OAAO,OAAO,SAAS;AACtB,QAAM,QAAQ,KAAK,IAAI;AACzB,CAAC;AAGH,QACG,QAAQ,OAAO,EACf,YAAY,0EAA0E,EACtF,OAAO,WAAW,2BAA2B,EAC7C,OAAO,UAAU,+FAA+F,EAChH;AAAA,EACC;AAAA,EACA;AAEF,EACC,OAAO,OAAO,SAAS;AACtB,QAAM,SAAS,KAAK,IAAI;AAC1B,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,iCAAiC,EAC7C,OAAO,YAAY;AAClB,QAAM,UAAU,GAAG;AACrB,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,oCAAoC,EAChD,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,SAAS;AACtB,QAAM,UAAU,KAAK,IAAI;AAC3B,CAAC;AAGH,QACG,QAAQ,MAAM,EACd,YAAY,sCAAiC,EAC7C,OAAO,aAAa,yCAAyC,EAC7D,OAAO,2BAA2B,iCAAiC,EACnE,OAAO,OAAO,SAAS;AACtB,QAAM,QAAQ,KAAK,EAAE,QAAQ,KAAK,SAAS,GAAG,WAAW,KAAK,UAAU,CAAC;AAC3E,CAAC;AAGH,QACG,QAAQ,OAAO,EACf,YAAY,8BAA8B,EAC1C,OAAO,iBAAiB,8CAA8C,SAAS,EAC/E,OAAO,OAAO,SAAS;AACtB,QAAM,SAAS,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;AACzC,CAAC;AAGH,IAAM,OAAO,QAAQ,QAAQ,MAAM,EAAE,YAAY,cAAc;AAE/D,KACG,QAAQ,KAAK,EACb,YAAY,0BAA0B,EACtC,OAAO,YAAY;AAClB,QAAM,WAAW,GAAG;AACtB,CAAC;AAEH,KACG,QAAQ,MAAM,EACd,YAAY,YAAY,EACxB,OAAO,qBAAqB,0DAA0D,EACtF,OAAO,cAAc,0BAA0B,EAC/C,OAAO,sBAAsB,oCAAoC,EACjE,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,SAAS;AACtB,QAAM,YAAY,KAAK,IAAI;AAC7B,CAAC;AAEH,KACG,QAAQ,gBAAgB,EACxB,YAAY,qBAAqB,EACjC,OAAO,OAAO,aAAqB;AAClC,QAAM,YAAY,KAAK,QAAQ;AACjC,CAAC;AAEH,KACG,QAAQ,MAAM,EACd,YAAY,2BAA2B,EACvC,OAAO,YAAY;AAClB,QAAM,YAAY,GAAG;AACvB,CAAC;AAGH,QACG,QAAQ,WAAW,EACnB,YAAY,8CAA8C,EAC1D,OAAO,qBAAqB,qBAAqB,WAAW,IAAI,EAChE,OAAO,aAAa,mCAAmC,EACvD,OAAO,OAAO,SAA0C;AACvD,QAAM,aAAa,KAAK,EAAE,MAAM,KAAK,MAAM,MAAM,KAAK,KAAK,CAAC;AAC9D,CAAC;AAaH,IAAM,UAAU,QACb,QAAQ,SAAS,EACjB,YAAY,8FAA8F;AAE7G,QACG,QAAQ,UAAU,EAClB,YAAY,yDAAyD,EACrE,OAAO,mBAAmB,gEAAgE,EAC1F,OAAO,OAAO,SAAS;AACtB,QAAM,WAAW,KAAK,IAAI;AAC5B,CAAC;AAEH,QACG,QAAQ,SAAS,EACjB;AAAA,EACC;AACF,EACC,OAAO,WAAW,2EAA2E,EAC7F,OAAO,aAAa,yDAAyD,EAC7E,OAAO,OAAO,SAAS;AACtB,MAAI;AACF,UAAM,kBAAkB,KAAK,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,SAAS,EAAE,CAAC;AAAA,EAC7E,SAAS,KAAK;AACZ,YAAQ,MAAMC,KAAG,IAAI,UAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE,CAAC;AAC7E,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,qBAAqB,EACjC,OAAO,SAAS,UAAU,EAC1B,OAAO,UAAU,kCAAkC,EACnD,OAAO,mBAAmB,oCAAoC,EAC9D,OAAO,OAAO,SAAS;AACtB,QAAM,UAAU,KAAK,IAAI;AAC3B,CAAC;AAIH,QACG,QAAQ,OAAO,EACf,YAAY,0DAA0D,EACtE,OAAO,WAAW,2BAA2B,EAC7C,OAAO,wDAAwD,6CAA6C,EAC5G,OAAO,OAAO,SAAS;AACtB,QAAM,SAAS,KAAK,IAAI;AAC1B,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,gEAAgE,EAC5E,OAAO,YAAY;AAClB,QAAM,UAAU,GAAG;AACrB,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,sGAAsG,EAClH,OAAO,YAAY;AAClB,QAAM,UAAU,GAAG;AACrB,CAAC;AAOH,QAAQ,KAAK,aAAa,MAAM;AAC9B,MAAI,CAAC,wBAAwB,GAAG,GAAG;AACjC,6BAAyB;AAIzB,QAAI,CAAC,mBAAmB,KAAK,GAAG;AAC9B,sCAAgC;AAAA,IAClC;AAAA,EACF;AACF,CAAC;AAED,QAAQ,KAAK,cAAc,YAAY;AACrC,QAAM,SAAS,MAAM;AACrB,MAAI,OAAQ,oBAAmB,MAAM;AACvC,CAAC;AAOD,SAAS,yBAAyB,MAA0B;AAC1D,QAAM,aAAa,KAAK,QAAQ,SAAS;AACzC,MAAI,eAAe,GAAI,QAAO;AAC9B,QAAM,OAAO,KAAK,aAAa,CAAC;AAChC,QAAM,eAAe,SAAS,UAAa,SAAS;AACpD,MAAI,CAAC,aAAc,QAAO;AAC1B,QAAM,YAAY,CAAC,GAAG,IAAI;AAC1B,YAAU,OAAO,aAAa,GAAG,GAAG,UAAU;AAC9C,SAAO;AACT;AAEA,QAAQ,MAAM,yBAAyB,QAAQ,IAAI,CAAC;","names":["pc","p","pc","existsSync","join","cwd","existsSync","readFileSync","join","existsSync","join","join","require","p","cwd","join","existsSync","pkgPath","cwd","existsSync","join","pkgPath","pkg","readFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","cwd","dirname","existsSync","mkdirSync","readFileSync","writeFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","resolve","fileURLToPath","readFileSync","dirname","join","fileURLToPath","dirname","fileURLToPath","join","readFileSync","v","__dirname","dirname","fileURLToPath","cwd","existsSync","join","mkdirSync","resolve","writeFileSync","readFileSync","cwd","existsSync","join","existsSync","mkdirSync","writeFileSync","join","resolve","cwd","write","join","mkdirSync","resolve","writeFileSync","existsSync","existsSync","mkdirSync","writeFileSync","join","resolve","cwd","write","join","mkdirSync","resolve","writeFileSync","existsSync","existsSync","mkdirSync","writeFileSync","join","resolve","cwd","write","join","mkdirSync","resolve","writeFileSync","existsSync","p","AGENT_LABELS","cwd","spinner","pc","dirname","join","fileURLToPath","pc","watch","existsSync","readFileSync","join","resolve","readFileSync","resolve","task","join","existsSync","watch","__dirname","dirname","fileURLToPath","cwd","join","pc","pc","existsSync","readFileSync","dirname","join","fileURLToPath","__dirname","dirname","fileURLToPath","v","join","existsSync","cwd","__dirname","readFileSync","pc","cwd","writeFileSync","pc","cwd","pc","writeFileSync","existsSync","homedir","join","resolve","pc","ok","pc","cwd","homedir","existsSync","join","resolve","existsSync","mkdirSync","readFileSync","writeFileSync","join","p","pc","v","p","v","existsSync","readFileSync","join","pc","cwd","pkgPath","join","existsSync","readFileSync","pkg","str","pc","join","existsSync","readFileSync","cwd","pc","spinner","writeFileSync","mkdirSync","p","pc","cwd","pc","spinner","existsSync","mkdirSync","writeFileSync","homedir","dirname","join","resolve","pc","log","cwd","join","resolve","mkdirSync","writeFileSync","dirname","existsSync","homedir","pc","join","pc","cwd","pc","join","existsSync","rmSync","homedir","join","resolve","p","pc","cwd","resolve","existsSync","pc","confirm","join","rmSync","homedir","existsSync","mkdirSync","readdirSync","readFileSync","writeFileSync","join","resolve","existsSync","join","cwd","cwd","resolve","ok","task","pkgPath","join","existsSync","pkg","readFileSync","mkdirSync","writeFileSync","name","readdirSync","text","v","cwd","pc","pc","cwd","existsSync","readFileSync","join","resolve","pc","cwd","resolve","join","existsSync","pc","readFileSync","p","pc","cwd","pc","spinner","task","spawnSync","existsSync","resolve","pc","cwd","resolve","existsSync","spawnSync","pc","task","p","pc","cwd","pc","task","spinner","Table","pc","STATUS_COLOR","pc","cwd","Table","readdirSync","join","pc","candidates","readdirSync","join","pc","pc","REGISTRY_URL","TIMEOUT_MS","resolve","isNewer","pc","v","pc"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/build.ts","../src/core/materializer/claude-code.ts","../src/utils/file.ts","../src/core/materializer/detect-package-manager.ts","../src/core/local-install-guard.ts","../src/core/package-data.ts","../src/core/materializer/mcp-merge.ts","../src/core/materializer/scaffold-utils.ts","../src/core/materializer/templates.ts","../src/core/materializer/agent-restrictions.ts","../src/core/materializer/codex-cli.ts","../src/core/materializer/grok.ts","../src/core/materializer/opencode.ts","../src/core/materializer/index.ts","../src/commands/claude-model-prompt.ts","../src/commands/codex-model-prompt.ts","../src/commands/dashboard.ts","../src/core/dashboard-server.ts","../src/core/port-utils.ts","../src/commands/doctor.ts","../src/core/doctor.ts","../src/commands/export.ts","../src/commands/health.ts","../src/commands/init.ts","../src/schema/init.ts","../src/schema/task.ts","../src/utils/form.ts","../src/commands/init-helpers.ts","../src/commands/migrate.ts","../src/commands/migrate-storage.ts","../src/commands/models.ts","../src/commands/reset.ts","../src/core/mcp-server.ts","../src/core/permissions-check.ts","../src/commands/serve.ts","../src/commands/status.ts","../src/commands/sync.ts","../src/commands/task/add.ts","../src/commands/task/done.ts","../src/commands/task/edit.ts","../src/commands/task/list.ts","../src/core/path-probe.ts","../src/core/update-check.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from 'commander'\nimport pc from 'picocolors'\n\nimport { runBuild } from '@/commands/build'\nimport { runDashboard } from '@/commands/dashboard'\nimport { runDoctor } from '@/commands/doctor'\nimport { runExport } from '@/commands/export'\nimport { runHealth } from '@/commands/health'\nimport { runInit } from '@/commands/init'\nimport { runMigrate } from '@/commands/migrate'\nimport { runMigrateStorage } from '@/commands/migrate-storage'\nimport { runModels } from '@/commands/models'\nimport { runReset } from '@/commands/reset'\nimport { runServe } from '@/commands/serve'\nimport { runStatus } from '@/commands/status'\nimport { runSync } from '@/commands/sync'\nimport { runTaskAdd, runTaskDone, runTaskEdit, runTaskList } from '@/commands/task/index'\nimport { isLocalInstallSatisfied, printLocalInstallWarning } from '@/core/local-install-guard'\nimport { pkg } from '@/core/package-data'\nimport { isExecutableOnPath, printMissingGlobalBinaryWarning } from '@/core/path-probe'\nimport { checkForUpdate, printUpdateMessage } from '@/core/update-check'\n\nconst cwd = process.cwd()\n\n/**\n * Strict CLI-boundary coercion for `--port`. Shared by every command that\n * accepts a port so the validation (and the user-facing error) is identical\n * everywhere. Rejects anything that is not a base-10 integer in 1..65535:\n * - non-numeric ('abc'), empty/whitespace, and trailing garbage ('4242abc')\n * are refused (plain `parseInt` would silently accept '4242abc' as 4242),\n * - out-of-range values (0, negatives, 65536+) are refused.\n * Throwing commander's `InvalidArgumentError` makes commander print a clean\n * `error: option '--port <port>' argument '<val>' is invalid. …` and exit\n * non-zero with no stack trace.\n */\nfunction parsePort(raw: string): number {\n const trimmed = raw.trim()\n const rangeHint = 'must be an integer between 1 and 65535'\n if (!/^\\d+$/.test(trimmed)) {\n throw new InvalidArgumentError(`--port ${rangeHint} (received \"${raw}\").`)\n }\n const port = Number(trimmed)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new InvalidArgumentError(`--port ${rangeHint} (received \"${raw}\").`)\n }\n return port\n}\n\nconst updateCheck = checkForUpdate(pkg.version)\n\nconst program = new Command()\n\nprogram\n .name('ahk')\n .description('agent-harness-kit — CLI scaffolding for multi-agent harness systems')\n .version(pkg.version, '-v, --version')\n\n// ─── init ─────────────────────────────────────────────────────────────────────\nprogram\n .command('init')\n .description('Scaffold a harness interactively in the current directory')\n .option('--name <name>', 'Project name (skip prompt)')\n .option('--provider <provider>', 'AI provider: claude-code | opencode | codex-cli | grok-cli (skip prompt)')\n .option('--docs <path>', 'Docs folder path (skip prompt)')\n .option('--tasks <adapter>', 'Task adapter: local | jira | linear (skip prompt)')\n .option('--storage-scope <scope>', 'Storage scope: local | global (skip prompt)')\n .action(async (opts) => {\n await runInit(cwd, opts)\n })\n\n// ─── build ────────────────────────────────────────────────────────────────────\nprogram\n .command('build')\n .description('Regenerate AGENTS.md and provider files from agent-harness-kit.config.ts')\n .option('--watch', 'Rebuild on config changes')\n .option('--sync', 'Sync tools: frontmatter in existing .claude/agents/*.md to match current permission constants')\n .option(\n '--force',\n 'Regenerate agent files that already exist, DESTROYING your customizations (a backup is written first). ' +\n 'Without this flag, build only creates agent files that are missing and never modifies existing ones.',\n )\n .action(async (opts) => {\n await runBuild(cwd, opts)\n })\n\n// ─── health ───────────────────────────────────────────────────────────────────\nprogram\n .command('health')\n .description('Run health.sh and report result')\n .action(async () => {\n await runHealth(cwd)\n })\n\n// ─── status ───────────────────────────────────────────────────────────────────\nprogram\n .command('status')\n .description('Show task table and active actions')\n .option('--json', 'Output as JSON')\n .action(async (opts) => {\n await runStatus(cwd, opts)\n })\n\n// ─── sync ─────────────────────────────────────────────────────────────────────\nprogram\n .command('sync')\n .description('Sync feature_list.json ↔ SQLite')\n .option('--dry-run', 'Show what would change without applying')\n .option('--direction <direction>', 'in | out | both (default: both)')\n .action(async (opts) => {\n await runSync(cwd, { dryRun: opts['dry-run'], direction: opts.direction })\n })\n\n// ─── serve ────────────────────────────────────────────────────────────────────\nprogram\n .command('serve')\n .description('Start the MCP server (stdio)')\n .option('--port <port>', 'Port hint stored in config (default: 3742)', parsePort)\n .action(async (opts) => {\n await runServe(cwd, { port: opts.port })\n })\n\n// ─── task ─────────────────────────────────────────────────────────────────────\nconst task = program.command('task').description('Manage tasks')\n\ntask\n .command('add')\n .description('Add a task interactively')\n .action(async () => {\n await runTaskAdd(cwd)\n })\n\ntask\n .command('list')\n .description('List tasks')\n .option('--status <status>', 'Filter by status: pending | in_progress | done | blocked')\n .option('--archived', 'Show only archived tasks')\n .option('--include-archived', 'Include archived tasks in the list')\n .option('--json', 'Output as JSON')\n .action(async (opts) => {\n await runTaskList(cwd, opts)\n })\n\ntask\n .command('done <id|slug>')\n .description('Mark a task as done')\n .action(async (idOrSlug: string) => {\n await runTaskDone(cwd, idOrSlug)\n })\n\ntask\n .command('edit')\n .description('Edit a task interactively')\n .action(async () => {\n await runTaskEdit(cwd)\n })\n\n// ─── dashboard ────────────────────────────────────────────────────────────────\nprogram\n .command('dashboard')\n .description('Open web dashboard to visualize harness data')\n .option('-p, --port <port>', 'Port to listen on', parsePort, 4242)\n .option('--no-open', 'Do not open browser automatically')\n .action(async (opts: { port: number; open: boolean }) => {\n await runDashboard(cwd, { port: opts.port, open: opts.open })\n })\n\n// ─── migrate ──────────────────────────────────────────────────────────────────\n// `ahk migrate` is a pure router (no options/action of its own — commander\n// does not reliably support an identical flag declared on both a parent\n// command and its subcommand, see the argv rewrite below) with two\n// subcommands:\n// - `migrate provider --to <x>` — migrate provider-specific scaffold files.\n// - `migrate storage [--force] [--dry-run]` — migrate harness DB storage\n// (local↔global scope, sqlite↔postgres/mysql). See migrate-storage.ts.\n// `ahk migrate --to <x>` (no subcommand) and bare `ahk migrate` are kept as\n// backward-compatible aliases for `migrate provider [--to <x>]` — see the\n// argv rewrite just before `program.parse()` below.\nconst migrate = program\n .command('migrate')\n .description('Migrate provider files to a different provider, or migrate harness storage (see subcommands)')\n\nmigrate\n .command('provider')\n .description('Migrate provider-specific files to a different provider')\n .option('--to <provider>', 'Target provider: claude-code | opencode | codex-cli | grok-cli')\n .action(async (opts) => {\n await runMigrate(cwd, opts)\n })\n\nmigrate\n .command('storage')\n .description(\n 'Migrate harness DB storage between local/global scope or sqlite/postgres/mysql, based on agent-harness-kit.config.ts vs the real current state',\n )\n .option('--force', 'Required to overwrite a non-empty destination (a backup is written first)')\n .option('--dry-run', 'Preview what would migrate without applying any changes')\n .action(async (opts) => {\n try {\n await runMigrateStorage(cwd, { force: opts.force, dryRun: opts['dry-run'] })\n } catch (err) {\n console.error(pc.red(`✗ ${err instanceof Error ? err.message : String(err)}`))\n process.exit(1)\n }\n })\n\n// ─── export ───────────────────────────────────────────────────────────────────\nprogram\n .command('export')\n .description('Export the database')\n .option('--sql', 'SQL dump')\n .option('--json', 'JSON export of tasks and actions')\n .option('--output <path>', 'Output file path (default: stdout)')\n .action(async (opts) => {\n await runExport(cwd, opts)\n })\n\n\n// ─── reset ────────────────────────────────────────────────────────────────────\nprogram\n .command('reset')\n .description('Reset/clear harness data (DB, feature list, agent files)')\n .option('--force', 'Skip confirmation prompts')\n .option('--provider <claude-code|opencode|codex-cli|grok-cli>', 'Reset agent MD files for specified provider')\n .action(async (opts) => {\n await runReset(cwd, opts)\n })\n\n// ─── doctor ───────────────────────────────────────────────────────────────────\nprogram\n .command('doctor')\n .description('Check lib version, agent files, and harness skills sync status')\n .action(async () => {\n await runDoctor(cwd)\n })\n\n// ─── models ───────────────────────────────────────────────────────────────────\nprogram\n .command('models')\n .description('Re-prompt per-role Claude Code models and regenerate .claude/agents/*.md (claude-code projects only)')\n .action(async () => {\n await runModels(cwd)\n })\n\n// Prints a non-blocking warning (but not for --version/--help, which\n// commander handles without invoking actions) when the package is only\n// installed globally and not available in the project's local\n// node_modules. This is purely informational — the command continues\n// its normal flow regardless of the check's result.\nprogram.hook('preAction', () => {\n if (!isLocalInstallSatisfied(cwd)) {\n printLocalInstallWarning()\n // Global-install path only: the generated MCP config launches the bare\n // `ahk serve` command, so warn early (never block) if `ahk` is not\n // resolvable on PATH and would therefore fail later at spawn time.\n if (!isExecutableOnPath('ahk')) {\n printMissingGlobalBinaryWarning()\n }\n }\n})\n\nprogram.hook('postAction', async () => {\n const update = await updateCheck\n if (update) printUpdateMessage(update)\n})\n\n// ─── backward-compat argv rewrite for `ahk migrate` ────────────────────────\n// Bare `ahk migrate` and `ahk migrate --to <x>` (no subcommand token) must\n// keep working exactly as before subcommands were introduced — rewrite them\n// to `ahk migrate provider [--to <x>]` before commander parses argv.\n// `ahk migrate provider ...` and `ahk migrate storage ...` are untouched.\nfunction rewriteLegacyMigrateArgv(argv: string[]): string[] {\n const migrateIdx = argv.indexOf('migrate')\n if (migrateIdx === -1) return argv\n const next = argv[migrateIdx + 1]\n const isLegacyForm = next === undefined || next === '--to'\n if (!isLegacyForm) return argv\n const rewritten = [...argv]\n rewritten.splice(migrateIdx + 1, 0, 'provider')\n return rewritten\n}\n\nprogram.parse(rewriteLegacyMigrateArgv(process.argv))\n","import { watch } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { getMaterializer } from '@/core/materializer/index'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\nimport { promptCodexAgentModels } from './codex-model-prompt'\n\nimport type { AgentName } from '@/core/materializer/agent-restrictions'\nimport type { CodexAgentModelChoice } from '@/types'\n\ninterface BuildOptions {\n watch?: boolean\n sync?: boolean\n force?: boolean\n}\n\nexport async function runBuild(cwd: string, opts: BuildOptions): Promise<void> {\n await buildOnce(cwd, opts.force)\n\n if (opts.sync) {\n p.log.step('Syncing agent permissions...')\n const config = await loadConfig(cwd)\n const materializer = getMaterializer(config.provider)\n await materializer.syncPermissions(cwd)\n }\n\n if (opts.watch) {\n p.log.info(`Watching agent-harness-kit.config.ts for changes...`)\n watch(cwd, { recursive: false }, async (_, filename) => {\n if (filename?.startsWith('agent-harness-kit.config')) {\n p.log.step('Config changed — rebuilding...')\n // Deliberately never forced: an automatic rebuild triggered by a file\n // watcher must not destroy agent-file customizations behind the user's\n // back. --force is a one-shot, explicitly requested operation.\n await buildOnce(cwd, false)\n }\n })\n // Keep process alive\n await new Promise(() => { })\n }\n}\n\nasync function buildOnce(cwd: string, force?: boolean): Promise<void> {\n // Load config OUTSIDE any spinner: when --force is set on a claude-code\n // project, the per-role model prompt below needs the provider (from config)\n // before it can decide whether to run, and an interactive p.select cannot\n // render while a p.spinner is active. Loading config is fast (no spinner\n // needed for it in practice), so it moved out of the spinner-wrapped block\n // that used to say \"Loading config...\".\n let config: Awaited<ReturnType<typeof loadConfig>>\n try {\n config = await loadConfig(cwd)\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n\n // Claude Code only, and only when --force is set: re-run the same per-role\n // model prompt `ahk init` and `ahk models` use, before regenerating agent\n // files. Must happen BEFORE the spinner below starts.\n let claudeAgentModels: Partial<Record<AgentName, string>> | undefined\n if (force && config.provider === 'claude-code') {\n claudeAgentModels = await promptClaudeAgentModels(config.provider)\n }\n\n // Codex CLI only, and only when --force is set: mirror the claude-code\n // branch above with the same per-role model + reasoning-effort prompt\n // `ahk init` uses. Must also happen BEFORE the spinner below starts.\n let codexAgentModels: Partial<Record<AgentName, CodexAgentModelChoice>> | undefined\n if (force && config.provider === 'codex-cli') {\n codexAgentModels = await promptCodexAgentModels(config.provider)\n }\n\n const spinner = p.spinner()\n spinner.start('Rebuilding files...')\n\n try {\n const materializer = getMaterializer(config.provider)\n const report = await materializer.build(config, cwd, { force, claudeAgentModels, codexAgentModels })\n spinner.stop(pc.green('Build complete'))\n\n // ── Config-derived files (AGENTS.md, and CLAUDE.md for claude-code) ──\n // Report the ACTUAL per-file outcome rather than a static line. Files that\n // are up to date (created / already current / config propagated) are\n // announced quietly; hand-edited files are called out LOUDLY so a user who\n // expects config to propagate is not left thinking it silently did.\n const d = report.derived\n const upToDate = [...d.created, ...d.current, ...d.propagated]\n if (upToDate.length > 0) {\n p.log.success(upToDate.join(', '))\n }\n if (d.propagated.length > 0) {\n p.log.info(`Propagated config changes to ${d.propagated.length} generated file(s):\\n ${d.propagated.join('\\n ')}`)\n }\n if (d.overwritten.length > 0) {\n p.log.warn(\n pc.yellow(\n `--force REGENERATED ${d.overwritten.length} hand-edited generated file(s), discarding your edits:\\n ` +\n d.overwritten.join('\\n '),\n ),\n )\n if (d.backupDir) {\n p.log.info(pc.yellow(` Previous content backed up → ${d.backupDir}`))\n }\n }\n if (d.preserved.length > 0) {\n // The anti-\"silently stale\" guard: these files diverge from the current\n // config but were hand-edited, so build left them alone. Say so loudly.\n p.log.warn(\n pc.yellow(\n `Left ${d.preserved.length} hand-edited generated file(s) UNTOUCHED — your edits are safe:\\n ` +\n d.preserved.join('\\n ') +\n `\\n These no longer match the current config. Re-run with --force to regenerate them\\n ` +\n `(this DESTROYS your edits; a backup is written first).`,\n ),\n )\n }\n\n p.log.success(`Agent definitions (${config.provider})`)\n p.log.success('MCP config')\n\n const { created, overwritten, preserved, backupDir } = report.agents\n\n if (created.length > 0) {\n p.log.info(`Created ${created.length} missing agent file(s):\\n ${created.join('\\n ')}`)\n }\n\n if (overwritten.length > 0) {\n // Name every file that lost its customizations. A count alone would not\n // let the user tell which of their edits are now only in the backup.\n p.log.warn(\n pc.yellow(\n `--force REGENERATED ${overwritten.length} existing agent file(s), discarding any customizations:\\n ` +\n overwritten.join('\\n '),\n ),\n )\n if (backupDir) {\n p.log.info(pc.yellow(` Previous content backed up → ${backupDir}`))\n }\n }\n\n if (preserved.length > 0) {\n // Without this, a user who edited a template and expects `build` to pick\n // up an upstream improvement gets silence and assumes it was applied.\n p.log.info(\n `Left ${preserved.length} existing agent file(s) untouched — agent files are yours to edit.\\n ` +\n `Re-run with --force to regenerate them from the packaged templates (this DESTROYS your edits;\\n ` +\n `a backup is written first).`,\n )\n }\n } catch (err) {\n spinner.stop(pc.red('Build failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n","import { existsSync } from 'fs'\nimport { join } from 'path'\n\nimport { write } from '@/utils/file'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport {\n mergeClaudeMcpJson,\n mergeClaudeSettingsJson,\n mergeClaudeSettingsLocalJson,\n} from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport {\n agentBuilder,\n agentConsultant,\n agentExplorer,\n agentLead,\n agentReviewer,\n agentsMd,\n claudeMd,\n HEALTH_SH,\n translateFrontmatterForClaudeCode,\n} from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** The set of agent files this provider owns, with their generated content.\n * Single definition shared by `scaffold()` and `build()` — the two used to\n * duplicate this list, which is how `build()` kept overwriting user edits\n * long after `scaffold()` had been fixed to preserve them.\n *\n * `modelsByRole` is optional, collected via `promptClaudeAgentModels`\n * (Claude Code only). It is populated by `scaffold()` (from `ahk init`'s\n * per-role model prompt), and can also be threaded into `build()` via\n * `BuildMaterializerOptions.claudeAgentModels` — which happens when\n * `ahk build --force` re-runs the prompt, and always when `ahk models`\n * calls this directly to regenerate just the 5 agent files. A plain\n * `ahk build` (no `--force`) never collects models, so `build()`'s default\n * call still passes no second argument here, and existing agent files are\n * left untouched regardless (see `writeAgentFiles`'s user-ownership policy).\n * Exported so `ahk models` (src/commands/models.ts) can build the entry\n * list itself and hand it to `writeAgentFiles`. */\nexport function claudeAgentFiles(\n config: HarnessConfig,\n modelsByRole?: ScaffoldOptions['claudeAgentModels']\n): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.claude/agents/lead.md', content: translateFrontmatterForClaudeCode(agentLead({ projectName }), 'lead', { model: modelsByRole?.lead }) },\n { relPath: '.claude/agents/explorer.md', content: translateFrontmatterForClaudeCode(agentExplorer({ projectName }), 'explorer', { model: modelsByRole?.explorer }) },\n { relPath: '.claude/agents/consultant.md', content: translateFrontmatterForClaudeCode(agentConsultant({ projectName }), 'consultant', { model: modelsByRole?.consultant }) },\n { relPath: '.claude/agents/builder.md', content: translateFrontmatterForClaudeCode(agentBuilder({ projectName }), 'builder', { model: modelsByRole?.builder }) },\n { relPath: '.claude/agents/reviewer.md', content: translateFrontmatterForClaudeCode(agentReviewer({ projectName }), 'reviewer', { model: modelsByRole?.reviewer }) },\n ]\n}\n\nexport class ClaudeCodeMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd, claudeAgentModels } = opts\n\n // AGENTS.md and CLAUDE.md — fresh project, write unconditionally, but STAMP\n // the provenance marker so the first `ahk build` recognizes these as our own\n // output and keeps propagating config changes (a markerless file would be\n // treated as human-edited and frozen from day one).\n write(cwd, 'AGENTS.md', stampGenerated(agentsMd(config)))\n write(cwd, 'CLAUDE.md', stampGenerated(claudeMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write(cwd, 'health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold.\n // It is accumulable user data (the \"human-editable task seed list\"), so it\n // is reconciled via the DB round-trip in init.ts (syncFromFeatureList →\n // writeFeatureList) rather than written unconditionally here — which used\n // to clobber a hand-written backlog and mis-path the file to the project\n // root instead of .harness/.\n\n // .harness/current.md placeholder — scope='global' — current.md lives\n // under ~/.harness/dbs/<projectId>/ (see resolveGlobalStorageDir in\n // db.ts), not in the project tree, and `markdownFallback.path` doesn't\n // exist on GlobalStorageConfig at all. Skip for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n cwd,\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .claude/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, claudeAgentFiles(config, claudeAgentModels))\n\n // .mcp.json — MERGE, never overwrite whole file. Detect the project's\n // package manager fresh from cwd so the spawned command matches npm/pnpm/yarn.\n mergeClaudeMcpJson(join(cwd, '.mcp.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n // .claude/settings.json — set `agent: \"lead\"` (the official Claude Code default-agent field)\n mergeClaudeSettingsJson(join(cwd, '.claude/settings.json'))\n // .claude/settings.local.json — merge MCP tool permissions\n mergeClaudeSettingsLocalJson(join(cwd, '.claude/settings.local.json'))\n\n // .gitignore additions\n appendGitignore(cwd)\n writeSkills(cwd, '.claude/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md and CLAUDE.md are DERIVED FROM CONFIG. Reconcile against the\n // provenance marker: untouched files propagate config changes automatically,\n // hand-edited files are preserved (and reported), --force regenerates them\n // after backing up. See reconcileGeneratedFiles in scaffold-utils.\n const derived = reconcileGeneratedFiles(\n cwd,\n [\n { relPath: 'AGENTS.md', content: agentsMd(config) },\n { relPath: 'CLAUDE.md', content: claudeMd(config) },\n ],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n // Agent files are USER-OWNED. Without --force they are created when\n // missing and never touched again; --force regenerates them, backing up\n // the previous content first. `opts.claudeAgentModels` is only ever set\n // when the caller (currently `ahk build --force`, see build.ts) collected\n // fresh per-role models via `promptClaudeAgentModels` — a plain build\n // never sets it, so this is `undefined` (no model line) exactly as before.\n const agents = writeAgentFiles(cwd, claudeAgentFiles(config, opts.claudeAgentModels), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // MCP config: always merge. Re-detecting the package manager on every\n // build means a stale/hardcoded command self-corrects the next time the\n // user runs `ahk build`, even if they switched package managers after\n // the initial `ahk init` — no separate migration flag needed.\n mergeClaudeMcpJson(join(cwd, '.mcp.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n mergeClaudeSettingsJson(join(cwd, '.claude/settings.json'))\n mergeClaudeSettingsLocalJson(join(cwd, '.claude/settings.local.json'))\n writeSkills(cwd, '.claude/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n // Migration from claude-code is handled by the target materializer\n }\n\n /**\n * No-op by design.\n *\n * This used to rewrite the `tools:` frontmatter block of every agent file,\n * re-injecting the canonical `mcp__agent-harness-kit__*` allowlist. Agent\n * files no longer declare `tools` at all: they inherit the full tool set\n * (Task and every MCP tool included) and express restrictions as a\n * `disallowedTools` denylist instead.\n *\n * Keeping the old rewrite alive would be actively harmful — on a project\n * upgraded from an older version, whose agent files still carry a legacy\n * `tools:` block, it would re-inject the allowlist and silently undo the\n * migration on exactly the files that most need it. Run `ahk build` to\n * regenerate agent files in the current shape.\n */\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Agent files inherit tools and declare a disallowedTools denylist —')\n console.log(' there is no permission allowlist to sync. Run `ahk build` to regenerate them.')\n }\n}\n","import { mkdirSync, writeFileSync } from 'fs'\nimport { join, resolve } from 'path'\n\nexport const write = (cwd: string, relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport { hasRealLocalInstall } from '@/core/local-install-guard'\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn-classic' | 'yarn-berry' | 'bun'\n\n/**\n * Detects the package manager used by the project at `cwd`.\n *\n * Priority:\n * 1. The `packageManager` field in `package.json` (e.g. `\"yarn@3.6.0\"`,\n * `\"pnpm@8.15.0\"`) — the most reliable signal when present, since it's an\n * explicit declaration (Corepack-compatible) rather than a guess.\n * 2. Lockfile heuristics — `pnpm-lock.yaml` → pnpm, `bun.lockb`/`bun.lock` →\n * bun, `yarn.lock` → yarn (distinguishing classic vs berry via the\n * presence of `.yarnrc.yml`, which only exists in Yarn Berry projects),\n * `package-lock.json` → npm.\n * 3. Fallback: `npm`.\n */\nexport function detectPackageManager(cwd: string): PackageManager {\n const fromField = detectFromPackageManagerField(cwd)\n if (fromField) return fromField\n\n if (existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm'\n if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) return 'bun'\n if (existsSync(join(cwd, 'yarn.lock'))) {\n return existsSync(join(cwd, '.yarnrc.yml')) ? 'yarn-berry' : 'yarn-classic'\n }\n if (existsSync(join(cwd, 'package-lock.json'))) return 'npm'\n\n return 'npm'\n}\n\nfunction detectFromPackageManagerField(cwd: string): PackageManager | null {\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) return null\n\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))\n const field = pkg?.packageManager\n if (typeof field !== 'string' || !field.trim()) return null\n\n // Format: \"<name>@<version>[+hash]\" (Corepack convention)\n const match = field.match(/^([a-z]+)@(\\d+)/i)\n if (!match) return null\n\n const [, rawName, majorStr] = match\n const name = rawName.toLowerCase()\n const major = Number(majorStr)\n\n switch (name) {\n case 'npm':\n return 'npm'\n case 'pnpm':\n return 'pnpm'\n case 'bun':\n return 'bun'\n case 'yarn':\n return major >= 2 ? 'yarn-berry' : 'yarn-classic'\n default:\n return null\n }\n } catch {\n return null\n }\n}\n\n/**\n * Returns the full command-line tokens for spawning the MCP server.\n *\n * When the package is genuinely installed locally in the project at `cwd`\n * (see {@link hasRealLocalInstall}), the command is mediated by the\n * project's package manager so the pinned local version is the one that runs:\n *\n * | Manager | Tokens |\n * | ------------ | ---------------------------------------------------- |\n * | npm | `npx --no ahk serve --port <port>` |\n * | pnpm | `pnpm exec ahk serve --port <port>` |\n * | yarn classic | `yarn run ahk serve --port <port>` |\n * | yarn berry | `yarn run ahk serve --port <port>` |\n * | bun | `bunx --no-install ahk serve --port <port>` |\n *\n * When there is no real local install, the package manager has nothing to\n * resolve and every one of those commands would fail. In that case the\n * binary from the global install is invoked directly, regardless of `pm`:\n *\n * | (no real local install) | `ahk serve --port <port>` |\n *\n * This deliberately uses {@link hasRealLocalInstall} rather than\n * {@link isLocalInstallSatisfied}: self-dev repos (where `cwd` IS this\n * package's own root) are treated as \"no local install\" here, even though\n * `isLocalInstallSatisfied` — used elsewhere for the non-blocking install\n * warning — still reports self-dev as satisfied. There is no real\n * node_modules entry for a package manager to mediate through in self-dev,\n * so self-dev gets the same bare global command form as any other project\n * with no local install.\n *\n * `cwd` is required on purpose: it must be the project root being configured,\n * never a process-wide default. Defaulting it to `process.cwd()` would make\n * the result depend on where the process happens to be running from.\n *\n * Callers split this into `command`/`args` (Claude Code, Codex CLI) or use\n * the array as-is (OpenCode, whose `mcp.<name>.command` field is a single\n * array rather than a separate command/args pair).\n */\nexport function getMcpCommandParts(pm: PackageManager, port: number, cwd: string): string[] {\n const portStr = String(port)\n\n // No real local install → the package manager cannot resolve `ahk`; call\n // the globally installed binary directly. This intentionally excludes the\n // self-dev shortcut (see JSDoc above).\n if (!hasRealLocalInstall(cwd)) {\n return ['ahk', 'serve', '--port', portStr]\n }\n\n switch (pm) {\n case 'pnpm':\n return ['pnpm', 'exec', 'ahk', 'serve', '--port', portStr]\n case 'yarn-classic':\n case 'yarn-berry':\n return ['yarn', 'run', 'ahk', 'serve', '--port', portStr]\n case 'bun':\n return ['bunx', '--no-install', 'ahk', 'serve', '--port', portStr]\n case 'npm':\n default:\n return ['npx', '--no', 'ahk', 'serve', '--port', portStr]\n }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { pkg } from '@/core/package-data'\n\n/**\n * Determines whether `@cardor/agent-harness-kit` is available as a local\n * dependency of the project at `cwd` (see {@link hasRealLocalInstall}), OR\n * whether `cwd` IS the package itself (self-dev case, e.g. working inside\n * this repo) — either is treated as \"satisfied\" here.\n *\n * This is the self-dev-inclusive, general-purpose check. It powers the\n * non-blocking install warning (`cli.ts`'s `preAction` hook) and the config\n * file format decision (`detectConfigExtension` in `init-helpers.ts`), where\n * self-dev genuinely behaves like a satisfied local install for those\n * purposes. Callers that need to distinguish a *real* local install from the\n * self-dev shortcut (e.g. `getMcpCommandParts`, which must not mediate\n * through a package manager that has nothing to resolve in self-dev) should\n * call {@link hasRealLocalInstall} directly instead.\n *\n * The generated config no longer needs the package resolvable at runtime\n * (`import type` is erased at compile time, and the .mjs/.cjs templates\n * don't import the package at all), so this check is no longer required\n * for `loadConfig(cwd)` to succeed. It is kept as a non-blocking warning\n * so a team/CI can still pin an explicit local version of the CLI for\n * reproducibility — the command always continues regardless of the result.\n */\nexport function isLocalInstallSatisfied(cwd: string): boolean {\n // Self-dev case: cwd is the agent-harness-kit repo itself, so there is\n // no (and should be no) node_modules/@cardor/agent-harness-kit entry.\n const selfPkgPath = join(cwd, 'package.json')\n if (existsSync(selfPkgPath)) {\n try {\n const selfPkg = JSON.parse(readFileSync(selfPkgPath, 'utf8'))\n if (selfPkg?.name === pkg.name) return true\n } catch {\n // Malformed package.json — ignore and fall through to the real-install check.\n }\n }\n\n return hasRealLocalInstall(cwd)\n}\n\n/**\n * Determines whether `@cardor/agent-harness-kit` is available as a *real*\n * local dependency of the project at `cwd` — a node_modules entry, or (for\n * Yarn Berry PnP, which never creates node_modules) a declared dependency\n * detected via the PnP loader files. Deliberately excludes the self-dev\n * shortcut (`cwd` being the package's own repo): in self-dev there is no\n * actual local install for a package manager to mediate through, so this\n * returns `false` there even though {@link isLocalInstallSatisfied} returns\n * `true`.\n *\n * Use this when the caller's decision hinges on there being something a\n * package manager can genuinely resolve — e.g. `getMcpCommandParts`, which\n * picks between a package-manager-mediated command and the bare global\n * binary. Use {@link isLocalInstallSatisfied} for general-purpose\n * \"is this project set up with the package available\" checks that should\n * treat self-dev the same as a real local install.\n */\nexport function hasRealLocalInstall(cwd: string): boolean {\n const [scope, name] = pkg.name.split('/')\n const localPath = pkg.name.startsWith('@') ? join(cwd, 'node_modules', scope, name) : join(cwd, 'node_modules', pkg.name)\n\n if (existsSync(localPath)) return true\n\n // Yarn Berry with Plug'n'Play (PnP) never creates a node_modules directory\n // at all, so the check above always fails there even when the package IS\n // correctly declared and resolvable via the PnP loader. Detect PnP via its\n // generated loader files and fall back to checking that the package is\n // declared as a dependency in package.json — the only signal available\n // without depending on a node_modules layout PnP intentionally omits.\n const isPnp = existsSync(join(cwd, '.pnp.cjs')) || existsSync(join(cwd, '.pnp.loader.mjs'))\n if (isPnp) {\n const pkgPath = join(cwd, 'package.json')\n if (existsSync(pkgPath)) {\n try {\n const projectPkg = JSON.parse(readFileSync(pkgPath, 'utf8'))\n const deps = {\n ...((projectPkg?.dependencies as Record<string, unknown>) ?? {}),\n ...((projectPkg?.devDependencies as Record<string, unknown>) ?? {}),\n }\n if (Object.prototype.hasOwnProperty.call(deps, pkg.name)) return true\n } catch {\n // Malformed package.json — ignore and fall through to false.\n }\n }\n }\n\n return false\n}\n\n/**\n * Prints a non-blocking warning recommending a local install, with the\n * exact command to fix it. This is informational only — the command\n * continues to run either way. A local install is no longer required for\n * config loading to work; it is still recommended so the version of the\n * package used stays reproducible and pinned across your team and CI,\n * instead of drifting with whatever is installed globally on each machine.\n */\nexport function printLocalInstallWarning(): void {\n console.error(pc.yellow(`⚠ ${pkg.name} is not installed locally in this project.`))\n console.error(pc.dim(' This is only a recommendation for reproducibility: pinning a local'))\n console.error(pc.dim(' version keeps behavior consistent across your team and CI, instead of'))\n console.error(pc.dim(' drifting with whatever version is installed globally on each machine.'))\n console.error(pc.dim(` Run: npm install --save-dev ${pkg.name}`))\n console.error(pc.dim(' (or the equivalent for your package manager: pnpm add -D, yarn add --dev, bun add -d)'))\n}\n","import { existsSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst require = createRequire(import.meta.url)\n\n// Resolved at runtime relative to the compiled file location:\n// - local dev (compiled): dist/core/package-data.js → ../../package.json (repo root)\n// - installed: node_modules/@cardor/agent-harness-kit/dist/core/package-data.js → ../../package.json (package root)\n// - local dev (running .ts directly via tsx, e.g. tests): src/core/package-data.ts → ../../package.json (repo root)\nconst here = dirname(fileURLToPath(import.meta.url))\nconst candidates = [join(here, '..', '..', 'package.json'), join(here, '..', 'package.json')]\nconst pkgPath = candidates.find((p) => existsSync(p)) ?? candidates[0]\n\nexport const pkg = require(pkgPath) as { version: string; name: string }\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\n\nimport { getMcpCommandParts } from './detect-package-manager'\n\nimport type { PackageManager } from './detect-package-manager'\n\n// ─── Claude Code ──────────────────────────────────────────────────────────────\n\nexport function mergeClaudeMcpJson(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n const folderPath = dirname(filePath)\n if (!existsSync(folderPath)) {\n mkdirSync(folderPath, { recursive: true })\n }\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // Unreadable JSON — start fresh to avoid corrupt state\n }\n }\n\n const [command, ...args] = getMcpCommandParts(pm, port, cwd)\n\n const merged = {\n ...existing,\n mcpServers: {\n ...((existing.mcpServers as Record<string, unknown>) ?? {}),\n 'agent-harness-kit': {\n type: 'stdio',\n command,\n args,\n },\n },\n }\n\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// Write `agent: \"lead\"` to .claude/settings.json — the correct Claude Code field\n// for setting which subagent runs as the main session thread.\nexport function mergeClaudeSettingsJson(filePath: string): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // start fresh\n }\n }\n\n const merged = {\n ...existing,\n agent: 'lead',\n }\n\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// Merge MCP tool permissions into .claude/settings.local.json\nexport const MCP_CLAUDE_PERMISSIONS_LEAD = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_add',\n 'mcp__agent-harness-kit__tasks_update',\n 'mcp__agent-harness-kit__tasks_edit',\n 'mcp__agent-harness-kit__tasks_archive',\n 'mcp__agent-harness-kit__tasks_unarchive',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_EXPLORER = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_BUILDER = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_add',\n 'mcp__agent-harness-kit__tasks_update',\n 'mcp__agent-harness-kit__tasks_edit',\n 'mcp__agent-harness-kit__tasks_archive',\n 'mcp__agent-harness-kit__tasks_unarchive',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_REVIEWER = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_add',\n 'mcp__agent-harness-kit__tasks_update',\n 'mcp__agent-harness-kit__tasks_edit',\n 'mcp__agent-harness-kit__tasks_archive',\n 'mcp__agent-harness-kit__tasks_unarchive',\n 'mcp__agent-harness-kit__tasks_acceptance_update',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n]\n\nexport const MCP_CLAUDE_PERMISSIONS_CONSULTANT = [\n 'mcp__agent-harness-kit__actions_start',\n 'mcp__agent-harness-kit__actions_write',\n 'mcp__agent-harness-kit__actions_complete',\n 'mcp__agent-harness-kit__actions_get',\n 'mcp__agent-harness-kit__actions_record_file',\n 'mcp__agent-harness-kit__actions_record_tool',\n 'mcp__agent-harness-kit__tasks_get',\n 'mcp__agent-harness-kit__tasks_claim',\n 'mcp__agent-harness-kit__tasks_acceptance_get',\n 'mcp__agent-harness-kit__deps_snapshot',\n 'mcp__agent-harness-kit__deps_check',\n 'mcp__agent-harness-kit__docs_search',\n 'mcp__agent-harness-kit__ahk_doctor',\n] as const\n\n// Full union — used by mergeClaudeSettingsLocalJson for project-wide settings\nexport const MCP_CLAUDE_PERMISSIONS = [\n ...new Set([\n ...MCP_CLAUDE_PERMISSIONS_LEAD,\n ...MCP_CLAUDE_PERMISSIONS_EXPLORER,\n ...MCP_CLAUDE_PERMISSIONS_BUILDER,\n ...MCP_CLAUDE_PERMISSIONS_REVIEWER,\n ...MCP_CLAUDE_PERMISSIONS_CONSULTANT,\n ]),\n]\n\nexport function mergeClaudeSettingsLocalJson(filePath: string): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // start fresh\n }\n }\n\n const existingPermissions = (existing.permissions as Record<string, unknown>) ?? {}\n const existingAllow = (existingPermissions.allow as string[]) ?? []\n const existingServers = (existing.enabledMcpjsonServers as string[]) ?? []\n\n const mergedAllow = Array.from(new Set([...existingAllow, ...MCP_CLAUDE_PERMISSIONS]))\n const mergedServers = Array.from(new Set([...existingServers, 'agent-harness-kit']))\n\n const merged = {\n ...existing,\n permissions: {\n ...existingPermissions,\n allow: mergedAllow,\n },\n enabledMcpjsonServers: mergedServers,\n }\n\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// ─── OpenCode ─────────────────────────────────────────────────────────────────\n\nexport function mergeOpencodeJson(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n const folderPath = dirname(filePath)\n if (!existsSync(folderPath)) {\n mkdirSync(folderPath, { recursive: true })\n }\n\n let existing: Record<string, unknown> = {}\n if (existsSync(filePath)) {\n try {\n existing = JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n // start fresh\n }\n }\n\n const existingMcp = (existing.mcp as Record<string, unknown>) ?? {}\n\n const merged = {\n ...existing,\n default_agent: 'lead',\n compaction: existing.compaction ?? { auto: true, prune: true, reserved: 10000 },\n permission: existing.permission ?? { write: 'ask' },\n mcp: {\n ...existingMcp,\n 'agent-harness-kit': {\n enabled: true,\n type: 'local',\n // OpenCode's mcp.<name>.command field is a single array (unlike\n // Claude/Codex, which split command/args) — pass the full token list.\n command: getMcpCommandParts(pm, port, cwd),\n },\n },\n }\n\n writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n}\n\n// ─── Codex CLI ────────────────────────────────────────────────────────────────\n\nfunction mergeTomlSection(content: string, sectionName: string, sectionBody: string): string {\n const lines = content.split('\\n')\n const header = `[${sectionName}]`\n\n const startIdx = lines.findIndex((l) => l.trim() === header)\n\n if (startIdx === -1) {\n const trimmed = content.trimEnd()\n return trimmed + (trimmed ? '\\n\\n' : '') + header + '\\n' + sectionBody.trimEnd() + '\\n'\n }\n\n // Find where the section ends: next line starting with `[` or EOF\n let endIdx = lines.length\n for (let i = startIdx + 1; i < lines.length; i++) {\n if (/^\\[/.test(lines[i])) {\n endIdx = i\n break\n }\n }\n\n const newLines = [\n ...lines.slice(0, startIdx),\n header,\n ...sectionBody.trimEnd().split('\\n'),\n '',\n ...lines.slice(endIdx),\n ]\n\n return newLines.join('\\n')\n}\n\n/**\n * Inserts a bare top-level `key = \"value\"` into a TOML document's preamble\n * (the region before the first `[section]` header), ONLY if that exact key is\n * not already present there. Never overwrites — once written, the value is\n * the user's, and re-running this must be a no-op that preserves their edit.\n *\n * A sibling to `mergeTomlSection` above, not a modification of it — that\n * helper is shared with the Grok path and only ever merges bracketed section\n * bodies. It appends an absent section at EOF, which is exactly the trap this\n * helper exists to avoid for bare top-level keys: TOML scalars belong to\n * whichever `[section]` header precedes them, so appending `model = \"...\"` at\n * EOF would silently land inside `[mcp_servers.agent-harness-kit]` and\n * corrupt that server's config (its struct almost certainly denies unknown\n * fields) instead of being a harmless top-level default.\n */\nexport function ensureTomlTopLevelKey(content: string, key: string, value: string): string {\n // Guard against `''.split('\\n')` → `['']`, which would otherwise insert a\n // spurious leading blank line into a brand-new file.\n const lines = content.length > 0 ? content.split('\\n') : []\n const firstSectionIdx = lines.findIndex((l) => /^\\s*\\[/.test(l))\n const preambleEnd = firstSectionIdx === -1 ? lines.length : firstSectionIdx\n\n // Anchored with `\\s*=` immediately after `key` so `model` never matches a\n // `model_reasoning_effort = ...` line (and vice versa) — the two keys share\n // a prefix, and a loose `.includes()`-style check would collide them.\n const keyRe = new RegExp(`^\\\\s*${key}\\\\s*=`)\n const alreadyPresent = lines.slice(0, preambleEnd).some((l) => keyRe.test(l))\n if (alreadyPresent) return content\n\n const newLines = [...lines]\n newLines.splice(preambleEnd, 0, `${key} = ${JSON.stringify(value)}`)\n return newLines.join('\\n')\n}\n\nexport function mergeCodexConfigToml(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let content = ''\n if (existsSync(filePath)) {\n content = readFileSync(filePath, 'utf8')\n }\n\n const [command, ...args] = getMcpCommandParts(pm, port, cwd)\n\n const sectionBody = [\n `command = ${JSON.stringify(command)}`,\n `args = ${JSON.stringify(args)}`,\n 'default_tools_approval_mode = \"approve\"',\n ].join('\\n')\n\n // Top-level defaults — written into the preamble, before any [section]\n // header. Merge-safe: only written once, a user's hand-edit is preserved\n // forever across re-runs (see `ensureTomlTopLevelKey`).\n content = ensureTomlTopLevelKey(content, 'model', 'gpt-5.6-terra')\n content = ensureTomlTopLevelKey(content, 'model_reasoning_effort', 'medium')\n content = ensureTomlTopLevelKey(content, 'sandbox_mode', 'danger-full-access')\n\n content = mergeTomlSection(content, 'mcp_servers.agent-harness-kit', sectionBody)\n\n writeFileSync(filePath, content, 'utf8')\n}\n\n// ─── Grok Build ───────────────────────────────────────────────────────────────\n\n/**\n * Writes/merges `.grok/config.toml`'s `[mcp_servers.agent-harness-kit]`\n * section. Follows `mergeCodexConfigToml`'s pattern above exactly, reusing the\n * already-generic `mergeTomlSection` helper — chosen (task #76 consultant\n * decision) over relying on `.mcp.json` compatibility, because that file is\n * written exclusively by Claude Code's materializer (a Grok-only project would\n * have none), and because Grok's own `.mcp.json` read is conditional on an\n * interactive Claude-import prompt that can also be disabled entirely via\n * `[compat.claude] mcps = false`.\n *\n * Unlike Codex's section, no `default_tools_approval_mode` key is emitted —\n * that key is Codex-specific, and Grok's own documented MCP TOML schema\n * (07-mcp-servers.md) does not call for it for a straightforward always-on\n * local stdio server. Kept minimal (`command`/`args` only) to match the\n * project's existing minimal-emission style and reduce drift surface on\n * re-merge.\n */\nexport function mergeGrokConfigToml(\n filePath: string,\n port: number,\n cwd: string,\n pm: PackageManager = 'npm'\n): void {\n mkdirSync(dirname(filePath), { recursive: true })\n\n let content = ''\n if (existsSync(filePath)) {\n content = readFileSync(filePath, 'utf8')\n }\n\n const [command, ...args] = getMcpCommandParts(pm, port, cwd)\n\n const sectionBody = [\n `command = ${JSON.stringify(command)}`,\n `args = ${JSON.stringify(args)}`,\n ].join('\\n')\n\n content = mergeTomlSection(content, 'mcp_servers.agent-harness-kit', sectionBody)\n\n writeFileSync(filePath, content, 'utf8')\n}\n","import { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { GITIGNORE_ENTRIES } from './templates'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n/* NOTE: the single-file `writeAgentFile()` was folded into `writeAgentFiles()`\n * below. Keeping both would have left two competing write policies in the same\n * module — and two policies is how this bug happened in the first place: the\n * batch call sites in `scaffold()` and `build()` drifted apart until\n * claude-code's `build()` was writing unconditionally while every other site\n * preserved. One helper, one policy. */\n\nexport interface AgentFileEntry {\n relPath: string\n content: string\n}\n\nexport interface WriteAgentFilesOptions {\n /** Overwrite files that already exist, destroying any customization.\n * Existing files are backed up to `backupRoot` FIRST. */\n force?: boolean\n /** Absolute directory under which the pre-overwrite backup is written.\n * Required when `force` is set and any file would actually be overwritten. */\n backupRoot?: string\n}\n\nexport interface WriteAgentFilesResult {\n /** Files that did not exist and were written. */\n created: string[]\n /** Files that existed and were overwritten (only possible with `force`). */\n overwritten: string[]\n /** Files that existed and were left untouched (no `force`). */\n preserved: string[]\n /** Absolute path of the backup directory, when one was written. */\n backupDir?: string\n}\n\n/**\n * Writes a batch of agent files under a single, explicit ownership policy.\n *\n * Agent files are USER-OWNED: the generator creates them when missing and\n * never touches them again. That is the whole point — a dev may edit the role\n * prompt, the model line, or the restriction fields, and a later `ahk build`\n * must not silently revert that work.\n *\n * `force` is the only escape hatch, and it is destructive: it regenerates every\n * file from the packaged template, discarding customizations. Because it is the\n * ONLY way to pick up template improvements, it must not destroy without a net\n * — so, following the `migrate storage --force` precedent, every file about to\n * be overwritten is copied to a timestamped backup directory BEFORE anything is\n * written, and a backup failure aborts the whole batch without touching a\n * single file.\n *\n * This helper exists because the same write policy was previously duplicated\n * across `scaffold()` and `build()` in all three materializers (six sites).\n * That duplication is exactly why `claude-code.ts` kept an unconditional write\n * in `build()` long after the other two providers had been fixed.\n */\nexport function writeAgentFiles(\n cwd: string,\n entries: AgentFileEntry[],\n opts: WriteAgentFilesOptions = {},\n): WriteAgentFilesResult {\n const result: WriteAgentFilesResult = { created: [], overwritten: [], preserved: [] }\n\n const existing = entries.filter((e) => existsSync(join(cwd, e.relPath)))\n\n // Back up BEFORE any write. If this throws, nothing has been touched yet.\n if (opts.force && existing.length > 0) {\n if (!opts.backupRoot) {\n throw new Error(\n 'writeAgentFiles: force is set and existing agent files would be overwritten, ' +\n 'but no backupRoot was provided. Refusing to overwrite without a backup.',\n )\n }\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const backupDir = join(opts.backupRoot, `agents-${stamp}`)\n try {\n for (const entry of existing) {\n const dest = join(backupDir, entry.relPath)\n mkdirSync(resolve(dest, '..'), { recursive: true })\n writeFileSync(dest, readFileSync(join(cwd, entry.relPath), 'utf8'), 'utf8')\n }\n } catch (err) {\n throw new Error(\n `Could not back up existing agent files to ${backupDir} ` +\n `(${err instanceof Error ? err.message : String(err)}). ` +\n `Aborting WITHOUT overwriting anything — no agent file was modified.`,\n )\n }\n result.backupDir = backupDir\n }\n\n for (const entry of entries) {\n const abs = join(cwd, entry.relPath)\n const exists = existsSync(abs)\n\n if (exists && !opts.force) {\n result.preserved.push(entry.relPath)\n continue\n }\n\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, entry.content, 'utf8')\n if (exists) result.overwritten.push(entry.relPath)\n else result.created.push(entry.relPath)\n }\n\n return result\n}\n\n/* ─── Config-derived files (AGENTS.md / CLAUDE.md) ────────────────────────────\n *\n * These differ from the user-owned agent files above: they are DERIVED FROM\n * CONFIG, so a config change legitimately SHOULD flow into them — a plain\n * create-if-missing policy would freeze them at their first-generated version.\n * But `ahk build` must never silently destroy a hand-edit either. Both cannot\n * be satisfied by content alone, so each generated file carries an out-of-body\n * provenance fingerprint: a trailing HTML comment holding the sha256 of the\n * EXACT body bytes we wrote. On the next build we recompute the hash of the\n * on-disk body and route:\n *\n * - file missing -> CREATE (stamp a marker)\n * - on-disk body == freshly generated body -> CURRENT (no-op)\n * - marker present AND its hash matches the on-disk\n * body, but the body differs from generated -> PROPAGATE (our own prior\n * output, made stale only by a config change — overwrite, no backup)\n * - marker absent OR hash mismatch -> PRESERVE (a human edited\n * the body after we wrote it, or it predates the fingerprint) + report\n * - --force over a PRESERVE file -> back up FIRST (fail-safe,\n * exactly like writeAgentFiles), then regenerate with a fresh marker.\n *\n * The linchpin safety property: the hash is over the EXACT bytes with NO\n * normalization. Any human change — even one space or a CRLF rewrite — makes\n * the hash mismatch and routes to PRESERVE. Misclassification can therefore\n * only ever OVER-preserve (harmless, self-announcing), never silently overwrite\n * a human edit. Do NOT trim or normalize the body before hashing.\n */\n\nconst GENERATED_MARKER_RE = /^([\\s\\S]*)\\n<!-- ahk:generated ([0-9a-f]{64}) -->\\n?$/\n\nfunction bodyFingerprint(body: string): string {\n return createHash('sha256').update(body, 'utf8').digest('hex')\n}\n\n/**\n * Wraps a freshly generated body with its provenance marker. The hash is over\n * the EXACT body bytes and is computed BEFORE the marker is appended, so a\n * round-trip of our own output re-hashes equal. Exported so `scaffold()` (which\n * writes unconditionally on a fresh project) stamps the SAME marker — without\n * it, the very first build would see a markerless file, classify it as\n * human-edited, and freeze config propagation from day one.\n */\nexport function stampGenerated(body: string): string {\n return `${body}\\n<!-- ahk:generated ${bodyFingerprint(body)} -->\\n`\n}\n\n/** Parses a stamped file back into its body and recorded hash. Returns null when\n * the file has no recognizable trailing marker (markerless, or a human appended\n * content after the marker). The split is byte-exact: `body` is precisely the\n * bytes that precede the `\\n<marker>\\n` we wrote. */\nfunction readStamp(fileContent: string): { body: string; hash: string } | null {\n const m = GENERATED_MARKER_RE.exec(fileContent)\n if (!m) return null\n return { body: m[1], hash: m[2] }\n}\n\n/** What happened to a single config-derived file during a build. */\nexport type DerivedFileOutcome = 'created' | 'current' | 'propagated' | 'preserved' | 'overwritten'\n\nexport interface ReconcileResult {\n /** Files that did not exist and were written with a fresh marker. */\n created: string[]\n /** Files already byte-identical to the generated body — left untouched. */\n current: string[]\n /** Files that were provably our own prior output, made stale by a config\n * change, and overwritten to propagate that change (no backup — our bytes). */\n propagated: string[]\n /** Files a human edited (or that predate the marker), left untouched. */\n preserved: string[]\n /** Files overwritten by `--force` despite being human-edited (backed up first). */\n overwritten: string[]\n /** Absolute path of the backup directory, when one was written. */\n backupDir?: string\n}\n\ninterface ReconcileOptions {\n /** Regenerate PRESERVE files (human-edited), destroying their edits. The\n * previous content is backed up FIRST; a backup failure aborts everything. */\n force?: boolean\n /** Absolute directory under which the pre-overwrite backup is written.\n * Required when `force` overwrites at least one human-edited file. */\n backupRoot?: string\n}\n\n/**\n * Reconciles a batch of config-derived files against what is on disk using the\n * provenance-fingerprint policy documented above. Mirrors `writeAgentFiles`'\n * fail-safe backup: everything a `--force` run would overwrite is copied to a\n * timestamped backup directory BEFORE a single byte is written, and a backup\n * failure aborts the whole batch without touching anything.\n */\nexport function reconcileGeneratedFiles(\n cwd: string,\n entries: AgentFileEntry[],\n opts: ReconcileOptions = {},\n): ReconcileResult {\n const result: ReconcileResult = {\n created: [],\n current: [],\n propagated: [],\n preserved: [],\n overwritten: [],\n }\n\n type Action = 'create' | 'current' | 'propagate' | 'preserve' | 'overwrite'\n const plans: { entry: AgentFileEntry; action: Action }[] = []\n const toBackup: AgentFileEntry[] = []\n\n for (const entry of entries) {\n const abs = join(cwd, entry.relPath)\n\n if (!existsSync(abs)) {\n plans.push({ entry, action: 'create' })\n continue\n }\n\n const onDisk = readFileSync(abs, 'utf8')\n const stamp = readStamp(onDisk)\n const onDiskBody = stamp ? stamp.body : onDisk\n\n if (onDiskBody === entry.content) {\n // Idempotent: byte-identical to the generated body. No-op, and do not even\n // rewrite the marker (holds true whether or not one is present).\n plans.push({ entry, action: 'current' })\n continue\n }\n\n // Body differs from generated. Is it provably our own prior output?\n if (stamp && stamp.hash === bodyFingerprint(stamp.body)) {\n // Marker matches the on-disk body byte-for-byte → the ONLY reason it\n // differs from `generated` is a config change. Safe to propagate.\n plans.push({ entry, action: 'propagate' })\n continue\n }\n\n // Markerless, or the marker's hash no longer matches the body → a human\n // touched it. Preserve unless the user explicitly asked to regenerate.\n if (opts.force) {\n plans.push({ entry, action: 'overwrite' })\n toBackup.push(entry)\n } else {\n plans.push({ entry, action: 'preserve' })\n }\n }\n\n // Fail-safe backup BEFORE any write. If this throws, nothing has been touched.\n if (toBackup.length > 0) {\n if (!opts.backupRoot) {\n throw new Error(\n 'reconcileGeneratedFiles: force is set and hand-edited generated files would be ' +\n 'overwritten, but no backupRoot was provided. Refusing to overwrite without a backup.',\n )\n }\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const backupDir = join(opts.backupRoot, `derived-${stamp}`)\n try {\n for (const entry of toBackup) {\n const dest = join(backupDir, entry.relPath)\n mkdirSync(resolve(dest, '..'), { recursive: true })\n writeFileSync(dest, readFileSync(join(cwd, entry.relPath), 'utf8'), 'utf8')\n }\n } catch (err) {\n throw new Error(\n `Could not back up existing generated files to ${backupDir} ` +\n `(${err instanceof Error ? err.message : String(err)}). ` +\n `Aborting WITHOUT overwriting anything — no file was modified.`,\n )\n }\n result.backupDir = backupDir\n }\n\n for (const { entry, action } of plans) {\n const abs = join(cwd, entry.relPath)\n switch (action) {\n case 'current':\n result.current.push(entry.relPath)\n break\n case 'preserve':\n result.preserved.push(entry.relPath)\n break\n case 'create':\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, stampGenerated(entry.content), 'utf8')\n result.created.push(entry.relPath)\n break\n case 'propagate':\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, stampGenerated(entry.content), 'utf8')\n result.propagated.push(entry.relPath)\n break\n case 'overwrite':\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, stampGenerated(entry.content), 'utf8')\n result.overwritten.push(entry.relPath)\n break\n }\n }\n\n return result\n}\n\nexport function appendGitignore(cwd: string): void {\n const giPath = join(cwd, '.gitignore')\n const existing = existsSync(giPath) ? readFileSync(giPath, 'utf8') : ''\n\n const toAdd = GITIGNORE_ENTRIES.split('\\n')\n .filter((line) => line && !existing.includes(line))\n .join('\\n')\n\n if (toAdd.trim()) {\n writeFileSync(giPath, existing + (existing.endsWith('\\n') ? '' : '\\n') + toAdd + '\\n', 'utf8')\n }\n}\n\nexport function slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 64)\n}\n\nexport function writeSkills(cwd: string, skillsDir: string): void {\n const skillNames = ['ahk-ask', 'ahk-consultant', 'ahk-triage', 'ahk-review', 'ahk-test']\n for (const skillName of skillNames) {\n const src = join(__dirname, 'skills', skillName, 'SKILL.md')\n const destDir = join(cwd, skillsDir, skillName)\n const dest = join(destDir, 'SKILL.md')\n mkdirSync(destDir, { recursive: true })\n writeFileSync(dest, readFileSync(src, 'utf8'), 'utf8')\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport {\n claudeDisallowedTools,\n codexRestrictionNotice,\n codexSandboxMode,\n grokToolsAllowlist,\n opencodePermissions,\n} from './agent-restrictions'\n\nimport type { AgentName } from './agent-restrictions'\nimport type { CodexAgentModelChoice, HarnessConfig } from '@/types'\n\n// ─── Agent template loader ────────────────────────────────────────────────────\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst TEMPLATES_DIR = join(__dirname, 'agent-templates')\n\n/**\n * Load an agent template file and interpolate {{variables}}.\n * Variables are replaced using a simple {{key}} pattern.\n */\nfunction loadAgentTemplate(\n name: 'lead' | 'explorer' | 'consultant' | 'builder' | 'reviewer',\n vars: Record<string, string> = {}\n): string {\n const raw = readFileSync(join(TEMPLATES_DIR, `${name}.md`), 'utf8')\n return raw.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? `{{${key}}}`)\n}\n\n// ─── health.sh — exits 1 until the dev implements it ─────────────────────────\n\nexport const HEALTH_SH = `#!/usr/bin/env bash\n# health.sh — project health check for agent-harness-kit\n#\n# This script must exit 0 when the project is healthy.\n# Agents will run this before making codebase changes.\n#\n# TODO: implement your project's health checks below.\n# Examples:\n# npm test\n# docker compose ps | grep -q \"running\"\n# psql -c \"SELECT 1\" > /dev/null 2>&1\n#\n# Until you implement it, this script intentionally exits 1\n# so agents know the environment is not verified.\n\necho \"health.sh not implemented yet.\"\necho \"Edit this file with your project's health checks.\"\necho \"It must exit 0 for agents to start working.\"\nexit 1\n`\n\n// ─── AGENTS.md template ───────────────────────────────────────────────────────\n\nexport function agentsMd(config: HarnessConfig): string {\n const { name, description, docsPath } = config.project\n const port = config.tools.mcp.port\n\n return `# AGENTS.md — ${name}\n\n> **Read this file first.** It is the navigation map for every AI agent working in this repository.\n\n## Project\n\n**${name}** — ${description}\n\n## Health check (run before making codebase changes)\n\n\\`\\`\\`bash\nbash health.sh\n\\`\\`\\`\n\nIf it exits non-zero, stop and report the issue. Do not proceed with codebase changes until health is green.\n\n## Harness data (source of truth)\n\n| File | Purpose |\n|------|---------|\n| \\`.harness/harness.db\\` | SQLite: all tasks, actions, file changes, tool calls |\n| \\`.harness/current.md\\` | Markdown fallback — read this if MCP server is unavailable |\n| \\`.harness/feature_list.json\\` | Human-editable task seed list |\n\n## MCP tools (preferred)\n\nThe harness exposes tools via MCP server on port ${port}. Use these instead of reading files directly.\n\n\\`\\`\\`\nactions.start taskId agent → start an action, returns a numeric actionId\nactions.write actionId section text → record a section (result, blockers, ...)\nactions.record_tool actionId calls[] → batch-log tool calls to the Tools dashboard (array, min 1)\nactions.record_file actionId files[] → batch-log file touches to the Files dashboard (array, min 1)\nactions.complete actionId summary → close the action\nactions.get taskId → full action history for a task\ntasks.add title [slug] [description] [acceptance] → create a new task from natural language\ntasks.get [status] → list tasks (pending | in_progress | done | blocked)\ntasks.claim id → atomically claim a pending task\ntasks.update id status → change task status\ntasks.acceptance.update criterionId → mark an acceptance criterion as met\ndocs.search query → search ${docsPath} for relevant content\n\\`\\`\\`\n\n## Workflow\n\n\\`\\`\\`\n1. INIT\n - Assess user intent: only run health.sh if changes are needed\n - tasks.get('in_progress') → resume if something is in progress\n - tasks.get('pending') → pick lowest id\n\n2. WORK (lead → explorer → consultant → builder → reviewer)\n - Each agent calls actions.start(taskId, agentName) → numeric actionId\n - Accumulate tool calls / file touches as you work; flush periodically (every few calls or at a phase boundary) via actions.record_tool(actionId, calls: [...]) and actions.record_file(actionId, files: [...]) — both are batch-only, even a single entry goes through as a one-element array\n - Closes with actions.complete(actionId, summary)\n\n3. CLOSE\n - tasks.update(taskId, 'done')\n - Run health.sh (if changes were made) → must be green before closing\n\\`\\`\\`\n\n## Agent roles\n\n| Agent | Responsibility |\n|-------|---------------|\n| lead | Decomposes the task into a plan, assigns sub-agents |\n| explorer | Reads and maps relevant code, never writes |\n| consultant | Technical advisor, runs after explorer, before builder. Never writes code. |\n| builder | Implements the plan, writes files |\n| reviewer | Verifies acceptance criteria, approves or blocks |\n\n## What to read\n\n\\`\\`\\`\nAlways: .harness/current.md (or MCP tasks.get)\nIf implementing: ${docsPath}/\nIf orchestrating: Agent definition files in your provider's agents directory\n\\`\\`\\`\n`\n}\n\n// ─── CLAUDE.md template (Claude Code provider) ───────────────────────────────\n\nexport function claudeMd(config: HarnessConfig): string {\n const { name, description, docsPath } = config.project\n const port = config.tools.mcp.port\n\n return `# CLAUDE.md — ${name}\n\n> **Read this file first.** It is the navigation map for every AI agent working in this repository.\n\n## Project\n\n**${name}** — ${description}\n\n## Health check (run before making codebase changes)\n\n\\`\\`\\`bash\nbash health.sh\n\\`\\`\\`\n\nIf it exits non-zero, stop and report the issue. Do not proceed with codebase changes until health is green.\n\n## Harness data (source of truth)\n\n| File | Purpose |\n|------|---------|\n| \\`.harness/harness.db\\` | SQLite: all tasks, actions, file changes, tool calls |\n| \\`.harness/current.md\\` | Markdown fallback — read this if MCP server is unavailable |\n| \\`.harness/feature_list.json\\` | Human-editable task seed list |\n\n## MCP tools (preferred)\n\nThe harness exposes tools via MCP server on port ${port}. Use these instead of reading files directly.\n\n\\`\\`\\`\nactions.start taskId agent → start an action, returns a numeric actionId\nactions.write actionId section text → record a section (result, blockers, ...)\nactions.record_tool actionId calls[] → batch-log tool calls to the Tools dashboard (array, min 1)\nactions.record_file actionId files[] → batch-log file touches to the Files dashboard (array, min 1)\nactions.complete actionId summary → close the action\nactions.get taskId → full action history for a task\ntasks.add title [slug] [description] [acceptance] → create a new task from natural language\ntasks.get [status] → list tasks (pending | in_progress | done | blocked)\ntasks.claim id → atomically claim a pending task\ntasks.update id status → change task status\ntasks.acceptance.update criterionId → mark an acceptance criterion as met\ndocs.search query → search ${docsPath} for relevant content\n\\`\\`\\`\n\n## Workflow\n\n\\`\\`\\`\n1. INIT\n - Assess user intent: only run health.sh if changes are needed\n - tasks.get('in_progress') → resume if something is in progress\n - tasks.get('pending') → pick lowest id\n - No pending tasks? → ask user, infer fields, call tasks.add, then tasks.claim\n\n2. WORK (lead → explorer → consultant → builder → reviewer)\n - Each agent calls actions.start(taskId, agentName) → numeric actionId\n - Accumulate tool calls / file touches as you work; flush periodically (every few calls or at a phase boundary) via actions.record_tool(actionId, calls: [...]) and actions.record_file(actionId, files: [...]) — both are batch-only, even a single entry goes through as a one-element array\n - Closes with actions.complete(actionId, summary)\n\n3. CLOSE\n - tasks.update(taskId, 'done')\n - Run health.sh (if changes were made) → must be green before closing\n\\`\\`\\`\n\n## Agent roles\n\n| Agent | Responsibility |\n|-------|---------------|\n| lead | Decomposes the task into a plan, assigns sub-agents |\n| explorer | Reads and maps relevant code, never writes |\n| consultant | Technical advisor, runs after explorer, before builder. Never writes code. |\n| builder | Implements the plan, writes files |\n| reviewer | Verifies acceptance criteria, approves or blocks |\n\n## What to read\n\n\\`\\`\\`\nAlways: .harness/current.md (or MCP tasks.get)\nIf implementing: ${docsPath}/\nIf orchestrating: Agent definition files in .claude/agents/\n\\`\\`\\`\n`\n}\n\n// ─── agent-harness-kit.config.ts template ───────────────────────────────────────────\n\ninterface ConfigTemplateParams {\n name: string\n description: string\n provider: string\n docsPath: string\n tasksAdapter: string\n port: number\n scope: 'local' | 'global'\n projectId: string\n}\n\n/**\n * Shared body of the config object literal, reused across the .ts/.mjs/.cjs\n * templates below. Returns the inner fields only (no wrapping braces) so\n * each variant can control its own import/export shape around it.\n */\nfunction configObjectBody(params: ConfigTemplateParams): string {\n const isGlobal = params.scope === 'global'\n\n // scope='global' — the sqlite file and current.md fallback both live under\n // ~/.harness/dbs/<projectId>/ (see resolveGlobalStorageDir in db.ts), so\n // there is no local path to declare for either. Emitting a `sqlitePath`\n // (local-only field) or `markdownFallback.path` for this scope would be\n // silently ignored at runtime — omit them entirely for this scope.\n const markdownFallbackLine = isGlobal\n ? `markdownFallback: { enabled: true },`\n : `markdownFallback: { enabled: true, path: '.harness/current.md' },`\n\n return ` project: {\n name: ${JSON.stringify(params.name)},\n description: ${JSON.stringify(params.description)},\n docsPath: '${params.docsPath}',\n },\n\n provider: '${params.provider}',\n\n // There is no 'agents' key. Agent files are yours: edit the role prompt and\n // the 'model:' frontmatter line directly in the generated file. 'ahk build'\n // creates them when missing and never overwrites them — use\n // 'ahk build --force' to regenerate them from the packaged templates.\n // What each role may NOT do is enforced per-tool inside those files\n // (disallowedTools / permission.edit / sandbox_mode); see\n // src/core/materializer/agent-restrictions.ts.\n\n // SQLite (default). Switch to postgres/mysql by changing database.type.\n // database: { type: 'postgres', connectionString: process.env.DATABASE_URL },\n // database: { type: 'mysql', connectionString: process.env.DATABASE_URL },\n database: { type: 'sqlite' },\n\n storage: {\n dir: '.harness',\n tasks: { adapter: '${params.tasksAdapter}' },\n sections: {\n toolsUsed: true,\n filesModified: true,\n result: true,\n blockers: true,\n nextSteps: false,\n },\n ${markdownFallbackLine}\n // 'local' — DB lives in .harness/ (project-relative). 'global' — DB lives\n // under ~/.harness/dbs/<projectId>/, outside the project tree.\n scope: '${params.scope}',\n projectId: '${params.projectId}',\n },\n\n health: {\n scriptPath: './health.sh',\n required: true,\n },\n\n tools: {\n mcp: { enabled: true, port: ${params.port} },\n scripts: { enabled: true, outputDir: './.harness/scripts' },\n },\n`\n}\n\n/**\n * Structural twin of `configObjectBody()` above, as a real object instead of a\n * source string. `configObjectBody` has to stay a hand-formatted string because\n * its explanatory comments are part of what makes the generated .ts/.mjs/.cjs\n * config readable — JSON has no comments, so the JSON variant cannot reuse it.\n *\n * The two are therefore maintained in parallel, and the drift that invites is\n * pinned by a test asserting that the parsed .ts body and this object are\n * deep-equal. Any field added to one and not the other fails that test.\n *\n * Deliberately contains no `$schema` key: no JSON Schema for HarnessConfig is\n * published or shipped with the package today, and pointing at a URL that does\n * not resolve would trade a type error for a fetch error.\n */\nfunction configObject(params: ConfigTemplateParams): Record<string, unknown> {\n const isGlobal = params.scope === 'global'\n\n return {\n project: {\n name: params.name,\n description: params.description,\n docsPath: params.docsPath,\n },\n provider: params.provider,\n // There is no 'agents' key here either — it was removed from the config\n // entirely, so the JSON variant must not reintroduce it.\n database: { type: 'sqlite' },\n storage: {\n dir: '.harness',\n tasks: { adapter: params.tasksAdapter },\n sections: {\n toolsUsed: true,\n filesModified: true,\n result: true,\n blockers: true,\n nextSteps: false,\n },\n // Same scope rule as configObjectBody(): 'global' has no local path to\n // declare, so markdownFallback.path is omitted for it.\n markdownFallback: isGlobal ? { enabled: true } : { enabled: true, path: '.harness/current.md' },\n scope: params.scope,\n projectId: params.projectId,\n },\n health: {\n scriptPath: './health.sh',\n required: true,\n },\n tools: {\n mcp: { enabled: true, port: params.port },\n scripts: { enabled: true, outputDir: './.harness/scripts' },\n },\n }\n}\n\n/**\n * JSON config: emitted when the package is NOT installed locally in the project\n * (see detectConfigExtension). Plain data — no import, no type annotation, no\n * reference to '@cardor/agent-harness-kit' of any kind — so an editor and a\n * `tsc --noEmit` have nothing to resolve and report zero errors. That is the\n * whole point of this variant: the .ts template's `import type` is erased at\n * runtime, but it still red-underlines in an editor that cannot resolve the\n * package.\n *\n * Cost of the trade: no autocompletion. JSON.stringify handles all quoting and\n * escaping, so descriptions containing quotes or apostrophes are safe by\n * construction rather than by careful template authoring.\n */\nexport function configJson(params: ConfigTemplateParams): string {\n return JSON.stringify(configObject(params), null, 2) + '\\n'\n}\n\n/** Exported for the drift test that compares this shape against the parsed\n * .ts/.mjs/.cjs config body. Not part of the public API. */\nexport const __configObjectForTests = configObject\n\n/**\n * TypeScript config: uses `import type` (type-only, erased at compile time)\n * instead of a value import of `defineHarness`. This means `loadConfig()`\n * (via jiti) never needs to resolve `@cardor/agent-harness-kit` as a real\n * module at runtime just to load the config — only the type is referenced,\n * which TypeScript strips entirely. `defineHarness()` itself is unaffected\n * and remains available for anyone who prefers to import and call it\n * manually; `loadConfig()` supports both shapes (see config.ts).\n */\nexport function configTs(params: ConfigTemplateParams): string {\n return `import type { HarnessConfig } from '@cardor/agent-harness-kit'\n\nconst config: HarnessConfig = {\n${configObjectBody(params)}}\n\nexport default config\n`\n}\n\n/**\n * .mjs config: plain JavaScript has no compile-time type checking, so there\n * is no benefit to importing anything from the package here — not even a\n * type. The object is exported as-is via ESM `export default`.\n */\nexport function configMjs(params: ConfigTemplateParams): string {\n return `const config = {\n${configObjectBody(params)}}\n\nexport default config\n`\n}\n\n/**\n * .cjs config: same reasoning as configMjs — plain JS, no types to import.\n * Exported via CommonJS `module.exports`, which `loadConfig()` already\n * handles through its `mod.default ?? mod` fallback.\n */\nexport function configCjs(params: ConfigTemplateParams): string {\n return `const config = {\n${configObjectBody(params)}}\n\nmodule.exports = config\n`\n}\n\n// ─── Agent definition templates (loaded from agent-templates/*.md) ─────────────\n\nexport function agentLead(vars: { projectName: string }): string {\n return loadAgentTemplate('lead', vars)\n}\n\nexport function agentExplorer(vars: { projectName: string }): string {\n return loadAgentTemplate('explorer', vars)\n}\n\nexport function agentBuilder(vars: { projectName: string }): string {\n return loadAgentTemplate('builder', vars)\n}\n\nexport function agentConsultant(vars: { projectName: string }): string {\n return loadAgentTemplate('consultant', vars)\n}\n\nexport function agentReviewer(vars: { projectName: string }): string {\n return loadAgentTemplate('reviewer', vars)\n}\n\n// Note: agentLead/agentExplorer/agentConsultant/agentBuilder/agentReviewer above produce the\n// raw markdown template (frontmatter without `model:` and without any permission fields).\n// No `model:` line is ever injected, by any provider: the per-agent `model` config was removed\n// along with the whole `agents` key, and the generated agent file is user-owned, so the model is\n// set by editing the file's frontmatter directly. Each provider applies its own default when no\n// model line is present. Permission/restriction fields ARE added downstream by each provider's\n// translator, driven by AGENT_RESTRICTIONS in ./agent-restrictions.ts, which is the single source\n// of truth for what a role may not do.\n\n// ─── feature_list.json initial seed ──────────────────────────────────────────\n\nexport function featureListJson(\n tasks: { slug: string; title: string; description?: string; acceptance?: string[] }[]\n): string {\n return JSON.stringify(tasks, null, 2) + '\\n'\n}\n\n// ─── Codex CLI agent TOML helpers ────────────────────────────────────────────\n\nfunction stripFrontmatter(md: string): { description: string; body: string } {\n const parts = md.split(/^---\\s*$/m)\n if (parts.length < 3) return { description: '', body: md }\n\n const frontmatter = parts[1]\n const body = parts.slice(2).join('---').replace(/^\\n/, '')\n\n let description = ''\n // YAML folded scalar: `description: >\\n line1\\n line2`\n const foldedMatch = frontmatter.match(/^description:\\s*[>|]\\s*\\n((?:[ \\t]+[^\\n]*\\n?)*)/m)\n if (foldedMatch) {\n description = foldedMatch[1]\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean)\n .join(' ')\n } else {\n const inlineMatch = frontmatter.match(/^description:\\s*(.+)$/m)\n if (inlineMatch) description = inlineMatch[1].trim()\n }\n\n return { description, body }\n}\n\n/**\n * No `model` / `model_reasoning_effort` line is emitted unless `opts` supplies\n * one. The generated file is user-owned, so by default the model is set by\n * editing those lines directly in `.codex/agents/<role>.toml`; omitting them\n * here lets Codex apply its own default, which is what the old 'inherit'\n * option meant. `opts` is the one caller-controlled exception — it is how\n * `ahk init`'s per-role Codex model+effort prompt (`promptCodexAgentModels`)\n * applies a user's actual answer, mirroring `translateFrontmatterForClaudeCode`'s\n * `opts.model` for Claude Code.\n *\n * Both fields are guarded against empty strings: Codex's per-agent-role file\n * format uses `#[serde(deny_unknown_fields)]`, so a malformed key takes the\n * WHOLE role file offline, and its reasoning-effort parser explicitly rejects\n * an empty string (every other unrecognized value is silently accepted as a\n * custom effort, but `\"\"` is the one hard error) — so a line is only ever\n * emitted for a genuinely non-empty value.\n */\nfunction toCodexToml(\n tomlName: string,\n agentName: AgentName,\n description: string,\n body: string,\n opts?: CodexAgentModelChoice\n): string {\n // TOML multiline basic strings end at `\"\"\"` — escape any that appear in content\n const safe = (s: string) => s.replace(/\"\"\"/g, '\"\"\\\\u0022')\n\n // Codex has no per-agent tool denylist. As of task #83, all roles run with\n // sandbox_mode = \"danger-full-access\" (deliberate, user-chosen project\n // configuration) — sandbox_mode is no longer an enforcement mechanism for\n // the no-write roles, so the restriction is restated in prose inside\n // developer_instructions, which is now the ONLY enforcement for those roles.\n const sandboxMode = codexSandboxMode(agentName)\n const notice = codexRestrictionNotice(agentName)\n const instructions = notice ? `${body.trimEnd()}\\n\\n---\\n\\n${notice}` : body.trimEnd()\n\n const modelLines: string[] = []\n if (opts?.model) modelLines.push(`model = \"${opts.model}\"`)\n if (opts?.effort) modelLines.push(`model_reasoning_effort = \"${opts.effort}\"`)\n const modelBlock = modelLines.length > 0 ? `${modelLines.join('\\n')}\\n` : ''\n\n return `name = \"${tomlName}\"\nsandbox_mode = \"${sandboxMode}\"\n${modelBlock}\ndescription = \"\"\"\n${safe(description)}\n\"\"\"\n\ndeveloper_instructions = \"\"\"\n${safe(instructions)}\n\"\"\"\n`\n}\n\nexport function agentLeadToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('lead', vars))\n return toCodexToml('lead', 'lead', description, body, opts)\n}\n\nexport function agentLeadAsDefaultToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('lead', vars))\n return toCodexToml('default', 'lead', description, body, opts)\n}\n\nexport function agentExplorerToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('explorer', vars))\n return toCodexToml('explorer', 'explorer', description, body, opts)\n}\n\nexport function agentBuilderToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('builder', vars))\n return toCodexToml('builder', 'builder', description, body, opts)\n}\n\nexport function agentReviewerToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('reviewer', vars))\n return toCodexToml('reviewer', 'reviewer', description, body, opts)\n}\n\nexport function agentConsultantToml(vars: { projectName: string }, opts?: CodexAgentModelChoice): string {\n const { description, body } = stripFrontmatter(loadAgentTemplate('consultant', vars))\n return toCodexToml('consultant', 'consultant', description, body, opts)\n}\n\n// ─── Claude Code frontmatter translation ─────────────────────────────────────\n\n/**\n * Removes a `tools:` (or `disallowedTools:`) YAML block sequence from the\n * frontmatter, if present. Used to normalise a template before re-emitting the\n * provider-native permission shape, so translation stays idempotent even when\n * fed already-translated content.\n */\nfunction stripFrontmatterBlockSequence(md: string, key: string): string {\n const re = new RegExp(`^${key}:\\\\n(?: - [^\\\\n]+\\\\n)+`, 'm')\n return md.replace(re, '')\n}\n\n/**\n * Appends a YAML block sequence (one ` - value` per line) to the end of the\n * frontmatter, just before its closing `---`. Block sequence — not the inline\n * comma form shown in some upstream docs — for consistency with the rest of the\n * agent files in this repo.\n */\nfunction appendFrontmatterBlockSequence(md: string, key: string, values: string[]): string {\n if (values.length === 0) return md\n const block = `${key}:\\n${values.map((v) => ` - ${v}`).join('\\n')}\\n`\n return md.replace(/^---\\n([\\s\\S]*?)^---\\n/m, (_m, body: string) => `---\\n${body}${block}---\\n`)\n}\n\n/**\n * Appends a single scalar key (e.g. `model: opus`) to the end of the\n * frontmatter, just before its closing `---`. Only used where the caller has\n * already guarded that the frontmatter does not carry a hand-authored value\n * for this key — this function does not check for an existing line itself.\n */\nfunction appendFrontmatterScalar(md: string, key: string, value: string): string {\n const block = `${key}: ${value}\\n`\n return md.replace(/^---\\n([\\s\\S]*?)^---\\n/m, (_m, body: string) => `---\\n${body}${block}---\\n`)\n}\n\n/**\n * Appends a nested YAML mapping (e.g. `permission:\\n edit: deny`) to the end of\n * the frontmatter, just before its closing `---`.\n */\nfunction appendFrontmatterMapping(md: string, key: string, entries: Record<string, string>): string {\n const keys = Object.keys(entries)\n if (keys.length === 0) return md\n const block = `${key}:\\n${keys.map((k) => ` ${k}: ${entries[k]}`).join('\\n')}\\n`\n return md.replace(/^---\\n([\\s\\S]*?)^---\\n/m, (_m, body: string) => `---\\n${body}${block}---\\n`)\n}\n\n/**\n * Translates a template's frontmatter into the Claude Code agent shape.\n *\n * `tools` is deliberately OMITTED: a Claude Code sub-agent with no `tools` key\n * inherits the full tool set, which includes `Task` and every `mcp__*` tool from\n * the connected servers. That inheritance replaces the explicit Task + MCP tool\n * injection this function used to perform — enumerating them was both redundant\n * and the reason `ahk doctor` reported hand-edited agent files as \"outdated\".\n *\n * Restrictions are expressed as a denylist via `disallowedTools`, which Claude\n * Code applies before `tools`.\n *\n * No `model:` line is emitted by default. Those generated files are\n * user-owned, so their model is normally set by editing the frontmatter\n * directly; with no line emitted, Claude Code applies its own default — the\n * behaviour the old 'inherit' option described.\n *\n * `opts.model` is the one caller-controlled exception: when the value is\n * provided and is not 'inherit', a `model: <value>` line is injected for\n * whichever `agentName` is passed in. This is how `ahk init`'s per-role model\n * prompt (Claude Code only) applies a user's choice to a role's generated\n * `.claude/agents/<role>.md` at scaffold time — it writes straight into this\n * function's output, never into config. Omitting `opts` (or passing 'inherit')\n * keeps the contract byte-identical to the no-model-line default.\n */\nexport function translateFrontmatterForClaudeCode(\n md: string,\n agentName: AgentName,\n opts?: { model?: string }\n): string {\n let result = stripFrontmatterBlockSequence(md, 'tools')\n result = stripFrontmatterBlockSequence(result, 'disallowedTools')\n if (opts?.model && opts.model !== 'inherit') {\n result = appendFrontmatterScalar(result, 'model', opts.model)\n }\n return appendFrontmatterBlockSequence(result, 'disallowedTools', claudeDisallowedTools(agentName))\n}\n\n// ─── OpenCode frontmatter translation ────────────────────────────────────────\n\n/**\n * Translates a template's frontmatter into the OpenCode agent shape.\n *\n * The `tools: { read: true, ... }` dict this function used to emit is\n * deprecated upstream in favour of `permission`, so no `tools` key is written\n * at all — the agent inherits the default tool set. Restrictions are expressed\n * as `permission` entries with `allow | ask | deny` values.\n *\n * Only ONE key is emitted for the no-write case: OpenCode has no separate\n * `write` permission — `edit` already covers write/patch/edit.\n *\n * Note on MCP tools: under OpenCode they are named `<server>_<tool>` with no\n * `mcp__` prefix, so Claude Code patterns must never be ported here verbatim.\n * Nothing in the current restriction set targets MCP tools, so none are emitted.\n */\nexport function translateFrontmatterForOpenCode(md: string, agentName: AgentName): string {\n let result = stripFrontmatterBlockSequence(md, 'tools')\n result = stripFrontmatterBlockSequence(result, 'disallowedTools')\n return appendFrontmatterMapping(result, 'permission', opencodePermissions(agentName))\n}\n\n// ─── Grok Build frontmatter translation ──────────────────────────────────────\n\n/**\n * Translates a template's frontmatter into the Grok Build agent shape.\n *\n * Grok Build's format is markdown + YAML frontmatter, like Claude Code and\n * OpenCode (unlike Codex's TOML), so this reuses the same generic\n * block-sequence helpers `translateFrontmatterForClaudeCode` uses — structural\n * twin to `translateFrontmatterForOpenCode` above.\n *\n * Unlike Claude's `disallowedTools` (a denylist), Grok's `tools:` field is an\n * ALLOWLIST: `grokToolsAllowlist()` returns the full set of permitted tool\n * names for 'no-write' roles, or `[]` for the unrestricted 'none' role (which\n * `appendFrontmatterBlockSequence` turns into an omitted `tools:` key,\n * inheriting every tool — matching Claude/OpenCode's \"inherit all\" behaviour\n * for `builder`).\n */\nexport function translateFrontmatterForGrok(md: string, agentName: AgentName): string {\n let result = stripFrontmatterBlockSequence(md, 'tools')\n result = stripFrontmatterBlockSequence(result, 'disallowedTools')\n return appendFrontmatterBlockSequence(result, 'tools', grokToolsAllowlist(agentName))\n}\n\n// ─── .gitignore additions ─────────────────────────────────────────────────────\n\nexport const GITIGNORE_ENTRIES = `\n# agent-harness-kit\n.harness/harness.db\n.harness/harness.db-shm\n.harness/harness.db-wal\n.harness/current.md\n`\n","/**\n * Internal, provider-agnostic model of what each role is *not* allowed to do.\n *\n * This is deliberately a tiny closed vocabulary rather than a literal list of\n * tool names: the three supported providers do not share a permission model,\n * so a single \"denylist of tools\" cannot be translated verbatim to all of them.\n * Each provider's materializer translates the restriction below into its own\n * native semantics:\n *\n * restriction | Claude Code | OpenCode | Codex CLI | Grok Build\n * --------------|------------------------------|--------------------------|-------------------------------|---------------------------------\n * 'none' | omit `tools` (inherit all) | omit `permission` | sandbox_mode=\"danger-full-access\" | omit `tools` (inherit all)\n * 'no-write' | disallowedTools: Write, Edit | permission: { edit: deny } | sandbox_mode=\"danger-full-access\" (enforced by prose only — see below) | tools: <allowlist, no Write/Edit>\n *\n * Notes on the asymmetries this abstraction hides:\n * - OpenCode has NO separate `write` permission. Its `edit` permission is\n * documented as \"file modifications including write/patch\", so a single\n * `edit: deny` covers Write + Edit + patch. Emitting two keys would be wrong.\n * - Codex CLI has no per-agent tool denylist at all, and as of task #83 it\n * also has no OS-level sandbox: by deliberate, user-chosen project\n * configuration, ALL 5 roles run with `sandbox_mode = \"danger-full-access\"`\n * (fully unsandboxed), including the 'no-write' roles. `restrictionFor()`\n * is intentionally ignored by `codexSandboxMode()` for this reason. The\n * no-write restriction for those roles under Codex is therefore enforced\n * ENTIRELY by the prose restated in `developer_instructions`\n * (`CODEX_READ_ONLY_NOTICE`) — there is no technical enforcement left. See\n * README.md for the documented tradeoff.\n * - Grok Build's `tools:` frontmatter field is the INVERSE shape of Claude's:\n * an ALLOWLIST, not a denylist. There is no way to say \"everything except\n * Write/Edit\" — the no-write role must enumerate every tool it IS allowed.\n * The allowlist below (PascalCase tool-class names, matching the vocabulary\n * Grok's own permission-rule engine enforces against, plus the two MCP\n * discovery meta-tools `search_tool`/`use_tool`) was resolved by the task\n * #76 consultant advisory after the docs turned out to use two competing\n * naming conventions with no single reconciling reference page. Bash is\n * included deliberately, consistent with Claude/OpenCode's existing\n * no-write scope (a tool-visibility restriction, not an OS sandbox like\n * Codex's) — see `grokToolsAllowlist` below.\n */\n\nexport type AgentName = 'lead' | 'explorer' | 'consultant' | 'builder' | 'reviewer'\n\nexport type AgentRestriction = 'none' | 'no-write'\n\nexport const AGENT_RESTRICTIONS: Record<AgentName, AgentRestriction> = {\n lead: 'no-write',\n explorer: 'no-write',\n consultant: 'no-write',\n builder: 'none',\n reviewer: 'no-write',\n}\n\nexport function restrictionFor(agentName: AgentName): AgentRestriction {\n return AGENT_RESTRICTIONS[agentName] ?? 'no-write'\n}\n\n// ─── Claude Code ─────────────────────────────────────────────────────────────\n\n/**\n * Tool names Claude Code should refuse for this role. An empty array means the\n * agent inherits everything (including `Task` and all `mcp__*` tools) — which is\n * exactly why `tools` is omitted entirely rather than enumerated.\n */\nexport function claudeDisallowedTools(agentName: AgentName): string[] {\n return restrictionFor(agentName) === 'no-write' ? ['Write', 'Edit'] : []\n}\n\n// ─── OpenCode ────────────────────────────────────────────────────────────────\n\n/**\n * OpenCode `permission` entries for this role. The legacy `tools: { x: false }`\n * dict is deprecated upstream in favour of `permission`, so nothing is emitted\n * for the unrestricted case.\n */\nexport function opencodePermissions(agentName: AgentName): Record<string, 'allow' | 'ask' | 'deny'> {\n return restrictionFor(agentName) === 'no-write' ? { edit: 'deny' } : {}\n}\n\n// ─── Codex CLI ───────────────────────────────────────────────────────────────\n\nexport type CodexSandboxMode = 'workspace-write' | 'read-only' | 'danger-full-access'\n\n/**\n * All 5 Codex roles run fully unsandboxed by deliberate, user-chosen project\n * configuration (task #83) — `restrictionFor()` is intentionally NOT consulted\n * here. This removes the only OS-level enforcement Codex CLI had for the\n * no-write roles; see `CODEX_READ_ONLY_NOTICE` below for the prose-only\n * backstop that replaces it, and README.md for the documented tradeoff.\n */\nexport function codexSandboxMode(_agentName: AgentName): CodexSandboxMode {\n return 'danger-full-access'\n}\n\n/**\n * Prose restated inside `developer_instructions`. Since sandbox_mode is now\n * `danger-full-access` for every role (task #83, user-chosen), this notice is\n * no longer a redundant backstop to an OS sandbox — it is the ONLY thing\n * enforcing the no-write restriction for lead/explorer/consultant/reviewer\n * under Codex CLI. A violation will not be technically rejected by anything;\n * it will silently corrupt the harness's audit trail and workflow guarantees.\n */\nexport const CODEX_READ_ONLY_NOTICE = `## Tool restrictions (enforced by instruction only — NOT by the sandbox)\n\nThis agent runs UNSANDBOXED: \\`sandbox_mode = \"danger-full-access\"\\`. There is no OS-level write protection. This is a deliberate project configuration choice, not an oversight.\n\nYou MUST NOT create, modify, or delete any file: no \\`Write\\`, no \\`Edit\\`, no \\`apply_patch\\`, and no shell command that writes to disk (\\`>\\`, \\`tee\\`, \\`sed -i\\`, \\`mv\\`, \\`rm\\`, ...). This restriction is enforced ONLY by you following this instruction — nothing will technically block or reject the call.\n\nIf you find yourself about to perform a write, STOP. Do not perform it. Report it as a blocker instead. Treat this as a hard rule: breaking it will not fail loudly, it will silently break the harness's audit trail and workflow guarantees.`\n\nexport function codexRestrictionNotice(agentName: AgentName): string {\n return restrictionFor(agentName) === 'no-write' ? CODEX_READ_ONLY_NOTICE : ''\n}\n\n// ─── Grok Build ──────────────────────────────────────────────────────────────\n\n/**\n * Tool allowlist for Grok Build's `tools:` frontmatter field.\n *\n * Unlike Claude Code's `disallowedTools`/OpenCode's `permission` (both\n * denylist-shaped), Grok Build's `tools:` field is an ALLOWLIST: an agent may\n * only call tools named in this list, so \"no-write\" must enumerate everything\n * it IS allowed rather than the two things it isn't.\n *\n * Names are PascalCase tool-class names (`Bash`, `Read`, `NotebookRead`,\n * `Grep`, `Glob`, `WebFetch`, `WebSearch`) plus the two MCP discovery\n * meta-tools (`search_tool`, `use_tool`) that have no PascalCase form\n * documented anywhere in Grok Build's docs. This is Convention A per the task\n * #76 consultant advisory: Grok's own permission-rule engine\n * (22-permissions-and-safety.md \"Tool Names\") only recognizes these names, so\n * they are not just best-evidence but the only reading under which the\n * frontmatter allowlist and the permission-rule engine can refer to the same\n * tool. `Bash` is included even for 'no-write' roles — matching the existing\n * precedent that Claude's `disallowedTools: ['Write','Edit']` and OpenCode's\n * `edit: deny` both already leave Bash fully permitted for a tool-visibility\n * restriction (as opposed to Codex's OS-level sandbox).\n *\n * Returns `[]` for the 'none' role (builder) so the caller's\n * `appendFrontmatterBlockSequence` no-ops and `tools:` is omitted entirely,\n * inheriting every tool — the same \"empty array means inherit everything\"\n * contract `claudeDisallowedTools` already uses.\n */\nexport function grokToolsAllowlist(agentName: AgentName): string[] {\n return restrictionFor(agentName) === 'no-write'\n ? ['Bash', 'Read', 'NotebookRead', 'Grep', 'Glob', 'WebFetch', 'WebSearch', 'search_tool', 'use_tool']\n : []\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport { mergeCodexConfigToml } from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport {\n agentBuilderToml,\n agentConsultantToml,\n agentExplorerToml,\n agentLeadAsDefaultToml,\n agentLeadToml,\n agentReviewerToml,\n agentsMd,\n HEALTH_SH,\n} from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** Agent files this provider owns. Shared by `scaffold()` and `build()`.\n *\n * `default.toml` is included deliberately. It is a shim that overrides Codex's\n * built-in `default` agent so `lead` runs when no agent is selected, but it is\n * still an agent file the user may edit, so it follows the same user-owned\n * policy as the five roles: created when missing, regenerated only with\n * --force.\n *\n * `modelsByRole` is optional, collected via `promptCodexAgentModels` (Codex\n * CLI only). It is populated by `scaffold()` (from `ahk init`'s per-role\n * model+effort prompt), and can also be threaded into `build()` via\n * `BuildMaterializerOptions.codexAgentModels`. A plain `ahk build` (no\n * `--force`) never collects models, so `build()`'s default call still passes\n * no second argument here, and existing agent files are left untouched\n * regardless (see `writeAgentFiles`'s user-ownership policy). Exported —\n * mirroring `claude-code.ts`'s exported `claudeAgentFiles` — so it can be\n * tested directly with an explicit map, without mocking `@clack/prompts`. */\nexport function codexAgentFiles(\n config: HarnessConfig,\n modelsByRole?: ScaffoldOptions['codexAgentModels']\n): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.codex/agents/lead.toml', content: agentLeadToml({ projectName }, modelsByRole?.lead) },\n { relPath: '.codex/agents/explorer.toml', content: agentExplorerToml({ projectName }, modelsByRole?.explorer) },\n { relPath: '.codex/agents/consultant.toml', content: agentConsultantToml({ projectName }, modelsByRole?.consultant) },\n { relPath: '.codex/agents/builder.toml', content: agentBuilderToml({ projectName }, modelsByRole?.builder) },\n { relPath: '.codex/agents/reviewer.toml', content: agentReviewerToml({ projectName }, modelsByRole?.reviewer) },\n { relPath: '.codex/agents/default.toml', content: agentLeadAsDefaultToml({ projectName }, modelsByRole?.lead) },\n ]\n}\n\nexport class CodexCliMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd, codexAgentModels } = opts\n\n const write = (relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n }\n\n // AGENTS.md — fresh project, write unconditionally, but STAMP the provenance\n // marker so the first `ahk build` recognizes it as our own output (a\n // markerless file would look human-edited and freeze config propagation).\n write('AGENTS.md', stampGenerated(agentsMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write('health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold — it\n // is accumulable user data reconciled via the DB round-trip in init.ts, so\n // the scaffold no longer writes it (which used to clobber a hand-written\n // backlog).\n\n // scope='global' — current.md lives under ~/.harness/dbs/<projectId>/\n // (see resolveGlobalStorageDir in db.ts), not in the project tree, and\n // `markdownFallback.path` doesn't exist on GlobalStorageConfig at all.\n // Skip the local placeholder entirely for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .codex/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, codexAgentFiles(config, codexAgentModels))\n\n // .codex/config.toml — MERGE, never overwrite whole file. Detect the\n // project's package manager fresh from cwd so the spawned command matches npm/pnpm/yarn.\n mergeCodexConfigToml(join(cwd, '.codex/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n\n appendGitignore(cwd)\n writeSkills(cwd, '.agents/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md is DERIVED FROM CONFIG. Reconcile against the provenance marker:\n // untouched files propagate config changes, hand-edited files are preserved\n // (and reported), --force regenerates after backing up.\n const derived = reconcileGeneratedFiles(\n cwd,\n [{ relPath: 'AGENTS.md', content: agentsMd(config) }],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n const agents = writeAgentFiles(cwd, codexAgentFiles(config, opts.codexAgentModels), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // Re-detecting on every build self-corrects the command if the user\n // switched package managers since `ahk init` — no migration flag needed.\n mergeCodexConfigToml(join(cwd, '.codex/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n writeSkills(cwd, '.agents/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n }\n\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Permissions sync not needed for codex-cli — skipping')\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport { mergeGrokConfigToml } from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport { agentBuilder, agentConsultant, agentExplorer, agentLead, agentReviewer, agentsMd, HEALTH_SH, translateFrontmatterForGrok } from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** Agent files this provider owns. Shared by `scaffold()` and `build()`.\n *\n * Grok Build's format is markdown + YAML frontmatter, like Claude Code and\n * OpenCode (unlike Codex's TOML), so agent files land at\n * `.grok/agents/<role>.md` with `translateFrontmatterForGrok` applying the\n * provider-native `tools:` allowlist per role. */\nfunction grokAgentFiles(config: HarnessConfig): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.grok/agents/lead.md', content: translateFrontmatterForGrok(agentLead({ projectName }), 'lead') },\n { relPath: '.grok/agents/explorer.md', content: translateFrontmatterForGrok(agentExplorer({ projectName }), 'explorer') },\n { relPath: '.grok/agents/consultant.md', content: translateFrontmatterForGrok(agentConsultant({ projectName }), 'consultant') },\n { relPath: '.grok/agents/builder.md', content: translateFrontmatterForGrok(agentBuilder({ projectName }), 'builder') },\n { relPath: '.grok/agents/reviewer.md', content: translateFrontmatterForGrok(agentReviewer({ projectName }), 'reviewer') },\n ]\n}\n\nexport class GrokMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd } = opts\n\n const write = (relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n }\n\n // AGENTS.md — fresh project, write unconditionally, but STAMP the provenance\n // marker so the first `ahk build` recognizes it as our own output (a\n // markerless file would look human-edited and freeze config propagation).\n // Grok Build, like OpenCode and Codex CLI, gets no second CLAUDE.md-\n // equivalent file — AGENTS.md is the sole provider-agnostic navigation doc.\n write('AGENTS.md', stampGenerated(agentsMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write('health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold — it\n // is accumulable user data reconciled via the DB round-trip in init.ts, so\n // the scaffold no longer writes it (which used to clobber a hand-written\n // backlog).\n\n // scope='global' — current.md lives under ~/.harness/dbs/<projectId>/\n // (see resolveGlobalStorageDir in db.ts), not in the project tree, and\n // `markdownFallback.path` doesn't exist on GlobalStorageConfig at all.\n // Skip the local placeholder entirely for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .grok/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, grokAgentFiles(config))\n\n // .grok/config.toml — MERGE, never overwrite whole file. Native TOML MCP\n // config (task #76 consultant decision — see mergeGrokConfigToml's doc\n // comment for why `.mcp.json` compatibility was rejected). Detect the\n // project's package manager fresh from cwd so the spawned command matches\n // npm/pnpm/yarn.\n mergeGrokConfigToml(join(cwd, '.grok/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n\n appendGitignore(cwd)\n\n // .grok/skills/ — provider-namespaced (task #76 consultant decision: matches\n // Grok Build's own native skill-discovery path, and 2 of 3 existing\n // providers — Claude, OpenCode — already namespace their skills dir).\n writeSkills(cwd, '.grok/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md is DERIVED FROM CONFIG. Reconcile against the provenance marker:\n // untouched files propagate config changes, hand-edited files are preserved\n // (and reported), --force regenerates after backing up.\n const derived = reconcileGeneratedFiles(\n cwd,\n [{ relPath: 'AGENTS.md', content: agentsMd(config) }],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n const agents = writeAgentFiles(cwd, grokAgentFiles(config), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // Re-detecting on every build self-corrects the command if the user\n // switched package managers since `ahk init` — no migration flag needed.\n mergeGrokConfigToml(join(cwd, '.grok/config.toml'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n writeSkills(cwd, '.grok/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n }\n\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Permissions sync not needed for grok-cli — skipping')\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { detectPackageManager } from './detect-package-manager'\nimport { mergeOpencodeJson } from './mcp-merge'\nimport { appendGitignore, reconcileGeneratedFiles, stampGenerated, writeAgentFiles, writeSkills } from './scaffold-utils'\nimport { agentBuilder, agentConsultant, agentExplorer, agentLead, agentReviewer, agentsMd, HEALTH_SH, translateFrontmatterForOpenCode } from './templates'\n\nimport type { BuildMaterializerOptions, BuildReport, Materializer } from './index'\nimport type { AgentFileEntry } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\n/** Agent files this provider owns. Shared by `scaffold()` and `build()`. */\nfunction opencodeAgentFiles(config: HarnessConfig): AgentFileEntry[] {\n const projectName = config.project.name\n return [\n { relPath: '.opencode/agents/lead.md', content: translateFrontmatterForOpenCode(agentLead({ projectName }), 'lead') },\n { relPath: '.opencode/agents/explorer.md', content: translateFrontmatterForOpenCode(agentExplorer({ projectName }), 'explorer') },\n { relPath: '.opencode/agents/consultant.md', content: translateFrontmatterForOpenCode(agentConsultant({ projectName }), 'consultant') },\n { relPath: '.opencode/agents/builder.md', content: translateFrontmatterForOpenCode(agentBuilder({ projectName }), 'builder') },\n { relPath: '.opencode/agents/reviewer.md', content: translateFrontmatterForOpenCode(agentReviewer({ projectName }), 'reviewer') },\n ]\n}\n\nexport class OpenCodeMaterializer implements Materializer {\n async scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void> {\n const { cwd } = opts\n\n const write = (relPath: string, content: string, mode?: number) => {\n const abs = join(cwd, relPath)\n mkdirSync(resolve(abs, '..'), { recursive: true })\n writeFileSync(abs, content, { encoding: 'utf8', mode })\n }\n\n // AGENTS.md — fresh project, write unconditionally, but STAMP the provenance\n // marker so the first `ahk build` recognizes it as our own output (a\n // markerless file would look human-edited and freeze config propagation).\n write('AGENTS.md', stampGenerated(agentsMd(config)))\n\n // health.sh — only create if it doesn't exist\n if (!existsSync(join(cwd, 'health.sh'))) {\n write('health.sh', HEALTH_SH, 0o755)\n }\n\n // .harness/feature_list.json is owned by `runInit`, not the scaffold — it\n // is accumulable user data reconciled via the DB round-trip in init.ts, so\n // the scaffold no longer writes it (which used to clobber a hand-written\n // backlog).\n\n // scope='global' — current.md lives under ~/.harness/dbs/<projectId>/\n // (see resolveGlobalStorageDir in db.ts), not in the project tree, and\n // `markdownFallback.path` doesn't exist on GlobalStorageConfig at all.\n // Skip the local placeholder entirely for that scope.\n if (config.storage.scope === 'local' && !existsSync(join(cwd, config.storage.markdownFallback.path))) {\n write(\n config.storage.markdownFallback.path,\n `<!-- AUTO-GENERATED by agent-harness-kit — DO NOT EDIT MANUALLY -->\\n<!-- Run ahk status to refresh -->\\n\\n# Current Session\\n\\nNo tasks in progress.\\n`\n )\n }\n\n // .opencode/agents/ — user-owned: create when missing, never overwrite\n writeAgentFiles(cwd, opencodeAgentFiles(config))\n\n // opencode.json — MERGE, never overwrite whole file. Detect the project's\n // package manager fresh from cwd so the spawned command matches npm/pnpm/yarn.\n mergeOpencodeJson(join(cwd, 'opencode.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n\n appendGitignore(cwd)\n writeSkills(cwd, '.opencode/skills')\n }\n\n async build(config: HarnessConfig, cwd: string, opts: BuildMaterializerOptions = {}): Promise<BuildReport> {\n // AGENTS.md is DERIVED FROM CONFIG. Reconcile against the provenance marker:\n // untouched files propagate config changes, hand-edited files are preserved\n // (and reported), --force regenerates after backing up.\n const derived = reconcileGeneratedFiles(\n cwd,\n [{ relPath: 'AGENTS.md', content: agentsMd(config) }],\n { force: opts.force, backupRoot: join(cwd, config.storage.dir, 'backups') },\n )\n\n const agents = writeAgentFiles(cwd, opencodeAgentFiles(config), {\n force: opts.force,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n // Re-detecting on every build self-corrects the command if the user\n // switched package managers since `ahk init` — no migration flag needed.\n mergeOpencodeJson(join(cwd, 'opencode.json'), config.tools.mcp.port, cwd, detectPackageManager(cwd))\n writeSkills(cwd, '.opencode/skills')\n\n return { agents, derived }\n }\n\n async migrate(config: HarnessConfig, _to: Provider, _cwd: string): Promise<void> {\n void config\n }\n\n async syncPermissions(_cwd: string): Promise<void> {\n console.log(' Permissions sync not needed for opencode — skipping')\n }\n}\n\n","import { ClaudeCodeMaterializer } from './claude-code'\nimport { CodexCliMaterializer } from './codex-cli'\nimport { GrokMaterializer } from './grok'\nimport { OpenCodeMaterializer } from './opencode'\n\nimport type { ReconcileResult, WriteAgentFilesResult } from './scaffold-utils'\nimport type { HarnessConfig, Provider, ScaffoldOptions } from '@/types'\n\nexport interface BuildMaterializerOptions {\n /** Regenerate agent files that already exist, DESTROYING any customization.\n * A backup of the previous content is written first; if the backup fails,\n * nothing is overwritten. */\n force?: boolean\n /** Claude Code only: per-role model choice collected via\n * `promptClaudeAgentModels`, keyed by `AgentName`. Threaded into\n * `ClaudeCodeMaterializer.build()` to inject a `model:` frontmatter line\n * when regenerating agent files (currently only reachable via\n * `ahk build --force`, which re-runs the prompt). Same shape as\n * `ScaffoldOptions['claudeAgentModels']` — reused verbatim rather than\n * redeclared. Purely additive and optional: `opencode.ts`, `codex-cli.ts`,\n * and `grok.ts` share the identical `build()` signature and simply never\n * read this field. */\n claudeAgentModels?: ScaffoldOptions['claudeAgentModels']\n /** Codex CLI only: per-role model + reasoning-effort choice collected via\n * `promptCodexAgentModels`, keyed by `AgentName`. Same shape as\n * `ScaffoldOptions['codexAgentModels']` — reused verbatim rather than\n * redeclared. Purely additive and optional: `claude-code.ts`, `opencode.ts`,\n * and `grok.ts` share the identical `build()` signature and simply never\n * read this field — this cuts both ways, since `codex-cli.ts` likewise\n * never reads `claudeAgentModels`. */\n codexAgentModels?: ScaffoldOptions['codexAgentModels']\n}\n\nexport interface BuildReport {\n /** What happened to the provider's agent files during this build. */\n agents: WriteAgentFilesResult\n /** What happened to the config-derived files (AGENTS.md, and CLAUDE.md for\n * claude-code) during this build. Untouched files propagate config changes\n * automatically; hand-edited files are preserved and reported. */\n derived: ReconcileResult\n}\n\nexport interface Materializer {\n scaffold(config: HarnessConfig, opts: ScaffoldOptions): Promise<void>\n build(config: HarnessConfig, cwd: string, opts?: BuildMaterializerOptions): Promise<BuildReport>\n migrate(config: HarnessConfig, to: Provider, cwd: string): Promise<void>\n syncPermissions(cwd: string): Promise<void>\n}\n\nexport function getMaterializer(provider: Provider): Materializer {\n switch (provider) {\n case 'claude-code':\n return new ClaudeCodeMaterializer()\n case 'opencode':\n return new OpenCodeMaterializer()\n case 'codex-cli':\n return new CodexCliMaterializer()\n case 'grok-cli':\n return new GrokMaterializer()\n default:\n throw new Error(`Unknown provider: ${provider as string}`)\n }\n}\n","import * as p from '@clack/prompts'\n\nimport type { AgentName } from '@/core/materializer/agent-restrictions'\nimport type { Provider } from '@/types'\n\nconst AGENT_LABELS: { key: AgentName; label: string }[] = [\n { key: 'lead', label: 'Lead' },\n { key: 'explorer', label: 'Explorer' },\n { key: 'consultant', label: 'Consultant' },\n { key: 'builder', label: 'Builder' },\n { key: 'reviewer', label: 'Reviewer' },\n]\n\n/**\n * Claude Code only: prompt once per generated role (lead, explorer,\n * consultant, builder, reviewer) for a model preference, defaulting to\n * 'inherit' (no override). The choice is meant to be written straight into\n * that role's generated `.claude/agents/<role>.md` frontmatter — never into\n * config.\n *\n * Shared by three call sites that all need the identical prompt loop and\n * cancel-handling: `ahk init`'s one-time scaffold, `ahk models`, and\n * `ahk build --force` (claude-code only). Extracted from `runInit` so the\n * loop is defined once instead of triplicated.\n *\n * Returns `{}` immediately for any other provider, so call sites don't need\n * their own provider guard before calling this.\n */\nexport async function promptClaudeAgentModels(\n provider: Provider\n): Promise<Partial<Record<AgentName, string>>> {\n const claudeAgentModels: Partial<Record<AgentName, string>> = {}\n if (provider !== 'claude-code') return claudeAgentModels\n\n for (const agent of AGENT_LABELS) {\n const val = await p.select({\n message: `Model for ${agent.label}`,\n options: [\n { value: 'inherit', label: 'inherit (default)' },\n { value: 'haiku', label: 'haiku' },\n { value: 'sonnet', label: 'sonnet' },\n { value: 'opus', label: 'opus' },\n { value: 'fable', label: 'fable' },\n ],\n initialValue: 'inherit',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n claudeAgentModels[agent.key] = val as string\n }\n\n return claudeAgentModels\n}\n","import * as p from '@clack/prompts'\n\nimport type { AgentName } from '@/core/materializer/agent-restrictions'\nimport type { CodexAgentModelChoice, Provider } from '@/types'\n\nconst AGENT_LABELS: { key: AgentName; label: string }[] = [\n { key: 'lead', label: 'Lead' },\n { key: 'explorer', label: 'Explorer' },\n { key: 'consultant', label: 'Consultant' },\n { key: 'builder', label: 'Builder' },\n { key: 'reviewer', label: 'Reviewer' },\n]\n\n// Verified against Codex CLI's own Rust source (see task #81 consultant\n// advisory for citations): `codex-rs/skills/src/assets/samples/openai-docs/\n// references/latest-model.md` lists these 7 slugs. Six are corroborated by\n// repo-wide code-search hits; `gpt-5.3-codex-spark` has none, but the user\n// explicitly confirmed keeping it (they trust the live picker over a\n// public-repo grep). This is a plain string list, not a TS literal union —\n// model catalogs go stale fast, and a hardcoded compile-time union would\n// turn a stale entry into a hard error for someone hand-editing a newer\n// model into their TOML.\nconst CODEX_MODEL_CHOICES = [\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n 'gpt-5.6-luna',\n 'gpt-5.5',\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.3-codex-spark',\n] as const\n\n// Intersection of Codex's real `ReasoningEffort` wire enum\n// (`codex-rs/protocol/src/openai_models.rs`: none|minimal|low|medium|high|\n// xhigh|max|ultra|Custom) and the whitelist its own per-agent-role-file\n// writer accepts (`codex-rs/external-agent-migration/src/subagents.rs`,\n// `map_agent_reasoning_effort`, which also rewrites max→xhigh and drops\n// ultra). `none` is deliberately excluded from this picker — it disables\n// reasoning entirely, a footgun for a lead/reviewer role; a user who wants\n// it can still hand-edit the TOML.\nconst CODEX_EFFORT_CHOICES = ['minimal', 'low', 'medium', 'high', 'xhigh'] as const\n\n/**\n * Codex CLI only: prompt once per generated role (lead, explorer, consultant,\n * builder, reviewer) for a model AND a reasoning-effort preference. Both\n * choices are written straight into that role's generated\n * `.codex/agents/<role>.toml` (`model = \"...\"` / `model_reasoning_effort =\n * \"...\"` lines) — never into config.toml, which carries its own separate\n * top-level default (see `ensureTomlTopLevelKey` in mcp-merge.ts).\n *\n * Mirrors `promptClaudeAgentModels` (claude-model-prompt.ts) in shape and\n * cancel-handling. Returns `{}` immediately for any other provider, so call\n * sites (currently only `ahk init`) don't need their own provider guard\n * before calling this — and no other provider's init can ever hang on these\n * prompts.\n */\nexport async function promptCodexAgentModels(\n provider: Provider\n): Promise<Partial<Record<AgentName, CodexAgentModelChoice>>> {\n const codexAgentModels: Partial<Record<AgentName, CodexAgentModelChoice>> = {}\n if (provider !== 'codex-cli') return codexAgentModels\n\n for (const agent of AGENT_LABELS) {\n const modelVal = await p.select({\n message: `Model for ${agent.label}`,\n options: CODEX_MODEL_CHOICES.map((value) => ({ value, label: value })),\n initialValue: 'gpt-5.6-terra',\n })\n if (p.isCancel(modelVal)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n\n const effortVal = await p.select({\n message: `Reasoning effort for ${agent.label}`,\n options: CODEX_EFFORT_CHOICES.map((value) => ({ value, label: value })),\n initialValue: 'medium',\n })\n if (p.isCancel(effortVal)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n\n codexAgentModels[agent.key] = {\n model: modelVal as string,\n effort: effortVal as CodexAgentModelChoice['effort'],\n }\n }\n\n return codexAgentModels\n}\n","import { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { startDashboardServer } from '@/core/dashboard-server'\nimport { openDB, resolveSqlitePath } from '@/core/db'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\ninterface DashboardOptions {\n port: number\n open: boolean\n}\n\nexport async function runDashboard(cwd: string, opts: DashboardOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n const dbPath = config.database.type === 'sqlite' ? resolveSqlitePath(config, cwd, homedir()) : null\n const staticPath = join(__dirname, 'dashboard-dist')\n\n const { url } = await startDashboardServer(db, dbPath, staticPath, opts.port)\n\n console.log(pc.green(`✓`) + ` Dashboard running at ${pc.bold(pc.cyan(url))}`)\n console.log(pc.dim(` WebSocket live updates enabled`))\n console.log(pc.dim(` Press Ctrl+C to stop`))\n\n if (opts.open) {\n const { default: open } = await import('open')\n await open(url)\n }\n\n process.on('SIGINT', () => {\n process.exit(0)\n })\n\n // Keep process alive until SIGINT\n await new Promise<void>(() => { })\n}\n","import { watch } from 'node:fs'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { extname, join } from 'node:path'\nimport { serve } from '@hono/node-server'\nimport { Hono } from 'hono'\nimport { WebSocketServer } from 'ws'\n\nimport { DASHBOARD_BIND_HOST, findFreePort } from './port-utils'\n\nimport type { HarnessDB } from './db'\nimport type { EventEmitter } from 'node:events'\nimport type { IncomingMessage } from 'node:http'\nimport type { Socket } from 'node:net'\n\n// ─── Static file serving ──────────────────────────────────────────────────────\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n}\n\nfunction fileResponse(filePath: string): Response {\n const content = readFileSync(filePath)\n const mime = MIME[extname(filePath)] ?? 'application/octet-stream'\n return new Response(content, {\n headers: { 'Content-Type': mime, 'Cache-Control': 'no-cache' },\n })\n}\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\n/**\n * Resolve once the server has actually bound, or reject with an actionable\n * message if the bind fails.\n *\n * `@hono/node-server`'s `serve()` returns synchronously before the bind\n * settles and attaches no `'error'` listener, so a failed bind lands as an\n * unhandled `'error'` event that terminates the process. Awaiting this turns\n * that crash into a rejected promise the caller can report, and also closes the\n * TOCTOU window between the free-port probe and the real bind.\n */\n/**\n * The subset of `http.Server` this helper needs: the `EventEmitter` surface for\n * the one-shot `'error'`/`'listening'` race, plus `close()` so a failed bind can\n * release the handle. `@hono/node-server`'s `serve()` return (`Server`,\n * `Http2Server`, or `Http2SecureServer`) and a bare `node:http` server both\n * satisfy this, so widening the parameter to it breaks no caller.\n */\ntype ClosableServer = EventEmitter & {\n close: (callback?: (err?: Error) => void) => void\n}\n\nexport function awaitServerListening(server: ClosableServer, port: number): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n // Best-effort teardown so a failed bind never leaves the http.Server handle\n // dangling. The server may never have bound (close() then reports\n // ERR_SERVER_NOT_RUNNING): pass a noop callback so that error is delivered to\n // the callback rather than re-emitted as an unhandled 'error' event, and\n // guard any synchronous throw. This must never mask the original\n // bind-failure rejection below, nor settle the promise a second time — the\n // one-shot onError has already been removed by the time it fires, so close()\n // cannot re-enter it.\n const closeQuietly = () => {\n try {\n server.close(() => {\n // swallow ERR_SERVER_NOT_RUNNING / any close error — best-effort\n })\n } catch {\n // handle was never open; nothing to release\n }\n }\n const onError = (err: NodeJS.ErrnoException) => {\n server.off('listening', onListening)\n closeQuietly()\n if (err.code === 'EADDRINUSE') {\n reject(\n new Error(\n `Port ${port} was taken by another process while starting the dashboard. Please retry, or pick a different port with --port.`\n )\n )\n return\n }\n reject(new Error(`Failed to start the dashboard on port ${port}: ${err.message}`))\n }\n const onListening = () => {\n server.off('error', onError)\n resolve()\n }\n server.once('error', onError)\n server.once('listening', onListening)\n })\n}\n\nexport interface DashboardServerResult {\n url: string\n close: () => void\n}\n\nexport async function startDashboardServer(\n db: HarnessDB,\n dbPath: string | null,\n staticPath: string,\n port: number\n): Promise<DashboardServerResult> {\n const app = new Hono()\n const { tasks, actions, stats } = db\n\n // ─── CORS ─────────────────────────────────────────────────────────────────\n app.use('/api/*', async (c, next) => {\n await next()\n c.res.headers.set('Access-Control-Allow-Origin', '*')\n })\n\n // ─── Stats overview ───────────────────────────────────────────────────────\n app.get('/api/stats', async (c) => {\n await db.reconnect()\n const summary = await tasks.getStatusSummary()\n const byStatus: Record<string, number> = { pending: 0, in_progress: 0, done: 0, blocked: 0 }\n for (const { status, total } of summary) byStatus[status] = total\n const counts = await stats.getCounts()\n return c.json({ byStatus, ...counts })\n })\n\n // ─── Meta ─────────────────────────────────────────────────────────────────\n app.get('/api/meta', (c) => {\n return c.json({ ok: true })\n })\n\n // ─── Tasks list ───────────────────────────────────────────────────────────\n app.get('/api/tasks', async (c) => {\n await db.reconnect()\n const includeArchived = c.req.query('includeArchived') === 'true'\n return c.json(await tasks.getAllWithAcceptanceCounts(includeArchived))\n })\n\n // ─── Task detail ──────────────────────────────────────────────────────────\n app.get('/api/tasks/:id', async (c) => {\n await db.reconnect()\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n\n const acceptance = await tasks.getAcceptance(id)\n const taskActions = await actions.getWithDetails(id)\n return c.json({ ...task, acceptance, actions: taskActions })\n })\n\n // ─── Task update (PATCH) ────────────────────────────────────────────────\n app.patch('/api/tasks/:id', async (c) => {\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n\n const body = await c.req.json()\n const updateParams: { title?: string; description?: string | null; slug?: string } = {}\n if (body.title !== undefined) updateParams.title = body.title\n if (body.description !== undefined) updateParams.description = body.description\n\n await db.updateTask(id, updateParams)\n\n if (body.acceptance !== undefined && Array.isArray(body.acceptance)) {\n await db.updateTaskAcceptance(\n id,\n body.acceptance.map((a: string) => a.trim()).filter(Boolean)\n )\n }\n\n const updated = await tasks.getById(id)\n const acceptance = await tasks.getAcceptance(id)\n const taskActions = await actions.getWithDetails(id)\n return c.json({ ...updated, acceptance, actions: taskActions })\n })\n\n // ─── Archive task ─────────────────────────────────────────────────────────\n app.patch('/api/tasks/:id/archive', async (c) => {\n await db.reconnect()\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n const updated = await db.archiveTask(id)\n return c.json(updated)\n })\n\n // ─── Unarchive task ──────────────────────────────────────────────────────\n app.patch('/api/tasks/:id/unarchive', async (c) => {\n await db.reconnect()\n const id = parseInt(c.req.param('id'))\n const task = await tasks.getById(id)\n if (!task) return c.json({ error: 'Not found' }, 404)\n const updated = await db.unarchiveTask(id)\n return c.json(updated)\n })\n\n // ─── Tools top ────────────────────────────────────────────────────────────\n app.get('/api/tools/top', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '20')\n return c.json(await actions.getTopTools(limit))\n })\n\n // ─── Tools recent ─────────────────────────────────────────────────────────\n app.get('/api/tools/recent', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '50')\n return c.json(await stats.getRecentTools(limit))\n })\n\n // ─── Files top ────────────────────────────────────────────────────────────\n app.get('/api/files/top', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '20')\n return c.json(await stats.getTopFiles(limit))\n })\n\n // ─── Files recent ─────────────────────────────────────────────────────────\n app.get('/api/files/recent', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '50')\n return c.json(await stats.getRecentFiles(limit))\n })\n\n // ─── Agents stats ─────────────────────────────────────────────────────────\n app.get('/api/agents/stats', async (c) => {\n await db.reconnect()\n return c.json(await stats.getAgentStats())\n })\n\n // ─── Timeline ─────────────────────────────────────────────────────────────\n app.get('/api/timeline', async (c) => {\n await db.reconnect()\n const limit = parseInt(c.req.query('limit') ?? '50')\n return c.json(await stats.getTimeline(limit))\n })\n\n // ─── Static SPA ───────────────────────────────────────────────────────────\n app.get('/*', (c) => {\n const urlPath = c.req.path\n if (urlPath !== '/') {\n const candidate = join(staticPath, urlPath)\n if (existsSync(candidate)) {\n try {\n return fileResponse(candidate)\n } catch {\n /* fall through */\n }\n }\n }\n return fileResponse(join(staticPath, 'index.html'))\n })\n\n // ─── Start HTTP server ────────────────────────────────────────────────────\n // The probe and the real bind MUST use the same host, otherwise the probe can\n // report an occupied port as free (see DASHBOARD_BIND_HOST).\n const resolvedPort = await findFreePort(port, { host: DASHBOARD_BIND_HOST })\n if (resolvedPort !== port) {\n console.log(`Port ${port} in use, using ${resolvedPort}`)\n }\n\n const httpServer = serve({\n fetch: app.fetch,\n port: resolvedPort,\n hostname: DASHBOARD_BIND_HOST,\n })\n\n // serve() returns before the bind settles and attaches no 'error' listener,\n // so an EADDRINUSE would otherwise surface as an unhandled event that kills\n // the process *after* the caller already printed a success banner. Wait for\n // the bind to resolve one way or the other before returning.\n await awaitServerListening(httpServer, resolvedPort)\n\n // Keep a handler attached for the server's lifetime so a later runtime error\n // is reported rather than crashing the process as an unhandled event.\n httpServer.on('error', (err: NodeJS.ErrnoException) => {\n console.error(`Dashboard server error: ${err.message}`)\n })\n\n // ─── WebSocket ────────────────────────────────────────────────────────────\n const wss = new WebSocketServer({ noServer: true })\n\n httpServer.on('upgrade', (req: IncomingMessage, socket: Socket, head: Buffer) => {\n if (req.url === '/ws') {\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit('connection', ws, req)\n })\n } else {\n socket.destroy()\n }\n })\n\n // ─── DB file watcher → broadcast update ──────────────────────────────────\n let debounce: ReturnType<typeof setTimeout>\n\n const broadcast = () => {\n clearTimeout(debounce)\n debounce = setTimeout(() => {\n for (const client of wss.clients) {\n if (client.readyState === 1) {\n client.send(JSON.stringify({ type: 'update' }))\n }\n }\n }, 150)\n }\n\n // SQLite only — no file to watch for Postgres/MySQL\n let watcher: ReturnType<typeof watch> | null = null\n if (dbPath) {\n const walPath = `${dbPath}-wal`\n const watchTarget = existsSync(walPath) ? walPath : dbPath\n watcher = watch(watchTarget, broadcast)\n }\n\n return {\n url: `http://localhost:${resolvedPort}`,\n close: () => {\n clearTimeout(debounce)\n watcher?.close()\n wss.close()\n httpServer.close()\n },\n }\n}\n","import { createServer } from 'node:net'\n\n/**\n * The host the dashboard binds to — the single source of truth shared by the\n * availability probe (`isPortFree`) and the real HTTP bind in\n * `startDashboardServer`.\n *\n * `undefined` means \"the Node default wildcard\": `::` on dual-stack hosts,\n * `0.0.0.0` on IPv4-only hosts. This is exactly what `@hono/node-server`'s\n * `serve()` binds when no `hostname` is supplied, so probe and bind cannot\n * disagree.\n *\n * Why not a literal like '127.0.0.1' or '::'?\n * - '127.0.0.1' was the original bug: a socket held on '::' does not block a\n * fresh 127.0.0.1 bind on macOS, so the probe reported occupied ports free,\n * the fallback never fired, and serve() then died on EADDRINUSE.\n * - A hardcoded '::' would fail with EADDRNOTAVAIL on IPv4-only hosts, making\n * every port look occupied.\n * Deferring to the platform default keeps probe and bind identical on every\n * platform. Both consumers must read this constant — never inline a host.\n */\nexport const DASHBOARD_BIND_HOST: string | undefined = undefined\n\nexport interface FindFreePortOptions {\n /** How many consecutive ports to try before giving up. */\n maxAttempts?: number\n /** Host to probe. Must match the host the caller will actually bind to. */\n host?: string\n}\n\n/**\n * Probe whether `port` can be bound on `host`.\n *\n * The host argument is required-by-convention: callers must pass the same host\n * they intend to bind on, otherwise the probe answers a different question than\n * the one being asked.\n */\nexport function isPortFree(port: number, host: string | undefined = DASHBOARD_BIND_HOST): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer()\n server.once('error', () => resolve(false))\n server.once('listening', () => {\n server.close(() => resolve(true))\n })\n server.listen(port, host)\n })\n}\n\nexport async function findFreePort(start: number, options: FindFreePortOptions = {}): Promise<number> {\n const { maxAttempts = 10, host = DASHBOARD_BIND_HOST } = options\n\n // Guard the boundary. `start` MUST be a number: the loop below computes\n // `start + i`, which silently becomes string concatenation if a string slips\n // through ('4242' + 0 === '42420'), producing a nonsense probe port and no\n // usable error. Commander hands `--port` over as a string (cli.ts:135), so\n // the sole caller coerces it (cli.ts:138). This check makes that contract\n // enforced rather than merely observed — if the coercion is ever removed,\n // the failure is loud and immediate instead of a bizarre port number.\n if (typeof start !== 'number' || !Number.isInteger(start)) {\n throw new Error(\n `findFreePort requires an integer port number, received ${typeof start} ${JSON.stringify(start)}. ` +\n `The port must be coerced to a number before it reaches here (commander supplies --port as a string).`\n )\n }\n\n for (let i = 0; i < maxAttempts; i++) {\n const port = start + i\n if (await isPortFree(port, host)) return port\n }\n\n throw new Error(\n `Could not find a free port after ${maxAttempts} attempts (tried ${start}-${start + maxAttempts - 1}). Please free a port and try again.`\n )\n}\n","import pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { getDoctorStatus } from '@/core/doctor'\n\nimport type { AgentStatus, SkillStatus } from '@/core/doctor'\n\n// ─── Formatting helpers ───────────────────────────────────────────────────────\n\nfunction ok(label: string, detail: string): void {\n console.log(` ${pc.cyan(label.padEnd(16))}${pc.green('[✓]')} ${detail}`)\n}\n\nfunction warn(label: string, detail: string, hint?: string): void {\n console.log(` ${pc.cyan(label.padEnd(16))}${pc.yellow('[!]')} ${detail}`)\n if (hint) {\n console.log(` ${''.padEnd(16)} ${pc.dim(hint)}`)\n }\n}\n\nfunction neutral(label: string, detail: string): void {\n console.log(` ${pc.cyan(label.padEnd(16))}${pc.dim('[~]')} ${detail}`)\n}\n\n// ─── Section formatters ───────────────────────────────────────────────────────\n\nfunction printLibSection(lib: { current: string; latest: string | null; outdated: boolean }): void {\n if (lib.latest === null) {\n neutral('lib version', `${lib.current} (unknown — could not reach npm registry)`)\n } else if (lib.outdated) {\n warn(\n 'lib version',\n `${lib.current} → ${lib.latest} available`,\n `run: npm i @cardor/agent-harness-kit@latest && ahk build`\n )\n } else {\n ok('lib version', `${lib.current} (up to date)`)\n }\n}\n\nfunction printAgentsSection(agents: AgentStatus[]): void {\n if (agents.length === 0) {\n warn('agent files', 'no config found — run: ahk init')\n return\n }\n\n // Existence only — a customised agent file is a supported state, not drift.\n const missing = agents.filter((a) => a.status === 'missing')\n\n if (missing.length === 0) {\n ok('agent files', 'all present')\n return\n }\n\n for (const agent of missing) {\n warn('agent files', `${agent.name} missing`, 'run: ahk build')\n }\n}\n\nfunction printSkillsSection(skills: SkillStatus[]): void {\n if (skills.length === 0) {\n warn('harness skills', 'no config found — run: ahk init')\n return\n }\n\n const issues = skills.filter((s) => s.status !== 'ok')\n if (issues.length === 0) {\n ok('harness skills', 'all present and up to date')\n return\n }\n\n for (const skill of issues) {\n const detail =\n skill.status === 'missing' ? `${skill.name} missing` : `${skill.name} outdated`\n warn('harness skills', detail, 'run: ahk build')\n }\n}\n\n// ─── Main command ─────────────────────────────────────────────────────────────\n\nexport async function runDoctor(cwd: string): Promise<void> {\n // Check for config first so we can give a helpful upfront message\n let configFound = true\n try {\n await loadConfig(cwd)\n } catch {\n configFound = false\n }\n\n console.log('')\n console.log(pc.bold(`● ahk doctor ` + '─'.repeat(44)))\n console.log('')\n\n const status = await getDoctorStatus(cwd)\n\n printLibSection(status.lib)\n\n if (!configFound) {\n console.log('')\n warn('config', 'no agent-harness-kit.config found', 'run: ahk init')\n console.log('')\n return\n }\n\n console.log('')\n printAgentsSection(status.agents)\n\n console.log('')\n printSkillsSection(status.skills)\n\n console.log('')\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { loadConfig } from '@/core/config'\nimport { pkg } from '@/core/package-data'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface LibStatus {\n current: string\n latest: string | null // null = couldn't fetch (offline)\n outdated: boolean\n}\n\n/**\n * Agent files are checked for EXISTENCE ONLY — there is deliberately no\n * 'outdated' state. Agent definitions are meant to be customised freely (body\n * and frontmatter alike), so comparing them against the packaged template would\n * flag every intentional edit as drift. Skills keep their content comparison;\n * they are not a customisation surface.\n */\nexport interface AgentStatus {\n name: string\n status: 'ok' | 'missing'\n}\n\nexport interface SkillStatus {\n name: string\n status: 'ok' | 'missing' | 'outdated'\n}\n\nexport interface DoctorStatus {\n lib: LibStatus\n agents: AgentStatus[]\n skills: SkillStatus[]\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`\nconst TIMEOUT_MS = 2000\nconst LIB_VERSION_CACHE_TTL_MS = 5 * 60 * 1000 // 5 minutes\nconst AGENT_NAMES = ['lead', 'explorer', 'consultant', 'builder', 'reviewer'] as const\nexport type AgentName = (typeof AGENT_NAMES)[number]\nconst SKILL_NAMES = ['ahk-ask', 'ahk-consultant', 'ahk-triage', 'ahk-review', 'ahk-test'] as const\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n// ─── Lib version check ────────────────────────────────────────────────────────\n\n// In-memory TTL cache for the npm registry lookup only. Agent/skill file checks\n// are local and cheap, so they are intentionally NOT cached — only the network\n// call to the npm registry benefits from memoization.\nlet libVersionCache: { status: LibStatus; fetchedAt: number } | null = null\n\n/** Clears the in-memory lib version cache. Exposed for tests only. */\nexport function __resetLibVersionCacheForTests(): void {\n libVersionCache = null\n}\n\nasync function checkLibVersion(): Promise<LibStatus> {\n const current = pkg.version\n\n if (libVersionCache && Date.now() - libVersionCache.fetchedAt < LIB_VERSION_CACHE_TTL_MS) {\n // Cache is keyed to the running process's current version. If somehow the\n // running version changed (unlikely mid-process), fall through to refetch.\n if (libVersionCache.status.current === current) {\n return libVersionCache.status\n }\n }\n\n try {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), TIMEOUT_MS)\n\n const res = await fetch(REGISTRY_URL, { signal: controller.signal })\n clearTimeout(timer)\n\n const data = (await res.json()) as { version: string }\n const latest = data.version\n const outdated = isNewer(latest, current)\n const status: LibStatus = { current, latest, outdated }\n libVersionCache = { status, fetchedAt: Date.now() }\n return status\n } catch {\n const status: LibStatus = { current, latest: null, outdated: false }\n // Cache the offline result too, so repeated calls within the TTL don't\n // keep retrying a network call that just timed out/failed.\n libVersionCache = { status, fetchedAt: Date.now() }\n return status\n }\n}\n\nfunction isNewer(latest: string, current: string): boolean {\n const toNum = (v: string) => v.split('.').map(Number)\n const [lMaj, lMin, lPat] = toNum(latest)\n const [cMaj, cMin, cPat] = toNum(current)\n if (lMaj !== cMaj) return lMaj > cMaj\n if (lMin !== cMin) return lMin > cMin\n return lPat > cPat\n}\n\n// ─── Agent file check ─────────────────────────────────────────────────────────\n\nfunction getProviderAgentInfo(provider: string): {\n agentsDir: string\n ext: string\n} {\n switch (provider) {\n case 'claude-code':\n return { agentsDir: '.claude/agents', ext: '.md' }\n case 'opencode':\n return { agentsDir: '.opencode/agents', ext: '.md' }\n case 'codex-cli':\n return { agentsDir: '.codex/agents', ext: '.toml' }\n case 'grok-cli':\n return { agentsDir: '.grok/agents', ext: '.md' }\n default:\n return { agentsDir: '.claude/agents', ext: '.md' }\n }\n}\n\n// Root-based existence check — shared by both the project-local (cwd) and\n// global (homeDir) checks. Callers resolve `agentsRoot` to an absolute\n// directory; this function never derives paths on its own.\n//\n// Existence is the ONLY signal. The file's contents are never read, so any\n// hand-editing of an agent definition is invisible here by design.\nfunction checkAgentFilesAtRoot(agentsRoot: string, ext: string): AgentStatus[] {\n return AGENT_NAMES.map((name) => {\n const filePath = join(agentsRoot, `${name}${ext}`)\n return { name, status: existsSync(filePath) ? ('ok' as const) : ('missing' as const) }\n })\n}\n\nfunction checkAgentFiles(cwd: string, provider: string): AgentStatus[] {\n const { agentsDir, ext } = getProviderAgentInfo(provider)\n return checkAgentFilesAtRoot(join(cwd, agentsDir), ext)\n}\n\n// ─── Skill check ─────────────────────────────────────────────────────────────\n\nfunction getProviderSkillsDir(provider: string): string {\n switch (provider) {\n case 'claude-code':\n return '.claude/skills'\n case 'opencode':\n return '.opencode/skills'\n case 'codex-cli':\n return '.agents/skills'\n case 'grok-cli':\n return '.grok/skills'\n default:\n return '.claude/skills'\n }\n}\n\n// Root-based comparison — shared by both the project-local (cwd) and global\n// (homeDir) checks. `skillsRoot` is an absolute directory already resolved\n// by the caller.\nfunction checkSkillsAtRoot(skillsRoot: string): SkillStatus[] {\n // Skills are in src/core/materializer/skills/ — at runtime dist/core/materializer/skills/\n const skillSourceBase = join(__dirname, 'materializer', 'skills')\n\n return SKILL_NAMES.map((name) => {\n const livePath = join(skillsRoot, name, 'SKILL.md')\n const sourcePath = join(skillSourceBase, name, 'SKILL.md')\n\n if (!existsSync(livePath)) {\n return { name, status: 'missing' as const }\n }\n\n try {\n const live = readFileSync(livePath, 'utf8')\n const source = readFileSync(sourcePath, 'utf8')\n return { name, status: live === source ? 'ok' : 'outdated' }\n } catch {\n return { name, status: 'outdated' as const }\n }\n })\n}\n\nfunction checkSkills(cwd: string, provider: string): SkillStatus[] {\n const skillsDir = getProviderSkillsDir(provider)\n return checkSkillsAtRoot(join(cwd, skillsDir))\n}\n\n// ─── Main export ──────────────────────────────────────────────────────────────\n\nexport async function getDoctorStatus(cwd: string): Promise<DoctorStatus> {\n const lib = await checkLibVersion()\n\n let config\n try {\n config = await loadConfig(cwd)\n } catch {\n // Config not found — return minimal status with empty agent/skill checks\n return {\n lib,\n agents: [],\n skills: [],\n }\n }\n\n const provider = config.provider\n\n const agents = checkAgentFiles(cwd, provider)\n const skills = checkSkills(cwd, provider)\n\n return { lib, agents, skills }\n}\n","import { writeFileSync } from 'node:fs'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\ninterface ExportOptions {\n sql?: boolean\n json?: boolean\n output?: string\n}\n\nexport async function runExport(cwd: string, opts: ExportOptions): Promise<void> {\n if (!opts.sql && !opts.json) {\n console.error(pc.red('Specify --sql or --json'))\n process.exit(1)\n }\n\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n if (opts.json) {\n const data = await db.exportJson()\n const out = JSON.stringify(data, null, 2) + '\\n'\n if (opts.output) {\n writeFileSync(opts.output, out, 'utf8')\n console.log(pc.green(`✓ Exported JSON → ${opts.output}`))\n } else {\n process.stdout.write(out)\n }\n }\n\n if (opts.sql) {\n console.error(pc.dim('SQL dump requires direct SQLite access — use: sqlite3 .harness/harness.db .dump'))\n process.exit(1)\n }\n } finally {\n await db.close()\n }\n}\n","import { spawnSync } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { resolveSqlitePath } from '@/core/db'\n\nimport type { HarnessConfig } from '@/types'\n\nfunction checkLine(label: string | null, ok: boolean, message: string, indent = 0): void {\n const prefix = label ? pc.cyan(`[${label}] `) : ' '.repeat(indent)\n const icon = ok ? pc.green('✓') : pc.red('✗')\n console.log(prefix + icon + ' ' + (ok ? pc.green(message) : pc.red(message)))\n}\n\nexport async function runHealth(cwd: string): Promise<void> {\n let config\n try {\n config = await loadConfig(cwd)\n } catch {\n console.error(pc.red('✗ No config found. Run: ahk init'))\n process.exit(1)\n }\n\n let allOk = true\n\n // ─── [checking DB] ──────────────────────────────────────────────────────────\n let dbOk: boolean\n if (config.database.type === 'sqlite') {\n const dbPath = resolveSqlitePath(config, cwd, homedir())\n dbOk = existsSync(dbPath)\n checkLine('checking DB', dbOk, `${dbPath} reachable`)\n } else {\n // For remote DBs we can't check the file — assume reachable (openDB will fail fast if not)\n dbOk = true\n checkLine('checking DB', true, `${config.database.type}://${config.database.connectionString.replace(/:[^:@]*@/, ':***@')} configured`)\n }\n if (!dbOk) allOk = false\n\n // ─── [checking agents] ──────────────────────────────────────────────────────\n const providerFiles = getProviderHealthFiles(config.provider)\n const agentsDir = providerFiles.agentsDir\n const agentNames = ['lead', 'explorer', 'consultant', 'builder', 'reviewer']\n\n const agentsLabelWidth = '[checking agents] '.length\n for (let i = 0; i < agentNames.length; i++) {\n const name = agentNames[i]\n const agentPath = join(cwd, agentsDir, `${name}${providerFiles.agentExtension}`)\n const ok = existsSync(agentPath)\n checkLine(\n i === 0 ? 'checking agents' : null,\n ok,\n `${name}${providerFiles.agentExtension} present`,\n agentsLabelWidth,\n )\n if (!ok) allOk = false\n }\n\n // ─── [checking MCP] ─────────────────────────────────────────────────────────\n if (config.tools.mcp.enabled) {\n const mcpFile = providerFiles.mcpFile\n const mcpPath = resolve(cwd, mcpFile)\n const mcpOk = existsSync(mcpPath)\n checkLine('checking MCP', mcpOk, `${mcpFile} valid`)\n if (!mcpOk) allOk = false\n }\n\n if (!allOk) {\n console.log('')\n console.error(pc.red('✗ Harness checks failed — fix the above before running health.sh'))\n process.exit(1)\n }\n\n // ─── Run health.sh ──────────────────────────────────────────────────────────\n const scriptPath = resolve(cwd, config.health.scriptPath)\n\n if (!existsSync(scriptPath)) {\n console.error(pc.red(`✗ health.sh not found: ${scriptPath}`))\n console.error(' Run ahk init first.')\n process.exit(1)\n }\n\n const result = spawnSync('bash', [scriptPath], {\n cwd,\n stdio: 'inherit',\n encoding: 'utf8',\n })\n\n if (result.error) {\n console.error(pc.red(`✗ Failed to run health.sh: ${result.error.message}`))\n process.exit(1)\n }\n\n if (result.status === 0) {\n console.log(pc.green('✓ Health check passed'))\n process.exit(0)\n } else {\n console.error(pc.red(`✗ Health check failed (exit ${result.status ?? 'unknown'})`))\n process.exit(result.status ?? 1)\n }\n}\n\nfunction getProviderHealthFiles(provider: HarnessConfig['provider']): {\n agentsDir: string\n agentExtension: '.md' | '.toml'\n mcpFile: string\n} {\n switch (provider) {\n case 'claude-code':\n return { agentsDir: '.claude/agents', agentExtension: '.md', mcpFile: '.mcp.json' }\n case 'opencode':\n return { agentsDir: '.opencode/agents', agentExtension: '.md', mcpFile: 'opencode.json' }\n case 'codex-cli':\n return { agentsDir: '.codex/agents', agentExtension: '.toml', mcpFile: '.codex/config.toml' }\n case 'grok-cli':\n return { agentsDir: '.grok/agents', agentExtension: '.md', mcpFile: '.grok/config.toml' }\n default:\n throw new Error(`Unknown provider: ${provider as string}`)\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { findConfigFile } from '@/core/config'\nimport { type HarnessDB, openDB } from '@/core/db'\nimport { getMaterializer } from '@/core/materializer/index'\nimport { slugify } from '@/core/materializer/scaffold-utils'\nimport { configCjs, configJson, configMjs, configTs } from '@/core/materializer/templates'\nimport { initDescriptionSchema, initDocsSchema, initNameSchema } from '@/schema/init'\nimport { taskDescriptionSchema, taskTitleSchema } from '@/schema/task'\nimport { cliFormWithRetry } from '@/utils/form'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\nimport { promptCodexAgentModels } from './codex-model-prompt'\nimport {\n applyConfigDefaults,\n detectConfigExtension,\n drawBox,\n printWelcomeMessage,\n readProjectNameFromPackageJson,\n} from './init-helpers'\n\nimport type { Provider } from '@/types'\n\ninterface InitOptions {\n name?: string\n provider?: string\n docs?: string\n tasks?: string\n storageScope?: string\n}\n\n/**\n * Reconcile `.harness/feature_list.json` — the \"human-editable task seed list\".\n *\n * This file is accumulable user data, so init MERGES rather than overwrites:\n * any hand-written backlog is absorbed into the DB (dedup by slug) alongside the\n * optional firstTask, then the canonical file is re-emitted. This is the same\n * round-trip `ahk sync both` performs, so init and sync agree on what the file\n * means. Merge is non-destructive by construction: it never destroys an existing\n * backlog and never drops a supplied firstTask.\n *\n * A malformed feature_list.json is still the user's data: it is left\n * byte-for-byte intact (never overwritten, never a process.exit), a supplied\n * firstTask is still seeded into the DB, and `parseFailed` is returned so the\n * caller can warn.\n */\nexport async function reconcileFeatureList(\n db: HarnessDB,\n installDir: string,\n storageDir: string,\n firstTask?: { title: string; description?: string; acceptance?: string[] }\n): Promise<{ parseFailed: boolean }> {\n const featureListPath = join(installDir, storageDir, 'feature_list.json')\n\n let existingSeeds: { slug: string; title: string; description?: string; acceptance?: string[] }[] = []\n let parseFailed = false\n if (existsSync(featureListPath)) {\n try {\n const parsed = JSON.parse(readFileSync(featureListPath, 'utf8'))\n if (!Array.isArray(parsed)) throw new Error('feature_list.json is not a JSON array')\n existingSeeds = parsed\n } catch {\n parseFailed = true\n }\n }\n\n const firstTaskSeed = firstTask\n ? {\n slug: slugify(firstTask.title),\n title: firstTask.title,\n description: firstTask.description,\n acceptance: firstTask.acceptance,\n }\n : undefined\n\n if (parseFailed) {\n // Do NOT touch the malformed file. Still seed the supplied firstTask into\n // the DB so it is not dropped.\n if (firstTaskSeed) await db.syncFromFeatureList([firstTaskSeed])\n } else {\n const seeds = firstTaskSeed ? [...existingSeeds, firstTaskSeed] : existingSeeds\n // Single dedup-by-slug merge (absorbs backlog + firstTask, collapses a\n // firstTask whose slug already exists), then re-emit the canonical file.\n await db.syncFromFeatureList(seeds)\n await db.writeFeatureList(installDir)\n }\n\n return { parseFailed }\n}\n\nexport async function runInit(cwd: string, flags: InitOptions): Promise<void> {\n const existingConfig = findConfigFile(cwd)\n if (existingConfig) {\n console.log(\n pc.yellow('⚠') +\n ' ' +\n pc.bold('Project already initialized.') +\n pc.dim(` (${existingConfig})`)\n )\n console.log()\n console.log(pc.dim('Suggested next steps:'))\n console.log(\n ' ' +\n pc.cyan('ahk build') +\n pc.dim(' — re-sync agent files after updating the library')\n )\n console.log(' ' + pc.cyan('ahk build --sync') + pc.dim(' — also sync agent permissions'))\n console.log(\n ' ' + pc.cyan('ahk reset') + pc.dim(' — wipe and re-initialize from scratch')\n )\n console.log(' ' + pc.cyan('ahk dashboard') + pc.dim(' — open the harness dashboard'))\n process.exit(0)\n }\n\n const detectedName = flags.name ?? readProjectNameFromPackageJson(cwd)\n const projectName = detectedName || 'my-project'\n printWelcomeMessage(projectName)\n\n // ─── Project name ────────────────────────────────────────────────────────\n let name: string\n if (flags.name) {\n name = flags.name\n } else {\n name = await cliFormWithRetry(async () => {\n const val = await p.text({\n message: 'Project name',\n placeholder: 'my-app',\n ...(detectedName && { initialValue: detectedName }),\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n return val as string\n }, initNameSchema)\n }\n\n // ─── Description ─────────────────────────────────────────────────────────\n const description = await cliFormWithRetry(async () => {\n const val = await p.text({\n message: 'Short description (shown to agents as context)',\n placeholder: 'A REST API for managing notes',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n return val as string\n }, initDescriptionSchema)\n\n // ─── Provider ─────────────────────────────────────────────────────────────\n let provider: Provider\n if (flags.provider && ['claude-code', 'opencode', 'codex-cli', 'grok-cli'].includes(flags.provider)) {\n provider = flags.provider as Provider\n } else {\n const val = await p.select({\n message: 'AI provider',\n options: [\n { value: 'opencode', label: 'OpenCode' },\n { value: 'claude-code', label: 'Claude Code' },\n { value: 'codex-cli', label: 'Codex CLI' },\n { value: 'grok-cli', label: 'Grok CLI' },\n ],\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n provider = val satisfies Provider\n }\n\n // Claude Code only: prompt once per generated role (lead, explorer,\n // consultant, builder, reviewer) for a model preference, defaulting to\n // 'inherit' (no override). The choice is written straight into that role's\n // generated `.claude/agents/<role>.md` frontmatter at scaffold time — never\n // into config (the old `config.agents.<role>.model` mechanism stays\n // removed). OpenCode is unaffected — it has no closed model enum to prompt\n // against.\n //\n // The prompt loop itself lives in `promptClaudeAgentModels` (shared with\n // `ahk models` and `ahk build --force`, which also re-run it to update an\n // existing project's agent files — see claude-code.ts).\n const claudeAgentModels = await promptClaudeAgentModels(provider)\n\n // Codex CLI only: prompt once per generated role for a model AND a\n // reasoning-effort preference. Both choices are written straight into that\n // role's generated `.codex/agents/<role>.toml` at scaffold time — never\n // into config.toml, which carries its own separate top-level default (see\n // `ensureTomlTopLevelKey` in mcp-merge.ts). OpenCode and Grok Build are\n // unaffected — same rationale as above.\n //\n // The prompt loop itself lives in `promptCodexAgentModels`\n // (codex-model-prompt.ts), mirroring `promptClaudeAgentModels`'s shape and\n // cancel-handling.\n const codexAgentModels = await promptCodexAgentModels(provider)\n\n // ─── Docs path ────────────────────────────────────────────────────────────\n let docsPath: string\n if (flags.docs) {\n docsPath = flags.docs\n } else {\n docsPath = await cliFormWithRetry(async () => {\n const val = await p.text({\n message: 'Docs folder path (agents will search here)',\n initialValue: './docs',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n return val as string\n }, initDocsSchema)\n }\n\n // ─── Storage scope ────────────────────────────────────────────────────────\n let storageScope: 'local' | 'global'\n if (flags.storageScope && ['local', 'global'].includes(flags.storageScope)) {\n storageScope = flags.storageScope as 'local' | 'global'\n } else {\n const val = await p.select({\n message: 'Storage scope',\n options: [\n { value: 'local', label: 'Local — .harness/harness.db lives in this project' },\n {\n value: 'global',\n label: 'Global — DB lives under ~/.harness/dbs/<projectId>/, outside the project',\n },\n ],\n initialValue: 'local',\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n storageScope = val as 'local' | 'global'\n }\n\n // ─── Task adapter ─────────────────────────────────────────────────────────\n let tasksAdapter: string\n if (flags.tasks && ['local', 'jira', 'linear'].includes(flags.tasks)) {\n tasksAdapter = flags.tasks\n } else {\n const val = await p.select({\n message: 'Task adapter',\n options: [\n { value: 'local', label: 'Local (feature_list.json)' },\n { value: 'jira', label: 'Jira (coming soon)' },\n { value: 'linear', label: 'Linear (coming soon)' },\n ],\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n tasksAdapter = val as string\n }\n\n // ─── Optional first task ──────────────────────────────────────────────────\n const addFirstTask = await p.confirm({ message: 'Add your first task now?', initialValue: false })\n if (p.isCancel(addFirstTask)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n\n let firstTask: { title: string; description: string; acceptance: string[] } | undefined\n\n if (addFirstTask) {\n const taskTitle = await cliFormWithRetry(async () => {\n const val = await p.text({ message: 'Task title' })\n if (p.isCancel(val)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n return (val as string).trim()\n }, taskTitleSchema)\n\n const taskDesc = await cliFormWithRetry(async () => {\n const val = await p.text({ message: 'Task description', placeholder: 'What and why' })\n if (p.isCancel(val)) {\n p.cancel('Cancelled')\n process.exit(0)\n }\n return (val as string).trim()\n }, taskDescriptionSchema)\n\n const acceptance: string[] = []\n p.log.info('Acceptance criteria — one per line, empty line to finish')\n while (true) {\n const criterionVal = await p.text({\n message: '>',\n placeholder: 'Criterion (or press Enter to finish)',\n })\n if (p.isCancel(criterionVal) || !criterionVal || !(criterionVal as string).trim()) break\n acceptance.push((criterionVal as string).trim())\n }\n\n firstTask = { title: taskTitle, description: taskDesc, acceptance }\n }\n\n // ─── Scaffold ─────────────────────────────────────────────────────────────\n let configExt: 'json' | 'ts' | 'mjs' | 'cjs' = 'ts'\n let featureListParseFailedPath: string | null = null\n const spinner = p.spinner()\n spinner.start('Scaffolding...')\n\n try {\n const config = applyConfigDefaults({\n name,\n description,\n provider,\n docsPath,\n tasksAdapter,\n scope: storageScope,\n })\n const materializer = getMaterializer(provider)\n\n const installDir = cwd\n\n configExt = detectConfigExtension(cwd)\n const configFileName = `agent-harness-kit.config.${configExt}`\n const templateFn =\n configExt === 'json'\n ? configJson\n : configExt === 'ts'\n ? configTs\n : configExt === 'mjs'\n ? configMjs\n : configCjs\n const configContent = templateFn({\n name,\n description,\n provider,\n docsPath,\n tasksAdapter,\n port: config.tools.mcp.port,\n scope: config.storage.scope,\n projectId: config.storage.projectId,\n })\n writeFileSync(join(installDir, configFileName), configContent, 'utf8')\n\n // Create .harness dir (always project-local, regardless of storage scope —\n // this is where health.sh, scripts, and storage-state.json live)\n mkdirSync(join(installDir, config.storage.dir), { recursive: true })\n\n // Initialize SQLite DB (scope-aware: local → .harness/harness.db, global → ~/.harness/dbs/<projectId>/harness.db)\n const db = await openDB(config, installDir)\n\n // Always write .harness/storage-state.json — reflects the REAL current\n // storage state (project-local regardless of scope). Consumed by the\n // future `ahk migrate storage` command.\n await db.writeStorageState(installDir)\n\n // Scaffold provider-specific files\n await materializer.scaffold(config, { cwd: installDir, firstTask, claudeAgentModels, codexAgentModels })\n\n // Reconcile .harness/feature_list.json — the \"human-editable task seed\n // list\". Owned by init (not the scaffold), and MERGED rather than\n // overwritten. See reconcileFeatureList for the full contract.\n const { parseFailed } = await reconcileFeatureList(db, installDir, config.storage.dir, firstTask)\n if (parseFailed) {\n featureListParseFailedPath = join(config.storage.dir, 'feature_list.json')\n }\n\n await db.close()\n spinner.stop('')\n } catch (err) {\n spinner.stop('Failed')\n p.log.error(err instanceof Error ? err.message : String(err))\n throw err\n }\n\n if (featureListParseFailedPath) {\n console.log(\n pc.yellow('⚠') +\n ' Existing ' +\n pc.bold(featureListParseFailedPath) +\n ' is not valid JSON — left untouched. Fix it and run `ahk sync`.'\n )\n }\n\n console.log(pc.green('✓ Scaffolded harness in current directory'))\n\n // ─── Summary ─────────────────────────────────────────────────────────────-\n const PROVIDER_SUMMARY_INFO: Record<Provider, { agentsDir: string; mcpFile: string }> = {\n 'claude-code': { agentsDir: '.claude/agents/', mcpFile: '.mcp.json' },\n opencode: { agentsDir: '.opencode/agents/', mcpFile: './opencode.json' },\n 'codex-cli': { agentsDir: '.codex/agents/', mcpFile: '.codex/config.toml' },\n 'grok-cli': { agentsDir: '.grok/agents/', mcpFile: '.grok/config.toml' },\n }\n const { agentsDir, mcpFile } = PROVIDER_SUMMARY_INFO[provider]\n\n console.log('')\n console.log(pc.green(`✓ agent-harness-kit.config.${configExt}`))\n console.log(pc.green('✓ AGENTS.md'))\n console.log(pc.green('✓ health.sh'))\n console.log(\n pc.green(\n storageScope === 'global'\n ? '✓ ~/.harness/dbs/<projectId>/harness.db'\n : '✓ .harness/harness.db'\n )\n )\n console.log(\n pc.green(\n storageScope === 'global'\n ? '✓ ~/.harness/dbs/<projectId>/current.md'\n : '✓ .harness/current.md'\n )\n )\n console.log(pc.green('✓ .harness/storage-state.json'))\n console.log(pc.green(`✓ ${agentsDir}lead.md`))\n console.log(pc.green(`✓ ${agentsDir}explorer.md`))\n console.log(pc.green(`✓ ${agentsDir}builder.md`))\n console.log(pc.green(`✓ ${agentsDir}reviewer.md`))\n console.log(pc.green(`✓ ${mcpFile}`))\n console.log(pc.green('✓ .gitignore entries added'))\n\n console.log('')\n console.log(pc.cyan('→') + ` Edit ${pc.cyan('health.sh')} with your project checks`)\n console.log(pc.cyan('→') + ` ${pc.cyan('ahk task add')} to queue work for agents`)\n console.log(\n pc.cyan('→') +\n ` Enrich your docs with knowledge graphs: ${pc.cyan('https://github.com/safishamsi/graphify')}`\n )\n\n const recommendations: string[] = [\n ` Give a try to Heimdall MCP: Transparent proxy that traces every MCP tool call with OpenTelemetry. `,\n ` Learn more: ${pc.cyan('https://github.com/enmanuelmag/heimdall-mcp')} `,\n ]\n\n console.log('')\n drawBox(recommendations)\n}\n","\nimport * as v from 'valibot'\n\nexport const initNameSchema = v\n .pipe(\n v.string(),\n v.nonEmpty('Project name is required'),\n v.minLength(3, 'Project name must be at least 3 characters'),\n v.maxLength(50, 'Project name must be at most 50 characters'),\n v.trim(),\n )\n\nexport const initDescriptionSchema = v\n .pipe(\n v.string(),\n v.nonEmpty('Description is required'),\n v.maxLength(300, 'Description must be at most 300 characters'),\n v.trim(),\n )\n\nexport const initDocsSchema = v\n .pipe(\n v.string(),\n v.nonEmpty('Docs folder path is required'),\n v.regex(/^[\\w\\-./]+$/, 'Docs folder path can only contain letters, numbers, dashes, underscores, dots, and slashes'),\n v.trim(),\n )","import * as v from 'valibot'\n\nexport const taskTitleSchema = v.pipe(\n v.string(),\n v.nonEmpty('Task title is required'),\n v.minLength(3, 'Task title must be at least 3 characters'),\n v.maxLength(100, 'Task title must be at most 100 characters'),\n)\n\nexport const taskDescriptionSchema = v.pipe(\n v.string(),\n v.nonEmpty('Description is required'),\n)\n","import * as p from '@clack/prompts'\nimport * as v from 'valibot'\n\n\nexport const cliFormWithRetry = async <T>(\n formFn: () => Promise<T>,\n schema: v.GenericSchema,\n): Promise<T> => {\n while (true) {\n const res = await formFn()\n const result = v.safeParse(schema, res)\n\n if (result.success) return result.output as T\n\n const messages = result.issues.map((i) => i.message).join(', ')\n p.log.error(messages)\n p.log.info('Please try again.\\n')\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { isLocalInstallSatisfied } from '@/core/local-install-guard'\n\nimport type { HarnessConfig, Provider } from '@/types'\n\n/**\n * Read the `name` field from a `package.json` in the given directory.\n * Returns `null` if the file doesn't exist, is malformed, or lacks a valid `name`.\n */\nexport function readProjectNameFromPackageJson(cwd: string): string | null {\n try {\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) return null\n const content = readFileSync(pkgPath, 'utf8')\n const pkg = JSON.parse(content)\n const name = pkg?.name\n if (typeof name === 'string' && name.trim()) return name.trim()\n return null\n } catch {\n return null\n }\n}\n\n/**\n * Chooses the config file format for `ahk init`.\n *\n * A local install of the package is the PRECONDITION, checked before anything\n * else: without it, the project cannot resolve '@cardor/agent-harness-kit', so\n * a .ts config's `import type` — and any editor autocompletion that depends on\n * it — resolves to nothing and the user sees a red-underlined, apparently\n * broken project. JSON has nothing to resolve, so it is correct by\n * construction there.\n *\n * Only once the package IS installed locally do we fall through to the\n * pre-existing project-type detection (tsconfig.json / package.json type),\n * whose behavior is unchanged.\n */\nexport function detectConfigExtension(cwd: string): 'json' | 'ts' | 'mjs' | 'cjs' {\n if (!isLocalInstallSatisfied(cwd)) return 'json'\n try {\n if (existsSync(join(cwd, 'tsconfig.json'))) return 'ts'\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) return 'mjs'\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))\n if (pkg?.type === 'module') return 'mjs'\n } catch {}\n return 'mjs'\n}\n\nexport function applyConfigDefaults(params: {\n name: string\n description: string\n provider: Provider\n docsPath: string\n tasksAdapter: string\n /** Storage scope chosen during init. Defaults to 'local' for backward compat. */\n scope?: 'local' | 'global'\n /** Reuse an existing projectId (e.g. re-running init logic). If omitted, a\n * fresh UUID is generated — NEVER derive it from the project path/hash. */\n projectId?: string\n}): HarnessConfig {\n const scope = params.scope ?? 'local'\n const projectId = params.projectId ?? randomUUID()\n const baseStorage = {\n dir: '.harness',\n tasks: { adapter: params.tasksAdapter as 'local' },\n sections: {\n toolsUsed: true,\n filesModified: true,\n result: true,\n blockers: true,\n nextSteps: false,\n },\n }\n const storage: HarnessConfig['storage'] =\n scope === 'global'\n ? { ...baseStorage, markdownFallback: { enabled: true }, scope: 'global', projectId }\n : { ...baseStorage, markdownFallback: { enabled: true, path: '.harness/current.md' }, scope: 'local', projectId }\n\n return {\n provider: params.provider,\n project: {\n name: params.name,\n description: params.description,\n docsPath: params.docsPath,\n agentsMd: './AGENTS.md',\n },\n // No `agents` key: per-agent settings (model, role instructions) live in\n // the generated agent file, which is user-owned. This object is the runtime\n // twin of the config body emitted by configObjectBody() in templates.ts —\n // drift between the two is the bug this pairing has to keep out.\n database: { type: 'sqlite' as const },\n storage,\n health: {\n scriptPath: './health.sh',\n required: true,\n },\n tools: {\n mcp: { enabled: true, port: 3742 },\n scripts: { enabled: true, outputDir: './.harness/scripts' },\n },\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n\n/** Strip ANSI escape codes for width calculation */\nfunction stripAnsi(str: string): string {\n return str.replace(/\\x1B\\[[0-9;]*m/g, '')\n}\n\n\n/** Draw a bordered box matching printUpdateMessage() style */\nexport function drawBox(lines: string[]): void {\n // Calculate max content width (excluding ANSI codes)\n const width = Math.max(...lines.map((l) => stripAnsi(l).length))\n const border = '─'.repeat(width)\n\n console.log(pc.yellow(`┌${border}┐`))\n for (const line of lines) {\n const pad = width - stripAnsi(line).length\n const padStr = pad > 0 ? ' '.repeat(pad) : ''\n console.log(pc.yellow('│') + line + padStr + pc.yellow('│'))\n }\n console.log(pc.yellow(`└${border}┘`))\n}\n\n/**\n * Print a pretty welcome message when user executes the init command.\n * Styled to match the existing printUpdateMessage() aesthetic.\n */\nexport function printWelcomeMessage(projectName: string): void {\n const sep = '─'.repeat(38)\n\n // Build lines with embedded ANSI codes for width calculation\n const lines: string[] = [\n ` ${pc.bold(pc.white('agent-harness-kit'))} `,\n ` ${pc.gray('—')} harness scaffolding ${pc.gray('—')} `,\n ` ${pc.gray(sep)} `,\n ` ${pc.bold('Project:')} ${projectName || '—'} `,\n ` ${pc.bold('Status:')} ${pc.green('ready to configure')} `,\n ` ${pc.gray(sep)} `,\n ` ${pc.gray('Next steps:')} `,\n ` ${pc.gray('→')} ${pc.gray('Set up your AI provider config')} `,\n ` ${pc.gray('→')} ${pc.gray('Run your health check to verify')} `,\n ` ${pc.gray('→')} ${pc.gray('Start adding tasks for your agents')} `,\n ]\n\n console.log()\n drawBox(lines)\n console.log()\n}\n","import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { getMaterializer } from '@/core/materializer/index'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\nimport { promptCodexAgentModels } from './codex-model-prompt'\n\nimport type { Provider } from '@/types'\n\ninterface MigrateOptions {\n to?: string\n}\n\nexport async function runMigrate(cwd: string, opts: MigrateOptions): Promise<void> {\n const config = await loadConfig(cwd)\n\n let target: Provider\n if (opts.to && ['claude-code', 'opencode', 'codex-cli', 'grok-cli'].includes(opts.to)) {\n target = opts.to as Provider\n } else {\n const val = await p.select({\n message: 'Migrate to provider',\n options: [\n { value: 'claude-code', label: 'Claude Code' },\n { value: 'opencode', label: 'OpenCode' },\n { value: 'codex-cli', label: 'Codex CLI' },\n { value: 'grok-cli', label: 'Grok CLI' },\n ],\n })\n if (p.isCancel(val)) {\n p.cancel('Cancelled.')\n process.exit(0)\n }\n target = val as Provider\n }\n\n if (target === config.provider) {\n console.log(pc.dim(`Already on ${target} — nothing to migrate.`))\n return\n }\n\n // Re-run the same per-role model prompt `ahk init` and `ahk build --force`\n // use, scoped to whichever provider we're migrating to. Both helpers\n // self-guard on the provider argument, so calling both unconditionally is\n // safe — only the target's own questions actually appear. Must happen\n // BEFORE the spinner below starts: an interactive p.select cannot render\n // while a p.spinner is active.\n const claudeAgentModels = await promptClaudeAgentModels(target)\n const codexAgentModels = await promptCodexAgentModels(target)\n\n const spinner = p.spinner()\n spinner.start(`Migrating from ${config.provider} to ${target}...`)\n\n try {\n // Scaffold the new provider's files\n const targetMaterializer = getMaterializer(target)\n await targetMaterializer.build(config, cwd, { claudeAgentModels, codexAgentModels })\n\n spinner.stop(pc.green(`Migrated to ${target}`))\n p.log.warn(`Update agent-harness-kit.config.ts: set provider: '${target}'`)\n p.log.warn(`Then run: ahk build`)\n } catch (err) {\n spinner.stop(pc.red('Migration failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n","import { copyFileSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport {\n DEFAULT_MARKDOWN_PATH,\n DEFAULT_SQLITE_PATH,\n type FullExport,\n getRowCounts,\n isEmptyDatabase,\n openDB,\n readStorageStateFile,\n resolveGlobalStorageDir,\n resolveSqlitePathForScope,\n} from '@/core/db'\n\nimport type { DatabaseConfig, HarnessConfig } from '@/types'\n\nexport interface MigrateStorageOptions {\n force?: boolean\n dryRun?: boolean\n}\n\ntype DbType = DatabaseConfig['type']\n\nfunction log(msg: string): void {\n console.log(msg)\n}\n\n/** Aborts the current migration by throwing — callers (the CLI action\n * handler) are responsible for printing the message and exiting non-zero.\n * Throwing (rather than calling process.exit here) keeps this module\n * testable without killing the test process. */\nfunction fail(msg: string): never {\n throw new Error(msg)\n}\n\n/** The relative markdown-fallback path to use as the base for\n * `currentMdPathForScope()` below. Mirrors `defaultSqlitePathForConfig()` —\n * `LocalStorageConfig.markdownFallback.path` only exists (and only means\n * anything) when `config.storage.scope === 'local'`; for a config CURRENTLY\n * in scope='global' there's no field to read a custom path from, so this\n * always falls back to `DEFAULT_MARKDOWN_PATH` in that case. */\nfunction defaultMarkdownPathForConfig(config: HarnessConfig): string {\n return config.storage.scope === 'local' ? config.storage.markdownFallback.path : DEFAULT_MARKDOWN_PATH\n}\n\n/** Physical location of a project's harness `current.md`, following the same\n * scope convention `HarnessDB.regenerateCurrentMd()` uses. */\nfunction currentMdPathForScope(scope: 'local' | 'global', config: HarnessConfig, cwd: string, homeDir: string): string {\n return scope === 'global'\n ? join(resolveGlobalStorageDir(config, homeDir), 'current.md')\n : resolve(cwd, defaultMarkdownPathForConfig(config))\n}\n\n/** The relative sqlite path override to use as the base for\n * `resolveSqlitePathForScope()` calls in this file. `LocalStorageConfig.sqlitePath`\n * only exists (and only means anything) when `config.storage.scope ===\n * 'local'` — for a config CURRENTLY in scope='global', there is no field to\n * read a custom local filename from at all, so this always falls back to\n * `DEFAULT_SQLITE_PATH` in that case.\n *\n * Known UX tradeoff (accepted, see task #56 consultant advisory): a custom\n * local sqlite filename (`storage.sqlitePath`) does NOT survive a\n * global -> local round trip — migrating back to local always lands at\n * `DEFAULT_SQLITE_PATH` unless the user re-sets `storage.sqlitePath`\n * afterward. This is a deliberate consequence of making `sqlitePath`\n * local-only in the type system (see StorageConfig in src/types.ts) rather\n * than leaving it unenforceable across scopes. */\nfunction defaultSqlitePathForConfig(config: HarnessConfig): string {\n return config.storage.scope === 'local' && config.database.type === 'sqlite'\n ? (config.storage.sqlitePath ?? DEFAULT_SQLITE_PATH)\n : DEFAULT_SQLITE_PATH\n}\n\n/** Backs up the destination's current content (all 6 tables, via\n * exportJson()) to a local JSON file BEFORE any destructive `--force`\n * overwrite. Aborts the whole command (throws) if the backup can't be\n * written — fail-safe, per task #47 consultant advisory point 2. */\nasync function backupDestination(cwd: string, storageDir: string, data: FullExport): Promise<string> {\n const backupsDir = resolve(cwd, storageDir, 'backups')\n const path = join(backupsDir, `pre-migrate-${new Date().toISOString().replace(/[:.]/g, '-')}.json`)\n try {\n mkdirSync(backupsDir, { recursive: true })\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n', 'utf8')\n } catch (err) {\n throw new Error(\n `Could not write destination backup to ${path} (${err instanceof Error ? err.message : String(err)}). ` +\n `Aborting migration WITHOUT touching the destination — nothing was overwritten.`,\n )\n }\n return path\n}\n\n/** Copies a sqlite `.db` file (plus WAL/SHM sidecars if present) to a new\n * path, verifying the copy exists before returning. Does not delete the\n * original — caller decides when it's safe to remove it. */\nfunction copySqliteFile(srcPath: string, destPath: string): void {\n mkdirSync(dirname(destPath), { recursive: true })\n copyFileSync(srcPath, destPath)\n for (const suffix of ['-wal', '-shm']) {\n if (existsSync(`${srcPath}${suffix}`)) {\n copyFileSync(`${srcPath}${suffix}`, `${destPath}${suffix}`)\n }\n }\n if (!existsSync(destPath)) {\n throw new Error(`Copy verification failed: ${destPath} does not exist after copy.`)\n }\n}\n\nexport async function runMigrateStorage(\n cwd: string,\n opts: MigrateStorageOptions,\n homeDir: string = homedir(),\n): Promise<void> {\n const config = await loadConfig(cwd)\n const storageDir = config.storage.dir\n const state = readStorageStateFile(cwd, storageDir)\n\n // ── Case: storage-state.json is missing ──────────────────────────────────\n // NEVER treat this as \"destination empty, safe to migrate\". Probe the real\n // content at both sqlite candidate locations (local + global default\n // paths) before deciding anything. See task #47 consultant advisory pt.6.\n let realScope: 'local' | 'global'\n let realDbType: DbType\n\n if (!state) {\n const defaultSqlitePath = defaultSqlitePathForConfig(config)\n const localPath = resolveSqlitePathForScope('local', defaultSqlitePath, cwd, config, homeDir)\n const globalPath = resolveSqlitePathForScope('global', defaultSqlitePath, cwd, config, homeDir)\n\n const localCount = await probeTaskCount(localPath)\n const globalCount = await probeTaskCount(globalPath)\n\n if (localCount > 0 && globalCount > 0) {\n fail(\n `storage-state.json is missing and BOTH candidate locations have data — ` +\n `local (${localPath}): ${localCount} task(s); global (${globalPath}): ${globalCount} task(s). ` +\n `Refusing to guess which one is authoritative. Resolve manually (inspect both databases) ` +\n `or delete the one that should be discarded, then re-run this command.`,\n )\n }\n\n if (localCount === 0 && globalCount === 0) {\n // Nothing exists anywhere yet — nothing to migrate. Just record the\n // current (desired) state so future runs have a storage-state.json.\n const db = await openDB(config, cwd, homeDir)\n try {\n await db.writeStorageState(cwd)\n } finally {\n await db.close()\n }\n log(pc.dim('storage-state.json was missing; no data found at either candidate location. Nothing to migrate — state recorded.'))\n return\n }\n\n // Exactly one candidate has data — self-heal: treat it as the real\n // (source) location without requiring --force, since this isn't a\n // blind guess (only one plausible source exists).\n realScope = localCount > 0 ? 'local' : 'global'\n realDbType = 'sqlite'\n log(\n pc.yellow(\n `storage-state.json was missing. Detected real data at ${realScope} sqlite location ` +\n `(${realScope === 'local' ? localPath : globalPath}) — using it as the migration source.`,\n ),\n )\n } else {\n realScope = state.scope\n realDbType = state.dbType\n }\n\n const desiredScope = config.storage.scope\n const desiredDbType = config.database.type\n\n // ── Case 1: everything matches — nothing to migrate ──────────────────────\n if (realScope === desiredScope && realDbType === desiredDbType) {\n log(pc.green(`✓ Storage already matches config (scope=${desiredScope}, database=${desiredDbType}) — nothing to migrate.`))\n return\n }\n\n // ── Unsupported direction: source was a remote DB ─────────────────────────\n // storage-state.json intentionally never stores connection strings/creds,\n // so we cannot auto-reconnect to a previous remote database. Out of scope\n // for this command — fail safe rather than guess.\n if (realDbType !== 'sqlite') {\n fail(\n `Cannot auto-locate the previous ${realDbType} database — storage-state.json does not retain connection ` +\n `credentials for security. Manually run \"ahk export --json\" while still connected to the old database ` +\n `(with the old config), then adjust agent-harness-kit.config.ts and re-import. This direction is out of scope for \"ahk migrate storage\".`,\n )\n }\n\n // ── Case: scope changes but dbType stays sqlite → move files directly ────\n if (desiredDbType === 'sqlite' && realDbType === 'sqlite') {\n return migrateScopeOnly(cwd, config, homeDir, realScope, desiredScope, opts)\n }\n\n // ── Case: dbType changes (sqlite -> postgres/mysql, or vice versa is\n // unsupported above) → full export/import through a transaction ──────\n return migrateAcrossDbType(cwd, config, homeDir, realScope, opts)\n}\n\n/** Returns the number of rows in `tasks` at `dbPath`, or 0 if the file\n * doesn't exist. Never creates the file (existence is checked first) —\n * probing must not have side effects. */\nasync function probeTaskCount(dbPath: string): Promise<number> {\n if (!existsSync(dbPath)) return 0\n const { SQLiteDriver } = await import('@/core/drivers/sqlite')\n const driver = new SQLiteDriver(dbPath)\n try {\n await driver.ensureSchema()\n const counts = await getRowCounts(driver)\n return counts.tasks\n } finally {\n await driver.close()\n }\n}\n\n// ─── Case: local <-> global, same engine (sqlite) ──────────────────────────\n\nasync function migrateScopeOnly(\n cwd: string,\n config: HarnessConfig,\n homeDir: string,\n fromScope: 'local' | 'global',\n toScope: 'local' | 'global',\n opts: MigrateStorageOptions,\n): Promise<void> {\n const sqlitePath = defaultSqlitePathForConfig(config)\n const srcDb = resolveSqlitePathForScope(fromScope, sqlitePath, cwd, config, homeDir)\n const destDb = resolveSqlitePathForScope(toScope, sqlitePath, cwd, config, homeDir)\n const srcMd = currentMdPathForScope(fromScope, config, cwd, homeDir)\n const destMd = currentMdPathForScope(toScope, config, cwd, homeDir)\n\n if (!existsSync(srcDb)) {\n fail(`Source database not found at ${srcDb} (expected ${fromScope} scope) — nothing to move.`)\n }\n\n const destExists = existsSync(destDb)\n if (destExists) {\n const { SQLiteDriver } = await import('@/core/drivers/sqlite')\n const destDriver = new SQLiteDriver(destDb)\n let destEmpty: boolean\n try {\n await destDriver.ensureSchema()\n destEmpty = await isEmptyDatabase(destDriver)\n } finally {\n await destDriver.close()\n }\n if (!destEmpty && !opts.force) {\n fail(\n `Destination (${toScope}, ${destDb}) already has data. Re-run with --force to overwrite it ` +\n `(a backup of the destination will be written first).`,\n )\n }\n if (!destEmpty && opts.force) {\n // Back up destination content before overwriting.\n const { SQLiteDriver: Driver } = await import('@/core/drivers/sqlite')\n const backupDriver = new Driver(destDb)\n let data: FullExport\n try {\n await backupDriver.ensureSchema()\n const { HarnessDB } = await import('@/core/db')\n // `config` is passed unmodified (not re-scoped to `toScope`) — safe\n // because exportJson() only queries `backupDriver`'s tables and never\n // reads `this.config.storage` at all. Re-scoping here would also no\n // longer type-check cleanly against the StorageConfig discriminated\n // union (task #56) since `sqlitePath` only exists on the 'local'\n // branch.\n const tmpDb = new HarnessDB(backupDriver, config, homeDir)\n data = await tmpDb.exportJson()\n } finally {\n await backupDriver.close()\n }\n const backupPath = await backupDestination(cwd, config.storage.dir, data)\n log(pc.yellow(` Backed up existing destination data → ${backupPath}`))\n }\n }\n\n if (opts.dryRun) {\n log(pc.dim(`[dry-run] Would copy ${srcDb} → ${destDb} (scope ${fromScope} → ${toScope}), and move current.md.`))\n return\n }\n\n copySqliteFile(srcDb, destDb)\n log(pc.green(`✓ Copied database ${srcDb} → ${destDb}`))\n\n if (existsSync(srcMd)) {\n mkdirSync(dirname(destMd), { recursive: true })\n copyFileSync(srcMd, destMd)\n log(pc.green(`✓ Copied current.md ${srcMd} → ${destMd}`))\n }\n\n // Only remove the source AFTER the copy is verified in place.\n rmSync(srcDb, { force: true })\n rmSync(`${srcDb}-wal`, { force: true })\n rmSync(`${srcDb}-shm`, { force: true })\n if (existsSync(srcMd) && srcMd !== destMd) rmSync(srcMd, { force: true })\n\n // Write storage-state ONLY after the move is confirmed successful.\n const db = await openDB(config, cwd, homeDir)\n try {\n await db.writeStorageState(cwd)\n } finally {\n await db.close()\n }\n\n log(pc.green(`✓ Storage migrated: scope ${fromScope} → ${toScope}`))\n}\n\n// ─── Case: database engine changes (sqlite -> postgres/mysql) ─────────────\n\nasync function migrateAcrossDbType(\n cwd: string,\n config: HarnessConfig,\n homeDir: string,\n sourceScope: 'local' | 'global',\n opts: MigrateStorageOptions,\n): Promise<void> {\n const sqlitePath = defaultSqlitePathForConfig(config)\n const srcPath = resolveSqlitePathForScope(sourceScope, sqlitePath, cwd, config, homeDir)\n if (!existsSync(srcPath)) {\n fail(`Source sqlite database not found at ${srcPath} (expected ${sourceScope} scope) — nothing to migrate.`)\n }\n\n const { SQLiteDriver } = await import('@/core/drivers/sqlite')\n const srcDriver = new SQLiteDriver(srcPath)\n let sourceData: FullExport\n let sourceCounts: Awaited<ReturnType<typeof getRowCounts>>\n try {\n await srcDriver.ensureSchema()\n sourceCounts = await getRowCounts(srcDriver)\n const { HarnessDB } = await import('@/core/db')\n // `config` is passed unmodified (not re-scoped/re-typed to sqlite) — safe\n // because exportJson() only queries `srcDriver`'s tables and never reads\n // `this.config` at all. See the identical comment above in\n // migrateScopeOnly() for why re-scoping isn't attempted here anymore.\n const srcDb = new HarnessDB(srcDriver, config, homeDir)\n sourceData = await srcDb.exportJson()\n } finally {\n await srcDriver.close()\n }\n\n // Fail fast: connect to destination before touching anything else.\n let destDb\n try {\n destDb = await openDB(config, cwd, homeDir)\n } catch (err) {\n fail(`Could not connect to destination (${config.database.type}): ${err instanceof Error ? err.message : String(err)}. Verify database configuration.`)\n }\n\n try {\n const destCounts = await destDb.getRowCounts()\n const destEmpty = Object.values(destCounts).every((n) => n === 0)\n const sourceEmpty = Object.values(sourceCounts).every((n) => n === 0)\n\n if (!destEmpty) {\n if (!opts.force) {\n const bothHaveData = !sourceEmpty\n fail(\n bothHaveData\n ? `Both source (${sourceCounts.tasks} task(s)) and destination (${config.database.type}, ${destCounts.tasks} task(s)) ` +\n `have data that DIVERGE — this is not a first-time migration. Refusing to auto-merge. ` +\n `Review both manually, or re-run with --force to overwrite the destination (a JSON backup will be written first).`\n : `Destination (${config.database.type}) already has data (${destCounts.tasks} task(s)). ` +\n `Re-run with --force to overwrite it (a backup of the destination will be written first).`,\n )\n }\n }\n\n if (opts.dryRun) {\n log(\n pc.dim(\n `[dry-run] Would migrate ${sourceCounts.tasks} task(s) from sqlite (${sourceScope}, ${srcPath}) ` +\n `to ${config.database.type}${destEmpty ? '' : ' (destination has data — would back up first, then overwrite)'}.`,\n ),\n )\n return\n }\n\n let backupPath: string | null = null\n if (!destEmpty && opts.force) {\n const currentDestData = await destDb.exportJson()\n backupPath = await backupDestination(cwd, config.storage.dir, currentDestData)\n log(pc.yellow(` Backed up existing destination data → ${backupPath}`))\n }\n\n // Single transaction covers the entire import (and truncate, if any).\n // storage-state is written ONLY after this resolves without throwing.\n await destDb.importFullExport(sourceData, config.database.type, { truncateFirst: !destEmpty })\n\n await destDb.writeStorageState(cwd)\n\n log(\n pc.green(\n `✓ Migrated ${sourceData.tasks.length} task(s), ${sourceData.actions.length} action(s) ` +\n `from sqlite (${sourceScope}) → ${config.database.type}.`,\n ),\n )\n if (backupPath) log(pc.dim(` Destination backup: ${backupPath}`))\n log(pc.yellow(` Note: the original sqlite file at ${srcPath} was NOT deleted — remove it manually once you've verified the migration.`))\n } finally {\n await destDb.close()\n }\n}\n","import { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { claudeAgentFiles } from '@/core/materializer/claude-code'\nimport { writeAgentFiles } from '@/core/materializer/scaffold-utils'\n\nimport { promptClaudeAgentModels } from './claude-model-prompt'\n\nimport type { HarnessConfig, Provider } from '@/types'\n\n/**\n * Resolves what `ahk models` should do, WITHOUT touching the interactive\n * prompt layer. Kept separate from `runModels` so the no-config-found and\n * non-claude-code no-op branches are testable directly — mirrors the\n * separation `getDoctorStatus`/`runDoctor` already have in doctor.ts. No test\n * in this repo mocks `@clack/prompts`; everything downstream of a resolved\n * `ModelsContext` is exercised at the pure-function level instead (see\n * `claudeAgentFiles` / `writeAgentFiles` tests).\n */\nexport type ModelsContext =\n | { ok: true; config: HarnessConfig }\n | { ok: false; reason: 'no-config' }\n | { ok: false; reason: 'not-claude-code'; provider: Provider }\n\nexport async function resolveModelsContext(cwd: string): Promise<ModelsContext> {\n let config: HarnessConfig\n try {\n config = await loadConfig(cwd)\n } catch {\n return { ok: false, reason: 'no-config' }\n }\n\n if (config.provider !== 'claude-code') {\n return { ok: false, reason: 'not-claude-code', provider: config.provider }\n }\n\n return { ok: true, config }\n}\n\n/**\n * `ahk models` — Claude Code only. Re-runs the same per-role model prompt\n * `ahk init` uses and regenerates ONLY the 5 `.claude/agents/*.md` files with\n * the freshly-collected models, backing up the previous content first (same\n * `writeAgentFiles(..., { force: true, backupRoot })` call shape `ahk build\n * --force` already uses). Scope is strictly the 5 agent files' model line —\n * AGENTS.md, CLAUDE.md, .mcp.json, .claude/settings.json, config, docs path,\n * storage scope, and the task adapter are never touched.\n */\nexport async function runModels(cwd: string): Promise<void> {\n const ctx = await resolveModelsContext(cwd)\n\n if (!ctx.ok) {\n if (ctx.reason === 'no-config') {\n // Mirrors runDoctor's no-config-found handling in doctor.ts.\n console.log('')\n console.log(` ${pc.cyan('config'.padEnd(16))}${pc.yellow('[!]')} no agent-harness-kit.config found`)\n console.log(` ${''.padEnd(16)} ${pc.dim('run: ahk init')}`)\n console.log('')\n return\n }\n\n console.log(\n pc.dim(\n `ahk models only applies to Claude Code projects (this project uses '${ctx.provider}') — nothing to do.`\n )\n )\n return\n }\n\n const { config } = ctx\n const claudeAgentModels = await promptClaudeAgentModels(config.provider)\n\n const agents = writeAgentFiles(cwd, claudeAgentFiles(config, claudeAgentModels), {\n force: true,\n backupRoot: join(cwd, config.storage.dir, 'backups'),\n })\n\n console.log('')\n if (agents.overwritten.length > 0) {\n console.log(pc.green(`✓ Regenerated ${agents.overwritten.length} agent file(s) with updated models:`))\n for (const file of agents.overwritten) console.log(pc.green(` ✓ ${file}`))\n if (agents.backupDir) {\n console.log(pc.dim(` Previous content backed up → ${agents.backupDir}`))\n }\n }\n if (agents.created.length > 0) {\n console.log(pc.green(`✓ Created ${agents.created.length} missing agent file(s):`))\n for (const file of agents.created) console.log(pc.green(` ✓ ${file}`))\n }\n console.log('')\n}\n","import { existsSync, readdirSync, rmSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { resolveSqlitePath } from '@/core/db'\n\nimport type { Provider } from '@/types'\n\ninterface ResetOptions {\n force?: boolean\n provider?: Provider\n}\n\n// Map of agent role names to their generated filenames (extension varies by provider)\nconst AGENT_MD_FILES = ['lead', 'explorer', 'consultant', 'builder', 'reviewer']\n\nconst PROVIDER_AGENT_DIRS: Record<Provider, string> = {\n 'claude-code': '.claude/agents',\n opencode: '.opencode/agents',\n 'codex-cli': '.codex/agents',\n 'grok-cli': '.grok/agents',\n}\n\n// codex-cli agent files are TOML (see codex-cli.ts materializer); every other\n// provider generates markdown + YAML frontmatter.\nconst PROVIDER_AGENT_EXT: Record<Provider, string> = {\n 'claude-code': '.md',\n opencode: '.md',\n 'codex-cli': '.toml',\n 'grok-cli': '.md',\n}\n\nasync function resetAgentMds(cwd: string, provider: Provider): Promise<void> {\n const agentDir = PROVIDER_AGENT_DIRS[provider]\n const agentDirPath = resolve(cwd, agentDir)\n const agentExt = PROVIDER_AGENT_EXT[provider]\n\n if (!existsSync(agentDirPath)) {\n console.log(pc.yellow(` Skipping agent files — directory not found: ${agentDirPath}`))\n return\n }\n\n // Collect existing agent files for this provider's extension\n const existingFiles: string[] = []\n try {\n const files = readdirSync(agentDirPath)\n for (const f of files) {\n if (f.endsWith(agentExt) && AGENT_MD_FILES.includes(f.replace(agentExt, ''))) {\n existingFiles.push(f)\n }\n }\n } catch {\n // Directory doesn't exist or can't be read\n console.log(pc.yellow(` Skipping agent files — ${agentDirPath} is not readable`))\n return\n }\n\n if (existingFiles.length === 0) {\n console.log(pc.yellow(` No agent MD files found in ${agentDir}/`))\n return\n }\n\n // Confirm removal of each agent MD file\n for (const file of existingFiles) {\n const confirm = await p.confirm({\n message: `Remove ${file}?`,\n initialValue: true,\n })\n if (p.isCancel(confirm)) {\n console.log(pc.red(' Cancelled by user.'))\n return\n }\n if (confirm) {\n try {\n const filePath = join(agentDirPath, file)\n rmSync(filePath, { force: true })\n console.log(pc.green(` Removed ${file}`))\n } catch {\n console.error(pc.red(` Failed to remove ${file}`))\n }\n } else {\n console.log(pc.cyan(` Skipped ${file}`))\n }\n }\n}\n\nexport async function runReset(cwd: string, opts: ResetOptions): Promise<void> {\n let config\n try {\n config = await loadConfig(cwd)\n } catch {\n console.error(pc.red('✗ No agent-harness-kit.config found. Run: ahk init'))\n process.exit(1)\n }\n\n const storageDir = config.storage.dir || '.harness'\n const dbPath = config.database.type === 'sqlite' ? resolveSqlitePath(config, cwd, homedir()) : null\n const featureListPath = resolve(cwd, storageDir, 'feature_list.json')\n\n let resetDb = false\n let resetFeatureList = false\n let resetAgentMdsFlag = false\n\n // ─── Determine what to reset ────────────────────────────────────────────────\n\n // Reset DB? (SQLite only — remote DBs are not reset by this command)\n if (dbPath && existsSync(dbPath)) {\n if (opts.force) {\n resetDb = true\n } else {\n if (config.database.type !== 'sqlite') {\n console.log(pc.yellow(` Skipping DB reset — database type \"${config.database.type}\" is not managed by this command.`))\n resetDb = false\n } else {\n const confirm = await p.confirm({\n message: `Delete database (${dbPath})?`,\n initialValue: true,\n })\n if (p.isCancel(confirm)) {\n console.log(pc.red(' Cancelled by user.'))\n return\n }\n resetDb = confirm\n }\n }\n } else if (!dbPath) {\n console.log(pc.dim(` Skipping DB reset — remote ${config.database.type} database is not managed by this command.`))\n }\n\n // Reset feature_list.json?\n if (existsSync(featureListPath)) {\n if (opts.force) {\n resetFeatureList = true\n } else {\n const confirm = await p.confirm({\n message: `Delete feature list (${storageDir}/feature_list.json)?`,\n initialValue: true,\n })\n if (p.isCancel(confirm)) {\n console.log(pc.red(' Cancelled by user.'))\n return\n }\n resetFeatureList = confirm\n }\n }\n\n // Reset agent MD files?\n if (opts.provider) {\n resetAgentMdsFlag = true\n }\n\n // ─── Perform resets ─────────────────────────────────────────────────\n if (resetDb && dbPath) {\n try {\n rmSync(dbPath, { force: true })\n rmSync(`${dbPath}-wal`, { force: true }) // also remove WAL file if it exists (only for SQLite)\n rmSync(`${dbPath}-shm`, { force: true }) // also remove SHM file if it exists (only for SQLite)\n console.log(pc.green(` ✓ Removed ${dbPath}`))\n } catch {\n console.error(pc.red(` ✗ Failed to remove ${dbPath}`))\n }\n }\n\n if (resetFeatureList) {\n try {\n rmSync(featureListPath, { force: true })\n console.log(pc.green(` ✓ Removed ${storageDir}/feature_list.json`))\n // = true\n } catch {\n console.error(pc.red(` ✗ Failed to remove ${featureListPath}`))\n }\n }\n\n if (resetAgentMdsFlag) {\n console.log('')\n await resetAgentMds(cwd, opts.provider || 'claude-code')\n }\n\n if (!resetDb && !resetFeatureList && !resetAgentMdsFlag) {\n console.log(pc.yellow(' Nothing to reset (all items missing or skipped).'))\n return\n }\n\n // ─── Summary ────────────────────────────────────────────────────────\n console.log('')\n console.log(pc.green('✓ Reset complete. Run \"ahk init\" to scaffold a fresh harness.'))\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { Server } from '@modelcontextprotocol/sdk/server'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js'\n\nimport { type HarnessDB, openDB } from './db'\nimport { getDoctorStatus } from './doctor'\nimport { slugify } from './materializer/scaffold-utils'\nimport { checkPermissionsSync } from './permissions-check'\n\nimport type { ActionFileRow, ActionStatus, AgentName, HarnessConfig, TaskStatus } from '@/types'\n\nconst VERSION = '0.1.0'\n\n// ─── Tool schemas ─────────────────────────────────────────────────────────────\n\nconst TOOLS = [\n {\n name: 'actions.start',\n description: 'Start a new action for a task. Returns an actionId.',\n inputSchema: {\n type: 'object',\n properties: {\n taskId: { type: 'number', description: 'The task ID from tasks.get' },\n agent: {\n type: 'string',\n description: 'Agent name: lead | explorer | consultant | builder | reviewer | custom:<name>',\n },\n },\n required: ['taskId', 'agent'],\n },\n },\n {\n name: 'actions.write',\n description:\n 'Record a section in an action. Standard sections: result, tools_used, blockers, next_steps.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId returned by actions.start' },\n sectionType: {\n type: 'string',\n description:\n 'Section name: result | tools_used | blockers | next_steps | <custom>. Do NOT use files_modified to track files — it is stored as plain text only. Use actions.record_file instead.',\n },\n content: {\n type: 'string',\n description:\n \"Content for this section. No length limit; avoid padding — it costs shared context for other agents.\",\n },\n },\n required: ['actionId', 'sectionType', 'content'],\n },\n },\n {\n name: 'actions.complete',\n description: 'Close an action with a one-line summary.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId of the action to close' },\n summary: { type: 'string', description: 'One-line summary of what was done' },\n },\n required: ['actionId', 'summary'],\n },\n },\n {\n name: 'actions.get',\n description: 'Full task action history, including every action and section. Potentially large; use only for audit or diagnosis.',\n inputSchema: {\n type: 'object',\n properties: {\n taskId: { type: 'number', description: 'Task ID' },\n },\n required: ['taskId'],\n },\n },\n {\n name: 'actions.list',\n description: 'Compact newest-first action index. Use to discover actions before reading a specific action or section.',\n inputSchema: {\n type: 'object', properties: {\n taskId: { type: 'number', description: 'Task ID' },\n agent: { type: 'string', description: 'Optional agent filter' },\n status: { type: 'string', enum: ['in_progress', 'completed', 'blocked'], description: 'Optional action status filter' },\n cursor: { type: 'string', description: 'Opaque cursor returned as nextCursor' },\n limit: { type: 'number', description: 'Maximum items (1-100; default 20)' },\n }, required: ['taskId'],\n },\n },\n {\n name: 'actions.get_by_id',\n description: 'Get one action and a compact index of its sections; section contents are not included.',\n inputSchema: { type: 'object', properties: { actionId: { type: 'number', description: 'Action ID' } }, required: ['actionId'] },\n },\n {\n name: 'actions.sections.list',\n description: 'Compact newest-first section index for one action. Filter by section types without loading content.',\n inputSchema: {\n type: 'object', properties: {\n actionId: { type: 'number', description: 'Action ID' },\n types: { type: 'array', items: { type: 'string' }, description: 'Optional section-type filter' },\n cursor: { type: 'string', description: 'Opaque cursor returned as nextCursor' },\n limit: { type: 'number', description: 'Maximum items (1-100; default 20)' },\n }, required: ['actionId'],\n },\n },\n {\n name: 'actions.sections.get',\n description: 'Read one section content with an explicit character range. This is the only generic action reader that returns long text.',\n inputSchema: {\n type: 'object', properties: {\n sectionId: { type: 'number', description: 'Section ID' },\n offset: { type: 'number', description: 'Zero-based character offset (default 0)' },\n length: { type: 'number', description: 'Characters to return (1-12000; default 8000)' },\n }, required: ['sectionId'],\n },\n },\n {\n name: 'actions.handoff.write',\n description: 'Write a validated, recipient-directed, bounded handoff for a completed action to resume work without loading the full history.',\n inputSchema: {\n type: 'object', properties: {\n actionId: { type: 'number', description: 'Producer action ID' },\n recipient: { type: 'string', enum: ['lead', 'explorer', 'consultant', 'builder', 'reviewer'] },\n goal: { type: 'string' }, completed: { type: 'array', items: { type: 'string' } },\n decisions: { type: 'array', items: { type: 'string' } }, files: { type: 'array', items: { type: 'string' } },\n verification: { type: 'array', items: { type: 'string' } }, blockers: { type: 'array', items: { type: 'string' } },\n nextStep: { type: 'string' },\n }, required: ['actionId', 'recipient', 'goal', 'completed', 'decisions', 'files', 'verification', 'blockers', 'nextStep'],\n },\n },\n {\n name: 'actions.handoff.get',\n description: 'Get the newest completed canonical handoff addressed to a recipient. Returns HANDOFF_NOT_FOUND instead of falling back to history.',\n inputSchema: {\n type: 'object', properties: {\n taskId: { type: 'number', description: 'Task ID' },\n recipient: { type: 'string', enum: ['lead', 'explorer', 'consultant', 'builder', 'reviewer'], description: 'Recipient role; defaults to builder' },\n }, required: ['taskId'],\n },\n },\n {\n name: 'tasks.get',\n description: 'List tasks, optionally filtered by status. Excludes archived tasks by default.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'done', 'blocked'],\n description: 'Filter by status (omit for all tasks)',\n },\n includeArchived: {\n type: 'boolean',\n description: 'If true, include archived tasks in results',\n },\n },\n },\n },\n {\n name: 'tasks.claim',\n description:\n 'Atomically claim a pending task. Returns task_already_claimed if another agent got it first.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to claim' },\n agent: { type: 'string', description: 'Your agent name' },\n },\n required: ['id', 'agent'],\n },\n },\n {\n name: 'tasks.update',\n description: 'Change the status of a task.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID' },\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'done', 'blocked'],\n },\n },\n required: ['id', 'status'],\n },\n },\n {\n name: 'docs.search',\n description: 'Search the project docs folder for content matching a query.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Search terms' },\n },\n required: ['query'],\n },\n },\n {\n name: 'actions.record_file',\n description:\n 'Record one or more files touched during an action, atomically (all-or-nothing). This is the only way to populate the files-touched count shown in the dashboard. Batch every file from a step of work into a single call — a single-element array is correct when only one file was touched.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId returned by actions.start' },\n files: {\n type: 'array',\n minItems: 1,\n description: 'Files touched, recorded atomically in one transaction.',\n items: {\n type: 'object',\n properties: {\n filePath: { type: 'string', description: 'Absolute or repo-relative path of the file' },\n operation: {\n type: 'string',\n enum: ['read', 'created', 'modified', 'deleted'],\n description: 'What was done to the file',\n },\n notes: { type: 'string', description: 'Optional short note about the change' },\n },\n required: ['filePath', 'operation'],\n },\n },\n },\n required: ['actionId', 'files'],\n },\n },\n {\n name: 'tasks.acceptance.update',\n description: 'Mark an acceptance criterion as met. Use the criterion id from tasks.get.',\n inputSchema: {\n type: 'object',\n properties: {\n criterionId: {\n type: 'number',\n description: 'The id of the acceptance criterion to mark as met',\n },\n },\n required: ['criterionId'],\n },\n },\n {\n name: 'tasks.acceptance.get',\n description:\n 'Given a taskId, returns all acceptance criteria for that task with their id, task_id, criterion text, and met status. Use the returned id values to call tasks.acceptance_update(criterionId).',\n inputSchema: {\n type: 'object',\n properties: {\n taskId: { type: 'number', description: 'Task ID' },\n },\n required: ['taskId'],\n },\n },\n {\n name: 'tasks.add',\n description:\n 'Create a new task in the harness. Use this when the user describes work in natural language. Infer slug, title, description, and acceptance criteria from the conversation. Ask for missing critical info before calling.',\n inputSchema: {\n type: 'object',\n properties: {\n title: { type: 'string', description: 'Short human-readable title for the task' },\n slug: {\n type: 'string',\n description:\n 'URL-safe identifier (lowercase, hyphens). Auto-derived from title if omitted.',\n },\n description: {\n type: 'string',\n description:\n 'Longer description of the task goal. No length limit; avoid padding — it costs shared context for other agents.',\n },\n acceptance: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'List of acceptance criteria (plain sentences). No length limit; avoid padding — it costs shared context for other agents.',\n },\n },\n required: ['title'],\n },\n },\n {\n name: 'actions.record_tool',\n description:\n 'Record one or more tool calls made during an action, atomically (all-or-nothing). This is the only way to populate the Tools dashboard. Batch every tool call from a step of work into a single call — a single-element array is correct when only one call was made.',\n inputSchema: {\n type: 'object',\n properties: {\n actionId: { type: 'number', description: 'The actionId returned by actions.start' },\n calls: {\n type: 'array',\n minItems: 1,\n description: 'Tool calls made, recorded atomically in one transaction.',\n items: {\n type: 'object',\n properties: {\n toolName: {\n type: 'string',\n description: 'Name of the tool that was called (e.g. Read, Bash, Edit)',\n },\n argsJson: {\n type: 'string',\n description: 'Optional JSON string of the arguments passed to the tool',\n },\n resultSummary: {\n type: 'string',\n description: 'Optional short summary of the tool result',\n },\n },\n required: ['toolName'],\n },\n },\n },\n required: ['actionId', 'calls'],\n },\n },\n {\n name: 'tasks.edit',\n description:\n 'Edit an existing task (title, description, acceptance criteria). Omitted fields keep their current values.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to edit' },\n title: { type: 'string', description: 'New title (optional)' },\n description: { type: 'string', description: 'New description (optional, null to clear)' },\n acceptance: {\n type: 'array',\n items: { type: 'string' },\n description: 'New acceptance criteria list (optional, null to keep existing)',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'tasks.archive',\n description:\n 'Archive a task. Archived tasks are hidden from default views (CLI and dashboard).',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to archive' },\n },\n required: ['id'],\n },\n },\n {\n name: 'tasks.unarchive',\n description: 'Unarchive a previously archived task, restoring it to default views.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'number', description: 'Task ID to unarchive' },\n },\n required: ['id'],\n },\n },\n {\n name: 'permissions.check',\n description:\n 'Check that a .claude/agents/*.md definition file exists for every role. Returns { in_sync, agents } where each agent is { ok } or { ok: false, reason: \"missing_file\" }. Agent file CONTENTS are never inspected — they are meant to be customised freely — so this never reports drift, only absence. Run `ahk build` to restore a missing file.',\n inputSchema: { type: 'object', properties: {}, required: [] },\n },\n {\n name: 'deps.snapshot',\n description: 'Snapshot current package.json dependencies to .harness/deps-lock.json',\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\n },\n {\n name: 'deps.check',\n description: 'Compare current package.json against .harness/deps-lock.json and report changes',\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\n },\n {\n name: 'ahk.doctor',\n description:\n 'Check lib version, agent files, and harness skills sync status. Returns structured JSON.',\n inputSchema: { type: 'object', properties: {}, required: [] },\n },\n] as const\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\nexport async function startMcpServer(config: HarnessConfig, cwd: string): Promise<void> {\n const db = await openDB(config, cwd)\n const docsPath = resolve(cwd, config.project.docsPath)\n\n const server = new Server(\n { name: 'agent-harness-kit', version: VERSION },\n { capabilities: { tools: {} } }\n )\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }))\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params\n const a = (args ?? {}) as Record<string, unknown>\n\n try {\n const result = await dispatch(name, a, db, docsPath, cwd, config)\n return result\n } catch (err) {\n return ok(`Error: ${err instanceof Error ? err.message : String(err)}`, true)\n }\n })\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n\n// ─── Dispatch ─────────────────────────────────────────────────────────────────\n\nexport async function dispatch(\n name: string,\n args: Record<string, unknown>,\n db: HarnessDB,\n docsPath: string,\n cwd: string,\n config: HarnessConfig\n): Promise<CallToolResult> {\n switch (name) {\n case 'actions.start': {\n const taskId = num(args, 'taskId')\n const agent = str(args, 'agent') as AgentName\n const action = await db.startAction(taskId, agent)\n return ok(JSON.stringify({ actionId: action.id }))\n }\n\n case 'actions.write': {\n const actionId = num(args, 'actionId')\n const sectionType = str(args, 'sectionType')\n if (sectionType === 'handoff') throw new Error('handoff sections must be written with actions.handoff.write')\n const content = str(args, 'content')\n await db.writeSection(actionId, sectionType, content)\n return ok(JSON.stringify({ recorded: true }))\n }\n\n case 'actions.complete': {\n const actionId = num(args, 'actionId')\n const summary = str(args, 'summary')\n const action = await db.completeAction(actionId, summary)\n return ok(JSON.stringify({ status: action.status, completedAt: action.completed_at }))\n }\n\n case 'actions.get': {\n const taskId = num(args, 'taskId')\n const actions = await db.getActionsForTask(taskId)\n const full = await Promise.all(\n actions.map(async (a) => {\n const sections = await db.getActionSections(a.id)\n return {\n id: a.id,\n agent: a.agent,\n status: a.status,\n created_at: a.created_at,\n completed_at: a.completed_at,\n summary: a.summary,\n sections: sections.map((s) => ({\n id: s.id,\n section_type: s.section_type,\n content: s.content,\n created_at: s.created_at,\n })),\n }\n })\n )\n return ok(JSON.stringify(full))\n }\n\n case 'actions.list': {\n const taskId = num(args, 'taskId')\n const limit = boundedInt(args, 'limit', 20, 1, 100)\n const rows = await db.listActionsForTask(taskId, { agent: optionalAgent(args, 'agent'), status: optionalActionStatus(args, 'status'), cursor: decodeActionCursor(optionalStr(args, 'cursor')), limit })\n const last = rows.at(-1)\n return ok(JSON.stringify({ items: rows.map((row) => ({ id: row.id, agent: row.agent, status: row.status, createdAt: row.created_at, completedAt: row.completed_at, summaryPreview: preview(row.summary), sectionCount: Number(row.section_count) })), nextCursor: rows.length === limit && last ? encodeActionCursor(last.created_at, last.id) : null }))\n }\n\n case 'actions.get_by_id': {\n const actionId = num(args, 'actionId')\n const action = await db.getAction(actionId)\n if (!action) return ok(JSON.stringify({ error: 'ACTION_NOT_FOUND', actionId }), true)\n const sections = await db.listActionSections(actionId, { limit: 100 })\n return ok(JSON.stringify({ id: action.id, taskId: action.task_id, agent: action.agent, status: action.status, summary: action.summary, createdAt: action.created_at, completedAt: action.completed_at, sections: sections.map(sectionIndex) }))\n }\n\n case 'actions.sections.list': {\n const actionId = num(args, 'actionId')\n const limit = boundedInt(args, 'limit', 20, 1, 100)\n const rows = await db.listActionSections(actionId, { types: optionalStringArray(args, 'types'), cursor: decodeSectionCursor(optionalStr(args, 'cursor')), limit })\n const last = rows.at(-1)\n return ok(JSON.stringify({ items: rows.map(sectionIndex), nextCursor: rows.length === limit && last ? encodeSectionCursor(last.id) : null }))\n }\n\n case 'actions.sections.get': {\n const sectionId = num(args, 'sectionId')\n const offset = boundedInt(args, 'offset', 0, 0, Number.MAX_SAFE_INTEGER)\n const length = boundedInt(args, 'length', 8000, 1, 12000)\n const section = await db.getActionSection(sectionId)\n if (!section) return ok(JSON.stringify({ error: 'SECTION_NOT_FOUND', sectionId }), true)\n const content = section.content.slice(offset, offset + length)\n const nextOffset = offset + content.length\n return ok(JSON.stringify({ sectionId: section.id, type: section.section_type, content, truncated: nextOffset < section.content.length, nextOffset: nextOffset < section.content.length ? nextOffset : null }))\n }\n\n case 'actions.handoff.write': {\n const actionId = num(args, 'actionId')\n const recipient = recipientRole(args['recipient'])\n const handoff = handoffFromArgs(args)\n const serialized = JSON.stringify({ version: 1, recipient, handoff })\n if (Buffer.byteLength(serialized, 'utf8') > 12_000) throw new Error('handoff must not exceed 12000 UTF-8 bytes')\n await db.writeSection(actionId, 'handoff', serialized)\n return ok(JSON.stringify({ recorded: true, recipient }))\n }\n\n case 'actions.handoff.get': {\n const taskId = num(args, 'taskId')\n const recipient = recipientRole(args['recipient'] ?? 'builder')\n for (const candidate of await db.getCompletedHandoffSections(taskId)) {\n const decoded = decodeHandoff(candidate.content)\n if (decoded?.recipient !== recipient) continue\n return ok(JSON.stringify({ found: true, taskId, sourceActionId: candidate.action_id, sourceAgent: candidate.agent, recipient, createdAt: candidate.created_at, handoff: decoded.handoff }))\n }\n return ok(JSON.stringify({ found: false, reason: 'HANDOFF_NOT_FOUND' }))\n }\n\n case 'tasks.get': {\n const status = args['status'] as string | undefined\n const includeArchived = args['includeArchived'] as boolean | undefined\n const tasks = status\n ? await db.getTasks(status as TaskStatus, includeArchived ?? false)\n : await db.getTasks(undefined, includeArchived ?? false)\n return ok(JSON.stringify(tasks))\n }\n\n case 'tasks.claim': {\n const id = num(args, 'id')\n const agent = str(args, 'agent')\n const task = await db.claimTask(id, agent)\n if (!task) {\n return ok(JSON.stringify({ error: 'task_already_claimed', taskId: id }))\n }\n return ok(JSON.stringify(task))\n }\n\n case 'tasks.add': {\n const title = str(args, 'title')\n const slug = (args['slug'] as string | undefined) ?? slugify(title)\n const description = args['description'] as string | undefined\n const acceptance = args['acceptance'] as string[] | undefined\n const task = await db.addTask({ slug, title, description, acceptance })\n return ok(JSON.stringify(task))\n }\n\n case 'tasks.update': {\n const id = num(args, 'id')\n const status = str(args, 'status') as TaskStatus\n if (status === 'done') {\n await db.closeOrphanedActions(id)\n }\n const task = await db.updateTaskStatus(id, status)\n return ok(JSON.stringify(task))\n }\n\n case 'docs.search': {\n const query = str(args, 'query')\n const results = searchDocs(docsPath, query)\n return ok(JSON.stringify(results))\n }\n\n case 'actions.record_file': {\n const actionId = num(args, 'actionId')\n const files = nonEmptyArray(args, 'files').map((f) => ({\n filePath: str(f, 'filePath'),\n operation: str(f, 'operation') as ActionFileRow['operation'],\n notes: f['notes'] as string | undefined,\n }))\n const recorded = await db.recordFiles(actionId, files)\n return ok(JSON.stringify({ recorded }))\n }\n\n case 'tasks.acceptance.update': {\n const criterionId = num(args, 'criterionId')\n await db.markAcceptanceMet(criterionId)\n return ok(JSON.stringify({ criterionId, met: true }))\n }\n\n case 'tasks.acceptance.get': {\n const taskId = num(args, 'taskId')\n const criteria = await db.getTaskAcceptance(taskId)\n return ok(JSON.stringify(criteria))\n }\n\n case 'actions.record_tool': {\n const actionId = num(args, 'actionId')\n const calls = nonEmptyArray(args, 'calls').map((c) => ({\n toolName: str(c, 'toolName'),\n argsJson: c['argsJson'] as string | undefined,\n resultSummary: c['resultSummary'] as string | undefined,\n }))\n const recorded = await db.recordTools(actionId, calls)\n return ok(JSON.stringify({ recorded }))\n }\n\n case 'tasks.edit': {\n const id = num(args, 'id')\n const title = args['title'] as string | undefined\n const description = args['description'] as string | null | undefined\n const acceptance = args['acceptance'] as string[] | null | undefined\n\n const task = await db.getTaskById(id)\n if (!task) return ok(JSON.stringify({ error: 'Task not found', taskId: id }), true)\n\n await db.updateTask(id, {\n title,\n description: description !== undefined ? description : undefined,\n })\n if (acceptance !== undefined && acceptance !== null) {\n await db.updateTaskAcceptance(id, acceptance)\n }\n const updated = await db.getTaskById(id)\n return ok(JSON.stringify(updated))\n }\n\n case 'tasks.archive': {\n const id = num(args, 'id')\n const task = await db.archiveTask(id)\n return ok(JSON.stringify(task))\n }\n\n case 'tasks.unarchive': {\n const id = num(args, 'id')\n const task = await db.unarchiveTask(id)\n return ok(JSON.stringify(task))\n }\n\n case 'permissions.check': {\n const result = checkPermissionsSync(cwd, config)\n return ok(JSON.stringify(result))\n }\n\n case 'deps.snapshot': {\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) {\n return ok('package.json not found in project root', true)\n }\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n const snapshot = {\n capturedAt: new Date().toISOString(),\n dependencies: pkg.dependencies ?? {},\n devDependencies: pkg.devDependencies ?? {},\n }\n const harnessDir = join(cwd, '.harness')\n mkdirSync(harnessDir, { recursive: true })\n writeFileSync(join(harnessDir, 'deps-lock.json'), JSON.stringify(snapshot, null, 2), 'utf8')\n return ok(\n JSON.stringify({\n message: 'Snapshot saved to .harness/deps-lock.json',\n capturedAt: snapshot.capturedAt,\n })\n )\n }\n\n case 'deps.check': {\n const pkgPath = join(cwd, 'package.json')\n const lockPath = join(cwd, '.harness', 'deps-lock.json')\n if (!existsSync(pkgPath)) {\n return ok('package.json not found in project root', true)\n }\n if (!existsSync(lockPath)) {\n return ok(\n JSON.stringify({\n status: 'no-snapshot',\n message: 'No deps-lock.json found. Run deps.snapshot first to establish a baseline.',\n })\n )\n }\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n const lock = JSON.parse(readFileSync(lockPath, 'utf8')) as {\n capturedAt: string\n dependencies: Record<string, string>\n devDependencies: Record<string, string>\n }\n const current = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n const previous = { ...(lock.dependencies ?? {}), ...(lock.devDependencies ?? {}) }\n\n const added: string[] = []\n const removed: string[] = []\n const majorBumps: Array<{ name: string; from: string; to: string }> = []\n\n for (const [name, version] of Object.entries(current)) {\n if (!(name in previous)) {\n added.push(`${name}@${version}`)\n } else {\n const prevMajor = parseInt(\n previous[name].replace(/^[\\^~>=v]/, '').split('.')[0] ?? '0',\n 10\n )\n const curMajor = parseInt(version.replace(/^[\\^~>=v]/, '').split('.')[0] ?? '0', 10)\n if (!isNaN(prevMajor) && !isNaN(curMajor) && curMajor > prevMajor) {\n majorBumps.push({ name, from: previous[name], to: version })\n }\n }\n }\n for (const depName of Object.keys(previous)) {\n if (!(depName in current)) {\n removed.push(depName)\n }\n }\n\n const significant = added.length > 0 || removed.length > 0 || majorBumps.length > 0\n const advisory = significant\n ? 'Significant dependency changes detected. Consider running `pnpx autoskills` (or `npx autoskills` if pnpm is unavailable) to refresh agent skills. Clearing stale skills before re-running is recommended.'\n : 'No significant dependency changes detected.'\n\n return ok(\n JSON.stringify({\n significant,\n added,\n removed,\n majorBumps,\n advisory,\n snapshotDate: lock.capturedAt,\n })\n )\n }\n\n case 'ahk.doctor': {\n const status = await getDoctorStatus(cwd)\n const result = {\n lib: { current: status.lib.current, latest: status.lib.latest, outdated: status.lib.outdated },\n // Agents are existence-checked only — there is no `outdated` bucket.\n // Hand-edited agent definitions are supported and must not be flagged.\n agents: {\n missing: status.agents.filter((a) => a.status === 'missing').map((a) => a.name),\n ok: status.agents.filter((a) => a.status === 'ok').map((a) => a.name),\n },\n skills: {\n missing: status.skills.filter((s) => s.status === 'missing').map((s) => s.name),\n outdated: status.skills.filter((s) => s.status === 'outdated').map((s) => s.name),\n ok: status.skills.filter((s) => s.status === 'ok').map((s) => s.name),\n },\n }\n return ok(JSON.stringify(result))\n }\n\n default:\n return ok(`Unknown tool: ${name}`, true)\n }\n}\n\n// ─── docs.search implementation ───────────────────────────────────────────────\n\ninterface DocSnippet {\n file: string\n line: number\n text: string\n}\n\nfunction searchDocs(docsPath: string, query: string, maxResults = 10): DocSnippet[] {\n const terms = query.toLowerCase().split(/\\s+/).filter(Boolean)\n const results: DocSnippet[] = []\n\n try {\n const files = collectMarkdownFiles(docsPath)\n for (const file of files) {\n if (results.length >= maxResults) break\n try {\n const content = readFileSync(file, 'utf8')\n const lines = content.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const lower = lines[i].toLowerCase()\n if (terms.every((t) => lower.includes(t))) {\n results.push({\n file: file.replace(docsPath + '/', ''),\n line: i + 1,\n text: lines[i].trim(),\n })\n if (results.length >= maxResults) break\n }\n }\n } catch {\n // skip unreadable files\n }\n }\n } catch {\n return [{ file: '', line: 0, text: `docs path not found: ${docsPath}` }]\n }\n\n return results\n}\n\nfunction collectMarkdownFiles(dir: string): string[] {\n const files: string[] = []\n try {\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry)\n const stat = statSync(full)\n if (stat.isDirectory()) {\n files.push(...collectMarkdownFiles(full))\n } else if (entry.endsWith('.md') || entry.endsWith('.txt')) {\n files.push(full)\n }\n }\n } catch {\n // directory may not exist yet\n }\n return files\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction ok(text: string, isError = false): CallToolResult {\n return { content: [{ type: 'text' as const, text }], isError }\n}\n\nfunction str(args: Record<string, unknown>, key: string): string {\n const v = args[key]\n if (typeof v !== 'string') throw new Error(`${key} must be a string`)\n return v\n}\n\nfunction num(args: Record<string, unknown>, key: string): number {\n const v = args[key]\n if (typeof v !== 'number') throw new Error(`${key} must be a number`)\n return v\n}\n\nfunction optionalStr(args: Record<string, unknown>, key: string): string | undefined { const value = args[key]; if (value === undefined) return undefined; if (typeof value !== 'string') throw new Error(`${key} must be a string`); return value }\nfunction boundedInt(args: Record<string, unknown>, key: string, fallback: number, min: number, max: number): number { const value = args[key]; if (value === undefined) return fallback; if (typeof value !== 'number' || !Number.isInteger(value) || value < min || value > max) throw new Error(`${key} must be an integer between ${min} and ${max}`); return value }\nfunction optionalStringArray(args: Record<string, unknown>, key: string): string[] | undefined { const value = args[key]; if (value === undefined) return undefined; if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || item.length === 0)) throw new Error(`${key} must be an array of non-empty strings`); return value }\n\nconst RECIPIENTS = ['lead', 'explorer', 'consultant', 'builder', 'reviewer'] as const\ntype HandoffRecipient = (typeof RECIPIENTS)[number]\ninterface Handoff { goal: string; completed: string[]; decisions: string[]; files: string[]; verification: string[]; blockers: string[]; nextStep: string }\nfunction recipientRole(value: unknown): HandoffRecipient { if (typeof value !== 'string' || !RECIPIENTS.includes(value as HandoffRecipient)) throw new Error(`recipient must be one of: ${RECIPIENTS.join(', ')}`); return value as HandoffRecipient }\nfunction requiredStringArray(args: Record<string, unknown>, key: string): string[] { if (!(key in args)) throw new Error(`${key} is required`); return optionalStringArray(args, key) ?? [] }\nfunction handoffFromArgs(args: Record<string, unknown>): Handoff { const goal = str(args, 'goal'); const nextStep = str(args, 'nextStep'); if (!goal.trim() || !nextStep.trim()) throw new Error('goal and nextStep must be non-empty strings'); return { goal, completed: requiredStringArray(args, 'completed'), decisions: requiredStringArray(args, 'decisions'), files: requiredStringArray(args, 'files'), verification: requiredStringArray(args, 'verification'), blockers: requiredStringArray(args, 'blockers'), nextStep } }\nfunction decodeHandoff(content: string): { recipient: HandoffRecipient; handoff: Handoff } | null { try { const value = JSON.parse(content) as { version?: unknown; recipient?: unknown; handoff?: Record<string, unknown> }; if (value.version !== 1 || !value.handoff) return null; return { recipient: recipientRole(value.recipient), handoff: handoffFromArgs(value.handoff) } } catch { return null } }\nfunction optionalAgent(args: Record<string, unknown>, key: string): AgentName | undefined { const value = optionalStr(args, key); if (value === undefined) return undefined; if (!['lead', 'explorer', 'consultant', 'builder', 'reviewer'].includes(value) && !value.startsWith('custom:')) throw new Error('agent must be a known role or custom:<name>'); return value as AgentName }\nfunction optionalActionStatus(args: Record<string, unknown>, key: string): ActionStatus | undefined { const value = optionalStr(args, key); if (value === undefined) return undefined; if (!['in_progress', 'completed', 'blocked'].includes(value)) throw new Error('status must be in_progress, completed, or blocked'); return value as ActionStatus }\nfunction encodeActionCursor(createdAt: string, id: number): string { return Buffer.from(JSON.stringify({ createdAt, id })).toString('base64url') }\nfunction decodeActionCursor(cursor: string | undefined): { createdAt: string; id: number } | undefined { if (!cursor) return undefined; try { const value = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8')) as { createdAt?: unknown; id?: unknown }; if (typeof value.createdAt !== 'string' || typeof value.id !== 'number' || !Number.isInteger(value.id)) throw new Error(); return { createdAt: value.createdAt, id: value.id } } catch { throw new Error('cursor is invalid') } }\nfunction encodeSectionCursor(id: number): string { return Buffer.from(String(id)).toString('base64url') }\nfunction decodeSectionCursor(cursor: string | undefined): number | undefined { if (!cursor) return undefined; const id = Number(Buffer.from(cursor, 'base64url').toString('utf8')); if (!Number.isInteger(id) || id < 1) throw new Error('cursor is invalid'); return id }\nfunction preview(summary: string | null): string | null { return summary ? summary.slice(0, 240) : null }\nfunction sectionIndex(section: { id: number; section_type: string; chars: number; created_at: string }) { return { id: section.id, type: section.section_type, chars: Number(section.chars), createdAt: section.created_at } }\n\n/** Validates that `args[key]` is a non-empty array of plain objects, as\n * required by the batch-only shapes of actions.record_file/record_tool\n * (task #74) — the single-entry top-level shape is no longer accepted, so\n * every entry must be pulled from this array via str()/num() on each item. */\nfunction nonEmptyArray(args: Record<string, unknown>, key: string): Record<string, unknown>[] {\n const v = args[key]\n if (!Array.isArray(v) || v.length === 0) {\n throw new Error(`${key} must be a non-empty array`)\n }\n for (const item of v) {\n if (typeof item !== 'object' || item === null) {\n throw new Error(`${key} entries must be objects`)\n }\n }\n return v as Record<string, unknown>[]\n}\n","import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { HarnessConfig } from '@/types'\n\nexport type AgentName = 'lead' | 'explorer' | 'consultant' | 'builder' | 'reviewer'\n\nexport interface AgentSyncResult {\n ok: boolean\n /** Only reason an agent can be out of sync now: its definition file is absent. */\n reason?: 'missing_file'\n}\n\nexport interface SyncCheckResult {\n in_sync: boolean\n agents?: Record<AgentName, AgentSyncResult>\n}\n\nconst AGENTS: AgentName[] = ['lead', 'explorer', 'consultant', 'builder', 'reviewer']\n\n/**\n * Verifies that each role's agent definition file exists.\n *\n * This used to parse the `tools:` frontmatter block and diff it against a\n * canonical list of `mcp__agent-harness-kit__*` tools. That premise no longer\n * holds: agent files intentionally omit `tools` so the agent inherits the full\n * tool set (including every MCP tool) from the session, and restrictions are\n * expressed as a `disallowedTools` denylist instead. With no allowlist in the\n * file, there is nothing to diff — every agent would have reported as missing\n * all of its tools.\n *\n * Agent file contents are user-customisable and are never inspected here.\n */\nexport function checkPermissionsSync(cwd: string, config: HarnessConfig): SyncCheckResult {\n if (config.provider !== 'claude-code') {\n return { in_sync: true }\n }\n\n const agents = {} as Record<AgentName, AgentSyncResult>\n let in_sync = true\n\n for (const agent of AGENTS) {\n const filePath = join(cwd, '.claude', 'agents', `${agent}.md`)\n const exists = existsSync(filePath)\n if (!exists) in_sync = false\n agents[agent] = exists ? { ok: true } : { ok: false, reason: 'missing_file' }\n }\n\n return { in_sync, agents }\n}\n","import { loadConfig } from '@/core/config'\nimport { startMcpServer } from '@/core/mcp-server'\nimport { checkPermissionsSync } from '@/core/permissions-check'\n\ninterface ServeOptions {\n port?: number\n}\n\nexport async function runServe(cwd: string, opts: ServeOptions): Promise<void> {\n const config = await loadConfig(cwd)\n\n if (opts.port) {\n config.tools.mcp.port = opts.port\n }\n\n // MCP server runs on stdio — do not write to stdout after this point.\n // Stderr is used for diagnostics.\n process.stderr.write(`[agent-harness-kit] MCP server starting (stdio)\\n`)\n\n const syncResult = checkPermissionsSync(cwd, config)\n if (!syncResult.in_sync && syncResult.agents) {\n const affected = Object.entries(syncResult.agents)\n .filter(([, r]) => !r.ok)\n .map(([name]) => name)\n .join(', ')\n process.stderr.write(`[agent-harness-kit] Agent definition files missing: ${affected}. Run: ahk build\\n`)\n }\n\n await startMcpServer(config, cwd)\n}\n","import Table from 'cli-table3'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\ninterface StatusOptions {\n json?: boolean\n}\n\nconst STATUS_COLOR: Record<string, (s: string) => string> = {\n pending: (s) => pc.dim(s),\n in_progress: (s) => pc.cyan(s),\n done: (s) => pc.green(s),\n blocked: (s) => pc.red(s),\n}\n\nexport async function runStatus(cwd: string, opts: StatusOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n const tasks = await db.getTasks()\n const summary = await db.getStatusSummary()\n\n if (opts.json) {\n const actions = await Promise.all(\n tasks.map(async (t) => ({\n ...t,\n actions: await db.getActionsForTask(t.id),\n acceptance: await db.getTaskAcceptance(t.id),\n })),\n )\n const archivedCount = (await db.getArchivedTasks()).length\n console.log(JSON.stringify({ tasks: actions, summary, archivedCount }, null, 2))\n return\n }\n\n if (tasks.length === 0) {\n console.log(pc.dim('No tasks yet. Run: ahk task add'))\n return\n }\n\n const table = new Table({\n head: ['ID', 'Slug', 'Title', 'Status', 'Assigned', 'Started'].map((h) => pc.bold(h)),\n style: { head: [], border: [] },\n })\n\n for (const t of tasks) {\n const colorFn = STATUS_COLOR[t.status] ?? ((s: string) => s)\n table.push([\n String(t.id),\n t.slug,\n t.title.slice(0, 40),\n colorFn(t.status),\n t.assigned_to ?? '—',\n t.started_at ? t.started_at.slice(0, 10) : '—',\n ])\n }\n\n console.log(table.toString())\n\n // Active actions\n const inProgress = tasks.filter((t) => t.status === 'in_progress')\n if (inProgress.length > 0) {\n console.log('')\n console.log(pc.bold('Active actions:'))\n for (const t of inProgress) {\n const actions = await db.getActionsForTask(t.id)\n const active = actions.filter((a) => a.status === 'in_progress')\n for (const a of active) {\n console.log(` ${pc.cyan(a.agent.padEnd(10))} → task #${t.id} ${t.slug}`)\n }\n }\n }\n\n // Summary line\n console.log('')\n const parts = summary.map((s) => {\n const fn = STATUS_COLOR[s.status] ?? ((x: string) => x)\n return `${fn(s.status)}: ${s.total}`\n })\n console.log(pc.dim('Tasks — ') + parts.join(pc.dim(' | ')))\n\n const archivedTasks = await db.getArchivedTasks()\n if (archivedTasks.length > 0) {\n console.log(pc.dim(`${archivedTasks.length} archived (use \\`ahk task list --archived\\` to view)`))\n }\n } finally {\n await db.close()\n }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\nimport type { TaskSeed } from '@/types'\n\ninterface SyncOptions {\n dryRun?: boolean\n direction?: 'in' | 'out' | 'both'\n}\n\nexport async function runSync(cwd: string, opts: SyncOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const direction = opts.direction ?? 'both'\n const featureListPath = resolve(join(cwd, config.storage.dir, 'feature_list.json'))\n\n const db = await openDB(config, cwd)\n\n try {\n if (direction === 'in' || direction === 'both') {\n await syncIn(featureListPath, db, opts.dryRun ?? false)\n }\n\n if (direction === 'out' || direction === 'both') {\n await syncOut(db, cwd, opts.dryRun ?? false)\n }\n } finally {\n await db.close()\n }\n}\n\nasync function syncIn(\n featureListPath: string,\n db: Awaited<ReturnType<typeof openDB>>,\n dryRun: boolean\n): Promise<void> {\n if (!existsSync(featureListPath)) {\n console.log(pc.dim(`feature_list.json not found at ${featureListPath} — skipping in-sync`))\n return\n }\n\n let seeds: TaskSeed[]\n try {\n seeds = JSON.parse(readFileSync(featureListPath, 'utf8')) as TaskSeed[]\n } catch (err) {\n console.error(pc.red(`Failed to parse feature_list.json: ${err}`))\n process.exit(1)\n }\n\n if (dryRun) {\n console.log(pc.bold('Dry run — in-sync (feature_list.json → SQLite):'))\n for (const t of seeds) {\n const existing = await db.getTaskBySlug(t.slug)\n console.log(` ${existing ? pc.dim('skip') : pc.green('add ')} ${t.slug}`)\n }\n return\n }\n\n const result = await db.syncFromFeatureList(seeds)\n console.log(pc.green(`✓ In-sync: ${result.added} added, ${result.skipped} already existed`))\n}\n\nasync function syncOut(\n db: Awaited<ReturnType<typeof openDB>>,\n cwd: string,\n dryRun: boolean\n): Promise<void> {\n if (dryRun) {\n const tasks = await db.getTasks()\n console.log(pc.bold('Dry run — out-sync (SQLite → feature_list.json):'))\n console.log(` ${tasks.length} tasks would be written`)\n return\n }\n\n await db.writeFeatureList(cwd)\n console.log(pc.green('✓ Out-sync: feature_list.json updated'))\n}\n","import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\nimport { slugify } from '@/core/materializer/scaffold-utils'\nimport { taskDescriptionSchema, taskTitleSchema } from '@/schema/task'\nimport { cliFormWithRetry } from '@/utils/form'\n\nexport async function runTaskAdd(cwd: string): Promise<void> {\n p.intro(pc.bold('agent-harness-kit — add task'))\n\n const title = await cliFormWithRetry(\n async () => {\n const val = await p.text({ message: 'Task title' })\n if (p.isCancel(val)) { p.cancel('Cancelled.'); process.exit(0) }\n return (val as string).trim()\n },\n taskTitleSchema,\n )\n\n const description = await cliFormWithRetry(\n async () => {\n const val = await p.text({\n message: 'Description (what and why)',\n placeholder: 'Describe the task in more detail, including any relevant context or instructions for the agents.',\n })\n if (p.isCancel(val)) { p.cancel('Cancelled.'); process.exit(0) }\n return (val as string).trim()\n },\n taskDescriptionSchema,\n )\n\n const acceptance: string[] = []\n p.log.info('Acceptance criteria — one per line, empty line to finish')\n while (true) {\n const val = await p.text({ message: '>', placeholder: 'Criterion (or press Enter to finish)' })\n if (p.isCancel(val) || !val || !(val as string).trim()) break\n acceptance.push((val as string).trim())\n }\n\n const spinner = p.spinner()\n spinner.start('Saving...')\n\n try {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n const slug = slugify(title)\n const task = await db.addTask({ slug, title, description: description || undefined, acceptance })\n await db.writeFeatureList(cwd)\n await db.close()\n\n spinner.stop('')\n console.log(pc.green(`✓ Task #${task.id} added — ${task.slug} (pending)`))\n console.log(pc.cyan('→') + ' ' + pc.cyan('ahk status') + ' to see all tasks')\n } catch (err) {\n spinner.stop(pc.red('Failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n}\n\n","import { spawnSync } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\nexport async function runTaskDone(cwd: string, idOrSlug: string): Promise<void> {\n const config = await loadConfig(cwd)\n\n // Run health check first if required\n if (config.health.required) {\n const scriptPath = resolve(cwd, config.health.scriptPath)\n if (existsSync(scriptPath)) {\n const result = spawnSync('bash', [scriptPath], { cwd, stdio: 'pipe', encoding: 'utf8' })\n if (result.status !== 0) {\n console.error(pc.red('✗ Health check failed — cannot mark task as done.'))\n if (result.stdout) console.error(result.stdout)\n if (result.stderr) console.error(result.stderr)\n process.exit(1)\n }\n }\n }\n\n const db = await openDB(config, cwd)\n\n try {\n const parsed = parseInt(idOrSlug, 10)\n const isId = !isNaN(parsed)\n const task = isId ? await db.getTaskById(parsed) : await db.getTaskBySlug(idOrSlug)\n\n if (!task) {\n console.error(pc.red(`Task not found: ${idOrSlug}`))\n process.exit(1)\n }\n\n if (task.status === 'done') {\n console.log(pc.dim(`Task #${task.id} is already done.`))\n return\n }\n\n await db.updateTaskStatus(task.id, 'done')\n await db.writeFeatureList(cwd)\n\n console.log(pc.green(`✓ Task #${task.id} — ${task.slug} marked as done`))\n } finally {\n await db.close()\n }\n}\n","import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\nimport { slugify } from '@/core/materializer/scaffold-utils'\n\nexport async function runTaskEdit(cwd: string): Promise<void> {\n p.intro(pc.bold('agent-harness-kit — edit task'))\n\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n // 1. Get all non-done tasks\n const allTasks = await db.getTasks()\n const activeTasks = allTasks.filter(t => t.status !== 'done')\n\n if (activeTasks.length === 0) {\n p.log.error('No active tasks to edit.')\n return\n }\n\n // 2. Let user select a task\n const taskId = await p.select({\n message: 'Select a task to edit',\n options: activeTasks.map(t => ({\n label: `#${t.id} — ${t.title} (${t.slug})`,\n value: t.id,\n })),\n })\n if (p.isCancel(taskId)) { p.cancel('Cancelled.'); process.exit(0) }\n\n const task = await db.getTaskById(taskId as number)\n if (!task) { p.log.error('Task not found'); process.exit(1) }\n\n // 3. Edit title\n const title = await p.text({\n message: 'Title',\n initialValue: task.title,\n })\n if (p.isCancel(title)) { p.cancel('Cancelled.'); process.exit(0) }\n\n // 4. Edit description\n const description = await p.text({\n message: 'Description (what and why)',\n initialValue: task.description ?? '',\n })\n if (p.isCancel(description)) { p.cancel('Cancelled.'); process.exit(0) }\n\n // 5. Edit acceptance criteria\n const currentAcceptance = await db.getTaskAcceptance(task.id)\n const newAcceptance: string[] = []\n\n p.log.info('Acceptance criteria — edit each, empty to delete. Add new ones at the end.')\n\n // Edit existing criteria\n for (let i = 0; i < currentAcceptance.length; i++) {\n const ac = currentAcceptance[i]\n const val = await p.text({\n message: `#${i + 1}/${currentAcceptance.length}`,\n initialValue: ac.criterion,\n defaultValue: '',\n })\n if (p.isCancel(val)) { p.cancel('Cancelled.'); process.exit(0) }\n const trimmed = (val as string).trim()\n if (trimmed !== '') {\n newAcceptance.push(trimmed)\n }\n // If empty, the criterion is deleted (not pushed)\n }\n\n // Add new criteria\n while (true) {\n const val = await p.text({ message: 'New acceptance criterion', placeholder: '(press Enter to finish)' })\n if (p.isCancel(val) || !val || !(val as string).trim()) break\n newAcceptance.push((val as string).trim())\n }\n\n // 6. Save\n const spinner = p.spinner()\n spinner.start('Saving...')\n\n try {\n const newSlug = slugify(title as string)\n await db.updateTask(task.id, {\n title: title as string,\n description: (description as string).trim() || undefined,\n slug: newSlug,\n })\n await db.updateTaskAcceptance(task.id, newAcceptance)\n await db.writeFeatureList(cwd)\n\n spinner.stop('')\n console.log(pc.green(`✓ Task #${task.id} updated — ${newSlug}`))\n } catch (err) {\n spinner.stop(pc.red('Failed'))\n p.log.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n } finally {\n await db.close()\n }\n}\n","import Table from 'cli-table3'\nimport pc from 'picocolors'\n\nimport { loadConfig } from '@/core/config'\nimport { openDB } from '@/core/db'\n\nimport type { TaskStatus } from '@/types'\n\ninterface TaskListOptions {\n status?: string\n json?: boolean\n archived?: boolean\n includeArchived?: boolean\n}\n\nconst STATUS_COLOR: Record<string, (s: string) => string> = {\n pending: (s) => pc.dim(s),\n in_progress: (s) => pc.cyan(s),\n done: (s) => pc.green(s),\n blocked: (s) => pc.red(s),\n}\n\nexport async function runTaskList(cwd: string, opts: TaskListOptions): Promise<void> {\n const config = await loadConfig(cwd)\n const db = await openDB(config, cwd)\n\n try {\n const validStatuses: TaskStatus[] = ['pending', 'in_progress', 'done', 'blocked']\n const filterStatus =\n opts.status && validStatuses.includes(opts.status as TaskStatus)\n ? (opts.status as TaskStatus)\n : undefined\n\n const tasks = opts.archived\n ? await db.getArchivedTasks()\n : filterStatus\n ? await db.getTasks(filterStatus, opts.includeArchived ?? false)\n : await db.getTasks(undefined, opts.includeArchived ?? false)\n\n if (opts.json) {\n console.log(JSON.stringify(tasks, null, 2))\n return\n }\n\n if (tasks.length === 0) {\n let msg = 'No tasks'\n if (filterStatus) msg += ` with status: ${filterStatus}`\n if (opts.archived) msg += ' (archived)'\n console.log(pc.dim(msg + '.'))\n return\n }\n\n const table = new Table({\n head: ['ID', 'Slug', 'Title', 'Status'].map((h) => pc.bold(h)),\n style: { head: [], border: [] },\n })\n\n for (const t of tasks) {\n const colorFn = STATUS_COLOR[t.status] ?? ((s: string) => s)\n table.push([String(t.id), t.slug, t.title.slice(0, 50), colorFn(t.status)])\n }\n\n console.log(table.toString())\n\n if (!opts.archived && !opts.includeArchived) {\n const archivedTasks = await db.getArchivedTasks()\n if (archivedTasks.length > 0) {\n console.log(pc.dim(`${archivedTasks.length} archived task${archivedTasks.length !== 1 ? 's' : ''} (use --archived to view)`))\n }\n }\n } finally {\n await db.close()\n }\n}\n","import { accessSync, constants, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport pc from 'picocolors'\n\nimport { pkg } from '@/core/package-data'\n\n/**\n * Fallback Windows executable extensions, used when `PATHEXT` is not set.\n * Mirrors the platform default (`.COM;.EXE;.BAT;.CMD`) — npm global installs\n * create an `ahk.cmd` shim (plus `ahk.ps1` and a bare shell script), never a\n * bare `ahk.exe`, so `.CMD` in particular must be covered.\n */\nconst DEFAULT_PATHEXT = ['.COM', '.EXE', '.BAT', '.CMD']\n\nexport interface ResolveOnPathOptions {\n /** PATH string to search. Defaults to `process.env.PATH`. */\n pathValue?: string\n /** PATHEXT string (Windows only). Defaults to `process.env.PATHEXT`. */\n pathext?: string\n /** Platform to resolve for. Defaults to `process.platform`. */\n platform?: NodeJS.Platform\n /**\n * POSIX executability probe for a candidate absolute path. Defaults to an\n * `fs.accessSync(p, X_OK)` check. Injectable for deterministic testing.\n */\n isExecutable?: (filePath: string) => boolean\n}\n\n/** Default POSIX executability check: file exists AND has an execute bit. */\nfunction defaultIsExecutable(filePath: string): boolean {\n try {\n accessSync(filePath, constants.X_OK)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Normalizes a `PATHEXT` value into a list of lowercased extensions each\n * beginning with a dot (e.g. `['.com', '.exe', '.bat', '.cmd']`). Falls back\n * to {@link DEFAULT_PATHEXT} when `pathext` is missing or blank.\n */\nfunction normalizeExts(pathext: string | undefined): string[] {\n const raw = pathext && pathext.trim().length > 0 ? pathext : DEFAULT_PATHEXT.join(';')\n return raw\n .split(';')\n .map((ext) => ext.trim().toLowerCase())\n .filter((ext) => ext.length > 0)\n .map((ext) => (ext.startsWith('.') ? ext : `.${ext}`))\n}\n\n/**\n * Pure, cross-platform \"is `name` resolvable as an executable on PATH?\" check.\n *\n * All environment inputs (PATH, PATHEXT, platform) are injectable so BOTH the\n * win32 and POSIX code paths are testable on any CI regardless of the host OS\n * (`process.platform` cannot be reassigned in a test).\n *\n * Behavior:\n * - Splits `pathValue` on the platform-appropriate delimiter (`;` on win32,\n * `:` elsewhere) and skips empty segments.\n * - win32: a candidate matches (case-insensitively) if a directory entry\n * equals the bare `name` or `name` + any `PATHEXT` extension. This is why\n * an `ahk.cmd` shim resolves for the bare name `ahk`.\n * - POSIX: a candidate matches if `join(dir, name)` exists AND is executable.\n * - An undefined/empty `pathValue` returns `false` and never throws; a\n * malformed or inaccessible directory is skipped rather than thrown.\n */\nexport function resolveOnPath(name: string, options: ResolveOnPathOptions = {}): boolean {\n const {\n pathValue = process.env.PATH,\n pathext = process.env.PATHEXT,\n platform = process.platform,\n isExecutable = defaultIsExecutable,\n } = options\n\n if (!pathValue) return false\n\n const isWindows = platform === 'win32'\n const sep = isWindows ? ';' : ':'\n const dirs = pathValue.split(sep).filter((dir) => dir.length > 0)\n if (dirs.length === 0) return false\n\n if (isWindows) {\n const lowerName = name.toLowerCase()\n // Candidate filenames (lowercased): the bare name (in case the caller\n // passed one that already includes an extension) plus name + each ext.\n const candidates = new Set<string>([lowerName, ...normalizeExts(pathext).map((ext) => `${lowerName}${ext}`)])\n for (const dir of dirs) {\n let entries: string[]\n try {\n entries = readdirSync(dir)\n } catch {\n // Missing/inaccessible directory on PATH — skip it, never throw.\n continue\n }\n for (const entry of entries) {\n if (candidates.has(entry.toLowerCase())) return true\n }\n }\n return false\n }\n\n for (const dir of dirs) {\n try {\n if (isExecutable(join(dir, name))) return true\n } catch {\n // Inaccessible entry — skip it, never throw.\n continue\n }\n }\n return false\n}\n\n/**\n * Thin wrapper over {@link resolveOnPath} that reads the real\n * `process.env.PATH`/`PATHEXT` and `process.platform`. Returns whether `name`\n * is resolvable as an executable on the current machine's PATH.\n */\nexport function isExecutableOnPath(name: string): boolean {\n return resolveOnPath(name)\n}\n\n/**\n * Non-blocking warning emitted at config-generation time when the project has\n * no local install AND the bare `ahk` binary is not resolvable on PATH. On the\n * global-install path the generated MCP config launches `ahk serve` directly,\n * so without `ahk` on PATH that config would fail later at spawn time. This\n * moves the failure earlier and makes it actionable. Modeled on\n * `printLocalInstallWarning()`: yellow ⚠ header + dim guidance + exact install\n * commands, all to stderr. Never calls `process.exit`; never changes the exit\n * code.\n */\nexport function printMissingGlobalBinaryWarning(): void {\n console.error(pc.yellow('⚠ `ahk` was not found on your PATH.'))\n console.error(pc.dim(' Your project has no local install, so the generated MCP config launches'))\n console.error(pc.dim(' `ahk serve` directly. Without `ahk` on your PATH, starting the MCP server'))\n console.error(pc.dim(' from that config will fail. This is only a warning — the command continues.'))\n console.error(pc.dim(` Run: npm i -g ${pkg.name} (install globally)`))\n console.error(pc.dim(` or: npm install --save-dev ${pkg.name} (install locally in this project)`))\n}\n","// src/core/update-check.ts\nimport pc from 'picocolors'\n\nimport { drawBox } from '@/commands/init-helpers'\n\nimport { pkg } from './package-data'\n\nconst REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`\nconst TIMEOUT_MS = 2500\n\ninterface UpdateInfo {\n current: string\n latest: string\n}\n\nexport function checkForUpdate(currentVersion: string): Promise<UpdateInfo | null> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => resolve(null), TIMEOUT_MS)\n\n fetch(REGISTRY_URL)\n .then((res) => res.json())\n .then((data) => {\n clearTimeout(timer)\n const latest = (data as { version: string }).version\n resolve(isNewer(latest, currentVersion) ? { current: currentVersion, latest } : null)\n })\n .catch(() => {\n clearTimeout(timer)\n resolve(null)\n })\n })\n}\n\nexport function printUpdateMessage({ current, latest }: UpdateInfo): void {\n const lines = [\n ` Update available ${pc.dim(current)} → ${pc.green(latest)} `,\n ` Run: ${pc.cyan(`pnpm i ${pkg.name}@${latest}`)} `,\n ]\n\n drawBox(lines)\n}\n\nfunction isNewer(latest: string, current: string): boolean {\n const toNum = (v: string) => v.split('.').map(Number)\n const [lMaj, lMin, lPat] = toNum(latest)\n const [cMaj, cMin, cPat] = toNum(current)\n\n if (lMaj !== cMaj) return lMaj > cMaj\n if (lMin !== cMin) return lMin > cMin\n\n return lPat > cPat\n}\n"],"mappings":"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","names":["pc","p","pc","existsSync","join","cwd","existsSync","readFileSync","join","existsSync","join","join","require","p","cwd","join","existsSync","pkgPath","cwd","existsSync","join","pkgPath","pkg","readFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","cwd","dirname","existsSync","mkdirSync","readFileSync","writeFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","resolve","fileURLToPath","readFileSync","dirname","join","fileURLToPath","dirname","fileURLToPath","join","readFileSync","v","__dirname","dirname","fileURLToPath","cwd","existsSync","join","mkdirSync","resolve","writeFileSync","readFileSync","cwd","existsSync","join","existsSync","mkdirSync","writeFileSync","join","resolve","cwd","write","join","mkdirSync","resolve","writeFileSync","existsSync","existsSync","mkdirSync","writeFileSync","join","resolve","cwd","write","join","mkdirSync","resolve","writeFileSync","existsSync","existsSync","mkdirSync","writeFileSync","join","resolve","cwd","write","join","mkdirSync","resolve","writeFileSync","existsSync","p","AGENT_LABELS","cwd","spinner","pc","dirname","join","fileURLToPath","pc","watch","existsSync","readFileSync","join","resolve","readFileSync","resolve","task","join","existsSync","watch","__dirname","dirname","fileURLToPath","cwd","join","pc","pc","existsSync","readFileSync","dirname","join","fileURLToPath","__dirname","dirname","fileURLToPath","v","join","existsSync","cwd","__dirname","readFileSync","pc","cwd","writeFileSync","pc","cwd","pc","writeFileSync","existsSync","homedir","join","resolve","pc","ok","pc","cwd","homedir","existsSync","join","resolve","existsSync","mkdirSync","readFileSync","writeFileSync","join","p","pc","v","p","v","existsSync","readFileSync","join","pc","cwd","pkgPath","join","existsSync","readFileSync","pkg","str","pc","join","existsSync","readFileSync","cwd","pc","spinner","writeFileSync","mkdirSync","p","pc","cwd","pc","spinner","existsSync","mkdirSync","writeFileSync","homedir","dirname","join","resolve","pc","log","cwd","join","resolve","mkdirSync","writeFileSync","dirname","existsSync","homedir","pc","join","pc","cwd","pc","join","existsSync","rmSync","homedir","join","resolve","p","pc","cwd","resolve","existsSync","pc","confirm","join","rmSync","homedir","existsSync","mkdirSync","readdirSync","readFileSync","writeFileSync","join","resolve","existsSync","join","cwd","cwd","resolve","ok","task","pkgPath","join","existsSync","pkg","readFileSync","mkdirSync","writeFileSync","name","readdirSync","text","v","cwd","pc","pc","cwd","existsSync","readFileSync","join","resolve","pc","cwd","resolve","join","existsSync","pc","readFileSync","p","pc","cwd","pc","spinner","task","spawnSync","existsSync","resolve","pc","cwd","resolve","existsSync","spawnSync","pc","task","p","pc","cwd","pc","task","spinner","Table","pc","STATUS_COLOR","pc","cwd","Table","readdirSync","join","pc","candidates","readdirSync","join","pc","pc","REGISTRY_URL","TIMEOUT_MS","resolve","isNewer","pc","v","pc"]}
|