@dendelion/paper-camp 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -7
- package/dist/app/assets/main-6nYButky.js +232 -0
- package/dist/app/assets/main-6nYButky.js.map +1 -0
- package/dist/app/assets/main-DUnpdvQF.css +1 -0
- package/dist/app/index.html +2 -2
- package/dist/chunks/serializer.B8u-L8BI.js +5249 -0
- package/dist/chunks/serializer.B8u-L8BI.js.map +1 -0
- package/dist/cli/index.js +2150 -932
- package/dist/cli/index.js.map +1 -1
- package/dist/core/frontmatter-schemas.d.ts +11 -0
- package/dist/core/frontmatter-schemas.d.ts.map +1 -0
- package/dist/core/frontmatter.test.d.ts +2 -0
- package/dist/core/frontmatter.test.d.ts.map +1 -0
- package/dist/core/idea-status.d.ts +7 -0
- package/dist/core/idea-status.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +48 -29
- package/dist/core/parser.d.ts +24 -3
- package/dist/core/parser.d.ts.map +1 -1
- package/dist/core/readers.d.ts +27 -0
- package/dist/core/readers.d.ts.map +1 -0
- package/dist/core/readers.test.d.ts +2 -0
- package/dist/core/readers.test.d.ts.map +1 -0
- package/dist/core/scaffold.d.ts +4 -2
- package/dist/core/scaffold.d.ts.map +1 -1
- package/dist/core/schemas.d.ts +75 -12
- package/dist/core/schemas.d.ts.map +1 -1
- package/dist/core/serializer.d.ts +52 -2
- package/dist/core/serializer.d.ts.map +1 -1
- package/dist/types/index.d.ts +24 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +32 -10
- package/dist/types/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/app/assets/main-B61tEYvn.css +0 -1
- package/dist/app/assets/main-tAEncq68.js +0 -272
- package/dist/app/assets/main-tAEncq68.js.map +0 -1
- package/dist/chunks/serializer.D1Ts_p8h.js +0 -462
- package/dist/chunks/serializer.D1Ts_p8h.js.map +0 -1
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/app/server/activity.ts","../../src/app/server/agents/claude-code.ts","../../src/app/server/agents/opencode.ts","../../src/app/server/agents/index.ts","../../src/app/server/agent.ts","../../src/app/server/git.ts","../../src/app/server/status.ts","../../src/app/server/api.ts","../../src/cli/dev-server.ts","../../src/cli/index.ts"],"sourcesContent":["import { watch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport { parseDecisions, parseOpenQuestions, parsePlans, parseProgress } from '../../core/parser';\nimport type { DecisionEntry, OpenQuestionEntry, PlanEntry, ProgressEntry } from '../../types';\n\nexport interface ActivityEvent {\n message: string;\n timestamp: string;\n}\n\ninterface Snapshot {\n plans: PlanEntry[];\n decisions: DecisionEntry[];\n openQuestions: OpenQuestionEntry[];\n progress: ProgressEntry[];\n}\n\nconst campFile = (root: string, name: string) => join(root, 'papercamp', name);\n\nconst readMaybe = (path: string): Promise<string> => readFile(path, 'utf-8').catch(() => '');\n\nasync function takeSnapshot(root: string): Promise<Snapshot> {\n const [plansRaw, decisionsRaw, questionsRaw, progressRaw] = await Promise.all([\n readMaybe(campFile(root, 'plans.md')),\n readMaybe(campFile(root, 'decisions.md')),\n readMaybe(campFile(root, 'open-questions.md')),\n readMaybe(campFile(root, 'progress.md')),\n ]);\n return {\n plans: parsePlans(plansRaw).entries,\n decisions: parseDecisions(decisionsRaw).entries,\n openQuestions: parseOpenQuestions(questionsRaw).entries,\n progress: parseProgress(progressRaw),\n };\n}\n\nfunction diffAndSynthesize(before: Snapshot, after: Snapshot): ActivityEvent[] {\n const events: ActivityEvent[] = [];\n const ts = new Date().toISOString();\n\n const beforePlans = new Map(before.plans.map((p) => [p.title, p]));\n const afterPlans = new Map(after.plans.map((p) => [p.title, p]));\n\n for (const [title, afterP] of afterPlans) {\n const beforeP = beforePlans.get(title);\n if (!beforeP) {\n events.push({ message: `New plan added: ${title}`, timestamp: ts });\n } else if (beforeP.status !== afterP.status) {\n events.push({ message: `Plan \"${title}\" marked ${afterP.status}`, timestamp: ts });\n } else {\n for (let i = 0; i < afterP.phases.length; i++) {\n const beforePhase = beforeP.phases[i];\n const afterPhase = afterP.phases[i];\n if (beforePhase && beforePhase.done !== afterPhase.done) {\n events.push({\n message: afterPhase.done\n ? `Phase ${i + 1}/${afterP.phases.length} checked off in \"${title}\"`\n : `Phase ${i + 1}/${afterP.phases.length} unchecked in \"${title}\"`,\n timestamp: ts,\n });\n }\n }\n }\n }\n\n for (const [title] of beforePlans) {\n if (!afterPlans.has(title)) {\n events.push({ message: `Plan removed: ${title}`, timestamp: ts });\n }\n }\n\n const beforeDecisions = new Map(before.decisions.map((d) => [d.title, d]));\n const afterDecisions = new Map(after.decisions.map((d) => [d.title, d]));\n for (const [title] of afterDecisions) {\n if (!beforeDecisions.has(title)) {\n events.push({ message: `New decision: ${title}`, timestamp: ts });\n }\n }\n\n const beforeQuestions = new Map(before.openQuestions.map((q) => [q.title, q]));\n const afterQuestions = new Map(after.openQuestions.map((q) => [q.title, q]));\n for (const [title] of afterQuestions) {\n if (!beforeQuestions.has(title)) {\n events.push({ message: `New open question: ${title}`, timestamp: ts });\n }\n }\n\n const beforeProgress = new Map(before.progress.map((p) => [p.date, p]));\n const afterProgress = new Map(after.progress.map((p) => [p.date, p]));\n for (const [date] of afterProgress) {\n if (!beforeProgress.has(date)) {\n events.push({ message: `Progress logged: ${date}`, timestamp: ts });\n }\n }\n\n return events;\n}\n\nexport function createActivityManager(root: string) {\n const clients = new Set<ServerResponse>();\n let snapshot: Snapshot | null = null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const files = ['plans.md', 'decisions.md', 'open-questions.md', 'progress.md'];\n\n async function check() {\n try {\n const next = await takeSnapshot(root);\n if (snapshot) {\n const events = diffAndSynthesize(snapshot, next);\n for (const event of events) {\n const data = `data: ${JSON.stringify(event)}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n }\n snapshot = next;\n } catch {\n // re-parse failed, keep the old snapshot\n }\n }\n\n for (const file of files) {\n const filePath = campFile(root, file);\n try {\n watch(filePath, () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(check, 300);\n });\n } catch {\n // file might not exist yet\n }\n }\n\n takeSnapshot(root).then((s) => {\n snapshot = s;\n });\n\n return {\n subscribe(res: ServerResponse) {\n clients.add(res);\n const connected = JSON.stringify({\n message: 'Watching for changes…',\n timestamp: new Date().toISOString(),\n });\n res.write(`data: ${connected}\\n\\n`);\n res.on('close', () => clients.delete(res));\n },\n };\n}\n","export interface ParsedAgentLine {\n text: string;\n done?: boolean;\n error?: boolean;\n}\n\nexport function buildArgs(prompt: string): string[] {\n return ['-p', prompt, '--output-format', 'stream-json', '--verbose', '--permission-mode', 'auto'];\n}\n\n/**\n * Shape confirmed by a live `claude -p ... --output-format stream-json` smoke test\n * (see decisions.md, \"Confirm Claude Code's headless stream-json shape...\"), not guessed\n * from --help. Unknown subtypes fall through to a generic status line rather than being\n * dropped or throwing, since new bookkeeping subtypes (e.g. thinking_tokens) can appear.\n */\nexport function parseLine(line: string): ParsedAgentLine | null {\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(line);\n } catch {\n return null;\n }\n\n switch (json.type) {\n case 'system': {\n if (json.subtype === 'init') {\n return { text: 'Agent session started' };\n }\n if (json.subtype === 'post_turn_summary' && typeof json.status_detail === 'string') {\n return { text: json.status_detail };\n }\n return null;\n }\n case 'rate_limit_event':\n return null;\n case 'assistant': {\n const message = json.message as { content?: unknown[] } | undefined;\n const blocks = message?.content ?? [];\n for (const block of blocks) {\n const b = block as { type?: string; name?: string; text?: string };\n if (b.type === 'tool_use') {\n return { text: `Running ${b.name ?? 'a tool'}…` };\n }\n if (b.type === 'text' && typeof b.text === 'string' && b.text.trim()) {\n return { text: b.text.trim() };\n }\n }\n return null;\n }\n case 'user': {\n const message = json.message as { content?: unknown[] } | undefined;\n const content = message?.content;\n const block = Array.isArray(content) ? (content[0] as Record<string, unknown>) : undefined;\n if (block?.is_error) {\n const text = typeof block.content === 'string' ? block.content : 'Tool call failed';\n return { text: `Error: ${text}`, error: true };\n }\n return { text: 'Tool finished' };\n }\n case 'result': {\n const error = Boolean(json.is_error);\n const result = typeof json.result === 'string' ? json.result.trim() : '';\n const text = result || (error ? 'Agent run failed' : 'Agent run finished');\n return { text, done: true, error };\n }\n default:\n return { text: 'Agent is working…' };\n }\n}\n","import type { ParsedAgentLine } from './claude-code';\n\nexport function buildArgs(prompt: string): string[] {\n return ['run', prompt, '--format', 'json'];\n}\n\nconst TOOL_LABELS: Record<string, string> = {\n bash: 'Running command',\n read: 'Reading file',\n edit: 'Editing file',\n write: 'Writing file',\n glob: 'Searching files',\n grep: 'Searching code',\n websearch: 'Searching web',\n webfetch: 'Fetching URL',\n question: 'Asking for input',\n};\n\nexport function parseLine(line: string): ParsedAgentLine | null {\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(line);\n } catch {\n return null;\n }\n\n const type = json.type as string | undefined;\n const part = json.part as Record<string, unknown> | undefined;\n\n if (!type || !part) return null;\n\n switch (type) {\n case 'step_start':\n return null;\n case 'text': {\n const text = part.text as string | undefined;\n if (text?.trim()) return { text: text.trim() };\n return null;\n }\n case 'tool_use': {\n const tool = part.tool as string | undefined;\n const input = part.state ? (part.state as Record<string, unknown>).input : undefined;\n const desc = input ? (input as Record<string, unknown>).description : undefined;\n const label = tool ? TOOL_LABELS[tool] : 'Running tool';\n const detail = typeof desc === 'string' && desc.trim() ? `: ${desc.trim()}` : '';\n return tool ? { text: `${label}${detail}…` } : null;\n }\n case 'step_finish': {\n const reason = part.reason as string | undefined;\n const text = reason === 'tool-calls' ? null : reason === 'stop' ? 'Done' : 'Step finished';\n if (!text) return null;\n return { text };\n }\n default:\n return null;\n }\n}\n","import type { AgentId, DefaultAgentsMap, TaskKind } from '../../../types/index';\nimport * as claudeCode from './claude-code';\nimport type { ParsedAgentLine } from './claude-code';\nimport * as opencode from './opencode';\n\nexport interface AgentAdapter {\n command: string;\n buildArgs: (prompt: string) => string[];\n parseLine: (line: string) => ParsedAgentLine | null;\n}\n\nexport const DEFAULT_AGENT_ID: AgentId = 'claude-code';\n\nexport const AGENTS: Record<AgentId, AgentAdapter> = {\n 'claude-code': {\n command: 'claude',\n buildArgs: claudeCode.buildArgs,\n parseLine: claudeCode.parseLine,\n },\n opencode: {\n command: 'opencode',\n buildArgs: opencode.buildArgs,\n parseLine: opencode.parseLine,\n },\n};\n\nconst TASK_KIND_TO_DEFAULT_KEY: Record<TaskKind, keyof DefaultAgentsMap> = {\n phase: 'phase',\n audit: 'phase',\n draft: 'planDraft',\n extend: 'ideaExtend',\n};\n\nexport function resolveAgent(opts: {\n agentId: AgentId | undefined;\n defaultAgents?: DefaultAgentsMap;\n taskKind?: TaskKind;\n}): { id: AgentId; adapter: AgentAdapter } {\n const { agentId, defaultAgents, taskKind } = opts;\n if (agentId && agentId in AGENTS) return { id: agentId, adapter: AGENTS[agentId] };\n if (taskKind && defaultAgents) {\n const key = TASK_KIND_TO_DEFAULT_KEY[taskKind];\n const fallback = defaultAgents[key];\n if (fallback && fallback in AGENTS) return { id: fallback, adapter: AGENTS[fallback] };\n }\n return { id: DEFAULT_AGENT_ID, adapter: AGENTS[DEFAULT_AGENT_ID] };\n}\n","import { type ChildProcess, spawn } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport { parseIdeas, parsePlans } from '../../core/parser';\nimport {\n type AgentId,\n type AgentTaskState,\n type AgentTaskStatus,\n DEFAULT_AGENTS,\n type DefaultAgentsMap,\n type IdeaEntry,\n type PaperCampConfig,\n type PhaseItem,\n type PlanEntry,\n type TaskKind,\n} from '../../types/index';\nimport { type AgentAdapter, resolveAgent } from './agents';\n\nconst MAX_LINES = 50;\n\ninterface AgentTask {\n taskKind: TaskKind;\n planTitle: string;\n planId?: string;\n // Absent for a plan-scoped task (e.g. a convergence audit spanning every phase),\n // present for a single-phase task.\n phaseIndex?: number;\n // Only set for plan-scoped tasks, to check success against: did Phases or Log grow?\n planBaseline?: { phases: number; log: number };\n // Only set for an idea-drafting task, which has neither planId nor phaseIndex since\n // the plan doesn't exist yet — success is checked by idea id instead.\n ideaId?: string;\n // For idea-extend tasks: snapshot the idea's body before launch so we can detect changes.\n ideaBodyBaseline?: string;\n status: AgentTaskStatus;\n agentId: AgentId;\n adapter: AgentAdapter;\n proc: ChildProcess;\n lines: string[];\n}\n\nfunction readDefaultAgentIds(root: string): DefaultAgentsMap {\n try {\n const raw = readFileSync(join(root, '.paper-camp', 'config.json'), 'utf-8');\n const config = JSON.parse(raw) as PaperCampConfig & { defaultAgent?: AgentId };\n if (config.defaultAgents) return config.defaultAgents;\n if (config.defaultAgent) {\n return {\n phase: config.defaultAgent,\n planDraft: config.defaultAgent,\n ideaExtend: config.defaultAgent,\n };\n }\n return DEFAULT_AGENTS;\n } catch {\n return DEFAULT_AGENTS;\n }\n}\n\ntype Result = { ok: true } | { ok: false; error: string };\n\nfunction buildAgentPrompt(plan: PlanEntry, phase: PhaseItem, phaseIndex: number): string {\n return `You're working on phase ${phaseIndex + 1} (\"${phase.text}\") of the plan \"${plan.title}\" (${plan.id ?? 'no id'}) in papercamp/plans.md.\n\n${phase.description ?? ''}\n\nPlan context: ${plan.body}\n\nDo only this phase. When done, check it off in plans.md (- [ ] -> - [x]) and append what you did to progress.md. If this was the last unchecked phase, set the plan's Status to \\`review\\`, not \\`done\\`, per this repo's AGENTS.md.`;\n}\n\nexport function createAgentManager(\n root: string,\n ensureBranch: (plan: PlanEntry) => void = () => {},\n) {\n const clients = new Set<ServerResponse>();\n let current: AgentTask | null = null;\n\n function broadcast(message: string) {\n const data = `data: ${JSON.stringify({ message, timestamp: new Date().toISOString(), type: 'agent' })}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n\n function pushLine(task: AgentTask, text: string) {\n task.lines.push(text);\n if (task.lines.length > MAX_LINES) task.lines.shift();\n broadcast(text);\n }\n\n function setStatus(task: AgentTask, status: AgentTaskStatus) {\n task.status = status;\n broadcast(`agent: ${status}`);\n }\n\n async function didTaskProgress(task: AgentTask): Promise<boolean | null> {\n try {\n if (task.taskKind === 'extend') {\n const raw = await readFile(join(root, 'papercamp', 'ideas.md'), 'utf-8');\n const entries = parseIdeas(raw);\n const idea = entries.find((e) => e.id === task.ideaId);\n if (!idea) return null;\n if (task.ideaBodyBaseline === undefined) return null;\n return idea.body !== task.ideaBodyBaseline;\n }\n const raw = await readFile(join(root, 'papercamp', 'plans.md'), 'utf-8');\n const { entries } = parsePlans(raw);\n if (task.ideaId !== undefined) {\n return entries.some((p) => p.idea === task.ideaId);\n }\n const plan =\n entries.find((p) => p.id === task.planId) ??\n entries.find((p) => p.title === task.planTitle);\n if (!plan) return null;\n if (task.phaseIndex !== undefined) {\n return plan.phases[task.phaseIndex]?.done ?? null;\n }\n if (!task.planBaseline) return null;\n return (\n plan.phases.length > task.planBaseline.phases ||\n (plan.log?.length ?? 0) > task.planBaseline.log\n );\n } catch {\n return null;\n }\n }\n\n function finishTask(task: AgentTask, error: boolean) {\n setStatus(task, error ? 'error' : 'done');\n if (error) return;\n didTaskProgress(task).then((progressed) => {\n if (current === task && progressed === false) {\n const warning =\n task.taskKind === 'extend'\n ? `Warning: agent finished but the idea body for ${task.ideaId} did not change — verify manually`\n : task.ideaId !== undefined\n ? `Warning: agent finished but no plan linking idea: ${task.ideaId} appeared in plans.md — verify manually`\n : task.phaseIndex !== undefined\n ? 'Warning: agent finished but did not check off this phase in plans.md — verify manually'\n : 'Warning: agent finished but appended nothing to Phases or Log — verify manually';\n pushLine(task, warning);\n }\n });\n }\n\n function attachReader(task: AgentTask) {\n if (!task.proc.stdout) return;\n const rl = createInterface({ input: task.proc.stdout });\n rl.on('line', (line) => {\n if (current !== task || !line.trim()) return;\n const parsed = task.adapter.parseLine(line);\n if (!parsed) return;\n pushLine(task, parsed.text);\n if (parsed.done) {\n finishTask(task, Boolean(parsed.error));\n }\n });\n\n task.proc.on('close', (code) => {\n if (current !== task) return;\n if (task.status === 'starting' || task.status === 'running') {\n finishTask(task, code !== 0);\n } else if (task.status === 'stopping') {\n setStatus(task, 'done');\n }\n });\n\n task.proc.on('error', (err) => {\n if (current !== task) return;\n pushLine(task, `Failed to spawn agent: ${err.message}`);\n setStatus(task, 'error');\n });\n }\n\n function spawnAgent(adapter: AgentAdapter, args: string[]): ChildProcess {\n return spawn(adapter.command, args, {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n }\n\n function isBusy(): boolean {\n return current !== null && current.status !== 'done' && current.status !== 'error';\n }\n\n // Shared by start()/startForPlan()/startForIdea(): synchronous on purpose, same\n // race-avoidance reasoning as the busy-guard above — no `await` between the guard\n // check and reserving `current`.\n function launch(\n identity: { planTitle: string; planId?: string; agentOverride?: AgentId },\n prompt: string,\n scope: Pick<\n AgentTask,\n 'taskKind' | 'phaseIndex' | 'planBaseline' | 'ideaId' | 'ideaBodyBaseline'\n >,\n ): Result {\n if (isBusy()) {\n return { ok: false, error: 'An agent task is already running' };\n }\n const defaultAgents = readDefaultAgentIds(root);\n const { id: agentId, adapter } = resolveAgent({\n agentId: identity.agentOverride,\n defaultAgents,\n taskKind: scope.taskKind,\n });\n const proc = spawnAgent(adapter, adapter.buildArgs(prompt));\n const task: AgentTask = {\n planTitle: identity.planTitle,\n planId: identity.planId,\n status: 'starting',\n agentId,\n adapter,\n proc,\n lines: [],\n ...scope,\n };\n current = task;\n attachReader(task);\n setStatus(task, 'running');\n return { ok: true };\n }\n\n function start(plan: PlanEntry, phaseIndex: number): Result {\n if (isBusy()) {\n return { ok: false, error: 'An agent task is already running' };\n }\n const phase = plan.phases[phaseIndex];\n if (!phase) {\n return { ok: false, error: 'Phase not found' };\n }\n ensureBranch(plan);\n const prompt = buildAgentPrompt(plan, phase, phaseIndex);\n return launch({ planTitle: plan.title, planId: plan.id, agentOverride: plan.agent }, prompt, {\n taskKind: 'phase',\n phaseIndex,\n });\n }\n\n // Plan-scoped launch mode: no single phase, so success is judged by whether the\n // agent appended anything to Phases or Log rather than whether one checkbox flipped.\n function startForPlan(plan: PlanEntry, prompt: string): Result {\n return launch({ planTitle: plan.title, planId: plan.id, agentOverride: plan.agent }, prompt, {\n taskKind: 'audit',\n planBaseline: { phases: plan.phases.length, log: plan.log?.length ?? 0 },\n });\n }\n\n // Idea-drafting launch mode: there's no plan yet (and so no per-plan agent override\n // either) — the plan only exists once the agent writes it, so success is judged by\n // whether a new plan entry linking this idea's id shows up in plans.md.\n function startForIdea(idea: IdeaEntry, prompt: string): Result {\n if (!idea.id) {\n return { ok: false, error: 'Idea has no id to link a drafted plan back to' };\n }\n return launch({ planTitle: `Draft plan for ${idea.id}` }, prompt, {\n taskKind: 'draft',\n ideaId: idea.id,\n });\n }\n\n // Idea-extend launch mode: given an idea, explores the codebase and rewrites its\n // body in place in ideas.md. Success is judged by whether that idea's body text\n // actually changed.\n function startForIdeaExtend(idea: IdeaEntry, prompt: string): Result {\n if (!idea.id) {\n return { ok: false, error: 'Idea has no id to extend' };\n }\n return launch({ planTitle: `Extend ${idea.id}` }, prompt, {\n taskKind: 'extend',\n ideaId: idea.id,\n ideaBodyBaseline: idea.body,\n });\n }\n\n function stop(): Result {\n if (!current) {\n return { ok: false, error: 'No agent task running' };\n }\n const task = current;\n setStatus(task, 'stopping');\n if (!task.proc.killed) task.proc.kill('SIGTERM');\n // SIGTERM can be ignored or delayed indefinitely; without this escalation a hung\n // process leaves `current` stuck in 'stopping' forever, permanently blocking start().\n setTimeout(() => {\n if (current === task && task.status === 'stopping') {\n task.proc.kill('SIGKILL');\n }\n }, 5000);\n return { ok: true };\n }\n\n function getStatus(): AgentTaskState | null {\n if (!current) return null;\n return {\n status: current.status,\n taskKind: current.taskKind,\n planTitle: current.planTitle,\n planId: current.planId,\n phaseIndex: current.phaseIndex,\n ideaId: current.ideaId,\n agentId: current.agentId,\n lines: [...current.lines],\n };\n }\n\n return {\n start,\n startForPlan,\n startForIdea,\n startForIdeaExtend,\n stop,\n getStatus,\n subscribe(res: ServerResponse) {\n clients.add(res);\n res.on('close', () => clients.delete(res));\n },\n killCurrent() {\n if (current?.proc && !current.proc.killed) {\n current.proc.kill();\n }\n },\n };\n}\n\nexport interface AgentManager {\n start: (plan: PlanEntry, phaseIndex: number) => Result;\n startForPlan: (plan: PlanEntry, prompt: string) => Result;\n startForIdea: (idea: IdeaEntry, prompt: string) => Result;\n startForIdeaExtend: (idea: IdeaEntry, prompt: string) => Result;\n stop: () => Result;\n getStatus: () => AgentTaskState | null;\n subscribe: (res: ServerResponse) => void;\n killCurrent: () => void;\n}\n","import { spawn, spawnSync } from 'node:child_process';\nimport { watch } from 'node:fs';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport type { GitStatusEntry, PlanEntry } from '../../types';\n\nexport function createGitManager(root: string) {\n const clients = new Set<ServerResponse>();\n\n function broadcast(event: { message: string; timestamp: string }) {\n const data = `data: ${JSON.stringify(event)}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n\n function parsePorcelain(output: string): GitStatusEntry[] {\n const entries: GitStatusEntry[] = [];\n for (const line of output.split('\\n')) {\n if (!line.trim()) continue;\n const x = line[0] ?? ' ';\n const y = line[1] ?? ' ';\n const rest = line.slice(3);\n const path = rest.split(' -> ').pop() ?? rest;\n entries.push({\n path,\n status: `${x}${y}`,\n staged: x !== ' ' && x !== '?',\n });\n }\n return entries;\n }\n\n function runGit(args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn('git', args, {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stdout = '';\n let stderr = '';\n proc.stdout?.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n proc.stderr?.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n proc.on('close', (code) => {\n if (code === 0) {\n resolve(stdout);\n } else {\n reject(new Error(stderr || `git ${args[0]} exited with code ${code}`));\n }\n });\n proc.on('error', reject);\n });\n }\n\n function runGitStatus(): Promise<GitStatusEntry[]> {\n return runGit(['status', '--porcelain=v1']).then(parsePorcelain);\n }\n\n async function commit(files: string[], title: string, message?: string): Promise<void> {\n if (files.length > 0) {\n await runGit(['add', '--', ...files]);\n }\n const args = ['commit', '-m', title];\n if (message) args.push('-m', message);\n await runGit(args);\n }\n\n function ensureBranch(plan: PlanEntry): void {\n if (!plan.kind || !plan.id) return;\n\n const kind = plan.kind.toLowerCase();\n const id = plan.id.toLowerCase();\n const title = plan.title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n const branch = `${kind}/${id}-${title}`;\n\n const currentResult = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: root });\n if (currentResult.status !== 0) {\n throw new Error(\n currentResult.stderr.toString().trim() || 'Unable to read current git branch',\n );\n }\n const currentBranch = currentResult.stdout.toString().trim();\n if (currentBranch === branch) return;\n\n const result = spawnSync('git', ['checkout', '-b', branch, 'main'], { cwd: root });\n if (result.status !== 0) {\n // Branch already exists — just check it out\n const checkoutResult = spawnSync('git', ['checkout', branch], { cwd: root });\n if (checkoutResult.status !== 0) {\n throw new Error(\n checkoutResult.stderr.toString().trim() ||\n result.stderr.toString().trim() ||\n `Unable to check out ${branch}`,\n );\n }\n }\n }\n\n async function refresh() {\n try {\n await runGitStatus();\n broadcast({\n message: 'Working tree status updated',\n timestamp: new Date().toISOString(),\n });\n } catch {\n // git not available or not a repo\n }\n }\n\n const gitDir = join(root, '.git');\n let timer: ReturnType<typeof setTimeout> | null = null;\n try {\n watch(gitDir, { recursive: true }, (eventType, filename) => {\n if (filename === 'index') {\n if (timer) clearTimeout(timer);\n timer = setTimeout(refresh, 500);\n }\n });\n } catch {\n // watcher not available\n }\n\n const srcDir = join(root, 'src');\n let srcTimer: ReturnType<typeof setTimeout> | null = null;\n try {\n watch(srcDir, { recursive: true }, () => {\n if (srcTimer) clearTimeout(srcTimer);\n srcTimer = setTimeout(refresh, 500);\n });\n } catch {\n // src/ doesn't exist or watcher not available\n }\n\n function getCurrentBranch(): string {\n const result = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: root });\n return result.stdout.toString().trim();\n }\n\n function getFeatureBranchPlanId(): string | null {\n const branch = getCurrentBranch();\n const match = branch.match(/^[a-z]+\\/([a-z]+-\\d+)-/);\n return match ? match[1].toUpperCase() : null;\n }\n\n return {\n async getStatus(): Promise<GitStatusEntry[]> {\n return runGitStatus();\n },\n getCurrentBranch,\n commit,\n ensureBranch,\n getFeatureBranchPlanId,\n subscribe(res: ServerResponse) {\n clients.add(res);\n res.on('close', () => clients.delete(res));\n },\n };\n}\n","import { spawn } from 'node:child_process';\nimport { watch } from 'node:fs';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport type { CheckName, CheckResult, CheckStatus } from '../../types';\n\ninterface StatusSnapshot {\n lint: CheckResult;\n format: CheckResult;\n test: CheckResult;\n}\n\nconst CHECK_COMMANDS: Record<CheckName, string> = {\n lint: 'npx biome lint .',\n format: 'npx biome format .',\n test: 'npx vitest run',\n};\n\nexport function createStatusManager(root: string) {\n const clients = new Set<ServerResponse>();\n const snapshot: StatusSnapshot = {\n lint: { status: 'stale', lastRun: null, output: '' },\n format: { status: 'stale', lastRun: null, output: '' },\n test: { status: 'stale', lastRun: null, output: '' },\n };\n const running = new Set<CheckName>();\n const queued = new Set<CheckName>();\n\n function broadcast(event: { message: string; timestamp: string }) {\n const data = `data: ${JSON.stringify(event)}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n\n function setResult(name: CheckName, status: CheckStatus, output: string) {\n snapshot[name] = { status, lastRun: new Date().toISOString(), output };\n broadcast({\n message: `${name}: ${status}`,\n timestamp: snapshot[name].lastRun!,\n });\n if (status !== 'running' && queued.has(name)) {\n queued.delete(name);\n runCheck(name);\n }\n }\n\n function runCheck(name: CheckName) {\n if (running.has(name)) {\n queued.add(name);\n return;\n }\n running.add(name);\n setResult(name, 'running', '');\n\n const cmd = CHECK_COMMANDS[name];\n const proc = spawn(cmd, {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout?.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n proc.stderr?.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n\n proc.on('close', (code) => {\n running.delete(name);\n const output = stdout + stderr;\n if (code === 0) {\n setResult(name, 'pass', output);\n } else {\n setResult(name, 'fail', output);\n }\n });\n\n proc.on('error', (err) => {\n running.delete(name);\n setResult(name, 'fail', `Failed to spawn process: ${err.message}`);\n });\n }\n\n function runQualityFix() {\n if (running.has('lint') || running.has('format')) return;\n setResult('lint', 'running', 'Applying automatic fixes…');\n setResult('format', 'running', 'Applying automatic fixes…');\n\n const proc = spawn('npx biome check . --write', {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n proc.on('close', () => {\n runCheck('lint');\n runCheck('format');\n });\n\n proc.on('error', (err) => {\n const message = `Failed to spawn fix process: ${err.message}`;\n setResult('lint', 'fail', message);\n setResult('format', 'fail', message);\n });\n }\n\n const srcDir = join(root, 'src');\n let srcTimer: ReturnType<typeof setTimeout> | null = null;\n try {\n watch(srcDir, { recursive: true }, () => {\n if (srcTimer) clearTimeout(srcTimer);\n srcTimer = setTimeout(() => {\n runCheck('lint');\n runCheck('format');\n }, 1000);\n });\n } catch {\n // watcher not available (src/ doesn't exist or platform doesn't support recursive)\n }\n\n return {\n getStatus(): StatusSnapshot {\n return {\n lint: { ...snapshot.lint },\n format: { ...snapshot.format },\n test: { ...snapshot.test },\n };\n },\n runCheck,\n runQualityFix,\n subscribe(res: ServerResponse) {\n clients.add(res);\n for (const name of ['lint', 'format', 'test'] as CheckName[]) {\n const result = snapshot[name];\n if (result.status !== 'stale') {\n res.write(\n `data: ${JSON.stringify({ message: `${name}: ${result.status}`, timestamp: result.lastRun })}\\n\\n`,\n );\n }\n }\n res.on('close', () => clients.delete(res));\n },\n };\n}\n","import { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { extname, join } from 'node:path';\nimport { applyEnvEntries, parseEnv } from '../../core/env';\nimport {\n findConsistencyIssues,\n parseDecisions,\n parseIdeas,\n parseOpenQuestions,\n parsePlans,\n parseProgress,\n} from '../../core/parser';\nimport {\n appendBlock,\n assignPlanId,\n formatPlanEntry,\n formatPlans,\n todayDateString,\n} from '../../core/serializer';\nimport {\n AGENT_IDS,\n type AgentId,\n DEFAULT_AGENTS,\n type DefaultAgentsMap,\n type EnvEntry,\n type LogEntry,\n PLAN_KINDS,\n type PaperCampConfig,\n type PhaseItem,\n type PlanEntry,\n type PlanStatus,\n} from '../../types/index';\nimport { createActivityManager } from './activity';\nimport { type AgentManager, createAgentManager } from './agent';\nimport { createGitManager } from './git';\nimport { createStatusManager } from './status';\n\nasync function readMaybe(path: string): Promise<string> {\n try {\n return await readFile(path, 'utf-8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return '';\n throw error;\n }\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk;\n });\n req.on('end', () => resolve(body));\n req.on('error', reject);\n });\n}\n\ninterface ApiRoute {\n path: string;\n handler: (root: string) => Promise<unknown>;\n}\n\nconst campFile = (root: string, name: string) => join(root, 'papercamp', name);\n\nconst CONFIG_ALLOWLIST = [\n 'biome.json',\n 'tsconfig.json',\n 'tailwind.config.ts',\n 'vite.config.ts',\n 'vite.app.config.ts',\n 'postcss.config.js',\n 'package.json',\n];\n\nasync function checkBranchConflictForPlan(\n root: string,\n git: { getFeatureBranchPlanId: () => string | null },\n targetPlanId?: string,\n): Promise<string | null> {\n const activePlanId = git.getFeatureBranchPlanId();\n if (!activePlanId) return null;\n if (targetPlanId && activePlanId === targetPlanId) return null;\n const plansRaw = await readMaybe(campFile(root, 'plans.md'));\n if (!plansRaw) return null;\n const { entries } = parsePlans(plansRaw);\n const activePlan = entries.find((p) => p.id === activePlanId);\n if (!activePlan || activePlan.status === 'done' || activePlan.status === 'dropped') return null;\n return `Finish \\`${activePlanId}\\` — ${activePlan.title} — before starting another plan`;\n}\n\nconst apiRoutes: ApiRoute[] = [\n {\n path: '/api/package-name',\n handler: async (root) => {\n const raw = await readMaybe(join(root, 'package.json'));\n if (!raw) return null;\n try {\n const pkg = JSON.parse(raw);\n return pkg.name ?? null;\n } catch {\n return null;\n }\n },\n },\n {\n path: '/api/plans',\n handler: async (root) => parsePlans(await readMaybe(campFile(root, 'plans.md'))),\n },\n {\n path: '/api/progress',\n handler: async (root) => ({\n entries: parseProgress(await readMaybe(campFile(root, 'progress.md'))),\n }),\n },\n {\n path: '/api/decisions',\n handler: async (root) => parseDecisions(await readMaybe(campFile(root, 'decisions.md'))),\n },\n {\n path: '/api/open-questions',\n handler: async (root) =>\n parseOpenQuestions(await readMaybe(campFile(root, 'open-questions.md'))),\n },\n {\n path: '/api/ideas',\n handler: async (root) => ({\n content: await readMaybe(campFile(root, 'ideas.md')),\n }),\n },\n {\n path: '/api/consistency',\n handler: async (root) => {\n const [decisionsRaw, openQuestionsRaw, plansRaw] = await Promise.all([\n readMaybe(campFile(root, 'decisions.md')),\n readMaybe(campFile(root, 'open-questions.md')),\n readMaybe(campFile(root, 'plans.md')),\n ]);\n const decisions = parseDecisions(decisionsRaw);\n const openQuestions = parseOpenQuestions(openQuestionsRaw);\n const plans = parsePlans(plansRaw);\n return findConsistencyIssues(decisions.entries, openQuestions.entries, plans.entries);\n },\n },\n {\n path: '/api/config',\n handler: async (root) => {\n const raw = await readMaybe(join(root, '.paper-camp', 'config.json'));\n return raw ? JSON.parse(raw) : null;\n },\n },\n {\n path: '/api/docs',\n handler: async (root) => {\n const docNames = ['MAIN.md', 'README.md', 'CHANGELOG.md', 'LICENSE'];\n const files: { name: string; content: string }[] = [];\n for (const name of docNames) {\n const content = await readMaybe(join(root, name));\n if (content) files.push({ name, content });\n }\n return { files };\n },\n },\n {\n path: '/api/configs',\n handler: async (root) => {\n const configNames = [\n 'biome.json',\n 'tsconfig.json',\n 'tailwind.config.ts',\n 'vite.config.ts',\n 'vite.app.config.ts',\n 'postcss.config.js',\n 'package.json',\n ];\n const files: string[] = [];\n for (const name of configNames) {\n const content = await readMaybe(join(root, name));\n if (content) files.push(name);\n }\n return { files };\n },\n },\n];\n\nexport interface ApiMiddleware {\n (req: IncomingMessage, res: ServerResponse, next: () => void): Promise<void>;\n agent: AgentManager;\n}\n\nexport function createApiMiddleware(root: string): ApiMiddleware {\n const activity = createActivityManager(root);\n const git = createGitManager(root);\n const status = createStatusManager(root);\n const agent = createAgentManager(root, (plan) => git.ensureBranch(plan));\n const handler = async (req: IncomingMessage, res: ServerResponse, next: () => void) => {\n const pathname = (req.url ?? '').split('?')[0];\n\n // DELETE /api/plans?title=... — remove a plan entry\n if (req.method === 'DELETE' && pathname === '/api/plans') {\n try {\n const url = new URL(req.url ?? '', `http://${req.headers.host ?? 'localhost'}`);\n const title = url.searchParams.get('title');\n if (!title?.trim()) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'title is required' }));\n return;\n }\n const filePath = campFile(root, 'plans.md');\n const parsed = parsePlans(await readMaybe(filePath));\n const trimmed = title.trim();\n const remaining = parsed.entries.filter((entry) => entry.title !== trimmed);\n if (remaining.length === parsed.entries.length) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'plan not found' }));\n return;\n }\n await writeFile(filePath, formatPlans(remaining));\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/plans — append a new idea entry\n if (req.method === 'POST' && pathname === '/api/plans') {\n try {\n const body = await readBody(req);\n const { title, content, kind } = JSON.parse(body) as {\n title: string;\n content?: string;\n kind?: string;\n };\n if (!title?.trim()) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'title is required' }));\n return;\n }\n const planKind =\n kind && PLAN_KINDS.includes(kind as (typeof PLAN_KINDS)[number]) ? kind : 'feat';\n\n const configPath = join(root, '.paper-camp', 'config.json');\n const id = await assignPlanId(configPath, planKind);\n\n const entry = formatPlanEntry({\n title: title.trim(),\n status: 'idea',\n kind: planKind,\n id,\n created: todayDateString(),\n body: content?.trim(),\n });\n await appendBlock(campFile(root, 'plans.md'), entry);\n res.statusCode = 201;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true, id }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // PATCH /api/plans?title=... — update an existing plan entry\n if (req.method === 'PATCH' && pathname === '/api/plans') {\n try {\n const url = new URL(req.url ?? '', `http://${req.headers.host ?? 'localhost'}`);\n const title = url.searchParams.get('title');\n if (!title?.trim()) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'title is required' }));\n return;\n }\n const body = await readBody(req);\n const updates = JSON.parse(body) as {\n phases?: PhaseItem[];\n status?: PlanStatus;\n log?: LogEntry[];\n agent?: AgentId | null;\n };\n if (updates.agent && !AGENT_IDS.includes(updates.agent)) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'agent must be a known agent id' }));\n return;\n }\n const filePath = campFile(root, 'plans.md');\n const parsed = parsePlans(await readMaybe(filePath));\n const trimmed = title.trim();\n let found = false;\n const updated = parsed.entries.map((entry: PlanEntry) => {\n if (entry.title === trimmed) {\n found = true;\n return {\n ...entry,\n ...(updates.status !== undefined && { status: updates.status }),\n ...(updates.phases !== undefined && { phases: updates.phases }),\n ...(updates.log !== undefined && { log: updates.log }),\n ...(updates.agent !== undefined && { agent: updates.agent ?? undefined }),\n updated: todayDateString(),\n };\n }\n // Starting a plan puts it in focus — only one other plan is ever \"in focus\"\n // (in-progress) at a time. A `review` plan isn't in focus, it's done and\n // awaiting approval, so starting a different plan must never touch it.\n if (updates.status === 'in-progress' && entry.status === 'in-progress') {\n return { ...entry, status: 'planned' as const, updated: todayDateString() };\n }\n return entry;\n });\n if (!found) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'plan not found' }));\n return;\n }\n if (updates.status === 'done') {\n const targetEntry = parsed.entries.find((e: PlanEntry) => e.title === trimmed);\n const conflict = await checkBranchConflictForPlan(root, git, targetEntry?.id);\n if (conflict) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: conflict }));\n return;\n }\n }\n await writeFile(filePath, formatPlans(updated));\n\n if (updates.status === 'done') {\n const finalEntry = updated.find((e: PlanEntry) => e.title === trimmed);\n if (finalEntry) {\n try {\n git.ensureBranch(finalEntry);\n } catch {\n // Non-fatal: git operations may fail (not a repo, etc.)\n }\n }\n }\n\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/ideas — append a new idea entry to ideas.md\n if (req.method === 'POST' && pathname === '/api/ideas') {\n try {\n const body = await readBody(req);\n const { title, content } = JSON.parse(body) as { title?: string; content?: string };\n if (!title?.trim()) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'title is required' }));\n return;\n }\n const filePath = campFile(root, 'ideas.md');\n const existing = await readMaybe(filePath);\n const parsed = parseIdeas(existing);\n const maxNum = parsed.reduce((max, idea) => {\n if (idea.id) {\n const num = Number.parseInt(idea.id.replace('IDEA-', ''), 10);\n return Number.isNaN(num) ? max : Math.max(max, num);\n }\n return max;\n }, 0);\n const newId = `IDEA-${maxNum + 1}`;\n const section = `### ${newId}: ${title.trim()}\\n\\n${content?.trim() ?? ''}`;\n const trimmed = existing.trimEnd();\n const separator = trimmed.length === 0 ? '' : '\\n\\n---\\n\\n';\n await writeFile(filePath, `${trimmed}${separator}${section}\\n`);\n res.statusCode = 201;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true, id: newId }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // GET /api/icon — serve project icon\n if (req.method === 'GET' && pathname === '/api/icon') {\n const assetsDir = join(root, '.paper-camp', 'assets');\n const mimeMap: Record<string, string> = {\n svg: 'image/svg+xml',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n };\n for (const [ext, mime] of Object.entries(mimeMap)) {\n try {\n const data = await readFile(join(assetsDir, `icon.${ext}`));\n res.statusCode = 200;\n res.setHeader('Content-Type', mime);\n res.setHeader('Cache-Control', 'no-cache');\n res.end(data);\n return;\n } catch {\n /* try next */\n }\n }\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'no icon uploaded' }));\n return;\n }\n\n // POST /api/icon — upload project icon\n if (req.method === 'POST' && pathname === '/api/icon') {\n try {\n const body = await readBody(req);\n const { dataUri } = JSON.parse(body) as { dataUri?: string };\n if (!dataUri) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'dataUri is required' }));\n return;\n }\n const match = dataUri.match(/^data:(image\\/[a-z0-9+.-]+);base64,(.+)$/);\n if (!match) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'invalid data URI' }));\n return;\n }\n const mime = match[1];\n const ext = mime === 'image/svg+xml' ? 'svg' : mime.split('/')[1];\n const buffer = Buffer.from(match[2], 'base64');\n const assetsDir = join(root, '.paper-camp', 'assets');\n await mkdir(assetsDir, { recursive: true });\n await writeFile(join(assetsDir, `icon.${ext}`), buffer);\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // GET /api/git/status — return working tree status\n if (req.method === 'GET' && pathname === '/api/git/status') {\n try {\n const entries = await git.getStatus();\n const branch = git.getCurrentBranch();\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ branch, entries }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/git/commit — stage files and create a commit\n if (req.method === 'POST' && pathname === '/api/git/commit') {\n try {\n const body = await readBody(req);\n const { files, title, message } = JSON.parse(body) as {\n files: string[];\n title: string;\n message?: string;\n };\n if (!title?.trim()) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'title is required' }));\n return;\n }\n await git.commit(files ?? [], title.trim(), message?.trim());\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // GET /api/status — return current lint/format/test check results\n if (req.method === 'GET' && pathname === '/api/status') {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(status.getStatus()));\n return;\n }\n\n // POST /api/status/check?name=lint|format|test — trigger a one-off check run\n if (req.method === 'POST' && pathname === '/api/status/check') {\n const url = new URL(req.url ?? '', `http://${req.headers.host ?? 'localhost'}`);\n const name = url.searchParams.get('name');\n if (name !== 'lint' && name !== 'format' && name !== 'test') {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'name must be lint, format, or test' }));\n return;\n }\n status.runCheck(name);\n res.statusCode = 202;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n return;\n }\n\n // POST /api/status/fix — run `biome check . --write` to auto-fix lint/format issues\n if (req.method === 'POST' && pathname === '/api/status/fix') {\n status.runQualityFix();\n res.statusCode = 202;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n return;\n }\n\n // GET /api/activity/stream — SSE endpoint for live activity events\n if (req.method === 'GET' && pathname === '/api/activity/stream') {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.flushHeaders();\n activity.subscribe(res);\n git.subscribe(res);\n status.subscribe(res);\n agent.subscribe(res);\n return;\n }\n\n // GET /api/agent/status — current agent task state, if any\n if (req.method === 'GET' && pathname === '/api/agent/status') {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(agent.getStatus()));\n return;\n }\n\n // POST /api/agent/launch — start a headless agent on one plan phase\n if (req.method === 'POST' && pathname === '/api/agent/launch') {\n try {\n const body = await readBody(req);\n const { planId, phaseIndex } = JSON.parse(body) as { planId?: string; phaseIndex?: number };\n if (!planId || typeof phaseIndex !== 'number') {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'planId and phaseIndex are required' }));\n return;\n }\n const parsed = parsePlans(await readMaybe(campFile(root, 'plans.md')));\n const plan = parsed.entries.find((p) => p.id === planId);\n if (!plan) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'plan not found' }));\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git, plan.id);\n if (conflict) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: conflict }));\n return;\n }\n const result = await agent.start(plan, phaseIndex);\n if (!result.ok) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: result.error }));\n return;\n }\n res.statusCode = 202;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/agent/launch-audit — start a headless agent on a plan-scoped convergence audit\n if (req.method === 'POST' && pathname === '/api/agent/launch-audit') {\n try {\n const body = await readBody(req);\n const { planId, prompt } = JSON.parse(body) as { planId?: string; prompt?: string };\n if (!planId || !prompt) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'planId and prompt are required' }));\n return;\n }\n const parsed = parsePlans(await readMaybe(campFile(root, 'plans.md')));\n const plan = parsed.entries.find((p) => p.id === planId);\n if (!plan) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'plan not found' }));\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git, plan.id);\n if (conflict) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: conflict }));\n return;\n }\n const result = agent.startForPlan(plan, prompt);\n if (!result.ok) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: result.error }));\n return;\n }\n res.statusCode = 202;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/agent/launch-draft — start a headless agent that drafts a new plan from an idea\n if (req.method === 'POST' && pathname === '/api/agent/launch-draft') {\n try {\n const body = await readBody(req);\n const { ideaId, prompt } = JSON.parse(body) as { ideaId?: string; prompt?: string };\n if (!ideaId || !prompt) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'ideaId and prompt are required' }));\n return;\n }\n const ideas = parseIdeas(await readMaybe(campFile(root, 'ideas.md')));\n const idea = ideas.find((i) => i.id === ideaId);\n if (!idea) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'idea not found' }));\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git);\n if (conflict) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: conflict }));\n return;\n }\n const result = agent.startForIdea(idea, prompt);\n if (!result.ok) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: result.error }));\n return;\n }\n res.statusCode = 202;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/agent/launch-extend — start a headless agent to extend an idea's body\n if (req.method === 'POST' && pathname === '/api/agent/launch-extend') {\n try {\n const body = await readBody(req);\n const { ideaId, prompt } = JSON.parse(body) as { ideaId?: string; prompt?: string };\n if (!ideaId || !prompt) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'ideaId and prompt are required' }));\n return;\n }\n const ideas = parseIdeas(await readMaybe(campFile(root, 'ideas.md')));\n const idea = ideas.find((i) => i.id === ideaId);\n if (!idea) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'idea not found' }));\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git);\n if (conflict) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: conflict }));\n return;\n }\n const result = agent.startForIdeaExtend(idea, prompt);\n if (!result.ok) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: result.error }));\n return;\n }\n res.statusCode = 202;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/agent/stop — kill the running agent task\n if (req.method === 'POST' && pathname === '/api/agent/stop') {\n const result = agent.stop();\n if (!result.ok) {\n res.statusCode = 409;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: result.error }));\n return;\n }\n res.statusCode = 202;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n return;\n }\n\n // POST /api/config — update editable fields in .paper-camp/config.json (port, projectName)\n if (req.method === 'POST' && pathname === '/api/config') {\n try {\n const configPath = join(root, '.paper-camp', 'config.json');\n const raw = await readMaybe(configPath);\n if (!raw) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'config not found' }));\n return;\n }\n const body = await readBody(req);\n const { port, projectName, defaultAgent, defaultAgents } = JSON.parse(body) as {\n port?: number;\n projectName?: string;\n defaultAgent?: AgentId;\n defaultAgents?: DefaultAgentsMap;\n };\n if (port !== undefined && (!Number.isInteger(port) || port <= 0)) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'port must be a positive integer' }));\n return;\n }\n if (projectName !== undefined && projectName.trim().length === 0) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'projectName must not be empty' }));\n return;\n }\n if (defaultAgent !== undefined && !AGENT_IDS.includes(defaultAgent)) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'defaultAgent must be a known agent id' }));\n return;\n }\n if (defaultAgents !== undefined) {\n for (const key of ['phase', 'planDraft', 'ideaExtend'] as const) {\n if (!AGENT_IDS.includes(defaultAgents[key])) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: `defaultAgents.${key} must be a known agent id` }));\n return;\n }\n }\n }\n const config = JSON.parse(raw) as PaperCampConfig;\n const resolvedDefaultAgents =\n defaultAgents ??\n (defaultAgent !== undefined\n ? { phase: defaultAgent, planDraft: defaultAgent, ideaExtend: defaultAgent }\n : undefined);\n const configWithOld = config as PaperCampConfig & { defaultAgent?: AgentId };\n const { defaultAgent: _oldAgent, ...configRest } = configWithOld;\n const updated: PaperCampConfig = {\n ...configRest,\n ...(port !== undefined && { port }),\n ...(projectName !== undefined && { projectName: projectName.trim() }),\n ...(resolvedDefaultAgents && { defaultAgents: resolvedDefaultAgents }),\n };\n await writeFile(configPath, JSON.stringify(updated, null, 2));\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // GET /api/env — read the project root's .env, masked client-side only\n if (req.method === 'GET' && pathname === '/api/env') {\n try {\n const envPath = join(root, '.env');\n const examplePath = join(root, '.env.example');\n const [exists, exampleExists] = await Promise.all([\n fileExists(envPath),\n fileExists(examplePath),\n ]);\n const entries = exists ? parseEnv(await readMaybe(envPath)) : [];\n const exampleKeys = exampleExists\n ? parseEnv(await readMaybe(examplePath)).map((e) => e.key)\n : [];\n const envKeys = new Set(entries.map((e) => e.key));\n const missingKeys = exampleKeys.filter((key) => !envKeys.has(key));\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ exists, exampleExists, entries, missingKeys }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // POST /api/env — write the full desired entry set back to .env\n if (req.method === 'POST' && pathname === '/api/env') {\n try {\n const body = await readBody(req);\n const { entries } = JSON.parse(body) as { entries?: EnvEntry[] };\n if (!Array.isArray(entries)) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'entries is required' }));\n return;\n }\n const keys = new Set<string>();\n for (const entry of entries) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(entry.key)) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: `invalid key: ${entry.key}` }));\n return;\n }\n if (keys.has(entry.key)) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: `duplicate key: ${entry.key}` }));\n return;\n }\n keys.add(entry.key);\n }\n const envPath = join(root, '.env');\n const current = await readMaybe(envPath);\n await writeFile(envPath, applyEnvEntries(current, entries));\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ ok: true }));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // GET /api/configs?name=... — read a specific config file's content\n if (req.method === 'GET' && pathname === '/api/configs') {\n const url = new URL(req.url ?? '', `http://${req.headers.host ?? 'localhost'}`);\n const name = url.searchParams.get('name');\n if (name) {\n try {\n if (!CONFIG_ALLOWLIST.includes(name)) {\n res.statusCode = 400;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'invalid config file name' }));\n return;\n }\n const content = await readMaybe(join(root, name));\n if (!content) {\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'config file not found' }));\n return;\n }\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ name, content }));\n return;\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n return;\n }\n }\n // No name param: fall through to the generic route handler for listing\n }\n\n const route = apiRoutes.find((r) => r.path === pathname);\n if (!route) {\n next();\n return;\n }\n\n try {\n const data = await route.handler(root);\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(data));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n };\n\n (handler as ApiMiddleware).agent = agent;\n return handler as ApiMiddleware;\n}\n","import { readFile, stat } from 'node:fs/promises';\nimport { type IncomingMessage, type ServerResponse, createServer } from 'node:http';\nimport { dirname, extname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createApiMiddleware } from '../app/server/api';\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n};\n\nfunction appDir(): string {\n return join(dirname(fileURLToPath(import.meta.url)), '..', 'app');\n}\n\nexport interface DevServerOptions {\n root: string;\n port: number;\n}\n\n/**\n * Serves the pre-built dashboard SPA (dist/app) plus the papercamp/ API, for an\n * installed package where there's no Vite runtime available (it's a devDependency).\n */\nexport async function startDevServer({ root, port }: DevServerOptions): Promise<void> {\n const staticDir = appDir();\n const indexPath = join(staticDir, 'index.html');\n const indexHtml = await readFile(indexPath, 'utf-8').catch(() => null);\n if (indexHtml === null) {\n throw new Error(\n `Dashboard assets not found at ${staticDir}. Run \\`pnpm build\\` (or reinstall the package) so dist/app exists.`,\n );\n }\n\n const apiMiddleware = createApiMiddleware(root);\n\n async function serveStatic(req: IncomingMessage, res: ServerResponse) {\n const pathname = decodeURIComponent((req.url ?? '/').split('?')[0]);\n const filePath = join(staticDir, pathname === '/' ? 'index.html' : pathname);\n\n try {\n const fileStat = await stat(filePath);\n if (fileStat.isFile()) {\n res.statusCode = 200;\n res.setHeader('Content-Type', MIME[extname(filePath)] ?? 'application/octet-stream');\n res.end(await readFile(filePath));\n return;\n }\n } catch {\n // not a file on disk — fall through to the SPA fallback below\n }\n\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(indexHtml);\n }\n\n const server = createServer((req, res) => {\n apiMiddleware(req, res, () => {\n serveStatic(req, res).catch((error) => {\n res.statusCode = 500;\n res.end(String(error));\n });\n });\n });\n\n const shutdown = () => {\n apiMiddleware.agent.killCurrent();\n process.exit(0);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n await new Promise<void>((resolve) => server.listen(port, resolve));\n}\n","#!/usr/bin/env node\nimport { basename, resolve } from 'node:path';\nimport { Command } from 'commander';\nimport { AlreadyInitializedError, PAPER_CAMP_VERSION, initProject } from '../core/scaffold';\nimport { appendBlock, assignPlanId, formatPlanEntry, todayDateString } from '../core/serializer';\nimport { PLAN_KINDS } from '../types/index';\nimport { startDevServer } from './dev-server';\n\nconst program = new Command();\n\nprogram\n .name('paper-camp')\n .description('Local-first, AI-native project companion.')\n .version(PAPER_CAMP_VERSION);\n\nprogram\n .command('init [project-name]')\n .description('Initialize Paper Camp in the current directory')\n .option('-i, --intent <text>', 'one-line description of what you are building')\n .action(async (projectName: string | undefined, opts: { intent?: string }) => {\n const targetDir = process.cwd();\n const name = projectName ?? basename(targetDir);\n try {\n await initProject(targetDir, { projectName: name, intent: opts.intent });\n console.log(`Initialized Paper Camp in ${targetDir}`);\n console.log(' .paper-camp/config.json');\n console.log(' papercamp/ideas.md, plans.md, progress.md, decisions.md, open-questions.md');\n } catch (error) {\n if (error instanceof AlreadyInitializedError) {\n console.error(error.message);\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n });\n\nprogram\n .command('dev')\n .description('Start the local dashboard')\n .option('-p, --port <number>', 'port to listen on', '3333')\n .action(async (opts: { port: string }) => {\n const port = Number(opts.port);\n const root = process.cwd();\n try {\n await startDevServer({ root, port });\n console.log(`Paper Camp dashboard running at http://localhost:${port}`);\n } catch (error) {\n console.error((error as Error).message);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command('add <type> [name]')\n .description('Add a new entry (currently supports: plan)')\n .option('-k, --kind <kind>', `plan kind (${PLAN_KINDS.join('|')})`, 'feat')\n .action(async (type: string, name: string | undefined, opts: { kind: string }) => {\n if (type !== 'plan') {\n console.error(`Unknown type \"${type}\". Supported types: plan`);\n process.exitCode = 1;\n return;\n }\n if (!name) {\n console.error('Usage: paper-camp add plan <name> [--kind feat|fix|chore|docs|refactor]');\n process.exitCode = 1;\n return;\n }\n if (!PLAN_KINDS.includes(opts.kind as (typeof PLAN_KINDS)[number])) {\n console.error(`Unknown kind \"${opts.kind}\". Supported kinds: ${PLAN_KINDS.join(', ')}`);\n process.exitCode = 1;\n return;\n }\n\n const kind = opts.kind;\n const configPath = resolve(process.cwd(), '.paper-camp', 'config.json');\n const id = await assignPlanId(configPath, kind);\n\n const filePath = resolve(process.cwd(), 'papercamp', 'plans.md');\n const block = formatPlanEntry({\n title: name,\n status: 'idea',\n kind,\n id,\n created: todayDateString(),\n });\n await appendBlock(filePath, block);\n console.log(`Added plan \"${name}\"${id ? ` (${id})` : ''} to papercamp/plans.md`);\n });\n\nprogram.parseAsync(process.argv);\n"],"names":["campFile","root","name","join","readMaybe","path","readFile","takeSnapshot","plansRaw","decisionsRaw","questionsRaw","progressRaw","parsePlans","parseDecisions","parseOpenQuestions","parseProgress","diffAndSynthesize","before","after","events","ts","beforePlans","p","afterPlans","title","afterP","beforeP","i","beforePhase","afterPhase","beforeDecisions","d","afterDecisions","beforeQuestions","q","afterQuestions","beforeProgress","afterProgress","date","createActivityManager","clients","snapshot","timer","files","check","next","event","data","client","file","filePath","watch","s","res","connected","buildArgs","prompt","parseLine","line","json","message","blocks","block","b","content","error","TOOL_LABELS","type","part","text","tool","input","desc","label","detail","reason","DEFAULT_AGENT_ID","AGENTS","claudeCode.buildArgs","claudeCode.parseLine","opencode.buildArgs","opencode.parseLine","TASK_KIND_TO_DEFAULT_KEY","resolveAgent","opts","agentId","defaultAgents","taskKind","key","fallback","MAX_LINES","readDefaultAgentIds","raw","readFileSync","config","DEFAULT_AGENTS","buildAgentPrompt","plan","phase","phaseIndex","createAgentManager","ensureBranch","current","broadcast","pushLine","task","setStatus","status","didTaskProgress","idea","parseIdeas","e","entries","_a","_b","finishTask","progressed","warning","attachReader","createInterface","parsed","code","err","spawnAgent","adapter","args","spawn","isBusy","launch","identity","scope","proc","start","startForPlan","startForIdea","startForIdeaExtend","stop","getStatus","createGitManager","parsePorcelain","output","x","y","rest","runGit","resolve","reject","stdout","stderr","runGitStatus","commit","kind","id","branch","currentResult","spawnSync","result","checkoutResult","refresh","gitDir","eventType","filename","srcDir","srcTimer","getCurrentBranch","getFeatureBranchPlanId","match","CHECK_COMMANDS","createStatusManager","running","queued","setResult","runCheck","cmd","runQualityFix","fileExists","stat","readBody","req","body","chunk","CONFIG_ALLOWLIST","checkBranchConflictForPlan","git","targetPlanId","activePlanId","activePlan","apiRoutes","openQuestionsRaw","decisions","openQuestions","plans","findConsistencyIssues","docNames","configNames","createApiMiddleware","activity","agent","handler","pathname","trimmed","remaining","entry","writeFile","formatPlans","planKind","PLAN_KINDS","configPath","assignPlanId","formatPlanEntry","todayDateString","appendBlock","updates","AGENT_IDS","found","updated","targetEntry","conflict","finalEntry","existing","newId","max","num","section","separator","assetsDir","mimeMap","ext","mime","dataUri","buffer","mkdir","planId","ideaId","port","projectName","defaultAgent","resolvedDefaultAgents","configWithOld","_oldAgent","configRest","envPath","examplePath","exists","exampleExists","parseEnv","exampleKeys","envKeys","missingKeys","keys","applyEnvEntries","route","r","MIME","appDir","dirname","fileURLToPath","startDevServer","staticDir","indexPath","indexHtml","apiMiddleware","serveStatic","extname","server","createServer","shutdown","program","Command","PAPER_CAMP_VERSION","targetDir","basename","initProject","AlreadyInitializedError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/app/features/plans/prompts.ts","../../src/app/server/agents/claude-code.ts","../../src/app/server/agents/opencode.ts","../../src/app/server/agents/index.ts","../../src/core/idea-status.ts","../../src/app/server/activity.ts","../../src/app/server/agent.ts","../../src/app/server/helpers.ts","../../src/app/server/agent-hooks.ts","../../src/app/server/git.ts","../../src/app/server/http.ts","../../src/app/server/routes/agent.ts","../../src/app/server/routes/config.ts","../../src/app/server/routes/docs.ts","../../src/app/server/routes/env.ts","../../src/app/features/plans/helpers.ts","../../src/app/server/commit-suggest.ts","../../src/app/server/routes/git.ts","../../src/app/server/routes/icon.ts","../../src/app/server/routes/ideas.ts","../../src/app/server/routes/plans.ts","../../src/app/server/routes/status.ts","../../src/app/server/routes/reads.ts","../../src/app/server/routes/index.ts","../../src/app/server/status.ts","../../src/app/server/api.ts","../../src/cli/dev-server.ts","../../src/cli/index.ts"],"sourcesContent":["import type { IdeaEntry, PlanEntry } from '@/types/index';\n\n// Wording notes for these prompts: all of them except buildClarifyPrompt run\n// headless (`claude -p` / `opencode run` — see server/agents/), so they must never\n// ask questions or wait for input, and each one's \"done\" condition is checked\n// mechanically by agent.ts's didTaskProgress. buildClarifyPrompt is the exception:\n// it is copied to the clipboard for the user to paste into an interactive session.\n\nexport function buildConvergenceAuditPrompt(plan: PlanEntry): string {\n const phaseList = plan.phases\n .map((phase, i) => `${i + 1}. [${phase.done ? 'x' : ' '}] ${phase.text}`)\n .join('\\n');\n\n const logList =\n plan.log && plan.log.length > 0\n ? plan.log.map((entry) => `- ${entry.date}: ${entry.text}`).join('\\n')\n : '(none)';\n\n const clarificationsList =\n plan.clarifications && plan.clarifications.length > 0\n ? plan.clarifications.map((entry) => `- ${entry.date}: ${entry.text}`).join('\\n')\n : '(none)';\n\n return `You are auditing the plan \"${plan.title}\" (${plan.id ?? 'no id'}) for missing phases. The plan is a single file at papercamp/plans/${plan.id ?? '<ID>'}.md — if it is not there, it is archived at papercamp/plans/archive/${plan.id ?? '<ID>'}.md. Edit only that file.\n\nPlan body: ${plan.body}\n\nCurrent phases:\n${phaseList}\n\nLog entries (issues, bugs, and review notes recorded so far):\n${logList}\n\nClarifications (answered scope/design questions):\n${clarificationsList}\n\nTask:\n1. Read the plan above, then inspect the relevant code in this repo.\n2. Identify work that is clearly required to fulfil this plan but is covered by no existing phase. The Log entries are the best source — they often record bugs or gaps that were never turned into phases.\n3. If you found missing work: append one \\`- [ ] <short phase title>\\` line per item at the end of the \\`### Phases\\` list. You may add detail below a checkbox line as continuation lines indented with 6 spaces. Then append exactly one line to the \\`### Log\\` section, formatted \\`- YYYY-MM-DD: <what was found and appended>\\`, creating that section after the Phases list if it does not exist.\n4. If nothing is missing: make no edits at all — no Log line, no empty heading, no \"nothing found\" note. This audit re-runs regularly and must leave no trace when there is nothing to add.\n\nRules:\n- Never modify, reorder, check, uncheck, or delete any existing line, even if it looks stale, wrong, or redundant.\n- Never touch the YAML frontmatter.\n- Append only: new unchecked phases at the end of the list, plus the single Log line.`;\n}\n\nexport function buildReconcilePrompt(plan: PlanEntry): string {\n const phaseList = plan.phases\n .map((phase, i) => `${i + 1}. [${phase.done ? 'x' : ' '}] ${phase.text}`)\n .join('\\n');\n\n return `You are reconciling the plan \"${plan.title}\" (${plan.id ?? 'no id'}), stored as a single file at papercamp/plans/${plan.id ?? '<ID>'}.md — if it is not there, it is archived at papercamp/plans/archive/${plan.id ?? '<ID>'}.md. Edit only that file.\n\nPlan body: ${plan.body}\n\nCurrent phases:\n${phaseList}\n\nTask: this plan has drifted from the codebase — some phase descriptions and body prose may reference file paths that moved, code symbols that were renamed or removed, or approaches that were superseded during implementation. Find and fix only that drift.\n\n1. Read the plan above, then inspect the relevant code in this repo to find what has actually changed since the prose was written.\n2. Reword only the sentences or phrases that are now stale: fix references and superseded approaches. Leave everything else byte-identical.\n3. Do not summarize, restructure, or \"improve\" prose that is still accurate — an unnecessary rewrite is a failure of this task, not a bonus.\n\nHard guardrails, never violate these:\n- Never touch the YAML frontmatter (id, title, kind, status, created, idea, tags, or any other field).\n- Never un-check, check, delete, or reorder any phase line, checked or unchecked.\n- Never add or remove phases.\n- Never touch the Log or Clarifications sections.\n- If nothing is stale, make no edits at all.`;\n}\n\nexport function buildIdeaExtendPrompt(idea: IdeaEntry): string {\n return `You are expanding the idea ${idea.id ?? 'no id'} (\"${idea.title}\"), stored as a single file at papercamp/ideas/${idea.id ?? '<ID>'}.md. Edit only that file.\n\nCurrent idea body, in full:\n${idea.body}\n\nTask:\n1. Explore this codebase and find what is relevant to the idea: the files it would touch, existing helpers or patterns it should build on, and constraints visible in the code.\n2. Rewrite the idea's prose body in that file so it is concrete and actionable: name specific files and symbols, describe a workable approach, and include the architectural context you found. Keep the idea's original intent — sharpen it, do not redirect it.\n\nKeep unchanged:\n- the YAML frontmatter (id, title)\n- the \\`## ${idea.id ?? 'IDEA-N'}: ${idea.title}\\` heading line\n\nReplace everything below that heading with the improved body.`;\n}\n\nexport function buildClarifyPrompt(plan: PlanEntry): string {\n return `You are clarifying the plan \"${plan.title}\" (${plan.id ?? 'no id'}), stored as a single file at papercamp/plans/${plan.id ?? '<ID>'}.md (or papercamp/plans/archive/${plan.id ?? '<ID>'}.md if archived). Edit only that file, and within it only the \\`### Clarifications\\` section.\n\nPlan body: ${plan.body}\n\nCurrent phases:\n${plan.phases.length > 0 ? plan.phases.map((p, i) => `${i + 1}. [${p.done ? 'x' : ' '}] ${p.text}`).join('\\n') : '(none yet)'}\n\nTask: surface the plan's most important unanswered questions and get them answered by the user, one at a time.\n\n1. Check the plan for gaps in: functional scope, data model, UX flow, non-functional requirements, edge cases, terminology, and completion criteria.\n2. Pick the gaps that would most change the implementation — at most 5. If the plan has no meaningful gaps, say so and stop; do not invent questions.\n3. Ask the user one question at a time. With each question, propose an answer marked **Recommended:** so the user can accept it with a single word. Wait for the user's reply before asking the next question.\n4. After each answered question, append one line to the plan file's \\`### Clarifications\\` section, creating the section between the body and \\`### Phases\\` if it does not exist:\n\n\\`\\`\\`\n- YYYY-MM-DD: Q: <question> → A: <the user's answer>\n\\`\\`\\`\n\nRules:\n- Record only answers the user actually gave (accepting your recommendation counts).\n- Append only — never rewrite or delete existing Clarifications lines.\n- Use today's date.`;\n}\n\nexport function buildPlanDraftPrompt(idea: IdeaEntry, otherPlans: PlanEntry[]): string {\n const openPlans = otherPlans.filter((p) => p.status !== 'done');\n const plansContext = openPlans.length\n ? openPlans\n .map((p) => {\n const phaseList = p.phases\n .map((ph) => ` - [${ph.done ? 'x' : ' '}] ${ph.text}`)\n .join('\\n');\n return `### ${p.id ?? 'no id'}: ${p.title} (status: ${p.status}${p.idea ? `, idea: ${p.idea}` : ''})\n${p.body}\n${phaseList || ' (no phases yet)'}`;\n })\n .join('\\n\\n')\n : '(no other open plans exist yet)';\n\n return `You are drafting a new plan from an idea: ${idea.id ?? 'no id'} (\"${idea.title}\"), stored at papercamp/ideas/${idea.id ?? '<ID>'}.md.\n\nIdea body, in full:\n${idea.body}\n\n## Plan file shape (see papercamp/about.md)\n\nEach plan is its own file at \\`papercamp/plans/<KIND>-<N>.md\\` (the file name is the plan's id). It has YAML frontmatter, a free-prose body, then a \\`### Phases\\` checklist:\n\n\\`\\`\\`\n---\nid: <KIND>-<N>\ntitle: <Short headline>\nkind: feat | fix | chore | docs | refactor\nstatus: idea\ncreated: <today, YYYY-MM-DD>\nidea: ${idea.id ?? 'IDEA-N'}\ntags:\n - app\n - agent\n---\n\nOne or two paragraphs of free prose giving context — what this is and why,\nin the same voice as the plans shown below.\n\n### Phases\n- [ ] Short phase title\n Optional description of the phase, indented with 6 spaces.\n\\`\\`\\`\n\nField rules:\n- \\`title\\`: a short verb-led headline, 2-6 words.\n- \\`kind\\`: the Conventional Commits type that best fits this idea (most are \\`feat\\`). It determines the ID prefix.\n- \\`id\\`: read \\`nextId.<kind>\\` from \\`papercamp/config.json\\` (e.g. \\`nextId.feat\\`), use that number as \\`<KIND>-<N>\\`, and write the incremented counter back to config.json. Never derive the number by scanning existing plan files for the highest one — a deleted plan's number must never be reused.\n- \\`idea\\`: exactly \\`${idea.id ?? \"this idea's id\"}\\`. This backlink is how the dashboard (and this task's own success check) finds the plan you wrote — without it the draft counts as failed.\n- \\`status\\`: exactly \\`idea\\`, never anything further along. Drafts land in the Backlog and a human promotes them from there (per papercamp/decisions.md, \"Plan-drafting agent writes directly, same as phase execution\").\n- \\`tags\\`: 1-4 short subsystem tags that fit the idea (the example values above are placeholders).\n- Phases: actionable steps a future agent or human could pick up one at a time — match the granularity of the phases in the plans shown below, not one giant phase.\n\n## Every other open (non-done) plan, for scope context\n\n${plansContext}\n\n## What to do\n\n1. Read \\`papercamp/config.json\\` and take the current \\`nextId.<kind>\\` value for your chosen kind.\n2. Create exactly one new file, \\`papercamp/plans/<KIND>-<N>.md\\`, in the shape above.\n3. Write the incremented counter back to \\`papercamp/config.json\\`.\n\nUse the open plans above only to avoid duplicating an in-flight plan's scope and to match phase granularity. Never create, edit, move, or rename any other plan file, and never write to the legacy monolithic file \\`papercamp/plans.md\\` — it is unused under per-file storage.`;\n}\n","import type { AgentRunOptions } from '../../../types/index';\n\nexport interface ParsedAgentLine {\n text: string;\n done?: boolean;\n error?: boolean;\n}\n\nexport function buildArgs(prompt: string, opts?: AgentRunOptions): string[] {\n const args = [\n '-p',\n prompt,\n '--output-format',\n 'stream-json',\n '--verbose',\n '--permission-mode',\n 'auto',\n ];\n if (opts?.model) args.push('--model', opts.model);\n if (opts?.effort) args.push('--effort', opts.effort);\n return args;\n}\n\n/**\n * Shape confirmed by a live `claude -p ... --output-format stream-json` smoke test\n * (see decisions.md, \"Confirm Claude Code's headless stream-json shape...\"), not guessed\n * from --help. Unknown subtypes fall through to a generic status line rather than being\n * dropped or throwing, since new bookkeeping subtypes (e.g. thinking_tokens) can appear.\n */\nexport function parseLine(line: string): ParsedAgentLine | null {\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(line);\n } catch {\n return null;\n }\n\n switch (json.type) {\n case 'system': {\n if (json.subtype === 'init') {\n return { text: 'Agent session started' };\n }\n if (json.subtype === 'post_turn_summary' && typeof json.status_detail === 'string') {\n return { text: json.status_detail };\n }\n return null;\n }\n case 'rate_limit_event':\n return null;\n case 'assistant': {\n const message = json.message as { content?: unknown[] } | undefined;\n const blocks = message?.content ?? [];\n for (const block of blocks) {\n const b = block as { type?: string; name?: string; text?: string };\n if (b.type === 'tool_use') {\n return { text: `Running ${b.name ?? 'a tool'}…` };\n }\n if (b.type === 'text' && typeof b.text === 'string' && b.text.trim()) {\n return { text: b.text.trim() };\n }\n }\n return null;\n }\n case 'user': {\n const message = json.message as { content?: unknown[] } | undefined;\n const content = message?.content;\n const block = Array.isArray(content) ? (content[0] as Record<string, unknown>) : undefined;\n if (block?.is_error) {\n const text = typeof block.content === 'string' ? block.content : 'Tool call failed';\n return { text: `Error: ${text}`, error: true };\n }\n return { text: 'Tool finished' };\n }\n case 'result': {\n const error = Boolean(json.is_error);\n const result = typeof json.result === 'string' ? json.result.trim() : '';\n const text = result || (error ? 'Agent run failed' : 'Agent run finished');\n return { text, done: true, error };\n }\n default:\n return { text: 'Agent is working…' };\n }\n}\n","import type { AgentRunOptions } from '../../../types/index';\nimport type { ParsedAgentLine } from './claude-code';\n\nexport function buildArgs(prompt: string, opts?: AgentRunOptions): string[] {\n const args = ['run', prompt, '--format', 'json'];\n if (opts?.model) args.push('-m', opts.model);\n if (opts?.effort) args.push('--variant', opts.effort);\n return args;\n}\n\nconst TOOL_LABELS: Record<string, string> = {\n bash: 'Running command',\n read: 'Reading file',\n edit: 'Editing file',\n write: 'Writing file',\n glob: 'Searching files',\n grep: 'Searching code',\n websearch: 'Searching web',\n webfetch: 'Fetching URL',\n question: 'Asking for input',\n};\n\nexport function parseLine(line: string): ParsedAgentLine | null {\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(line);\n } catch {\n return null;\n }\n\n const type = json.type as string | undefined;\n const part = json.part as Record<string, unknown> | undefined;\n\n if (!type || !part) return null;\n\n switch (type) {\n case 'step_start':\n return null;\n case 'text': {\n const text = part.text as string | undefined;\n if (text?.trim()) return { text: text.trim() };\n return null;\n }\n case 'tool_use': {\n const tool = part.tool as string | undefined;\n const input = part.state ? (part.state as Record<string, unknown>).input : undefined;\n const desc = input ? (input as Record<string, unknown>).description : undefined;\n const label = tool ? TOOL_LABELS[tool] : 'Running tool';\n const detail = typeof desc === 'string' && desc.trim() ? `: ${desc.trim()}` : '';\n return tool ? { text: `${label}${detail}…` } : null;\n }\n case 'step_finish': {\n const reason = part.reason as string | undefined;\n const text = reason === 'tool-calls' ? null : reason === 'stop' ? 'Done' : 'Step finished';\n if (!text) return null;\n return { text };\n }\n default:\n return null;\n }\n}\n","import { AGENT_OPTIONS } from '../../../types/index';\nimport type {\n AgentId,\n AgentOptionsDescriptor,\n AgentRunOptions,\n DefaultAgentsMap,\n TaskKind,\n} from '../../../types/index';\nimport * as claudeCode from './claude-code';\nimport type { ParsedAgentLine } from './claude-code';\nimport * as opencode from './opencode';\n\nexport interface AgentAdapter {\n command: string;\n buildArgs: (prompt: string, opts?: AgentRunOptions) => string[];\n parseLine: (line: string) => ParsedAgentLine | null;\n options: AgentOptionsDescriptor;\n}\n\nexport const DEFAULT_AGENT_ID: AgentId = 'claude-code';\n\nexport const AGENTS: Record<AgentId, AgentAdapter> = {\n 'claude-code': {\n command: 'claude',\n buildArgs: claudeCode.buildArgs,\n parseLine: claudeCode.parseLine,\n options: AGENT_OPTIONS['claude-code'],\n },\n opencode: {\n command: 'opencode',\n buildArgs: opencode.buildArgs,\n parseLine: opencode.parseLine,\n options: AGENT_OPTIONS.opencode,\n },\n};\n\nconst TASK_KIND_TO_DEFAULT_KEY: Record<TaskKind, keyof DefaultAgentsMap> = {\n phase: 'phase',\n audit: 'phase',\n 'batch-audit': 'phase',\n 'run-all': 'phase',\n sync: 'phase',\n reconcile: 'phase',\n draft: 'planDraft',\n extend: 'ideaExtend',\n 'commit-suggest': 'commitSuggest',\n};\n\nexport function resolveAgent(opts: {\n agentId?: AgentId;\n defaultAgents?: DefaultAgentsMap;\n taskKind?: TaskKind;\n}): { id: AgentId; adapter: AgentAdapter } & AgentRunOptions {\n const { agentId, defaultAgents, taskKind } = opts;\n if (agentId && agentId in AGENTS) return { id: agentId, adapter: AGENTS[agentId] };\n if (taskKind && defaultAgents) {\n const key = TASK_KIND_TO_DEFAULT_KEY[taskKind];\n const fallback = defaultAgents[key];\n if (fallback) {\n const id = fallback.agent;\n if (id in AGENTS) {\n return { id, adapter: AGENTS[id], model: fallback.model, effort: fallback.effort };\n }\n }\n }\n return { id: DEFAULT_AGENT_ID, adapter: AGENTS[DEFAULT_AGENT_ID] };\n}\n","import type { IdeaEntry, PlanEntry } from '../types/index';\n\n/**\n * Pure, no I/O — kept out of parser.ts so client-bundled importers (e.g.\n * app-store.ts) don't pull in parser.ts's Node-only file-reading code.\n */\nexport function deriveIdeaStatuses(ideas: IdeaEntry[], plans: PlanEntry[]): IdeaEntry[] {\n return ideas.map((idea) => {\n if (!idea.id) {\n return { ...idea, status: 'planned' };\n }\n const linkedPlans = plans.filter((p) => p.idea === idea.id);\n if (linkedPlans.length === 0) {\n return { ...idea, status: 'planned' };\n }\n const allDone = linkedPlans.every((p) => p.status === 'done' || p.status === 'dropped');\n return { ...idea, status: allDone ? 'done' : 'planned' };\n });\n}\n","import { watch } from 'node:fs';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\n\n/**\n * Live-refresh notifier over SSE. Watches the whole papercamp/ directory and\n * pushes a tick whenever anything under it changes, so connected dashboards\n * refetch.\n *\n * It deliberately does NOT synthesize a human-readable activity feed: the only\n * consumer (stack-panel.tsx) ignores the event payload and treats every tick as\n * a generic \"something changed, reload everything\" signal. Watching the\n * directory recursively covers the per-file `plans/` and `ideas/` trees (incl.\n * `plans/archive/`) as well as the monolithic `decisions.md`,\n * `open-questions.md`, and `progress.md` — replacing the old hardcoded list that\n * still pointed at the removed legacy `plans.md`.\n */\nexport type ActivityManager = ReturnType<typeof createActivityManager>;\n\nexport function createActivityManager(root: string) {\n const clients = new Set<ServerResponse>();\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n function broadcast() {\n const data = `data: ${JSON.stringify({\n message: 'changed',\n timestamp: new Date().toISOString(),\n })}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n\n try {\n // Debounced so a burst of writes (e.g. a plan file plus its regenerated\n // index.md) collapses into a single refresh tick.\n watch(join(root, 'papercamp'), { recursive: true }, () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(broadcast, 300);\n });\n } catch {\n // papercamp/ doesn't exist yet (uninitialized project) — nothing to watch.\n }\n\n return {\n subscribe(res: ServerResponse) {\n clients.add(res);\n const connected = JSON.stringify({\n message: 'Watching for changes…',\n timestamp: new Date().toISOString(),\n });\n res.write(`data: ${connected}\\n\\n`);\n res.on('close', () => clients.delete(res));\n },\n };\n}\n","import { type ChildProcess, spawn } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { readFile, stat } from 'node:fs/promises';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport { parsePlanFile } from '../../core/parser';\nimport { readAllPlanFiles, readIdeasMerged, readPlansMerged } from '../../core/readers';\nimport {\n type AgentId,\n type AgentTaskState,\n type AgentTaskStatus,\n DEFAULT_AGENTS,\n type DefaultAgentsMap,\n type IdeaEntry,\n type PaperCampConfig,\n type PhaseItem,\n type PlanEntry,\n type TaskKind,\n coerceAgentConfig,\n} from '../../types/index';\nimport { buildConvergenceAuditPrompt } from '../features/plans/prompts';\nimport { AGENTS, type AgentAdapter, resolveAgent } from './agents';\n\nconst MAX_LINES = 50;\n// Maximum wall-clock time per phase before treating it as a stall/clarifying-question hang.\nconst PHASE_TIMEOUT_MS = 30 * 60 * 1000;\n\ninterface AgentTask {\n taskKind: TaskKind;\n planTitle: string;\n planId?: string;\n // Absent for a plan-scoped task (e.g. a convergence audit spanning every phase),\n // present for a single-phase task.\n phaseIndex?: number;\n // Only set for plan-scoped tasks, to check success against: did Phases or Log grow?\n planBaseline?: { phases: number; log: number };\n // Only set for an idea-drafting task, which has neither planId nor phaseIndex since\n // the plan doesn't exist yet — success is checked by idea id instead.\n ideaId?: string;\n // For idea-extend tasks: snapshot the idea's body before launch so we can detect changes.\n ideaBodyBaseline?: string;\n // For reconcile tasks: snapshot of body + phase text before launch, since a reconcile\n // rewrites prose in place rather than growing Phases/Log like an audit does.\n reconcileBaseline?: string;\n status: AgentTaskStatus;\n agentId: AgentId;\n adapter: AgentAdapter;\n proc: ChildProcess;\n lines: string[];\n}\n\nfunction readDefaultAgentIds(root: string): DefaultAgentsMap {\n try {\n const raw = readFileSync(join(root, 'papercamp', 'config.json'), 'utf-8');\n const config = JSON.parse(raw) as Record<string, unknown> & { defaultAgent?: AgentId };\n const rawAgents = config.defaultAgents as Record<string, unknown> | undefined;\n if (rawAgents) {\n return {\n phase: coerceAgentConfig(rawAgents.phase),\n planDraft: coerceAgentConfig(rawAgents.planDraft),\n ideaExtend: coerceAgentConfig(rawAgents.ideaExtend),\n commitSuggest: coerceAgentConfig(rawAgents.commitSuggest),\n };\n }\n if (config.defaultAgent) {\n const id = config.defaultAgent;\n return {\n phase: { agent: id },\n planDraft: { agent: id },\n ideaExtend: { agent: id },\n commitSuggest: { agent: id },\n };\n }\n return DEFAULT_AGENTS;\n } catch {\n return DEFAULT_AGENTS;\n }\n}\n\ntype Result = { ok: true } | { ok: false; error: string };\n\nexport function buildAgentPrompt(plan: PlanEntry, phase: PhaseItem, phaseIndex: number): string {\n const details = phase.description ? `Phase details:\\n${phase.description}\\n\\n` : '';\n return `You are executing exactly one phase of the plan \"${plan.title}\" (${plan.id ?? 'no id'}): phase ${phaseIndex + 1}, \"${phase.text}\". The plan is a single file at papercamp/plans/${plan.id ?? '<ID>'}.md.\n\n${details}Plan context: ${plan.body}\n\nDo only this phase — do not start any other phase, even if it looks quick.\n\nWhen the work is done:\n1. In the plan file's \\`### Phases\\` list, change this phase's checkbox from \\`- [ ]\\` to \\`- [x]\\`. Do not change any other line.\n2. Add one bullet describing what you did under today's \\`## YYYY-MM-DD\\` heading at the top of progress.md (create the heading at the top if today's is not there yet — newest day stays first).\n3. If every phase in the list is now checked, set the plan's \\`status:\\` frontmatter field to \\`review\\` — never \\`done\\`; per this repo's AGENTS.md a human promotes plans to done.`;\n}\n\nexport function createAgentManager(\n root: string,\n ensureBranch: (plan: PlanEntry) => void = () => {},\n onAuditComplete?: (planId: string, gapPhases: number) => Promise<void>,\n onPhaseCommit?: (plan: PlanEntry, phase: PhaseItem, phaseIndex: number) => Promise<void>,\n onRunComplete?: (plan: PlanEntry) => Promise<void>,\n) {\n const clients = new Set<ServerResponse>();\n let current: AgentTask | null = null;\n\n function broadcast(message: string) {\n const data = `data: ${JSON.stringify({ message, timestamp: new Date().toISOString(), type: 'agent' })}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n\n function pushLine(task: AgentTask, text: string) {\n task.lines.push(text);\n if (task.lines.length > MAX_LINES) task.lines.shift();\n broadcast(text);\n }\n\n function setStatus(task: AgentTask, status: AgentTaskStatus) {\n task.status = status;\n broadcast(`agent: ${status}`);\n }\n\n async function didTaskProgress(task: AgentTask): Promise<boolean | null> {\n try {\n if (task.taskKind === 'extend') {\n const ideasDir = join(root, 'papercamp', 'ideas');\n const { entries } = await readIdeasMerged(ideasDir, join(root, 'papercamp', 'ideas.md'));\n const idea = entries.find((e) => e.id === task.ideaId);\n if (!idea) return null;\n if (task.ideaBodyBaseline === undefined) return null;\n return idea.body !== task.ideaBodyBaseline;\n }\n if (task.taskKind === 'reconcile') {\n const { entries } = await readPlansMerged(\n join(root, 'papercamp', 'plans'),\n join(root, 'papercamp', 'plans.md'),\n );\n const plan = entries.find((p: { id?: string }) => p.id === task.planId);\n if (!plan || task.reconcileBaseline === undefined) return null;\n return (\n JSON.stringify({ body: plan.body, phases: plan.phases.map((p) => p.text) }) !==\n task.reconcileBaseline\n );\n }\n const plansDir = join(root, 'papercamp', 'plans');\n const { entries } = await readPlansMerged(plansDir, join(root, 'papercamp', 'plans.md'));\n if (task.ideaId !== undefined) {\n return entries.some((p: { idea?: string }) => p.idea === task.ideaId);\n }\n const plan =\n entries.find((p: { id?: string }) => p.id === task.planId) ??\n entries.find((p: { title: string }) => p.title === task.planTitle);\n if (!plan) return null;\n if (task.phaseIndex !== undefined) {\n return plan.phases[task.phaseIndex]?.done ?? null;\n }\n if (!task.planBaseline) return null;\n return (\n plan.phases.length > task.planBaseline.phases ||\n (plan.log?.length ?? 0) > task.planBaseline.log\n );\n } catch {\n return null;\n }\n }\n\n function finishTask(task: AgentTask, error: boolean) {\n setStatus(task, error ? 'error' : 'done');\n if (error) return;\n didTaskProgress(task).then((progressed) => {\n if (current === task && progressed === false) {\n const warning =\n task.taskKind === 'extend'\n ? `Warning: agent finished but the idea body for ${task.ideaId} did not change — verify manually`\n : task.taskKind === 'reconcile'\n ? 'Warning: agent finished but the plan body and phase text did not change — verify manually'\n : task.ideaId !== undefined\n ? `Warning: agent finished but no plan linking idea: ${task.ideaId} appeared in papercamp/plans/ — verify manually`\n : task.phaseIndex !== undefined\n ? 'Warning: agent finished but did not check off this phase in the plan file — verify manually'\n : 'Warning: agent finished but appended nothing to Phases or Log — verify manually';\n pushLine(task, warning);\n }\n if (current === task && task.taskKind === 'audit' && task.planId && progressed === true) {\n onAuditComplete?.(task.planId, 0).catch(() => {});\n }\n });\n }\n\n function attachReader(task: AgentTask) {\n if (!task.proc.stdout) return;\n const rl = createInterface({ input: task.proc.stdout });\n rl.on('line', (line) => {\n if (current !== task || !line.trim()) return;\n const parsed = task.adapter.parseLine(line);\n if (!parsed) return;\n pushLine(task, parsed.text);\n if (parsed.done) {\n finishTask(task, Boolean(parsed.error));\n }\n });\n\n task.proc.on('close', (code) => {\n if (current !== task) return;\n if (task.status === 'starting' || task.status === 'running') {\n finishTask(task, code !== 0);\n } else if (task.status === 'stopping') {\n setStatus(task, 'done');\n }\n });\n\n task.proc.on('error', (err) => {\n if (current !== task) return;\n pushLine(task, `Failed to spawn agent: ${err.message}`);\n setStatus(task, 'error');\n });\n }\n\n function spawnAgent(adapter: AgentAdapter, args: string[]): ChildProcess {\n return spawn(adapter.command, args, {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n }\n\n function isBusy(): boolean {\n return current !== null && current.status !== 'done' && current.status !== 'error';\n }\n\n // Shared by start()/startForPlan()/startForIdea(): synchronous on purpose, same\n // race-avoidance reasoning as the busy-guard above — no `await` between the guard\n // check and reserving `current`.\n function launch(\n identity: { planTitle: string; planId?: string; agentOverride?: AgentId },\n prompt: string,\n scope: Pick<\n AgentTask,\n | 'taskKind'\n | 'phaseIndex'\n | 'planBaseline'\n | 'ideaId'\n | 'ideaBodyBaseline'\n | 'reconcileBaseline'\n >,\n ): Result {\n if (isBusy()) {\n return { ok: false, error: 'An agent task is already running' };\n }\n const defaultAgents = readDefaultAgentIds(root);\n const {\n id: agentId,\n adapter,\n model,\n effort,\n } = resolveAgent({\n agentId: identity.agentOverride,\n defaultAgents,\n taskKind: scope.taskKind,\n });\n const proc = spawnAgent(adapter, adapter.buildArgs(prompt, { model, effort }));\n const task: AgentTask = {\n planTitle: identity.planTitle,\n planId: identity.planId,\n status: 'starting',\n agentId,\n adapter,\n proc,\n lines: [],\n ...scope,\n };\n current = task;\n attachReader(task);\n setStatus(task, 'running');\n return { ok: true };\n }\n\n function start(plan: PlanEntry, phaseIndex: number): Result {\n if (isBusy()) {\n return { ok: false, error: 'An agent task is already running' };\n }\n const phase = plan.phases[phaseIndex];\n if (!phase) {\n return { ok: false, error: 'Phase not found' };\n }\n ensureBranch(plan);\n const prompt = buildAgentPrompt(plan, phase, phaseIndex);\n return launch({ planTitle: plan.title, planId: plan.id, agentOverride: plan.agent }, prompt, {\n taskKind: 'phase',\n phaseIndex,\n });\n }\n\n // Plan-scoped launch mode: no single phase, so success is judged by whether the\n // agent appended anything to Phases or Log rather than whether one checkbox flipped.\n // Reconcile tasks rewrite prose in place instead, so they're judged against a\n // snapshot of body + phase text rather than the Phases/Log growth baseline.\n function startForPlan(\n plan: PlanEntry,\n prompt: string,\n taskKind: 'audit' | 'reconcile' = 'audit',\n ): Result {\n return launch({ planTitle: plan.title, planId: plan.id, agentOverride: plan.agent }, prompt, {\n taskKind,\n ...(taskKind === 'reconcile'\n ? {\n reconcileBaseline: JSON.stringify({\n body: plan.body,\n phases: plan.phases.map((p) => p.text),\n }),\n }\n : { planBaseline: { phases: plan.phases.length, log: plan.log?.length ?? 0 } }),\n });\n }\n\n // Idea-drafting launch mode: there's no plan yet (and so no per-plan agent override\n // either) — the plan only exists once the agent writes it, so success is judged by\n // whether a new plan file linking this idea's id shows up in papercamp/plans/.\n function startForIdea(idea: IdeaEntry, prompt: string): Result {\n if (!idea.id) {\n return { ok: false, error: 'Idea has no id to link a drafted plan back to' };\n }\n return launch({ planTitle: `Draft plan for ${idea.id}` }, prompt, {\n taskKind: 'draft',\n ideaId: idea.id,\n });\n }\n\n // Idea-extend launch mode: given an idea, explores the codebase and rewrites its\n // body in place in its papercamp/ideas/ file. Success is judged by whether that idea's body text\n // actually changed.\n function startForIdeaExtend(idea: IdeaEntry, prompt: string): Result {\n if (!idea.id) {\n return { ok: false, error: 'Idea has no id to extend' };\n }\n return launch({ planTitle: `Extend ${idea.id}` }, prompt, {\n taskKind: 'extend',\n ideaId: idea.id,\n ideaBodyBaseline: idea.body,\n });\n }\n\n function startSync(prompt: string): Result {\n return launch({ planTitle: 'Sync to main' }, prompt, { taskKind: 'sync' });\n }\n\n async function findBatchPlanFile(plansDir: string, id: string): Promise<string | null> {\n const direct = join(plansDir, `${id}.md`);\n try {\n await stat(direct);\n return direct;\n } catch {}\n const archived = join(plansDir, 'archive', `${id}.md`);\n try {\n await stat(archived);\n return archived;\n } catch {}\n return null;\n }\n\n // Batch audit: iterate every review/done plan and run a convergence audit on each,\n // skipping plans whose \"audited\" marker is newer than the file's last modification.\n // Runs plans sequentially; updates task.proc before each spawn so stop() kills the\n // right subprocess.\n function startBatchAudit(): Result {\n if (isBusy()) {\n return { ok: false, error: 'An agent task is already running' };\n }\n const defaultAgents = readDefaultAgentIds(root);\n const {\n id: agentId,\n adapter,\n model,\n effort,\n } = resolveAgent({ defaultAgents, taskKind: 'audit' });\n\n // Stub proc — replaced per plan in the loop. Already-exited is fine: stop() sets\n // task.status = 'stopping' first; kill() on a dead process is a no-op.\n const stubProc = spawn('sh', ['-c', 'exit 0'], {\n cwd: root,\n stdio: 'ignore',\n });\n const task: AgentTask = {\n taskKind: 'batch-audit',\n planTitle: 'Batch audit',\n status: 'starting',\n agentId,\n adapter,\n proc: stubProc,\n lines: [],\n };\n current = task;\n setStatus(task, 'running');\n\n (async () => {\n try {\n const plansDir = join(root, 'papercamp', 'plans');\n const { entries } = await readAllPlanFiles(plansDir);\n const candidates = entries.filter((p) => p.status === 'review' || p.status === 'done');\n\n if (candidates.length === 0) {\n if (current === task) {\n pushLine(task, 'No plans with status \"review\" or \"done\" to audit.');\n setStatus(task, 'done');\n }\n return;\n }\n\n pushLine(task, `Auditing ${candidates.length} plan(s)…`);\n let audited = 0;\n let skipped = 0;\n let failed = 0;\n\n for (const plan of candidates) {\n if (current !== task || task.status === 'stopping') break;\n if (!plan.id) {\n skipped++;\n continue;\n }\n\n const planFile = await findBatchPlanFile(plansDir, plan.id);\n if (!planFile) {\n skipped++;\n continue;\n }\n\n if (plan.audited) {\n const fileStat = await stat(planFile).catch(() => null);\n const mtimeDate = fileStat ? fileStat.mtime.toISOString().slice(0, 10) : null;\n if (mtimeDate && plan.audited >= mtimeDate) {\n pushLine(task, `[skip] ${plan.id} — up to date`);\n skipped++;\n continue;\n }\n }\n\n pushLine(task, `[audit] ${plan.id} ${plan.title}`);\n const prompt = buildConvergenceAuditPrompt(plan);\n const proc = spawn(adapter.command, adapter.buildArgs(prompt, { model, effort }), {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n task.proc = proc;\n\n if (proc.stdout) {\n const rl = createInterface({ input: proc.stdout });\n rl.on('line', (line) => {\n if (current !== task) return;\n const parsed = adapter.parseLine(line);\n if (parsed?.text && parsed.text !== 'Agent is working…') {\n pushLine(task, ` ${parsed.text}`);\n }\n });\n }\n // Drain stderr — an unread pipe can fill and hang the subprocess.\n proc.stderr?.on('data', () => {});\n\n const success = await new Promise<boolean>((resolve) => {\n proc.on('close', (code) => resolve(code === 0));\n proc.on('error', () => resolve(false));\n });\n\n if (current !== task) return;\n\n if (success) {\n let gapPhases = 0;\n try {\n const rawAfter = await readFile(planFile, 'utf-8');\n const parsedAfter = parsePlanFile(rawAfter);\n const afterCount = parsedAfter.entries[0]?.phases.length ?? plan.phases.length;\n gapPhases = Math.max(0, afterCount - plan.phases.length);\n } catch {\n /* gapPhases stays 0 */\n }\n await onAuditComplete?.(plan.id, gapPhases);\n audited++;\n pushLine(\n task,\n gapPhases > 0\n ? `[done] ${plan.id} — ${gapPhases} gap phase${gapPhases === 1 ? '' : 's'} added`\n : `[done] ${plan.id}`,\n );\n } else {\n failed++;\n pushLine(task, `[fail] ${plan.id} — agent error`);\n }\n }\n\n if (current !== task) return;\n\n if (task.status === 'stopping') {\n setStatus(task, 'done');\n return;\n }\n\n pushLine(task, `Audit complete — ${audited} audited, ${skipped} skipped, ${failed} failed`);\n setStatus(task, failed > 0 ? 'error' : 'done');\n } catch (err) {\n if (current === task) {\n pushLine(task, `Batch audit failed: ${(err as Error).message}`);\n setStatus(task, 'error');\n }\n }\n })();\n\n return { ok: true };\n }\n\n // Run all unchecked phases sequentially, spawning a fresh agent per phase.\n // Calls ensureBranch up front, then iterates unchecked phases in order.\n // Stops on first failure; calls onPhaseCommit (wired at construction) after each verified success.\n function startRunAllPhases(plan: PlanEntry, runProjectChecks?: () => Promise<boolean>): Result {\n if (isBusy()) {\n return { ok: false, error: 'An agent task is already running' };\n }\n const unchecked = plan.phases\n .map((phase, i) => ({ phase, i }))\n .filter(({ phase }) => !phase.done);\n\n if (unchecked.length === 0) {\n return { ok: false, error: 'No unchecked phases to run' };\n }\n\n ensureBranch(plan);\n\n const defaultAgents = readDefaultAgentIds(root);\n const {\n id: agentId,\n adapter,\n model,\n effort,\n } = resolveAgent({ agentId: plan.agent, defaultAgents, taskKind: 'run-all' });\n\n const stubProc = spawn('sh', ['-c', 'exit 0'], { cwd: root, stdio: 'ignore' });\n const task: AgentTask = {\n taskKind: 'run-all',\n planTitle: plan.title,\n planId: plan.id,\n status: 'starting',\n agentId,\n adapter,\n proc: stubProc,\n lines: [],\n };\n current = task;\n setStatus(task, 'running');\n\n (async () => {\n try {\n const total = plan.phases.length;\n let completed = 0;\n let failed = 0;\n\n for (const { phase, i } of unchecked) {\n if (current !== task || task.status === 'stopping') break;\n\n // Set phaseIndex so didTaskProgress can verify the right checkbox.\n task.phaseIndex = i;\n pushLine(task, `[phase ${i + 1}/${total}] ${phase.text}`);\n\n const prompt = buildAgentPrompt(plan, phase, i);\n const proc = spawn(adapter.command, adapter.buildArgs(prompt, { model, effort }), {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n task.proc = proc;\n\n if (proc.stdout) {\n const rl = createInterface({ input: proc.stdout });\n rl.on('line', (line) => {\n if (current !== task) return;\n const parsed = adapter.parseLine(line);\n if (parsed?.text && parsed.text !== 'Agent is working…') {\n pushLine(task, ` ${parsed.text}`);\n }\n });\n }\n proc.stderr?.on('data', () => {});\n\n // Wait for the agent with a timeout so a stall or clarifying-question\n // hang is treated as a failure rather than blocking indefinitely.\n let timedOut = false;\n const procDone = new Promise<boolean>((resolve) => {\n proc.on('close', (code) => resolve(code === 0));\n proc.on('error', () => resolve(false));\n });\n const timeoutHandle = setTimeout(() => {\n timedOut = true;\n if (!proc.killed) proc.kill('SIGTERM');\n // SIGTERM can be ignored; without escalation `await procDone` never\n // resolves and this run-all task blocks the agent slot forever — same\n // reasoning as the escalation in stop().\n setTimeout(() => {\n if (proc.exitCode === null && proc.signalCode === null) {\n proc.kill('SIGKILL');\n }\n }, 5000);\n }, PHASE_TIMEOUT_MS);\n const exitedOk = await procDone;\n clearTimeout(timeoutHandle);\n\n if (current !== task) return;\n\n if (timedOut) {\n failed++;\n pushLine(\n task,\n `[timeout] phase ${i + 1} — no progress for ${PHASE_TIMEOUT_MS / 60000}min, stopping`,\n );\n break;\n }\n\n if (!exitedOk) {\n failed++;\n pushLine(task, `[fail] phase ${i + 1} — agent error, stopping`);\n break;\n }\n\n // Gate 1: did the phase checkbox actually flip?\n const progressed = await didTaskProgress(task);\n if (!progressed) {\n failed++;\n pushLine(\n task,\n progressed === null\n ? `[fail] phase ${i + 1} — could not read plan after run, stopping`\n : `[fail] phase ${i + 1} — phase checkbox did not flip, stopping`,\n );\n break;\n }\n\n // Gate 2: lint / format / test must all pass.\n if (runProjectChecks) {\n pushLine(task, `[verify] phase ${i + 1} — running lint/format/test`);\n const checksOk = await runProjectChecks();\n if (current !== task) return;\n if (!checksOk) {\n failed++;\n pushLine(task, `[fail] phase ${i + 1} — project checks failed, stopping`);\n break;\n }\n }\n\n completed++;\n if (onPhaseCommit) {\n pushLine(task, `[commit] phase ${i + 1} — ${phase.text}`);\n await onPhaseCommit(plan, phase, i);\n }\n }\n\n if (current !== task) return;\n\n if (task.status === 'stopping') {\n setStatus(task, 'done');\n return;\n }\n\n if (failed > 0) {\n pushLine(task, `Run stopped after ${completed} phase(s) completed, 1 failed`);\n setStatus(task, 'error');\n } else {\n pushLine(task, `All ${completed} phase(s) completed`);\n if (onRunComplete) {\n try {\n pushLine(task, '[review] setting plan status to review');\n await onRunComplete(plan);\n } catch (err) {\n pushLine(\n task,\n `Warning: could not set plan status to review: ${(err as Error).message}`,\n );\n }\n }\n setStatus(task, 'done');\n }\n } catch (err) {\n if (current === task) {\n pushLine(task, `Run all phases failed: ${(err as Error).message}`);\n setStatus(task, 'error');\n }\n }\n })();\n\n return { ok: true };\n }\n\n // Read-only, one-shot task: ask the configured agent to turn a diff into a commit\n // message. Uses the configured agent's binary but constructs its own arguments so it\n // never picks up the shared adapter's `--permission-mode auto` flag — this call must\n // stay deny-by-default since the model is only ever supposed to read the diff text.\n const COMMIT_SUGGEST_TIMEOUT_MS = 60_000;\n const STDIN_MAX_BYTES = 10 * 1024 * 1024;\n\n function runCommitSuggest(prompt: string): Promise<string> {\n if (isBusy()) {\n return Promise.reject(new Error('An agent task is already running'));\n }\n if (Buffer.byteLength(prompt, 'utf-8') > STDIN_MAX_BYTES) {\n return Promise.reject(new Error('Commit suggestion prompt exceeds the 10MB stdin limit'));\n }\n const defaultAgents = readDefaultAgentIds(root);\n const {\n id: agentId,\n adapter,\n model,\n effort,\n } = resolveAgent({\n defaultAgents,\n taskKind: 'commit-suggest',\n });\n\n const isClaude = agentId === 'claude-code';\n const args = isClaude ? ['-p', '--output-format', 'json'] : ['run', '--format', 'json'];\n if (model) args.push(isClaude ? '--model' : '-m', model);\n if (effort) args.push(isClaude ? '--effort' : '--variant', effort);\n\n return new Promise((resolve, reject) => {\n const proc = spawn(adapter.command, args, {\n cwd: root,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const task: AgentTask = {\n taskKind: 'commit-suggest',\n planTitle: 'Suggest commit message',\n status: 'starting',\n agentId,\n adapter,\n proc,\n lines: [],\n };\n current = task;\n setStatus(task, 'running');\n\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n fn();\n };\n const timeout = setTimeout(() => {\n settle(() => {\n if (current === task) {\n pushLine(task, 'Commit suggestion timed out');\n setStatus(task, 'error');\n if (!proc.killed) proc.kill('SIGTERM');\n }\n reject(new Error('Commit suggestion timed out'));\n });\n }, COMMIT_SUGGEST_TIMEOUT_MS);\n\n proc.stdin?.on('error', () => {});\n proc.stdin?.write(prompt);\n proc.stdin?.end();\n\n let stdout = '';\n let stderr = '';\n proc.stdout?.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n proc.stderr?.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n proc.on('close', (code) => {\n if (current !== task) return;\n settle(() => {\n if (task.status === 'stopping') {\n setStatus(task, 'done');\n reject(new Error('Stopped'));\n return;\n }\n if (code === 0) {\n setStatus(task, 'done');\n // opencode outputs JSON events — extract text content to find the response.\n const result = isClaude\n ? stdout\n : stdout\n .split('\\n')\n .map((line) => {\n try {\n const evt = JSON.parse(line);\n if (evt?.type === 'text' && evt?.part?.text) return evt.part.text;\n } catch {}\n return null;\n })\n .filter(Boolean)\n .join('\\n');\n resolve(result);\n } else {\n const errText = stderr || `${adapter.command} exited with code ${code}`;\n pushLine(task, errText);\n setStatus(task, 'error');\n reject(new Error(errText));\n }\n });\n });\n proc.on('error', (err) => {\n if (current !== task) return;\n settle(() => {\n pushLine(task, `Failed to spawn agent: ${err.message}`);\n setStatus(task, 'error');\n reject(err);\n });\n });\n });\n }\n\n function stop(): Result {\n if (!current) {\n return { ok: false, error: 'No agent task running' };\n }\n const task = current;\n setStatus(task, 'stopping');\n if (!task.proc.killed) task.proc.kill('SIGTERM');\n // SIGTERM can be ignored or delayed indefinitely; without this escalation a hung\n // process leaves `current` stuck in 'stopping' forever, permanently blocking start().\n setTimeout(() => {\n if (current === task && task.status === 'stopping') {\n task.proc.kill('SIGKILL');\n }\n }, 5000);\n return { ok: true };\n }\n\n function getStatus(): AgentTaskState | null {\n if (!current) return null;\n return {\n status: current.status,\n taskKind: current.taskKind,\n planTitle: current.planTitle,\n planId: current.planId,\n phaseIndex: current.phaseIndex,\n ideaId: current.ideaId,\n agentId: current.agentId,\n lines: [...current.lines],\n };\n }\n\n return {\n start,\n startForPlan,\n startForIdea,\n startForIdeaExtend,\n startBatchAudit,\n startRunAllPhases,\n startSync,\n runCommitSuggest,\n stop,\n getStatus,\n subscribe(res: ServerResponse) {\n clients.add(res);\n res.on('close', () => clients.delete(res));\n },\n killCurrent() {\n if (current?.proc && !current.proc.killed) {\n current.proc.kill();\n }\n },\n };\n}\n\nexport interface AgentManager {\n start: (plan: PlanEntry, phaseIndex: number) => Result;\n startForPlan: (plan: PlanEntry, prompt: string, taskKind?: 'audit' | 'reconcile') => Result;\n startForIdea: (idea: IdeaEntry, prompt: string) => Result;\n startForIdeaExtend: (idea: IdeaEntry, prompt: string) => Result;\n startBatchAudit: () => Result;\n startRunAllPhases: (plan: PlanEntry, runProjectChecks?: () => Promise<boolean>) => Result;\n startSync: (prompt: string) => Result;\n runCommitSuggest: (prompt: string) => Promise<string>;\n stop: () => Result;\n getStatus: () => AgentTaskState | null;\n subscribe: (res: ServerResponse) => void;\n killCurrent: () => void;\n}\n","import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { deriveIdeaStatuses } from '../../core/idea-status';\nimport { readIdeasMerged, readPlansMerged } from '../../core/readers';\nimport { formatIdeasIndex, formatPlanFile, formatPlansIndex } from '../../core/serializer';\nimport type { BranchHygieneStatus, PlanEntry } from '../../types/index';\n\nexport async function readMaybe(path: string): Promise<string> {\n try {\n return await readFile(path, 'utf-8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return '';\n throw error;\n }\n}\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport const campFile = (root: string, name: string) => join(root, 'papercamp', name);\n\nexport type PlanFileInput = Parameters<typeof formatPlanFile>[0];\n\n/**\n * Serializer input for re-writing an existing plan file: carries every field of the\n * parsed entry so a partial update can't silently drop idea backlinks, agent\n * overrides, or tags, with `overrides` applied on top.\n */\nexport function planFileInput(\n entry: PlanEntry,\n overrides: Partial<PlanFileInput> = {},\n): PlanFileInput {\n return {\n id: entry.id ?? '',\n title: entry.title,\n kind: entry.kind ?? 'feat',\n status: entry.status,\n idea: entry.idea,\n agent: entry.agent,\n created: entry.created,\n updated: entry.updated,\n audited: entry.audited,\n tags: entry.tags,\n body: entry.body,\n phases: entry.phases,\n log: entry.log,\n clarifications: entry.clarifications,\n ...overrides,\n };\n}\n\nexport async function writePlanFile(path: string, input: PlanFileInput): Promise<void> {\n await writeFile(path, `${formatPlanFile(input)}\\n`, 'utf-8');\n}\n\nexport async function regenerateIndexes(root: string): Promise<void> {\n const plansDir = campFile(root, 'plans');\n const ideasDir = campFile(root, 'ideas');\n\n const [plansResult, ideasResult] = await Promise.all([\n readPlansMerged(plansDir, campFile(root, 'plans.md')),\n readIdeasMerged(ideasDir, campFile(root, 'ideas.md')),\n ]);\n\n const ideasWithStatus = deriveIdeaStatuses(ideasResult.entries, plansResult.entries);\n\n await mkdir(plansDir, { recursive: true });\n await mkdir(ideasDir, { recursive: true });\n\n await Promise.all([\n writeFile(join(plansDir, 'index.md'), formatPlansIndex(plansResult.entries)),\n writeFile(join(ideasDir, 'index.md'), formatIdeasIndex(ideasWithStatus)),\n ]);\n}\n\nexport async function checkBranchConflictForPlan(\n root: string,\n git: {\n getFeatureBranchPlanId: () => string | null;\n getBranchHygieneStatus: () => Promise<BranchHygieneStatus>;\n },\n targetPlanId?: string,\n): Promise<string | null> {\n const activePlanId = git.getFeatureBranchPlanId();\n // Working on the current branch's own plan (e.g. running its phases) is always\n // allowed — this must come before any hygiene/other check so you can never be\n // blocked from advancing the plan you're already on.\n if (targetPlanId && activePlanId === targetPlanId) return null;\n // Not on a feature branch (on main, etc.) — nothing to finish first.\n if (!activePlanId) return null;\n\n // Only relevant when starting a *different* plan than the one this branch is for.\n const hygiene = await git.getBranchHygieneStatus();\n if (hygiene === 'stale-merged') {\n return \"You're on a merged branch — switch to main before starting another plan\";\n }\n\n const plansDir = campFile(root, 'plans');\n const { entries } = await readPlansMerged(plansDir, campFile(root, 'plans.md'));\n const activePlan = entries.find((p) => p.id === activePlanId);\n if (!activePlan || activePlan.status === 'done' || activePlan.status === 'dropped') return null;\n return `Finish \\`${activePlanId}\\` — ${activePlan.title} — before starting another plan`;\n}\n","import { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parsePlanFile } from '../../core/parser';\nimport { todayDateString } from '../../core/serializer';\nimport type { PhaseItem, PlanEntry } from '../../types/index';\nimport type { GitManager } from './git';\nimport { campFile, fileExists, planFileInput, readMaybe, writePlanFile } from './helpers';\n\n/**\n * Callbacks the agent manager invokes as tasks progress: stamping audit dates,\n * committing per-phase work, and handing a finished run over to review. Kept out of\n * api.ts so the middleware only wires managers together.\n */\nexport function createAgentHooks(root: string, git: GitManager) {\n async function prependProgressItem(item: string): Promise<void> {\n const progressPath = campFile(root, 'progress.md');\n const today = todayDateString();\n const heading = `## ${today}`;\n const raw = await readMaybe(progressPath);\n if (raw.startsWith(`${heading}\\n`)) {\n await writeFile(\n progressPath,\n `${heading}\\n- ${item}\\n${raw.slice(heading.length + 1)}`,\n 'utf-8',\n );\n } else {\n const trimmed = raw.trimEnd();\n const next = trimmed ? `${heading}\\n- ${item}\\n\\n${trimmed}\\n` : `${heading}\\n- ${item}\\n`;\n await writeFile(progressPath, next, 'utf-8');\n }\n }\n\n async function stampAuditDate(planId: string, gapPhases: number): Promise<void> {\n const plansDir = campFile(root, 'plans');\n // Batch audit can touch archived (done/dropped) plans too — resolve the\n // actual file so those get stamped instead of re-audited every run.\n const directPlanFile = join(plansDir, `${planId}.md`);\n const archivedPlanFile = join(plansDir, 'archive', `${planId}.md`);\n const planFile = (await fileExists(directPlanFile))\n ? directPlanFile\n : (await fileExists(archivedPlanFile))\n ? archivedPlanFile\n : null;\n if (!planFile) return;\n const raw = await readMaybe(planFile);\n if (!raw) return;\n const parsed = parsePlanFile(raw);\n if (parsed.entries.length === 0) return;\n const entry = parsed.entries[0];\n await writePlanFile(planFile, planFileInput(entry, { id: planId, audited: todayDateString() }));\n if (gapPhases > 0) {\n const label = `gap phase${gapPhases === 1 ? '' : 's'}`;\n await prependProgressItem(\n `Batch audit of ${planId} (${entry.title}) — ${gapPhases} ${label} appended`,\n );\n }\n }\n\n async function commitPhase(plan: PlanEntry, phase: PhaseItem): Promise<void> {\n const area = plan.tags?.[0] ?? 'plans';\n const title = `${plan.kind ?? 'feat'}(${area}): ${phase.text}`;\n const refs = plan.id ? `Refs: ${plan.id}` : undefined;\n await git.stageAll();\n await git.commit([], title, refs);\n }\n\n async function setRunReview(plan: PlanEntry): Promise<void> {\n if (!plan.id) return;\n const plansDir = campFile(root, 'plans');\n const planFile = join(plansDir, `${plan.id}.md`);\n const raw = await readMaybe(planFile);\n if (!raw) return;\n const parsed = parsePlanFile(raw);\n if (parsed.entries.length === 0) return;\n const entry = parsed.entries[0];\n if (entry.status === 'review' || entry.status === 'done' || entry.status === 'dropped') return;\n await writePlanFile(\n planFile,\n planFileInput(entry, {\n id: entry.id ?? plan.id,\n status: 'review',\n updated: todayDateString(),\n }),\n );\n const area = plan.tags?.[0] ?? 'plans';\n const refs = plan.id ? `Refs: ${plan.id}` : undefined;\n await git.stageAll();\n await git.commit([], `${entry.kind ?? 'feat'}(${area}): mark ${plan.id} review`, refs);\n }\n\n return { stampAuditDate, commitPhase, setRunReview };\n}\n","import { spawn, spawnSync } from 'node:child_process';\nimport { watch } from 'node:fs';\nimport { lstat, readFile } from 'node:fs/promises';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport type { BranchHygieneStatus, GitStatusEntry, PlanEntry } from '../../types';\n\nconst AI_DIFF_BLOCKLIST = [/(^|\\/)\\.env(\\.|$)/i, /\\.(pem|key|p12|crt)$/i];\n\n// Git expands pathspec magic (e.g. `:/`) even after `--`, which can broaden a\n// command beyond the caller-selected files. Force every API-supplied path to be\n// treated literally so selections can't widen to unrelated files.\nconst toLiteralPathspec = (file: string) => `:(literal)${file}`;\n\nexport type GitManager = ReturnType<typeof createGitManager>;\n\nexport interface GitManagerOptions {\n /**\n * Start the recursive fs watchers on `.git/` and `src/` that push live status\n * ticks to SSE subscribers. Defaults to true; tests disable it because Node's\n * recursive-watch fallback crashes uncatchably when a watched tree is deleted\n * (e.g. a temp repo being cleaned up), and the watchers live for the process\n * lifetime with no close handle.\n */\n watch?: boolean;\n}\n\nexport function createGitManager(root: string, options: GitManagerOptions = {}) {\n const clients = new Set<ServerResponse>();\n\n function broadcast(event: { message: string; timestamp: string }) {\n const data = `data: ${JSON.stringify(event)}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n\n function parsePorcelain(output: string): GitStatusEntry[] {\n const entries: GitStatusEntry[] = [];\n for (const line of output.split('\\n')) {\n if (!line.trim()) continue;\n const x = line[0] ?? ' ';\n const y = line[1] ?? ' ';\n const rest = line.slice(3);\n const parts = rest.split(' -> ');\n const path = parts.pop() ?? rest;\n entries.push({\n path,\n status: `${x}${y}`,\n staged: x !== ' ' && x !== '?',\n renameSource: (x === 'R' || x === 'C') && parts.length > 0 ? parts[0] : undefined,\n });\n }\n return entries;\n }\n\n function runGit(args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n // quotepath=off keeps non-ASCII paths (e.g. Cyrillic filenames) as raw UTF-8 in\n // porcelain output instead of octal-escaped quoted strings the parser would\n // pass through garbled, breaking every downstream pathspec.\n const proc = spawn('git', ['-c', 'core.quotepath=off', ...args], {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stdout = '';\n let stderr = '';\n proc.stdout?.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n proc.stderr?.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n proc.on('close', (code) => {\n if (code === 0) {\n resolve(stdout);\n } else {\n reject(new Error(stderr || `git ${args[0]} exited with code ${code}`));\n }\n });\n proc.on('error', reject);\n });\n }\n\n function runGitStatus(): Promise<GitStatusEntry[]> {\n return runGit(['status', '--porcelain=v1']).then(parsePorcelain);\n }\n\n async function commit(files: string[], title: string, message?: string): Promise<void> {\n let renameSources = new Map<string, string>();\n if (files.length > 0) {\n const statusEntries = await runGitStatus();\n const statusByPath = new Map(statusEntries.map((e) => [e.path, e.status]));\n renameSources = new Map(\n statusEntries\n .filter((e): e is GitStatusEntry & { renameSource: string } => !!e.renameSource)\n .map((e) => [e.path, e.renameSource]),\n );\n // Files already fully staged (no pending worktree change) have nothing left for\n // `git add` to match — passing them anyway makes git fail with \"did not match any files\".\n const toAdd = files.filter((f) => {\n const status = statusByPath.get(f);\n return status === undefined || status[1] !== ' ';\n });\n if (toAdd.length > 0) {\n await runGit(['add', '--', ...toAdd.map(toLiteralPathspec)]);\n }\n }\n const args = ['commit', '-m', title];\n if (message) args.push('-m', message);\n // Restrict the commit to the selected files so unrelated already-staged\n // paths aren't swept in; an empty selection falls through to \"commit\n // whatever's staged\", which is the intended behavior for that case.\n if (files.length > 0) {\n // A staged rename spans two paths. Restricting the commit to the new path alone\n // records the add but leaves the old path's staged deletion behind — HEAD ends\n // up with both files. Include the rename source so the deletion lands too.\n const pathspecs = files.flatMap((f) => {\n const source = renameSources.get(f);\n return source ? [f, source] : [f];\n });\n args.push('--', ...pathspecs.map(toLiteralPathspec));\n }\n await runGit(args);\n }\n\n function ensureBranch(plan: PlanEntry): void {\n if (!plan.kind || !plan.id) return;\n\n const kind = plan.kind.toLowerCase();\n const id = plan.id.toLowerCase();\n const title = plan.title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n const branch = `${kind}/${id}-${title}`;\n\n const currentResult = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: root });\n if (currentResult.status !== 0) {\n throw new Error(\n currentResult.stderr.toString().trim() || 'Unable to read current git branch',\n );\n }\n const currentBranch = currentResult.stdout.toString().trim();\n if (currentBranch === branch) return;\n\n const result = spawnSync('git', ['checkout', '-b', branch, 'main'], { cwd: root });\n if (result.status !== 0) {\n // Branch already exists — just check it out\n const checkoutResult = spawnSync('git', ['checkout', branch], { cwd: root });\n if (checkoutResult.status !== 0) {\n throw new Error(\n checkoutResult.stderr.toString().trim() ||\n result.stderr.toString().trim() ||\n `Unable to check out ${branch}`,\n );\n }\n }\n }\n\n async function refresh() {\n try {\n await runGitStatus();\n broadcast({\n message: 'Working tree status updated',\n timestamp: new Date().toISOString(),\n });\n } catch {\n // git not available or not a repo\n }\n }\n\n if (options.watch !== false) {\n const gitDir = join(root, '.git');\n let timer: ReturnType<typeof setTimeout> | null = null;\n try {\n watch(gitDir, { recursive: true }, (eventType, filename) => {\n if (filename === 'index') {\n if (timer) clearTimeout(timer);\n timer = setTimeout(refresh, 500);\n }\n });\n } catch {\n // watcher not available\n }\n\n const srcDir = join(root, 'src');\n let srcTimer: ReturnType<typeof setTimeout> | null = null;\n try {\n watch(srcDir, { recursive: true }, () => {\n if (srcTimer) clearTimeout(srcTimer);\n srcTimer = setTimeout(refresh, 500);\n });\n } catch {\n // src/ doesn't exist or watcher not available\n }\n }\n\n async function hasUpstream(): Promise<boolean> {\n try {\n await runGit(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}']);\n return true;\n } catch {\n return false;\n }\n }\n\n // Counts commits on HEAD not yet on the upstream branch. When no upstream is\n // configured (e.g. a fresh branch that's never been pushed), every local commit\n // not reachable from any remote-tracking branch counts as ahead.\n async function getAheadCount(): Promise<number> {\n try {\n const args = (await hasUpstream())\n ? ['rev-list', '--count', '@{u}..HEAD']\n : ['rev-list', '--count', 'HEAD', '--not', '--remotes'];\n const output = await runGit(args);\n return Number.parseInt(output.trim(), 10) || 0;\n } catch {\n return 0;\n }\n }\n\n async function push(): Promise<void> {\n if (await hasUpstream()) {\n await runGit(['push']);\n } else {\n await runGit(['push', '--set-upstream', 'origin', getCurrentBranch()]);\n }\n }\n\n function getCurrentBranch(): string {\n const result = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: root });\n return result.stdout.toString().trim();\n }\n\n async function isMergedIntoMain(): Promise<boolean> {\n const currentBranch = getCurrentBranch();\n if (currentBranch === 'main' || currentBranch === 'master') return false;\n\n try {\n // Merged status only — the upstream check lives in getBranchHygieneStatus so\n // it can tell 'stale-merged' apart from 'stale-no-upstream'. Conflating them\n // here missed the common case: a pushed branch merged via PR (still has an\n // upstream) would never report 'stale-merged'.\n const mergedBranches = await runGit(['branch', '--merged', 'main']);\n return mergedBranches.split('\\n').some((line) => {\n const branch = line.trim().replace(/^\\*\\s+/, '');\n return branch === currentBranch;\n });\n } catch {\n return false;\n }\n }\n\n async function getBranchHygieneStatus(): Promise<BranchHygieneStatus> {\n const currentBranch = getCurrentBranch();\n const status = await runGitStatus();\n const isDirty = status.length > 0;\n\n if (currentBranch === 'main' || currentBranch === 'master') {\n return isDirty ? 'dirty' : 'clean-on-main';\n }\n\n // Only \"stale\" if the branch is fully merged into main AND main has advanced\n // past it — i.e. its work is done and elsewhere. A freshly-created branch still\n // at main's tip, or one with un-merged local work (with or without an upstream),\n // is normal active work, not stale.\n if (await isMergedIntoMain()) {\n const behind = await runGit(['rev-list', '--count', 'HEAD..main'])\n .then((n) => Number.parseInt(n.trim(), 10) || 0)\n .catch(() => 0);\n if (behind > 0) return 'stale-merged';\n }\n\n return isDirty ? 'dirty' : 'fine';\n }\n\n function getFeatureBranchPlanId(): string | null {\n const branch = getCurrentBranch();\n const match = branch.match(/^[a-z]+\\/([a-z]+-\\d+)-/);\n return match ? match[1].toUpperCase() : null;\n }\n\n /**\n * Diff text for the given paths, capped to a sane size for feeding into a prompt.\n * Plain `git diff` skips untracked files entirely, so those are read directly and\n * presented as new-file content instead.\n */\n async function diff(files: string[], maxChars = 12000): Promise<string> {\n if (files.length === 0) return '';\n const blocked = files.find((file) => AI_DIFF_BLOCKLIST.some((pattern) => pattern.test(file)));\n if (blocked) {\n throw new Error(`Refusing to send sensitive file \"${blocked}\" to commit suggestion`);\n }\n const statusEntries = await runGitStatus();\n const untracked = new Set(statusEntries.filter((e) => e.status === '??').map((e) => e.path));\n\n const renameSources = new Map(\n statusEntries\n .filter((e): e is GitStatusEntry & { renameSource: string } => !!e.renameSource)\n .map((e) => [e.path, e.renameSource]),\n );\n\n const tracked = files.filter((f) => {\n if (untracked.has(f)) return false;\n const source = renameSources.get(f);\n if (source && AI_DIFF_BLOCKLIST.some((pattern) => pattern.test(source))) return false;\n return true;\n });\n const parts: string[] = [];\n\n if (tracked.length > 0) {\n const trackedDiff = await runGit([\n 'diff',\n 'HEAD',\n '--',\n ...tracked.map(toLiteralPathspec),\n ]).catch(() => '');\n if (trackedDiff) parts.push(trackedDiff);\n }\n\n for (const file of files.filter((f) => untracked.has(f))) {\n const filePath = join(root, file);\n // lstat (not stat) so a symlink is identified as such instead of followed —\n // otherwise its target's content, possibly outside the repo, leaks into the AI prompt.\n const stats = await lstat(filePath).catch(() => null);\n if (!stats) continue;\n if (stats.isSymbolicLink()) {\n parts.push(`--- /dev/null\\n+++ b/${file}\\n(new file omitted: symlink)`);\n continue;\n }\n if (stats.size > maxChars) {\n parts.push(`--- /dev/null\\n+++ b/${file}\\n(new file omitted: exceeds diff size cap)`);\n continue;\n }\n const content = await readFile(filePath, 'utf-8').catch(() => '');\n if (content) {\n parts.push(`--- /dev/null\\n+++ b/${file}\\n(new file)\\n${content}`);\n }\n }\n\n const combined = parts.join('\\n\\n');\n return combined.length > maxChars\n ? `${combined.slice(0, maxChars)}\\n... (truncated)`\n : combined;\n }\n\n async function stageAll(): Promise<void> {\n await runGit(['add', '-A']);\n }\n\n async function runGitSync(): Promise<void> {\n // Clean sync: checkout main, fetch, and fast-forward merge\n await runGit(['checkout', 'main']);\n await runGit(['fetch', '--prune']);\n await runGit(['merge', '--ff-only', 'origin/main']);\n }\n\n return {\n async getStatus(): Promise<GitStatusEntry[]> {\n return runGitStatus();\n },\n getCurrentBranch,\n commit,\n stageAll,\n diff,\n ensureBranch,\n getFeatureBranchPlanId,\n getAheadCount,\n push,\n isMergedIntoMain,\n getBranchHygieneStatus,\n runGitSync,\n subscribe(res: ServerResponse) {\n clients.add(res);\n res.on('close', () => clients.delete(res));\n },\n };\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\n\n/** Uniform JSON responder — every API route replies through this. */\nexport function sendJson(res: ServerResponse, statusCode: number, data: unknown): void {\n res.statusCode = statusCode;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(data));\n}\n\nexport async function readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk;\n });\n req.on('end', () => resolve(body));\n req.on('error', reject);\n });\n}\n\n/** Parsed request URL for query-param access — the host part only anchors parsing. */\nexport function requestUrl(req: IncomingMessage): URL {\n return new URL(req.url ?? '', `http://${req.headers.host ?? 'localhost'}`);\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parseIdeas, parsePlans } from '../../../core/parser';\nimport { readAllIdeaFiles, readAllPlanFiles } from '../../../core/readers';\nimport type { IdeaEntry, PlanEntry } from '../../../types/index';\nimport { campFile, checkBranchConflictForPlan, fileExists, readMaybe } from '../helpers';\nimport { readBody, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\n/** Resolves a per-file plan's path, checking the archive subdirectory as a fallback. */\nasync function resolvePlanFilePath(root: string, planId: string): Promise<string | null> {\n const primary = join(campFile(root, 'plans'), `${planId}.md`);\n if (await fileExists(primary)) return primary;\n const archived = join(campFile(root, 'plans'), 'archive', `${planId}.md`);\n if (await fileExists(archived)) return archived;\n return null;\n}\n\n/**\n * Known path/identifier renames from this project's own history (see progress.md),\n * cheap enough to fix with plain substitution before spending a model call on the\n * rest of a plan's drift.\n */\nconst KNOWN_RENAMES: ReadonlyArray<readonly [string, string]> = [\n ['`plans.md`', '`papercamp/plans/`'],\n ['`ideas.md`', '`papercamp/ideas/`'],\n ['.paper-camp/', 'papercamp/'],\n ['FocusTaskItem', 'FocusPhaseItem'],\n ['TaskItem', 'PhaseItem'],\n ['taskProgress', 'phaseProgress'],\n ['taskPercentage', 'phasePercentage'],\n];\n\n/**\n * Applies KNOWN_RENAMES line-by-line, skipping the YAML frontmatter and any\n * checked phase line (plus its indented continuation lines) — the same\n * guardrails the AI reconcile pass itself enforces.\n */\nfunction applyKnownRenames(content: string): { content: string; changed: boolean } {\n const frontmatterEnd = content.startsWith('---\\n') ? content.indexOf('\\n---', 4) + 4 : -1;\n const frontmatter = frontmatterEnd >= 4 ? content.slice(0, frontmatterEnd) : '';\n const rest = frontmatterEnd >= 4 ? content.slice(frontmatterEnd) : content;\n\n const lines = rest.split('\\n');\n let changed = false;\n let skippingCheckedPhase = false;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (/^- \\[x\\]/.test(line)) {\n skippingCheckedPhase = true;\n continue;\n }\n if (skippingCheckedPhase) {\n if (line.trim() === '' || /^\\s+\\S/.test(line)) continue;\n skippingCheckedPhase = false;\n }\n let updated = line;\n for (const [from, to] of KNOWN_RENAMES) {\n if (updated.includes(from)) updated = updated.split(from).join(to);\n }\n if (updated !== line) {\n changed = true;\n lines[i] = updated;\n }\n }\n\n return { content: frontmatter + lines.join('\\n'), changed };\n}\n\n/** Per-file plan lookup with fallback to the legacy monolithic plans.md. */\nasync function findPlanById(root: string, planId: string): Promise<PlanEntry | undefined> {\n const { entries } = await readAllPlanFiles(campFile(root, 'plans'));\n const plan = entries.find((p) => p.id === planId);\n if (plan) return plan;\n const mono = parsePlans(await readMaybe(campFile(root, 'plans.md')));\n return mono.entries.find((p) => p.id === planId);\n}\n\n/** Per-file idea lookup with fallback to the legacy monolithic ideas.md. */\nasync function findIdeaById(root: string, ideaId: string): Promise<IdeaEntry | undefined> {\n const { entries } = await readAllIdeaFiles(campFile(root, 'ideas'));\n const idea = entries.find((i) => i.id === ideaId);\n if (idea) return idea;\n const mono = parseIdeas(await readMaybe(campFile(root, 'ideas.md')));\n return mono.find((i) => i.id === ideaId);\n}\n\nexport function agentRoutes({ root, git, status, agent }: RouteContext): Route[] {\n return [\n // GET /api/agent/status — current agent task state, if any\n {\n method: 'GET',\n path: '/api/agent/status',\n handle: (_req, res) => {\n sendJson(res, 200, agent.getStatus());\n },\n },\n\n // POST /api/agent/launch — start a headless agent on one plan phase\n {\n method: 'POST',\n path: '/api/agent/launch',\n handle: async (req, res) => {\n const reqBody = await readBody(req);\n const { planId, phaseIndex } = JSON.parse(reqBody) as {\n planId?: string;\n phaseIndex?: number;\n };\n if (!planId || typeof phaseIndex !== 'number') {\n sendJson(res, 400, { error: 'planId and phaseIndex are required' });\n return;\n }\n const plan = await findPlanById(root, planId);\n if (!plan) {\n sendJson(res, 404, { error: 'plan not found' });\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git, plan.id);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const result = agent.start(plan, phaseIndex);\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/agent/launch-audit — start a headless agent on a plan-scoped convergence audit\n {\n method: 'POST',\n path: '/api/agent/launch-audit',\n handle: async (req, res) => {\n const reqBody = await readBody(req);\n const { planId, prompt } = JSON.parse(reqBody) as { planId?: string; prompt?: string };\n if (!planId || !prompt) {\n sendJson(res, 400, { error: 'planId and prompt are required' });\n return;\n }\n const plan = await findPlanById(root, planId);\n if (!plan) {\n sendJson(res, 404, { error: 'plan not found' });\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git, plan.id);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const result = agent.startForPlan(plan, prompt);\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/agent/launch-reconcile — start a headless agent that reconciles stale prose in a plan\n {\n method: 'POST',\n path: '/api/agent/launch-reconcile',\n handle: async (req, res) => {\n const reqBody = await readBody(req);\n const { planId, prompt } = JSON.parse(reqBody) as { planId?: string; prompt?: string };\n if (!planId || !prompt) {\n sendJson(res, 400, { error: 'planId and prompt are required' });\n return;\n }\n const plan = await findPlanById(root, planId);\n if (!plan) {\n sendJson(res, 404, { error: 'plan not found' });\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git, plan.id);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const filePath = await resolvePlanFilePath(root, planId);\n if (filePath) {\n const raw = await readFile(filePath, 'utf-8');\n const { content, changed } = applyKnownRenames(raw);\n if (changed) await writeFile(filePath, content, 'utf-8');\n }\n const result = agent.startForPlan(plan, prompt, 'reconcile');\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/agent/launch-draft — start a headless agent that drafts a new plan from an idea\n {\n method: 'POST',\n path: '/api/agent/launch-draft',\n handle: async (req, res) => {\n const reqBody = await readBody(req);\n const { ideaId, prompt } = JSON.parse(reqBody) as { ideaId?: string; prompt?: string };\n if (!ideaId || !prompt) {\n sendJson(res, 400, { error: 'ideaId and prompt are required' });\n return;\n }\n const idea = await findIdeaById(root, ideaId);\n if (!idea) {\n sendJson(res, 404, { error: 'idea not found' });\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const result = agent.startForIdea(idea, prompt);\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/agent/launch-extend — start a headless agent to extend an idea's body\n {\n method: 'POST',\n path: '/api/agent/launch-extend',\n handle: async (req, res) => {\n const reqBody = await readBody(req);\n const { ideaId, prompt } = JSON.parse(reqBody) as { ideaId?: string; prompt?: string };\n if (!ideaId || !prompt) {\n sendJson(res, 400, { error: 'ideaId and prompt are required' });\n return;\n }\n const idea = await findIdeaById(root, ideaId);\n if (!idea) {\n sendJson(res, 404, { error: 'idea not found' });\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const result = agent.startForIdeaExtend(idea, prompt);\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/agent/launch-audit-all — start a batch convergence audit across all review/done plans\n {\n method: 'POST',\n path: '/api/agent/launch-audit-all',\n handle: async (_req, res) => {\n // Batch audit can modify many plan files — gate it behind the same\n // active-plan guard the other write-capable agent routes use.\n const conflict = await checkBranchConflictForPlan(root, git);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const result = agent.startBatchAudit();\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/agent/launch-run-all — run every unchecked phase sequentially with per-phase commits\n {\n method: 'POST',\n path: '/api/agent/launch-run-all',\n handle: async (req, res) => {\n const reqBody = await readBody(req);\n const { planId } = JSON.parse(reqBody) as { planId?: string };\n if (!planId) {\n sendJson(res, 400, { error: 'planId is required' });\n return;\n }\n const plan = await findPlanById(root, planId);\n if (!plan) {\n sendJson(res, 404, { error: 'plan not found' });\n return;\n }\n const conflict = await checkBranchConflictForPlan(root, git, plan.id);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const result = agent.startRunAllPhases(plan, () => status.runChecksAndWait());\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/agent/stop — kill the running agent task\n {\n method: 'POST',\n path: '/api/agent/stop',\n handle: (_req, res) => {\n const result = agent.stop();\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n ];\n}\n","import { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n AGENT_IDS,\n type AgentId,\n type DefaultAgentsMap,\n type PaperCampConfig,\n coerceAgentConfig,\n} from '../../../types/index';\nimport { readMaybe } from '../helpers';\nimport { readBody, requestUrl, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\n/** Repo config files the dashboard may list and read — nothing outside this set. */\nexport const CONFIG_ALLOWLIST = [\n 'biome.json',\n 'tsconfig.json',\n 'tailwind.config.ts',\n 'vite.config.ts',\n 'vite.app.config.ts',\n 'postcss.config.js',\n 'package.json',\n];\n\nexport async function listConfigFiles(root: string): Promise<{ files: string[] }> {\n const files: string[] = [];\n for (const name of CONFIG_ALLOWLIST) {\n const content = await readMaybe(join(root, name));\n if (content) files.push(name);\n }\n return { files };\n}\n\nexport function configRoutes({ root }: RouteContext): Route[] {\n return [\n // POST /api/config — update editable fields in papercamp/config.json (port, projectName)\n {\n method: 'POST',\n path: '/api/config',\n handle: async (req, res) => {\n const configPath = join(root, 'papercamp', 'config.json');\n const raw = await readMaybe(configPath);\n if (!raw) {\n sendJson(res, 404, { error: 'config not found' });\n return;\n }\n const body = await readBody(req);\n const bodyParsed = JSON.parse(body) as {\n port?: number;\n projectName?: string;\n defaultAgent?: AgentId;\n defaultAgents?: Record<string, unknown>;\n };\n const { port, projectName, defaultAgent } = bodyParsed;\n const rawDefaultAgents = bodyParsed.defaultAgents;\n if (port !== undefined && (!Number.isInteger(port) || port <= 0)) {\n sendJson(res, 400, { error: 'port must be a positive integer' });\n return;\n }\n if (projectName !== undefined && projectName.trim().length === 0) {\n sendJson(res, 400, { error: 'projectName must not be empty' });\n return;\n }\n if (defaultAgent !== undefined && !AGENT_IDS.includes(defaultAgent)) {\n sendJson(res, 400, { error: 'defaultAgent must be a known agent id' });\n return;\n }\n if (rawDefaultAgents !== undefined) {\n for (const key of ['phase', 'planDraft', 'ideaExtend', 'commitSuggest'] as const) {\n const val = rawDefaultAgents[key];\n const agentId =\n typeof val === 'string' ? val : (val as Record<string, unknown> | undefined)?.agent;\n if (!agentId || !AGENT_IDS.includes(agentId as AgentId)) {\n sendJson(res, 400, { error: `defaultAgents.${key} must be a known agent id` });\n return;\n }\n }\n }\n const config = JSON.parse(raw) as PaperCampConfig;\n const defaultAgents: DefaultAgentsMap | undefined = rawDefaultAgents\n ? {\n phase: coerceAgentConfig(rawDefaultAgents.phase),\n planDraft: coerceAgentConfig(rawDefaultAgents.planDraft),\n ideaExtend: coerceAgentConfig(rawDefaultAgents.ideaExtend),\n commitSuggest: coerceAgentConfig(rawDefaultAgents.commitSuggest),\n }\n : undefined;\n const resolvedDefaultAgents: DefaultAgentsMap | undefined =\n defaultAgents ??\n (defaultAgent !== undefined\n ? {\n phase: { agent: defaultAgent },\n planDraft: { agent: defaultAgent },\n ideaExtend: { agent: defaultAgent },\n commitSuggest: { agent: defaultAgent },\n }\n : undefined);\n const configWithOld = config as PaperCampConfig & { defaultAgent?: AgentId };\n const { defaultAgent: _oldAgent, ...configRest } = configWithOld;\n const updated: PaperCampConfig = {\n ...configRest,\n ...(port !== undefined && { port }),\n ...(projectName !== undefined && { projectName: projectName.trim() }),\n ...(resolvedDefaultAgents && { defaultAgents: resolvedDefaultAgents }),\n };\n await writeFile(configPath, `${JSON.stringify(updated, null, 2)}\\n`);\n sendJson(res, 200, { ok: true });\n },\n },\n\n // GET /api/configs — list readable config files, or ?name=... for one file's content\n {\n method: 'GET',\n path: '/api/configs',\n handle: async (req, res) => {\n const name = requestUrl(req).searchParams.get('name');\n if (!name) {\n sendJson(res, 200, await listConfigFiles(root));\n return;\n }\n if (!CONFIG_ALLOWLIST.includes(name)) {\n sendJson(res, 400, { error: 'invalid config file name' });\n return;\n }\n const content = await readMaybe(join(root, name));\n if (!content) {\n sendJson(res, 404, { error: 'config file not found' });\n return;\n }\n sendJson(res, 200, { name, content });\n },\n },\n ];\n}\n","import { writeFile } from 'node:fs/promises';\nimport { parseOpenQuestions } from '../../../core/parser';\nimport {\n appendBlock,\n formatDecisionEntry,\n formatOpenQuestions,\n todayDateString,\n} from '../../../core/serializer';\nimport { campFile, readMaybe } from '../helpers';\nimport { readBody, requestUrl, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\nexport function docsRoutes({ root }: RouteContext): Route[] {\n return [\n // POST /api/open-questions/resolve?title=... — resolve an open question with a new decision\n {\n method: 'POST',\n path: '/api/open-questions/resolve',\n handle: async (req, res) => {\n const title = requestUrl(req).searchParams.get('title');\n if (!title?.trim()) {\n sendJson(res, 400, { error: 'title is required' });\n return;\n }\n const body = await readBody(req);\n const { decision, rationale } = JSON.parse(body) as {\n decision?: string;\n rationale?: string;\n };\n if (!decision?.trim()) {\n sendJson(res, 400, { error: 'decision is required' });\n return;\n }\n\n // Validate everything before any writes — avoids partial state on failure.\n const questionsPath = campFile(root, 'open-questions.md');\n const raw = await readMaybe(questionsPath);\n if (!raw) {\n sendJson(res, 404, { error: 'open-questions.md not found' });\n return;\n }\n const parsed = parseOpenQuestions(raw);\n if (parsed.warnings.length > 0) {\n sendJson(res, 409, {\n error:\n 'open-questions.md has parse warnings — resolve them before updating to avoid data loss',\n warnings: parsed.warnings.map((w) => `${w.title}: ${w.message}`),\n });\n return;\n }\n const trimmed = title.trim();\n const target = parsed.entries.find((q) => q.title === trimmed);\n if (!target) {\n sendJson(res, 404, { error: `open question \"${trimmed}\" not found` });\n return;\n }\n if (target.status !== 'open') {\n sendJson(res, 409, { error: `open question \"${trimmed}\" is already ${target.status}` });\n return;\n }\n\n // Both targets validated — now write the two files.\n const decisionBlock = formatDecisionEntry({\n title: decision.trim(),\n date: todayDateString(),\n status: 'decided',\n body: rationale?.trim(),\n });\n await appendBlock(campFile(root, 'decisions.md'), decisionBlock);\n\n target.status = 'resolved';\n target.resolvedBy = decision.trim();\n const updated = formatOpenQuestions(parsed.entries);\n await writeFile(questionsPath, `${updated}\\n`, 'utf-8');\n\n sendJson(res, 200, { ok: true });\n },\n },\n ];\n}\n","import { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { applyEnvEntries, parseEnv } from '../../../core/env';\nimport type { EnvEntry } from '../../../types/index';\nimport { fileExists, readMaybe } from '../helpers';\nimport { readBody, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\nexport function envRoutes({ root }: RouteContext): Route[] {\n return [\n // GET /api/env — read the project root's .env, masked client-side only\n {\n method: 'GET',\n path: '/api/env',\n handle: async (_req, res) => {\n const envPath = join(root, '.env');\n const examplePath = join(root, '.env.example');\n const [exists, exampleExists] = await Promise.all([\n fileExists(envPath),\n fileExists(examplePath),\n ]);\n const entries = exists ? parseEnv(await readMaybe(envPath)) : [];\n const exampleKeys = exampleExists\n ? parseEnv(await readMaybe(examplePath)).map((e) => e.key)\n : [];\n const envKeys = new Set(entries.map((e) => e.key));\n const missingKeys = exampleKeys.filter((key) => !envKeys.has(key));\n sendJson(res, 200, { exists, exampleExists, entries, missingKeys });\n },\n },\n\n // POST /api/env — write the full desired entry set back to .env\n {\n method: 'POST',\n path: '/api/env',\n handle: async (req, res) => {\n const body = await readBody(req);\n const { entries } = JSON.parse(body) as { entries?: EnvEntry[] };\n if (!Array.isArray(entries)) {\n sendJson(res, 400, { error: 'entries is required' });\n return;\n }\n const keys = new Set<string>();\n for (const entry of entries) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(entry.key)) {\n sendJson(res, 400, { error: `invalid key: ${entry.key}` });\n return;\n }\n if (keys.has(entry.key)) {\n sendJson(res, 400, { error: `duplicate key: ${entry.key}` });\n return;\n }\n keys.add(entry.key);\n }\n const envPath = join(root, '.env');\n const current = await readMaybe(envPath);\n await writeFile(envPath, applyEnvEntries(current, entries));\n sendJson(res, 200, { ok: true });\n },\n },\n ];\n}\n","import type { PlanEntry } from '@/types/index';\n\nexport const relativeDate = (dateStr: string): string => {\n const date = new Date(dateStr);\n if (Number.isNaN(date.getTime())) return dateStr;\n const days = Math.floor((Date.now() - date.getTime()) / 86400000);\n if (days === 0) return 'today';\n if (days === 1) return 'yesterday';\n if (days < 7) return `${days}d ago`;\n if (days < 30) return `${Math.floor(days / 7)}w ago`;\n if (days < 365) return `${Math.floor(days / 30)}mo ago`;\n return `${Math.floor(days / 365)}y ago`;\n};\n\nexport const phaseProgress = (plan: PlanEntry) => {\n if (plan.phases.length === 0) return null;\n const done = plan.phases.filter((p) => p.done).length;\n return { done, total: plan.phases.length, pct: Math.round((done / plan.phases.length) * 100) };\n};\n\nexport const phasePercentage = (plan: PlanEntry): number | null => {\n if (plan.phases.length === 0) return null;\n return Math.round((plan.phases.filter((p) => p.done).length / plan.phases.length) * 100);\n};\n\nexport const findFocusPlan = (\n plans: PlanEntry[] | undefined,\n activePlanTitle?: string | null,\n): PlanEntry | undefined => {\n if (!plans) return undefined;\n if (activePlanTitle) {\n const selected = plans.find((p) => p.title === activePlanTitle);\n if (selected) return selected;\n }\n return plans.find((p) => p.status === 'in-progress' || p.status === 'review');\n};\n","function buildPrompt(diffText: string, planContext?: string): string {\n return `You are writing a single git commit message for the diff below. Do not use any tools, do not read or edit any files — base your answer only on the diff text given.\n\nFollow this repo's commit convention: \\`type(scope): Description\\`, where type is one of feat|fix|chore|docs|refactor and scope is a subsystem area from this fixed list: core, cli, app, server, agent, plans, ideas, docs, settings, stack, ui, ci, config, deps, repo. Pick the area the diff most affects. Keep the whole title under 100 characters and do not end it with a period.${\n planContext\n ? `\\nThis work belongs to plan ${planContext}. Do NOT put the plan id in the scope — instead end the message body with a \\`Refs: ${planContext}\\` line as its final line.`\n : ''\n }\n\nRespond with ONLY a single JSON object, no prose, no code fences, no markdown — exactly this shape:\n{\"title\": \"type(scope): Description\", \"message\": \"${\n planContext\n ? `longer body describing what changed and why, ending with a \\`Refs: ${planContext}\\` line`\n : 'optional longer body describing what changed and why, or an empty string if the title alone is clear enough'\n }\"}\n\nDiff:\n${diffText}`;\n}\n\n/**\n * One-shot, read-only agent call — not the long-running phase/task system in agent.ts.\n * The actual process spawn lives in agent.ts's runCommitSuggest, which tracks it on the\n * shared `current` task so the UI's Agent card shows it running; this module only builds\n * the prompt and parses the result.\n */\nexport async function suggestCommitMessage(\n diffText: string,\n planContext: string | undefined,\n runPrompt: (prompt: string) => Promise<string>,\n): Promise<{ title: string; message: string }> {\n if (!diffText.trim()) {\n throw new Error('No changes to summarize — select at least one file first');\n }\n\n const prompt = buildPrompt(diffText, planContext);\n const output = await runPrompt(prompt);\n\n let resultText = output;\n try {\n const parsed = JSON.parse(output) as { result?: string };\n if (typeof parsed.result === 'string') resultText = parsed.result;\n } catch {\n // fall through with raw output\n }\n\n const match = resultText.match(/\\{[\\s\\S]*\\}/);\n if (!match) throw new Error('Agent did not return a parseable commit message');\n\n const data = JSON.parse(match[0]) as { title?: string; message?: string };\n if (!data.title) throw new Error('Agent response missing a title');\n let message = data.message ?? '';\n // The prompt asks for a `Refs: <plan>` footer when a plan is active; backfill it\n // if the model dropped it, so plan traceability stays consistent.\n if (planContext && !/Refs:\\s*\\S/.test(message)) {\n message = message ? `${message}\\n\\nRefs: ${planContext}` : `Refs: ${planContext}`;\n }\n return { title: data.title, message };\n}\n","import { readPlansMerged } from '../../../core/readers';\nimport { findFocusPlan } from '../../features/plans/helpers';\nimport { suggestCommitMessage } from '../commit-suggest';\nimport { campFile } from '../helpers';\nimport { readBody, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\nconst DIRTY_SYNC_PROMPT = `Sync the current branch to main by:\n1. Stashing or committing any uncommitted changes (do not use \\`git reset --hard\\` or \\`git clean -fd\\` without an explicit confirmation step)\n2. Relocating any mis-filed content (e.g., any new plans written to the legacy \\`papercamp/plans.md\\` instead of per-file \\`papercamp/plans/*.md\\`)\n3. Checking out main: \\`git checkout main\\`\n4. Fetching from origin: \\`git fetch --prune\\`\n5. Fast-forwarding the merge: \\`git merge --ff-only origin/main\\`\n6. Confirming success\n\nReport the final branch and status to verify the sync completed.`;\n\nexport function gitRoutes({ root, git, agent }: RouteContext): Route[] {\n return [\n // GET /api/git/status — return working tree status\n {\n method: 'GET',\n path: '/api/git/status',\n handle: async (_req, res) => {\n const entries = await git.getStatus();\n const branch = git.getCurrentBranch();\n const ahead = await git.getAheadCount();\n const branchHygiene = await git.getBranchHygieneStatus();\n sendJson(res, 200, { branch, entries, ahead, branchHygiene });\n },\n },\n\n // POST /api/git/push — push the current branch to its upstream\n {\n method: 'POST',\n path: '/api/git/push',\n handle: async (_req, res) => {\n try {\n await git.push();\n sendJson(res, 200, { ok: true });\n } catch (error) {\n sendJson(res, 400, { error: (error as Error).message });\n }\n },\n },\n\n // POST /api/git/commit — stage files and create a commit\n {\n method: 'POST',\n path: '/api/git/commit',\n handle: async (req, res) => {\n try {\n const body = await readBody(req);\n const { files, title, message } = JSON.parse(body) as {\n files: string[];\n title: string;\n message?: string;\n };\n if (!title?.trim()) {\n sendJson(res, 400, { error: 'title is required' });\n return;\n }\n await git.commit(files ?? [], title.trim(), message?.trim());\n sendJson(res, 200, { ok: true });\n } catch (error) {\n sendJson(res, 400, { error: (error as Error).message });\n }\n },\n },\n\n // POST /api/git/sync — sync to main (clean: inline, dirty: agent task)\n {\n method: 'POST',\n path: '/api/git/sync',\n handle: async (req, res) => {\n const body = await readBody(req);\n const { mode } = JSON.parse(body) as { mode?: string };\n if (mode !== 'clean' && mode !== 'dirty') {\n sendJson(res, 400, { error: \"mode must be 'clean' or 'dirty'\" });\n return;\n }\n\n if (mode === 'clean') {\n // Re-verify cleanliness server-side — the client's `mode` is derived from\n // a possibly-stale status snapshot, and checking out main against an\n // actually-dirty tree could fail confusingly or carry changes onto main.\n const currentStatus = await git.getStatus();\n if (currentStatus.length > 0) {\n sendJson(res, 409, { error: 'Working tree is no longer clean — refresh and retry' });\n return;\n }\n // Inline sync: checkout main, fetch, fast-forward merge\n await git.runGitSync();\n sendJson(res, 200, { ok: true });\n return;\n }\n\n // Dirty mode: launch agent task\n const result = agent.startSync(DIRTY_SYNC_PROMPT);\n if (!result.ok) {\n sendJson(res, 409, { error: result.error });\n return;\n }\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/git/suggest-commit-message — agent-written title/body from the actual diff\n {\n method: 'POST',\n path: '/api/git/suggest-commit-message',\n handle: async (req, res) => {\n try {\n const body = await readBody(req);\n const { files } = JSON.parse(body) as { files?: string[] };\n if (!files?.length) {\n sendJson(res, 400, { error: 'files is required' });\n return;\n }\n const diffText = await git.diff(files);\n const { entries } = await readPlansMerged(\n campFile(root, 'plans'),\n campFile(root, 'plans.md'),\n );\n const activePlan = findFocusPlan(entries);\n const suggestion = await suggestCommitMessage(\n diffText,\n activePlan?.id,\n agent.runCommitSuggest,\n );\n sendJson(res, 200, suggestion);\n } catch (error) {\n sendJson(res, 400, { error: (error as Error).message });\n }\n },\n },\n ];\n}\n","import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { readBody, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\nconst MIME_BY_EXT: Record<string, string> = {\n svg: 'image/svg+xml',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n};\n\nexport function iconRoutes({ root }: RouteContext): Route[] {\n return [\n // GET /api/icon — serve project icon\n {\n method: 'GET',\n path: '/api/icon',\n handle: async (_req, res) => {\n const assetsDir = join(root, 'papercamp', 'assets');\n for (const [ext, mime] of Object.entries(MIME_BY_EXT)) {\n try {\n const data = await readFile(join(assetsDir, `icon.${ext}`));\n res.statusCode = 200;\n res.setHeader('Content-Type', mime);\n res.setHeader('Cache-Control', 'no-cache');\n res.end(data);\n return;\n } catch {\n /* try next */\n }\n }\n sendJson(res, 404, { error: 'no icon uploaded' });\n },\n },\n\n // POST /api/icon — upload project icon\n {\n method: 'POST',\n path: '/api/icon',\n handle: async (req, res) => {\n const body = await readBody(req);\n const { dataUri } = JSON.parse(body) as { dataUri?: string };\n if (!dataUri) {\n sendJson(res, 400, { error: 'dataUri is required' });\n return;\n }\n const match = dataUri.match(/^data:(image\\/[a-z0-9+.-]+);base64,(.+)$/);\n if (!match) {\n sendJson(res, 400, { error: 'invalid data URI' });\n return;\n }\n const mime = match[1];\n const ext = mime === 'image/svg+xml' ? 'svg' : mime.split('/')[1];\n const buffer = Buffer.from(match[2], 'base64');\n const assetsDir = join(root, 'papercamp', 'assets');\n await mkdir(assetsDir, { recursive: true });\n // Remove any previously uploaded icon with a different extension — GET serves\n // the first extension it finds, so a stale icon.svg would permanently shadow\n // a newly uploaded icon.png.\n await Promise.all(\n Object.keys(MIME_BY_EXT)\n .filter((e) => e !== ext)\n .map((e) => unlink(join(assetsDir, `icon.${e}`)).catch(() => {})),\n );\n await writeFile(join(assetsDir, `icon.${ext}`), buffer);\n sendJson(res, 200, { ok: true });\n },\n },\n ];\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { readIdeasMerged } from '../../../core/readers';\nimport { formatIdeaFile } from '../../../core/serializer';\nimport { campFile, regenerateIndexes } from '../helpers';\nimport { readBody, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\nexport function ideaRoutes({ root }: RouteContext): Route[] {\n return [\n // POST /api/ideas — create a new per-file idea entry\n {\n method: 'POST',\n path: '/api/ideas',\n handle: async (req, res) => {\n const reqBody = await readBody(req);\n const { title, content } = JSON.parse(reqBody) as { title?: string; content?: string };\n if (!title?.trim()) {\n sendJson(res, 400, { error: 'title is required' });\n return;\n }\n const ideasDir = campFile(root, 'ideas');\n const existing = await readIdeasMerged(ideasDir, campFile(root, 'ideas.md'));\n const maxNum = existing.entries.reduce((max, idea) => {\n if (idea.id) {\n const num = Number.parseInt(idea.id.replace('IDEA-', ''), 10);\n return Number.isNaN(num) ? max : Math.max(max, num);\n }\n return max;\n }, 0);\n const newId = `IDEA-${maxNum + 1}`;\n await mkdir(ideasDir, { recursive: true });\n const ideaContent = formatIdeaFile({\n id: newId,\n title: title.trim(),\n body: content?.trim(),\n });\n await writeFile(join(ideasDir, `${newId}.md`), `${ideaContent}\\n`, 'utf-8');\n await regenerateIndexes(root);\n sendJson(res, 201, { ok: true, id: newId });\n },\n },\n ];\n}\n","import { mkdir, unlink, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parsePlanFile } from '../../../core/parser';\nimport { readAllPlanFiles } from '../../../core/readers';\nimport {\n archivePlanFile,\n assignPlanId,\n formatPlanFile,\n todayDateString,\n} from '../../../core/serializer';\nimport {\n AGENT_IDS,\n type AgentId,\n type LogEntry,\n PLAN_KINDS,\n type PhaseItem,\n type PlanEntry,\n type PlanStatus,\n} from '../../../types/index';\nimport {\n campFile,\n checkBranchConflictForPlan,\n fileExists,\n planFileInput,\n readMaybe,\n regenerateIndexes,\n writePlanFile,\n} from '../helpers';\nimport { readBody, requestUrl, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\nexport function planRoutes({ root, git }: RouteContext): Route[] {\n return [\n // DELETE /api/plans?title=... — remove a plan entry from per-file storage\n {\n method: 'DELETE',\n path: '/api/plans',\n handle: async (req, res) => {\n const title = requestUrl(req).searchParams.get('title');\n if (!title?.trim()) {\n sendJson(res, 400, { error: 'title is required' });\n return;\n }\n const plansDir = campFile(root, 'plans');\n const trimmed = title.trim();\n const { entries } = await readAllPlanFiles(plansDir);\n const target = entries.find((e) => e.title === trimmed || e.id === trimmed);\n if (!target?.id) {\n sendJson(res, 404, { error: 'plan not found in per-file storage' });\n return;\n }\n const filePath = join(plansDir, `${target.id}.md`);\n if (!(await fileExists(filePath))) {\n sendJson(res, 404, { error: 'plan file not found' });\n return;\n }\n await unlink(filePath);\n await regenerateIndexes(root);\n sendJson(res, 200, { ok: true });\n },\n },\n\n // POST /api/plans — create a new per-file plan entry\n {\n method: 'POST',\n path: '/api/plans',\n handle: async (req, res) => {\n const body = await readBody(req);\n const { title, content, kind } = JSON.parse(body) as {\n title: string;\n content?: string;\n kind?: string;\n };\n if (!title?.trim()) {\n sendJson(res, 400, { error: 'title is required' });\n return;\n }\n // Server-side branch-hygiene guard — the sidebar disables this client-side,\n // but a stale-branch request must not create a plan by bypassing the UI.\n const conflict = await checkBranchConflictForPlan(root, git);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n const planKind =\n kind && PLAN_KINDS.includes(kind as (typeof PLAN_KINDS)[number]) ? kind : 'feat';\n\n const configPath = join(root, 'papercamp', 'config.json');\n const id = await assignPlanId(configPath, planKind);\n\n if (!id) {\n sendJson(res, 500, { error: 'could not assign plan ID' });\n return;\n }\n\n const plansDir = campFile(root, 'plans');\n await mkdir(plansDir, { recursive: true });\n\n const planContent = formatPlanFile({\n id,\n title: title.trim(),\n kind: planKind,\n status: 'idea',\n created: todayDateString(),\n body: content?.trim(),\n });\n await writeFile(join(plansDir, `${id}.md`), `${planContent}\\n`, 'utf-8');\n await regenerateIndexes(root);\n sendJson(res, 201, { ok: true, id });\n },\n },\n\n // PATCH /api/plans?title=... — update an existing plan entry\n {\n method: 'PATCH',\n path: '/api/plans',\n handle: async (req, res) => {\n const title = requestUrl(req).searchParams.get('title');\n if (!title?.trim()) {\n sendJson(res, 400, { error: 'title is required' });\n return;\n }\n const reqBody = await readBody(req);\n const updates = JSON.parse(reqBody) as {\n body?: string;\n phases?: PhaseItem[];\n status?: PlanStatus;\n log?: LogEntry[];\n agent?: AgentId | null;\n };\n if (updates.agent && !AGENT_IDS.includes(updates.agent)) {\n sendJson(res, 400, { error: 'agent must be a known agent id' });\n return;\n }\n\n const plansDir = campFile(root, 'plans');\n const { entries } = await readAllPlanFiles(plansDir);\n const trimmed = title.trim();\n const target = entries.find((e) => e.title === trimmed || e.id === trimmed);\n\n if (!target?.id) {\n sendJson(res, 404, { error: 'plan not found' });\n return;\n }\n\n const targetFile = join(plansDir, `${target.id}.md`);\n const raw = await readMaybe(targetFile);\n if (!raw) {\n sendJson(res, 404, { error: 'plan file not found' });\n return;\n }\n\n const parsed = parsePlanFile(raw);\n if (parsed.entries.length === 0) {\n sendJson(res, 500, { error: 'failed to parse plan file' });\n return;\n }\n\n const updatedEntry: PlanEntry = {\n ...parsed.entries[0],\n ...(updates.body !== undefined && { body: updates.body }),\n ...(updates.status !== undefined && { status: updates.status }),\n ...(updates.phases !== undefined && { phases: updates.phases }),\n ...(updates.log !== undefined && { log: updates.log }),\n ...(updates.agent !== undefined && { agent: updates.agent ?? undefined }),\n updated: todayDateString(),\n };\n\n if (updates.status === 'done' || updates.status === 'dropped') {\n const conflict = await checkBranchConflictForPlan(root, git, target.id);\n if (conflict) {\n sendJson(res, 409, { error: conflict });\n return;\n }\n }\n\n // Demote other in-progress plans when starting a new one\n if (updates.status === 'in-progress') {\n const allPlans = await readAllPlanFiles(plansDir);\n for (const other of allPlans.entries) {\n if (other.id !== target.id && other.status === 'in-progress') {\n const otherFile = join(plansDir, `${other.id}.md`);\n const otherRaw = await readMaybe(otherFile);\n if (otherRaw) {\n const otherParsed = parsePlanFile(otherRaw);\n if (otherParsed.entries.length > 0) {\n await writePlanFile(\n otherFile,\n planFileInput(otherParsed.entries[0], {\n id: otherParsed.entries[0].id ?? other.id!,\n status: 'planned',\n updated: todayDateString(),\n }),\n );\n }\n }\n }\n }\n }\n\n await writePlanFile(\n targetFile,\n planFileInput(updatedEntry, { id: updatedEntry.id ?? target.id }),\n );\n await regenerateIndexes(root);\n\n if (updates.status === 'done' || updates.status === 'dropped') {\n await archivePlanFile(root, target.id);\n try {\n git.ensureBranch(updatedEntry);\n } catch {\n // Non-fatal\n }\n }\n\n sendJson(res, 200, { ok: true });\n },\n },\n ];\n}\n","import { requestUrl, sendJson } from '../http';\nimport type { Route, RouteContext } from './types';\n\nexport function statusRoutes({ activity, agent, git, status }: RouteContext): Route[] {\n return [\n // GET /api/status — return current lint/format/test check results\n {\n method: 'GET',\n path: '/api/status',\n handle: (_req, res) => {\n sendJson(res, 200, status.getStatus());\n },\n },\n\n // POST /api/status/check?name=lint|format|test — trigger a one-off check run\n {\n method: 'POST',\n path: '/api/status/check',\n handle: (req, res) => {\n const name = requestUrl(req).searchParams.get('name');\n if (name !== 'lint' && name !== 'format' && name !== 'test') {\n sendJson(res, 400, { error: 'name must be lint, format, or test' });\n return;\n }\n status.runCheck(name);\n sendJson(res, 202, { ok: true });\n },\n },\n\n // POST /api/status/fix — run `biome check . --write` to auto-fix lint/format issues\n {\n method: 'POST',\n path: '/api/status/fix',\n handle: (_req, res) => {\n status.runQualityFix();\n sendJson(res, 202, { ok: true });\n },\n },\n\n // GET /api/activity/stream — SSE endpoint for live activity events\n {\n method: 'GET',\n path: '/api/activity/stream',\n handle: (_req, res) => {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.flushHeaders();\n activity.subscribe(res);\n git.subscribe(res);\n status.subscribe(res);\n agent.subscribe(res);\n },\n },\n ];\n}\n","import { join } from 'node:path';\nimport {\n findConsistencyIssues,\n parseDecisions,\n parseOpenQuestions,\n parseProgress,\n} from '../../../core/parser';\nimport { readIdeasMerged, readPlansMerged } from '../../../core/readers';\nimport { coerceAgentConfig } from '../../../types/index';\nimport { campFile, readMaybe } from '../helpers';\nimport { listConfigFiles } from './config';\nimport type { ReadRoute } from './types';\n\nexport const readRoutes: ReadRoute[] = [\n {\n path: '/api/package-name',\n handler: async (root) => {\n const raw = await readMaybe(join(root, 'package.json'));\n if (!raw) return null;\n try {\n const pkg = JSON.parse(raw);\n return pkg.name ?? null;\n } catch {\n return null;\n }\n },\n },\n {\n path: '/api/plans',\n handler: async (root) => readPlansMerged(campFile(root, 'plans'), campFile(root, 'plans.md')),\n },\n {\n path: '/api/progress',\n handler: async (root) => ({\n entries: parseProgress(await readMaybe(campFile(root, 'progress.md'))),\n }),\n },\n {\n path: '/api/decisions',\n handler: async (root) => parseDecisions(await readMaybe(campFile(root, 'decisions.md'))),\n },\n {\n path: '/api/open-questions',\n handler: async (root) =>\n parseOpenQuestions(await readMaybe(campFile(root, 'open-questions.md'))),\n },\n {\n path: '/api/ideas',\n handler: async (root) => readIdeasMerged(campFile(root, 'ideas'), campFile(root, 'ideas.md')),\n },\n {\n path: '/api/consistency',\n handler: async (root) => {\n const [decisionsRaw, openQuestionsRaw, plansResult] = await Promise.all([\n readMaybe(campFile(root, 'decisions.md')),\n readMaybe(campFile(root, 'open-questions.md')),\n readPlansMerged(campFile(root, 'plans'), campFile(root, 'plans.md')),\n ]);\n const decisions = parseDecisions(decisionsRaw);\n const openQuestions = parseOpenQuestions(openQuestionsRaw);\n return findConsistencyIssues(decisions.entries, openQuestions.entries, plansResult.entries);\n },\n },\n {\n path: '/api/config',\n handler: async (root) => {\n const raw = await readMaybe(join(root, 'papercamp', 'config.json'));\n if (!raw) return null;\n const config = JSON.parse(raw);\n // Coerce legacy bare-string defaultAgents (e.g. \"phase\": \"opencode\") into\n // the { agent, model?, effort? } shape the settings UI expects — old\n // config.json files predate FEAT-26 and would otherwise crash the page.\n if (config?.defaultAgents) {\n config.defaultAgents = {\n phase: coerceAgentConfig(config.defaultAgents.phase),\n planDraft: coerceAgentConfig(config.defaultAgents.planDraft),\n ideaExtend: coerceAgentConfig(config.defaultAgents.ideaExtend),\n commitSuggest: coerceAgentConfig(config.defaultAgents.commitSuggest),\n };\n }\n return config;\n },\n },\n {\n path: '/api/docs',\n handler: async (root) => {\n const docNames = ['MAIN.md', 'README.md', 'CHANGELOG.md', 'LICENSE'];\n const files: { name: string; content: string }[] = [];\n for (const name of docNames) {\n const content = await readMaybe(join(root, name));\n if (content) files.push({ name, content });\n }\n return { files };\n },\n },\n {\n path: '/api/configs',\n handler: async (root) => listConfigFiles(root),\n },\n];\n","import { agentRoutes } from './agent';\nimport { configRoutes } from './config';\nimport { docsRoutes } from './docs';\nimport { envRoutes } from './env';\nimport { gitRoutes } from './git';\nimport { iconRoutes } from './icon';\nimport { ideaRoutes } from './ideas';\nimport { planRoutes } from './plans';\nimport { statusRoutes } from './status';\nimport type { Route, RouteContext } from './types';\n\nexport { readRoutes } from './reads';\nexport type { ReadRoute, Route, RouteContext } from './types';\n\nexport function buildRoutes(ctx: RouteContext): Route[] {\n return [\n ...planRoutes(ctx),\n ...ideaRoutes(ctx),\n ...iconRoutes(ctx),\n ...gitRoutes(ctx),\n ...statusRoutes(ctx),\n ...agentRoutes(ctx),\n ...configRoutes(ctx),\n ...envRoutes(ctx),\n ...docsRoutes(ctx),\n ];\n}\n","import { spawn } from 'node:child_process';\nimport { watch } from 'node:fs';\nimport type { ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport type { CheckName, CheckResult, CheckStatus } from '../../types';\n\ninterface StatusSnapshot {\n lint: CheckResult;\n format: CheckResult;\n test: CheckResult;\n}\n\nconst CHECK_COMMANDS: Record<CheckName, string> = {\n lint: 'npx biome lint .',\n format: 'npx biome format .',\n test: 'npx vitest run',\n};\n\nexport type StatusManager = ReturnType<typeof createStatusManager>;\n\nexport function createStatusManager(root: string) {\n const clients = new Set<ServerResponse>();\n const snapshot: StatusSnapshot = {\n lint: { status: 'stale', lastRun: null, output: '' },\n format: { status: 'stale', lastRun: null, output: '' },\n test: { status: 'stale', lastRun: null, output: '' },\n };\n const running = new Set<CheckName>();\n const queued = new Set<CheckName>();\n\n function broadcast(event: { message: string; timestamp: string }) {\n const data = `data: ${JSON.stringify(event)}\\n\\n`;\n for (const client of clients) {\n try {\n client.write(data);\n } catch {\n clients.delete(client);\n }\n }\n }\n\n function setResult(name: CheckName, status: CheckStatus, output: string) {\n snapshot[name] = { status, lastRun: new Date().toISOString(), output };\n broadcast({\n message: `${name}: ${status}`,\n timestamp: snapshot[name].lastRun!,\n });\n if (status !== 'running' && queued.has(name)) {\n queued.delete(name);\n runCheck(name);\n }\n }\n\n function runCheck(name: CheckName) {\n if (running.has(name)) {\n queued.add(name);\n return;\n }\n running.add(name);\n setResult(name, 'running', '');\n\n const cmd = CHECK_COMMANDS[name];\n const proc = spawn(cmd, {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout?.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n proc.stderr?.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n\n proc.on('close', (code) => {\n running.delete(name);\n const output = stdout + stderr;\n if (code === 0) {\n setResult(name, 'pass', output);\n } else {\n setResult(name, 'fail', output);\n }\n });\n\n proc.on('error', (err) => {\n running.delete(name);\n setResult(name, 'fail', `Failed to spawn process: ${err.message}`);\n });\n }\n\n function runQualityFix() {\n if (running.has('lint') || running.has('format')) return;\n setResult('lint', 'running', 'Applying automatic fixes…');\n setResult('format', 'running', 'Applying automatic fixes…');\n\n const proc = spawn('npx biome check . --write', {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n proc.on('close', () => {\n runCheck('lint');\n runCheck('format');\n });\n\n proc.on('error', (err) => {\n const message = `Failed to spawn fix process: ${err.message}`;\n setResult('lint', 'fail', message);\n setResult('format', 'fail', message);\n });\n }\n\n const srcDir = join(root, 'src');\n let srcTimer: ReturnType<typeof setTimeout> | null = null;\n try {\n watch(srcDir, { recursive: true }, () => {\n if (srcTimer) clearTimeout(srcTimer);\n srcTimer = setTimeout(() => {\n runCheck('lint');\n runCheck('format');\n }, 1000);\n });\n } catch {\n // watcher not available (src/ doesn't exist or platform doesn't support recursive)\n }\n\n // One-shot: spawn fresh processes for all three checks and resolve true only if\n // all pass. Intentionally bypasses the queue so callers get a clean result that\n // reflects the current working tree rather than a stale cached status.\n function runChecksAndWait(): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const names: CheckName[] = ['lint', 'format', 'test'];\n const passed: Record<CheckName, boolean | null> = { lint: null, format: null, test: null };\n let pending = names.length;\n\n function onDone(name: CheckName, ok: boolean) {\n passed[name] = ok;\n pending--;\n if (pending === 0) resolve(names.every((n) => passed[n] === true));\n }\n\n for (const name of names) {\n const proc = spawn(CHECK_COMMANDS[name], { cwd: root, stdio: 'ignore', shell: true });\n proc.on('close', (code) => onDone(name, code === 0));\n proc.on('error', () => onDone(name, false));\n }\n });\n }\n\n return {\n getStatus(): StatusSnapshot {\n return {\n lint: { ...snapshot.lint },\n format: { ...snapshot.format },\n test: { ...snapshot.test },\n };\n },\n runCheck,\n runChecksAndWait,\n runQualityFix,\n subscribe(res: ServerResponse) {\n clients.add(res);\n for (const name of ['lint', 'format', 'test'] as CheckName[]) {\n const result = snapshot[name];\n if (result.status !== 'stale') {\n res.write(\n `data: ${JSON.stringify({ message: `${name}: ${result.status}`, timestamp: result.lastRun })}\\n\\n`,\n );\n }\n }\n res.on('close', () => clients.delete(res));\n },\n };\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { createActivityManager } from './activity';\nimport { type AgentManager, createAgentManager } from './agent';\nimport { createAgentHooks } from './agent-hooks';\nimport { createGitManager } from './git';\nimport { sendJson } from './http';\nimport { buildRoutes, readRoutes } from './routes/index';\nimport { createStatusManager } from './status';\n\nexport interface ApiMiddleware {\n (req: IncomingMessage, res: ServerResponse, next: () => void): Promise<void>;\n agent: AgentManager;\n}\n\nexport function createApiMiddleware(root: string): ApiMiddleware {\n const activity = createActivityManager(root);\n const git = createGitManager(root);\n const status = createStatusManager(root);\n const hooks = createAgentHooks(root, git);\n const agent = createAgentManager(\n root,\n (plan) => git.ensureBranch(plan),\n hooks.stampAuditDate,\n hooks.commitPhase,\n hooks.setRunReview,\n );\n\n const routes = buildRoutes({ root, activity, agent, git, status });\n\n const handler = async (req: IncomingMessage, res: ServerResponse, next: () => void) => {\n const pathname = (req.url ?? '').split('?')[0];\n\n const route = routes.find((r) => r.method === req.method && r.path === pathname);\n if (route) {\n try {\n await route.handle(req, res);\n } catch (error) {\n sendJson(res, 500, { error: (error as Error).message });\n }\n return;\n }\n\n const read = readRoutes.find((r) => r.path === pathname);\n if (!read) {\n next();\n return;\n }\n try {\n sendJson(res, 200, await read.handler(root));\n } catch (error) {\n sendJson(res, 500, { error: (error as Error).message });\n }\n };\n\n (handler as ApiMiddleware).agent = agent;\n return handler as ApiMiddleware;\n}\n","import { readFile, stat } from 'node:fs/promises';\nimport { type IncomingMessage, type ServerResponse, createServer } from 'node:http';\nimport { dirname, extname, join, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createApiMiddleware } from '../app/server/api';\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n};\n\nfunction appDir(): string {\n return join(dirname(fileURLToPath(import.meta.url)), '..', 'app');\n}\n\nexport interface DevServerOptions {\n root: string;\n port: number;\n}\n\n/**\n * Serves the pre-built dashboard SPA (dist/app) plus the papercamp/ API, for an\n * installed package where there's no Vite runtime available (it's a devDependency).\n */\nexport async function startDevServer({ root, port }: DevServerOptions): Promise<void> {\n const staticDir = appDir();\n const indexPath = join(staticDir, 'index.html');\n const indexHtml = await readFile(indexPath, 'utf-8').catch(() => null);\n if (indexHtml === null) {\n throw new Error(\n `Dashboard assets not found at ${staticDir}. Run \\`pnpm build\\` (or reinstall the package) so dist/app exists.`,\n );\n }\n\n const apiMiddleware = createApiMiddleware(root);\n\n async function serveStatic(req: IncomingMessage, res: ServerResponse) {\n const pathname = decodeURIComponent((req.url ?? '/').split('?')[0]);\n const filePath = join(staticDir, pathname === '/' ? 'index.html' : pathname);\n\n // join() normalizes `..`, so a crafted path like /../../.env would resolve\n // outside the asset directory and serve arbitrary files (the server binds all\n // interfaces). Anything that escapes staticDir gets the SPA fallback instead.\n const escapesStaticDir = filePath !== staticDir && !filePath.startsWith(staticDir + sep);\n\n try {\n const fileStat = escapesStaticDir ? null : await stat(filePath);\n if (fileStat?.isFile()) {\n res.statusCode = 200;\n res.setHeader('Content-Type', MIME[extname(filePath)] ?? 'application/octet-stream');\n res.end(await readFile(filePath));\n return;\n }\n } catch {\n // not a file on disk — fall through to the SPA fallback below\n }\n\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(indexHtml);\n }\n\n const server = createServer((req, res) => {\n apiMiddleware(req, res, () => {\n serveStatic(req, res).catch((error) => {\n res.statusCode = 500;\n res.end(String(error));\n });\n });\n });\n\n const shutdown = () => {\n apiMiddleware.agent.killCurrent();\n process.exit(0);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n // Reject on listen errors (EADDRINUSE etc.) — with only the success callback,\n // a taken port left this promise pending forever and the CLI hanging silently.\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, resolve);\n });\n}\n","#!/usr/bin/env node\nimport { spawn } from 'node:child_process';\nimport { mkdir, readFile, stat, writeFile } from 'node:fs/promises';\nimport { basename, join, resolve } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport { Command } from 'commander';\nimport { buildConvergenceAuditPrompt } from '../app/features/plans/prompts';\nimport { type AgentAdapter, resolveAgent } from '../app/server/agents/index';\nimport { deriveIdeaStatuses } from '../core/idea-status';\nimport { parseIdeas, parsePlanFile, parsePlans } from '../core/parser';\nimport { readAllIdeaFiles, readAllPlanFiles } from '../core/readers';\nimport { AlreadyInitializedError, PAPER_CAMP_VERSION, initProject } from '../core/scaffold';\nimport {\n assignPlanId,\n formatIdeaFile,\n formatIdeasIndex,\n formatPlanFile,\n formatPlansIndex,\n todayDateString,\n} from '../core/serializer';\nimport {\n type AgentRunOptions,\n DEFAULT_AGENTS,\n PLAN_KINDS,\n type PlanEntry,\n coerceAgentConfig,\n} from '../types/index';\nimport { startDevServer } from './dev-server';\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function findPlanFile(plansDir: string, id: string): Promise<string | null> {\n const direct = join(plansDir, `${id}.md`);\n if (await exists(direct)) return direct;\n const archived = join(plansDir, 'archive', `${id}.md`);\n if (await exists(archived)) return archived;\n return null;\n}\n\nasync function getFileMtimeDateString(filePath: string): Promise<string | null> {\n try {\n const s = await stat(filePath);\n return s.mtime.toISOString().slice(0, 10);\n } catch {\n return null;\n }\n}\n\nasync function stampCliAuditDate(planFile: string, planId: string): Promise<void> {\n // Throw on failure so the caller can mark the audit failed rather than\n // logging [done] while the audited stamp was silently never written.\n const raw = await readFile(planFile, 'utf-8');\n const parsed = parsePlanFile(raw);\n const entry = parsed.entries[0];\n if (!entry) {\n throw new Error(`Could not parse plan file after audit: ${planFile}`);\n }\n const writeInput: Parameters<typeof formatPlanFile>[0] = {\n id: planId,\n title: entry.title,\n kind: entry.kind ?? 'feat',\n status: entry.status,\n idea: entry.idea,\n agent: entry.agent,\n created: entry.created,\n updated: entry.updated,\n audited: todayDateString(),\n tags: entry.tags,\n body: entry.body,\n phases: entry.phases,\n log: entry.log,\n clarifications: entry.clarifications,\n };\n await writeFile(planFile, `${formatPlanFile(writeInput)}\\n`, 'utf-8');\n}\n\nasync function runPlanAudit(\n root: string,\n plan: PlanEntry,\n adapter: AgentAdapter,\n opts?: AgentRunOptions,\n): Promise<boolean> {\n const prompt = buildConvergenceAuditPrompt(plan);\n const proc = spawn(adapter.command, adapter.buildArgs(prompt, opts), {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n if (proc.stdout) {\n const rl = createInterface({ input: proc.stdout });\n rl.on('line', (line) => {\n const parsed = adapter.parseLine(line);\n if (parsed?.text && parsed.text !== 'Agent is working…') {\n process.stdout.write(` ${parsed.text}\\n`);\n }\n });\n }\n proc.stderr?.on('data', (d: Buffer) => process.stderr.write(d));\n\n return new Promise((resolve) => {\n proc.on('close', (code) => resolve(code === 0));\n proc.on('error', () => resolve(false));\n });\n}\n\nconst program = new Command();\n\nprogram\n .name('paper-camp')\n .description('Local-first, AI-native project companion.')\n .version(PAPER_CAMP_VERSION);\n\nprogram\n .command('init [project-name]')\n .description('Initialize Paper Camp in the current directory')\n .option('-i, --intent <text>', 'one-line description of what you are building')\n .action(async (projectName: string | undefined, opts: { intent?: string }) => {\n const targetDir = process.cwd();\n const name = projectName ?? basename(targetDir);\n try {\n await initProject(targetDir, { projectName: name, intent: opts.intent });\n console.log(`Initialized Paper Camp in ${targetDir}`);\n console.log(' papercamp/config.json');\n console.log(' papercamp/plans/ (per-file plan entries)');\n console.log(' papercamp/plans/index.md');\n console.log(' papercamp/plans/archive/');\n console.log(' papercamp/ideas/ (per-file idea entries)');\n console.log(' papercamp/ideas/index.md');\n console.log(' papercamp/progress.md, decisions.md, open-questions.md');\n } catch (error) {\n if (error instanceof AlreadyInitializedError) {\n console.error(error.message);\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n });\n\nprogram\n .command('dev')\n .description('Start the local dashboard')\n .option('-p, --port <number>', 'port to listen on', '3333')\n .action(async (opts: { port: string }) => {\n const port = Number(opts.port);\n const root = process.cwd();\n try {\n await startDevServer({ root, port });\n console.log(`Paper Camp dashboard running at http://localhost:${port}`);\n } catch (error) {\n console.error((error as Error).message);\n // Hard-exit: the API middleware's fs watchers are already running by the time\n // listen fails, and they keep the event loop alive forever with exitCode alone.\n process.exit(1);\n }\n });\n\nprogram\n .command('add <type> [name]')\n .description('Add a new entry (currently supports: plan)')\n .option('-k, --kind <kind>', `plan kind (${PLAN_KINDS.join('|')})`, 'feat')\n .action(async (type: string, name: string | undefined, opts: { kind: string }) => {\n if (type !== 'plan') {\n console.error(`Unknown type \"${type}\". Supported types: plan`);\n process.exitCode = 1;\n return;\n }\n if (!name) {\n console.error('Usage: paper-camp add plan <name> [--kind feat|fix|chore|docs|refactor]');\n process.exitCode = 1;\n return;\n }\n if (!PLAN_KINDS.includes(opts.kind as (typeof PLAN_KINDS)[number])) {\n console.error(`Unknown kind \"${opts.kind}\". Supported kinds: ${PLAN_KINDS.join(', ')}`);\n process.exitCode = 1;\n return;\n }\n\n const kind = opts.kind;\n const root = process.cwd();\n const configPath = resolve(root, 'papercamp', 'config.json');\n const id = await assignPlanId(configPath, kind);\n\n if (!id) {\n console.error('Could not assign plan ID — is the project initialized?');\n process.exitCode = 1;\n return;\n }\n\n const plansDir = resolve(root, 'papercamp', 'plans');\n await mkdir(plansDir, { recursive: true });\n\n const planContent = formatPlanFile({\n id,\n title: name,\n kind,\n status: 'idea',\n created: todayDateString(),\n });\n await writeFile(join(plansDir, `${id}.md`), `${planContent}\\n`, 'utf-8');\n\n // Regenerate index\n const { entries } = await readAllPlanFiles(plansDir);\n await writeFile(join(plansDir, 'index.md'), formatPlansIndex(entries), 'utf-8');\n\n console.log(`Added plan \"${name}\" (${id}) to papercamp/plans/${id}.md`);\n });\n\nprogram\n .command('migrate')\n .description(\n 'One-time migration: split monolithic plans.md/ideas.md into per-file YAML frontmatter entries',\n )\n .action(async () => {\n const root = process.cwd();\n const plansDir = resolve(root, 'papercamp', 'plans');\n const archiveDir = join(plansDir, 'archive');\n const ideasDir = resolve(root, 'papercamp', 'ideas');\n await mkdir(archiveDir, { recursive: true });\n await mkdir(ideasDir, { recursive: true });\n\n const plansPath = resolve(root, 'papercamp', 'plans.md');\n const ideasPath = resolve(root, 'papercamp', 'ideas.md');\n\n let migratedPlans = 0;\n let skippedPlans = 0;\n let planWarnings = 0;\n const plansRaw = await readFile(plansPath, 'utf-8').catch(() => '');\n if (plansRaw.trim()) {\n const { entries, warnings } = parsePlans(plansRaw);\n planWarnings = warnings.length;\n for (const warning of warnings) {\n console.warn(` warning: ${warning.title}: ${warning.message}`);\n }\n for (const entry of entries) {\n if (!entry.id) {\n console.warn(` skipping plan \"${entry.title}\" — no Id assigned, cannot migrate`);\n skippedPlans++;\n continue;\n }\n const targetDir =\n entry.status === 'done' || entry.status === 'dropped' ? archiveDir : plansDir;\n const targetFile = join(targetDir, `${entry.id}.md`);\n if (await exists(targetFile)) {\n skippedPlans++;\n continue;\n }\n const content = formatPlanFile({\n id: entry.id,\n title: entry.title,\n kind: entry.kind ?? 'feat',\n status: entry.status,\n idea: entry.idea,\n agent: entry.agent,\n created: entry.created,\n updated: entry.updated,\n tags: entry.tags,\n body: entry.body,\n phases: entry.phases,\n log: entry.log,\n clarifications: entry.clarifications,\n });\n await writeFile(targetFile, `${content}\\n`, 'utf-8');\n migratedPlans++;\n }\n }\n\n let migratedIdeas = 0;\n let skippedIdeas = 0;\n const ideasRaw = await readFile(ideasPath, 'utf-8').catch(() => '');\n if (ideasRaw.trim()) {\n const entries = parseIdeas(ideasRaw);\n for (const idea of entries) {\n if (!idea.id) {\n console.warn(` skipping idea \"${idea.title}\" — no Id assigned, cannot migrate`);\n skippedIdeas++;\n continue;\n }\n const targetFile = join(ideasDir, `${idea.id}.md`);\n if (await exists(targetFile)) {\n skippedIdeas++;\n continue;\n }\n const body = idea.body.replace(/^#{1,3}\\s+.+(?:\\r?\\n)?/, '').trim();\n const content = formatIdeaFile({ id: idea.id, title: idea.title, body });\n await writeFile(targetFile, `${content}\\n`, 'utf-8');\n migratedIdeas++;\n }\n }\n\n const { entries: allPlans } = await readAllPlanFiles(plansDir);\n await writeFile(join(plansDir, 'index.md'), formatPlansIndex(allPlans), 'utf-8');\n const { entries: allIdeas } = await readAllIdeaFiles(ideasDir);\n const ideasWithStatus = deriveIdeaStatuses(allIdeas, allPlans);\n await writeFile(join(ideasDir, 'index.md'), formatIdeasIndex(ideasWithStatus), 'utf-8');\n\n // Empty, not a pointer comment: readPlansMerged/readIdeasMerged fast-path on falsy\n // monolithic content, and parseIdeas() in particular has no heading match for plain\n // prose, producing a phantom null-id entry that the merge step's dedup logic always\n // keeps. A truly empty file avoids both parsers entirely.\n if (migratedPlans > 0 && skippedPlans === 0 && planWarnings === 0) {\n await writeFile(plansPath, '', 'utf-8');\n }\n if (migratedIdeas > 0 && skippedIdeas === 0) {\n await writeFile(ideasPath, '', 'utf-8');\n }\n\n console.log(\n `Migrated ${migratedPlans} plans (${skippedPlans} skipped), ${migratedIdeas} ideas (${skippedIdeas} skipped).`,\n );\n });\n\nprogram\n .command('audit')\n .description('Audit all review/done plans for missing phases')\n .action(async () => {\n const root = process.cwd();\n const plansDir = resolve(root, 'papercamp', 'plans');\n\n const { entries, warnings } = await readAllPlanFiles(plansDir);\n\n for (const warning of warnings) {\n console.warn(` warning: ${warning.title}: ${warning.message}`);\n }\n\n const candidates = entries.filter((p) => p.status === 'review' || p.status === 'done');\n\n if (candidates.length === 0) {\n console.log('No plans with status \"review\" or \"done\" found.');\n return;\n }\n\n const configRaw = await readFile(join(root, 'papercamp', 'config.json'), 'utf-8').catch(\n () => '{}',\n );\n let config: {\n defaultAgents?: Record<string, unknown>;\n defaultAgent?: string;\n };\n try {\n config = JSON.parse(configRaw) as typeof config;\n } catch {\n console.error('Invalid papercamp/config.json');\n process.exitCode = 1;\n return;\n }\n const rawAgents = config.defaultAgents;\n const defaultAgents = rawAgents\n ? {\n phase: coerceAgentConfig(rawAgents.phase),\n planDraft: coerceAgentConfig(rawAgents.planDraft),\n ideaExtend: coerceAgentConfig(rawAgents.ideaExtend),\n commitSuggest: coerceAgentConfig(rawAgents.commitSuggest),\n }\n : DEFAULT_AGENTS;\n const { adapter, model, effort } = resolveAgent({ defaultAgents, taskKind: 'audit' });\n\n console.log(`Auditing ${candidates.length} plan(s):\\n`);\n\n interface AuditResult {\n id: string;\n title: string;\n status: 'audited' | 'skipped' | 'failed';\n gapPhases?: number;\n skipReason?: string;\n }\n\n const results: AuditResult[] = [];\n\n for (const plan of candidates) {\n const id = plan.id ?? '(no id)';\n const label = id.padEnd(14);\n\n if (!plan.id) {\n console.log(` [skip] ${label} ${plan.title} — no id`);\n results.push({ id, title: plan.title, status: 'skipped', skipReason: 'no id' });\n continue;\n }\n\n const planFile = await findPlanFile(plansDir, plan.id);\n if (!planFile) {\n console.log(` [skip] ${label} ${plan.title} — file not found`);\n results.push({ id, title: plan.title, status: 'skipped', skipReason: 'file not found' });\n continue;\n }\n\n if (plan.audited) {\n const mtimeDate = await getFileMtimeDateString(planFile);\n if (mtimeDate && plan.audited >= mtimeDate) {\n console.log(\n ` [skip] ${label} ${plan.title} — audited ${plan.audited}, unchanged since`,\n );\n results.push({\n id,\n title: plan.title,\n status: 'skipped',\n skipReason: `audited ${plan.audited}, unchanged`,\n });\n continue;\n }\n }\n\n const phasesBefore = plan.phases.length;\n\n console.log(` [audit] ${label} ${plan.title}`);\n const success = await runPlanAudit(root, plan, adapter, { model, effort });\n\n if (success) {\n try {\n await stampCliAuditDate(planFile, plan.id);\n } catch (err) {\n console.log(` [fail] ${label} ${plan.title} — ${(err as Error).message}`);\n process.exitCode = 1;\n results.push({ id, title: plan.title, status: 'failed' });\n continue;\n }\n\n const afterRaw = await readFile(planFile, 'utf-8').catch(() => '');\n const afterParsed = parsePlanFile(afterRaw);\n const phasesAfter = afterParsed.entries[0]?.phases.length ?? phasesBefore;\n const gapPhases = Math.max(0, phasesAfter - phasesBefore);\n\n console.log(` [done] ${label} ${plan.title}`);\n results.push({ id, title: plan.title, status: 'audited', gapPhases });\n } else {\n console.log(` [fail] ${label} ${plan.title} — agent exited with error`);\n process.exitCode = 1;\n results.push({ id, title: plan.title, status: 'failed' });\n }\n }\n\n const audited = results.filter((r) => r.status === 'audited');\n const skipped = results.filter((r) => r.status === 'skipped');\n const failed = results.filter((r) => r.status === 'failed');\n const totalGaps = audited.reduce((sum, r) => sum + (r.gapPhases ?? 0), 0);\n const bar = '─'.repeat(43);\n\n console.log(`\\n${bar}`);\n console.log('Audit summary');\n console.log(\n ` Audited : ${audited.length} Skipped : ${skipped.length} Failed : ${failed.length}`,\n );\n if (audited.length > 0) {\n if (totalGaps > 0) {\n console.log(` Gap phases appended: ${totalGaps} total`);\n for (const r of audited.filter((r) => (r.gapPhases ?? 0) > 0)) {\n console.log(` ${r.id.padEnd(14)} +${r.gapPhases} phase(s)`);\n }\n } else {\n console.log(' No gap phases appended — all audited plans are complete.');\n }\n }\n if (skipped.length > 0) {\n console.log(' Skipped:');\n for (const r of skipped) {\n console.log(` ${r.id.padEnd(14)} ${r.skipReason}`);\n }\n }\n console.log(bar);\n });\n\nprogram.parseAsync(process.argv);\n"],"names":["buildConvergenceAuditPrompt","plan","phaseList","phase","i","logList","entry","clarificationsList","buildArgs","prompt","opts","args","parseLine","line","json","message","blocks","block","b","content","error","TOOL_LABELS","type","part","text","tool","input","desc","label","detail","reason","DEFAULT_AGENT_ID","AGENTS","claudeCode.buildArgs","claudeCode.parseLine","AGENT_OPTIONS","opencode.buildArgs","opencode.parseLine","TASK_KIND_TO_DEFAULT_KEY","resolveAgent","agentId","defaultAgents","taskKind","key","fallback","id","deriveIdeaStatuses","ideas","plans","idea","linkedPlans","p","allDone","createActivityManager","root","clients","timer","broadcast","data","client","watch","join","res","connected","MAX_LINES","PHASE_TIMEOUT_MS","readDefaultAgentIds","raw","readFileSync","config","rawAgents","coerceAgentConfig","DEFAULT_AGENTS","buildAgentPrompt","phaseIndex","details","createAgentManager","ensureBranch","onAuditComplete","onPhaseCommit","onRunComplete","current","pushLine","task","setStatus","status","didTaskProgress","ideasDir","entries","readIdeasMerged","e","readPlansMerged","plansDir","_a","_b","finishTask","progressed","warning","attachReader","createInterface","parsed","code","err","spawnAgent","adapter","spawn","isBusy","launch","identity","scope","model","effort","proc","start","startForPlan","startForIdea","startForIdeaExtend","startSync","findBatchPlanFile","direct","stat","archived","startBatchAudit","stubProc","readAllPlanFiles","candidates","audited","skipped","failed","planFile","fileStat","mtimeDate","success","resolve","gapPhases","rawAfter","readFile","afterCount","parsePlanFile","startRunAllPhases","runProjectChecks","unchecked","total","completed","timedOut","procDone","timeoutHandle","exitedOk","checksOk","COMMIT_SUGGEST_TIMEOUT_MS","STDIN_MAX_BYTES","runCommitSuggest","isClaude","reject","settled","settle","fn","timeout","_c","stdout","stderr","_d","d","_e","result","evt","errText","stop","getStatus","readMaybe","path","fileExists","campFile","name","planFileInput","overrides","writePlanFile","writeFile","formatPlanFile","regenerateIndexes","plansResult","ideasResult","ideasWithStatus","mkdir","formatPlansIndex","formatIdeasIndex","checkBranchConflictForPlan","git","targetPlanId","activePlanId","activePlan","createAgentHooks","prependProgressItem","item","progressPath","heading","todayDateString","trimmed","next","stampAuditDate","planId","directPlanFile","archivedPlanFile","commitPhase","area","title","refs","setRunReview","AI_DIFF_BLOCKLIST","toLiteralPathspec","file","createGitManager","options","event","parsePorcelain","output","x","y","rest","parts","runGit","runGitStatus","commit","files","renameSources","statusEntries","statusByPath","toAdd","f","pathspecs","source","kind","branch","currentResult","spawnSync","checkoutResult","refresh","gitDir","eventType","filename","srcDir","srcTimer","hasUpstream","getAheadCount","push","getCurrentBranch","isMergedIntoMain","currentBranch","getBranchHygieneStatus","isDirty","n","getFeatureBranchPlanId","match","diff","maxChars","blocked","pattern","untracked","tracked","trackedDiff","filePath","stats","lstat","combined","stageAll","runGitSync","sendJson","statusCode","readBody","req","body","chunk","requestUrl","resolvePlanFilePath","primary","KNOWN_RENAMES","applyKnownRenames","frontmatterEnd","frontmatter","lines","changed","skippingCheckedPhase","updated","from","to","findPlanById","parsePlans","findIdeaById","ideaId","readAllIdeaFiles","parseIdeas","agentRoutes","agent","_req","reqBody","conflict","CONFIG_ALLOWLIST","listConfigFiles","configRoutes","configPath","bodyParsed","port","projectName","defaultAgent","rawDefaultAgents","AGENT_IDS","val","resolvedDefaultAgents","configWithOld","_oldAgent","configRest","docsRoutes","decision","rationale","questionsPath","parseOpenQuestions","w","target","q","decisionBlock","formatDecisionEntry","appendBlock","formatOpenQuestions","envRoutes","envPath","examplePath","exists","exampleExists","parseEnv","exampleKeys","envKeys","missingKeys","keys","applyEnvEntries","findFocusPlan","activePlanTitle","buildPrompt","diffText","planContext","suggestCommitMessage","runPrompt","resultText","DIRTY_SYNC_PROMPT","gitRoutes","ahead","branchHygiene","mode","suggestion","MIME_BY_EXT","iconRoutes","assetsDir","ext","mime","dataUri","buffer","unlink","ideaRoutes","newId","max","num","ideaContent","formatIdeaFile","planRoutes","planKind","PLAN_KINDS","assignPlanId","planContent","updates","targetFile","updatedEntry","allPlans","other","otherFile","otherRaw","otherParsed","archivePlanFile","statusRoutes","activity","readRoutes","parseProgress","parseDecisions","decisionsRaw","openQuestionsRaw","decisions","openQuestions","findConsistencyIssues","docNames","buildRoutes","ctx","CHECK_COMMANDS","createStatusManager","snapshot","running","queued","setResult","runCheck","cmd","runQualityFix","runChecksAndWait","names","passed","pending","onDone","ok","createApiMiddleware","hooks","routes","handler","pathname","route","r","read","MIME","appDir","dirname","fileURLToPath","startDevServer","staticDir","indexPath","indexHtml","apiMiddleware","serveStatic","escapesStaticDir","sep","extname","server","createServer","shutdown","findPlanFile","getFileMtimeDateString","stampCliAuditDate","writeInput","runPlanAudit","program","Command","PAPER_CAMP_VERSION","targetDir","basename","initProject","AlreadyInitializedError","archiveDir","plansPath","ideasPath","migratedPlans","skippedPlans","planWarnings","plansRaw","warnings","migratedIdeas","skippedIdeas","ideasRaw","allIdeas","configRaw","results","phasesBefore","afterRaw","phasesAfter","totalGaps","sum","bar"],"mappings":"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"}
|