fifony 0.1.21 → 0.1.22-next.ca3682c
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 +19 -7
- package/app/dist/assets/KeyboardShortcutsHelp-CqCRSinb.js +1 -0
- package/app/dist/assets/OnboardingWizard-sB4Jirx5.js +1 -0
- package/app/dist/assets/analytics.lazy-BPdQoH_Z.js +1 -0
- package/app/dist/assets/{createLucideIcon-DtZs0TX0.js → createLucideIcon-BWC-guQt.js} +1 -1
- package/app/dist/assets/index-BaDR-1h-.js +43 -0
- package/app/dist/assets/index-DjmUHXd1.css +1 -0
- package/app/dist/assets/vendor-BTlTWMUF.js +9 -0
- package/app/dist/dinofffaur.png +0 -0
- package/app/dist/index.html +4 -5
- package/app/dist/service-worker.js +1 -1
- package/app/public/dinofffaur.png +0 -0
- package/bin/fifony-wrap.js +53 -0
- package/dist/agent/cli-wrapper.js +78 -0
- package/dist/agent/cli-wrapper.js.map +1 -0
- package/dist/agent/run-local.js +217 -7893
- package/dist/agent/run-local.js.map +1 -1
- package/dist/chunk-CWC7H4H3.js +91 -0
- package/dist/chunk-CWC7H4H3.js.map +1 -0
- package/dist/{chunk-SMGXYOWU.js → chunk-DD5BE2W6.js} +430 -31
- package/dist/chunk-DD5BE2W6.js.map +1 -0
- package/dist/chunk-DVU3CXWA.js +75 -0
- package/dist/chunk-DVU3CXWA.js.map +1 -0
- package/dist/chunk-IXE2JEIU.js +7115 -0
- package/dist/chunk-IXE2JEIU.js.map +1 -0
- package/dist/chunk-NA6PJPZD.js +2110 -0
- package/dist/chunk-NA6PJPZD.js.map +1 -0
- package/dist/cli.js +187 -1
- package/dist/cli.js.map +1 -1
- package/dist/issue-runner-OEUARE4A.js +13 -0
- package/dist/issue-runner-OEUARE4A.js.map +1 -0
- package/dist/issue-state-machine-OKQIWTVN.js +37 -0
- package/dist/issue-state-machine-OKQIWTVN.js.map +1 -0
- package/dist/mcp/server.js +592 -605
- package/dist/mcp/server.js.map +1 -1
- package/dist/queue-workers-SVNB4ESJ.js +20 -0
- package/dist/queue-workers-SVNB4ESJ.js.map +1 -0
- package/dist/store-NIW6OEYC.js +56 -0
- package/dist/store-NIW6OEYC.js.map +1 -0
- package/package.json +10 -9
- package/FIFONY.md +0 -173
- package/app/dist/assets/KeyboardShortcutsHelp-BTjiQe_Y.js +0 -1
- package/app/dist/assets/OnboardingWizard-BALlquG0.js +0 -1
- package/app/dist/assets/analytics.lazy-DjSzXIey.js +0 -1
- package/app/dist/assets/index-BV11ScVl.js +0 -42
- package/app/dist/assets/index-DWbxgKSd.css +0 -1
- package/app/dist/assets/vendor-BoGBoEwT.js +0 -9
- package/app/dist/assets/zap-DpjdVd1i.js +0 -1
- package/dist/chunk-SMGXYOWU.js.map +0 -1
- package/src/fixtures/agent-catalog.json +0 -208
- package/src/fixtures/skill-catalog.json +0 -67
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/domains/workspace.ts","../src/agents/command-executor.ts","../src/agents/providers.ts","../src/agents/adapters/claude.ts","../src/agents/adapters/shared.ts","../src/agents/adapters/commands.ts","../src/agents/adapters/codex.ts","../src/agents/adapters/gemini.ts","../src/agents/adapters/registry.ts","../src/agents/prompt-builder.ts","../src/domains/metrics.ts","../src/persistence/metrics-cache.ts","../src/persistence/dirty-tracker.ts","../src/persistence/plugins/issue-state-machine.ts"],"sourcesContent":["import {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { copyFile, mkdir, readdir, stat, writeFile } from \"node:fs/promises\";\nimport { extname, join, resolve } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport type { IssueEntry, RuntimeState } from \"../types.ts\";\nimport {\n SOURCE_ROOT,\n SOURCE_MARKER,\n TARGET_ROOT,\n WORKSPACE_ROOT,\n} from \"../concerns/constants.ts\";\nimport {\n now,\n idToSafePath,\n} from \"../concerns/helpers.ts\";\nimport { logger } from \"../concerns/logger.ts\";\nimport { runHook } from \"../agents/command-executor.ts\";\nimport { buildPrompt } from \"../agents/prompt-builder.ts\";\nimport { inferCapabilityPaths } from \"../routing/capability-resolver.ts\";\n\n// ── Source bootstrap ────────────────────────────────────────────────────────\n\nconst SKIP_DIRS = new Set([\n \".git\", \".fifony\", \"node_modules\", \".venv\", \"data\",\n \"dist\", \"build\", \".turbo\", \".next\", \".nuxt\", \".tanstack\",\n \"coverage\", \"artifacts\", \"captures\", \"tmp\", \"temp\",\n]);\n\nfunction shouldSkipPath(relativePath: string): boolean {\n const parts = relativePath.split(\"/\");\n if (parts.some((segment) => SKIP_DIRS.has(segment))) return true;\n const base = parts.at(-1) ?? \"\";\n if (base.startsWith(\"map_scan_\") && extname(base) === \".json\") return true;\n if (extname(base) === \".xlsx\") return true;\n return false;\n}\n\nexport function bootstrapSource(): void {\n if (existsSync(SOURCE_MARKER)) return;\n\n logger.info(\"Creating local source snapshot for Fifony (local-only runtime)...\");\n\n const copyRecursive = (source: string, target: string, rel = \"\") => {\n mkdirSync(target, { recursive: true });\n const items = readdirSync(source, { withFileTypes: true });\n\n for (const item of items) {\n const nextRel = rel ? `${rel}/${item.name}` : item.name;\n if (shouldSkipPath(nextRel)) continue;\n\n const sourcePath = `${source}/${item.name}`;\n const targetPath = `${target}/${item.name}`;\n const itemStat = statSync(sourcePath);\n\n if (item.isDirectory()) {\n copyRecursive(sourcePath, targetPath, nextRel);\n continue;\n }\n\n if (item.isSymbolicLink() || itemStat.isSymbolicLink()) continue;\n\n if (itemStat.isFile() || itemStat.isFIFO()) {\n try {\n const file = readFileSync(sourcePath);\n writeFileSync(targetPath, file);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n logger.debug(`Skipped missing source file: ${sourcePath}`);\n } else {\n throw error;\n }\n }\n }\n }\n };\n\n mkdirSync(SOURCE_ROOT, { recursive: true });\n copyRecursive(TARGET_ROOT, SOURCE_ROOT);\n writeFileSync(SOURCE_MARKER, `${now()}\\n`, \"utf8\");\n}\n\nlet sourceReadyPromise: Promise<void> | null = null;\nlet skipSourceFlag = false;\n\nexport function setSkipSource(skip: boolean): void {\n skipSourceFlag = skip;\n}\n\n/**\n * Async, lazy version of bootstrapSource().\n * Only runs the copy once, on first call. Subsequent calls resolve immediately.\n * Emits progress via optional callback.\n */\nexport async function ensureSourceReady(\n onProgress?: (status: \"copying\" | \"ready\") => void,\n): Promise<void> {\n if (skipSourceFlag) {\n onProgress?.(\"ready\");\n return;\n }\n if (existsSync(SOURCE_MARKER)) {\n onProgress?.(\"ready\");\n return;\n }\n\n // Deduplicate concurrent calls\n if (sourceReadyPromise) return sourceReadyPromise;\n\n sourceReadyPromise = (async () => {\n onProgress?.(\"copying\");\n logger.info(\"Creating local source snapshot (async) for Fifony...\");\n\n const copyRecursiveAsync = async (source: string, target: string, rel = \"\") => {\n await mkdir(target, { recursive: true });\n const items = await readdir(source, { withFileTypes: true });\n\n for (const item of items) {\n const nextRel = rel ? `${rel}/${item.name}` : item.name;\n if (shouldSkipPath(nextRel)) continue;\n\n const sourcePath = `${source}/${item.name}`;\n const targetPath = `${target}/${item.name}`;\n const itemStat = await stat(sourcePath);\n\n if (item.isDirectory()) {\n await copyRecursiveAsync(sourcePath, targetPath, nextRel);\n continue;\n }\n\n if (item.isSymbolicLink() || itemStat.isSymbolicLink()) continue;\n\n if (itemStat.isFile() || itemStat.isFIFO()) {\n try {\n await copyFile(sourcePath, targetPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n logger.debug(`Skipped missing source file: ${sourcePath}`);\n } else {\n throw error;\n }\n }\n }\n }\n };\n\n await mkdir(SOURCE_ROOT, { recursive: true });\n await copyRecursiveAsync(TARGET_ROOT, SOURCE_ROOT);\n await writeFile(SOURCE_MARKER, `${now()}\\n`, \"utf8\");\n onProgress?.(\"ready\");\n logger.info(\"Source snapshot ready (async).\");\n })();\n\n return sourceReadyPromise;\n}\n\n// ── Workspace setup ─────────────────────────────────────────────────────────\n\n/** Check if a directory is inside a git repository. */\nfunction isGitRepo(dir: string): boolean {\n try {\n execSync(\"git rev-parse --git-dir\", { cwd: dir, stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Detect the default branch for a git repo using multiple fallback strategies. */\nexport function detectDefaultBranch(dir: string): string {\n try {\n const current = execSync(\"git rev-parse --abbrev-ref HEAD\", { cwd: dir, encoding: \"utf8\" }).trim();\n if (current && current !== \"HEAD\") return current;\n // HEAD = detached state, fall through to remote detection\n const remote = execSync(\"git symbolic-ref refs/remotes/origin/HEAD\", { cwd: dir, encoding: \"utf8\" }).trim();\n return remote.replace(\"refs/remotes/origin/\", \"\");\n } catch {\n return \"main\";\n }\n}\n\n/** Create a git worktree for the issue at the given path. */\nexport async function createGitWorktree(issue: IssueEntry, worktreePath: string, baseBranch?: string): Promise<void> {\n let headCommitAtStart = \"\";\n const resolvedBaseBranch = baseBranch ?? detectDefaultBranch(TARGET_ROOT);\n try {\n headCommitAtStart = execSync(\"git rev-parse HEAD\", { cwd: TARGET_ROOT, encoding: \"utf8\" }).trim();\n } catch {}\n\n const branchName = `fifony/${issue.id}`;\n\n // -B creates or resets the branch (handles retry scenarios)\n execSync(`git worktree add \"${worktreePath}\" -B \"${branchName}\"`, {\n cwd: TARGET_ROOT,\n stdio: \"pipe\",\n });\n\n // Register fifony runtime files as ignored in the worktree's local excludes\n try {\n const gitFileContent = readFileSync(join(worktreePath, \".git\"), \"utf8\").trim();\n const gitDirRel = gitFileContent.replace(\"gitdir: \", \"\").trim();\n const gitDirPath = resolve(worktreePath, gitDirRel);\n mkdirSync(join(gitDirPath, \"info\"), { recursive: true });\n writeFileSync(join(gitDirPath, \"info\", \"exclude\"), \"fifony-*\\n.fifony-*\\nfifony_*\\n\", \"utf8\");\n } catch (err) {\n logger.warn({ err: String(err) }, \"[Agent] Failed to write worktree excludes\");\n }\n\n issue.branchName = branchName;\n issue.baseBranch = resolvedBaseBranch;\n issue.headCommitAtStart = headCommitAtStart;\n issue.worktreePath = worktreePath;\n\n logger.debug({ issueId: issue.id, branchName, baseBranch: resolvedBaseBranch, worktreePath }, \"[Agent] Git worktree created\");\n}\n\nexport async function prepareWorkspace(\n issue: IssueEntry,\n state: RuntimeState,\n defaultBranch?: string,\n): Promise<{ workspacePath: string; promptText: string; promptFile: string }> {\n const safeId = idToSafePath(issue.id);\n const workspaceRoot = join(WORKSPACE_ROOT, safeId); // management dir\n const worktreePath = join(workspaceRoot, \"worktree\"); // code dir (git worktree)\n const createdNow = !existsSync(worktreePath);\n\n if (createdNow) {\n mkdirSync(workspaceRoot, { recursive: true });\n logger.debug({ issueId: issue.id, identifier: issue.identifier, workspacePath: workspaceRoot }, \"[Agent] Creating workspace\");\n\n if (state.config.afterCreateHook) {\n mkdirSync(worktreePath, { recursive: true });\n await runHook(state.config.afterCreateHook, worktreePath, issue, \"after_create\");\n } else if (isGitRepo(TARGET_ROOT)) {\n await createGitWorktree(issue, worktreePath, defaultBranch);\n } else {\n // Fallback: copy SOURCE_ROOT snapshot\n await ensureSourceReady();\n mkdirSync(worktreePath, { recursive: true });\n cpSync(SOURCE_ROOT, worktreePath, {\n recursive: true,\n force: true,\n filter: (sourcePath) => !sourcePath.startsWith(WORKSPACE_ROOT),\n });\n }\n\n logger.debug({ issueId: issue.id, workspacePath: workspaceRoot, worktreePath }, \"[Agent] Workspace created\");\n } else {\n logger.debug({ issueId: issue.id, workspacePath: workspaceRoot }, \"[Agent] Reusing existing workspace\");\n }\n\n const metaPath = join(workspaceRoot, \"issue.json\");\n const promptText = await buildPrompt(issue, null);\n const promptFile = join(workspaceRoot, \"prompt.md\");\n writeFileSync(metaPath, JSON.stringify({ ...issue, runtimeSource: SOURCE_ROOT, bootstrapAt: now() }, null, 2), \"utf8\");\n writeFileSync(promptFile, `${promptText}\\n`, \"utf8\");\n\n issue.workspacePath = workspaceRoot;\n issue.worktreePath = worktreePath;\n issue.workspacePreparedAt = now();\n\n return { workspacePath: workspaceRoot, promptText, promptFile };\n}\n\nexport async function cleanWorkspace(\n issueId: string,\n issue: IssueEntry | null,\n state: RuntimeState,\n): Promise<void> {\n const safeId = idToSafePath(issueId);\n const workspacePath = issue?.workspacePath ?? join(WORKSPACE_ROOT, safeId);\n if (!existsSync(workspacePath)) return;\n\n // Run before_remove hook (failure is logged but ignored)\n if (state.config.beforeRemoveHook) {\n try {\n const dummyIssue = issue ?? { id: issueId, identifier: issueId } as IssueEntry;\n await runHook(state.config.beforeRemoveHook, workspacePath, dummyIssue, \"before_remove\");\n } catch (error) {\n logger.warn(`before_remove hook failed for ${issueId}: ${String(error)}`);\n }\n }\n\n // Git worktree cleanup\n if (issue?.branchName && issue.worktreePath) {\n try {\n execSync(`git worktree remove --force \"${issue.worktreePath}\"`, { cwd: TARGET_ROOT, stdio: \"pipe\" });\n logger.info(`Removed worktree for ${issueId}: ${issue.worktreePath}`);\n } catch (error) {\n logger.warn(`Failed to remove worktree for ${issueId}: ${String(error)}`);\n try { rmSync(issue.worktreePath, { recursive: true, force: true }); } catch {}\n }\n try {\n execSync(`git branch -D \"${issue.branchName}\"`, { cwd: TARGET_ROOT, stdio: \"pipe\" });\n } catch { /* branch may already be gone */ }\n // Also remove the management dir\n try { rmSync(workspacePath, { recursive: true, force: true }); } catch {}\n return;\n }\n\n // Legacy: remove the whole workspace dir\n try {\n rmSync(workspacePath, { recursive: true, force: true });\n logger.info(`Cleaned workspace for ${issueId}: ${workspacePath}`);\n } catch (error) {\n logger.warn(`Failed to clean workspace for ${issueId}: ${String(error)}`);\n }\n}\n\n// ── Workspace diff ──────────────────────────────────────────────────────────\n\nexport function inferChangedWorkspacePaths(workspacePath: string, limit = 32, issue?: IssueEntry): string[] {\n if (!issue?.baseBranch || !issue.branchName) return [];\n try {\n const output = execSync(\n `git diff --name-only \"${issue.baseBranch}\"...\"${issue.branchName}\"`,\n { cwd: TARGET_ROOT, encoding: \"utf8\", timeout: 10_000, stdio: \"pipe\" },\n );\n return output.trim().split(\"\\n\").filter(Boolean).slice(0, limit);\n } catch {\n return [];\n }\n}\n\n/** Compute lines added/removed/files changed from workspace diff. */\nexport function computeDiffStats(issue: IssueEntry): void {\n if (!issue.baseBranch || !issue.branchName) return;\n try {\n let raw = \"\";\n try {\n raw = execSync(\n `git diff --stat \"${issue.baseBranch}\"...\"${issue.branchName}\"`,\n { cwd: TARGET_ROOT, encoding: \"utf8\", maxBuffer: 512_000, timeout: 10_000, stdio: \"pipe\" },\n );\n } catch (err: any) {\n raw = err.stdout || \"\";\n }\n if (raw) parseDiffStats(issue, raw);\n } catch {}\n}\n\nexport function parseDiffStats(issue: IssueEntry, raw: string): void {\n const lines = raw.trim().split(\"\\n\");\n const summary = lines[lines.length - 1] || \"\";\n const filesMatch = summary.match(/(\\d+)\\s+files?\\s+changed/);\n const addMatch = summary.match(/(\\d+)\\s+insertions?\\(\\+\\)/);\n const delMatch = summary.match(/(\\d+)\\s+deletions?\\(-\\)/);\n\n const internalRe = /fifony[-_]|\\.fifony-|WORKFLOW\\.local/;\n const fileLines = lines.slice(0, -1).filter((l) => {\n const name = l.trim().split(\"|\")[0]?.trim().split(\"/\").pop() || \"\";\n return !internalRe.test(name);\n });\n\n issue.filesChanged = fileLines.length || (filesMatch ? parseInt(filesMatch[1], 10) : 0);\n issue.linesAdded = addMatch ? parseInt(addMatch[1], 10) : 0;\n issue.linesRemoved = delMatch ? parseInt(delMatch[1], 10) : 0;\n}\n\n// ── Workspace merge ─────────────────────────────────────────────────────────\n\nexport interface MergeResult {\n copied: string[];\n deleted: string[];\n skipped: string[];\n conflicts: string[];\n}\n\nfunction ensureWorktreeCommitted(issue: IssueEntry): void {\n const worktreePath = issue.worktreePath;\n if (!worktreePath || !issue.branchName) return;\n\n execSync(\"git add -A\", { cwd: worktreePath, stdio: \"pipe\" });\n const statusBeforeCommit = execSync(\"git status --porcelain\", { cwd: worktreePath, encoding: \"utf8\" }).trim();\n if (!statusBeforeCommit) return;\n\n try {\n execSync(`git commit -m \"fifony: agent changes for ${issue.identifier}\"`, { cwd: worktreePath, stdio: \"pipe\" });\n } catch (error) {\n const remaining = execSync(\"git status --porcelain\", { cwd: worktreePath, encoding: \"utf8\" }).trim();\n if (remaining) {\n throw new Error(`Failed to commit agent changes for ${issue.identifier}: ${String(error)}`);\n }\n }\n\n const statusAfterCommit = execSync(\"git status --porcelain\", { cwd: worktreePath, encoding: \"utf8\" }).trim();\n if (statusAfterCommit) {\n throw new Error(`Worktree for ${issue.identifier} still has uncommitted changes after commit.`);\n }\n}\n\nexport { ensureWorktreeCommitted };\n\n/** Merge a worktree branch into TARGET_ROOT using git merge --no-ff. */\nfunction mergeWorktree(issue: IssueEntry, worktreePath: string): MergeResult {\n const result: MergeResult = { copied: [], deleted: [], skipped: [], conflicts: [] };\n ensureWorktreeCommitted(issue);\n\n const currentBranch = execSync(\"git rev-parse --abbrev-ref HEAD\", { cwd: TARGET_ROOT, encoding: \"utf8\" }).trim();\n if (currentBranch !== issue.baseBranch) {\n throw new Error(`Cannot merge ${issue.identifier}: current branch is ${currentBranch}, expected ${issue.baseBranch}.`);\n }\n\n const targetStatus = execSync(\"git status --porcelain\", { cwd: TARGET_ROOT, encoding: \"utf8\" }).trim();\n if (targetStatus) {\n throw new Error(`Cannot merge ${issue.identifier}: target repository has uncommitted changes.`);\n }\n\n // Collect changed files before merging (for the result summary)\n try {\n const diffOut = execSync(\n `git diff --name-status \"${issue.baseBranch}\"...\"${issue.branchName}\"`,\n { cwd: TARGET_ROOT, encoding: \"utf8\" },\n );\n for (const line of diffOut.trim().split(\"\\n\").filter(Boolean)) {\n const [statusChar, ...parts] = line.split(\"\\t\");\n const filePath = parts.join(\"\\t\");\n if (statusChar === \"D\") result.deleted.push(filePath);\n else result.copied.push(filePath);\n }\n } catch { /* best-effort */ }\n\n try {\n execSync(\n `git merge --no-ff \"${issue.branchName}\" -m \"fifony: merge ${issue.identifier}\"`,\n { cwd: TARGET_ROOT, stdio: \"pipe\" },\n );\n } catch (err: any) {\n // Merge failed — collect conflict files and abort\n try {\n const conflictOut = execSync(\n \"git diff --name-only --diff-filter=U\",\n { cwd: TARGET_ROOT, encoding: \"utf8\" },\n );\n result.conflicts.push(...conflictOut.trim().split(\"\\n\").filter(Boolean));\n } catch {}\n try { execSync(\"git merge --abort\", { cwd: TARGET_ROOT, stdio: \"pipe\" }); } catch {}\n logger.warn({ issueId: issue.id, err: String(err) }, \"[Agent] Git merge failed, aborted\");\n }\n\n return result;\n}\n\nexport function shouldSkipMergePath(relativePath: string): boolean {\n const parts = relativePath.split(\"/\");\n if (parts.some((s) => s === \".git\" || s === \"node_modules\" || s === \".fifony\" || s === \"dist\" || s === \".tanstack\")) {\n return true;\n }\n const base = parts.at(-1) ?? \"\";\n return base === \"WORKFLOW.local.md\"\n || base === \".fifony-env.sh\"\n || base === \".fifony-compiled-env.sh\"\n || base === \".fifony-local-source-ready\"\n || base.startsWith(\"fifony-\")\n || base.startsWith(\"fifony_\");\n}\n\n/** Push the issue worktree branch to origin and attempt to create a PR via gh CLI. */\nexport function pushWorktreeBranch(issue: IssueEntry): string {\n if (!issue.branchName || !issue.baseBranch || !issue.worktreePath) {\n throw new Error(`Issue ${issue.identifier} has no git worktree — cannot push.`);\n }\n\n ensureWorktreeCommitted(issue);\n execSync(`git push -u origin \"${issue.branchName}\"`, { cwd: TARGET_ROOT, stdio: \"pipe\" });\n\n // Try to create PR via gh CLI if available\n try {\n const prUrl = execSync(\n `gh pr create --head \"${issue.branchName}\" --base \"${issue.baseBranch}\" --title \"${issue.title.replace(/\"/g, '\\\\\"')}\" --body \"Automated by fifony\"`,\n { cwd: TARGET_ROOT, encoding: \"utf8\" },\n ).trim();\n return prUrl;\n } catch {\n // gh not available or PR already exists — return a best-effort compare URL\n try {\n const remote = execSync(\"git remote get-url origin\", { cwd: TARGET_ROOT, encoding: \"utf8\" }).trim();\n const cleanRemote = remote.replace(/\\.git$/, \"\");\n return `${cleanRemote}/compare/${issue.baseBranch}...${issue.branchName}`;\n } catch {\n return `(branch: ${issue.branchName})`;\n }\n }\n}\n\n/** Merge a worktree branch into TARGET_ROOT. */\nexport function mergeWorkspace(issue: IssueEntry): MergeResult {\n if (!issue.branchName || !issue.baseBranch || !issue.worktreePath) {\n throw new Error(`Issue ${issue.identifier} has no git worktree — cannot merge.`);\n }\n return mergeWorktree(issue, issue.worktreePath);\n}\n\nexport function hydrateIssuePathsFromWorkspace(issue: IssueEntry): string[] {\n const inferredPaths = inferChangedWorkspacePaths(issue.workspacePath ?? \"\", 32, issue);\n if (inferredPaths.length === 0) return [];\n issue.paths = [...new Set([...(issue.paths ?? []), ...inferredPaths])];\n issue.inferredPaths = [...new Set([...(issue.inferredPaths ?? []), ...inferredPaths])];\n return inferredPaths;\n}\n\nexport function describeRoutingSignals(issue: IssueEntry, workspaceDerivedPaths: string[]): string {\n const explicitPaths = issue.paths ?? [];\n const textDerivedPaths = inferCapabilityPaths({\n id: issue.id,\n identifier: issue.identifier,\n title: issue.title,\n description: issue.description,\n labels: issue.labels,\n }).filter((path) => !explicitPaths.includes(path));\n\n const parts: string[] = [];\n if (explicitPaths.length > 0) parts.push(`payload paths=${explicitPaths.join(\", \")}`);\n if (textDerivedPaths.length > 0) parts.push(`text hints=${textDerivedPaths.join(\", \")}`);\n if (workspaceDerivedPaths.length > 0) parts.push(`workspace diff=${workspaceDerivedPaths.join(\", \")}`);\n return parts.join(\" | \");\n}\n\n/** Write versioned review artifacts to workspace (also used for execute artifacts). */\nexport function writeVersionedArtifacts(\n workspacePath: string,\n prefix: string,\n planVersion: number,\n attempt: number,\n sources: Array<{ srcFile: string; destSuffix: string }>,\n): void {\n const { writeFileSync: _wfs, readFileSync: _rfs, existsSync: _es } = { writeFileSync, readFileSync, existsSync };\n for (const { srcFile, destSuffix } of sources) {\n const src = join(workspacePath, srcFile);\n if (_es(src)) {\n _wfs(join(workspacePath, `${prefix}.v${planVersion}a${attempt}.${destSuffix}`), _rfs(src, \"utf8\"), \"utf8\");\n }\n }\n}\n","import {\n appendFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { env } from \"node:process\";\nimport { spawn } from \"node:child_process\";\nimport type { IssueEntry, RuntimeConfig } from \"../types.ts\";\nimport { appendFileTail } from \"../concerns/helpers.ts\";\nimport { logger } from \"../concerns/logger.ts\";\nimport { normalizeAgentProvider } from \"./providers.ts\";\n\nexport async function runCommandWithTimeout(\n command: string,\n workspacePath: string,\n issue: IssueEntry,\n config: RuntimeConfig,\n promptText: string,\n promptFile: string,\n extraEnv: Record<string, string> = {},\n): Promise<{ success: boolean; code: number | null; output: string }> {\n return new Promise((resolve) => {\n const started = Date.now();\n const resultFile = extraEnv.FIFONY_RESULT_FILE;\n if (resultFile && extraEnv.FIFONY_PRESERVE_RESULT_FILE !== \"1\") {\n rmSync(resultFile, { force: true });\n }\n\n // Write all FIFONY_* vars to an env file and source it in the command.\n // This avoids E2BIG: child inherits process.env naturally (no ...env spread),\n // and our custom vars are loaded from a file instead of argv/env.\n const allVars: Record<string, string> = {\n FIFONY_ISSUE_ID: issue.id,\n FIFONY_ISSUE_IDENTIFIER: issue.identifier,\n FIFONY_ISSUE_TITLE: issue.title,\n FIFONY_ISSUE_PRIORITY: String(issue.priority),\n FIFONY_WORKSPACE_PATH: issue.worktreePath ?? workspacePath,\n FIFONY_PROMPT_FILE: promptFile,\n };\n for (const [key, value] of Object.entries(extraEnv)) {\n if (value.length > 4000) {\n const valFile = join(workspacePath, `${key.toLowerCase()}.txt`);\n writeFileSync(valFile, value, \"utf8\");\n allVars[`${key}_FILE`] = valFile;\n } else {\n allVars[key] = value;\n }\n }\n\n const envFilePath = join(workspacePath, \".env.sh\");\n const envFileLines = Object.entries(allVars)\n .map(([k, v]) => `export ${k}='${String(v).replace(/'/g, \"'\\\\''\")}'`)\n .join(\"\\n\");\n writeFileSync(envFilePath, envFileLines, \"utf8\");\n\n const wrappedCommand = `. \"${envFilePath}\" && ${command}`;\n const child = spawn(wrappedCommand, {\n shell: true,\n cwd: issue.worktreePath ?? workspacePath,\n detached: true, // Survive parent death\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n // Detach from parent so child survives SIGINT/restart\n child.unref();\n\n if (child.stdin) {\n child.stdin.end();\n }\n\n // Write PID file for recovery\n const pidFile = join(workspacePath, \"agent.pid\");\n const pid = child.pid;\n if (pid) {\n logger.debug({ issueId: issue.id, pid, command: command.slice(0, 120), cwd: workspacePath }, \"[Agent] Process spawned\");\n writeFileSync(pidFile, JSON.stringify({\n pid,\n issueId: issue.id,\n startedAt: new Date(started).toISOString(),\n command: command.slice(0, 200),\n }), \"utf8\");\n }\n\n let output = \"\";\n let timedOut = false;\n let outputBytes = 0;\n let outputHeader = \"\"; // First 2KB — always contains provider header (model name, etc.)\n const liveLogFile = join(workspacePath, \"live-output.log\");\n writeFileSync(liveLogFile, \"\", \"utf8\");\n\n const onChunk = (chunk: Buffer | string) => {\n const text = String(chunk);\n if (outputHeader.length < 2000) outputHeader = (outputHeader + text).slice(0, 2000);\n output = appendFileTail(output, text, config.logLinesTail);\n outputBytes += text.length;\n try { appendFileSync(liveLogFile, text); } catch {}\n issue.commandOutputTail = output;\n };\n\n child.stdout?.on(\"data\", onChunk);\n child.stderr?.on(\"data\", onChunk);\n\n const AGENT_STALE_OUTPUT_MS = 300_000; // 5 minutes without output growth → stuck\n\n const timer = setTimeout(() => {\n timedOut = true;\n // Kill the whole process group (detached child + its children)\n if (pid) { try { process.kill(-pid, \"SIGTERM\"); } catch {} }\n else { child.kill(\"SIGTERM\"); }\n }, config.commandTimeoutMs);\n\n // Progress watchdog: check PID alive + output growing every 30s\n let lastWatchdogBytes = 0;\n let lastOutputGrowthAt = Date.now();\n let watchdogKilled = false;\n const watchdog = setInterval(() => {\n // Check if PID is still alive\n if (pid) {\n try { process.kill(pid, 0); } catch {\n // PID died without triggering close — force resolve\n clearInterval(watchdog);\n clearTimeout(timer);\n watchdogKilled = true;\n try { rmSync(pidFile, { force: true }); } catch {}\n resolve({ success: false, code: null, output: appendFileTail(output, `\\nAgent process died unexpectedly (PID ${pid}).`, config.logLinesTail) });\n return;\n }\n }\n // Check if output is still growing\n if (outputBytes > lastWatchdogBytes) {\n lastWatchdogBytes = outputBytes;\n lastOutputGrowthAt = Date.now();\n } else if (Date.now() - lastOutputGrowthAt > AGENT_STALE_OUTPUT_MS) {\n clearInterval(watchdog);\n clearTimeout(timer);\n timedOut = true;\n watchdogKilled = true;\n if (pid) { try { process.kill(-pid, \"SIGTERM\"); } catch {} }\n else { child.kill(\"SIGTERM\"); }\n try { rmSync(pidFile, { force: true }); } catch {}\n resolve({ success: false, code: null, output: appendFileTail(output, `\\nAgent process stuck — no output for ${Math.round(AGENT_STALE_OUTPUT_MS / 60_000)} minutes.`, config.logLinesTail) });\n }\n }, 30_000);\n\n const cleanup = () => {\n clearInterval(watchdog);\n try { rmSync(pidFile, { force: true }); } catch {}\n };\n\n child.on(\"error\", () => {\n clearTimeout(timer);\n cleanup();\n if (watchdogKilled) return;\n resolve({ success: false, code: null, output: `Command execution failed for issue ${issue.id}.` });\n });\n\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n cleanup();\n if (watchdogKilled) return;\n // Prepend the captured header if it was truncated out of the tail — ensures model name is always extractable\n const buildOutput = (suffix: string) => {\n const tail = appendFileTail(output, suffix, config.logLinesTail);\n return outputHeader.length > 0 && !tail.startsWith(outputHeader.slice(0, 80))\n ? `${outputHeader}\\n${tail}`\n : tail;\n };\n if (timedOut) {\n resolve({ success: false, code: null, output: buildOutput(`\\nExecution timeout after ${config.commandTimeoutMs}ms.`) });\n return;\n }\n const duration = Math.max(0, Date.now() - started);\n if (code === 0) {\n resolve({ success: true, code, output: buildOutput(`\\nExecution succeeded in ${duration}ms.`) });\n return;\n }\n resolve({ success: false, code, output: buildOutput(`\\nCommand exit code ${code ?? \"unknown\"} after ${duration}ms.`) });\n });\n });\n}\n\nexport async function runHook(\n command: string,\n workspacePath: string,\n issue: IssueEntry,\n hookName: string,\n extraEnv: Record<string, string> = {},\n): Promise<void> {\n if (!command.trim()) return;\n\n const result = await runCommandWithTimeout(command, workspacePath, issue, {\n pollIntervalMs: 0,\n workerConcurrency: 1,\n maxConcurrentByState: {},\n commandTimeoutMs: 300_000,\n maxAttemptsDefault: 1,\n retryDelayMs: 0,\n staleInProgressTimeoutMs: 0,\n logLinesTail: 12_000,\n agentProvider: normalizeAgentProvider(env.FIFONY_AGENT_PROVIDER ?? \"codex\"),\n agentCommand: command,\n maxTurns: 1,\n runMode: \"filesystem\",\n }, \"\", \"\", { FIFONY_HOOK_NAME: hookName, ...extraEnv });\n\n if (!result.success) {\n throw new Error(`${hookName} hook failed: ${result.output}`);\n }\n}\n","import { execFileSync, spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type {\n AgentProviderDefinition,\n AgentProviderRole,\n DetectedProvider,\n EffortConfig,\n IssueEntry,\n JsonRecord,\n PipelineStageConfig,\n ReasoningEffort,\n RuntimeState,\n WorkflowConfig,\n} from \"../types.ts\";\nimport { TARGET_ROOT } from \"../concerns/constants.ts\";\nimport {\n toStringValue,\n toStringArray,\n toNumberValue,\n getNestedRecord,\n getNestedString,\n} from \"../concerns/helpers.ts\";\nimport { logger } from \"../concerns/logger.ts\";\nimport {\n resolveTaskCapabilities,\n mergeCapabilityProviders,\n type CapabilityResolverOptions,\n} from \"../routing/capability-resolver.ts\";\n\nexport function resolveAgentProfile(name: string): { profilePath: string; instructions: string } {\n const normalized = name.trim();\n if (!normalized) return { profilePath: \"\", instructions: \"\" };\n\n const candidates = [\n join(TARGET_ROOT, \".codex\", \"agents\", `${normalized}.md`),\n join(TARGET_ROOT, \".codex\", \"agents\", normalized, \"AGENT.md\"),\n join(TARGET_ROOT, \"agents\", `${normalized}.md`),\n join(TARGET_ROOT, \"agents\", normalized, \"AGENT.md\"),\n join(homedir(), \".codex\", \"agents\", `${normalized}.md`),\n join(homedir(), \".codex\", \"agents\", normalized, \"AGENT.md\"),\n join(homedir(), \".claude\", \"agents\", `${normalized}.md`),\n join(homedir(), \".claude\", \"agents\", normalized, \"AGENT.md\"),\n ];\n\n for (const candidate of candidates) {\n if (!existsSync(candidate)) continue;\n return {\n profilePath: candidate,\n instructions: readFileSync(candidate, \"utf8\").trim(),\n };\n }\n\n return { profilePath: \"\", instructions: \"\" };\n}\n\nexport function normalizeAgentProvider(value: string): string {\n const normalized = value.trim().toLowerCase();\n if (normalized === \"claude\" || normalized === \"codex\" || normalized === \"gemini\") return normalized;\n if (!normalized) return \"codex\";\n return normalized;\n}\n\nexport function normalizeAgentRole(value: string): AgentProviderRole {\n const normalized = value.trim().toLowerCase();\n if (normalized === \"planner\" || normalized === \"executor\" || normalized === \"reviewer\") {\n return normalized;\n }\n return \"executor\";\n}\n\nexport function resolveAgentCommand(\n provider: string,\n explicitCommand: string,\n codexCommand: string,\n claudeCommand: string,\n reasoningEffort?: string,\n): string {\n if (explicitCommand.trim()) return explicitCommand.trim();\n if (provider === \"claude\" && claudeCommand.trim()) return claudeCommand.trim();\n if (provider === \"codex\" && codexCommand.trim()) return codexCommand.trim();\n return getProviderDefaultCommand(provider, reasoningEffort);\n}\n\n/** Resolve the effective reasoning effort for a given role, considering issue override and global defaults. */\nexport function resolveEffort(\n role: string,\n issueEffort?: EffortConfig,\n globalEffort?: EffortConfig,\n): ReasoningEffort | undefined {\n // Issue-level per-role override takes highest priority\n const roleKey = role as keyof EffortConfig;\n if (issueEffort?.[roleKey]) return issueEffort[roleKey];\n // Issue-level default\n if (issueEffort?.default) return issueEffort.default;\n // Global per-role\n if (globalEffort?.[roleKey]) return globalEffort[roleKey];\n // Global default\n return globalEffort?.default;\n}\n\nimport { ADAPTERS } from \"./adapters/registry.ts\";\nimport { CLAUDE_RESULT_SCHEMA } from \"./adapters/commands.ts\";\n\nexport function getProviderDefaultCommand(provider: string, reasoningEffort?: string, model?: string): string {\n const adapter = ADAPTERS[provider];\n if (!adapter) return \"\";\n // Claude needs a JSON schema in its default command; pass effort for all providers\n const jsonSchema = provider === \"claude\" ? CLAUDE_RESULT_SCHEMA : undefined;\n return adapter.buildCommand({ model, effort: reasoningEffort, jsonSchema });\n}\n\nlet cachedProviders: DetectedProvider[] | null = null;\nlet providersCachedAt = 0;\nconst PROVIDER_CACHE_TTL = 60_000;\n\nexport function detectAvailableProviders(): DetectedProvider[] {\n if (cachedProviders && Date.now() - providersCachedAt < PROVIDER_CACHE_TTL) {\n return cachedProviders;\n }\n\n const providers: DetectedProvider[] = [];\n\n for (const name of [\"claude\", \"codex\", \"gemini\"]) {\n try {\n const path = execFileSync(\"which\", [name], { encoding: \"utf8\", timeout: 5000 }).trim();\n providers.push({ name, available: true, path });\n } catch {\n providers.push({ name, available: false, path: \"\" });\n }\n }\n\n cachedProviders = providers;\n providersCachedAt = Date.now();\n return providers;\n}\n\nexport function invalidateProviderCache(): void {\n cachedProviders = null;\n providersCachedAt = 0;\n}\n\n// ── Model discovery ─────────────────────────────────────────────────────────\n\nexport type DiscoveredModel = {\n id: string;\n provider: string;\n label: string;\n tier: string;\n};\n\n/** Cache: { models, fetchedAt } per provider */\nconst modelCache = new Map<string, { models: DiscoveredModel[]; fetchedAt: number }>();\nconst MODEL_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetch models from the OpenAI /v1/models API.\n * Filters to models relevant for Codex CLI usage (chat/reasoning models).\n */\n/**\n * Read Codex CLI's own model list from ~/.codex/models_cache.json.\n *\n * The Codex CLI fetches and caches its supported models locally.\n * This is the authoritative source — same data the /model picker uses.\n * We read it directly: zero hardcoding, always up-to-date with the CLI version.\n *\n * Falls back to OpenAI /v1/models API (filtered to gpt-5.*) if cache doesn't exist.\n */\n/**\n * Read the user's configured default model from ~/.codex/config.toml.\n * Returns the model string (e.g. \"gpt-5.4\") and reasoning effort if present.\n */\nexport function readCodexConfig(): { model?: string; reasoningEffort?: string } {\n try {\n const configPath = join(homedir(), \".codex\", \"config.toml\");\n if (!existsSync(configPath)) return {};\n const raw = readFileSync(configPath, \"utf8\");\n const model = raw.match(/^model\\s*=\\s*\"([^\"]+)\"/m)?.[1];\n const reasoningEffort = raw.match(/^model_reasoning_effort\\s*=\\s*\"([^\"]+)\"/m)?.[1];\n return { model, reasoningEffort };\n } catch {\n return {};\n }\n}\n\n/**\n * Read the user's configured default model from ~/.claude/settings.json.\n * Returns the model alias/ID (e.g. \"sonnet\", \"opus\").\n */\nfunction readClaudeConfig(): { model?: string } {\n try {\n const settingsPath = join(homedir(), \".claude\", \"settings.json\");\n if (!existsSync(settingsPath)) return {};\n const raw = readFileSync(settingsPath, \"utf8\");\n const settings = JSON.parse(raw) as { model?: string };\n return { model: typeof settings.model === \"string\" ? settings.model : undefined };\n } catch {\n return {};\n }\n}\n\n/**\n * Read the user's config from ~/.gemini/settings.json.\n * Returns the configured model (if any) and whether preview features are enabled.\n */\nexport function readGeminiConfig(): { model?: string; previewFeatures?: boolean } {\n try {\n const settingsPath = join(homedir(), \".gemini\", \"settings.json\");\n if (!existsSync(settingsPath)) return {};\n const raw = readFileSync(settingsPath, \"utf8\");\n const settings = JSON.parse(raw) as {\n model?: string;\n general?: { previewFeatures?: boolean };\n };\n return {\n model: typeof settings.model === \"string\" ? settings.model : undefined,\n previewFeatures: settings.general?.previewFeatures === true,\n };\n } catch {\n return {};\n }\n}\n\n/**\n * Find the models.js file from the installed @google/gemini-cli package.\n *\n * Strategy: resolve the `gemini` symlink → get real path of dist/index.js\n * → navigate to node_modules/@google/gemini-cli-core/dist/src/config/models.js\n * This is always in sync with whatever version of the CLI is installed.\n */\nfunction resolveGeminiModelsFile(): string | null {\n try {\n const binPath = execFileSync(\"which\", [\"gemini\"], { encoding: \"utf8\", timeout: 3000 }).trim();\n if (!binPath) return null;\n // Resolve the symlink: bin/gemini → .../node_modules/@google/gemini-cli/dist/index.js\n const realBin = realpathSync(binPath);\n // Go up: dist/index.js → dist → @google/gemini-cli\n const cliRoot = dirname(dirname(realBin));\n const modelsPath = join(cliRoot, \"node_modules\", \"@google\", \"gemini-cli-core\", \"dist\", \"src\", \"config\", \"models.js\");\n return existsSync(modelsPath) ? modelsPath : null;\n } catch {\n return null;\n }\n}\n\nasync function fetchGeminiModels(): Promise<DiscoveredModel[]> {\n const modelsPath = resolveGeminiModelsFile();\n if (!modelsPath) return [];\n\n try {\n const content = readFileSync(modelsPath, \"utf8\");\n\n // Parse `export const SOME_CONST = 'gemini-...'` lines\n const regex = /export const ([A-Z0-9_]+)\\s*=\\s*'(gemini-[^']+)';/g;\n const seen = new Set<string>();\n const stable: DiscoveredModel[] = [];\n const preview: DiscoveredModel[] = [];\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(content)) !== null) {\n const [, constName, modelId] = match;\n if (seen.has(modelId)) continue;\n if (modelId.includes(\"embedding\")) continue;\n seen.add(modelId);\n\n const isPreview = constName.startsWith(\"PREVIEW_\");\n const tier = isPreview ? \"Preview\" : \"Stable\";\n const model: DiscoveredModel = { id: modelId, provider: \"gemini\", label: modelId, tier };\n if (isPreview) preview.push(model);\n else stable.push(model);\n }\n\n // Stable models first, preview models after\n return [...stable, ...preview];\n } catch {\n return [];\n }\n}\n\nasync function fetchCodexModels(): Promise<DiscoveredModel[]> {\n // 1. Try ~/.codex/models_cache.json (authoritative — from the CLI itself)\n const cachePath = join(homedir(), \".codex\", \"models_cache.json\");\n try {\n if (existsSync(cachePath)) {\n const raw = readFileSync(cachePath, \"utf8\");\n const cache = JSON.parse(raw) as {\n models?: Array<{\n slug: string;\n display_name?: string;\n description?: string;\n visibility?: string;\n priority?: number;\n supported_reasoning_levels?: Array<{ effort: string; description?: string }>;\n }>;\n };\n\n if (Array.isArray(cache.models) && cache.models.length > 0) {\n return cache.models\n // Show \"list\" models first, then \"hide\" (legacy) — sorted by CLI priority\n .sort((a, b) => {\n const visA = a.visibility === \"list\" ? 0 : 1;\n const visB = b.visibility === \"list\" ? 0 : 1;\n if (visA !== visB) return visA - visB;\n return (a.priority ?? 99) - (b.priority ?? 99);\n })\n .map((m) => ({\n id: m.slug,\n provider: \"codex\",\n label: m.slug,\n tier: m.description || (m.visibility === \"list\" ? \"Supported\" : \"Legacy\"),\n }));\n }\n }\n } catch {\n // Cache unreadable\n }\n\n return [];\n}\n\n/**\n * Discover Claude models from the CLI.\n *\n * Strategy: use the stable aliases that the Claude CLI maintains itself\n * (opus → latest opus, sonnet → latest sonnet, haiku → latest haiku).\n *\n * Why aliases instead of version-pinned IDs extracted from the binary:\n * - Aliases always point to the current production model — no stale IDs\n * - No `strings` parsing, no binary inspection, no network calls\n * - When Anthropic releases a new version, the alias updates automatically\n *\n * The actual resolved model ID (e.g. claude-sonnet-4-6) is captured from\n * the `modelUsage` field in the CLI JSON response after each run.\n */\nasync function fetchAnthropicModels(): Promise<DiscoveredModel[]> {\n // Verify the CLI is reachable before returning anything\n try {\n execFileSync(\"which\", [\"claude\"], { encoding: \"utf8\", timeout: 3000 });\n } catch {\n return [];\n }\n\n // These aliases are maintained by Anthropic in the Claude CLI itself.\n // They always resolve to the current production model for each family.\n return [\n { id: \"opus\", provider: \"claude\", label: \"claude/opus (latest)\", tier: \"Most capable\" },\n { id: \"sonnet\", provider: \"claude\", label: \"claude/sonnet (latest)\", tier: \"Balanced\" },\n { id: \"haiku\", provider: \"claude\", label: \"claude/haiku (latest)\", tier: \"Fast\" },\n ];\n}\n\n\n/**\n * Discover available models for all detected providers.\n * Results are cached for 5 minutes.\n */\nexport async function discoverModels(providers: DetectedProvider[]): Promise<Record<string, DiscoveredModel[]>> {\n const result: Record<string, DiscoveredModel[]> = {};\n\n const tasks: Array<{ name: string; fetch: () => Promise<DiscoveredModel[]> }> = [];\n\n for (const p of providers) {\n if (!p.available) continue;\n const cached = modelCache.get(p.name);\n if (cached && Date.now() - cached.fetchedAt < MODEL_CACHE_TTL_MS) {\n result[p.name] = cached.models;\n continue;\n }\n if (p.name === \"codex\") tasks.push({ name: \"codex\", fetch: fetchCodexModels });\n if (p.name === \"claude\") tasks.push({ name: \"claude\", fetch: fetchAnthropicModels });\n if (p.name === \"gemini\") tasks.push({ name: \"gemini\", fetch: fetchGeminiModels });\n }\n\n const settled = await Promise.allSettled(tasks.map((t) => t.fetch()));\n for (let i = 0; i < tasks.length; i++) {\n const res = settled[i];\n let models = res.status === \"fulfilled\" ? res.value : [];\n\n // Promote the user's configured CLI default model to the top of the list\n if (tasks[i].name === \"codex\") {\n const { model: configuredModel } = readCodexConfig();\n if (configuredModel) {\n const idx = models.findIndex((m) => m.id === configuredModel);\n if (idx > 0) {\n // Move to front\n models = [models[idx], ...models.slice(0, idx), ...models.slice(idx + 1)];\n } else if (idx === -1) {\n // Not in list yet — add it\n models = [{ id: configuredModel, provider: \"codex\", label: configuredModel, tier: \"Configured default\" }, ...models];\n }\n }\n }\n\n if (tasks[i].name === \"claude\") {\n const { model: configuredModel } = readClaudeConfig();\n if (configuredModel) {\n // Claude config uses aliases (\"sonnet\", \"opus\") — find matching model by id/prefix\n const idx = models.findIndex((m) => m.id === configuredModel || m.id.includes(configuredModel));\n if (idx > 0) {\n models = [models[idx], ...models.slice(0, idx), ...models.slice(idx + 1)];\n }\n }\n }\n\n if (tasks[i].name === \"gemini\") {\n const { model: configuredModel, previewFeatures } = readGeminiConfig();\n if (configuredModel) {\n // Explicit model configured — promote it to top\n const idx = models.findIndex((m) => m.id === configuredModel);\n if (idx > 0) {\n models = [models[idx], ...models.slice(0, idx), ...models.slice(idx + 1)];\n } else if (idx === -1) {\n models = [{ id: configuredModel, provider: \"gemini\", label: configuredModel, tier: \"Configured default\" }, ...models];\n }\n } else if (previewFeatures) {\n // No explicit model, but preview features enabled → promote the first preview model to top\n const previewIdx = models.findIndex((m) => m.tier === \"Preview\");\n if (previewIdx > 0) {\n models = [models[previewIdx], ...models.slice(0, previewIdx), ...models.slice(previewIdx + 1)];\n }\n }\n }\n\n result[tasks[i].name] = models;\n modelCache.set(tasks[i].name, { models, fetchedAt: Date.now() });\n }\n\n return result;\n}\n\nexport function resolveDefaultProvider(detected: DetectedProvider[]): string {\n const available = detected.filter((p) => p.available);\n if (available.length === 0) return \"\";\n if (available.some((p) => p.name === \"codex\")) return \"codex\";\n return available[0].name;\n}\n\nexport function resolveWorkflowAgentProviders(\n config: JsonRecord,\n fallbackProvider: string,\n fallbackProfile: string,\n explicitCommand: string,\n): AgentProviderDefinition[] {\n const agentConfig = getNestedRecord(config, \"agent\");\n const codexConfig = getNestedRecord(config, \"codex\");\n const claudeConfig = getNestedRecord(config, \"claude\");\n const providersRaw = (agentConfig.providers ?? []) as unknown;\n const providers: AgentProviderDefinition[] = [];\n\n if (Array.isArray(providersRaw)) {\n for (const entry of providersRaw) {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) continue;\n const record = entry as JsonRecord;\n const provider = normalizeAgentProvider(\n toStringValue(record.provider) || toStringValue(record.name) || fallbackProvider,\n );\n const role = normalizeAgentRole(toStringValue(record.role, \"executor\"));\n const profile = toStringValue(record.profile, role === \"executor\" ? fallbackProfile : \"\");\n const resolvedProfile = resolveAgentProfile(profile);\n const command = resolveAgentCommand(\n provider,\n toStringValue(record.command),\n getNestedString(codexConfig, \"command\"),\n getNestedString(claudeConfig, \"command\"),\n );\n\n providers.push({\n provider,\n role,\n command,\n profile,\n profilePath: resolvedProfile.profilePath,\n profileInstructions: resolvedProfile.instructions,\n });\n }\n }\n\n if (providers.length > 0) return providers;\n\n const resolvedProfile = resolveAgentProfile(fallbackProfile);\n return [\n {\n provider: fallbackProvider,\n role: \"executor\",\n command: resolveAgentCommand(\n fallbackProvider,\n explicitCommand,\n getNestedString(codexConfig, \"command\"),\n getNestedString(claudeConfig, \"command\"),\n ),\n profile: fallbackProfile,\n profilePath: resolvedProfile.profilePath,\n profileInstructions: resolvedProfile.instructions,\n },\n ];\n}\n\nexport function getBaseAgentProviders(\n state: RuntimeState,\n): AgentProviderDefinition[] {\n return [\n {\n provider: state.config.agentProvider,\n role: \"executor\",\n command: state.config.agentCommand,\n profile: \"\",\n profilePath: \"\",\n profileInstructions: \"\",\n },\n ];\n}\n\nexport function getCapabilityRoutingOptions(): CapabilityResolverOptions {\n // Provider/model/effort overrides from user settings are applied via\n // applyWorkflowConfigToProviders after capability classification.\n return { enabled: true, overrides: [] };\n}\n\nexport function getCapabilityPriorityMap(): Record<string, number> {\n return {\n security: 0,\n bugfix: 1,\n backend: 2,\n devops: 3,\n \"frontend-ui\": 4,\n architecture: 5,\n documentation: 6,\n default: 7,\n \"workflow-disabled\": 8,\n };\n}\n\nexport function getIssueCapabilityPriority(\n issue: IssueEntry,\n _workflowDefinition: null,\n): number {\n const category = issue.capabilityCategory?.trim() || \"default\";\n const priorities = getCapabilityPriorityMap();\n return priorities[category] ?? 100;\n}\n\nexport function applyCapabilityMetadata(\n issue: IssueEntry,\n resolution: ReturnType<typeof resolveTaskCapabilities>,\n): void {\n issue.capabilityCategory = resolution.category;\n issue.capabilityOverlays = [...resolution.overlays];\n issue.capabilityRationale = [...resolution.rationale];\n\n const baseLabels = (issue.labels ?? []).filter((label) => !label.startsWith(\"capability:\") && !label.startsWith(\"overlay:\"));\n const derivedLabels = [\n resolution.category ? `capability:${resolution.category}` : \"\",\n ...resolution.overlays.map((overlay) => `overlay:${overlay}`),\n ].filter(Boolean);\n\n issue.labels = [...new Set([...baseLabels, ...derivedLabels])];\n}\n\n/** Map AgentProviderRole to WorkflowConfig stage key */\nfunction roleToStageKey(role: AgentProviderRole): keyof WorkflowConfig {\n switch (role) {\n case \"planner\": return \"plan\";\n case \"executor\": return \"execute\";\n case \"reviewer\": return \"review\";\n }\n}\n\n/**\n * Apply user's WorkflowConfig (from Settings → Workflow) to provider definitions.\n * Overrides provider, model, and effort for each role when a WorkflowConfig is present.\n */\nexport function applyWorkflowConfigToProviders(\n providers: AgentProviderDefinition[],\n workflowConfig: WorkflowConfig | null,\n): AgentProviderDefinition[] {\n if (!workflowConfig) return providers;\n\n return providers.map((provider) => {\n const stageKey = roleToStageKey(provider.role);\n const stageConfig: PipelineStageConfig | undefined = workflowConfig[stageKey];\n if (!stageConfig) return provider;\n\n const newProvider = stageConfig.provider || provider.provider;\n const newModel = stageConfig.model || undefined;\n const newEffort = stageConfig.effort || provider.reasoningEffort;\n\n // Rebuild command with the configured provider, model, and effort\n const command = getProviderDefaultCommand(newProvider, newEffort, newModel);\n\n return {\n ...provider,\n provider: newProvider,\n model: newModel,\n command: command || provider.command,\n reasoningEffort: newEffort,\n };\n });\n}\n\nexport function getEffectiveAgentProviders(\n state: RuntimeState,\n issue: IssueEntry,\n _workflowDefinition: null,\n workflowConfig?: WorkflowConfig | null,\n): AgentProviderDefinition[] {\n const baseProviders = getBaseAgentProviders(state);\n const resolution = resolveTaskCapabilities(\n {\n id: issue.id,\n identifier: issue.identifier,\n title: issue.title,\n description: issue.description,\n labels: issue.labels,\n paths: issue.paths,\n },\n getCapabilityRoutingOptions(),\n );\n applyCapabilityMetadata(issue, resolution);\n\n const merged = mergeCapabilityProviders(baseProviders, resolution).map((provider) => {\n const resolvedProfile = resolveAgentProfile(provider.profile ?? \"\");\n const suggestion = resolution.providers.find(\n (entry) => entry.provider === provider.provider && entry.role === provider.role,\n );\n\n const effort = resolveEffort(provider.role, issue.effort, state.config.defaultEffort);\n\n // Keep existing command (effort is metadata, not a CLI flag)\n const command = provider.command;\n\n return {\n ...provider,\n command,\n profilePath: resolvedProfile.profilePath,\n profileInstructions: resolvedProfile.instructions,\n selectionReason: suggestion?.reason ?? resolution.rationale.join(\" \"),\n overlays: resolution.overlays,\n capabilityCategory: resolution.category,\n reasoningEffort: effort,\n };\n });\n\n // Apply user's WorkflowConfig overrides (Settings → Workflow)\n return applyWorkflowConfigToProviders(merged, workflowConfig ?? null);\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { IssueEntry, AgentProviderDefinition, RuntimeConfig, IssuePlan } from \"../../types.ts\";\nimport type { CompiledExecution } from \"./types.ts\";\nimport type { ProviderAdapter, ProviderCommandOptions } from \"./registry.ts\";\nimport { renderPrompt } from \"../prompting.ts\";\nimport { buildFullPlanPrompt, resolveEffortForProvider, extractValidationCommands } from \"./shared.ts\";\nimport { CLAUDE_RESULT_SCHEMA, REVIEW_RESULT_SCHEMA, extractPlanDirs } from \"./commands.ts\";\n\n// ── Command builder ───────────────────────────────────────────────────────────\n\nexport function buildClaudeCommand(options: ProviderCommandOptions): string {\n const parts = [\"claude\", \"--print\"];\n\n if (!options.noToolAccess) {\n parts.push(\"--dangerously-skip-permissions\");\n }\n\n parts.push(\"--no-session-persistence\", \"--output-format json\");\n\n if (options.effort) {\n parts.push(`--effort ${options.effort}`);\n }\n\n if (options.jsonSchema) {\n parts.push(`--json-schema '${options.jsonSchema}'`);\n }\n\n if (options.addDirs?.length) {\n for (const dir of options.addDirs) {\n parts.push(`--add-dir \"${dir}\"`);\n }\n }\n\n if (options.model && options.model !== \"claude\") {\n parts.splice(1, 0, `--model ${options.model}`);\n }\n\n parts.push(\"< \\\"$FIFONY_PROMPT_FILE\\\"\");\n return parts.join(\" \");\n}\n\n// ── Adapter ───────────────────────────────────────────────────────────────────\n\nasync function compile(\n issue: IssueEntry,\n provider: AgentProviderDefinition,\n plan: IssuePlan,\n config: RuntimeConfig,\n workspacePath: string,\n skillContext: string,\n): Promise<CompiledExecution> {\n const effort = resolveEffortForProvider(plan, provider.role, config.defaultEffort);\n\n const prompt = await renderPrompt(\"compile-execution-claude\", {\n isPlanner: provider.role === \"planner\",\n isReviewer: provider.role === \"reviewer\",\n profileInstructions: provider.profileInstructions || \"\",\n skillContext,\n planPrompt: buildFullPlanPrompt(plan),\n subagentsToUse: plan.toolingDecision?.shouldUseSubagents ? (plan.toolingDecision.subagentsToUse ?? []) : [],\n skillsToUse: plan.toolingDecision?.shouldUseSkills ? (plan.toolingDecision.skillsToUse ?? []) : [],\n suggestedPaths: plan.suggestedPaths ?? [],\n workspacePath,\n issueIdentifier: issue.identifier,\n title: issue.title,\n description: issue.description || \"(none)\",\n validationItems: (plan.validation ?? []).map((value) => ({ value })),\n });\n\n const relativeDirs = extractPlanDirs(plan);\n const codePath = existsSync(join(workspacePath, \"worktree\")) ? join(workspacePath, \"worktree\") : workspacePath;\n const absoluteDirs = relativeDirs.map((d) => join(codePath, d));\n\n const command = buildClaudeCommand({\n model: provider.model,\n effort,\n addDirs: absoluteDirs,\n jsonSchema: CLAUDE_RESULT_SCHEMA,\n });\n\n const env: Record<string, string> = {\n FIFONY_PLAN_COMPLEXITY: plan.estimatedComplexity,\n FIFONY_PLAN_STEPS: String(plan.steps.length),\n FIFONY_EXECUTION_PAYLOAD_FILE: \"fifony-execution-payload.json\",\n };\n if (plan.suggestedPaths?.length) env.FIFONY_PLAN_PATHS = plan.suggestedPaths.join(\",\");\n if (plan.toolingDecision?.skillsToUse?.length) {\n env.FIFONY_PLAN_SKILLS = plan.toolingDecision.skillsToUse.map((s) => s.name).join(\",\");\n }\n\n const { pre, post } = extractValidationCommands(plan);\n\n return {\n prompt,\n command,\n env,\n preHooks: pre,\n postHooks: post,\n outputSchema: CLAUDE_RESULT_SCHEMA,\n payload: null,\n meta: {\n adapter: \"claude\",\n reasoningEffort: effort || \"default\",\n model: provider.model || \"default\",\n skillsActivated: plan.toolingDecision?.skillsToUse?.map((s) => s.name) || [],\n subagentsRequested: plan.toolingDecision?.subagentsToUse?.map((a) => a.name) || [],\n phasesCount: plan.phases?.length || 0,\n },\n };\n}\n\nexport const claudeAdapter: ProviderAdapter = {\n buildCommand: buildClaudeCommand,\n buildReviewCommand: (reviewer) => buildClaudeCommand({\n model: reviewer.model,\n effort: reviewer.reasoningEffort,\n jsonSchema: REVIEW_RESULT_SCHEMA,\n }),\n compile,\n};\n","import type { IssuePlan, IssuePlanStep, IssueEntry, AgentProviderDefinition, EffortConfig, AgentProviderRole } from \"../../types.ts\";\n\n/** Render plan context (summary, assumptions, constraints, unknowns) */\nexport function buildPlanContextSection(plan: IssuePlan): string {\n const parts: string[] = [\"## Plan Context\", \"\", `**Summary:** ${plan.summary}`];\n\n if (plan.assumptions?.length) {\n parts.push(\"\", \"**Assumptions:**\");\n plan.assumptions.forEach((a) => parts.push(`- ${a}`));\n }\n if (plan.constraints?.length) {\n parts.push(\"\", \"**Constraints:**\");\n plan.constraints.forEach((c) => parts.push(`- ${c}`));\n }\n if (plan.unknowns?.length) {\n parts.push(\"\", \"**Unknowns to investigate:**\");\n plan.unknowns.forEach((u) => {\n parts.push(`- **${u.question}**`);\n if (u.whyItMatters) parts.push(` Why it matters: ${u.whyItMatters}`);\n if (u.howToResolve) parts.push(` How to resolve: ${u.howToResolve}`);\n });\n }\n\n return parts.join(\"\\n\");\n}\n\n/** Render execution steps or phases */\nexport function buildStepsSection(plan: IssuePlan): string {\n const parts: string[] = [\"## Execution Steps\"];\n\n if (plan.phases?.length) {\n for (const phase of plan.phases) {\n parts.push(\"\", `### Phase: ${phase.phaseName}`, `Goal: ${phase.goal}`);\n if (phase.dependencies?.length) parts.push(`Dependencies: ${phase.dependencies.join(\", \")}`);\n for (const task of phase.tasks) {\n parts.push(`${task.step}. **${task.action}**${task.ownerType ? ` [${task.ownerType}]` : \"\"}`);\n if (task.details) parts.push(` ${task.details}`);\n if (task.doneWhen) parts.push(` Done when: ${task.doneWhen}`);\n if (task.files?.length) parts.push(` Files: ${task.files.join(\", \")}`);\n }\n if (phase.outputs?.length) parts.push(`Outputs: ${phase.outputs.join(\", \")}`);\n }\n } else {\n parts.push(\"\");\n for (const step of plan.steps) {\n parts.push(`${step.step}. **${step.action}**${step.ownerType ? ` [${step.ownerType}]` : \"\"}`);\n if (step.details) parts.push(` ${step.details}`);\n if (step.doneWhen) parts.push(` Done when: ${step.doneWhen}`);\n if (step.files?.length) parts.push(` Files: ${step.files.join(\", \")}`);\n }\n }\n\n parts.push(\"\", \"Follow this plan. Complete each step in order.\");\n return parts.join(\"\\n\");\n}\n\n/** Render risks section */\nexport function buildRiskSection(plan: IssuePlan): string {\n if (!plan.risks?.length) return \"\";\n const parts = [\"## Risks\"];\n for (const r of plan.risks) {\n parts.push(`- **${r.risk}** — Impact: ${r.impact}. Mitigation: ${r.mitigation}`);\n }\n return parts.join(\"\\n\");\n}\n\n/** Render validation requirements */\nexport function buildValidationSection(plan: IssuePlan): string {\n const parts: string[] = [];\n\n if (plan.successCriteria?.length) {\n parts.push(\"## Success Criteria\");\n plan.successCriteria.forEach((c) => parts.push(`- ${c}`));\n }\n if (plan.validation?.length) {\n parts.push(\"\", \"## Validation Checks\");\n parts.push(\"Run these before marking as done:\");\n plan.validation.forEach((v) => parts.push(`- ${v}`));\n }\n if (plan.deliverables?.length) {\n parts.push(\"\", \"## Deliverables\");\n plan.deliverables.forEach((d) => parts.push(`- ${d}`));\n }\n\n return parts.join(\"\\n\");\n}\n\n/** Render tooling/delegation decisions */\nexport function buildToolingSection(plan: IssuePlan): string {\n const td = plan.toolingDecision;\n if (!td) return \"\";\n\n const parts = [\"## Tooling & Delegation Strategy\"];\n\n if (td.decisionSummary) parts.push(\"\", td.decisionSummary);\n\n if (td.shouldUseSkills && td.skillsToUse?.length) {\n parts.push(\"\", \"**Skills to activate:**\");\n td.skillsToUse.forEach((s) => parts.push(`- **${s.name}**: ${s.why}`));\n }\n\n if (td.shouldUseSubagents && td.subagentsToUse?.length) {\n parts.push(\"\", \"**Subagents to use:**\");\n td.subagentsToUse.forEach((a) => parts.push(`- **${a.name}** (${a.role}): ${a.why}`));\n }\n\n return parts.join(\"\\n\");\n}\n\n/** Render execution strategy */\nexport function buildStrategySection(plan: IssuePlan): string {\n const es = plan.executionStrategy;\n if (!es) return \"\";\n\n const parts = [\n \"## Execution Strategy\",\n \"\",\n `**Approach:** ${es.approach}`,\n `**Rationale:** ${es.whyThisApproach}`,\n ];\n\n if (es.alternativesConsidered?.length) {\n parts.push(\"\", \"Alternatives considered:\");\n es.alternativesConsidered.forEach((a) => parts.push(`- ${a}`));\n }\n\n return parts.join(\"\\n\");\n}\n\n/** Resolve effort for a given role */\nexport function resolveEffortForProvider(\n plan: IssuePlan | undefined,\n role: AgentProviderRole,\n globalEffort?: EffortConfig,\n): string | undefined {\n const planEffort = plan?.suggestedEffort;\n const roleKey = role as keyof EffortConfig;\n return planEffort?.[roleKey] as string\n || planEffort?.default as string\n || globalEffort?.[roleKey] as string\n || globalEffort?.default as string\n || undefined;\n}\n\n/** Build the complete plan section for any provider */\nexport function buildFullPlanPrompt(plan: IssuePlan): string {\n return [\n buildPlanContextSection(plan),\n buildStrategySection(plan),\n buildToolingSection(plan),\n buildStepsSection(plan),\n buildRiskSection(plan),\n buildValidationSection(plan),\n ].filter(Boolean).join(\"\\n\\n\");\n}\n\n/** Extract validation commands from plan for hooks */\nexport function extractValidationCommands(plan: IssuePlan): { pre: string[]; post: string[] } {\n const pre: string[] = [];\n const post: string[] = [];\n\n for (const v of plan.validation || []) {\n const lower = v.toLowerCase();\n if (lower.includes(\"lint\")) post.push(\"pnpm lint --quiet 2>/dev/null || true\");\n if (lower.includes(\"typecheck\") || lower.includes(\"tsc\")) post.push(\"pnpm tsc --noEmit 2>/dev/null || true\");\n if (lower.includes(\"test\")) post.push(\"pnpm test 2>/dev/null || true\");\n }\n\n // Deduplicate\n return { pre: [...new Set(pre)], post: [...new Set(post)] };\n}\n\n// ── Execution Payload ─────────────────────────────────────────────────────────\n\n/**\n * Canonical structured input for CLI execution.\n * This is the single source of truth that the prompt references.\n * The prompt provides the markdown frame (instructions, role, strategy);\n * the payload carries the structured data (plan, constraints, criteria).\n */\nexport type ExecutionPayload = {\n /** Schema version for forward compat */\n version: 1;\n\n /** Issue identity */\n issue: {\n id: string;\n identifier: string;\n title: string;\n description: string;\n priority: number;\n labels: string[];\n paths: string[];\n };\n\n /** Provider context */\n provider: {\n name: string;\n role: AgentProviderRole;\n model: string;\n effort: string;\n capabilityCategory: string;\n overlays: string[];\n };\n\n /** Execution intent — what to do and how */\n executionIntent: {\n complexity: string;\n approach: string;\n rationale: string;\n workPattern: \"sequential\" | \"phased\" | \"parallel_subtasks\";\n };\n\n /** Structured plan data */\n plan: {\n summary: string;\n steps: Array<{\n step: number;\n action: string;\n files: string[];\n ownerType: string;\n doneWhen: string;\n }>;\n phases: Array<{\n name: string;\n goal: string;\n tasks: number[];\n dependencies: string[];\n outputs: string[];\n }>;\n };\n\n /** Constraints the agent must respect */\n constraints: string[];\n\n /** Success criteria — each must be met for \"done\" */\n successCriteria: string[];\n\n /** Validation commands to run before reporting done */\n validation: string[];\n\n /** Expected deliverables */\n deliverables: string[];\n\n /** Assumptions the plan is built on */\n assumptions: string[];\n\n /** Unknowns that may need resolution */\n unknowns: Array<{ question: string; whyItMatters: string; howToResolve: string }>;\n\n /** Risks with impact and mitigation */\n risks: Array<{ risk: string; impact: string; mitigation: string }>;\n\n /** Tooling decisions */\n tooling: {\n skills: Array<{ name: string; why: string }>;\n subagents: Array<{ name: string; role: string; why: string }>;\n };\n\n /** Target paths for focused changes */\n targetPaths: string[];\n\n /** Workspace location */\n workspacePath: string;\n\n /** Timestamp */\n createdAt: string;\n};\n\n/**\n * Build the canonical execution payload from issue + plan + provider context.\n */\nexport function buildExecutionPayload(\n issue: IssueEntry,\n provider: AgentProviderDefinition,\n plan: IssuePlan,\n workspacePath: string,\n): ExecutionPayload {\n const strategy = plan.executionStrategy;\n const hasPhases = Boolean(plan.phases?.length);\n\n return {\n version: 1,\n\n issue: {\n id: issue.id,\n identifier: issue.identifier,\n title: issue.title,\n description: issue.description || \"\",\n priority: issue.priority,\n labels: issue.labels || [],\n paths: issue.paths || [],\n },\n\n provider: {\n name: provider.provider,\n role: provider.role,\n model: provider.model || \"default\",\n effort: provider.reasoningEffort || \"medium\",\n capabilityCategory: provider.capabilityCategory || \"\",\n overlays: provider.overlays || [],\n },\n\n executionIntent: {\n complexity: plan.estimatedComplexity,\n approach: strategy?.approach || \"\",\n rationale: strategy?.whyThisApproach || \"\",\n workPattern: hasPhases\n ? \"phased\"\n : plan.toolingDecision?.shouldUseSubagents\n ? \"parallel_subtasks\"\n : \"sequential\",\n },\n\n plan: {\n summary: plan.summary,\n steps: plan.steps.map((s) => ({\n step: s.step,\n action: s.action,\n files: s.files || [],\n ownerType: s.ownerType || \"agent\",\n doneWhen: s.doneWhen || \"\",\n })),\n phases: (plan.phases || []).map((p) => ({\n name: p.phaseName,\n goal: p.goal,\n tasks: p.tasks.map((t) => t.step),\n dependencies: p.dependencies || [],\n outputs: p.outputs || [],\n })),\n },\n\n constraints: plan.constraints || [],\n successCriteria: plan.successCriteria || [],\n validation: plan.validation || [],\n deliverables: plan.deliverables || [],\n assumptions: plan.assumptions || [],\n unknowns: (plan.unknowns || []).map((u) => ({\n question: u.question,\n whyItMatters: u.whyItMatters || \"\",\n howToResolve: u.howToResolve || \"\",\n })),\n risks: (plan.risks || []).map((r) => ({\n risk: r.risk,\n impact: r.impact || \"\",\n mitigation: r.mitigation || \"\",\n })),\n\n tooling: {\n skills: plan.toolingDecision?.skillsToUse || [],\n subagents: plan.toolingDecision?.subagentsToUse || [],\n },\n\n targetPaths: plan.suggestedPaths || [],\n workspacePath,\n createdAt: new Date().toISOString(),\n };\n}\n","/**\n * Shared schemas and helpers used by all provider adapters.\n *\n * Provider-specific command builders live in their own adapter files:\n * adapters/claude.ts → buildClaudeCommand\n * adapters/codex.ts → buildCodexCommand\n * adapters/gemini.ts → buildGeminiCommand\n */\n\nimport type { IssuePlan } from \"../../types.ts\";\n\n// ── Result schemas ────────────────────────────────────────────────────────────\n\nexport const CLAUDE_RESULT_SCHEMA = JSON.stringify({\n type: \"object\",\n properties: {\n status: { type: \"string\", enum: [\"done\", \"continue\", \"blocked\", \"failed\"] },\n summary: { type: \"string\" },\n nextPrompt: { type: \"string\" },\n },\n required: [\"status\"],\n});\n\nexport const REVIEW_RESULT_SCHEMA = JSON.stringify({\n type: \"object\",\n properties: {\n status: { type: \"string\", enum: [\"done\", \"continue\", \"blocked\", \"failed\"] },\n summary: { type: \"string\" },\n nextPrompt: { type: \"string\" },\n criteriaResults: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: { criterion: { type: \"string\" }, met: { type: \"boolean\" }, note: { type: \"string\" } },\n },\n },\n },\n required: [\"status\"],\n});\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/** Extract unique directory paths from plan suggested paths (for --add-dir / --include-directories). */\nexport function extractPlanDirs(plan: IssuePlan): string[] {\n if (!plan.suggestedPaths?.length) return [];\n const dirs = new Set<string>();\n for (const p of plan.suggestedPaths) {\n const lastSlash = p.lastIndexOf(\"/\");\n if (lastSlash > 0) dirs.add(p.slice(0, lastSlash));\n else if (!p.includes(\".\")) dirs.add(p);\n }\n return [...dirs];\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { IssueEntry, AgentProviderDefinition, RuntimeConfig, IssuePlan } from \"../../types.ts\";\nimport type { CompiledExecution } from \"./types.ts\";\nimport type { ProviderAdapter, ProviderCommandOptions } from \"./registry.ts\";\nimport { renderPrompt } from \"../prompting.ts\";\nimport { buildFullPlanPrompt, resolveEffortForProvider, extractValidationCommands } from \"./shared.ts\";\nimport { REVIEW_RESULT_SCHEMA, extractPlanDirs } from \"./commands.ts\";\n\n// ── Result contract (embedded in prompt — no --json-schema flag in codex) ────\n\nconst CODEX_RESULT_CONTRACT = `\nReturn a JSON object with this exact schema when finished:\n{\n \"status\": \"done\" | \"continue\" | \"blocked\" | \"failed\",\n \"summary\": \"one paragraph summary of what was done\",\n \"root_cause\": [\"list of root causes found\"],\n \"changes_made\": [\"list of files/changes\"],\n \"validation\": { \"commands_run\": [\"...\"], \"result\": \"pass\" | \"partial\" | \"fail\" },\n \"open_questions\": [\"...\"],\n \"followups\": [\"...\"],\n \"nextPrompt\": \"guidance for next turn if status is continue\"\n}\n`.trim();\n\n// ── Command builder ───────────────────────────────────────────────────────────\n\nexport function buildCodexCommand(options: ProviderCommandOptions): string {\n const parts = [\"codex\", \"exec\", \"--dangerously-bypass-approvals-and-sandbox\"];\n\n if (options.model && options.model !== \"codex\") {\n parts.push(`--model ${options.model}`);\n }\n\n if (options.effort) {\n // Codex uses -c config overrides, not a dedicated --effort flag\n parts.push(`-c reasoning_effort=\"${options.effort}\"`);\n }\n\n if (options.addDirs?.length) {\n for (const dir of options.addDirs) {\n parts.push(`--add-dir \"${dir}\"`);\n }\n }\n\n if (options.imagePaths?.length) {\n for (const img of options.imagePaths) {\n parts.push(`--image \"${img}\"`);\n }\n }\n\n parts.push(\"< \\\"$FIFONY_PROMPT_FILE\\\"\");\n return parts.join(\" \");\n}\n\n// ── Adapter ───────────────────────────────────────────────────────────────────\n\nasync function compile(\n issue: IssueEntry,\n provider: AgentProviderDefinition,\n plan: IssuePlan,\n config: RuntimeConfig,\n workspacePath: string,\n skillContext: string,\n): Promise<CompiledExecution> {\n const effort = resolveEffortForProvider(plan, provider.role, config.defaultEffort) || provider.reasoningEffort;\n\n const prompt = await renderPrompt(\"compile-execution-codex\", {\n isPlanner: provider.role === \"planner\",\n isReviewer: provider.role === \"reviewer\",\n profileInstructions: provider.profileInstructions || \"\",\n skillContext,\n issueIdentifier: issue.identifier,\n title: issue.title,\n description: issue.description || \"(none)\",\n workspacePath,\n planPrompt: buildFullPlanPrompt(plan),\n phases: (plan.phases ?? []).map((phase) => ({\n phaseName: phase.phaseName,\n goal: phase.goal,\n outputs: phase.outputs ?? [],\n })),\n suggestedPaths: plan.suggestedPaths ?? [],\n skillsToUse: plan.toolingDecision?.shouldUseSkills ? (plan.toolingDecision.skillsToUse ?? []) : [],\n validationItems: (plan.validation ?? []).map((value) => ({ value })),\n outputContract: CODEX_RESULT_CONTRACT,\n });\n\n const relativeDirs = extractPlanDirs(plan);\n const codePath = existsSync(join(workspacePath, \"worktree\")) ? join(workspacePath, \"worktree\") : workspacePath;\n const absoluteDirs = relativeDirs.map((d) => join(codePath, d));\n\n const command = buildCodexCommand({\n model: provider.model,\n addDirs: absoluteDirs,\n effort,\n });\n\n const env: Record<string, string> = {\n FIFONY_PLAN_COMPLEXITY: plan.estimatedComplexity,\n FIFONY_PLAN_STEPS: String(plan.steps.length),\n FIFONY_PLAN_PHASES: String(plan.phases?.length || 0),\n FIFONY_EXECUTION_PAYLOAD_FILE: \"execution-payload.json\",\n };\n if (plan.suggestedPaths?.length) env.FIFONY_PLAN_PATHS = plan.suggestedPaths.join(\",\");\n\n const { pre, post } = extractValidationCommands(plan);\n\n return {\n prompt,\n command,\n env,\n preHooks: pre,\n postHooks: post,\n outputSchema: \"\",\n payload: null,\n meta: {\n adapter: \"codex\",\n reasoningEffort: effort || \"default\",\n model: provider.model || \"default\",\n skillsActivated: plan.toolingDecision?.skillsToUse?.map((s) => s.name) || [],\n subagentsRequested: [],\n phasesCount: plan.phases?.length || 0,\n },\n };\n}\n\nexport const codexAdapter: ProviderAdapter = {\n buildCommand: buildCodexCommand,\n buildReviewCommand: (reviewer) => buildCodexCommand({\n model: reviewer.model,\n effort: reviewer.reasoningEffort,\n }),\n compile,\n};\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { IssueEntry, AgentProviderDefinition, RuntimeConfig, IssuePlan } from \"../../types.ts\";\nimport type { CompiledExecution } from \"./types.ts\";\nimport type { ProviderAdapter, ProviderCommandOptions } from \"./registry.ts\";\nimport { renderPrompt } from \"../prompting.ts\";\nimport { buildFullPlanPrompt, resolveEffortForProvider, extractValidationCommands } from \"./shared.ts\";\nimport { REVIEW_RESULT_SCHEMA, extractPlanDirs } from \"./commands.ts\";\n\n// ── Result contract (embedded in prompt — Gemini CLI has no --json-schema flag) ─\n\nconst GEMINI_RESULT_CONTRACT = `\nReturn a JSON object with this exact schema when finished:\n{\n \"status\": \"done\" | \"continue\" | \"blocked\" | \"failed\",\n \"summary\": \"one paragraph summary of what was done\",\n \"root_cause\": [\"list of root causes found\"],\n \"changes_made\": [\"list of files/changes\"],\n \"validation\": { \"commands_run\": [\"...\"], \"result\": \"pass\" | \"partial\" | \"fail\" },\n \"open_questions\": [\"...\"],\n \"followups\": [\"...\"],\n \"nextPrompt\": \"guidance for next turn if status is continue\"\n}\n`.trim();\n\n// ── Command builder ───────────────────────────────────────────────────────────\n\nexport function buildGeminiCommand(options: ProviderCommandOptions): string {\n const parts = [\"gemini\", \"--yolo\"];\n\n if (options.model) {\n parts.push(`--model ${options.model}`);\n }\n\n if (options.addDirs?.length) {\n parts.push(`--include-directories ${options.addDirs.map((d) => `\"${d}\"`).join(\",\")}`);\n }\n\n // -p triggers non-interactive (headless) mode; stdin provides the prompt content\n parts.push(\"-p \\\"\\\" < \\\"$FIFONY_PROMPT_FILE\\\"\");\n return parts.join(\" \");\n}\n\n// ── Adapter ───────────────────────────────────────────────────────────────────\n\nasync function compile(\n issue: IssueEntry,\n provider: AgentProviderDefinition,\n plan: IssuePlan,\n config: RuntimeConfig,\n workspacePath: string,\n skillContext: string,\n): Promise<CompiledExecution> {\n const effort = resolveEffortForProvider(plan, provider.role, config.defaultEffort) || provider.reasoningEffort;\n\n const prompt = await renderPrompt(\"compile-execution-codex\", {\n isPlanner: provider.role === \"planner\",\n isReviewer: provider.role === \"reviewer\",\n profileInstructions: provider.profileInstructions || \"\",\n skillContext,\n issueIdentifier: issue.identifier,\n title: issue.title,\n description: issue.description || \"(none)\",\n workspacePath,\n planPrompt: buildFullPlanPrompt(plan),\n phases: (plan.phases ?? []).map((phase) => ({\n phaseName: phase.phaseName,\n goal: phase.goal,\n outputs: phase.outputs ?? [],\n })),\n suggestedPaths: plan.suggestedPaths ?? [],\n skillsToUse: plan.toolingDecision?.shouldUseSkills ? (plan.toolingDecision.skillsToUse ?? []) : [],\n validationItems: (plan.validation ?? []).map((value) => ({ value })),\n outputContract: GEMINI_RESULT_CONTRACT,\n });\n\n const relativeDirs = extractPlanDirs(plan);\n const codePath = existsSync(join(workspacePath, \"worktree\")) ? join(workspacePath, \"worktree\") : workspacePath;\n const absoluteDirs = relativeDirs.map((d) => join(codePath, d));\n\n const command = buildGeminiCommand({\n model: provider.model,\n addDirs: absoluteDirs,\n });\n\n const env: Record<string, string> = {\n FIFONY_PLAN_COMPLEXITY: plan.estimatedComplexity,\n FIFONY_PLAN_STEPS: String(plan.steps.length),\n FIFONY_PLAN_PHASES: String(plan.phases?.length || 0),\n FIFONY_EXECUTION_PAYLOAD_FILE: \"execution-payload.json\",\n };\n if (plan.suggestedPaths?.length) env.FIFONY_PLAN_PATHS = plan.suggestedPaths.join(\",\");\n\n const { pre, post } = extractValidationCommands(plan);\n\n return {\n prompt,\n command,\n env,\n preHooks: pre,\n postHooks: post,\n outputSchema: \"\",\n payload: null,\n meta: {\n adapter: \"gemini\",\n reasoningEffort: effort || \"default\",\n model: provider.model || \"default\",\n skillsActivated: plan.toolingDecision?.skillsToUse?.map((s) => s.name) || [],\n subagentsRequested: [],\n phasesCount: plan.phases?.length || 0,\n },\n };\n}\n\nexport const geminiAdapter: ProviderAdapter = {\n buildCommand: buildGeminiCommand,\n buildReviewCommand: (reviewer) => buildGeminiCommand({\n model: reviewer.model,\n }),\n compile,\n};\n","import type { IssueEntry, AgentProviderDefinition, RuntimeConfig, IssuePlan } from \"../../types.ts\";\nimport type { CompiledExecution } from \"./types.ts\";\n\n/** Normalized options passed to every provider's buildCommand. */\nexport type ProviderCommandOptions = {\n model?: string;\n effort?: string;\n addDirs?: string[];\n /** Images to attach (codex only) */\n imagePaths?: string[];\n /** JSON schema for structured output (claude only) */\n jsonSchema?: string;\n /** Disable tool access — for planning runs where tools break --json-schema (claude only) */\n noToolAccess?: boolean;\n};\n\nexport type ProviderAdapter = {\n /** Build the CLI command string for execution/planning */\n buildCommand(options: ProviderCommandOptions): string;\n /** Build the CLI command string for review */\n buildReviewCommand(reviewer: AgentProviderDefinition): string;\n /** Compile full execution payload for the provider */\n compile(\n issue: IssueEntry,\n provider: AgentProviderDefinition,\n plan: IssuePlan,\n config: RuntimeConfig,\n workspacePath: string,\n skillContext: string,\n ): Promise<CompiledExecution>;\n};\n\nimport { claudeAdapter } from \"./claude.ts\";\nimport { codexAdapter } from \"./codex.ts\";\nimport { geminiAdapter } from \"./gemini.ts\";\n\nexport const ADAPTERS: Record<string, ProviderAdapter> = {\n claude: claudeAdapter,\n codex: codexAdapter,\n gemini: geminiAdapter,\n};\n","import type {\n AgentProviderDefinition,\n IssueEntry,\n} from \"../types.ts\";\nimport { renderPrompt } from \"./prompting.ts\";\n\nexport async function buildPrompt(issue: IssueEntry, _workflowDefinition: null): Promise<string> {\n const rendered = await renderPrompt(\"workflow-default\", { issue, attempt: issue.attempts || 0 });\n\n if (!issue.plan?.steps?.length) {\n return rendered;\n }\n\n const planSection = await renderPrompt(\"workflow-plan-section\", {\n estimatedComplexity: issue.plan.estimatedComplexity,\n summary: issue.plan.summary,\n steps: issue.plan.steps.map((step) => ({\n step: step.step,\n action: step.action,\n files: step.files ?? [],\n details: step.details ?? \"\",\n })),\n });\n\n return `${rendered}\\n\\n${planSection}`;\n}\n\nexport async function buildTurnPrompt(\n issue: IssueEntry,\n basePrompt: string,\n previousOutput: string,\n turnIndex: number,\n maxTurns: number,\n nextPrompt: string,\n): Promise<string> {\n if (turnIndex === 1) return basePrompt;\n\n return renderPrompt(\"agent-turn\", {\n issueIdentifier: issue.identifier,\n turnIndex,\n maxTurns,\n basePrompt,\n continuation: nextPrompt.trim() || \"Continue the work, inspect the workspace, and move the issue toward completion.\",\n outputTail: previousOutput.trim() || \"No previous output captured.\",\n });\n}\n\nexport async function buildProviderBasePrompt(\n provider: AgentProviderDefinition,\n issue: IssueEntry,\n basePrompt: string,\n workspacePath: string,\n skillContext: string,\n): Promise<string> {\n return renderPrompt(\"agent-provider-base\", {\n isPlanner: provider.role === \"planner\",\n isReviewer: provider.role === \"reviewer\",\n hasImpeccableOverlay: provider.overlays?.includes(\"impeccable\") ?? false,\n hasFrontendDesignOverlay: provider.overlays?.includes(\"frontend-design\") ?? false,\n profileInstructions: provider.profileInstructions || \"\",\n skillContext,\n capabilityCategory: provider.capabilityCategory || \"\",\n selectionReason: provider.selectionReason ?? \"No additional routing reason.\",\n overlays: provider.overlays ?? [],\n targetPaths: issue.paths ?? [],\n workspacePath,\n basePrompt,\n });\n}\n","import type { IssueEntry, RuntimeMetrics } from \"../types.ts\";\n\nexport function computeMetrics(issues: IssueEntry[]): RuntimeMetrics {\n let planning = 0;\n let queued = 0;\n let inProgress = 0;\n let blocked = 0;\n let done = 0;\n let cancelled = 0;\n const completionTimes: number[] = [];\n\n for (const issue of issues) {\n const duration = issue.durationMs;\n if (issue.state === \"Done\") {\n const candidate = typeof duration === \"number\" && Number.isFinite(duration)\n ? duration\n : Number.isFinite(Date.parse(issue.startedAt ?? \"\")) && Number.isFinite(Date.parse(issue.completedAt ?? \"\"))\n ? Date.parse(issue.completedAt) - Date.parse(issue.startedAt)\n : NaN;\n if (Number.isFinite(candidate) && candidate >= 0) {\n completionTimes.push(candidate);\n }\n }\n\n switch (issue.state) {\n case \"Planning\":\n planning += 1;\n break;\n case \"Planned\":\n queued += 1;\n break;\n case \"Queued\":\n case \"Running\":\n case \"Reviewing\":\n case \"Reviewed\":\n inProgress += 1;\n break;\n case \"Blocked\":\n blocked += 1;\n break;\n case \"Done\":\n done += 1;\n break;\n case \"Cancelled\":\n cancelled += 1;\n break;\n }\n }\n\n if (completionTimes.length === 0) {\n return {\n total: issues.length,\n planning,\n queued,\n inProgress,\n blocked,\n done,\n cancelled,\n activeWorkers: 0,\n };\n }\n\n const sortedCompletionTimes = completionTimes.slice().sort((a, b) => a - b);\n const totalCompletionMs = sortedCompletionTimes.reduce((acc, value) => acc + value, 0);\n const mid = Math.floor(sortedCompletionTimes.length / 2);\n const medianCompletionMs = sortedCompletionTimes.length % 2 === 1\n ? sortedCompletionTimes[mid]\n : Math.round((sortedCompletionTimes[mid - 1] + sortedCompletionTimes[mid]) / 2);\n\n return {\n total: issues.length,\n planning,\n queued,\n inProgress,\n blocked,\n done,\n cancelled,\n activeWorkers: 0,\n avgCompletionMs: Math.round(totalCompletionMs / completionTimes.length),\n medianCompletionMs,\n fastestCompletionMs: sortedCompletionTimes[0]!,\n slowestCompletionMs: sortedCompletionTimes[sortedCompletionTimes.length - 1]!,\n };\n}\n\nexport function computeCapabilityCounts(issues: IssueEntry[]): Record<string, number> {\n return issues.reduce<Record<string, number>>((accumulator, issue) => {\n const key = issue.capabilityCategory?.trim() || \"default\";\n accumulator[key] = (accumulator[key] ?? 0) + 1;\n return accumulator;\n }, {});\n}\n","import type { IssueEntry, RuntimeMetrics } from \"../types.ts\";\nimport { computeMetrics } from \"../domains/metrics.ts\";\n\nlet cachedMetrics: RuntimeMetrics | null = null;\nlet metricsStale = true;\n\nexport function invalidateMetrics(): void {\n metricsStale = true;\n}\n\nexport function getMetrics(issues: IssueEntry[]): RuntimeMetrics {\n if (!metricsStale && cachedMetrics) return cachedMetrics;\n cachedMetrics = computeMetrics(issues);\n metricsStale = false;\n return cachedMetrics;\n}\n","/**\n * Dirty tracking for incremental persistence.\n * Tracks which issue and event IDs have been modified since last persist.\n */\n\nconst dirtyIssueIds = new Set<string>();\nconst dirtyIssuePlanIds = new Set<string>();\nconst dirtyEventIds = new Set<string>();\n\nexport function markIssueDirty(id: string): void {\n dirtyIssueIds.add(id);\n}\n\nexport function markIssuePlanDirty(id: string): void {\n dirtyIssuePlanIds.add(id);\n}\n\nexport function markEventDirty(id: string): void {\n dirtyEventIds.add(id);\n}\n\nexport function hasDirtyState(): boolean {\n return dirtyIssueIds.size > 0 || dirtyEventIds.size > 0;\n}\n\nexport function getDirtyIssueIds(): Set<string> {\n return dirtyIssueIds;\n}\n\nexport function getDirtyIssuePlanIds(): Set<string> {\n return dirtyIssuePlanIds;\n}\n\nexport function getDirtyEventIds(): Set<string> {\n return dirtyEventIds;\n}\n\nexport function clearDirtyIssueIds(): void {\n dirtyIssueIds.clear();\n}\n\nexport function clearDirtyIssuePlanIds(): void {\n dirtyIssuePlanIds.clear();\n}\n\nexport function clearDirtyEventIds(): void {\n dirtyEventIds.clear();\n}\n\nexport function markAllIssuesDirty(ids: string[]): void {\n for (const id of ids) dirtyIssueIds.add(id);\n}\n\nexport function markAllIssuePlansDirty(ids: string[]): void {\n for (const id of ids) dirtyIssuePlanIds.add(id);\n}\n\nexport function markAllEventsDirty(ids: string[]): void {\n for (const id of ids) dirtyEventIds.add(id);\n}\n","import type { IssueEntry, IssueState } from \"../../types.ts\";\nimport { S3DB_ISSUE_RESOURCE, TERMINAL_STATES } from \"../../concerns/constants.ts\";\nimport { computeDiffStats } from \"../../domains/workspace.ts\";\nimport { invalidateMetrics } from \"../metrics-cache.ts\";\nimport { markIssueDirty } from \"../dirty-tracker.ts\";\nimport { isoWeek } from \"../../concerns/helpers.ts\";\nimport { logger } from \"../../concerns/logger.ts\";\n\n// Lazy imports to avoid circular dependency (queue-workers → issue-runner → transition-issue → this)\nasync function lazyEnqueueForPlanning(issue: IssueEntry): Promise<void> {\n const { enqueueForPlanning } = await import(\"./queue-workers.ts\");\n return enqueueForPlanning(issue);\n}\n\nasync function lazyEnqueueForExecution(issue: IssueEntry): Promise<void> {\n const { enqueueForExecution } = await import(\"./queue-workers.ts\");\n return enqueueForExecution(issue);\n}\n\nasync function lazyEnqueueForReview(issue: IssueEntry): Promise<void> {\n const { enqueueForReview } = await import(\"./queue-workers.ts\");\n return enqueueForReview(issue);\n}\n\nexport const ISSUE_STATE_MACHINE_ID = \"issue-lifecycle\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\n/** Shape injected by StateMachinePlugin into action/guard callbacks. */\ntype Machine = {\n database: any;\n machineId: string;\n entityId: string;\n};\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction markDirtyAndInvalidate(issueId: string): void {\n markIssueDirty(issueId);\n invalidateMetrics();\n}\n\nfunction resolveIssue(context: Record<string, unknown>): IssueEntry | null {\n return (context.issue as IssueEntry) ?? null;\n}\n\nfunction issueResource(machine: Machine) {\n return machine.database?.resources?.[S3DB_ISSUE_RESOURCE];\n}\n\n// ── FSM config: states, transitions, guards, actions, triggers ──────────────\n\nexport const issueStateMachineConfig = {\n persistTransitions: true,\n workerId: `fifony-${process.pid}`,\n lockTimeout: 5_000,\n lockTTL: 30,\n\n stateMachines: {\n [ISSUE_STATE_MACHINE_ID]: {\n resource: S3DB_ISSUE_RESOURCE,\n stateField: \"state\",\n initialState: \"Planning\",\n autoCleanup: false,\n\n states: {\n Planning: {\n on: { PLANNED: \"Planned\", CANCEL: \"Cancelled\" },\n entry: \"onEnterPlanning\",\n },\n Planned: {\n on: { QUEUE: \"Queued\", REPLAN: \"Planning\", CANCEL: \"Cancelled\" },\n entry: \"onEnterPlanned\",\n },\n Queued: {\n on: { RUN: \"Running\" },\n entry: \"onEnterQueued\",\n },\n Running: {\n on: { REVIEW: \"Reviewing\", REQUEUE: \"Queued\", BLOCK: \"Blocked\" },\n guards: { BLOCK: \"requireBlockReason\" },\n triggers: [{\n type: \"cron\" as const,\n cron: \"*/10 * * * *\",\n sendEvent: \"BLOCK\",\n condition: async (context: Record<string, unknown>, _entityId: string) => {\n const issue = resolveIssue(context);\n if (!issue) return false;\n return Date.now() - Date.parse(issue.updatedAt) > 2_400_000;\n },\n }],\n },\n Reviewing: {\n on: { REVIEWED: \"Reviewed\", REQUEUE: \"Queued\", BLOCK: \"Blocked\" },\n entry: \"onEnterReviewing\",\n guards: { BLOCK: \"requireBlockReason\" },\n triggers: [{\n type: \"cron\" as const,\n cron: \"*/10 * * * *\",\n sendEvent: \"BLOCK\",\n condition: async (context: Record<string, unknown>, _entityId: string) => {\n const issue = resolveIssue(context);\n if (!issue) return false;\n return Date.now() - Date.parse(issue.updatedAt) > 2_400_000;\n },\n }],\n },\n Reviewed: {\n on: { DONE: \"Done\", REQUEUE: \"Queued\", REPLAN: \"Planning\", CANCEL: \"Cancelled\" },\n },\n Blocked: {\n on: { UNBLOCK: \"Queued\", REPLAN: \"Planning\", CANCEL: \"Cancelled\" },\n entry: \"onEnterBlocked\",\n },\n Done: {\n on: { REOPEN: \"Planning\" },\n type: \"final\" as const,\n entry: \"onEnterDone\",\n },\n Cancelled: {\n on: { REOPEN: \"Planning\" },\n type: \"final\" as const,\n entry: \"onEnterCancelled\",\n },\n },\n },\n },\n\n // ── Actions: (context, event, machine) ──────────────────────────────────\n // context = payload from send()\n // event = event name (\"PLANNED\", \"BLOCK\", etc.)\n // machine = { database, machineId, entityId }\n //\n // Actions only mutate the in-memory issue + fire side effects (enqueue, s3db patch).\n // Dirty tracking + metrics invalidation is done once in executeTransition() after send().\n\n actions: {\n onEnterPlanning: async (context: Record<string, unknown>, _event: string, _machine: Machine) => {\n const issue = resolveIssue(context);\n if (issue) {\n issue.planningStatus = \"idle\";\n issue.planningError = undefined;\n lazyEnqueueForPlanning(issue).catch(() => {});\n }\n },\n\n onEnterPlanned: async (context: Record<string, unknown>, _event: string, _machine: Machine) => {\n const issue = resolveIssue(context);\n if (issue) {\n logger.info({ issueId: issue.id, identifier: issue.identifier }, \"[FSM] onEnterPlanned — scheduling auto-queue\");\n setImmediate(async () => {\n try {\n const { executeTransition } = await import(\"./issue-state-machine.ts\");\n await executeTransition(issue, \"QUEUE\", { issue });\n logger.info({ issueId: issue.id }, \"[FSM] onEnterPlanned — QUEUE transition succeeded\");\n } catch (err) {\n logger.warn({ err, issueId: issue.id }, \"[FSM] Auto-transition Planned → Queued failed\");\n }\n });\n }\n },\n\n onEnterQueued: async (context: Record<string, unknown>, _event: string, _machine: Machine) => {\n const issue = resolveIssue(context);\n if (issue) {\n logger.info({ issueId: issue.id, identifier: issue.identifier }, \"[FSM] onEnterQueued — enqueuing for execution\");\n lazyEnqueueForExecution(issue).catch((err) => {\n logger.error({ err, issueId: issue.id }, \"[FSM] onEnterQueued — enqueue FAILED\");\n });\n }\n },\n\n onEnterReviewing: async (context: Record<string, unknown>, _event: string, machine: Machine) => {\n const issue = resolveIssue(context);\n const ts = new Date().toISOString();\n if (issue) {\n issue.reviewingAt = ts;\n lazyEnqueueForReview(issue).catch(() => {});\n }\n const res = issueResource(machine);\n if (res) {\n res.patch(machine.entityId, { reviewingAt: ts }).catch(() => {});\n }\n },\n\n onEnterBlocked: async (context: Record<string, unknown>, _event: string, _machine: Machine) => {\n const issue = resolveIssue(context);\n const note = typeof context.note === \"string\" ? context.note : \"Blocked\";\n if (issue) {\n issue.lastError = note;\n }\n },\n\n onEnterDone: async (context: Record<string, unknown>, _event: string, machine: Machine) => {\n const issue = resolveIssue(context);\n const ts = new Date().toISOString();\n const week = isoWeek();\n if (issue) {\n if (!issue.linesAdded && !issue.linesRemoved) computeDiffStats(issue);\n issue.completedAt = ts;\n issue.terminalWeek = week;\n issue.nextRetryAt = undefined;\n issue.lastError = undefined;\n }\n const res = issueResource(machine);\n if (res) {\n res.patch(machine.entityId, {\n completedAt: ts, terminalWeek: week, nextRetryAt: undefined, lastError: undefined,\n linesAdded: issue?.linesAdded, linesRemoved: issue?.linesRemoved, filesChanged: issue?.filesChanged,\n branchName: issue?.branchName, workspacePath: issue?.workspacePath, worktreePath: issue?.worktreePath,\n }).catch(() => {});\n }\n },\n\n onEnterCancelled: async (context: Record<string, unknown>, _event: string, machine: Machine) => {\n const issue = resolveIssue(context);\n const ts = new Date().toISOString();\n const week = isoWeek();\n if (issue) {\n issue.completedAt = ts;\n issue.terminalWeek = week;\n issue.nextRetryAt = undefined;\n }\n const res = issueResource(machine);\n if (res) {\n res.patch(machine.entityId, {\n completedAt: ts, terminalWeek: week, nextRetryAt: undefined,\n }).catch(() => {});\n }\n },\n },\n\n // ── Guards: (context, event, machine) ───────────────────────────────────\n\n guards: {\n requireBlockReason: async (context: Record<string, unknown>, _event: string, _machine: Machine) => {\n return typeof context.note === \"string\" && context.note.trim().length > 0;\n },\n },\n};\n\n// ── Event mapping: FSM event name → target state ────────────────────────────\n\nconst EVENT_TO_STATE: Record<string, IssueState> = {\n PLANNED: \"Planned\",\n QUEUE: \"Queued\",\n RUN: \"Running\",\n REVIEW: \"Reviewing\",\n REVIEWED: \"Reviewed\",\n DONE: \"Done\",\n CANCEL: \"Cancelled\",\n BLOCK: \"Blocked\",\n UNBLOCK: \"Queued\",\n REPLAN: \"Planning\",\n REQUEUE: \"Queued\",\n REOPEN: \"Planning\",\n};\n\nexport function eventToTargetState(event: string): IssueState | undefined {\n return EVENT_TO_STATE[event];\n}\n\n// ── State → valid events (for BFS path finding) ─────────────────────────────\n\nfunction getStatesFromConfig(): Record<string, Record<string, string>> {\n const machine = issueStateMachineConfig.stateMachines[ISSUE_STATE_MACHINE_ID];\n const result: Record<string, Record<string, string>> = {};\n for (const [state, def] of Object.entries(machine.states)) {\n result[state] = (def as { on?: Record<string, string> }).on ?? {};\n }\n return result;\n}\n\n/**\n * Returns the state machine transitions map: { state: [reachable target states] }\n * This is the single source of truth — the frontend should consume this.\n */\nexport function getStateMachineTransitions(): Record<string, string[]> {\n const edges = getStatesFromConfig();\n const result: Record<string, string[]> = {};\n for (const [state, events] of Object.entries(edges)) {\n const targets = [...new Set(Object.values(events))];\n result[state] = targets;\n }\n return result;\n}\n\n// ── BFS path finder (event sequence from→to) ────────────────────────────────\n\nexport function findIssueStateMachineTransitionPath(\n _machineDefinition: unknown,\n from: string,\n to: string,\n): string[] | null {\n if (from === to) return [];\n\n const edges = getStatesFromConfig();\n if (!edges[from] || !edges[to]) return null;\n\n const queue: string[] = [from];\n const previousState = new Map<string, string>();\n const previousEvent = new Map<string, string>();\n previousState.set(from, \"\");\n\n for (let i = 0; i < queue.length; i += 1) {\n const current = queue[i]!;\n const transitions = edges[current];\n if (!transitions) continue;\n\n for (const [evt, next] of Object.entries(transitions)) {\n if (previousState.has(next)) continue;\n\n previousState.set(next, current);\n previousEvent.set(next, evt);\n\n if (next === to) {\n const events: string[] = [];\n let cursor = next;\n while (cursor !== from) {\n const prev = previousState.get(cursor);\n const e = previousEvent.get(cursor);\n if (!prev || !e) return null;\n events.unshift(e);\n cursor = prev;\n }\n return events;\n }\n\n queue.push(next);\n }\n }\n\n return null;\n}\n\n// ── Resource-level state API accessor ───────────────────────────────────────\n// When the plugin is attached with `resource: S3DB_ISSUE_RESOURCE`, the resource\n// gains `resource.state.*` shortcuts:\n// resource.state.send(entityId, event, context)\n// resource.state.get(entityId)\n// resource.state.canTransition(entityId, event)\n// resource.state.history(entityId, options?)\n// resource.state.initialize(entityId, context?)\n// resource.state.getValidEvents(entityId)\n// resource.state.delete(entityId)\n\ntype ResourceStateApi = {\n send: (entityId: string, event: string, context?: Record<string, unknown>) => Promise<unknown>;\n get: (entityId: string) => Promise<string>;\n canTransition: (entityId: string, event: string) => Promise<boolean>;\n history: (entityId: string, options?: { limit?: number; offset?: number }) => Promise<unknown[]>;\n initialize: (entityId: string, context?: Record<string, unknown>) => Promise<unknown>;\n getValidEvents: (entityId: string) => Promise<string[]>;\n delete: (entityId: string) => Promise<void>;\n};\n\nlet issueResourceStateApi: ResourceStateApi | null = null;\n\nexport function setIssueResourceStateApi(api: ResourceStateApi | null): void {\n issueResourceStateApi = api;\n}\n\nexport function getIssueResourceStateApi(): ResourceStateApi | null {\n return issueResourceStateApi;\n}\n\n// ── Plugin-level accessor (fallback when resource.state is not available) ────\n\nexport type IssueStateMachinePluginLike = {\n getMachineDefinition?: (machineId: string) => unknown;\n getState?: (machineId: string, entityId: string) => Promise<string>;\n getValidEvents?: (machineId: string, stateOrEntityId: string) => Promise<string[]>;\n initializeEntity?: (machineId: string, entityId: string, context?: Record<string, unknown>) => Promise<unknown>;\n send?: (machineId: string, entityId: string, event: string, context?: Record<string, unknown>) => Promise<unknown>;\n getTransitionHistory?: (machineId: string, entityId: string, options?: { limit?: number; offset?: number }) => Promise<unknown[]>;\n visualize?: (machineId: string) => string;\n waitForPendingEvents?: (timeout?: number) => Promise<void>;\n};\n\nlet issueStateMachinePlugin: IssueStateMachinePluginLike | null = null;\n\nexport function setIssueStateMachinePlugin(plugin: IssueStateMachinePluginLike | null): void {\n issueStateMachinePlugin = plugin;\n}\n\nexport function getIssueStateMachinePlugin(): IssueStateMachinePluginLike | null {\n return issueStateMachinePlugin;\n}\n\nexport function getIssueStateMachineDefinition(): unknown {\n return issueStateMachinePlugin?.getMachineDefinition?.(ISSUE_STATE_MACHINE_ID)\n ?? issueStateMachineConfig.stateMachines[ISSUE_STATE_MACHINE_ID];\n}\n\nexport function getIssueStateMachineInitialState(): string {\n return issueStateMachineConfig.stateMachines[ISSUE_STATE_MACHINE_ID].initialState;\n}\n\n// ── Domain transition executor ──────────────────────────────────────────────\n// Primary path: resource.state.send(entityId, event, context)\n// Fallback: plugin.send(machineId, entityId, event, context)\n// Last resort: local validation + guard + action execution\n//\n// The plugin handles: lock → validate → guard → persist state/history → entry action\n// After send(), we apply universal in-memory effects (state, updatedAt, history, dirty).\n\nexport async function executeTransition(\n issue: IssueEntry,\n event: string,\n context: Record<string, unknown> = {},\n): Promise<{ previousState: IssueState }> {\n const ts = new Date().toISOString();\n const previous = issue.state;\n const targetState = eventToTargetState(event);\n\n if (!targetState) {\n throw new Error(`Unknown FSM event '${event}' for issue ${issue.id}.`);\n }\n\n const resourceApi = getIssueResourceStateApi();\n const plugin = getIssueStateMachinePlugin();\n const sendContext = { ...context, issue };\n\n if (resourceApi) {\n // ── Primary: resource.state.send(entityId, event, context)\n try {\n await resourceApi.send(issue.id, event, sendContext);\n } catch (err) {\n if (String(err).includes(\"not found\") || String(err).includes(\"not initialized\")) {\n await resourceApi.initialize(issue.id, { issue, state: previous });\n await resourceApi.send(issue.id, event, sendContext);\n } else {\n throw err;\n }\n }\n } else if (plugin?.send) {\n // ── Fallback: plugin.send(machineId, entityId, event, context)\n try {\n await plugin.send(ISSUE_STATE_MACHINE_ID, issue.id, event, sendContext);\n } catch (err) {\n if (plugin.initializeEntity && String(err).includes(\"not found\")) {\n await plugin.initializeEntity(ISSUE_STATE_MACHINE_ID, issue.id, { issue, state: previous });\n await plugin.send(ISSUE_STATE_MACHINE_ID, issue.id, event, sendContext);\n } else {\n throw err;\n }\n }\n } else {\n // ── Last resort: local validation + guard + action (no locking, no history)\n if (previous !== targetState) {\n const edges = getStatesFromConfig();\n const stateTransitions = edges[previous];\n if (!stateTransitions || !stateTransitions[event]) {\n throw new Error(`State machine does not allow event '${event}' from '${previous}' for issue ${issue.id}.`);\n }\n }\n\n const stateDef = issueStateMachineConfig.stateMachines[ISSUE_STATE_MACHINE_ID]\n .states[previous as keyof typeof issueStateMachineConfig.stateMachines[typeof ISSUE_STATE_MACHINE_ID][\"states\"]];\n if (stateDef && \"guards\" in stateDef && (stateDef as any).guards?.[event]) {\n const guardName = (stateDef as any).guards[event] as string;\n const guardFn = (issueStateMachineConfig.guards as Record<string, (ctx: any, evt: any, m: any) => Promise<boolean>>)[guardName];\n if (guardFn) {\n const allowed = await guardFn(sendContext, event, { database: null, machineId: ISSUE_STATE_MACHINE_ID, entityId: issue.id });\n if (!allowed) {\n throw new Error(`Guard '${guardName}' rejected event '${event}' for issue ${issue.id}.`);\n }\n }\n }\n\n const targetDef = issueStateMachineConfig.stateMachines[ISSUE_STATE_MACHINE_ID]\n .states[targetState as keyof typeof issueStateMachineConfig.stateMachines[typeof ISSUE_STATE_MACHINE_ID][\"states\"]];\n if (targetDef && \"entry\" in targetDef && typeof (targetDef as any).entry === \"string\") {\n const actionName = (targetDef as any).entry as string;\n const actionFn = (issueStateMachineConfig.actions as Record<string, (ctx: any, evt: any, m: any) => Promise<void>>)[actionName];\n if (actionFn) {\n await actionFn(sendContext, event, { database: null, machineId: ISSUE_STATE_MACHINE_ID, entityId: issue.id });\n }\n }\n }\n\n // ── Universal in-memory effects (applied once, regardless of path taken)\n issue.state = targetState;\n issue.updatedAt = ts;\n const note = typeof context.note === \"string\" ? context.note : `${event}: ${previous} → ${targetState}`;\n issue.history.push(`[${ts}] ${note}`);\n\n if (TERMINAL_STATES.has(previous) && !TERMINAL_STATES.has(targetState)) {\n issue.terminalWeek = \"\";\n }\n\n markDirtyAndInvalidate(issue.id);\n\n return { previousState: previous };\n}\n\n// ── Convenience: get transition history ─────────────────────────────────────\n\nexport async function getIssueTransitionHistory(\n issueId: string,\n options?: { limit?: number; offset?: number },\n): Promise<unknown[]> {\n const resourceApi = getIssueResourceStateApi();\n if (resourceApi?.history) {\n try { return await resourceApi.history(issueId, options); } catch { /* fall through */ }\n }\n const plugin = getIssueStateMachinePlugin();\n if (plugin?.getTransitionHistory) {\n try { return await plugin.getTransitionHistory(ISSUE_STATE_MACHINE_ID, issueId, options); } catch { /* */ }\n }\n return [];\n}\n\n// ── Convenience: check if transition is valid ───────────────────────────────\n\nexport async function canTransitionIssue(issueId: string, event: string): Promise<boolean> {\n const resourceApi = getIssueResourceStateApi();\n if (resourceApi?.canTransition) {\n try { return await resourceApi.canTransition(issueId, event); } catch { /* fall through */ }\n }\n return false;\n}\n\n// ── Convenience: visualize the machine as GraphViz DOT ──────────────────────\n\nexport function visualizeStateMachine(): string | null {\n const plugin = getIssueStateMachinePlugin();\n if (!plugin?.visualize) return null;\n return plugin.visualize(ISSUE_STATE_MACHINE_ID);\n}\n"],"mappings":"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","names":["existsSync","readFileSync","rmSync","writeFileSync","join","join","spawn","existsSync","join","env","existsSync","join","compile","existsSync","join","env","existsSync","join","compile","existsSync","join","env","join","existsSync","join","existsSync","resolve","join","spawn","existsSync","readFileSync","join","writeFileSync","rmSync","executeTransition"]}
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getReferenceRepositoriesRoot,
|
|
3
|
+
importReferenceArtifacts,
|
|
4
|
+
listReferenceRepositories,
|
|
5
|
+
syncReferenceRepositories
|
|
6
|
+
} from "./chunk-IXE2JEIU.js";
|
|
7
|
+
import "./chunk-CWC7H4H3.js";
|
|
8
|
+
import "./chunk-NA6PJPZD.js";
|
|
9
|
+
import "./chunk-DD5BE2W6.js";
|
|
10
|
+
import "./chunk-DVU3CXWA.js";
|
|
11
|
+
|
|
1
12
|
// src/cli.ts
|
|
2
13
|
import { spawn } from "child_process";
|
|
3
14
|
import { cwd, env, execPath, exit, kill, pid } from "process";
|
|
@@ -14,7 +25,7 @@ var require2 = createRequire(import.meta.url);
|
|
|
14
25
|
var packageJson = JSON.parse(readFileSync(resolve(packageRoot, "package.json"), "utf8"));
|
|
15
26
|
var distRuntime = resolve(packageRoot, "dist", "agent", "run-local.js");
|
|
16
27
|
var distMcp = resolve(packageRoot, "dist", "mcp", "server.js");
|
|
17
|
-
var srcRuntime = resolve(packageRoot, "src", "
|
|
28
|
+
var srcRuntime = resolve(packageRoot, "src", "boot.ts");
|
|
18
29
|
var srcMcp = resolve(packageRoot, "src", "mcp", "server.ts");
|
|
19
30
|
var forceSource = process.argv.includes("--dev") || env.NODE_ENV === "development";
|
|
20
31
|
var useCompiled = !forceSource && existsSync(distRuntime);
|
|
@@ -73,6 +84,127 @@ function getNumberOption(result, key) {
|
|
|
73
84
|
function getBooleanOption(result, key) {
|
|
74
85
|
return result.options[key] === true;
|
|
75
86
|
}
|
|
87
|
+
function parseReferenceKind(value) {
|
|
88
|
+
const normalized = typeof value === "string" ? value.trim().toLowerCase() : "all";
|
|
89
|
+
if (normalized === "all") return "all";
|
|
90
|
+
if (normalized === "agents" || normalized === "agent") return "agents";
|
|
91
|
+
if (normalized === "skills" || normalized === "skill") return "skills";
|
|
92
|
+
throw new Error(`Invalid kind: ${normalized}. Expected all, agents, or skills.`);
|
|
93
|
+
}
|
|
94
|
+
function getWorkspaceRoot(result) {
|
|
95
|
+
const workspace = getStringOption(result, "workspace");
|
|
96
|
+
return resolve(workspace ?? env.FIFONY_WORKSPACE_ROOT ?? cwd());
|
|
97
|
+
}
|
|
98
|
+
async function runOnboardingList() {
|
|
99
|
+
const root = getReferenceRepositoriesRoot();
|
|
100
|
+
const repositories = listReferenceRepositories();
|
|
101
|
+
console.log("Reference repositories:");
|
|
102
|
+
console.log(`Storage: ${root}`);
|
|
103
|
+
console.log("");
|
|
104
|
+
for (const repository of repositories) {
|
|
105
|
+
const status = repository.synced ? repository.branch ? `synced (${repository.branch})` : "synced" : repository.present ? `present \u2014 ${repository.error ?? "not synced"}` : "not found";
|
|
106
|
+
console.log(`- ${repository.id}`);
|
|
107
|
+
console.log(` name: ${repository.name}`);
|
|
108
|
+
console.log(` url: ${repository.url}`);
|
|
109
|
+
console.log(` path: ${repository.path}`);
|
|
110
|
+
console.log(` status: ${status}`);
|
|
111
|
+
if (repository.remote) {
|
|
112
|
+
console.log(` remote: ${repository.remote}`);
|
|
113
|
+
}
|
|
114
|
+
console.log("");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function runOnboardingSync(result) {
|
|
118
|
+
const repositoryFilter = getStringOption(result, "repository");
|
|
119
|
+
let syncTarget;
|
|
120
|
+
try {
|
|
121
|
+
syncTarget = repositoryFilter ? syncReferenceRepositories(repositoryFilter) : syncReferenceRepositories();
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
124
|
+
exit(1);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const succeeded = [];
|
|
128
|
+
const failed = [];
|
|
129
|
+
for (const item of syncTarget) {
|
|
130
|
+
if (item.action === "failed") {
|
|
131
|
+
failed.push(item);
|
|
132
|
+
} else {
|
|
133
|
+
succeeded.push(item);
|
|
134
|
+
}
|
|
135
|
+
if (item.action === "failed") {
|
|
136
|
+
console.log(`\u2717 ${item.id}: ${item.message}`);
|
|
137
|
+
} else if (item.action === "cloned") {
|
|
138
|
+
console.log(`+ ${item.id}: ${item.message}`);
|
|
139
|
+
} else {
|
|
140
|
+
console.log(`\u21BB ${item.id}: ${item.message}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (failed.length > 0) {
|
|
144
|
+
console.log("");
|
|
145
|
+
console.log(`${succeeded.length} repository(ies) synced, ${failed.length} failed.`);
|
|
146
|
+
console.log("Run onboarding sync with a direct repository to retry failed items.");
|
|
147
|
+
exit(1);
|
|
148
|
+
}
|
|
149
|
+
console.log("");
|
|
150
|
+
console.log(`Done: ${succeeded.length} repository(ies) synced.`);
|
|
151
|
+
}
|
|
152
|
+
async function runOnboardingImport(result) {
|
|
153
|
+
const repository = typeof result.positional?.repository === "string" ? result.positional.repository : "";
|
|
154
|
+
let kind;
|
|
155
|
+
try {
|
|
156
|
+
kind = parseReferenceKind(result.options.kind);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
159
|
+
exit(1);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const overwrite = getBooleanOption(result, "overwrite");
|
|
163
|
+
const dryRun = getBooleanOption(result, "dryRun");
|
|
164
|
+
const importToGlobal = getBooleanOption(result, "global");
|
|
165
|
+
const workspaceRoot = getWorkspaceRoot(result);
|
|
166
|
+
if (!repository) {
|
|
167
|
+
console.error("Repository argument is required.");
|
|
168
|
+
exit(1);
|
|
169
|
+
}
|
|
170
|
+
let summary;
|
|
171
|
+
try {
|
|
172
|
+
summary = importReferenceArtifacts(repository, workspaceRoot, {
|
|
173
|
+
kind,
|
|
174
|
+
overwrite,
|
|
175
|
+
dryRun,
|
|
176
|
+
importToGlobal
|
|
177
|
+
});
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
180
|
+
exit(1);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const targetLabel = importToGlobal ? "global ~/.codex" : `${workspaceRoot}/.codex`;
|
|
184
|
+
if (dryRun) {
|
|
185
|
+
console.log(`Dry run active. No files were written.`);
|
|
186
|
+
}
|
|
187
|
+
console.log(`Reference repository: ${summary.repositoryId}`);
|
|
188
|
+
console.log(`Source: ${summary.localPath}`);
|
|
189
|
+
console.log(`Target: ${targetLabel}`);
|
|
190
|
+
console.log(`Kind: ${summary.requestedKind}`);
|
|
191
|
+
console.log(`Imported agents: ${summary.importedAgents.length}`);
|
|
192
|
+
console.log(`Imported skills: ${summary.importedSkills.length}`);
|
|
193
|
+
console.log(`Skipped agents: ${summary.skippedAgents.length}`);
|
|
194
|
+
console.log(`Skipped skills: ${summary.skippedSkills.length}`);
|
|
195
|
+
if (summary.errors.length > 0) {
|
|
196
|
+
console.log("");
|
|
197
|
+
console.log("Errors:");
|
|
198
|
+
for (const item of summary.errors) {
|
|
199
|
+
console.log(`- ${item.kind}/${item.targetName}: ${item.error}`);
|
|
200
|
+
}
|
|
201
|
+
exit(1);
|
|
202
|
+
}
|
|
203
|
+
if (summary.importedAgents.length + summary.importedSkills.length === 0) {
|
|
204
|
+
console.log("Nothing to import. Run onboarding sync first if the repository was not downloaded.");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
76
208
|
function buildRuntimeArgs(result) {
|
|
77
209
|
const runtimeArgs = [];
|
|
78
210
|
const workspace = getStringOption(result, "workspace");
|
|
@@ -182,6 +314,60 @@ var cli = createCLI({
|
|
|
182
314
|
description: "Run a Fifony MCP server over stdio with resources, tools, and prompts backed by the local durable store.",
|
|
183
315
|
options: commonOptions,
|
|
184
316
|
handler: (result) => runMcpServer(result)
|
|
317
|
+
},
|
|
318
|
+
onboarding: {
|
|
319
|
+
description: "Manage reference repositories and import agents/skills from them.",
|
|
320
|
+
aliases: ["onboard"],
|
|
321
|
+
commands: {
|
|
322
|
+
list: {
|
|
323
|
+
description: "List reference repositories and local sync status.",
|
|
324
|
+
handler: () => runOnboardingList()
|
|
325
|
+
},
|
|
326
|
+
sync: {
|
|
327
|
+
description: "Clone/update reference repositories into ~/.fifony/repositories.",
|
|
328
|
+
options: {
|
|
329
|
+
repository: {
|
|
330
|
+
short: "r",
|
|
331
|
+
type: "string",
|
|
332
|
+
description: "Sync only this repository by id or URL."
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
handler: (result) => runOnboardingSync(result)
|
|
336
|
+
},
|
|
337
|
+
import: {
|
|
338
|
+
description: "Import agents/skills from a synced reference repository.",
|
|
339
|
+
aliases: ["integrate"],
|
|
340
|
+
positional: [
|
|
341
|
+
{
|
|
342
|
+
name: "repository",
|
|
343
|
+
type: "string",
|
|
344
|
+
required: true,
|
|
345
|
+
description: "Repository id or URL"
|
|
346
|
+
}
|
|
347
|
+
],
|
|
348
|
+
options: {
|
|
349
|
+
kind: {
|
|
350
|
+
short: "k",
|
|
351
|
+
type: "string",
|
|
352
|
+
default: "all",
|
|
353
|
+
description: "What to import: agents, skills, or all (default: all)."
|
|
354
|
+
},
|
|
355
|
+
overwrite: {
|
|
356
|
+
type: "boolean",
|
|
357
|
+
description: "Overwrite existing local files."
|
|
358
|
+
},
|
|
359
|
+
dryRun: {
|
|
360
|
+
type: "boolean",
|
|
361
|
+
description: "Show what would be imported without writing files."
|
|
362
|
+
},
|
|
363
|
+
global: {
|
|
364
|
+
type: "boolean",
|
|
365
|
+
description: "Import into ~/.codex instead of workspace .codex."
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
handler: (result) => runOnboardingImport(result)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
185
371
|
}
|
|
186
372
|
}
|
|
187
373
|
});
|