cubefarm 0.3.8 → 0.3.10

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../server/index.ts", "../server/config.ts", "../server/exec.ts", "../server/github.ts", "../server/workspace.ts", "../server/agentRunner.ts", "../server/browser.ts", "../server/cliRunner.ts", "../server/clis.ts", "../server/ptyClient.ts", "../server/ptyProtocol.ts", "../server/previewRunner.ts", "../server/officeUpdate.ts", "../server/backend.ts", "../server/demo.ts", "../server/swarm.ts", "../server/ceo.ts", "../shared/issues.ts", "../server/fixOutcome.ts", "../server/httpError.ts", "../server/issueClaims.ts", "../server/mergeGate.ts", "../server/qaOrphans.ts", "../server/restartRecovery.ts", "../server/previews.ts", "../server/prompts.ts", "../server/pacing.ts", "../server/terminal.ts", "../shared/models.ts", "../shared/types.ts"],
4
- "sourcesContent": ["import http from 'node:http';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport express, { type NextFunction, type Request, type Response } from 'express';\nimport type { AddressInfo } from 'node:net';\nimport { WebSocketServer } from 'ws';\nimport { DEMO, PORT, STATE_FILE, WORKSPACE_ROOT } from './config.ts';\nimport { realBackend } from './backend.ts';\nimport { handleHook, handleMcp, setOfficeUrl } from './cliRunner.ts';\nimport { createDemoBackend } from './demo.ts';\nimport { underLauncher } from './officeUpdate.ts';\nimport { HttpError, Swarm } from './swarm.ts';\n\nconst swarm = new Swarm(DEMO ? createDemoBackend() : realBackend);\n// Sessions the office picks back up while it starts need the address their CLIs call back on before it listens.\nif (PORT) setOfficeUrl(`http://127.0.0.1:${PORT}`);\nawait swarm.init();\n\nconst app = express();\n// Agent CLIs calling back: hooks (a tool result can be a large screenshot, hence the limit) and the CEO's office tools.\n// The token in the path is the session's; unknown tokens get an empty answer.\napp.post('/api/hooks/:token', express.json({ limit: '64mb' }), (req, res) => void res.json(handleHook(String(req.params.token), req.body)));\napp.post('/api/mcp/:token', express.json({ limit: '4mb' }), (req, res, next) => void handleMcp(String(req.params.token), req, res).catch(next));\napp.all('/api/mcp/:token', (_req, res) => void res.status(405).set('Allow', 'POST').end());\napp.use(express.json({ limit: '1mb' }));\n\ntype Handler = (req: Request, res: Response) => Promise<unknown> | unknown;\nconst route = (fn: Handler) => async (req: Request, res: Response, next: NextFunction) => {\n try {\n const out = await fn(req, res);\n if (!res.headersSent) res.json(out ?? { ok: true });\n } catch (err) {\n next(err);\n }\n};\nconst num = (v: unknown) => {\n const n = Number(v);\n if (!Number.isInteger(n) || n <= 0) throw new HttpError(400, `Invalid number: ${v}`);\n return n;\n};\nconst str = (v: unknown) => (typeof v === 'string' ? v : '');\n// Repo ids contain a slash (\"owner/name\"), so they travel URL-encoded as a single segment.\nconst repoId = (req: Request) => decodeURIComponent(String(req.params.repo));\n\napp.get('/api/state', route(() => swarm.snapshot()));\n\napp.get('/api/github/repos', route((req) => swarm.listGithubRepos(str(req.query.owner) || undefined)));\n\n// What happens once a project moves in: the CEO's brief, and whether work starts on its own.\nconst floorOptions = (req: Request) => ({ mission: str(req.body.mission), autoAssign: req.body.autoAssign === true });\n\napp.post('/api/repos', route((req) => swarm.connectRepo(str(req.body.fullName).trim(), floorOptions(req))));\n\n// Your projects folder\napp.get('/api/folders', route((req) => swarm.listProjectFolders(str(req.query.dir) || undefined)));\napp.post('/api/folders/connect', route((req) => swarm.connectFolder(str(req.body.path), floorOptions(req))));\napp.post(\n '/api/folders/publish',\n route((req) =>\n swarm.publishFolder(str(req.body.path), {\n ...floorOptions(req),\n name: str(req.body.name) || undefined,\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\n description: str(req.body.description),\n }),\n ),\n);\napp.post(\n '/api/setup',\n route((req) =>\n swarm.setup({\n managerName: str(req.body.managerName),\n companyName: str(req.body.companyName),\n hiring: str(req.body.hiring),\n ceoName: str(req.body.ceoName),\n ceoLook: str(req.body.ceoLook),\n ceoColor: str(req.body.ceoColor),\n }),\n ),\n);\napp.post(\n '/api/repos/new',\n route((req) =>\n swarm.createRepo(str(req.body.name).trim(), {\n ...floorOptions(req),\n description: str(req.body.description),\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\n owner: str(req.body.owner).trim() || undefined,\n }),\n ),\n);\napp.patch('/api/repos/:repo', route((req) => swarm.updateRepo(repoId(req), req.body ?? {})));\napp.delete('/api/repos/:repo', route((req) => swarm.disconnectRepo(repoId(req))));\napp.post('/api/repos/:repo/sync', route((req) => swarm.syncRepo(repoId(req))));\napp.post('/api/repos/:repo/sync-folder', route((req) => swarm.syncFolderNow(repoId(req))));\napp.post(\n '/api/repos/:repo/issues',\n route(async (req) => ({\n number: await swarm.createIssue(repoId(req), str(req.body.title), str(req.body.body), str(req.body.assignTo) || undefined, str(req.body.specialty) || undefined),\n })),\n);\napp.post('/api/repos/:repo/plan', route((req) => swarm.planFloor(repoId(req), typeof req.body?.mission === 'string' ? req.body.mission : undefined)));\napp.post('/api/repos/:repo/onboard', route((req) => swarm.onboardFloor(repoId(req))));\n// The floor's app, for the preview monitor\napp.post(\n '/api/repos/:repo/preview',\n route((req) => {\n const pr = req.body?.pr;\n if (pr !== undefined && pr !== null && (typeof pr !== 'number' || !Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, 'pr must be a positive integer');\n return swarm.startPreview(repoId(req), pr ?? null);\n }),\n);\napp.delete('/api/repos/:repo/preview', route((req) => swarm.stopPreview(repoId(req))));\napp.post('/api/repos/:repo/pulls/:n/merge', route((req) => swarm.mergePull(repoId(req), num(req.params.n), req.body?.method ?? 'squash')));\napp.post('/api/repos/:repo/pulls/:n/close', route((req) => swarm.closePull(repoId(req), num(req.params.n))));\napp.post('/api/repos/:repo/pulls/:n/qa', route((req) => swarm.sendToQa(repoId(req), num(req.params.n))));\napp.post(\n '/api/repos/:repo/agents',\n route((req) =>\n swarm.hireAgent(repoId(req), {\n name: str(req.body.name),\n model: str(req.body.model),\n effort: str(req.body.effort),\n role: str(req.body.role),\n look: str(req.body.look),\n title: str(req.body.title),\n specialty: str(req.body.specialty),\n brief: str(req.body.brief),\n }),\n ),\n);\n\napp.patch('/api/agents/:id', route((req) => swarm.updateAgent(String(req.params.id), req.body ?? {})));\napp.delete('/api/agents/:id', route((req) => swarm.fireAgent(String(req.params.id))));\napp.post('/api/agents/:id/assign', route((req) => swarm.assign(String(req.params.id), num(req.body.issueNumber), str(req.body.note) || undefined)));\napp.post('/api/agents/:id/stop', route((req) => swarm.stopAgent(String(req.params.id))));\napp.post('/api/agents/:id/reset', route((req) => swarm.resetAgent(String(req.params.id))));\napp.post('/api/agents/:id/message', route((req) => swarm.message(String(req.params.id), str(req.body.text))));\napp.get('/api/agents/:id/prompt', route((req) => swarm.agentPrompt(String(req.params.id))));\napp.get('/api/agents/:id/screen', (req, res) => {\n const shot = swarm.screenshot(String(req.params.id));\n if (!shot) return void res.status(404).end();\n res.setHeader('Content-Type', shot.mime);\n res.setHeader('Cache-Control', 'no-store');\n res.end(shot.data);\n});\n\napp.patch('/api/settings', route((req) => swarm.updateSettings(req.body ?? {})));\n// The office's own update: Update now / Later\napp.post('/api/office/update', route((req) => swarm.updateOffice(req.body?.action)));\n\n// The CEO and the manager's phone\napp.post('/api/ceo/message', route((req) => swarm.messageCeo(str(req.body.text))));\napp.post('/api/ceo/review', route(() => swarm.requestReview()));\napp.post('/api/phone/read', route((req) => swarm.markPhoneRead(Number(req.body?.at) || Date.now())));\napp.post(\n '/api/requests/:id/approve',\n route((req) => swarm.approveRequest(String(req.params.id), { name: str(req.body?.name) || undefined, model: typeof req.body?.model === 'string' ? req.body.model : undefined, effort: typeof req.body?.effort === 'string' ? req.body.effort : undefined })),\n);\napp.post('/api/requests/:id/reject', route((req) => swarm.rejectRequest(String(req.params.id), str(req.body?.note))));\n\n// Serve the built client: the published package, or `npm start` after `npm run build`.\nconst dist = path.resolve(import.meta.dirname, '../dist');\nif (fs.existsSync(dist)) {\n app.use(express.static(dist));\n app.get(/^(?!\\/api).*/, (_req, res) => res.sendFile(path.join(dist, 'index.html')));\n}\n\napp.use((err: unknown, _req: Request, res: Response, _next: NextFunction) => {\n // express.json() flags malformed bodies with a 4xx status of its own.\n const parserStatus = (err as { status?: unknown })?.status;\n const status = err instanceof HttpError ? err.status : typeof parserStatus === 'number' && parserStatus >= 400 && parserStatus < 500 ? parserStatus : 500;\n const message = err instanceof Error ? err.message : String(err);\n if (status >= 500) console.error(err);\n res.status(status).json({ error: message });\n});\n\nconst server = http.createServer(app);\n// Two sockets: /ws carries the office's state to every tab, /ws/term?agent=<id> one agent's terminal to whoever opened it.\nconst wss = new WebSocketServer({ noServer: true });\nconst terms = new WebSocketServer({ noServer: true });\nwss.on('connection', (ws) => swarm.addClient(ws));\nterms.on('connection', (ws, req) => swarm.attachTerminal(new URL(req.url ?? '', 'http://localhost').searchParams.get('agent') ?? '', ws));\nserver.on('upgrade', (req, socket, head) => {\n const { pathname } = new URL(req.url ?? '', 'http://localhost');\n const target = pathname === '/ws' ? wss : pathname === '/ws/term' ? terms : null;\n if (!target) return void socket.destroy();\n target.handleUpgrade(req, socket, head, (ws) => target.emit('connection', ws, req));\n});\n\nserver.listen(PORT, '127.0.0.1', () => {\n setOfficeUrl(`http://127.0.0.1:${(server.address() as AddressInfo).port}`);\n console.log(`\\n \uD83C\uDFE2 cubefarm on http://localhost:${PORT}${DEMO ? ' (DEMO MODE: fake GitHub + fake agents)' : ''}`);\n console.log(` state: ${STATE_FILE}`);\n console.log(` workspaces: ${WORKSPACE_ROOT}\\n`);\n});\n\n// Floors' apps don't outlive the office. (A hard kill skips this; the next start clears the orphans.) Agents' CLIs\n// carry on through a restart and stop when the office quits.\nlet closing = false;\nconst shutdown = (signal: string) => {\n if (closing) return;\n closing = true;\n console.log(`\\n ${signal}: stopping floor previews\u2026`);\n const force = setTimeout(() => process.exit(0), 15_000);\n void swarm\n .shutdown(signal === 'restart')\n .catch((err) => console.error(err))\n .finally(() => {\n clearTimeout(force);\n process.exit(0);\n });\n};\nprocess.once('SIGINT', () => shutdown('SIGINT'));\nprocess.once('SIGTERM', () => shutdown('SIGTERM'));\nprocess.once('SIGHUP', () => shutdown('SIGHUP')); // its terminal window closed (macOS, Linux; Windows' console too)\n// The launcher asks the office to stop: to restart it (an update, a code change) unless it says it's quitting.\nif (underLauncher()) {\n process.on('message', (msg) => {\n const m = msg as { type?: unknown; restart?: unknown } | null;\n if (m?.type === 'office:shutdown') shutdown(m.restart === false ? 'stop' : 'restart');\n });\n}\n", "import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nexport const PORT = Number(process.env.SWARM_PORT ?? 4317);\n// package.json sits one folder up both from server/ and from the published dist-server/.\nexport const VERSION: string = JSON.parse(fs.readFileSync(path.resolve(import.meta.dirname, '..', 'package.json'), 'utf8')).version;\n\n// Everything the swarm writes lives outside this project so that agents working in\n// cloned repos never pick up this project's CLAUDE.md or settings by walking up the tree.\nexport const HOME_DIR = process.env.SWARM_HOME ?? path.join(os.homedir(), '.cubefarm');\nexport const WORKSPACE_ROOT = path.join(HOME_DIR, 'workspaces');\nexport const DEMO = process.argv.includes('--demo') || process.env.SWARM_DEMO === '1' || process.env.SWARM_DEMO === 'true';\nexport const STATE_FILE = path.join(HOME_DIR, DEMO ? 'demo-state.json' : 'state.json');\n\n// How often each connected repo's issues and PRs are refreshed from GitHub.\nexport const SYNC_INTERVAL_MS = 45_000;\n// How often idle agents on auto-assign floors look for new work.\nexport const SCHEDULER_INTERVAL_MS = 8_000;\n// How often each floor's desks and finished branches are swept (also at start and after a let-go).\nexport const DESK_SWEEP_INTERVAL_MS = 30 * 60_000;\n// Terminal lines kept per agent.\nexport const LOG_BUFFER = 600;\n\n/**\n * Where new projects go unless the manager picks another folder. Run from a checkout, that's the folder the app sits\n * in (C:\\Projects\\cubefarm \u2192 C:\\Projects). Installed from npm the app lives in node_modules, so it's the usual\n * projects folder in your home instead.\n */\nexport function defaultProjectsDir(appDir: string, home = os.homedir()): string {\n if (!appDir.split(/[\\\\/]/).includes('node_modules')) return path.resolve(appDir, '..');\n const names = ['Projects', 'projects', 'code', 'Code', 'dev', 'Developer', 'src', 'repos', 'git', 'GitHub'];\n return names.map((n) => path.join(home, n)).find((d) => fs.existsSync(d)) ?? path.join(home, 'Projects');\n}\n", "import { execFile } from 'node:child_process';\n\nexport class CommandError extends Error {\n constructor(\n message: string,\n public readonly stderr: string,\n public readonly code: number | null,\n ) {\n super(message);\n }\n}\n\n/** Run a CLI (gh, git) without a shell and return trimmed stdout. */\nexport function run(cmd: string, args: string[], opts: { cwd?: string; timeoutMs?: number; input?: string } = {}): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = execFile(\n cmd,\n args,\n {\n cwd: opts.cwd,\n timeout: opts.timeoutMs ?? 120_000,\n maxBuffer: 32 * 1024 * 1024,\n windowsHide: true,\n env: { ...process.env, GH_PROMPT_DISABLED: '1', GIT_TERMINAL_PROMPT: '0', NO_COLOR: '1' },\n },\n (err, stdout, stderr) => {\n if (err) {\n const detail = (stderr || err.message).toString().trim();\n reject(new CommandError(`${cmd} ${args.slice(0, 3).join(' ')} failed: ${detail}`, stderr?.toString() ?? '', (err as { code?: number }).code ?? null));\n return;\n }\n resolve(stdout.toString().trim());\n },\n );\n if (opts.input !== undefined) {\n child.stdin?.end(opts.input);\n }\n });\n}\n\nexport const gh = (args: string[], opts?: { cwd?: string; timeoutMs?: number; input?: string }) => run('gh', args, opts);\nexport const git = (args: string[], opts?: { cwd?: string; timeoutMs?: number }) => run('git', args, opts);\n\nexport async function ghJson<T>(args: string[], opts?: { cwd?: string; timeoutMs?: number }): Promise<T> {\n const out = await gh(args, opts);\n return (out ? JSON.parse(out) : null) as T;\n}\n", "import { gh, ghJson } from './exec.ts';\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\n\n// All GitHub access goes through the gh CLI so it reuses the user's existing `gh auth login`.\n\nexport async function currentUser(): Promise<string> {\n return gh(['api', 'user', '--jq', '.login']);\n}\n\nexport async function listMyRepos(owner?: string): Promise<GhRepoSummary[]> {\n const args = ['repo', 'list'];\n if (owner) args.push(owner);\n args.push('--limit', '200', '--json', 'nameWithOwner,description,visibility,updatedAt');\n const repos = await ghJson<GhRepoSummary[]>(args);\n return repos.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n}\n\nexport interface RepoMeta {\n nameWithOwner: string;\n description: string;\n url: string;\n defaultBranch: string;\n}\n\nexport async function repoMeta(fullName: string): Promise<RepoMeta> {\n const raw = await ghJson<{ nameWithOwner: string; description: string | null; url: string; defaultBranchRef: { name: string } | null }>([\n 'repo',\n 'view',\n fullName,\n '--json',\n 'nameWithOwner,description,url,defaultBranchRef',\n ]);\n return {\n nameWithOwner: raw.nameWithOwner,\n description: raw.description ?? '',\n url: raw.url,\n defaultBranch: raw.defaultBranchRef?.name || 'main',\n };\n}\n\nexport async function listIssues(fullName: string): Promise<IssueInfo[]> {\n const raw = await ghJson<\n { number: number; title: string; body: string; url: string; labels: { name: string }[]; createdAt: string }[]\n >(['issue', 'list', '-R', fullName, '--state', 'open', '--limit', '100', '--json', 'number,title,body,url,labels,createdAt']);\n return raw\n .map((i) => ({ number: i.number, title: i.title, body: i.body ?? '', url: i.url, labels: i.labels.map((l) => l.name), createdAt: i.createdAt }))\n .sort((a, b) => a.number - b.number);\n}\n\ninterface RawPull {\n number: number;\n title: string;\n url: string;\n headRefName: string;\n state: 'OPEN' | 'CLOSED' | 'MERGED';\n isDraft: boolean;\n mergeable: string;\n reviewDecision: string | null;\n closingIssuesReferences: { number: number }[] | null;\n createdAt: string;\n mergedAt: string | null;\n additions: number;\n deletions: number;\n headRefOid: string;\n mergeStateStatus: string;\n // check runs (GitHub Actions\u2026) carry name/status/conclusion/detailsUrl; commit statuses (Vercel\u2026) carry context/state/targetUrl\n statusCheckRollup: { name?: string; context?: string; status?: string; conclusion?: string; state?: string; detailsUrl?: string; targetUrl?: string }[] | null;\n}\n\nconst PR_FIELDS =\n 'number,title,url,headRefName,headRefOid,state,isDraft,mergeable,mergeStateStatus,reviewDecision,closingIssuesReferences,createdAt,mergedAt,additions,deletions,statusCheckRollup';\n\ntype Check = NonNullable<RawPull['statusCheckRollup']>[number];\nconst BAD = ['FAILURE', 'ERROR', 'CANCELLED', 'TIMED_OUT', 'ACTION_REQUIRED', 'STARTUP_FAILURE'];\nconst failed = (c: Check) => BAD.includes(c.conclusion ?? '') || BAD.includes(c.state ?? '');\nconst pending = (c: Check) => (!!c.status && c.status !== 'COMPLETED') || c.state === 'PENDING' || c.state === 'EXPECTED';\nconst checkName = (c: Check) => c.name || c.context || 'check';\n\nfunction checksOf(rollup: RawPull['statusCheckRollup']): PullInfo['checks'] {\n if (!rollup || rollup.length === 0) return 'none';\n if (rollup.some(failed)) return 'failing';\n if (rollup.some(pending)) return 'pending';\n return 'passing';\n}\n\nfunction toPull(p: RawPull): PullInfo {\n return {\n number: p.number,\n title: p.title,\n url: p.url,\n headRefName: p.headRefName,\n state: p.state,\n isDraft: p.isDraft,\n mergeable: p.mergeable,\n reviewDecision: p.reviewDecision || null,\n closesIssues: (p.closingIssuesReferences ?? []).map((r) => r.number),\n createdAt: p.createdAt,\n mergedAt: p.mergedAt,\n additions: p.additions,\n deletions: p.deletions,\n checks: checksOf(p.statusCheckRollup),\n headSha: p.headRefOid,\n mergeState: p.mergeStateStatus || 'UNKNOWN',\n failedChecks: (p.statusCheckRollup ?? []).filter(failed).map((c) => ({ name: checkName(c), url: c.detailsUrl || c.targetUrl || null })),\n pendingChecks: (p.statusCheckRollup ?? []).filter(pending).map(checkName),\n };\n}\n\nexport async function listPulls(fullName: string): Promise<PullInfo[]> {\n const [open, merged] = await Promise.all([\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'open', '--limit', '50', '--json', PR_FIELDS]),\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'merged', '--limit', '8', '--json', PR_FIELDS]),\n ]);\n return [...open, ...merged].map(toPull);\n}\n\n// swarm:<specialty> labels route issues to specialists. gh refuses unknown labels, so they're created on first use.\nconst labelsMade = new Set<string>();\n\nasync function ensureLabel(fullName: string, name: string) {\n const key = `${fullName}#${name}`;\n if (labelsMade.has(key)) return;\n await gh(['label', 'create', name, '-R', fullName, '--color', 'c77dff', '--description', 'cubefarm: routed to this specialty', '--force']);\n labelsMade.add(key);\n}\n\nexport async function createIssue(fullName: string, title: string, body: string, labels: string[] = []): Promise<number> {\n for (const l of labels) await ensureLabel(fullName, l);\n const args = ['issue', 'create', '-R', fullName, '--title', title, '--body-file', '-'];\n for (const l of labels) args.push('--label', l);\n const out = await gh(args, { input: body || ' ' });\n const match = out.match(/\\/issues\\/(\\d+)/);\n if (!match) throw new Error(`Could not read the new issue number from gh output: ${out}`);\n return Number(match[1]);\n}\n\n/** OPEN or CLOSED; null when the repo has no such issue. */\nexport async function issueState(fullName: string, number: number): Promise<'OPEN' | 'CLOSED' | null> {\n try {\n const raw = await ghJson<{ state: string }>(['issue', 'view', String(number), '-R', fullName, '--json', 'state']);\n return raw.state === 'OPEN' ? 'OPEN' : 'CLOSED';\n } catch {\n return null;\n }\n}\n\n/** Close an issue as completed, with a comment saying why. */\nexport async function closeIssue(fullName: string, number: number, comment: string): Promise<void> {\n await gh(['issue', 'close', String(number), '-R', fullName, '--reason', 'completed', '--comment', comment]);\n}\n\n/** Replace an issue's body and/or add and remove labels. */\nexport async function editIssue(fullName: string, number: number, edit: { body?: string; addLabels?: string[]; removeLabels?: string[] }): Promise<void> {\n const args = ['issue', 'edit', String(number), '-R', fullName];\n if (edit.body !== undefined) args.push('--body-file', '-');\n for (const l of edit.addLabels ?? []) {\n await ensureLabel(fullName, l);\n args.push('--add-label', l);\n }\n for (const l of edit.removeLabels ?? []) args.push('--remove-label', l);\n if (args.length === 5) return;\n await gh(args, edit.body !== undefined ? { input: edit.body || ' ' } : undefined);\n}\n\n/** Merge a PR. With headSha, GitHub refuses if anything was pushed after that commit (e.g. after QA signed it off). */\nexport async function mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void> {\n const pr = await ghJson<{ headRefName: string; isCrossRepository: boolean }>(['pr', 'view', String(number), '-R', fullName, '--json', 'headRefName,isCrossRepository']);\n await gh(['pr', 'merge', String(number), '-R', fullName, `--${method}`, ...(headSha ? ['--match-head-commit', headSha] : [])], { timeoutMs: 60_000 });\n // Tidy up the swarm branch on the remote; the local worktree is cleaned when the agent takes its next issue.\n if (!pr.isCrossRepository && pr.headRefName.startsWith('swarm/')) {\n await gh(['api', '-X', 'DELETE', `repos/${fullName}/git/refs/heads/${pr.headRefName}`]).catch(() => undefined);\n }\n}\n\n/** Merge the base branch into a PR's branch on GitHub, for repos that only merge up-to-date branches. */\nexport async function updateBranch(fullName: string, number: number): Promise<void> {\n await gh(['pr', 'update-branch', String(number), '-R', fullName], { timeoutMs: 60_000 });\n}\n\nexport async function closePull(fullName: string, number: number): Promise<void> {\n await gh(['pr', 'close', String(number), '-R', fullName]);\n}\n\nexport async function prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null> {\n const list = await ghJson<{ number: number; url: string }[]>(['pr', 'list', '-R', fullName, '--head', branch, '--state', 'all', '--json', 'number,url', '--limit', '1']);\n return list[0] ?? null;\n}\n\n// ---------- QA support ----------\n\nexport interface PrDetails {\n number: number;\n title: string;\n body: string;\n url: string;\n headRefName: string;\n headSha: string;\n isCrossRepository: boolean;\n closesIssues: number[];\n state: 'OPEN' | 'CLOSED' | 'MERGED';\n mergeable: string;\n mergeState: string;\n}\n\nexport async function prDetails(fullName: string, number: number): Promise<PrDetails> {\n const raw = await ghJson<{\n number: number;\n title: string;\n body: string;\n url: string;\n headRefName: string;\n headRefOid: string;\n isCrossRepository: boolean;\n closingIssuesReferences: { number: number }[] | null;\n state: PrDetails['state'];\n mergeable: string;\n mergeStateStatus: string;\n }>(['pr', 'view', String(number), '-R', fullName, '--json', 'number,title,body,url,headRefName,headRefOid,isCrossRepository,closingIssuesReferences,state,mergeable,mergeStateStatus']);\n return {\n number: raw.number,\n title: raw.title,\n body: raw.body ?? '',\n url: raw.url,\n headRefName: raw.headRefName,\n headSha: raw.headRefOid,\n isCrossRepository: raw.isCrossRepository,\n closesIssues: (raw.closingIssuesReferences ?? []).map((r) => r.number),\n state: raw.state,\n mergeable: raw.mergeable,\n mergeState: raw.mergeStateStatus || 'UNKNOWN',\n };\n}\n\nexport async function issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }> {\n const raw = await ghJson<{ title: string; body: string }>(['issue', 'view', String(number), '-R', fullName, '--json', 'title,body']);\n return { title: raw.title, body: raw.body ?? '' };\n}\n\nexport async function commentPull(fullName: string, number: number, body: string): Promise<string> {\n const out = await gh(['pr', 'comment', String(number), '-R', fullName, '--body-file', '-'], { input: body });\n return out.match(/https:\\/\\/github\\.com\\/\\S+/)?.[0] ?? '';\n}\n\n// QA screenshots live on an orphan branch so evidence never lands in the default branch when a PR is merged.\nexport const EVIDENCE_BRANCH = 'swarm-qa-evidence';\nconst evidenceReady = new Set<string>();\n\nconst ghApiJson = <T>(method: string, endpoint: string, body: unknown) =>\n gh(['api', '-X', method, endpoint, '-H', 'Content-Type: application/json', '--input', '-'], { input: JSON.stringify(body), timeoutMs: 120_000 }).then(\n (out) => (out ? JSON.parse(out) : null) as T,\n );\n\nasync function ensureEvidenceBranch(fullName: string) {\n if (evidenceReady.has(fullName)) return;\n try {\n await gh(['api', `repos/${fullName}/git/ref/heads/${EVIDENCE_BRANCH}`]);\n } catch {\n const readme =\n '# QA evidence\\n\\nScreenshots attached to pull request QA reports by cubefarm QA agents.\\nThis branch has no shared history with the code and is never merged.\\n';\n const newTree = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/trees`, {\n tree: [{ path: 'README.md', mode: '100644', type: 'blob', content: readme }],\n });\n const commit = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/commits`, { message: 'QA evidence branch (cubefarm)', tree: newTree.sha, parents: [] });\n await ghApiJson('POST', `repos/${fullName}/git/refs`, { ref: `refs/heads/${EVIDENCE_BRANCH}`, sha: commit.sha });\n }\n evidenceReady.add(fullName);\n}\n\n/** Upload one evidence file and return a URL that renders inside PR comments (also for private repos). */\nexport async function uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string> {\n await ensureEvidenceBranch(fullName);\n await ghApiJson('PUT', `repos/${fullName}/contents/${filePath}`, {\n message: `QA evidence: ${filePath}`,\n content: data.toString('base64'),\n branch: EVIDENCE_BRANCH,\n });\n return `https://github.com/${fullName}/raw/${EVIDENCE_BRANCH}/${filePath}`;\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { HOME_DIR, WORKSPACE_ROOT } from './config.ts';\nimport { type CommandError, gh, git, run } from './exec.ts';\n\n// Layout on disk:\n// <your projects folder>/<repo> the floor's main checkout: your own folder, only fetched and fast-forwarded (syncMain)\n// <WORKSPACE_ROOT>/<owner>__<repo>/desks/<agent> one git worktree per agent, reused from task to task\n// Desks stay outside your project so its dev server, tsc and linters never see them.\n// Floors connected before project folders existed keep their clone at <WORKSPACE_ROOT>/<owner>__<repo>/main.\n\nconst locks = new Map<string, Promise<unknown>>();\nconst localRoots = new Map<string, string>(); // lowercased owner/name -> the user's project folder\n\n/** Serialise git operations per repo so concurrent worktree adds don't fight over index locks. */\nfunction withRepoLock<T>(fullName: string, fn: () => Promise<T>): Promise<T> {\n const prev = locks.get(fullName) ?? Promise.resolve();\n const next = prev.catch(() => undefined).then(fn);\n locks.set(fullName, next);\n return next;\n}\n\nexport const repoDir = (fullName: string) => path.join(WORKSPACE_ROOT, fullName.replace('/', '__'));\nexport const mainDir = (fullName: string) => localRoots.get(fullName.toLowerCase()) ?? path.join(repoDir(fullName), 'main');\nexport const deskDir = (fullName: string, agentSlug: string) => path.join(repoDir(fullName), 'desks', agentSlug);\n\n/** Use the user's own folder as a floor's main checkout (null: back to a clone the office manages). */\nexport function setLocalPath(fullName: string, dir: string | null) {\n if (dir) localRoots.set(fullName.toLowerCase(), path.resolve(dir));\n else localRoots.delete(fullName.toLowerCase());\n}\n\nasync function exists(p: string) {\n return fs\n .access(p)\n .then(() => true)\n .catch(() => false);\n}\n\n// Tool droppings that should never be committed from a desk (shared by all worktrees of the clone).\n// .preview-tmp/ is the preview worktree's {tmp} scratch folder.\nconst LOCAL_EXCLUDES = ['.playwright-mcp/', '.preview-tmp/'];\n\nasync function addLocalExcludes(main: string) {\n const file = path.join(main, '.git', 'info', 'exclude');\n const current = await fs.readFile(file, 'utf8').catch(() => '');\n const missing = LOCAL_EXCLUDES.filter((l) => !current.split(/\\r?\\n/).includes(l));\n if (missing.length === 0) return;\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.appendFile(file, `${current && !current.endsWith('\\n') ? '\\n' : ''}# added by cubefarm\\n${missing.join('\\n')}\\n`);\n}\n\n/** Make sure the floor's worktrees keep LOCAL_EXCLUDES out of git status. */\nexport const ensureLocalExcludes = (fullName: string) => addLocalExcludes(mainDir(fullName));\n\nexport function ensureClone(fullName: string): Promise<void> {\n return withRepoLock(fullName, async () => {\n const dir = mainDir(fullName);\n if (await exists(path.join(dir, '.git'))) {\n // Only remote-tracking refs change: your checkout, branch and uncommitted work are left alone.\n await git(['fetch', 'origin', '--prune'], { cwd: dir, timeoutMs: 180_000 });\n } else {\n await fs.mkdir(path.dirname(dir), { recursive: true });\n await gh(['repo', 'clone', fullName, dir], { timeoutMs: 600_000 });\n }\n await addLocalExcludes(dir);\n });\n}\n\nconst installs = new Map<string, Promise<unknown>>();\n\n/** npm install in a folder, one at a time per folder. */\nfunction npmInstall(dir: string) {\n const prev = installs.get(dir) ?? Promise.resolve();\n const opts = { cwd: dir, timeoutMs: 600_000 };\n const next = prev\n .catch(() => undefined)\n .then(() => (process.platform === 'win32' ? run('cmd.exe', ['/d', '/s', '/c', 'npm install --no-audit --no-fund'], opts) : run('npm', ['install', '--no-audit', '--no-fund'], opts)));\n installs.set(dir, next);\n return next;\n}\n\n/**\n * The paths in `git status --porcelain` output, as git prints them (repo-relative, forward slashes); for a rename\n * or copy (`old -> new`) the new path. Tolerates a first line whose leading space was trimmed (exec trims stdout).\n */\nexport function porcelainPaths(porcelain: string): string[] {\n return porcelain\n .split(/\\r?\\n/)\n .map((line) => /^([ MTADRCU?!]{1,2}) (.+)$/.exec(line))\n .filter((m): m is RegExpExecArray => m !== null)\n .map(([, xy, file]) => (/[RC]/.test(xy) ? (/^(?:\"(?:[^\"\\\\]|\\\\.)*\"|.*?) -> (.+)$/.exec(file)?.[1] ?? file) : file));\n}\n\n/** The paths git lists (tab-indented) under \"... would be overwritten by merge:\" in a failed merge's stderr. */\nexport function overwrittenPaths(stderr: string): string[] {\n const lines = stderr.split(/\\r?\\n/);\n const start = lines.findIndex((l) => /would be overwritten by/.test(l));\n if (start < 0) return [];\n const files: string[] = [];\n for (const line of lines.slice(start + 1)) {\n if (!line.startsWith('\\t')) break;\n files.push(line.trim());\n }\n return files.filter(Boolean);\n}\n\n/** The first few paths, then \"+K more\": \"a, b, c +2 more\", kept to about `maxChars` so a status stays short. */\nexport function fileList(files: string[], max = 3, maxChars = 120): string {\n const shown: string[] = [];\n let length = 0;\n for (const file of files.slice(0, max)) {\n const name = file.length > maxChars ? `\u2026${file.slice(-(maxChars - 1))}` : file;\n const add = name.length + (shown.length ? 2 : 0);\n if (shown.length && length + add > maxChars) break;\n shown.push(name);\n length += add;\n }\n const more = files.length - shown.length;\n return `${shown.join(', ')}${more ? ` +${more} more` : ''}`;\n}\n\n/** How a floor's main checkout stands after syncMain. */\nexport interface MainSync {\n status: string; // e.g. \"in sync\", \"updated to abc1234\", \"update ready (3 commits)\" or \"2 behind: local changes in README.md\"\n behind: number; // commits it is still behind GitHub's default branch\n updatable: boolean; // on the default branch without local commits, so a fast-forward would bring it up to date\n}\n\n/**\n * Bring a floor's main checkout up to date with GitHub. It only ever fast-forwards, and only when the checkout is on\n * the default branch with no local changes: nothing is stashed, reset or discarded, and anything else leaves the\n * folder as it is. Installs dependencies when package.json or the lockfile changed. With `touch: false` it only\n * reports (the office's own folder). Returns how the checkout stands; null when there is no checkout yet.\n */\nexport async function syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<MainSync | null> {\n const dir = mainDir(fullName);\n const result = await withRepoLock(fullName, async (): Promise<(MainSync & { install?: boolean }) | null> => {\n if (!(await exists(path.join(dir, '.git')))) return null;\n const g = (args: string[], timeoutMs?: number) => git(args, { cwd: dir, timeoutMs });\n let behind = 0;\n try {\n await g(['fetch', 'origin', '--prune'], 180_000);\n const target = `origin/${defaultBranch}`;\n behind = Number(await g(['rev-list', '--count', `HEAD..${target}`]));\n const commits = `${behind} commit${behind === 1 ? '' : 's'}`;\n const branch = await g(['symbolic-ref', '--short', '-q', 'HEAD']).catch(() => '');\n const stays = (status: string) => ({ status, behind, updatable: false });\n if (branch !== defaultBranch) return stays(`on ${branch ? `branch ${branch}` : 'a detached HEAD'}${behind ? ` (${defaultBranch} is ${commits} ahead)` : ''}`);\n if (behind === 0) return stays('in sync');\n if (Number(await g(['rev-list', '--count', `${target}..HEAD`])) > 0) return stays(`diverged: local commits, and ${commits} to pull`);\n if (!opts.touch) return { status: `update ready (${commits})`, behind, updatable: true };\n const dirty = await g(['status', '--porcelain', '--untracked-files=no']);\n if (dirty) {\n const files = porcelainPaths(dirty);\n return { status: `${behind} behind: local changes${files.length ? ` in ${fileList(files)}` : ''}`, behind, updatable: true };\n }\n const before = await g(['rev-parse', 'HEAD']);\n try {\n await g(['merge', '--ff-only', target], 120_000);\n } catch (err) {\n const files = overwrittenPaths((err as CommandError).stderr ?? '');\n return { status: `${behind} behind: local files are in the way${files.length ? `: ${fileList(files)}` : ''}`, behind, updatable: true };\n }\n const changed = (await g(['diff', '--name-only', before, 'HEAD'])).split(/\\r?\\n/);\n const install = changed.some((f) => f === 'package.json' || f === 'package-lock.json') && (await exists(path.join(dir, 'package.json')));\n return { status: `updated to ${await g(['rev-parse', '--short', 'HEAD'])}`, behind: 0, updatable: false, install };\n } catch (err) {\n return { status: `sync failed: ${(err as Error).message.split(/\\r?\\n/)[0].slice(0, 160)}`, behind, updatable: false };\n }\n });\n if (!result?.install) return result;\n const { install: _install, ...sync } = result;\n // Outside the repo lock: agents' worktrees don't wait for npm.\n try {\n await npmInstall(dir);\n return { ...sync, status: `${sync.status} \u00B7 dependencies installed` };\n } catch (err) {\n console.warn(`npm install in ${dir} failed:`, (err as Error).message);\n return { ...sync, status: `${sync.status} \u00B7 npm install failed` };\n }\n}\n\n// ---------- your projects folder ----------\n\nexport interface LocalFolder {\n name: string;\n path: string;\n git: boolean;\n github: string | null; // owner/name of its GitHub origin\n modified: number;\n}\n\n/** owner/name from a git config's origin URL, if it points at GitHub. */\nfunction githubFromConfig(config: string): string | null {\n const url = config.match(/\\[remote \"origin\"\\][^[]*?url\\s*=\\s*(\\S+)/)?.[1];\n const m = url?.match(/github\\.com[:/]([^/\\s]+)\\/([^/\\s]+?)(?:\\.git)?\\/?$/i);\n return m ? `${m[1]}/${m[2]}` : null;\n}\n\n/** What a folder is: a git repo? with a GitHub origin? Reads .git/config directly, so scanning is quick. */\nexport async function inspectFolder(dir: string): Promise<LocalFolder> {\n const full = path.resolve(dir);\n const stat = await fs.stat(full).catch(() => null);\n if (!stat?.isDirectory()) throw new Error(`${full} is not a folder`);\n const dotGit = path.join(full, '.git');\n const gitStat = await fs.stat(dotGit).catch(() => null);\n let config = '';\n if (gitStat?.isDirectory()) config = await fs.readFile(path.join(dotGit, 'config'), 'utf8').catch(() => '');\n else if (gitStat) {\n // a worktree or submodule: .git is a file pointing at the real git dir\n const ref = (await fs.readFile(dotGit, 'utf8').catch(() => '')).match(/gitdir:\\s*(.+)/)?.[1]?.trim();\n if (ref) {\n const gitDir = path.resolve(full, ref);\n config = await fs.readFile(path.join(gitDir, 'config'), 'utf8').catch(() => fs.readFile(path.join(gitDir, '..', '..', 'config'), 'utf8').catch(() => ''));\n }\n }\n return { name: path.basename(full), path: full, git: !!gitStat, github: githubFromConfig(config), modified: stat.mtimeMs };\n}\n\n/** The folders directly inside the projects folder, most recently changed first. */\nexport async function scanProjects(root: string): Promise<LocalFolder[]> {\n const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => {\n throw new Error(`Can't read the projects folder ${root}`);\n });\n const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules');\n const folders = await Promise.all(dirs.map((e) => inspectFolder(path.join(root, e.name)).catch(() => null)));\n return folders.filter((f): f is LocalFolder => !!f).sort((a, b) => b.modified - a.modified);\n}\n\nasync function commitReadme(dir: string, title: string, description: string) {\n const readme = path.join(dir, 'README.md');\n if (!(await exists(readme))) await fs.writeFile(readme, `# ${title}\\n\\n${description.trim()}\\n`);\n await git(['add', 'README.md'], { cwd: dir });\n try {\n await git(['commit', '-m', 'Initial commit'], { cwd: dir });\n } catch (err) {\n if (!/tell me who you are|user\\.(name|email)/i.test((err as Error).message)) throw err;\n // No git identity on this machine: commit as the GitHub account gh is signed in to.\n const login = await gh(['api', 'user', '--jq', '.login']);\n await git(['-c', `user.name=${login}`, '-c', `user.email=${login}@users.noreply.github.com`, 'commit', '-m', 'Initial commit'], { cwd: dir });\n }\n}\n\n/**\n * Put a folder on GitHub (gh repo create --source --push). Only what's already committed is pushed. A folder with\n * no commits yet gets a README commit, but only when it's empty: the office never decides which of your files go public.\n */\nexport async function publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string> {\n const full = path.resolve(dir);\n const info = await inspectFolder(full);\n if (info.github) return info.github;\n if (!info.git) await git(['init', '-b', 'main'], { cwd: full });\n const hasCommit = await git(['rev-parse', '--verify', 'HEAD'], { cwd: full }).then(\n () => true,\n () => false,\n );\n if (!hasCommit) {\n const files = (await fs.readdir(full)).filter((f) => f !== '.git' && f !== 'README.md');\n if (files.length) {\n throw new Error(`${info.name} has files but no commits yet. Commit what you want on GitHub first (git add, git commit), then publish it.`);\n }\n await commitReadme(full, opts.name, opts.description ?? '');\n }\n const origin = await git(['remote', 'get-url', 'origin'], { cwd: full }).catch(() => '');\n if (origin) throw new Error(`${info.name}'s origin (${origin}) isn't on GitHub. cubefarm needs GitHub for issues and pull requests.`);\n const target = opts.owner ? `${opts.owner}/${opts.name}` : opts.name;\n const args = ['repo', 'create', target, `--${opts.visibility}`, '--source', full, '--remote', 'origin', '--push'];\n if (opts.description) args.push('--description', opts.description);\n const out = await gh(args, { cwd: full, timeoutMs: 120_000 });\n return out.match(/github\\.com\\/([^/\\s]+\\/[^/\\s]+?)(?:\\.git)?(?:\\s|$)/)?.[1] ?? (await inspectFolder(full)).github ?? target;\n}\n\n/** A brand-new project: <root>/<name> with a README, pushed to a new GitHub repo. */\nexport async function createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }) {\n const dir = path.join(root, name);\n if (await exists(dir)) {\n const inside = await fs.readdir(dir).catch(() => ['?']);\n if (inside.length) throw new Error(`${dir} already exists. Pick another name, or connect that folder instead.`);\n }\n await fs.mkdir(dir, { recursive: true });\n await git(['init', '-b', 'main'], { cwd: dir });\n await commitReadme(dir, name, opts.description ?? '');\n const fullName = await publishFolder(dir, { name, ...opts });\n return { fullName, path: dir };\n}\n\nexport interface DeskBase {\n defaultBranch: string;\n /** Start from a pull request's head instead of the default branch (QA testing, fixes after QA). */\n pr?: number;\n}\n\n/** Remove a directory, retrying while Windows still has handles open in it. */\nasync function removeDir(dir: string) {\n await fs.rm(dir, { recursive: true, force: true, maxRetries: 8, retryDelay: 250 });\n}\n\nexport function prepareDesk(fullName: string, base: DeskBase, agentSlug: string, branch: string): Promise<string> {\n return withRepoLock(fullName, async () => {\n const main = mainDir(fullName);\n await git(['fetch', 'origin', '--prune'], { cwd: main, timeoutMs: 180_000 });\n let ref = `origin/${base.defaultBranch}`;\n if (base.pr) {\n // refs/pull/N/head works for branches in this repo and for forks alike\n ref = `origin/pr/${base.pr}`;\n await git(['fetch', 'origin', `+refs/pull/${base.pr}/head:refs/remotes/${ref}`], { cwd: main, timeoutMs: 180_000 });\n }\n try {\n await git(['rev-parse', '--verify', ref], { cwd: main });\n } catch {\n throw new Error(\n base.pr\n ? `Could not fetch pull request #${base.pr} of ${fullName}.`\n : `${fullName} has no ${base.defaultBranch} branch yet. Push an initial commit (or create the repo with a README) before assigning work.`,\n );\n }\n\n const wt = deskDir(fullName, agentSlug);\n\n // Reuse the desk's worktree in place. Deleting it fails on Windows while any process (a dev server\n // the agent left running, a browser) still has its working directory inside, and reuse keeps\n // node_modules warm between tasks.\n if (await exists(path.join(wt, '.git'))) {\n try {\n await git(['checkout', '--force', '-B', branch, ref], { cwd: wt });\n await git(['reset', '--hard', ref], { cwd: wt });\n // Untracked leftovers from the last task go; ignored files (node_modules, build caches) stay.\n await git(['clean', '-fd'], { cwd: wt }).catch(() => undefined);\n return wt;\n } catch {\n // fall through and rebuild the worktree from scratch\n }\n }\n\n if (await exists(wt)) {\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\n try {\n await removeDir(wt);\n } catch (err) {\n throw new Error(\n `Could not clear the desk folder ${wt}: ${(err as Error).message}. A program started by the previous task is probably still running there. Close it and try again.`,\n );\n }\n }\n await git(['worktree', 'prune'], { cwd: main });\n await fs.mkdir(path.dirname(wt), { recursive: true });\n await git(['worktree', 'add', '-B', branch, wt, ref], { cwd: main });\n return wt;\n });\n}\n\n/** `main`: the floor's checkout when it was let go (a disconnect points mainDir elsewhere before this runs). */\nexport function removeDesk(fullName: string, agentSlug: string, main = mainDir(fullName)): Promise<void> {\n return withRepoLock(fullName, async () => {\n const wt = deskDir(fullName, agentSlug);\n if (!(await exists(wt))) return;\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\n await removeDir(wt).catch(() => undefined);\n await git(['worktree', 'prune'], { cwd: main }).catch(() => undefined);\n });\n}\n\n// ---------- desk sweep ----------\n\n// Homes the office lived in before (Office Swarm became cubefarm): desks there can still be registered in a checkout.\nconst OLD_HOMES = ['.office-swarm'];\nconst OFFICE_BRANCH = /^(swarm\\/issue-|qa\\/pr-)/;\n\nexport interface WorktreeEntry {\n path: string;\n /** The branch it has checked out (null: a detached HEAD). */\n branch: string | null;\n locked: boolean;\n}\n\n/** The worktrees in `git worktree list --porcelain` output, the main worktree first. */\nexport function parseWorktrees(porcelain: string): WorktreeEntry[] {\n const out: WorktreeEntry[] = [];\n for (const line of porcelain.split(/\\r?\\n/)) {\n if (line.startsWith('worktree ')) out.push({ path: path.resolve(line.slice(9)), branch: null, locked: false });\n else if (!out.length) continue;\n else if (line.startsWith('branch ')) out[out.length - 1].branch = line.slice(7).replace(/^refs\\/heads\\//, '');\n else if (line === 'locked' || line.startsWith('locked ')) out[out.length - 1].locked = true;\n }\n return out;\n}\n\n/** What a sweep must leave alone. */\nexport interface SweepKeep {\n /** Desks in use: the floor's agents' slugs and its preview's. */\n desks: string[];\n /** Branches in use: agents' current branches and open PRs' heads. */\n branches: string[];\n}\n\nexport interface SweepInput {\n fullName: string;\n /** The office's workspaces folder (WORKSPACE_ROOT). */\n root: string;\n /** The main checkout's worktrees (parseWorktrees), the main worktree first. */\n worktrees: WorktreeEntry[];\n /** The main checkout's local branches. */\n branches: string[];\n /** The folder names in this floor's desks folder under `root`. */\n folders: string[];\n}\n\nexport interface SweepPlan {\n /** Office desks still registered that nobody uses any more. */\n worktrees: WorktreeEntry[];\n /** Folders in the desks folder that are no worktree and nobody's desk. */\n folders: string[];\n /** Finished swarm/issue-* and qa/pr-* branches. */\n branches: string[];\n}\n\nconst samePath = (a: string, b: string) => (process.platform === 'win32' ? a.toLowerCase() === b.toLowerCase() : a === b);\n\n/** A worktree is an office desk when it sits at <root>/<owner>__<repo>/desks/<name>, under this home or an older one. */\nfunction isOfficeDesk(p: string, fullName: string, root: string) {\n const desks = path.dirname(p);\n const repo = path.dirname(desks);\n const workspaces = path.dirname(repo);\n if (!samePath(path.basename(desks), 'desks') || !samePath(path.basename(repo), fullName.replace('/', '__'))) return false;\n if (samePath(workspaces, path.resolve(root))) return true;\n return path.basename(workspaces) === 'workspaces' && OLD_HOMES.some((h) => samePath(path.basename(path.dirname(workspaces)), h));\n}\n\n/**\n * What a sweep removes: office desks nobody uses (never the main worktree or one outside a desks folder), stray\n * folders in the desks folder, and swarm/issue-* / qa/pr-* branches that no remaining worktree has checked out and\n * nothing in `keep` names. Pure, so it can be tested apart from git.\n */\nexport function planSweep(input: SweepInput, keep: SweepKeep): SweepPlan {\n const deskRoot = path.join(path.resolve(input.root), input.fullName.replace('/', '__'), 'desks');\n const kept = (p: string) => keep.desks.some((slug) => samePath(p, path.join(deskRoot, slug)));\n const worktrees = input.worktrees.slice(1).filter((w) => !w.locked && isOfficeDesk(w.path, input.fullName, input.root) && !kept(w.path));\n const stays = input.worktrees.filter((w) => !worktrees.includes(w));\n const folders = input.folders.filter((name) => {\n const p = path.join(deskRoot, name);\n return !kept(p) && !input.worktrees.some((w) => samePath(w.path, p));\n });\n const branches = input.branches.filter((b) => OFFICE_BRANCH.test(b) && !keep.branches.includes(b) && !stays.some((w) => w.branch === b));\n return { worktrees, folders, branches };\n}\n\nexport interface SweepResult {\n desks: number;\n folders: number;\n branches: number;\n /** Patches saved from removed desks (work that was on no remote branch). */\n patches: string[];\n /** Folders still in use by some process: tried again on the next sweep. */\n skipped: string[];\n}\n\n/** Windows won't rename a folder a process still has open (its working directory, an open file): skip those. */\nasync function inUse(dir: string) {\n const probe = `${dir}.sweep`;\n try {\n await fs.rename(dir, probe);\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ENOENT';\n }\n await fs.rename(probe, dir);\n return false;\n}\n\nconst stamp = (d: Date) => `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;\n\n/**\n * Save a desk's modified tracked files and the commits that are on no remote branch to\n * <HOME_DIR>/leftovers/<owner>__<repo>/<desk>-<YYYYMMDD>.patch (format-patch, then `git diff HEAD`). Null: nothing to save.\n */\nasync function saveLeftovers(fullName: string, desk: string): Promise<string | null> {\n const g = (args: string[]) => git(args, { cwd: desk, timeoutMs: 60_000 });\n if (!(await g(['rev-parse', '--verify', '-q', 'HEAD']).catch(() => ''))) return null;\n const dirty = await g(['status', '--porcelain', '--untracked-files=no']);\n const commits = Number(await g(['rev-list', '--count', 'HEAD', '--not', '--remotes']));\n if (!dirty && !commits) return null;\n const dir = path.join(HOME_DIR, 'leftovers', fullName.replace('/', '__'));\n await fs.mkdir(dir, { recursive: true });\n const tmp = await fs.mkdtemp(path.join(dir, '.tmp-'));\n try {\n // Written to files, not read from stdout: exec trims it, and a patch's trailing whitespace matters.\n if (commits) await g(['format-patch', '-q', '-o', tmp, 'HEAD', '--not', '--remotes']);\n if (dirty) await g(['diff', 'HEAD', '--binary', `--output=${path.join(tmp, 'zz-uncommitted.patch')}`]);\n const parts = (await fs.readdir(tmp)).sort();\n const base = `${path.basename(desk)}-${stamp(new Date())}`;\n let file = path.join(dir, `${base}.patch`);\n for (let n = 2; await exists(file); n++) file = path.join(dir, `${base}-${n}.patch`);\n await fs.writeFile(file, Buffer.concat(await Promise.all(parts.map((p) => fs.readFile(path.join(tmp, p))))));\n return file;\n } finally {\n await removeDir(tmp).catch(() => undefined);\n }\n}\n\n/**\n * Clean up after agents who left: their desks (work on no remote branch is saved as a patch first), stray folders in\n * the desks folder, and finished swarm/issue-* / qa/pr-* branches in the main checkout. Only touches what the office\n * made, never kills a process, and skips a folder that is still in use (the next sweep tries again).\n */\nexport function sweepDesks(fullName: string, keep: SweepKeep): Promise<SweepResult> {\n return withRepoLock(fullName, async () => {\n const result: SweepResult = { desks: 0, folders: 0, branches: 0, patches: [], skipped: [] };\n const main = mainDir(fullName);\n if (!(await exists(path.join(main, '.git')))) return result;\n const g = (args: string[]) => git(args, { cwd: main, timeoutMs: 60_000 });\n await g(['worktree', 'prune']);\n // Real paths on both sides: git may print a path another way than the office spells it (8.3 names, symlinks).\n const real = (p: string) => fs.realpath(p).catch(() => p);\n const worktrees = await Promise.all(parseWorktrees(await g(['worktree', 'list', '--porcelain'])).map(async (w) => ({ ...w, path: await real(w.path) })));\n const refs = await g(['for-each-ref', '--format=%(refname)', 'refs/heads/swarm', 'refs/heads/qa']);\n const branches = refs.split(/\\r?\\n/).filter(Boolean).map((r) => r.replace(/^refs\\/heads\\//, ''));\n const root = await real(WORKSPACE_ROOT);\n const deskRoot = path.join(root, fullName.replace('/', '__'), 'desks');\n const folders = (await fs.readdir(deskRoot, { withFileTypes: true }).catch(() => [])).filter((e) => e.isDirectory()).map((e) => e.name);\n const plan = planSweep({ fullName, root, worktrees, branches, folders }, keep);\n\n const held = new Set<string>(); // branches of desks that stay this time\n for (const wt of plan.worktrees) {\n try {\n if (await inUse(wt.path)) throw new Error('in use');\n const patch = await saveLeftovers(fullName, wt.path);\n if (patch) result.patches.push(patch);\n await g(['worktree', 'remove', '--force', wt.path]).catch(() => undefined);\n await removeDir(wt.path);\n result.desks++;\n } catch {\n result.skipped.push(wt.path);\n if (wt.branch) held.add(wt.branch);\n }\n }\n await g(['worktree', 'prune']).catch(() => undefined);\n for (const name of plan.folders) {\n const dir = path.join(deskRoot, name);\n try {\n if (await inUse(dir)) throw new Error('in use');\n await removeDir(dir);\n result.folders++;\n } catch {\n result.skipped.push(dir);\n }\n }\n const doomed = plan.branches.filter((b) => !held.has(b));\n // A few dozen per command (a floor can have hundreds); git deletes what it can and complains about the rest.\n for (let i = 0; i < doomed.length; i += 40) await g(['branch', '-D', ...doomed.slice(i, i + 40)]).catch(() => undefined);\n if (doomed.length) {\n const left = new Set((await g(['for-each-ref', '--format=%(refname)', 'refs/heads/swarm', 'refs/heads/qa'])).split(/\\r?\\n/));\n result.branches = doomed.filter((b) => !left.has(`refs/heads/${b}`)).length;\n }\n return result;\n });\n}\n\n// ---------- leftover processes ----------\n\n// Only these kinds of processes are stopped when walking up from a leftover to its (orphaned) launcher.\nconst LAUNCHERS = ['node.exe', 'cmd.exe', 'bash.exe', 'sh.exe', 'conhost.exe', 'python.exe', 'npm.exe', 'npx.exe', 'bun.exe', 'deno.exe'];\n\n/** What a desk clean-up leaves alone: the office's own processes, and command lines that carry these paths. */\nexport interface OfficeProcesses {\n /** The office, its terminal keeper and every CLI running in an agent's terminal. */\n pids: number[];\n /** Paths only the CLIs' own command lines carry (the office's session files): those are agents, not leftovers. */\n markers: string[];\n}\n\n/** A path as it can appear in a command line: as is, with forward slashes, and JSON-escaped (Codex's -c values). */\nexport const pathForms = (p: string) => [...new Set([p, p.replaceAll('\\\\', '/'), p.replaceAll('\\\\', '\\\\\\\\')])];\n\n/** The processes of a `ps -A -ww -o pid=,args=` listing whose command line points into a desk, except the office's. */\nexport function leftoversInDesk(listing: string, desk: string, keep: OfficeProcesses): number[] {\n const out: number[] = [];\n for (const line of listing.split('\\n')) {\n const m = line.trim().match(/^(\\d+)\\s+(.*)$/);\n if (!m) continue;\n const [pid, args] = [Number(m[1]), m[2]];\n if (keep.pids.includes(pid) || keep.markers.some((mark) => pathForms(mark).some((f) => args.includes(f)))) continue;\n if (pathForms(desk).some((f) => args.includes(f))) out.push(pid);\n }\n return out;\n}\n\n/**\n * Stop what an agent left running: anything listening on its reserved port or whose command line points into its\n * desk, plus the shell/node chain that launched it. Never the office's own processes (the keeper, the CLIs in agents'\n * terminals): the walk up from a leftover stops at them.\n */\nexport async function releaseDesk(fullName: string, agentSlug: string, port: number, keep: OfficeProcesses = { pids: [], markers: [] }): Promise<void> {\n const desk = deskDir(fullName, agentSlug);\n const spare = [process.pid, ...keep.pids];\n if (process.platform === 'win32') {\n const psList = (paths: string[]) => paths.flatMap(pathForms).map((d) => `'${d.toLowerCase().replaceAll(\"'\", \"''\")}'`).join(', ');\n const script = `\n$ErrorActionPreference = 'SilentlyContinue'\n$spare = @(${spare.join(', ')})\n$seed = @()\nGet-NetTCPConnection -LocalPort ${port} -State Listen | ForEach-Object { $seed += [int]$_.OwningProcess }\n$desks = @(${psList([desk])})\n$marks = @(${psList(keep.markers)})\n$all = Get-CimInstance Win32_Process\n$byId = @{}; foreach ($p in $all) { $byId[[int]$p.ProcessId] = $p }\nforeach ($p in $all) {\n if (-not $p.CommandLine) { continue }\n $cmd = $p.CommandLine.ToLower()\n $ours = $false\n foreach ($m in $marks) { if ($cmd.Contains($m)) { $ours = $true } }\n if ($ours) { continue }\n foreach ($d in $desks) { if ($cmd.Contains($d)) { $seed += [int]$p.ProcessId } }\n}\n$launchers = @(${LAUNCHERS.map((n) => `'${n}'`).join(', ')})\n$kill = New-Object 'System.Collections.Generic.HashSet[int]'\nforeach ($id in $seed) {\n $cur = $byId[$id]\n $first = $true\n while ($cur -and -not ($spare -contains [int]$cur.ProcessId) -and ($first -or $launchers -contains $cur.Name.ToLower())) {\n [void]$kill.Add([int]$cur.ProcessId)\n $first = $false\n $cur = $byId[[int]$cur.ParentProcessId]\n }\n}\nforeach ($id in $kill) { taskkill /PID $id /T /F 2>&1 | Out-Null }\nWrite-Output $kill.Count`;\n await run('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], { timeoutMs: 30_000 }).catch(() => undefined);\n return;\n }\n const listening = await run('sh', ['-c', `lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null || true`]).catch(() => '');\n const listing = await run('ps', ['-A', '-ww', '-o', 'pid=,args=']).catch(() => '');\n const pids = new Set([...listening.split(/\\s+/).map(Number), ...leftoversInDesk(listing, desk, keep)]);\n for (const pid of pids) {\n if (!pid || spare.includes(pid)) continue;\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n // already gone\n }\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { query, type CanUseTool, type Options, type SDKMessage, type SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { AgentCli, AgentRole, EffortLevel, LogKind } from '../shared/types.ts';\nimport type { OfficeTools } from './ceo.ts';\nimport type { UsageWarning } from './pacing.ts';\nimport type { AgentTerminal } from './terminal.ts';\nimport { browserProblem, playwrightMcp } from './browser.ts';\nimport { VERSION } from './config.ts';\n\n// One Claude Code instance (via the Claude Agent SDK) working one issue in its own git worktree.\n// The CEO runs through here too, with the office tools instead of a shell.\n\nexport interface SessionOptions {\n cwd: string;\n prompt: string;\n systemAppend: string;\n model: string; // e.g. 'claude-opus-5-5'\n effort: EffortLevel;\n browserTesting: boolean;\n additionalDirectories: string[]; // read-only reference clones of linked repos\n role: AgentRole;\n /** JSON schema for a structured final answer (QA reports). */\n outputSchema?: Record<string, unknown>;\n resumeSessionId?: string;\n /** The CEO's in-process MCP server (mcp__office__*). */\n office?: OfficeTools;\n /** The terminal runtime: the agent's terminal and the CLI to run in it. Without one: an Agent SDK session. */\n terminal?: AgentTerminal;\n cli?: AgentCli;\n /** Who and on what, for the CLI's session name and status line, e.g. \"Ada \u00B7 #12 Add dark mode\". */\n label?: string;\n /** Leave the CLI waiting at its prompt when the task is done, for the manager and for follow-ups. */\n keepAlive?: boolean;\n /** The prompt was typed at the CLI's prompt by the manager: it's already running, so it isn't sent again. */\n typed?: boolean;\n /** Whose terminal it is (the terminal keeper holds this, for the office that picks the CLI up after a restart). */\n agentId?: string;\n /** Follow the session of the CLI still running in the terminal after the office restarted; start nothing. */\n reattach?: boolean;\n}\n\nexport interface LogEntry {\n kind: LogKind;\n text: string;\n tool?: string;\n}\n\nexport interface SessionResult {\n ok: boolean;\n text: string;\n costUsd: number;\n turns: number;\n errors: string[];\n structured?: unknown;\n /** The manager interrupted the turn in the agent's terminal (Esc). */\n interrupted?: boolean;\n}\n\nexport interface SessionCallbacks {\n log(entries: LogEntry[]): void;\n tool(name: string | null): void;\n /** The session to resume next time; null: there's none to resume (the next session starts a new one). */\n sessionId(id: string | null): void;\n browserUrl(url: string): void;\n screenshot(data: Buffer, mime: string): void;\n /** The final text of each turn: the reply to the prompt and to every message sent while it ran. */\n turn?(text: string): void;\n /** Claude turned the session away for the subscription's usage limit (epoch ms when it resets, if known). */\n limited?(resetsAt: number | null): void;\n /** Claude warned that the subscription's usage is getting high (not while on overage). */\n usageWarning?(info: UsageWarning): void;\n finished(result: SessionResult): void;\n}\n\nexport interface SessionHandle {\n send(text: string): void;\n stop(): void;\n}\n\n/** Async queue used as the streaming-input prompt so the manager can message a running agent. */\nclass InputQueue implements AsyncIterable<SDKUserMessage> {\n private items: SDKUserMessage[] = [];\n private waiters: ((r: IteratorResult<SDKUserMessage>) => void)[] = [];\n private closed = false;\n\n push(text: string) {\n if (this.closed) return;\n const msg: SDKUserMessage = { type: 'user', message: { role: 'user', content: text }, parent_tool_use_id: null };\n const waiter = this.waiters.shift();\n if (waiter) waiter({ value: msg, done: false });\n else this.items.push(msg);\n }\n\n close() {\n this.closed = true;\n for (const w of this.waiters.splice(0)) w({ value: undefined, done: true });\n }\n\n [Symbol.asyncIterator](): AsyncIterator<SDKUserMessage> {\n return {\n next: () => {\n const item = this.items.shift();\n if (item) return Promise.resolve({ value: item, done: false });\n if (this.closed) return Promise.resolve({ value: undefined, done: true });\n return new Promise((resolve) => this.waiters.push(resolve));\n },\n };\n }\n}\n\n// ---------- permissions and screenshots ----------\n\n// Agents work like the manager's own CLI, but nobody may be watching to answer a permission question: every tool call\n// is approved. The office's rules (branches, pull requests, QA leaving GitHub alone) are in their instructions only.\nconst allowAll: CanUseTool = async (_toolName, input) => ({ behavior: 'allow', updatedInput: input });\n\n/**\n * A Playwright screenshot saved to a file (browser_take_screenshot with a filename) comes back as a link, not an\n * image: the file, read from the agent's worktree, so it still counts as QA evidence.\n */\nexport function screenshotFile(cwd: string, text: string): { data: Buffer; mime: string } | null {\n const file = text.match(/\\]\\(([^)\\s]+\\.(png|jpe?g))\\)/i);\n if (!file) return null;\n try {\n return { data: fs.readFileSync(path.resolve(cwd, file[1])), mime: /png$/i.test(file[2]) ? 'image/png' : 'image/jpeg' };\n } catch {\n return null;\n }\n}\n\nconst IMAGE_MIME: Record<string, string> = { '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg' };\n\n/**\n * Screenshots in a browser's output folder that aren't in `seen` yet, oldest first (Playwright names them\n * page-<timestamp>). Files changed in the last second may still be being written, so they wait for the next look.\n */\nexport function newScreenshots(dir: string, seen: Set<string>, now = Date.now()): { name: string; file: string; mime: string }[] {\n let names: string[];\n try {\n names = fs.readdirSync(dir);\n } catch {\n return [];\n }\n const found: { name: string; file: string; mime: string }[] = [];\n for (const name of names.sort()) {\n const mime = IMAGE_MIME[path.extname(name).toLowerCase()];\n const file = path.join(dir, name);\n if (!mime || seen.has(name)) continue;\n try {\n if (now - fs.statSync(file).mtimeMs < 1000) continue;\n } catch {\n continue;\n }\n found.push({ name, file, mime });\n }\n return found;\n}\n\n// ---------- formatting the stream into terminal lines ----------\n\nexport const clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 1)}\u2026` : s);\n\nfunction rel(cwd: string, p: unknown) {\n const s = String(p ?? '');\n if (!s) return '';\n const r = path.relative(cwd, path.resolve(cwd, s)); // a relative path (Codex's patches) is the agent's, not ours\n return r && !r.startsWith('..') ? r.replaceAll('\\\\', '/') : s;\n}\n\nconst escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** Agents often prefix commands with `cd \"<worktree>\" &&` and print absolute paths; show them relative instead. */\nexport function tidyPaths(cwd: string, text: string): string {\n let out = text;\n for (const v of new Set([cwd, cwd.replaceAll('\\\\', '/')])) {\n out = out.replace(new RegExp(`^cd\\\\s+\"?${escapeRe(v)}\"?\\\\s*(&&|;)\\\\s*`, 'i'), '');\n out = out.replace(new RegExp(`${escapeRe(v)}[\\\\\\\\/]?`, 'gi'), './');\n }\n return out;\n}\n\nexport function describeTool(cwd: string, name: string, input: Record<string, unknown>): string {\n switch (name) {\n case 'Bash':\n case 'PowerShell':\n return `$ ${clip(tidyPaths(cwd, String(input.command ?? '')).split('\\n')[0], 220)}`;\n case 'Read':\n return `Read ${rel(cwd, input.file_path)}`;\n case 'Write':\n return `Write ${rel(cwd, input.file_path)}`;\n case 'Edit':\n case 'MultiEdit':\n return `Edit ${rel(cwd, input.file_path)}`;\n case 'Glob':\n return `Glob ${input.pattern}`;\n case 'Grep':\n return `Grep \"${clip(String(input.pattern ?? ''), 80)}\"`;\n case 'WebFetch':\n return `Fetch ${input.url}`;\n case 'WebSearch':\n return `Search \"${input.query}\"`;\n case 'Task':\n case 'Agent':\n return `Subagent: ${input.description ?? ''}`;\n case 'TodoWrite':\n return 'Update todo list';\n case 'ToolSearch':\n return `Load tools ${String(input.query ?? '').replace(/^select:/, '')}`;\n case 'apply_patch': {\n // Codex's file edits: \"*** Add File: a.ts\", \"*** Update File: b.ts\", \"*** Delete File: c.ts\"\n const files = [...String(input.command ?? '').matchAll(/^\\*\\*\\* (Add|Update|Delete) File: (.+)$/gm)].map((m) => `${m[1] === 'Update' ? '' : `${m[1].toLowerCase()} `}${rel(cwd, m[2].trim())}`);\n return `Edit ${clip(files.join(', ') || 'files', 200)}`;\n }\n }\n if (name.startsWith('mcp__playwright__')) {\n const action = name.replace('mcp__playwright__browser_', '').replace('mcp__playwright__', '');\n const detail = input.url ?? input.element ?? input.text ?? '';\n return `\uD83C\uDF10 ${action}${detail ? ` ${clip(String(detail), 120)}` : ''}`;\n }\n if (name.startsWith('mcp__office__')) return describeOfficeTool(name.slice('mcp__office__'.length), input);\n return `${name}(${clip(JSON.stringify(input), 140)})`;\n}\n\nexport function describeOfficeTool(action: string, input: Record<string, unknown>): string {\n const floor = input.floor != null ? ` \u2192 floor ${input.floor}` : '';\n switch (action) {\n case 'company_status':\n return '\uD83C\uDFE2 company_status';\n case 'agent_detail':\n return `\uD83D\uDD0E agent_detail ${String(input.agent_id ?? '')}`;\n case 'set_floor_profile':\n return `\uD83D\uDDC2\uFE0F set_floor_profile${floor}${input.summary ? `: ${clip(String(input.summary), 90)}` : ''}`;\n case 'update_job':\n return `\uD83E\uDEAA update_job ${input.title ? `\"${clip(String(input.title), 60)}\"` : String(input.agent_id ?? '')}`;\n case 'propose_hire':\n return `\uD83E\uDD1D propose_hire ${input.role === 'qa' ? 'QA ' : ''}\"${clip(String(input.title ?? ''), 60)}\"${floor}`;\n case 'propose_let_go':\n return `\uD83D\uDC4B propose_let_go ${String(input.agent_id ?? '')}`;\n case 'file_issue':\n return `\uD83D\uDCDD file_issue \"${clip(String(input.title ?? ''), 70)}\"${floor}${input.specialty ? ` \u00B7 ${input.specialty}` : ''}`;\n case 'route_issue':\n return `\uD83D\uDD00 route_issue #${String(input.number ?? '?')}${floor}${input.specialty !== undefined ? ` \u00B7 ${input.specialty || 'no specialty'}` : ''}${Array.isArray(input.depends_on) ? ` \u00B7 depends on ${input.depends_on.map((n) => `#${n}`).join(', ') || 'nothing'}` : ''}`;\n }\n return `\uD83C\uDFE2 ${action}(${clip(JSON.stringify(input), 120)})`;\n}\n\nexport function todoLines(input: Record<string, unknown>): LogEntry[] {\n const todos = Array.isArray(input.todos) ? (input.todos as { content?: string; status?: string }[]) : [];\n return todos.slice(0, 12).map((t) => ({\n kind: 'result' as const,\n text: ` ${t.status === 'completed' ? '\u2612' : t.status === 'in_progress' ? '\u25D0' : '\u2610'} ${clip(t.content ?? '', 150)}`,\n }));\n}\n\nexport function resultText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n return content\n .filter((b): b is { type: 'text'; text: string } => b?.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n }\n return '';\n}\n\nconst lineCount = (text: string) => text.replace(/\\r/g, '').split('\\n').filter((l) => l.trim() !== '').length;\n\nexport function summariseResult(cwd: string, tool: string, text: string): LogEntry[] {\n // Claude Code-style one-liners for the chatty file tools\n if (tool === 'Edit' || tool === 'MultiEdit' || tool === 'NotebookEdit') return [{ kind: 'result', text: ' \u23BF Updated' }];\n if (tool === 'apply_patch' && /Success\\. Updated the following files/.test(text)) return [{ kind: 'result', text: ' \u23BF Updated' }];\n if (tool === 'Write') return [{ kind: 'result', text: ' \u23BF Saved' }];\n if (tool === 'Read') return [{ kind: 'result', text: ` \u23BF Read ${lineCount(text)} lines` }];\n if (tool === 'Glob') return [{ kind: 'result', text: ` \u23BF Found ${lineCount(text)} files` }];\n const lines = tidyPaths(cwd, text).replace(/\\r/g, '').split('\\n').filter((l) => l.trim() !== '');\n if (lines.length === 0) return [{ kind: 'result', text: ' \u23BF (no output)' }];\n const shown = lines.slice(0, 3).map((l, i) => ({ kind: 'result' as const, text: `${i === 0 ? ' \u23BF ' : ' '}${clip(l, 170)}` }));\n if (lines.length > 3) shown.push({ kind: 'result', text: ` \u2026 +${lines.length - 3} lines` });\n return shown;\n}\n\n// ---------- the session ----------\n\nexport function startSession(opts: SessionOptions, callbacks: SessionCallbacks): SessionHandle {\n let done = false;\n const cb: SessionCallbacks = {\n ...callbacks,\n finished: (r) => {\n if (done) return;\n done = true;\n callbacks.finished(r);\n },\n };\n const input = new InputQueue();\n const abort = new AbortController();\n let pendingTurns = 1;\n let stopped = false;\n let lastCost = 0;\n let lastTurns = 0;\n const toolNames = new Map<string, string>();\n\n input.push(opts.prompt);\n\n // Each agent must be a clean Claude Code instance on the subscription Claude Code is logged into.\n // Drop API keys (they would switch billing to the API) and any CLAUDE_* / ANTHROPIC_* variables\n // inherited from a parent Claude Code session (base URL proxies, session sockets, effort overrides\u2026).\n const env: Record<string, string | undefined> = {};\n for (const [k, v] of Object.entries(process.env)) {\n if (/^(ANTHROPIC_|CLAUDE)/i.test(k) && k !== 'CLAUDE_CONFIG_DIR') continue;\n env[k] = v;\n }\n env.CLAUDE_AGENT_SDK_CLIENT_APP = `cubefarm/${VERSION}`;\n\n const mcpServers: Options['mcpServers'] = {};\n if (opts.browserTesting) {\n const browser = playwrightMcp();\n if (browser) mcpServers.playwright = browser;\n const problem = browserProblem(browser);\n if (problem) cb.log([{ kind: 'error', text: problem }]);\n }\n if (opts.office) mcpServers.office = opts.office.server;\n // The CEO reads repositories and acts through the office tools; it never runs commands.\n const disallowedTools = ['AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode'];\n if (opts.role === 'ceo') disallowedTools.push('Bash', 'PowerShell', 'NotebookEdit');\n\n const options: Options = {\n cwd: opts.cwd,\n additionalDirectories: opts.additionalDirectories,\n abortController: abort,\n env,\n model: opts.model || undefined,\n effort: opts.effort,\n // The manager's own setup (settings, skills, plugins, MCP servers, connectors), plus the office's servers below.\n settingSources: ['user', 'project', 'local'],\n systemPrompt: { type: 'preset', preset: 'claude_code', append: opts.systemAppend },\n mcpServers,\n disallowedTools,\n resume: opts.resumeSessionId,\n stderr: (data) => {\n const line = data.trim();\n if (line && /error|fail/i.test(line)) cb.log([{ kind: 'error', text: clip(line, 200) }]);\n },\n permissionMode: 'acceptEdits',\n canUseTool: allowAll,\n ...(opts.outputSchema ? { outputFormat: { type: 'json_schema' as const, schema: opts.outputSchema } } : {}),\n };\n\n // The office's prompts are answered one result each. See the 'result' case for results that answer none of them.\n let emptyTurn: NodeJS.Timeout | undefined;\n const answered = (msg: Extract<SDKMessage, { type: 'result' }>) => {\n pendingTurns -= 1;\n if (pendingTurns > 0) return;\n input.close();\n const ok = msg.subtype === 'success' && !msg.is_error;\n cb.finished({\n ok,\n text: msg.subtype === 'success' ? msg.result : '',\n costUsd: lastCost,\n turns: lastTurns,\n errors: msg.subtype === 'success' ? [] : msg.errors,\n structured: msg.subtype === 'success' ? msg.structured_output : undefined,\n });\n };\n\n const handle = (msg: SDKMessage) => {\n clearTimeout(emptyTurn);\n if (done && msg.type === 'assistant' && !stopped) {\n // The office already treated this session as finished and no longer follows it.\n stopped = true;\n cb.log([{ kind: 'system', text: '\u25A0 This session kept working after it had finished, so it was stopped.' }]);\n abort.abort();\n return;\n }\n switch (msg.type) {\n case 'system': {\n if (msg.subtype === 'init') {\n cb.sessionId(msg.session_id);\n const mcp = msg.mcp_servers.map((s) => `${s.name}:${s.status}`).join(', ');\n cb.log([\n { kind: 'system', text: `\u273B Claude Code ${msg.claude_code_version} \u00B7 ${msg.model} \u00B7 ${msg.effort ?? opts.effort} effort` },\n { kind: 'system', text: ` cwd ${msg.cwd}${mcp ? ` \u00B7 mcp ${mcp}` : ''}` },\n ]);\n } else if (msg.subtype === 'api_retry') {\n cb.log([{ kind: 'system', text: `\u2026 API retry ${msg.attempt}/${msg.max_retries} in ${Math.round(msg.retry_delay_ms / 1000)}s` }]);\n } else if (msg.subtype === 'compact_boundary') {\n cb.log([{ kind: 'system', text: '\u273B Conversation compacted' }]);\n }\n break;\n }\n case 'rate_limit_event': {\n const info = msg.rate_limit_info;\n if (info.status !== 'allowed') {\n const when = info.resetsAt ? new Date(info.resetsAt * 1000).toLocaleTimeString() : 'later';\n cb.log([{ kind: 'error', text: `\u26A0 Subscription usage ${info.status === 'rejected' ? 'limit reached' : 'warning'} (${info.rateLimitType ?? 'limit'}) \u00B7 resets ${when}` }]);\n const overage = info.isUsingOverage || info.overageStatus === 'allowed' || info.overageStatus === 'allowed_warning';\n if (info.status === 'rejected' && !overage) cb.limited?.(info.resetsAt ? info.resetsAt * 1000 : null);\n if (info.status === 'allowed_warning' && !overage) {\n cb.usageWarning?.({ resetsAt: info.resetsAt ? info.resetsAt * 1000 : null, rateLimitType: info.rateLimitType ?? null, utilization: info.utilization ?? null });\n }\n }\n break;\n }\n case 'assistant': {\n if (msg.parent_tool_use_id) break; // subagent chatter stays off the main screen\n const out: LogEntry[] = [];\n for (const block of msg.message.content) {\n if (block.type === 'text' && block.text.trim()) {\n const lines = block.text.trim().split('\\n');\n lines.slice(0, 30).forEach((l, i) => out.push({ kind: 'text', text: `${i === 0 ? '\u25CF ' : ' '}${l}` }));\n if (lines.length > 30) out.push({ kind: 'text', text: ` \u2026 (${lines.length - 30} more lines)` });\n } else if (block.type === 'thinking') {\n out.push({ kind: 'thinking', text: '\u273B Thinking\u2026' });\n } else if (block.type === 'tool_use') {\n const toolInput = (block.input ?? {}) as Record<string, unknown>;\n toolNames.set(block.id, block.name);\n out.push({ kind: 'tool', tool: block.name, text: `\u23FA ${describeTool(opts.cwd, block.name, toolInput)}` });\n if (block.name === 'TodoWrite') out.push(...todoLines(toolInput));\n cb.tool(block.name);\n if (block.name === 'mcp__playwright__browser_navigate' && typeof toolInput.url === 'string') cb.browserUrl(toolInput.url);\n }\n }\n if (out.length) cb.log(out);\n break;\n }\n case 'user': {\n if (msg.parent_tool_use_id) break;\n const content = msg.message.content;\n if (!Array.isArray(content)) break;\n const out: LogEntry[] = [];\n for (const block of content) {\n if (block.type !== 'tool_result') continue;\n const name = toolNames.get(block.tool_use_id) ?? '';\n const text = resultText(block.content);\n let images = 0;\n if (Array.isArray(block.content)) {\n for (const part of block.content) {\n if (part.type === 'image' && part.source.type === 'base64') {\n images += 1;\n cb.screenshot(Buffer.from(part.source.data, 'base64'), part.source.media_type);\n }\n }\n }\n const saved = name === 'mcp__playwright__browser_take_screenshot' && !images ? screenshotFile(opts.cwd, text) : null;\n if (saved) cb.screenshot(saved.data, saved.mime);\n if (name.startsWith('mcp__playwright__')) {\n const url = text.match(/Page URL:\\s*(\\S+)/);\n if (url) cb.browserUrl(url[1]);\n }\n if (name === 'TodoWrite') continue;\n if (block.is_error) out.push({ kind: 'error', text: ` \u23BF ${clip(tidyPaths(opts.cwd, text).split('\\n')[0] || 'Error', 200)}` });\n else out.push(...summariseResult(opts.cwd, name, text));\n }\n cb.tool(null);\n if (out.length) cb.log(out);\n break;\n }\n case 'result': {\n lastCost = msg.total_cost_usd;\n lastTurns = msg.num_turns;\n if (msg.subtype === 'success' && !msg.is_error && msg.num_turns === 0) {\n // A resumed session can first replay a turn left over from before an office restart: an empty \"success\"\n // that answers none of our prompts, with the real turn right behind it. Counting it ended the session\n // while the real turn ran on without its permission channel. If nothing follows, it was the answer.\n emptyTurn = setTimeout(() => answered(msg), 30_000);\n break;\n }\n if (msg.subtype === 'success' && !msg.is_error && msg.result.trim()) cb.turn?.(msg.result.trim());\n answered(msg);\n break;\n }\n }\n };\n\n (async () => {\n try {\n for await (const msg of query({ prompt: input, options })) handle(msg);\n if (pendingTurns > 0) {\n cb.finished({ ok: false, text: '', costUsd: lastCost, turns: lastTurns, errors: [stopped ? 'Stopped by manager' : 'Session ended unexpectedly'] });\n }\n } catch (err) {\n input.close();\n const message = stopped ? 'Stopped by manager' : err instanceof Error ? err.message : String(err);\n cb.finished({ ok: false, text: '', costUsd: lastCost, turns: lastTurns, errors: [message] });\n }\n })();\n\n return {\n send(text) {\n pendingTurns += 1;\n input.push(text);\n },\n stop() {\n stopped = true;\n clearTimeout(emptyTurn);\n input.close();\n abort.abort();\n },\n };\n}\n", "import fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport os from 'node:os';\nimport path from 'node:path';\n\n// The agents' test browser: the Playwright MCP server pinned in package.json, started with node from the installed\n// package (no npx, no npm registry, no surprise browser download at session start), driving the installed Google\n// Chrome the README asks for.\n\nexport interface McpCommand {\n command: string;\n args: string[];\n}\n\n/** The pinned Playwright MCP's CLI script, resolved from cubefarm's own dependencies; null when it isn't installed. */\nexport function playwrightMcpCli(): string | null {\n try {\n const pkgFile = createRequire(import.meta.url).resolve('@playwright/mcp/package.json');\n const bin = (JSON.parse(fs.readFileSync(pkgFile, 'utf8')) as { bin?: Record<string, string> }).bin?.['playwright-mcp'] ?? 'cli.js';\n return path.join(path.dirname(pkgFile), bin);\n } catch {\n return null;\n }\n}\n\n/**\n * The MCP server command: node on the CLI script, each path its own argument (no shell, so spaces need no quoting).\n * browser-init.js keeps pages from taking the real mouse with pointer lock (headless Chrome does on Windows).\n * `outputDir` gets snapshots and unnamed screenshots (the terminal runtime collects them from there).\n */\nexport function playwrightMcpCommand(cli: string, initScript: string, outputDir?: string, node = process.execPath): McpCommand {\n return { command: node, args: [cli, '--headless', '--isolated', ...(outputDir ? ['--output-dir', outputDir] : []), '--init-script', initScript] };\n}\n\n/** The office's Playwright MCP server for a session, or null when the pinned package can't be found. */\nexport function playwrightMcp(outputDir?: string): McpCommand | null {\n const cli = playwrightMcpCli();\n return cli ? playwrightMcpCommand(cli, path.join(import.meta.dirname, 'browser-init.js'), outputDir) : null;\n}\n\n/** Where Playwright's \"chrome\" channel looks for Google Chrome (bin/cubefarm.js doctor checks the same places). */\nexport function chromePaths(platform: NodeJS.Platform = process.platform, env: NodeJS.ProcessEnv = process.env, home = os.homedir()): string[] {\n if (platform === 'win32') {\n return [env.LOCALAPPDATA, env.PROGRAMFILES, env['PROGRAMFILES(X86)']].filter((d): d is string => !!d).map((d) => path.win32.join(d, 'Google', 'Chrome', 'Application', 'chrome.exe'));\n }\n if (platform === 'darwin') return ['/Applications/Google Chrome.app', path.posix.join(home, 'Applications', 'Google Chrome.app')];\n return ['/opt/google/chrome/chrome', '/usr/bin/google-chrome', '/usr/bin/google-chrome-stable'];\n}\n\nexport const hasChrome = () => chromePaths().some((p) => fs.existsSync(p));\n\n/** The one line a session's log shows when browser testing can't work on this machine, or null when it can. */\nexport function browserProblem(mcp: McpCommand | null, chrome = hasChrome()): string | null {\n if (!mcp) return '\u26A0 The browser tool (@playwright/mcp) is not installed with cubefarm: reinstall it, or run npx cubefarm doctor';\n if (!chrome) return '\u26A0 Google Chrome not found, so this session cannot test in a browser: install it, or run npx cubefarm doctor';\n return null;\n}\n", "import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { Request, Response } from 'express';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { browserProblem, playwrightMcp } from './browser.ts';\nimport { HOME_DIR } from './config.ts';\nimport { cliLabel, CODEX_HOOK_SOURCE, codexThread, commandFor, hookReviewKey, interruptions, isCli, launchArgs, NOTIFY_SOURCE, OPENCODE_PLUGIN_SOURCE, STATUSLINE_SOURCE, trustKey } from './clis.ts';\nimport { adoptPty, discardPty, hooksReady, keeperHookUrl, keeperPid, leaveKeeper, spawnPty, startKeeper, terminalsAvailable, type Pty } from './ptyClient.ts';\nimport {\n clip,\n describeTool,\n newScreenshots,\n resultText,\n screenshotFile,\n summariseResult,\n tidyPaths,\n todoLines,\n type LogEntry,\n type SessionCallbacks,\n type SessionHandle,\n type SessionOptions,\n type SessionResult,\n} from './agentRunner.ts';\nimport type { OfficeTools } from './ceo.ts';\nimport type { AgentTerminal } from './terminal.ts';\nimport type { AgentCli } from '../shared/types.ts';\n\n// One agent session as the real CLI in a pseudo-terminal: the same contract as the Agent SDK runner (log lines, the\n// current tool, the final text, finished), so the rest of the office doesn't care which runtime an agent uses.\n//\n// Claude Code reports through HTTP hooks passed with --settings: every tool call (PreToolUse also approves it, so the\n// CLI never stops to ask), each finished turn (Stop, with the final text), failures (StopFailure) and, through its\n// status line, cost and usage limits. Codex says when a turn ends (notify) and, once the manager trusts the office's\n// hooks in its /hooks, reports its steps through them too. OpenCode's plugin only says when a turn ends.\n//\n// The CLIs run in the office's terminal keeper (ptyClient.ts) and call their hooks there, so an office restart doesn't\n// stop them: the office picks them up again when it's back (reconnectClis).\n\nexport { terminalsAvailable };\n\nconst SESSIONS_DIR = path.join(HOME_DIR, 'sessions');\nconst BIN_DIR = path.join(HOME_DIR, 'bin');\n/** After a turn ends the CLI may still pick up a queued message: only an idle prompt this long means it's done. */\nconst FINISH_GRACE_MS = 3000;\n/** Starting up: how long before the office says the CLI seems to be waiting on something. */\nconst BOOT_MS = 60_000;\n/** Claude's usage warning, the way the SDK's allowed_warning is used: pace new work from here. */\nconst USAGE_WARN_PCT = 90;\n/** Prompts longer than this go in a file: Windows caps a command line at 32K characters. */\nconst INLINE_PROMPT_MAX = 8000;\n\n// ---------- routing the CLIs' calls back to their sessions ----------\n\nlet officeUrl = '';\n\n/** The office's own address, for the hook and MCP endpoints the CLIs call back on. Set once the server listens. */\nexport function setOfficeUrl(url: string) {\n officeUrl = url;\n}\n\ninterface Route {\n hook(body: Record<string, unknown>): Record<string, unknown>;\n office?: OfficeTools;\n}\nconst routes = new Map<string, Route>();\n\n/** A hook, status line or notify call from a CLI (POST /api/hooks/:token). The answer is the hook's output. */\nexport function handleHook(token: string, body: unknown): Record<string, unknown> {\n const route = routes.get(token);\n if (!route || !body || typeof body !== 'object' || Array.isArray(body)) return {};\n try {\n return route.hook(body as Record<string, unknown>);\n } catch (err) {\n console.warn('hook failed', err);\n return {};\n }\n}\n\n/** The CEO's office tools over MCP (Streamable HTTP, stateless: a fresh server per request). */\nexport async function handleMcp(token: string, req: Request, res: Response) {\n const office = routes.get(token)?.office;\n if (!office) {\n res.status(404).json({ jsonrpc: '2.0', error: { code: -32001, message: 'This session has ended.' }, id: null });\n return;\n }\n const server = office.serve();\n const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true });\n res.on('close', () => {\n void transport.close();\n void server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n}\n\n// ---------- helper scripts ----------\n\nlet helpersWritten = false;\n\n/** The status line, notify and plugin scripts the CLIs run. Rewritten once per office start, so updates reach them. */\nfunction writeHelpers() {\n if (helpersWritten) return;\n fs.mkdirSync(BIN_DIR, { recursive: true });\n fs.writeFileSync(path.join(BIN_DIR, 'statusline.cjs'), STATUSLINE_SOURCE);\n fs.writeFileSync(path.join(BIN_DIR, 'notify.cjs'), NOTIFY_SOURCE);\n fs.writeFileSync(path.join(BIN_DIR, 'codex-hook.cjs'), CODEX_HOOK_SOURCE);\n fs.writeFileSync(path.join(BIN_DIR, 'opencode-plugin.mjs'), OPENCODE_PLUGIN_SOURCE);\n helpersWritten = true;\n}\n\n/** A command line for Claude Code's shell (Git Bash on Windows): forward slashes, quoted. */\nconst shellArg = (p: string) => `\"${p.replaceAll('\\\\', '/')}\"`;\n\n// ---------- plumbing ----------\n\nconst HOOK_EVENTS = ['UserPromptSubmit', 'PreToolUse', 'PostToolUse', 'PostToolUseFailure', 'Stop', 'StopFailure', 'Notification'];\n\n/** What a tool call returned, as text, and any images in it (Playwright screenshots). */\nfunction toolOutput(response: unknown): { text: string; images: { data: string; mime: string }[] } {\n const images: { data: string; mime: string }[] = [];\n const blocks = Array.isArray(response) ? response : Array.isArray((response as { content?: unknown })?.content) ? (response as { content: unknown[] }).content : null;\n if (blocks) {\n for (const b of blocks as Record<string, unknown>[]) {\n const source = b?.source as { type?: string; data?: string; media_type?: string } | undefined;\n if (b?.type === 'image' && source?.type === 'base64' && source.data) images.push({ data: source.data, mime: source.media_type ?? 'image/png' });\n else if (b?.type === 'image' && typeof b.data === 'string') images.push({ data: b.data, mime: String(b.mimeType ?? 'image/png') });\n }\n return { text: resultText(blocks), images };\n }\n if (typeof response === 'string') return { text: response, images };\n const r = response as { stdout?: unknown; stderr?: unknown; file?: { content?: unknown }; filenames?: unknown } | null;\n if (r && typeof r === 'object') {\n if (typeof r.stdout === 'string' || typeof r.stderr === 'string') return { text: [r.stdout, r.stderr].filter((s) => typeof s === 'string' && s).join('\\n'), images };\n if (typeof r.file?.content === 'string') return { text: r.file.content, images };\n if (Array.isArray(r.filenames)) return { text: r.filenames.join('\\n'), images };\n }\n return { text: '', images };\n}\n\n/** A pseudo-terminal whose CLI just died throws on writes and resizes before it reports the exit: ignore that. */\nfunction quietly(fn: () => void) {\n try {\n fn();\n } catch {\n // the CLI is gone; its exit is on the way\n }\n}\n\n// ---------- CLIs that outlive their session ----------\n\n/**\n * A CLI running in an agent's terminal. It can outlive the office session that started it: when a developer's task\n * is done their CLI waits at its prompt, so the manager can keep using it, and a follow-up picks it up again. It also\n * outlives an office restart, held by the terminal keeper.\n */\ninterface LiveCli {\n agentId: string;\n cli: AgentCli;\n term: AgentTerminal;\n proc: Pty | null;\n token: string;\n dir: string;\n resumeId: string | null; // the session a follow-up resumes\n statusLine: string;\n /** Browser screenshots already passed on (Codex and OpenCode: collected from the browser's output folder). */\n shots: Set<string>;\n /** The office session driving it; null while it waits at its prompt. */\n session: { hook(b: Record<string, unknown>): Record<string, unknown>; exited(code: number): void } | null;\n idleTimer?: NodeJS.Timeout;\n}\nconst lives = new Map<AgentTerminal, LiveCli>();\n/** How to trust Codex's hooks was said once this run (Codex asks at the start of every session until they are). */\nlet hooksHinted = false;\n/** A CLI left at its prompt this long is closed; its session can still be resumed. */\nconst IDLE_MS = 30 * 60_000;\n\n/** PreToolUse's answer: nobody may be watching to answer a permission question, so every tool call is approved. */\nconst ALLOW = { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow', permissionDecisionReason: 'Approved by cubefarm' } };\n\nconst toolInput = (b: Record<string, unknown>) => (b.tool_input && typeof b.tool_input === 'object' ? b.tool_input : {}) as Record<string, unknown>;\n\n/** The CLI has exited, or has had a few seconds to. */\nconst exitOf = (p: Pty) =>\n new Promise<void>((resolve) => {\n p.onExit(() => resolve());\n setTimeout(resolve, 5000);\n });\n\n/** Close a CLI for good. A Codex thread is archived once its CLI is gone (see codexThread). */\nfunction endLive(live: LiveCli): Promise<void> {\n if (lives.get(live.term) !== live) return Promise.resolve();\n lives.delete(live.term);\n clearTimeout(live.idleTimer);\n routes.delete(live.token);\n live.term.releaseIdle = null;\n live.term.bind(null);\n const gone = live.proc ? exitOf(live.proc) : undefined;\n live.proc?.kill();\n live.proc = null;\n live.term.note(`\u2500\u2500 ${cliLabel(live.cli)} session ended \u2500\u2500`);\n fs.rm(live.dir, { recursive: true, force: true, maxRetries: 5 }, () => undefined);\n return live.cli === 'codex' && live.resumeId ? codexThread('archive', live.resumeId, gone) : Promise.resolve();\n}\n\n/** What the keeper holds with a CLI's terminal, so the office can pick it up again after a restart. */\ninterface CliMeta {\n agentId: string;\n cli: AgentCli;\n token: string;\n dir: string;\n resumeId: string | null;\n /** An office session was driving it (not waiting at its prompt). */\n busy: boolean;\n}\n\nconst metaOf = (l: LiveCli): CliMeta => ({ agentId: l.agentId, cli: l.cli, token: l.token, dir: l.dir, resumeId: l.resumeId, busy: !!l.session });\nconst remember = (l: LiveCli) => l.proc?.setMeta(metaOf(l));\n\n/** A CLI is running in its terminal: its output, its keys and its hooks are connected. */\nfunction wire(l: LiveCli, office?: OfficeTools) {\n const p = l.proc!;\n lives.set(l.term, l);\n routes.set(l.token, { hook: (b) => (l.session ? l.session.hook(b) : idleHook(l, b)), office });\n l.term.bind({ write: (d) => quietly(() => p.write(d)), resize: (c, r) => quietly(() => p.resize(c, r)) });\n p.onData((data) => {\n if (lives.get(l.term) === l) l.term.write(data);\n });\n p.onExit((code) => {\n l.proc = null;\n if (lives.get(l.term) !== l) return; // already replaced or closed\n if (l.session) l.session.exited(code);\n else endLive(l); // quit while waiting at its prompt\n });\n}\n\n/** The task is done but the CLI stays at its prompt for the manager (or a follow-up), for a while. */\nfunction waitAtPrompt(l: LiveCli) {\n clearTimeout(l.idleTimer);\n l.idleTimer = setTimeout(() => endLive(l), IDLE_MS);\n l.term.releaseIdle = () => endLive(l);\n remember(l);\n}\n\nexport interface ReconnectedCli {\n agentId: string;\n cli: AgentCli;\n resumeId: string | null;\n /** It was working on a task: the office should follow its session again. */\n busy: boolean;\n}\n\n/**\n * The office started: connect to the terminal keeper and take back the CLIs it kept running through the restart, each\n * into its agent's terminal. They wait at their prompt until the office follows their session again (busy ones) or\n * the manager uses them. Ones whose agent is gone, or that exited while the office was away, are stopped: the office\n * resumes those sessions itself. Call hooksReady() once the busy ones are followed again.\n */\nexport async function reconnectClis(terminalFor: (agentId: string) => AgentTerminal | null): Promise<ReconnectedCli[]> {\n const held = await startKeeper(HOME_DIR, handleHook);\n const back: ReconnectedCli[] = [];\n for (const h of held) {\n const meta = (h.meta ?? {}) as Partial<CliMeta>;\n const term = meta.agentId ? terminalFor(meta.agentId) : null;\n if (h.exit !== null || !term || lives.has(term) || !isCli(meta.cli) || !meta.token || !meta.dir || !meta.agentId) {\n discardPty(h);\n if (meta.cli === 'codex' && meta.resumeId) void codexThread('archive', meta.resumeId, h.exit === null ? new Promise((r) => setTimeout(r, 5000)) : undefined);\n continue;\n }\n const l: LiveCli = { agentId: meta.agentId, cli: meta.cli, term, proc: adoptPty(h), token: meta.token, dir: meta.dir, resumeId: meta.resumeId ?? null, statusLine: '\uD83C\uDFE2 cubefarm', shots: new Set(), session: null };\n wire(l);\n waitAtPrompt(l);\n // Resizing makes the CLI draw its whole screen again, over whatever the saved copy of the terminal missed.\n setTimeout(() => quietly(() => (l.proc?.resize(term.cols - 1, term.rows), l.proc?.resize(term.cols, term.rows))), 500);\n back.push({ agentId: l.agentId, cli: l.cli, resumeId: l.resumeId, busy: !!meta.busy });\n }\n return back;\n}\n\nexport { hooksReady };\n\n/**\n * What a desk clean-up (releaseDesk) must leave alone: the keeper, every CLI in a terminal, and the office's session\n * files, which only the CLIs' own command lines carry (Codex's instructions name the worktree, for one).\n */\nexport function officeProcesses(): { pids: number[]; markers: string[] } {\n const pids = [keeperPid(), ...[...lives.values()].map((l) => l.proc?.pid ?? 0)].filter((p) => p > 0);\n return { pids, markers: [SESSIONS_DIR, BIN_DIR] };\n}\n\n/**\n * The office is stopping. On a restart its CLIs carry on in the terminal keeper, which holds their output and hooks\n * until it's back; when it quits for good they stop with it (once they're gone, their Codex threads are archived).\n */\nexport async function releaseClis(restart: boolean): Promise<void> {\n if (!restart) await Promise.all([...lives.values()].map(endLive)); // their exits come through the keeper\n leaveKeeper();\n}\n\n/** A CLI waiting at its prompt: what the manager types there becomes a follow-up. */\nfunction idleHook(live: LiveCli, b: Record<string, unknown>): Record<string, unknown> {\n switch (String(b.hook_event_name ?? '')) {\n case 'PreToolUse':\n return ALLOW;\n case 'UserPromptSubmit': {\n const text = String(b.prompt ?? '').trim();\n if (!text || live.term.onIdlePrompt?.(text)) return {};\n return { decision: 'block', reason: \"The office couldn't take that on as a follow-up right now (see the agent's panel). Nothing was sent.\" };\n }\n case 'StatusLine':\n return { statusLine: live.statusLine };\n }\n return {};\n}\n\n// ---------- the session ----------\n\n/**\n * The Claude Code session a hook reports, once its conversation is on disk: only then can --resume pick it up. Claude\n * writes the file during the first turn, after SessionStart and UserPromptSubmit, so a session the office keeps any\n * earlier could be one that never existed.\n */\nexport function resumableSession(b: Record<string, unknown>, exists: (file: string) => boolean): string | null {\n const id = typeof b.session_id === 'string' ? b.session_id : '';\n const file = typeof b.transcript_path === 'string' ? b.transcript_path : '';\n return id && file && exists(file) ? id : null;\n}\n\n/** Claude Code was told to resume a conversation that isn't on disk (it says so and exits 1). */\nexport const lostConversation = (screen: string) => /No conversation found with session ID/i.test(screen);\n\nexport function startCliSession(opts: SessionOptions, callbacks: SessionCallbacks): SessionHandle {\n const term = opts.terminal!;\n // A follow-up to the session a CLI is still waiting in picks that CLI up again, and so does an office that restarted\n // while it worked (reattach); anything else replaces it.\n const prev = lives.get(term);\n const waiting = !!prev?.proc && !prev.session;\n const adopt = waiting && (!!opts.reattach || (prev!.cli === (opts.cli ?? 'claude') && !!opts.resumeSessionId && prev!.resumeId === opts.resumeSessionId));\n if (prev && !adopt) endLive(prev);\n let live: LiveCli | null = adopt ? prev! : null;\n const cli = live?.cli ?? opts.cli ?? 'claude';\n const label = cliLabel(cli);\n\n const token = crypto.randomUUID();\n const sessionId = opts.resumeSessionId ?? crypto.randomUUID();\n const dir = path.join(SESSIONS_DIR, token);\n const started = Date.now();\n const statusLine = `\uD83C\uDFE2 cubefarm${opts.label ? ` \u00B7 ${opts.label}` : ''}`;\n const toolNames = new Map<string, string>();\n const officePrompts: string[] = []; // prompts the office typed, so the ones the manager typed are told apart\n const launched: string[] = []; // every prompt the CLI was given, as given (Codex: finds its main thread)\n let mainThread: string | null = opts.resumeSessionId ?? null;\n let kept: string | null = opts.resumeSessionId ?? null; // the Claude session the agent has saved to resume\n const usageResets = new Map<string, number | null>();\n const warned = new Set<string>();\n let done = false;\n let costUsd = 0;\n let turns = 0;\n let lastText = '';\n let turnError: string | null = null; // the turn failed (OpenCode reports errors separately from going idle)\n let begun = false; // the CLI took its first prompt\n let finishTimer: NodeJS.Timeout | undefined;\n let bootTimer: NodeJS.Timeout | undefined;\n let screenTimer: NodeJS.Timeout | undefined;\n let shotTimer: NodeJS.Timeout | undefined;\n const nudged = new Set<string>();\n let trustKeys = 0; // keys pressed on a folder-trust question (a few at most)\n let trustedAt = 0;\n\n const cb: SessionCallbacks = { ...callbacks };\n const log = (entries: LogEntry[]) => entries.length && cb.log(entries);\n\n /** Codex and OpenCode don't report tool results: pass on the screenshots their browser saved instead. all: the last look. */\n const collectShots = (all = false) => {\n const l = live;\n if (!l || cli === 'claude' || !opts.browserTesting) return;\n for (const shot of newScreenshots(path.join(l.dir, 'browser'), l.shots, all ? Infinity : Date.now())) {\n l.shots.add(shot.name);\n try {\n cb.screenshot(fs.readFileSync(shot.file), shot.mime);\n } catch {\n // removed before we got to it\n }\n }\n };\n\n /** The session is over. A developer's CLI that ended its turn normally stays at its prompt (keep); others close. */\n const finish = (r: Omit<SessionResult, 'costUsd' | 'turns'>, keep = false) => {\n if (done) return;\n done = true;\n for (const t of [finishTimer, bootTimer]) clearTimeout(t);\n clearInterval(screenTimer);\n clearInterval(shotTimer);\n collectShots(true);\n if (term.onInput === watchKeys) term.onInput = null;\n const l = live;\n if (l && lives.get(term) === l) {\n l.session = null;\n if (keep && opts.keepAlive && l.proc) waitAtPrompt(l);\n else endLive(l);\n }\n cb.tool(null);\n cb.finished({ ...r, costUsd, turns });\n };\n\n /** A turn ended: finished, unless the CLI picks up another prompt within the grace period. */\n const turnEnded = (text: string) => {\n lastText = text;\n cb.tool(null);\n clearTimeout(finishTimer);\n finishTimer = setTimeout(() => finish({ ok: !turnError, text: lastText, errors: turnError ? [turnError] : [] }, true), FINISH_GRACE_MS);\n };\n const busy = () => {\n begun = true;\n clearTimeout(finishTimer);\n };\n\n /** The turn was interrupted from the terminal: the office treats it like Stop, and the CLI waits for the manager. */\n const interrupted = () => finish({ ok: false, text: lastText, errors: ['Interrupted in the terminal'], interrupted: true }, true);\n\n /** Esc typed in the terminal while the agent works: if the CLI then says it interrupted the turn, it's over. */\n const watchKeys = (data: string) => {\n if (data !== '\\x1b' || done || !begun) return;\n const before = interruptions(term.screen());\n let looks = 0;\n const look = () => {\n if (done) return;\n if (interruptions(term.screen()) > before) interrupted();\n else if (++looks < 4) setTimeout(look, 1000);\n };\n setTimeout(look, 800);\n };\n term.onInput = watchKeys;\n\n const assistantLines = (text: string): LogEntry[] => {\n const lines = text.split('\\n');\n const out: LogEntry[] = lines.slice(0, 30).map((l, i) => ({ kind: 'text', text: `${i === 0 ? '\u25CF ' : ' '}${l}` }));\n if (lines.length > 30) out.push({ kind: 'text', text: ` \u2026 (${lines.length - 30} more lines)` });\n return out;\n };\n\n const onStatus = (b: Record<string, unknown>) => {\n const cost = Number((b.cost as { total_cost_usd?: unknown } | undefined)?.total_cost_usd);\n if (Number.isFinite(cost)) costUsd = cost;\n const limits = (b.rate_limits ?? {}) as Record<string, { used_percentage?: unknown; resets_at?: unknown } | null>;\n for (const [type, l] of Object.entries(limits)) {\n const used = Number(l?.used_percentage);\n if (!Number.isFinite(used)) continue;\n const resetsAt = Number(l?.resets_at) > 0 ? Number(l?.resets_at) * 1000 : null;\n usageResets.set(type, used >= 100 ? resetsAt : null);\n if (used >= USAGE_WARN_PCT && used < 100 && !warned.has(type)) {\n warned.add(type);\n cb.usageWarning?.({ resetsAt, rateLimitType: type, utilization: used / 100 });\n }\n }\n return { statusLine };\n };\n\n const hook = (b: Record<string, unknown>): Record<string, unknown> => {\n const event = String(b.hook_event_name ?? '');\n const sub = typeof b.agent_id === 'string' && b.agent_id !== ''; // a subagent's call: kept off the log\n if (cli === 'claude' && !sub && b.session_id !== kept) {\n const id = resumableSession(b, fs.existsSync);\n if (id) {\n kept = id;\n cb.sessionId(id);\n }\n }\n switch (event) {\n case 'PreToolUse': {\n const name = String(b.tool_name ?? '');\n const input = toolInput(b);\n if (!sub) {\n busy();\n turns += 1;\n toolNames.set(String(b.tool_use_id ?? ''), name);\n log([{ kind: 'tool', tool: name, text: `\u23FA ${describeTool(opts.cwd, name, input)}` }, ...(name === 'TodoWrite' ? todoLines(input) : [])]);\n cb.tool(name);\n if (name === 'mcp__playwright__browser_navigate' && typeof input.url === 'string') cb.browserUrl(input.url);\n }\n return ALLOW;\n }\n case 'PostToolUse':\n case 'PostToolUseFailure': {\n if (sub) return {};\n const name = toolNames.get(String(b.tool_use_id ?? '')) ?? String(b.tool_name ?? '');\n const out = toolOutput(b.tool_response);\n // Codex's unnamed screenshots are collected from the browser's folder (its hooks may not be trusted yet).\n if (cli === 'claude') for (const img of out.images) cb.screenshot(Buffer.from(img.data, 'base64'), img.mime);\n const saved = name === 'mcp__playwright__browser_take_screenshot' && !out.images.length ? screenshotFile(opts.cwd, out.text) : null;\n if (saved) cb.screenshot(saved.data, saved.mime);\n if (name.startsWith('mcp__playwright__')) {\n const url = out.text.match(/Page URL:\\s*(\\S+)/);\n if (url) cb.browserUrl(url[1]);\n }\n if (event === 'PostToolUseFailure') log([{ kind: 'error', text: ` \u23BF ${clip(tidyPaths(opts.cwd, String(b.error ?? out.text ?? 'Error')).split('\\n')[0] || 'Error', 200)}` }]);\n else if (name !== 'TodoWrite') log(summariseResult(opts.cwd, name, out.text));\n cb.tool(null);\n return {};\n }\n case 'UserPromptSubmit': {\n if (sub) return {};\n busy();\n const prompt = String(b.prompt ?? '').trim();\n const i = officePrompts.findIndex((p) => p.slice(0, 60) === prompt.slice(0, 60));\n if (i >= 0) officePrompts.splice(i, 1);\n else if (prompt) log([{ kind: 'manager', text: `\u25B6 Typed in the terminal: ${clip(prompt.split('\\n')[0], 200)}` }]);\n return {};\n }\n case 'Stop': {\n const text = String(b.last_assistant_message ?? '').trim();\n turns += 1;\n if (text) {\n log(assistantLines(text));\n cb.turn?.(text);\n }\n turnEnded(text);\n return {};\n }\n case 'StopFailure': {\n const error = String(b.error ?? 'unknown');\n const details = String(b.error_details ?? '').trim();\n if (error === 'rate_limit') cb.limited?.([...usageResets.values()].find((t) => t !== null) ?? null);\n finish({ ok: false, text: lastText, errors: [`${label} stopped: ${error.replace(/_/g, ' ')}${details ? ` (${clip(details, 160)})` : ''}`] }, true);\n return {};\n }\n case 'Notification': {\n if (b.notification_type === 'permission_prompt') log([{ kind: 'error', text: `\u26A0 ${label} is waiting for a permission answer: open the terminal to answer it.` }]);\n return {};\n }\n case 'StatusLine':\n return onStatus(b);\n case 'Interrupt': // Codex: Esc in its terminal\n if (!sub) interrupted();\n return {};\n // Codex's notify program and the OpenCode plugin\n case 'TurnComplete': {\n const thread = typeof b.session_id === 'string' ? b.session_id : '';\n if (cli === 'codex' && thread !== mainThread) {\n // Codex also runs side threads (it titles each task in one): the main thread is the one given our prompt.\n const input = String(b.input ?? '').trim();\n if (mainThread || !launched.some((p) => input.startsWith(p.slice(0, 40)))) return {};\n mainThread = thread;\n }\n if (thread) {\n cb.sessionId(thread);\n if (live && live.resumeId !== thread) {\n live.resumeId = thread;\n remember(live);\n }\n }\n const text = String(b.last_assistant_message ?? '').trim();\n turns += 1;\n if (text) {\n log(assistantLines(text));\n cb.turn?.(text);\n }\n turnEnded(text);\n return {};\n }\n case 'TurnError':\n turnError = `${label}: ${clip(String(b.error ?? 'error'), 200)}`;\n log([{ kind: 'error', text: `\u2717 ${turnError}` }]);\n return {};\n }\n return {};\n };\n\n /** The CLI quit on its own: /exit typed in the terminal, a crash, or it couldn't start (not signed in, bad flag\u2026). */\n const exited = (exitCode: number) => {\n if (cli === 'claude' && opts.resumeSessionId && !begun && lostConversation(term.screen())) {\n cb.sessionId(null);\n finish({ ok: false, text: '', errors: [`${label} couldn't find the conversation it was resuming, so the next session starts a new one.`] });\n return;\n }\n const ok = exitCode === 0 && (lastText !== '' || (cli !== 'claude' && Date.now() - started > 20_000));\n finish({ ok, text: lastText, errors: ok ? [] : [`${label} exited${exitCode ? ` with code ${exitCode}` : ''} before finishing.`] });\n };\n\n const handle: SessionHandle = {\n send(text) {\n const proc = live?.proc;\n if (done || !proc) return;\n busy();\n turnError = null;\n officePrompts.push(text.trim());\n // Pasted, so newlines stay in the message instead of sending it early; then Enter.\n const clean = text.replace(/\\x1b\\[20[01]~/g, '').replace(/\\r\\n?/g, '\\n');\n launched.push(clean.trim());\n quietly(() => proc.write(`\\x1b[200~${clean}\\x1b[201~`));\n setTimeout(() => quietly(() => live?.proc?.write('\\r')), 150);\n },\n stop() {\n finish({ ok: false, text: '', errors: ['Stopped by manager'] });\n },\n };\n\n if (adopt && live) {\n // Back in the CLI that was waiting at its prompt: same conversation, same terminal.\n clearTimeout(live.idleTimer);\n term.releaseIdle = null;\n live.session = { hook, exited };\n Object.assign(live, { statusLine });\n remember(live);\n if (live.resumeId) cb.sessionId(live.resumeId);\n if (opts.typed || opts.reattach) busy(); // typed at the prompt, or still at it after a restart: already running\n else handle.send(opts.prompt);\n shotTimer = setInterval(collectShots, 2000);\n return handle;\n }\n if (opts.reattach) {\n // Its CLI didn't make it through the restart after all.\n setTimeout(() => finish({ ok: false, text: '', errors: [`${label} stopped while the office restarted.`] }), 0);\n return handle;\n }\n\n // ---------- a new CLI: files for this session, and the command line ----------\n\n const cmd = commandFor(cli);\n if (!terminalsAvailable || !cmd) {\n const why = !terminalsAvailable ? 'the terminal module could not be loaded on this machine' : `${label} isn't installed (no \"${cli}\" on PATH)`;\n setTimeout(() => finish({ ok: false, text: '', errors: [`Could not start ${label}: ${why}.`] }), 0);\n return handle;\n }\n\n // Through the keeper, a hook waits while the office restarts instead of failing: the CLIs allow it longer.\n const keeper = keeperHookUrl();\n const hookUrl = `${keeper ?? officeUrl}/api/hooks/${token}`;\n // The browser for a session. Its snapshots and unnamed screenshots go to the session's folder, not the worktree.\n const browser = opts.browserTesting ? playwrightMcp(path.join(dir, 'browser')) : null;\n const browserIssue = opts.browserTesting ? browserProblem(browser) : null;\n if (browserIssue) log([{ kind: 'error', text: browserIssue }]);\n let prompt = opts.prompt;\n if (opts.outputSchema) {\n prompt += `\\n\\nWhen you are done, end your final message with your report as one JSON object in a \\`\\`\\`json block, matching this JSON schema:\\n${JSON.stringify(opts.outputSchema)}`;\n }\n let files: { settings: string; mcp: string | null; system: string };\n try {\n writeHelpers();\n fs.mkdirSync(dir, { recursive: true });\n const settings = {\n hooks: Object.fromEntries(HOOK_EVENTS.map((e) => [e, [{ hooks: [{ type: 'http', url: hookUrl, timeout: keeper ? 120 : 30 }] }]])),\n statusLine: { type: 'command', command: `${shellArg(process.execPath)} ${shellArg(path.join(BIN_DIR, 'statusline.cjs'))} ${shellArg(hookUrl)}`, padding: 0 },\n };\n const servers: Record<string, unknown> = {};\n if (browser) servers.playwright = browser;\n if (opts.office) servers.office = { type: 'http', url: `${officeUrl}/api/mcp/${token}` };\n files = { settings: path.join(dir, 'settings.json'), mcp: Object.keys(servers).length ? path.join(dir, 'mcp.json') : null, system: path.join(dir, 'instructions.md') };\n fs.writeFileSync(files.settings, JSON.stringify(settings, null, 2));\n if (files.mcp) fs.writeFileSync(files.mcp, JSON.stringify({ mcpServers: servers }, null, 2));\n fs.writeFileSync(files.system, opts.systemAppend);\n if (prompt.length > INLINE_PROMPT_MAX) {\n const file = path.join(dir, 'task.md');\n fs.writeFileSync(file, prompt);\n prompt = `Your task is in ${file}. Read all of it first, then do what it says.`;\n }\n } catch (err) {\n setTimeout(() => finish({ ok: false, text: '', errors: [`Could not prepare ${label}: ${(err as Error).message}`] }), 0);\n return handle;\n }\n officePrompts.push(prompt.trim()); // as given: a long one is a pointer to its file\n launched.push(prompt.trim());\n\n const launch = launchArgs(cli, {\n prompt,\n systemAppend: opts.systemAppend,\n model: opts.model,\n effort: opts.effort,\n resumeId: opts.resumeSessionId,\n sessionId,\n name: opts.label ?? 'cubefarm',\n role: opts.role,\n additionalDirectories: opts.additionalDirectories,\n files,\n notify: { script: path.join(BIN_DIR, 'notify.cjs'), url: hookUrl },\n codexHook: path.join(BIN_DIR, 'codex-hook.cjs'),\n plugin: pathToFileURL(path.join(BIN_DIR, 'opencode-plugin.mjs')).href,\n browser,\n });\n\n // Each agent must be a clean instance on the account its CLI is logged into: no API keys (they would switch Claude\n // Code's billing to the API) and nothing inherited from a Claude Code session the office itself was started from.\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(process.env)) {\n if (v === undefined) continue;\n if (/^(ANTHROPIC_|CLAUDE)/i.test(k) && k !== 'CLAUDE_CONFIG_DIR') continue;\n if (/^(NO_COLOR|FORCE_COLOR|TERM_PROGRAM|TERM_PROGRAM_VERSION|CODEX_THREAD_ID|OPENCODE_CONFIG_CONTENT)$/i.test(k)) continue;\n env[k] = v;\n }\n Object.assign(env, { TERM: 'xterm-256color', COLORTERM: 'truecolor' }, launch.env);\n\n if (cli === 'claude' && opts.resumeSessionId) cb.sessionId(sessionId);\n term.note(`\u2500\u2500 ${label}${opts.label ? ` \u00B7 ${opts.label}` : ''} \u2500\u2500`);\n const resumeId = cli === 'claude' ? sessionId : (opts.resumeSessionId ?? null);\n const l: LiveCli = { agentId: opts.agentId ?? '', cli, term, proc: null, token, dir, resumeId, statusLine, shots: new Set(), session: { hook, exited } };\n const begin = () => {\n if (done) return; // stopped while its thread was being unarchived\n let p: Pty;\n try {\n p = spawnPty(cmd.file, [...cmd.args, ...launch.args], { cols: term.cols, rows: term.rows, cwd: opts.cwd, env }, metaOf(l));\n } catch (err) {\n setTimeout(() => finish({ ok: false, text: '', errors: [`Could not start ${label}: ${(err as Error).message}`] }), 0);\n return;\n }\n l.proc = p;\n live = l;\n wire(l, opts.office);\n shotTimer = setInterval(collectShots, 2000);\n\n // Starting up: answer the folder-trust question for the office's own worktrees (the answer that trusts it), and\n // say so when a CLI is waiting on something only the manager can do (signing in).\n screenTimer = setInterval(() => {\n if (done || Date.now() - started > BOOT_MS * 2) return clearInterval(screenTimer);\n const screen = term.screen();\n const review = hookReviewKey(screen);\n const key = trustKeys < 12 && Date.now() - trustedAt > 3000 ? (trustKey(screen) ?? review) : null;\n if (key === 'down') {\n trustKeys += 1;\n quietly(() => p.write(term.appCursor ? '\\x1bOB' : '\\x1b[B'));\n } else if (key === 'enter') {\n trustKeys += 1;\n trustedAt = Date.now(); // the question takes a moment to go: don't answer it twice\n if (!review) log([{ kind: 'system', text: `\u2713 Trusted the worktree for ${label}.` }]);\n else if (!hooksHinted) {\n hooksHinted = true;\n log([{ kind: 'system', text: `\u2139 To see ${label}'s steps here, trust the office's hooks once: in this terminal, type /hooks and press t. Until then the office shows its task.` }]);\n }\n quietly(() => p.write('\\r'));\n }\n if (!nudged.has('login') && /Not logged in|run \\/login|Select login method|Sign in with ChatGPT|Please login|Invalid API key/i.test(screen)) {\n nudged.add('login');\n log([{ kind: 'error', text: `\u26A0 ${label} needs you to sign in: open the terminal and sign in there, or run \"${cli}\" in a terminal of your own.` }]);\n } else if (!nudged.has('setup') && !trustKey(screen) && Date.now() - trustedAt > 5000 && /Choose the text style|Press Enter to continue|Bypass Permissions mode|Settings Error/i.test(screen)) {\n // First-run screens only the manager should answer: the CLI waits for them in the terminal.\n nudged.add('setup');\n log([{ kind: 'error', text: `\u26A0 ${label} is waiting on a setup screen: open the terminal to answer it.` }]);\n }\n }, 1000);\n bootTimer = setTimeout(() => {\n if (!done && !begun && cli === 'claude') log([{ kind: 'error', text: `\u26A0 ${label} hasn't started on the task yet. Open the terminal to see what it's waiting for.` }]);\n }, BOOT_MS);\n };\n // Codex won't resume a thread the office archived (see codexThread): it's unarchived first.\n if (cli === 'codex' && opts.resumeSessionId) void codexThread('unarchive', opts.resumeSessionId).then(begin);\n else begin();\n\n return handle;\n}\n", "import fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { run } from './exec.ts';\nimport type { AgentCli, CliView, EffortLevel } from '../shared/types.ts';\n\n// The coding-agent CLIs an agent can run in its terminal, how to find them on this machine, and how to start one on\n// a task. Claude Code is fully wired in: its hooks report every tool call to the office.\n// The others start on the same prompt and report only when a turn ends (Codex's notify program, an OpenCode plugin);\n// the office shows their task instead of their tool calls.\n\nexport interface CliDef {\n id: AgentCli;\n label: string;\n command: string;\n integrated: boolean;\n}\n\nexport const CLIS: CliDef[] = [\n { id: 'claude', label: 'Claude Code', command: 'claude', integrated: true },\n { id: 'codex', label: 'Codex', command: 'codex', integrated: false },\n { id: 'opencode', label: 'OpenCode', command: 'opencode', integrated: false },\n];\n\nexport const isCli = (v: unknown): v is AgentCli => CLIS.some((c) => c.id === v);\nexport const cliLabel = (id: AgentCli) => CLIS.find((c) => c.id === id)?.label ?? id;\n\n// ---------- finding a CLI ----------\n\nconst WIN = process.platform === 'win32';\n\n/** The executable for a command name on PATH: on Windows only .exe/.cmd/.bat/.com, never an extensionless sh shim. */\nexport function resolveCommand(name: string, env: NodeJS.ProcessEnv = process.env): string | null {\n const key = Object.keys(env).find((k) => k.toUpperCase() === 'PATH') ?? 'PATH';\n const dirs = (env[key] ?? '').split(path.delimiter).filter(Boolean);\n const exts = WIN ? (env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD').split(';').filter((e) => /^\\.(exe|cmd|bat|com)$/i.test(e)) : [''];\n for (const dir of dirs) {\n for (const ext of exts) {\n const file = path.join(dir, name + ext.toLowerCase());\n try {\n const st = fs.statSync(file);\n if (st.isFile() && (WIN || (st.mode & 0o111) !== 0)) return file;\n } catch {\n // not here\n }\n }\n }\n return null;\n}\n\n/**\n * npm installs Windows CLIs as .cmd shims. Running one puts every argument through cmd.exe, which expands %VARS% and\n * trips over quotes in a prompt, so run what the shim runs instead: the package's .exe, or node on its script.\n */\nexport function unwrapCmdShim(shimPath: string, text: string): { file: string; args: string[] } | null {\n const line = text.split(/\\r?\\n/).find((l) => /%\\*\\s*$/.test(l));\n if (!line) return null;\n const dir = path.dirname(shimPath);\n const targets = [...line.matchAll(/\"%dp0%\\\\([^\"]+)\"/g)].map((m) => path.join(dir, m[1]));\n const target = targets[targets.length - 1];\n if (!target) return null;\n if (/\\.exe$/i.test(target)) return { file: target, args: [] };\n if (!/\\.[cm]?js$/i.test(target)) return null;\n const between = line.slice(line.indexOf('\"%_prog%\"') + '\"%_prog%\"'.length, line.lastIndexOf(`\"%dp0%\\\\`));\n const nodeFlags = line.includes('\"%_prog%\"') ? between.trim().split(/\\s+/).filter((f) => f.startsWith('--')) : [];\n const localNode = path.join(dir, 'node.exe');\n return { file: fs.existsSync(localNode) ? localNode : process.execPath, args: [...nodeFlags, target] };\n}\n\n/**\n * The Claude Code the Agent SDK ships as a per-platform package (the one `cubefarm login` signs in with), so the\n * terminal runtime works without Claude Code installed, on the version the office was tested with. Same lookup as\n * the SDK's own and bin/cubefarm.js.\n */\nlet bundled: string | null | undefined;\n\nfunction bundledClaude(): string | null {\n if (bundled !== undefined) return bundled;\n bundled = null;\n let sdk: string;\n try {\n sdk = createRequire(import.meta.url).resolve('@anthropic-ai/claude-agent-sdk');\n } catch {\n return null;\n }\n const { platform, arch } = process;\n // Only Linux needs the report (glibc or musl). On Windows it walks every native handle, and with pseudo-consoles\n // closing on other threads that takes the whole office down.\n const report = platform === 'linux' ? (process.report?.getReport() as { header?: { glibcVersionRuntime?: string } } | undefined) : undefined;\n const musl = platform === 'linux' && !report?.header?.glibcVersionRuntime;\n const targets = platform === 'linux' ? (musl ? [`linux-${arch}-musl`, `linux-${arch}`] : [`linux-${arch}`, `linux-${arch}-musl`]) : [`${platform}-${arch}`];\n for (const target of targets) {\n try {\n bundled = createRequire(sdk).resolve(`@anthropic-ai/claude-agent-sdk-${target}/claude${WIN ? '.exe' : ''}`);\n return bundled;\n } catch {\n // not installed for this target\n }\n }\n return null;\n}\n\n/** How to start a CLI: the program and the arguments that come before the office's own. */\nexport function commandFor(id: AgentCli): { file: string; args: string[] } | null {\n const bundled = id === 'claude' ? bundledClaude() : null;\n if (bundled) return { file: bundled, args: [] };\n const def = CLIS.find((c) => c.id === id);\n const found = def && resolveCommand(def.command);\n if (!found) return null;\n if (WIN && /\\.(cmd|bat)$/i.test(found)) {\n try {\n return unwrapCmdShim(found, fs.readFileSync(found, 'utf8')) ?? { file: found, args: [] };\n } catch {\n return { file: found, args: [] };\n }\n }\n return { file: found, args: [] };\n}\n\n/** Which CLIs this machine has, with their versions. */\nexport async function detectClis(): Promise<CliView[]> {\n return Promise.all(\n CLIS.map(async (c) => {\n const cmd = commandFor(c.id);\n const version = cmd ? await run(cmd.file, [...cmd.args, '--version'], { timeoutMs: 20_000 }).catch(() => null) : null;\n return { id: c.id, label: c.label, installed: !!cmd, version: version?.split(/\\r?\\n/)[0].trim().slice(0, 60) || null, integrated: c.integrated };\n }),\n );\n}\n\n// ---------- starting one on a task ----------\n\nexport interface LaunchContext {\n prompt: string;\n systemAppend: string;\n model: string; // '' = the CLI's own default\n effort: EffortLevel | '';\n resumeId?: string;\n sessionId: string; // the id the office gives a new Claude Code session\n name: string; // shown in Claude Code's prompt box and the terminal title\n role: 'dev' | 'qa' | 'ceo';\n additionalDirectories: string[];\n /** Files the office wrote for this session (settings, MCP config, instructions). */\n files: { settings: string; mcp: string | null; system: string };\n /** Where the CLI's turn-complete signal goes (Codex notify, the OpenCode plugin). */\n notify: { script: string; url: string };\n /** Codex's hook program: forwards each hook to the office (notify.url). */\n codexHook: string;\n plugin: string; // file URL of the OpenCode plugin\n /** The Playwright MCP server, when the floor tests in a browser. Claude Code gets it through its MCP config file. */\n browser: { command: string; args: string[] } | null;\n}\n\nexport interface Launch {\n args: string[];\n env: Record<string, string>;\n}\n\nconst EFFORT_CODEX: Record<EffortLevel, string> = { low: 'low', medium: 'medium', high: 'high', xhigh: 'xhigh', max: 'xhigh' };\n\n/** Codex hooks the office listens to: its steps, and Esc interrupting a turn. Turn endings come from notify. */\nexport const CODEX_HOOK_EVENTS = ['SessionStart', 'UserPromptSubmit', 'PreToolUse', 'PostToolUse', 'Interrupt'];\n\n/**\n * The command Codex runs for each hook. It never changes (the office's address travels in CUBEFARM_HOOK_URL), so the\n * manager trusts the hooks once in Codex's /hooks and that holds for every session. On Windows, Codex runs it through\n * PowerShell or cmd depending on its version, and a command starting with a quote fails in both: plain `node` (on the\n * PATH the office gave it) and the script in double quotes work in either. Elsewhere it goes through the shell.\n */\nexport function codexHookCommand(node: string, script: string, win = WIN): string {\n return win ? `node \"${script}\"` : [node, script].map((s) => `'${s.replaceAll(\"'\", `'\"'\"'`)}'`).join(' ');\n}\n\nexport function launchArgs(id: AgentCli, ctx: LaunchContext): Launch {\n switch (id) {\n case 'claude': {\n const disallowed = ['AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode', ...(ctx.role === 'ceo' ? ['Bash', 'PowerShell', 'NotebookEdit'] : [])];\n const args = [\n ...(ctx.resumeId ? ['--resume', ctx.resumeId] : ['--session-id', ctx.sessionId]),\n ...(ctx.model ? ['--model', ctx.model] : []),\n ...(ctx.effort ? ['--effort', ctx.effort] : []),\n // The office's PreToolUse hook answers every permission question (allow, or deny with an office rule).\n '--permission-mode',\n 'acceptEdits',\n // On top of the manager's own setup (settings, skills, plugins, MCP servers): the office's hooks and servers.\n '--settings',\n ctx.files.settings,\n ...(ctx.files.mcp ? ['--mcp-config', ctx.files.mcp] : []),\n '--append-system-prompt-file',\n ctx.files.system,\n '--name',\n ctx.name,\n ...ctx.additionalDirectories.flatMap((d) => ['--add-dir', d]),\n '--disallowedTools',\n ...disallowed,\n '--',\n ctx.prompt,\n ];\n return { args, env: { DISABLE_AUTOUPDATER: '1' } }; // the office's own copy: agents mustn't each try to update it\n }\n case 'codex': {\n const toml = (s: string) => JSON.stringify(s); // a JSON string is a valid TOML basic string\n const args = [\n '--no-alt-screen',\n '-c',\n `notify=[${[process.execPath, ctx.notify.script, ctx.notify.url].map(toml).join(',')}]`,\n '-c',\n `developer_instructions=${toml(ctx.systemAppend)}`,\n ...(ctx.model ? ['-m', ctx.model] : []),\n ...(ctx.effort ? ['-c', `model_reasoning_effort=${toml(EFFORT_CODEX[ctx.effort])}`] : []),\n ...(ctx.browser ? ['-c', `mcp_servers.playwright={command=${toml(ctx.browser.command)},args=[${ctx.browser.args.map(toml).join(',')}]}`] : []),\n ...CODEX_HOOK_EVENTS.flatMap((e) => ['-c', `hooks.${e}=[{hooks=[{type=\"command\",command=${toml(codexHookCommand(process.execPath, ctx.codexHook))},timeout=10}]}]`]),\n // Like the manager's own Codex, but it can't stop to ask: no approvals and no sandbox (its sandbox can't reach\n // the credential store, so git and gh fail in it).\n '--dangerously-bypass-approvals-and-sandbox',\n ];\n return { args: ctx.resumeId ? ['resume', ...args, ctx.resumeId, ctx.prompt] : [...args, '--', ctx.prompt], env: { CUBEFARM_HOOK_URL: ctx.notify.url } };\n }\n case 'opencode': {\n const config = {\n plugin: [ctx.plugin],\n instructions: [ctx.files.system],\n autoupdate: false, // several agents starting at once must not each reinstall it\n permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' }, // it can't stop to ask either\n ...(ctx.browser ? { mcp: { playwright: { type: 'local', command: [ctx.browser.command, ...ctx.browser.args], enabled: true } } } : {}),\n };\n // No project argument: it starts in its terminal's folder, and a desk path in its command line would make the\n // desk clean-up take it for a leftover.\n const args = [\n '--auto',\n ...(ctx.model ? ['--model', ctx.model] : []),\n ...(ctx.resumeId ? ['--session', ctx.resumeId] : []),\n '--prompt',\n ctx.prompt,\n ];\n return { args, env: { OPENCODE_CONFIG_CONTENT: JSON.stringify(config), CUBEFARM_NOTIFY_URL: ctx.notify.url } };\n }\n }\n}\n\n// ---------- Codex's saved threads ----------\n\n/** Runs each key's steps one after another; one that fails doesn't hold up the next. */\nexport function oneAtATime() {\n const tails = new Map<string, Promise<void>>();\n return (key: string, step: () => Promise<unknown>): Promise<void> => {\n const next = (tails.get(key) ?? Promise.resolve()).then(step).then(\n () => undefined,\n () => undefined,\n );\n tails.set(key, next);\n void next.then(() => tails.get(key) === next && tails.delete(key));\n return next;\n };\n}\n\nconst threadSteps = oneAtATime();\n\n/**\n * Codex saves every terminal session where the manager's own Codex and ChatGPT apps list it with their chats. The\n * office archives its threads there once their CLI is gone (`after`), and unarchives one before resuming it: Codex\n * won't resume an archived thread. A thread's steps run in order; one with nothing to do (already archived) fails.\n */\nexport function codexThread(action: 'archive' | 'unarchive', id: string, after?: Promise<unknown>): Promise<void> {\n return threadSteps(id, async () => {\n await after;\n const cmd = commandFor('codex');\n if (cmd) await run(cmd.file, [...cmd.args, action, id], { timeoutMs: 30_000 });\n });\n}\n\n// ---------- prompts the office answers ----------\n\nconst TRUST_PROMPT = /Quick safety check|Do you trust the (files|contents) (in|of) this|trust this folder|allow Codex to work in this folder/i;\n\n/**\n * The key that moves a CLI's folder-trust question toward trusting the office's own worktree: Enter when the\n * selected option says yes, Down when it says no (Claude Code selects \"No, exit\" first), null when there's no such\n * question on screen.\n */\nexport function trustKey(screen: string): 'enter' | 'down' | null {\n if (!TRUST_PROMPT.test(screen)) return null;\n const selected = screen.match(/^\\s*[\u276F\u203A]\\s*(?:\\d+\\.\\s*)?(.+)$/m)?.[1] ?? '';\n if (/^(yes|trust|continue|proceed)\\b/i.test(selected.trim())) return 'enter';\n if (/^(no|exit|quit|cancel)\\b/i.test(selected.trim())) return 'down';\n return null;\n}\n\n/**\n * Codex asks to review new hooks before it starts. They only show the office Codex's steps, so trusting them is the\n * manager's call (once, in /hooks): the office moves to \"Continue without trusting\" (Down) and takes it (Enter).\n */\nexport function hookReviewKey(screen: string): 'enter' | 'down' | null {\n if (!/Hooks need review/i.test(screen)) return null;\n const selected = screen.match(/^\\s*[\u276F\u203A]\\s*(?:\\d+\\.\\s*)?(.+)$/m)?.[1] ?? '';\n return /^continue without trusting/i.test(selected.trim()) ? 'enter' : 'down';\n}\n\n/**\n * Lines on screen where a CLI says it interrupted a turn (Claude Code: \"Interrupted \u00B7 What should Claude do\n * instead?\", Codex: \"Conversation interrupted\"). Esc fires no hook in Claude Code, so a new one is how the office\n * knows the manager stopped the turn from the terminal.\n */\nexport function interruptions(screen: string): number {\n return screen.split('\\n').filter((l) => /\\binterrupted\\b/i.test(l)).length;\n}\n\n// ---------- helper scripts the CLIs run ----------\n\n/** Claude Code's status line: posts its data (cost, usage limits) to the office and shows the office's line. */\nexport const STATUSLINE_SOURCE = String.raw`// cubefarm: Claude Code's status line. Forwards the session's status to the office and prints the office's line.\nconst url = process.argv[2];\nlet body = '';\nprocess.stdin.on('data', (c) => (body += c));\nprocess.stdin.on('end', async () => {\n try {\n const status = JSON.parse(body);\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ hook_event_name: 'StatusLine', session_id: status.session_id, cost: status.cost, rate_limits: status.rate_limits }),\n signal: AbortSignal.timeout(2000),\n });\n const out = await res.json();\n process.stdout.write(String(out.statusLine ?? ''));\n } catch {\n process.stdout.write('cubefarm');\n }\n});\n`;\n\n/** Codex's notify program: Codex runs it with a JSON argument when a turn completes. */\nexport const NOTIFY_SOURCE = String.raw`// cubefarm: Codex's notify program. Tells the office a turn is complete.\nconst [url, payload] = process.argv.slice(2);\nlet event = {};\ntry {\n event = JSON.parse(payload ?? '{}');\n} catch {}\nif (event.type === 'agent-turn-complete') {\n const input = String((event['input-messages'] ?? [])[0] ?? '').slice(0, 300);\n fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ hook_event_name: 'TurnComplete', session_id: event['thread-id'] ?? null, last_assistant_message: event['last-assistant-message'] ?? '', input }),\n signal: AbortSignal.timeout(3000),\n }).catch(() => {});\n}\n`;\n\n/** Codex's hook program: passes what Codex tells a hook on to the office and answers nothing, so Codex carries on as usual. */\nexport const CODEX_HOOK_SOURCE = String.raw`// cubefarm: Codex's hooks. Tells the office what Codex is doing; never changes what it does.\nconst url = process.env.CUBEFARM_HOOK_URL;\nconst chunks = [];\nprocess.stdin.on('data', (c) => chunks.push(c));\nprocess.stdin.on('end', async () => {\n try {\n if (url) await fetch(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: Buffer.concat(chunks), signal: AbortSignal.timeout(5000) });\n } catch {}\n process.stdout.write('{}');\n});\n`;\n\n/** OpenCode plugin: reports its session and when it goes idle (a turn is complete). No imports: loaded from a file. */\nexport const OPENCODE_PLUGIN_SOURCE = String.raw`// cubefarm: tells the office when OpenCode's session goes idle.\nexport default async function CubefarmPlugin({ client } = {}) {\n const url = process.env.CUBEFARM_NOTIFY_URL;\n if (!url) return {};\n let root;\n const post = (body) =>\n fetch(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body), signal: AbortSignal.timeout(3000) }).catch(() => {});\n const lastReply = async (id) => {\n try {\n const res = await client.session.messages({ path: { id } });\n const reply = (res?.data ?? []).filter((m) => m?.info?.role === 'assistant').pop();\n return (reply?.parts ?? []).filter((p) => p?.type === 'text').map((p) => p.text).join('\\n').trim();\n } catch {\n return '';\n }\n };\n return {\n event: async ({ event }) => {\n const props = event?.properties ?? {};\n if (event?.type === 'session.created' && !props.info?.parentID && !root) root = props.info?.id;\n const sessionID = props.sessionID ?? props.info?.id;\n if (event?.type === 'session.idle' && (!root || sessionID === root)) {\n post({ hook_event_name: 'TurnComplete', session_id: sessionID ?? null, last_assistant_message: sessionID ? await lastReply(sessionID) : '' });\n }\n if (event?.type === 'session.error') post({ hook_event_name: 'TurnError', session_id: sessionID ?? null, error: String(props.error?.data?.message ?? props.error?.name ?? 'error') });\n },\n };\n}\n`;\n", "import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport net from 'node:net';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { IPty } from '@lydell/node-pty';\nimport { encode, hostSocket, PTY_PROTOCOL, readMessages, type FromHost, type HeldPty } from './ptyProtocol.ts';\n\n// The office's side of its terminal keeper (ptyHost.ts): CLIs start in terminals the keeper holds, so they outlive an\n// office restart, and the office picks them up again when it comes back. If the keeper can't start, terminals run in\n// the office's own process and stop with it.\n\nconst nodePty = await import('@lydell/node-pty').catch((err: unknown) => {\n console.warn(` terminals unavailable: ${(err as Error).message}`);\n return null;\n});\n\n/** The native terminal module loaded, so the terminal runtime can run. */\nexport const terminalsAvailable = nodePty !== null;\n\n/** A CLI's pseudo-terminal, held by the keeper or by this process. */\nexport interface Pty {\n readonly pid: number;\n write(data: string): void;\n resize(cols: number, rows: number): void;\n /** Stop the CLI and everything it started. */\n kill(): void;\n /** Kept with the terminal, for the office that picks it up after a restart. */\n setMeta(meta: unknown): void;\n onData(cb: (data: string) => void): void;\n onExit(cb: (code: number) => void): void;\n}\n\nexport interface PtyOptions {\n cols: number;\n rows: number;\n cwd: string;\n env: Record<string, string>;\n}\n\nlet conn: net.Socket | null = null;\nlet leaving = false; // the office is closing its connection on purpose (a restart): the terminals carry on\nlet hookPort = 0;\nlet hostPid = 0;\nlet found: HeldPty[] = [];\nconst remote = new Map<string, RemotePty>();\nlet hookHandler: (token: string, body: unknown) => unknown = () => ({});\n\nconst send = (m: Parameters<typeof encode>[0]) => {\n if (conn && !conn.destroyed) conn.write(encode(m));\n};\n\nclass RemotePty implements Pty {\n pid = 0;\n private dataFns: ((data: string) => void)[] = [];\n private exitFns: ((code: number) => void)[] = [];\n private done = false;\n constructor(readonly id: string) {\n remote.set(id, this);\n }\n write(data: string) {\n send({ op: 'write', id: this.id, data });\n }\n resize(cols: number, rows: number) {\n send({ op: 'resize', id: this.id, cols, rows });\n }\n kill() {\n send({ op: 'kill', id: this.id });\n }\n setMeta(meta: unknown) {\n send({ op: 'meta', id: this.id, meta });\n }\n onData(cb: (data: string) => void) {\n this.dataFns.push(cb);\n }\n onExit(cb: (code: number) => void) {\n this.exitFns.push(cb);\n }\n data(data: string) {\n for (const fn of this.dataFns) fn(data);\n }\n exit(code: number) {\n if (this.done) return;\n this.done = true;\n remote.delete(this.id);\n for (const fn of this.exitFns) fn(code);\n }\n}\n\nfunction onMessage(m: FromHost) {\n switch (m.op) {\n case 'spawned': {\n const p = remote.get(m.id);\n if (p) p.pid = m.pid;\n return;\n }\n case 'failed':\n console.warn(` could not start a terminal: ${m.error}`);\n return remote.get(m.id)?.exit(-1);\n case 'data':\n return remote.get(m.id)?.data(m.data);\n case 'exit':\n return remote.get(m.id)?.exit(m.code);\n case 'hook':\n void Promise.resolve()\n .then(() => hookHandler(m.token, m.body))\n .catch(() => ({}))\n .then((answer) => send({ op: 'hookReply', rid: m.rid, answer }));\n return;\n }\n}\n\n// ---------- connecting ----------\n\ntype Ready = Extract<FromHost, { op: 'ready' }>;\n\n/** Say hello to a keeper: its answer and the open socket, or null when none answers. */\nfunction connect(socket: string, secret: string): Promise<{ ready: Ready; sock: net.Socket } | null> {\n return new Promise((resolve) => {\n const sock = net.connect(socket);\n let ready = false;\n const fail = () => {\n clearTimeout(timer);\n sock.destroy();\n resolve(null);\n };\n const timer = setTimeout(fail, 2000);\n sock.once('error', fail);\n sock.once('connect', () => sock.write(encode({ op: 'hello', secret, version: PTY_PROTOCOL })));\n readMessages<FromHost>(sock, (m) => {\n if (ready) return onMessage(m);\n if (m.op !== 'ready') return;\n ready = true;\n clearTimeout(timer);\n sock.removeListener('error', fail);\n sock.on('error', () => undefined);\n resolve({ ready: m, sock });\n });\n sock.on('close', () => {\n if (conn !== sock) return;\n conn = null;\n if (leaving) return;\n // The keeper is gone, and its terminals with it.\n console.warn(' the terminal keeper stopped; running agents lost their terminals');\n for (const p of [...remote.values()]) p.exit(-1);\n });\n });\n}\n\n/** Node flags the office runs with that the keeper needs too (tsx in development), not debugging or watching. */\nconst runtimeFlags = () => process.execArgv.filter((a, i, all) => !/^--(inspect|watch|debug)/.test(a) && !/^--(inspect|watch|debug)/.test(all[i - 1] ?? ''));\n\nfunction launch(socket: string, secretFile: string) {\n const entry = path.join(import.meta.dirname, `ptyHost${path.extname(import.meta.filename)}`);\n spawn(process.execPath, [...runtimeFlags(), entry, 'launch', socket, secretFile], { detached: true, stdio: 'ignore', windowsHide: true })\n .once('error', () => undefined)\n .unref();\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\n/**\n * Connect to the office's terminal keeper, starting one if there's none (or replacing one on another version).\n * Returns the terminals it still holds from before a restart. Without a keeper, terminals run in this process.\n */\nexport async function startKeeper(home: string, onHook: (token: string, body: unknown) => unknown): Promise<HeldPty[]> {\n hookHandler = onHook;\n if (!nodePty) return [];\n const socket = hostSocket(home);\n const secretFile = path.join(home, 'pty.secret');\n try {\n if (!fs.existsSync(secretFile)) {\n fs.mkdirSync(home, { recursive: true });\n fs.writeFileSync(secretFile, crypto.randomBytes(24).toString('hex'), { mode: 0o600 });\n }\n } catch (err) {\n console.warn(` terminal keeper unavailable: ${(err as Error).message}`);\n return [];\n }\n const secret = fs.readFileSync(secretFile, 'utf8').trim();\n let hello = await connect(socket, secret);\n if (hello && hello.ready.version !== PTY_PROTOCOL) {\n // A keeper from another version of the office: its terminals can't be picked up, so they stop and it goes.\n console.log(` replacing the terminal keeper (v${hello.ready.version}); the ${hello.ready.ptys.length} terminal(s) it held are stopped`);\n hello.sock.end(encode({ op: 'shutdown' }));\n hello = null;\n await sleep(3500);\n }\n if (!hello) {\n launch(socket, secretFile);\n for (let i = 0; i < 30 && !hello; i++) {\n await sleep(200);\n hello = await connect(socket, secret);\n }\n }\n if (!hello) {\n console.warn(\" terminal keeper unavailable: agents' terminals run in the office and stop when it restarts\");\n return [];\n }\n conn = hello.sock;\n leaving = false;\n hookPort = hello.ready.hookPort;\n hostPid = hello.ready.pid ?? 0;\n found = hello.ready.ptys;\n return found;\n}\n\n/** The keeper's process (0 when there's none, or it didn't say): desk clean-ups must never stop it. */\nexport const keeperPid = () => (conn ? hostPid : 0);\n\n// ---------- terminals ----------\n\n/** Where the CLIs' hooks go: the keeper, which holds them while the office restarts. null: straight to the office. */\nexport function keeperHookUrl(): string | null {\n return conn ? `http://127.0.0.1:${hookPort}` : null;\n}\n\n/** A CLI in a new pseudo-terminal: in the keeper when there is one, else in this process (throws if it can't start). */\nexport function spawnPty(file: string, args: string[], o: PtyOptions, meta: unknown): Pty {\n if (conn) {\n const p = new RemotePty(crypto.randomUUID());\n send({ op: 'spawn', id: p.id, file, args, cwd: o.cwd, env: o.env, cols: o.cols, rows: o.rows, meta });\n return p;\n }\n if (!nodePty) throw new Error('the terminal module could not be loaded on this machine');\n // useConptyDll: Windows' own console host lingers after each CLI exits (one conhost.exe per terminal); the one\n // node-pty ships goes with its terminal. Ignored elsewhere.\n const p = nodePty.spawn(file, args, { name: 'xterm-256color', cols: o.cols, rows: o.rows, cwd: o.cwd, env: o.env, useConptyDll: true });\n return {\n get pid() {\n return p.pid;\n },\n write: (data) => p.write(data),\n resize: (cols, rows) => p.resize(cols, rows),\n kill: () => killTree(p),\n setMeta: () => undefined,\n onData: (cb) => void p.onData(cb),\n onExit: (cb) => void p.onExit(({ exitCode }) => cb(exitCode)),\n };\n}\n\n/** Take over a terminal the keeper held through a restart: what it printed meanwhile, then everything live. */\nexport function adoptPty(held: HeldPty): Pty {\n const p = new RemotePty(held.id);\n p.pid = held.pid;\n queueMicrotask(() => send({ op: 'attach', id: held.id })); // once the caller has its listeners on\n return p;\n}\n\n/** A held terminal nobody picks up: its CLI is stopped. */\nexport function discardPty(held: HeldPty) {\n send({ op: 'kill', id: held.id });\n}\n\n/** The office has picked up its terminals and their sessions: hooks that waited for it can come in. */\nexport function hooksReady() {\n send({ op: 'hooksReady' });\n}\n\n/** The office is restarting: its terminals stay with the keeper, which holds their output until it's back. */\nexport function leaveKeeper() {\n leaving = true;\n conn?.end();\n}\n\nfunction killTree(proc: IPty) {\n if (process.platform === 'win32') {\n const tk = spawn('taskkill', ['/PID', String(proc.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' });\n tk.once('error', () => undefined);\n return;\n }\n try {\n process.kill(-proc.pid, 'SIGTERM'); // the CLI leads its own session: take its MCP servers and tools with it\n } catch {\n proc.kill();\n }\n}\n", "import crypto from 'node:crypto';\nimport path from 'node:path';\nimport type { Socket } from 'node:net';\n\n// What the office and its terminal keeper (ptyHost.ts) say to each other over their local socket: one JSON message\n// per line. Kept free of the rest of the server so the keeper stays small and starts fast.\n\n/** Bumped when the messages change: an office that finds a keeper on another version replaces it. */\nexport const PTY_PROTOCOL = 1;\n\n/** A terminal the keeper holds, as it reports it to an office that (re)connects. */\nexport interface HeldPty {\n id: string;\n pid: number;\n /** What the office stored with it (who it belongs to, its session). */\n meta: unknown;\n /** The CLI has exited (while no office was listening): its exit code. */\n exit: number | null;\n}\n\nexport type ToHost =\n | { op: 'hello'; secret: string; version: number }\n | { op: 'hooksReady' } // the office has picked up its terminals: hooks that waited for it can come in now\n | { op: 'spawn'; id: string; file: string; args: string[]; cwd: string; env: Record<string, string>; cols: number; rows: number; meta: unknown }\n | { op: 'attach'; id: string } // an office picking up a terminal it found: what it missed, then everything live\n | { op: 'write'; id: string; data: string }\n | { op: 'resize'; id: string; cols: number; rows: number }\n | { op: 'meta'; id: string; meta: unknown }\n | { op: 'kill'; id: string }\n | { op: 'hookReply'; rid: number; answer: unknown }\n | { op: 'shutdown' }; // stop every terminal and exit (a keeper on another version)\n\nexport type FromHost =\n | { op: 'ready'; version: number; hookPort: number; ptys: HeldPty[]; pid?: number }\n | { op: 'spawned'; id: string; pid: number }\n | { op: 'failed'; id: string; error: string }\n | { op: 'data'; id: string; data: string }\n | { op: 'exit'; id: string; code: number }\n | { op: 'hook'; rid: number; token: string; body: unknown };\n\n/** The keeper's socket for an office home: a named pipe on Windows, a Unix socket in the home elsewhere. */\nexport function hostSocket(home: string, platform = process.platform): string {\n if (platform !== 'win32') return path.join(home, 'pty.sock');\n const tag = crypto.createHash('sha1').update(path.resolve(home).toLowerCase()).digest('hex').slice(0, 12);\n return `\\\\\\\\.\\\\pipe\\\\cubefarm-pty-${tag}`;\n}\n\nexport const encode = (m: ToHost | FromHost) => `${JSON.stringify(m)}\\n`;\n\n/** Calls back with each message a socket sends (newline-delimited JSON); a line that isn't JSON is skipped. */\nexport function readMessages<T>(sock: Socket, onMessage: (m: T) => void) {\n let buf = '';\n sock.setEncoding('utf8');\n sock.on('data', (chunk: string) => {\n buf += chunk;\n let nl: number;\n while ((nl = buf.indexOf('\\n')) >= 0) {\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + 1);\n if (!line) continue;\n let m: T;\n try {\n m = JSON.parse(line) as T;\n } catch {\n continue;\n }\n onMessage(m);\n }\n });\n}\n", "import { spawn, type ChildProcess } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport net from 'node:net';\nimport path from 'node:path';\nimport { git } from './exec.ts';\nimport * as workspace from './workspace.ts';\n\n// A floor's app, run for the preview monitor: checked out in its own worktree (never the floor's main checkout,\n// which for floor 1 is the folder the live office runs from), installed, started, and watched until its port answers.\n\nexport const PREVIEW_SLUG = 'preview';\nexport const PREVIEW_BRANCH = 'swarm-preview';\n/** Scratch folder inside the preview worktree, offered to commands and env as {tmp}; excluded from git status. */\nexport const PREVIEW_TMP = '.preview-tmp';\nconst INSTALL_MARKER = '.cubefarm-preview-install';\nconst START_TIMEOUT_MS = 3 * 60_000;\nconst INSTALL_TIMEOUT_MS = 15 * 60_000;\n\nexport interface PreviewJob {\n fullName: string;\n defaultBranch: string;\n pr: number | null;\n port: number;\n command: string | null;\n env: Record<string, string>;\n /** \"<floor> app \u00B7 <ref>\", for the demo's placeholder page. */\n title: string;\n}\n\nexport interface PreviewCallbacks {\n status(status: 'preparing' | 'installing' | 'starting' | 'running'): void;\n commit(sha: string): void;\n log(lines: string[]): void;\n /** The run ended by itself: failed to start, or the app exited. unconfigured: there was nothing to run. */\n failed(message: string, unconfigured?: boolean): void;\n}\n\nexport interface PreviewHandle {\n /** Stop the app (and anything it started). Safe to call in any phase. */\n stop(): Promise<void>;\n}\n\nexport interface PreviewBackend {\n start(job: PreviewJob, cb: PreviewCallbacks): PreviewHandle;\n /** Whether there is something to run with no command set (a package.json in the floor's checkout). */\n hasDefault(fullName: string): Promise<boolean>;\n}\n\n/** Replace {port} and {tmp}. */\nexport const fillPlaceholders = (s: string, port: number, tmp: string) => s.replaceAll('{port}', String(port)).replaceAll('{tmp}', tmp);\n\n/**\n * The environment a preview runs with: the office's, minus Claude credentials and config (same rule as the agents,\n * with no exceptions) and minus the office's own SWARM_* settings, so an app that is itself an office never\n * inherits the live office's home or port. Then the floor's env, then PORT.\n */\nexport function previewEnv(extra: Record<string, string>, port: number, tmp: string): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(process.env)) {\n if (v === undefined || /^(ANTHROPIC_|CLAUDE|SWARM_)/i.test(k)) continue;\n env[k] = v;\n }\n env.BROWSER = 'none'; // dev servers that open a browser tab on start shouldn't\n for (const [k, v] of Object.entries(extra)) env[k] = fillPlaceholders(v, port, tmp);\n env.PORT = String(port);\n return env;\n}\n\n/** Whether something accepts TCP connections on the port (IPv4 or IPv6 loopback). */\nexport async function portOpen(port: number): Promise<boolean> {\n const probe = (host: string) =>\n new Promise<boolean>((resolve) => {\n const sock = net.connect({ port, host });\n const done = (ok: boolean) => {\n sock.destroy();\n resolve(ok);\n };\n sock.setTimeout(800, () => done(false));\n sock.once('connect', () => done(true));\n sock.once('error', () => done(false));\n });\n const [v4, v6] = await Promise.all([probe('127.0.0.1'), probe('::1')]);\n return v4 || v6;\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nasync function readJson(file: string): Promise<{ scripts?: Record<string, string> } | null> {\n try {\n return JSON.parse(await fs.readFile(file, 'utf8'));\n } catch {\n return null;\n }\n}\n\n/** npm run dev, else start, else preview. Vite ignores PORT, so it is told the port when the script is plain vite. */\nexport function defaultCommand(pkg: { scripts?: Record<string, string> } | null): string | null {\n const scripts = pkg?.scripts ?? {};\n const name = ['dev', 'start', 'preview'].find((s) => typeof scripts[s] === 'string' && scripts[s].trim());\n if (!name) return null;\n const script = scripts[name];\n const vite = /^\\s*vite(\\s|$)/.test(script) && !/--port\\b/.test(script);\n return `npm run ${name}${vite ? ' -- --port {port} --strictPort' : ''}`;\n}\n\n/** Kill a process and its children. */\nfunction killTree(child: ChildProcess): Promise<void> {\n if (child.pid === undefined || child.exitCode !== null || child.signalCode !== null) return Promise.resolve();\n if (process.platform === 'win32') {\n return new Promise((resolve) => {\n const tk = spawn('taskkill', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' });\n tk.once('error', () => resolve());\n tk.once('close', () => resolve());\n });\n }\n try {\n process.kill(-child.pid, 'SIGKILL'); // the whole process group (spawned detached)\n } catch {\n child.kill('SIGKILL');\n }\n return Promise.resolve();\n}\n\nclass Stopped extends Error {}\n\n/** One run of a floor's app, from checkout to a listening port. */\nclass RealPreview implements PreviewHandle {\n private child: ChildProcess | null = null;\n private stopped = false;\n private partial = '';\n\n constructor(\n private job: PreviewJob,\n private cb: PreviewCallbacks,\n ) {\n void this.run().catch((err) => {\n if (this.stopped || err instanceof Stopped) return;\n this.stopped = true;\n if (this.child) void killTree(this.child);\n this.cb.failed((err as Error).message);\n });\n }\n\n async stop() {\n this.stopped = true;\n if (this.child) await killTree(this.child);\n }\n\n private check() {\n if (this.stopped) throw new Stopped();\n }\n\n private async run() {\n const { job, cb } = this;\n cb.status('preparing');\n const wt = await workspace.prepareDesk(job.fullName, { defaultBranch: job.defaultBranch, pr: job.pr ?? undefined }, PREVIEW_SLUG, PREVIEW_BRANCH);\n this.check();\n await workspace.ensureLocalExcludes(job.fullName).catch(() => undefined);\n cb.commit(await git(['rev-parse', '--short', 'HEAD'], { cwd: wt }).catch(() => ''));\n const tmp = path.join(wt, PREVIEW_TMP);\n await fs.mkdir(tmp, { recursive: true });\n\n const pkg = await readJson(path.join(wt, 'package.json'));\n const command = job.command ?? defaultCommand(pkg);\n if (!command) {\n this.stopped = true;\n cb.failed(\n pkg\n ? 'package.json has no dev, start or preview script. Set a preview command for this floor.'\n : 'Nothing to run: this floor has no preview command and no package.json.',\n true,\n );\n return;\n }\n const env = previewEnv(job.env, job.port, tmp);\n\n if (pkg) {\n cb.status('installing');\n await this.install(wt, env);\n this.check();\n }\n\n cb.status('starting');\n const cmd = fillPlaceholders(command, job.port, tmp);\n cb.log([`$ ${cmd}`]);\n const exited = this.spawn(cmd, wt, env);\n const deadline = Date.now() + START_TIMEOUT_MS;\n let exitCode: number | null | undefined;\n void exited.then((code) => (exitCode = code));\n while (!(await portOpen(job.port))) {\n this.check();\n if (exitCode !== undefined) throw new Error(`The app exited (code ${exitCode}) before it listened on port ${job.port}.`);\n if (Date.now() > deadline) throw new Error(`The app did not listen on port ${job.port} within 3 minutes. Does the command use PORT or {port}?`);\n await sleep(700);\n }\n this.check();\n cb.status('running');\n const code = await exited;\n // Some launchers exit while the server they started keeps serving: it's only over once the port closes.\n while (!this.stopped && (await portOpen(job.port))) await sleep(3000);\n if (this.stopped) return;\n this.stopped = true;\n cb.failed(`The app stopped (exit code ${code}).`);\n }\n\n /** npm ci (or npm install without a lockfile), skipped when package.json and the lockfile haven't changed. */\n private async install(wt: string, env: Record<string, string>) {\n const lockFile = path.join(wt, 'package-lock.json');\n const lock = await fs.readFile(lockFile, 'utf8').catch(() => null);\n const hash = crypto\n .createHash('sha256')\n .update(await fs.readFile(path.join(wt, 'package.json'), 'utf8'))\n .update('\\0')\n .update(lock ?? '')\n .digest('hex');\n const marker = path.join(wt, 'node_modules', INSTALL_MARKER);\n if ((await fs.readFile(marker, 'utf8').catch(() => '')) === hash) {\n this.cb.log(['Dependencies unchanged since the last install; skipping it.']);\n return;\n }\n const cmd = lock !== null ? 'npm ci' : 'npm install';\n this.cb.log([`$ ${cmd}`]);\n const code = await Promise.race([this.spawn(cmd, wt, env), sleep(INSTALL_TIMEOUT_MS).then(() => 'timeout' as const)]);\n this.check();\n if (code === 'timeout') {\n if (this.child) await killTree(this.child);\n throw new Error(`${cmd} took longer than ${INSTALL_TIMEOUT_MS / 60_000} minutes.`);\n }\n if (code !== 0) throw new Error(`${cmd} failed (code ${code}).`);\n this.child = null;\n await fs.writeFile(marker, hash).catch(() => undefined);\n }\n\n /** Run a command line through the platform shell; resolves with its exit code. */\n private spawn(cmd: string, cwd: string, env: Record<string, string>): Promise<number | null> {\n this.check();\n const child = spawn(cmd, { cwd, env, shell: true, windowsHide: true, detached: process.platform !== 'win32', stdio: ['ignore', 'pipe', 'pipe'] });\n this.child = child;\n const onData = (buf: Buffer) => {\n const text = this.partial + buf.toString().replace(/\\x1b\\[[0-9;?]*[A-Za-z]/g, '');\n const lines = text.split(/\\r?\\n|\\r/);\n this.partial = lines.pop() ?? '';\n const out = lines.filter((l) => l.trim());\n if (out.length) this.cb.log(out);\n };\n child.stdout?.on('data', onData);\n child.stderr?.on('data', onData);\n return new Promise((resolve) => {\n child.once('error', (err) => {\n this.cb.log([err.message]);\n resolve(-1);\n });\n child.once('close', (code) => {\n if (this.partial.trim()) this.cb.log([this.partial]);\n this.partial = '';\n resolve(code);\n });\n });\n }\n}\n\nexport const realPreviews: PreviewBackend = {\n start: (job, cb) => new RealPreview(job, cb),\n hasDefault: async (fullName) =>\n fs\n .access(path.join(workspace.mainDir(fullName), 'package.json'))\n .then(() => true)\n .catch(() => false),\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { HOME_DIR } from './config.ts';\nimport { git } from './exec.ts';\nimport type { OfficeUpdateState } from '../shared/types.ts';\n\n// The office updating itself (#37). The server only decides when: it drains (starts nothing new, lets running\n// sessions finish) and then hands the update to the launcher (scripts/office.mjs), which pulls, installs, builds and\n// restarts it. Contract with the launcher:\n// server \u2192 launcher { type: 'office:update', from: '<full HEAD sha>' } once drained\n// launcher \u2192 server { type: 'office:shutdown', restart } run shutdown(), then exit 0\n// (restart: false when the office quits; agents' CLIs stop instead of waiting in the keeper)\n// <SWARM_HOME>/last-update.json = { from, to, ok, error?, installed, built, at }, read and deleted on startup\n\n/** Sessions still running this long after draining started are stopped, and the update goes ahead. */\nexport const DRAIN_TIMEOUT_MS = 20 * 60_000;\n/** Later: ask again after this long, or sooner when a newer commit lands. */\nexport const POSTPONE_MS = 2 * 60 * 60_000;\n\n/** Started by the launcher: an IPC channel and SWARM_LAUNCHER=1. Anything else (tsx, the demo, QA) only reports. */\nexport function underLauncher(proc: { send?: unknown; env: Record<string, string | undefined> } = process): boolean {\n return typeof proc.send === 'function' && proc.env.SWARM_LAUNCHER === '1';\n}\n\nexport interface DrainInput {\n now: number;\n behind: number; // commits the office's folder can fast-forward by (0: nothing to update)\n launcher: boolean;\n autoUpdate: boolean;\n requested: boolean; // the manager pressed Update now\n postponedUntil: number | null; // the manager pressed Later\n postponedBehind: number; // how far behind it was then: a newer commit ends the postponement\n failed: string | null; // the last update's error\n failedBehind: number | null; // how far behind it was after that failure: only a newer commit retries on its own\n drainingSince: number | null;\n sent: boolean; // handed to the launcher\n running: number; // sessions still running\n}\n\nexport interface DrainDecision {\n state: OfficeUpdateState;\n drainingSince: number | null;\n /** Hand the update to the launcher now: nothing is running, or the drain timed out (`timedOut`). */\n send: boolean;\n timedOut: boolean;\n}\n\n/**\n * Where the office's own update stands and what to do about it. Draining (start nothing new, let running sessions\n * finish) happens when there is an update, a launcher, and either autoUpdate is on or the manager pressed Update now.\n * Later holds an automatic update back for POSTPONE_MS or until a newer commit lands ('waiting'); a failed update is\n * only retried automatically for a newer commit.\n */\nexport function drainDecision(s: DrainInput): DrainDecision {\n const idle = (state: OfficeUpdateState): DrainDecision => ({ state, drainingSince: null, send: false, timedOut: false });\n if (s.sent) return { state: 'updating', drainingSince: s.drainingSince, send: false, timedOut: false };\n if (s.behind <= 0) return idle('none');\n if (!s.launcher) return idle(s.failed ? 'failed' : 'available');\n const postponed = s.postponedUntil !== null && s.now < s.postponedUntil && s.behind <= s.postponedBehind;\n const failedHold = s.failed !== null && s.behind <= (s.failedBehind ?? Infinity);\n const due = s.requested || (s.autoUpdate && !postponed && !failedHold);\n if (!due) return idle(s.failed ? 'failed' : s.autoUpdate && postponed ? 'waiting' : 'available');\n const since = s.drainingSince ?? s.now;\n const timedOut = s.running > 0 && s.now - since >= DRAIN_TIMEOUT_MS;\n return { state: 'draining', drainingSince: since, send: s.running === 0 || timedOut, timedOut };\n}\n\n/** What the launcher leaves behind after an update. */\nexport interface LastUpdate {\n from: string;\n to: string;\n ok: boolean;\n error?: string;\n installed: boolean;\n built: boolean;\n at: number;\n}\n\n/** Parse last-update.json; null when it isn't one. */\nexport function parseLastUpdate(raw: string): LastUpdate | null {\n try {\n const u = JSON.parse(raw) as Partial<LastUpdate>;\n if (!u || typeof u.from !== 'string' || typeof u.ok !== 'boolean') return null;\n return {\n from: u.from,\n to: typeof u.to === 'string' ? u.to : '',\n ok: u.ok,\n error: typeof u.error === 'string' ? u.error : undefined,\n installed: !!u.installed,\n built: !!u.built,\n at: Number(u.at) || Date.now(),\n };\n } catch {\n return null;\n }\n}\n\n/** Read and delete <home>/last-update.json, so its phone message is posted once. */\nexport async function takeLastUpdate(home: string): Promise<LastUpdate | null> {\n const file = path.join(home, 'last-update.json');\n const raw = await fs.readFile(file, 'utf8').catch(() => null);\n if (raw === null) return null;\n await fs.rm(file, { force: true, maxRetries: 3 }).catch(() => undefined);\n return parseLastUpdate(raw);\n}\n\n/** The phone message for an update: \"Updated the office from abc1234 to def5678 (3 commits)\" or why it failed. */\nexport function lastUpdateMessage(u: LastUpdate, commits: number | null): string {\n if (!u.ok) return `\u26A0\uFE0F Update failed and was rolled back: ${u.error || 'unknown error'}`;\n const n = commits === null ? '' : ` (${commits} commit${commits === 1 ? '' : 's'})`;\n return `\u2B06\uFE0F Updated the office from ${u.from.slice(0, 7)} to ${u.to.slice(0, 7)}${n}`;\n}\n\n// ---------- the running office ----------\n\n/** The running office's own checkout and its launcher. The demo fakes it. */\nexport interface OfficeHost {\n launcher: boolean;\n /** Full sha of the commit the office runs, or null when it doesn't run from a git checkout (e.g. installed from npm). */\n head(): Promise<string | null>;\n /** Is this floor checkout the office's own folder? Syncing it would restart the office mid-work, so it's only reported. */\n isOwnFolder(dir: string): boolean;\n /** Commits between two shas of the office's folder, or null when git can't tell. */\n commitsBetween(from: string, to: string): Promise<number | null>;\n /** Read and delete the result the launcher left from the last update. */\n takeLastUpdate(): Promise<LastUpdate | null>;\n /** Hand the drained office to the launcher, which restarts it (resolves null). The demo resolves with a fake result. */\n update(from: string): Promise<LastUpdate | null>;\n}\n\nconst OFFICE_DIR = path.resolve(import.meta.dirname, '..');\nconst isSamePath = (a: string, b: string) => (process.platform === 'win32' ? path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase() : path.resolve(a) === path.resolve(b));\n\nexport const realOffice: OfficeHost = {\n launcher: underLauncher(),\n head: () => git(['rev-parse', 'HEAD'], { cwd: OFFICE_DIR }).catch(() => null),\n isOwnFolder: (dir) => isSamePath(dir, OFFICE_DIR),\n commitsBetween: (from, to) =>\n git(['rev-list', '--count', `${from}..${to}`], { cwd: OFFICE_DIR })\n .then(Number)\n .catch(() => null),\n takeLastUpdate: () => takeLastUpdate(HOME_DIR),\n async update(from) {\n if (!underLauncher()) throw new Error('The office was not started by the launcher');\n await new Promise<void>((resolve, reject) => process.send!({ type: 'office:update', from }, undefined, {}, (err) => (err ? reject(err) : resolve())));\n return null;\n },\n};\n", "import * as github from './github.ts';\nimport * as workspace from './workspace.ts';\nimport { startSession, type SessionCallbacks, type SessionHandle, type SessionOptions } from './agentRunner.ts';\nimport { hooksReady, officeProcesses, reconnectClis, releaseClis, startCliSession, terminalsAvailable, type ReconnectedCli } from './cliRunner.ts';\nimport { detectClis } from './clis.ts';\nimport { realPreviews, type PreviewBackend } from './previewRunner.ts';\nimport { realOffice, type OfficeHost } from './officeUpdate.ts';\nimport type { AgentTerminal } from './terminal.ts';\nimport type { CliView, GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\n\n/** Everything the swarm needs from the outside world. The demo backend fakes all of it. */\nexport interface Backend {\n demo: boolean;\n user(): Promise<string>;\n listMyRepos(owner?: string): Promise<GhRepoSummary[]>;\n repoMeta(fullName: string): Promise<github.RepoMeta>;\n listIssues(fullName: string): Promise<IssueInfo[]>;\n listPulls(fullName: string): Promise<PullInfo[]>;\n createIssue(fullName: string, title: string, body: string, labels?: string[]): Promise<number>;\n /** OPEN or CLOSED; null when there is no such issue. */\n issueState(fullName: string, number: number): Promise<'OPEN' | 'CLOSED' | null>;\n editIssue(fullName: string, number: number, edit: { body?: string; addLabels?: string[]; removeLabels?: string[] }): Promise<void>;\n /** Close an issue as completed, with a comment. */\n closeIssue(fullName: string, number: number, comment: string): Promise<void>;\n mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void>;\n updateBranch(fullName: string, number: number): Promise<void>;\n closePull(fullName: string, number: number): Promise<void>;\n prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null>;\n prDetails(fullName: string, number: number): Promise<github.PrDetails>;\n issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }>;\n commentPull(fullName: string, number: number, body: string): Promise<string>;\n uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string>;\n ensureClone(fullName: string): Promise<void>;\n /** Fast-forward the floor's main checkout to GitHub when that is safe; returns how it stands. */\n syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<workspace.MainSync | null>;\n /** Point a floor at the user's own project folder (null: a clone the office manages). */\n setLocalPath(fullName: string, dir: string | null): void;\n scanProjects(root: string): Promise<workspace.LocalFolder[]>;\n inspectFolder(dir: string): Promise<workspace.LocalFolder>;\n publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string>;\n createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<{ fullName: string; path: string }>;\n mainDir(fullName: string): string;\n deskDir(fullName: string, agentSlug: string): string;\n prepareDesk(fullName: string, base: workspace.DeskBase, agentSlug: string, branch: string): Promise<string>;\n /** `main`: the floor's checkout as it was when the desk was let go (default: mainDir now). */\n removeDesk(fullName: string, agentSlug: string, main?: string): Promise<void>;\n /** Remove desks, stray desk folders and finished swarm/qa branches nothing in `keep` uses. */\n sweepDesks(fullName: string, keep: workspace.SweepKeep): Promise<workspace.SweepResult>;\n /** Stop processes an agent left running (dev servers on its port, anything started in its desk). */\n releaseDesk(fullName: string, agentSlug: string, port: number): Promise<void>;\n /** An agent session: the real CLI in the agent's terminal when opts.terminal is set, else an Agent SDK session. */\n startSession(opts: SessionOptions, cb: SessionCallbacks): SessionHandle;\n /** Terminals can run here (the native pseudo-terminal module loaded). */\n terminals: boolean;\n /** The office started: the CLIs its terminal keeper kept running through a restart, back in their agents' terminals. */\n reconnectClis(terminalFor: (agentId: string) => AgentTerminal | null): Promise<ReconnectedCli[]>;\n /** The office follows those CLIs' sessions again: hooks that waited for it can come in. */\n hooksReady(): void;\n /** The office is stopping: its CLIs carry on in the keeper through a restart (true), or stop with it. */\n releaseClis(restart: boolean): Promise<void>;\n /** The coding-agent CLIs installed on this machine. */\n detectClis(): Promise<CliView[]>;\n /** Run a floor's app for the preview monitor (its own worktree, its own port). */\n previews: PreviewBackend;\n /** The running office's own folder and its launcher, for the office's self-update. */\n office: OfficeHost;\n}\n\nexport const realBackend: Backend = {\n demo: false,\n user: github.currentUser,\n listMyRepos: github.listMyRepos,\n repoMeta: github.repoMeta,\n listIssues: github.listIssues,\n listPulls: github.listPulls,\n createIssue: github.createIssue,\n issueState: github.issueState,\n editIssue: github.editIssue,\n closeIssue: github.closeIssue,\n mergePull: github.mergePull,\n updateBranch: github.updateBranch,\n closePull: github.closePull,\n prForBranch: github.prForBranch,\n prDetails: github.prDetails,\n issueDetails: github.issueDetails,\n commentPull: github.commentPull,\n uploadEvidence: github.uploadEvidence,\n ensureClone: workspace.ensureClone,\n syncMain: workspace.syncMain,\n setLocalPath: workspace.setLocalPath,\n scanProjects: workspace.scanProjects,\n inspectFolder: workspace.inspectFolder,\n publishFolder: workspace.publishFolder,\n createProject: workspace.createProject,\n mainDir: workspace.mainDir,\n deskDir: workspace.deskDir,\n prepareDesk: workspace.prepareDesk,\n removeDesk: workspace.removeDesk,\n sweepDesks: workspace.sweepDesks,\n releaseDesk: (fullName, agentSlug, port) => workspace.releaseDesk(fullName, agentSlug, port, officeProcesses()),\n startSession: (opts, cb) => (opts.terminal ? startCliSession(opts, cb) : startSession(opts, cb)),\n terminals: terminalsAvailable,\n reconnectClis: (terminalFor) => (terminalsAvailable ? reconnectClis(terminalFor) : Promise.resolve([])),\n hooksReady,\n releaseClis,\n detectClis,\n previews: realPreviews,\n office: realOffice,\n};\n", "import crypto from 'node:crypto';\nimport http from 'node:http';\nimport path from 'node:path';\nimport type { Backend } from './backend.ts';\nimport type { PreviewBackend } from './previewRunner.ts';\nimport { describeOfficeTool, type LogEntry, type SessionCallbacks, type SessionHandle, type SessionOptions } from './agentRunner.ts';\nimport { CLIS } from './clis.ts';\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\nimport type { LocalFolder } from './workspace.ts';\nimport { HOME_DIR } from './config.ts';\nimport { takeLastUpdate, underLauncher, type OfficeHost } from './officeUpdate.ts';\n\n// `npm run demo`: a fake GitHub and fake Claude Code sessions, so the office (including the\n// dev \u2192 QA \u2192 fix loop) can be explored without spending any usage or touching real repos.\n\ninterface FakeRepo {\n fullName: string;\n description: string;\n issues: IssueInfo[];\n pulls: PullInfo[];\n nextNumber: number;\n}\n\nconst now = () => new Date().toISOString();\n\nfunction issue(n: number, title: string, body: string, fullName: string, labels: string[] = []): IssueInfo {\n return { number: n, title, body, url: `https://github.com/${fullName}/issues/${n}`, labels, createdAt: now() };\n}\n\nconst repos = new Map<string, FakeRepo>();\n/** Repos made in the demo (new projects, published folders): empty, so no package.json for the preview to fall back on. */\nconst bareRepos = new Set<string>();\nconst mergedSinceSync = new Map<string, number>(); // merges the fake project folder hasn't pulled yet\nconst closedIssues = new Set<string>(); // `${fullName}#${n}`: issues closed by a merge\n\nconst fakeSha = () => crypto.randomBytes(20).toString('hex');\n\n/** Fake CI: checks run for a while after every push, and now and then one fails so the fix loop shows. */\nfunction runChecks(pr: PullInfo, fail = Math.random() < 0.2) {\n Object.assign(pr, { checks: 'pending', pendingChecks: ['CI / build', 'Vercel'], failedChecks: [] });\n setTimeout(() => {\n Object.assign(pr, {\n checks: fail ? 'failing' : 'passing',\n pendingChecks: [],\n failedChecks: fail ? [{ name: 'CI / build', url: `${pr.url}/checks` }] : [],\n });\n }, 12_000 + Math.random() * 10_000);\n}\n\nfunction seed(fullName: string, description: string, titles: [string, string][]) {\n const r: FakeRepo = { fullName, description, issues: [], pulls: [], nextNumber: 1 };\n for (const [title, body] of titles) r.issues.push(issue(r.nextNumber++, title, body, fullName));\n repos.set(fullName, r);\n}\n\nseed('demo-co/pixel-todo', 'A cheerful todo app', [\n ['Add dark mode toggle', 'Users want a dark theme. Persist the choice in localStorage.'],\n ['Todos should support due dates', 'Add an optional due date and highlight overdue items.'],\n ['Drag and drop to reorder', 'Let users reorder todos by dragging.'],\n ['Empty state illustration', 'Show a friendly illustration when the list is empty.'],\n ['Keyboard shortcuts', 'N for new todo, / to search, ? for help.'],\n ['Fix: completed count off by one', 'The footer shows one more completed item than there is.'],\n]);\nseed('demo-co/weather-api', 'Tiny weather REST API', [\n ['Add /forecast endpoint', 'Return a 5-day forecast for a city.'],\n ['Rate limit anonymous callers', '60 requests per minute per IP.'],\n ['OpenAPI spec', 'Publish an OpenAPI 3.1 document at /openapi.json.'],\n]);\n\nfunction screenshotSvg(title: string, url: string, hue: number) {\n const safe = (s: string) => s.replace(/[<>&\"]/g, '');\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"640\" height=\"400\" viewBox=\"0 0 640 400\">\n <rect width=\"640\" height=\"400\" fill=\"hsl(${hue},60%,97%)\"/>\n <rect width=\"640\" height=\"56\" fill=\"hsl(${hue},70%,55%)\"/>\n <text x=\"24\" y=\"37\" font-family=\"Segoe UI, Arial\" font-size=\"22\" font-weight=\"700\" fill=\"#fff\">${safe(title)}</text>\n <text x=\"620\" y=\"36\" text-anchor=\"end\" font-family=\"Segoe UI, Arial\" font-size=\"13\" fill=\"#fff\">${safe(url)}</text>\n ${[0, 1, 2, 3]\n .map(\n (i) => `<rect x=\"24\" y=\"${84 + i * 70}\" width=\"592\" height=\"56\" rx=\"10\" fill=\"#fff\" stroke=\"hsl(${hue},40%,85%)\"/>\n <circle cx=\"54\" cy=\"${112 + i * 70}\" r=\"11\" fill=\"none\" stroke=\"hsl(${hue},60%,55%)\" stroke-width=\"3\"/>\n <rect x=\"80\" y=\"${104 + i * 70}\" width=\"${180 + ((i * 97) % 220)}\" height=\"14\" rx=\"7\" fill=\"hsl(${hue},25%,80%)\"/>`,\n )\n .join('\\n')}\n</svg>`;\n}\n\ntype Step = LogEntry[] | (() => void);\n\nfunction devScript(opts: SessionOptions, cb: SessionCallbacks, issueNumber: number, issueTitle: string): Step[] {\n const branch = path.basename(opts.cwd);\n const hue = (issueNumber * 67) % 360;\n const file = ['src/App.tsx', 'src/components/TodoList.tsx', 'src/api/routes.ts', 'src/styles.css'][issueNumber % 4];\n const port = 5200 + (issueNumber % 50);\n return [\n [{ kind: 'text', text: `\u25CF I'll start by getting familiar with the codebase for \"${issueTitle}\".` }],\n [{ kind: 'tool', tool: 'Glob', text: '\u23FA Glob src/**/*.{ts,tsx}' }, { kind: 'result', text: ' \u23BF Found 23 files' }],\n [{ kind: 'tool', tool: 'Read', text: `\u23FA Read ${file}` }, { kind: 'result', text: ' \u23BF Read 184 lines' }],\n [{ kind: 'thinking', text: '\u273B Thinking\u2026' }],\n [\n { kind: 'tool', tool: 'TodoWrite', text: '\u23FA Update todo list' },\n { kind: 'result', text: ' \u25D0 Understand current behaviour' },\n { kind: 'result', text: ' \u2610 Implement the change' },\n { kind: 'result', text: ' \u2610 Add tests' },\n { kind: 'result', text: ' \u2610 Verify in the browser' },\n ],\n [{ kind: 'tool', tool: 'Grep', text: '\u23FA Grep \"useTodos\"' }, { kind: 'result', text: ' \u23BF Found 6 matches in 4 files' }],\n [{ kind: 'text', text: \"\u25CF The state lives in a single hook. I'll extend it and keep the API backwards compatible.\" }],\n [{ kind: 'tool', tool: 'Edit', text: `\u23FA Edit ${file}` }, { kind: 'result', text: ' \u23BF Updated' }],\n [{ kind: 'tool', tool: 'Write', text: '\u23FA Write src/__tests__/feature.test.ts' }, { kind: 'result', text: ' \u23BF Saved' }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm test -- --run' }],\n [\n { kind: 'result', text: ' \u23BF \u2713 src/__tests__/feature.test.ts (4 tests) 38ms' },\n { kind: 'result', text: ' Test Files 7 passed (7)' },\n ],\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ npm run dev -- --port ${port} &` }, { kind: 'result', text: ' \u23BF VITE ready in 412 ms' }],\n () => cb.browserUrl(`http://localhost:${port}/`),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_navigate', text: `\u23FA \uD83C\uDF10 navigate http://localhost:${port}/` }, { kind: 'result', text: ` \u23BF Page URL: http://localhost:${port}/` }],\n () => cb.screenshot(Buffer.from(screenshotSvg(issueTitle, `localhost:${port}`, hue)), 'image/svg+xml'),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_take_screenshot', text: '\u23FA \uD83C\uDF10 take_screenshot' }, { kind: 'result', text: ' \u23BF Took a screenshot of the current page' }],\n [{ kind: 'text', text: '\u25CF Looks right in the browser. Committing and opening a PR.' }],\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ git commit -am \"feat: ${issueTitle.toLowerCase()}\"` }, { kind: 'result', text: ` \u23BF [${branch} 3f2a91c] feat: ${issueTitle.toLowerCase()}` }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git push -u origin HEAD' }, { kind: 'result', text: ' \u23BF branch set up to track origin' }],\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ gh pr create --title \"${issueTitle}\" --body \"Closes #${issueNumber}\"` }],\n ];\n}\n\nfunction qaScript(cb: SessionCallbacks, pr: number, title: string, round: number): Step[] {\n const port = 5600 + (pr % 50);\n const hue = (pr * 41) % 360;\n return [\n [{ kind: 'text', text: `\u25CF Testing PR #${pr} \"${title}\" (round ${round}). First, the acceptance criteria from the issue.` }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git diff origin/main...HEAD --stat' }, { kind: 'result', text: ' \u23BF 3 files changed, 82 insertions(+), 9 deletions(-)' }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm ci && npm test -- --run' }],\n [\n { kind: 'result', text: ' \u23BF Test Files 8 passed (8)' },\n { kind: 'result', text: ' Tests 41 passed (41)' },\n ],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm run lint && npm run build' }, { kind: 'result', text: ' \u23BF \u2713 built in 1.84s' }],\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ npm run preview -- --port ${port} &` }, { kind: 'result', text: ` \u23BF Local: http://localhost:${port}/` }],\n () => cb.browserUrl(`http://localhost:${port}/`),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_navigate', text: `\u23FA \uD83C\uDF10 navigate http://localhost:${port}/` }, { kind: 'result', text: ` \u23BF Page URL: http://localhost:${port}/` }],\n () => cb.screenshot(Buffer.from(screenshotSvg(`QA \u00B7 ${title}`, `localhost:${port}`, hue)), 'image/svg+xml'),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_take_screenshot', text: '\u23FA \uD83C\uDF10 take_screenshot' }, { kind: 'result', text: ' \u23BF Took a screenshot of the current page' }],\n [{ kind: 'tool', tool: 'mcp__playwright__browser_click', text: '\u23FA \uD83C\uDF10 click \"Add todo\" button' }, { kind: 'result', text: ' \u23BF Clicked' }],\n [{ kind: 'tool', tool: 'mcp__playwright__browser_resize', text: '\u23FA \uD83C\uDF10 resize 375x740' }, { kind: 'result', text: ' \u23BF Resized' }],\n () => cb.screenshot(Buffer.from(screenshotSvg(`QA \u00B7 mobile \u00B7 ${title}`, `localhost:${port}`, (hue + 40) % 360)), 'image/svg+xml'),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_take_screenshot', text: '\u23FA \uD83C\uDF10 take_screenshot' }, { kind: 'result', text: ' \u23BF Took a screenshot of the current page' }],\n [{ kind: 'tool', tool: 'mcp__playwright__browser_console_messages', text: '\u23FA \uD83C\uDF10 console_messages' }, { kind: 'result', text: ' \u23BF No errors' }],\n ];\n}\n\nfunction fixScript(pr: number, pushes: boolean): Step[] {\n return [\n [{ kind: 'text', text: `\u25CF Reading the QA report for PR #${pr}. The toolbar overflows on phones; I'll let it wrap.` }],\n [{ kind: 'tool', tool: 'Read', text: '\u23FA Read src/styles.css' }, { kind: 'result', text: ' \u23BF Read 212 lines' }],\n [{ kind: 'tool', tool: 'Edit', text: '\u23FA Edit src/styles.css' }, { kind: 'result', text: ' \u23BF Updated' }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm test -- --run' }, { kind: 'result', text: ' \u23BF Test Files 8 passed (8)' }],\n pushes\n ? [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git commit -am \"fix: wrap toolbar on narrow screens\" && git push origin HEAD' }, { kind: 'result', text: ' \u23BF pushed' }]\n : [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git status --short' }, { kind: 'result', text: ' \u23BF M src/styles.css' }],\n ];\n}\n\nfunction fakeSession(opts: SessionOptions, cb: SessionCallbacks, fullName: string): SessionHandle {\n const timers: NodeJS.Timeout[] = [];\n let stopped = false;\n const kind = opts.role === 'qa' ? 'qa' : /FAILED|taking over pull request|git push origin HEAD:/.test(opts.prompt) ? 'fix' : 'issue';\n const prMatch = opts.prompt.match(/pull request #(\\d+)(?::\\s*(.+))?/);\n const issueMatch = opts.prompt.match(/#(\\d+):\\s*(.+)/);\n const number = Number((kind === 'issue' ? issueMatch?.[1] : prMatch?.[1]) ?? 0);\n const title = (kind === 'issue' ? issueMatch?.[2] : prMatch?.[2])?.trim() ?? 'follow-up';\n const round = Number(opts.prompt.match(/QA round (\\d+)/)?.[1] ?? 1);\n // Now and then a QA fix ends without pushing, so the office's \"no new commits\" check can be seen.\n const pushes = kind !== 'fix' || !/FAILED|taking over pull request/.test(opts.prompt) || Math.random() > 0.25;\n\n const header: Step = [\n { kind: 'system', text: `\u273B Claude Code (demo) \u00B7 ${opts.model} \u00B7 ${opts.effort} effort` },\n { kind: 'system', text: ` cwd ${opts.cwd}` },\n ];\n const body = kind === 'qa' ? qaScript(cb, number, title, round) : kind === 'fix' ? fixScript(number, pushes) : devScript(opts, cb, number, title);\n const script = [header, ...body];\n\n const finish = () => {\n const costUsd = 0.3 + Math.random();\n const turns = 15 + Math.floor(Math.random() * 20);\n cb.tool(null);\n if (kind === 'qa') {\n // Most first rounds pass; some fail so the fix loop can be seen in action.\n const pass = round > 1 || Math.random() > 0.35;\n cb.log([{ kind: 'text', text: pass ? '\u25CF Everything checks out. Writing up the report.' : '\u25CF The toolbar overflows on a 375px screen. Failing this round.' }]);\n cb.finished({\n ok: true,\n text: '',\n costUsd,\n turns,\n errors: [],\n structured: {\n verdict: pass ? 'pass' : 'fail',\n summary: pass\n ? 'The change does what the issue asks: the feature works on desktop and mobile, all 41 tests pass, and lint and build are clean.'\n : 'The feature works on desktop, but on a 375px-wide screen the toolbar overflows and the new button is cut off.',\n checks: [\n { name: 'Unit tests', result: 'pass', details: '41 passed, 0 failed' },\n { name: 'Lint + build', result: 'pass', details: 'No lint errors; production build succeeds' },\n { name: 'Feature works on desktop', result: 'pass', details: 'Clicked through the new flow at 1280x800' },\n { name: 'Mobile layout (375px)', result: pass ? 'pass' : 'fail', details: pass ? 'Layout wraps correctly' : 'Toolbar overflows horizontally; button unreachable' },\n { name: 'Console errors', result: 'pass', details: 'None' },\n ],\n commands: [\n { command: 'npm test -- --run', result: '41 passed' },\n { command: 'npm run lint && npm run build', result: 'clean, built in 1.84s' },\n ],\n screenshots: ['Desktop view after the change', 'Mobile view at 375px'],\n fixInstructions: pass ? undefined : 'Make the toolbar wrap (flex-wrap: wrap) below 480px so every button stays visible.',\n },\n });\n return;\n }\n if (kind === 'fix') {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (pr && pushes) {\n pr.headSha = fakeSha();\n pr.mergeState = 'CLEAN';\n pr.mergeable = 'MERGEABLE';\n runChecks(pr, false);\n }\n cb.log([{ kind: 'text', text: pushes ? `\u25CF Fixed PR #${number} and pushed. Ready for another QA round.` : `\u25CF The toolbar wraps on narrow screens now. Ready for another QA round.` }]);\n cb.finished({ ok: true, text: '', costUsd, turns, errors: [] });\n return;\n }\n const repo = repos.get(fullName);\n let url = '';\n if (repo && number) {\n const n = repo.nextNumber++;\n url = `https://github.com/${fullName}/pull/${n}`;\n repo.pulls.unshift({\n number: n,\n title,\n url,\n headRefName: `swarm/issue-${number}-${path.basename(opts.cwd).replace(/-[0-9a-f]{4}$/, '')}`,\n state: 'OPEN',\n isDraft: false,\n mergeable: 'MERGEABLE',\n reviewDecision: null,\n closesIssues: [number],\n createdAt: now(),\n mergedAt: null,\n additions: 40 + ((number * 13) % 200),\n deletions: (number * 7) % 40,\n checks: 'pending',\n headSha: fakeSha(),\n mergeState: 'CLEAN',\n failedChecks: [],\n pendingChecks: [],\n });\n runChecks(repo.pulls[0]);\n cb.log([{ kind: 'result', text: ` \u23BF ${url}` }]);\n }\n cb.log([{ kind: 'text', text: `\u25CF Opened ${url || 'the pull request'}. It closes #${number} and includes tests.` }]);\n cb.finished({ ok: true, text: url, costUsd, turns, errors: [] });\n };\n\n let i = 0;\n const step = () => {\n if (stopped) return;\n if (i >= script.length) return finish();\n const s = script[i++];\n if (typeof s === 'function') s();\n else {\n const tool = s.find((e) => e.kind === 'tool');\n cb.tool(tool?.tool ?? null);\n cb.log(s);\n }\n timers.push(setTimeout(step, 1600 + Math.random() * 3800));\n };\n timers.push(setTimeout(step, 600));\n\n return {\n send(text) {\n timers.push(\n setTimeout(() => {\n if (stopped) return;\n cb.log([{ kind: 'text', text: `\u25CF Got it \u2014 \"${text.slice(0, 60)}\". Adjusting my approach.` }]);\n }, 1500),\n );\n },\n stop() {\n stopped = true;\n timers.forEach(clearTimeout);\n cb.finished({ ok: false, text: '', costUsd: 0.1, turns: i, errors: ['Stopped by manager'] });\n },\n };\n}\n\n// ---------- the terminal runtime ----------\n\nconst ANSI: Record<LogEntry['kind'], (text: string) => string> = {\n text: (t) => t.replace(/^\u25CF /, '\\x1b[97m\u25CF\\x1b[0m '),\n tool: (t) => `\\x1b[32m\u25CF\\x1b[0m \\x1b[1m${t.replace(/^\u23FA /, '')}\\x1b[0m`,\n result: (t) => `\\x1b[2m${t}\\x1b[0m`,\n thinking: (t) => `\\x1b[35m${t}\\x1b[0m`,\n error: (t) => `\\x1b[31m${t}\\x1b[0m`,\n system: (t) => `\\x1b[2m${t}\\x1b[0m`,\n manager: (t) => `\\x1b[36m${t.replace(/^\u25B6 /, '\u276F ')}\\x1b[0m`,\n done: (t) => `\\x1b[32m${t}\\x1b[0m`,\n};\n\n/**\n * With a terminal (the terminal runtime), the fake session's lines are drawn there the way Claude Code draws them,\n * and what the manager types into it is taken as a message.\n */\nfunction inTerminal(opts: SessionOptions, cb: SessionCallbacks, start: (cb: SessionCallbacks) => SessionHandle): SessionHandle {\n const term = opts.terminal;\n if (!term) return start(cb);\n const name = CLIS.find((c) => c.id === (opts.cli ?? 'claude'))?.label ?? 'Claude Code';\n term.note(`\u2500\u2500 ${name}${opts.label ? ` \u00B7 ${opts.label}` : ''} \u2500\u2500`);\n term.write(\n [\n '',\n ` \\x1b[38;5;209m\u2590\u259B\u2588\u2588\u2588\u259C\u258C\\x1b[0m \\x1b[1m${name}\\x1b[0m (demo)`,\n `\\x1b[38;5;209m\u259D\u259C\u2588\u2588\u2588\u2588\u2588\u259B\u2598\\x1b[0m ${opts.model || 'default model'} \u00B7 ${opts.effort} effort`,\n `\\x1b[38;5;209m \u2598\u2598 \u259D\u259D\\x1b[0m \\x1b[2m${opts.cwd}\\x1b[0m`,\n '',\n `\\x1b[36m\u276F\\x1b[0m ${opts.prompt.split('\\n')[0].slice(0, 200)}`,\n '',\n ].join('\\r\\n'),\n );\n let handle: SessionHandle | null = null;\n let line = '';\n term.bind({\n write: (data) => {\n for (const ch of data.replace(/\\x1b\\[[0-9;?]*[A-Za-z~]|\\x1b./g, '')) {\n if (ch === '\\r') {\n const text = line.trim();\n line = '';\n term.write('\\r\\n');\n if (text && handle) {\n cb.log([{ kind: 'manager', text: `\u25B6 Typed in the terminal: ${text}` }]);\n handle.send(text);\n }\n } else if (ch === '\\x7f' || ch === '\\b') {\n if (line) term.write('\\b \\b');\n line = line.slice(0, -1);\n } else if (ch >= ' ') {\n line += ch;\n term.write(ch);\n }\n }\n },\n resize: () => undefined,\n });\n handle = start({\n ...cb,\n log: (entries) => {\n cb.log(entries);\n for (const e of entries) term.write(`${e.kind === 'tool' || (e.kind === 'text' && e.text.startsWith('\u25CF')) ? '\\r\\n' : ''}${ANSI[e.kind](e.text)}\\r\\n`);\n },\n finished: (r) => {\n term.bind(null);\n term.note(`\u2500\u2500 ${name} session ended \u2500\u2500`);\n cb.finished(r);\n },\n });\n return handle;\n}\n\n// Claude's usage warning, faked once so the office can be seen pacing new work: the 4th session gets it, and the\n// window \"resets\" 5 minutes later.\nconst USAGE_WARNING_AT = 4;\nconst USAGE_WARNING_MS = 5 * 60_000;\nlet sessionsStarted = 0;\n\nfunction fakeUsageWarning(cb: SessionCallbacks) {\n setTimeout(() => {\n const resetsAt = Date.now() + USAGE_WARNING_MS;\n cb.log([{ kind: 'error', text: `\u26A0 Subscription usage warning (five_hour) \u00B7 resets ${new Date(resetsAt).toLocaleTimeString()} (demo)` }]);\n cb.usageWarning?.({ resetsAt, rateLimitType: 'five_hour', utilization: 0.82 });\n }, 3000);\n}\n\nexport function createDemoBackend(): Backend {\n // Tie each fake session back to its repo via the desk directory name.\n const deskRepo = new Map<string, string>();\n // A pretend projects folder: the demo repos, one git folder that isn't on GitHub yet, and one plain folder.\n const folders = new Map<string, LocalFolder>();\n const addFolder = (name: string, github: string | null, git = true) =>\n folders.set(name, { name, path: `/demo/projects/${name}`, git, github, modified: Date.now() - folders.size * 3_600_000 });\n for (const r of repos.values()) addFolder(r.fullName.split('/')[1], r.fullName);\n addFolder('sketchbook', null);\n addFolder('recipe-notes', null, false);\n const newRepo = (name: string, description = '') => {\n const fullName = `demo-co/${name}`;\n if (!repos.has(fullName)) {\n repos.set(fullName, { fullName, description, issues: [], pulls: [], nextNumber: 1 });\n bareRepos.add(fullName);\n }\n addFolder(name, fullName);\n return fullName;\n };\n const folderOf = (dir: string) => {\n const f = folders.get(dir.replace(/\\\\/g, '/').split('/').pop() ?? '');\n if (!f) throw new Error(`${dir} is not a folder`);\n return f;\n };\n return {\n demo: true,\n user: async () => 'demo-manager',\n listMyRepos: async (): Promise<GhRepoSummary[]> =>\n [...repos.values()].map((r) => ({ nameWithOwner: r.fullName, description: r.description, visibility: 'PUBLIC', updatedAt: now() })),\n repoMeta: async (fullName) => {\n const r = repos.get(fullName);\n if (!r) throw new Error(`Unknown demo repo ${fullName}`);\n return { nameWithOwner: fullName, description: r.description, url: `https://github.com/${fullName}`, defaultBranch: 'main' };\n },\n setLocalPath: () => undefined,\n scanProjects: async () => [...folders.values()].sort((a, b) => b.modified - a.modified),\n inspectFolder: async (dir) => folderOf(dir),\n publishFolder: async (dir, opts) => {\n const f = folderOf(dir);\n return f.github ?? newRepo(f.name, opts.description);\n },\n createProject: async (_root, name, opts) => {\n if (folders.has(name)) throw new Error(`/demo/projects/${name} already exists. Pick another name, or connect that folder instead.`);\n return { fullName: newRepo(name, opts.description), path: `/demo/projects/${name}` };\n },\n listIssues: async (fullName) => [...(repos.get(fullName)?.issues ?? [])],\n listPulls: async (fullName) => [...(repos.get(fullName)?.pulls ?? [])],\n createIssue: async (fullName, title, body, labels = []) => {\n const r = repos.get(fullName);\n if (!r) throw new Error('Unknown repo');\n const n = r.nextNumber++;\n r.issues.push(issue(n, title, body, fullName, labels));\n return n;\n },\n issueState: async (fullName, number) => {\n const r = repos.get(fullName);\n return r?.issues.some((i) => i.number === number) ? 'OPEN' : closedIssues.has(`${fullName}#${number}`) ? 'CLOSED' : null;\n },\n editIssue: async (fullName, number, edit) => {\n const i = repos.get(fullName)?.issues.find((x) => x.number === number);\n if (!i) throw new Error(`Unknown issue #${number}`);\n if (edit.body !== undefined) i.body = edit.body;\n i.labels = [...i.labels.filter((l) => !edit.removeLabels?.includes(l)), ...(edit.addLabels ?? []).filter((l) => !i.labels.includes(l))];\n },\n mergePull: async (fullName, number, _method, headSha) => {\n const r = repos.get(fullName);\n const pr = r?.pulls.find((p) => p.number === number);\n if (!r || !pr) throw new Error('Unknown PR');\n if (headSha && pr.headSha !== headSha) throw new Error('Head branch was modified. Review and try the merge again.');\n mergedSinceSync.set(fullName, (mergedSinceSync.get(fullName) ?? 0) + 1);\n pr.state = 'MERGED';\n pr.mergedAt = now();\n // GitHub closes what \"Closes #N\" links a little after the merge, not straight away.\n setTimeout(() => {\n for (const n of pr.closesIssues) closedIssues.add(`${fullName}#${n}`);\n r.issues = r.issues.filter((i) => !pr.closesIssues.includes(i.number));\n }, 20_000).unref();\n },\n closeIssue: async (fullName, number) => {\n const r = repos.get(fullName);\n if (!r?.issues.some((i) => i.number === number)) throw new Error(`Issue #${number} is not open`);\n closedIssues.add(`${fullName}#${number}`);\n r.issues = r.issues.filter((i) => i.number !== number);\n },\n updateBranch: async (fullName, number) => {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (!pr) throw new Error('Unknown PR');\n Object.assign(pr, { headSha: fakeSha(), mergeState: 'CLEAN' });\n runChecks(pr, false);\n },\n closePull: async (fullName, number) => {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (pr) pr.state = 'CLOSED';\n },\n prForBranch: async () => null,\n prDetails: async (fullName, number) => {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (!pr) throw new Error(`Unknown PR #${number}`);\n return {\n number,\n title: pr.title,\n body: `Implements the change.\\n\\nCloses #${pr.closesIssues[0] ?? '?'}`,\n url: pr.url,\n headRefName: pr.headRefName,\n headSha: pr.headSha,\n isCrossRepository: false,\n closesIssues: pr.closesIssues,\n state: pr.state,\n mergeable: pr.mergeable,\n mergeState: pr.mergeState,\n };\n },\n issueDetails: async (fullName, number) => {\n const i = repos.get(fullName)?.issues.find((x) => x.number === number);\n return { title: i?.title ?? `Issue #${number}`, body: i?.body ?? '' };\n },\n commentPull: async (fullName, number) => `https://github.com/${fullName}/pull/${number}#issuecomment-${Date.now()}`,\n uploadEvidence: async (fullName, filePath) => `https://github.com/${fullName}/raw/swarm-qa-evidence/${filePath}`,\n ensureClone: async () => new Promise((r) => setTimeout(r, 400)),\n syncMain: async (fullName, _branch, { touch }) => {\n const behind = mergedSinceSync.get(fullName) ?? 0;\n if (behind === 0) return { status: 'in sync', behind: 0, updatable: false };\n if (!touch) return { status: `update ready (${behind} commit${behind === 1 ? '' : 's'})`, behind, updatable: true };\n mergedSinceSync.set(fullName, 0);\n return { status: `updated to ${fakeSha().slice(0, 7)}`, behind: 0, updatable: false };\n },\n mainDir: (fullName) => `/demo/${fullName}/main`,\n deskDir: (fullName, slug) => `/demo/${fullName}/desks/${slug}`,\n prepareDesk: async (fullName, _base, slug) => {\n await new Promise((r) => setTimeout(r, 900));\n const dir = `/demo/${fullName}/desks/${slug}`;\n deskRepo.set(dir, fullName);\n return dir;\n },\n removeDesk: async () => undefined,\n sweepDesks: async () => ({ desks: 0, folders: 0, branches: 0, patches: [], skipped: [] }),\n releaseDesk: async () => undefined,\n startSession: (opts, cb) => {\n if (++sessionsStarted === USAGE_WARNING_AT) fakeUsageWarning(cb);\n return inTerminal(opts, cb, (c) => (opts.role === 'ceo' ? ceoSession(opts, c) : fakeSession(opts, c, deskRepo.get(opts.cwd) ?? [...repos.keys()][0])));\n },\n terminals: true,\n reconnectClis: async () => [], // fake sessions end with the office\n hooksReady: () => undefined,\n releaseClis: async () => undefined,\n detectClis: async () =>\n CLIS.map((c) => ({ id: c.id, label: c.label, installed: true, version: 'demo', integrated: c.integrated })),\n previews: demoPreviews,\n office: demoOffice,\n };\n}\n\n// ---------- the office's own update ----------\n\n/**\n * Floor 1's folder plays the office's own folder, so merges there make an update ready. There is a launcher when\n * the real one started the demo, or with SWARM_DEMO_LAUNCHER=1; either way the update is faked: a short pause, then\n * the result message, and nothing restarts.\n */\nconst OFFICE_REPO = 'demo-co/pixel-todo';\nconst DEMO_HEAD = `0ff1ce5${'0'.repeat(33)}`;\nconst lastFakeUpdate = { to: '', commits: 0 };\nconst demoOffice: OfficeHost = {\n launcher: underLauncher() || process.env.SWARM_DEMO_LAUNCHER === '1',\n head: async () => DEMO_HEAD,\n isOwnFolder: (dir) => dir === `/demo/${OFFICE_REPO}/main`,\n // Only its own fake updates have a count; one the real launcher did (u) gets no count rather than a wrong one.\n commitsBetween: async (_from, to) => (to === lastFakeUpdate.to ? lastFakeUpdate.commits : null),\n takeLastUpdate: () => takeLastUpdate(HOME_DIR),\n async update(from) {\n await new Promise((r) => setTimeout(r, 4000));\n lastFakeUpdate.commits = mergedSinceSync.get(OFFICE_REPO) ?? 0;\n mergedSinceSync.set(OFFICE_REPO, 0);\n lastFakeUpdate.to = fakeSha();\n return { from, to: lastFakeUpdate.to, ok: true, installed: true, built: true, at: Date.now() };\n },\n};\n\n// ---------- the demo preview ----------\n\nfunction placeholderPage(title: string, hue: number) {\n const safe = title.replace(/[<>&\"]/g, '');\n return `<!doctype html>\n<html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>${safe}</title><link rel=\"icon\" href=\"data:,\">\n<style>\n body { margin: 0; min-height: 100vh; display: grid; place-items: center; font-family: 'Segoe UI', Arial, sans-serif; background: hsl(${hue},60%,96%); color: #222; }\n main { text-align: center; padding: 32px 40px; background: #fff; border-radius: 18px; box-shadow: 0 8px 30px hsla(${hue},50%,40%,.18); }\n h1 { margin: 0 0 6px; font-size: 26px; color: hsl(${hue},60%,38%); }\n p { margin: 0 0 22px; color: #666; }\n button { font: inherit; font-size: 18px; padding: 10px 26px; border: 0; border-radius: 999px; background: hsl(${hue},70%,55%); color: #fff; cursor: pointer; }\n button:active { transform: scale(.97); }\n #count { display: block; margin-top: 16px; font-size: 15px; color: #444; }\n</style></head>\n<body><main>\n <h1>${safe}</h1>\n <p>A placeholder app served by the demo office.</p>\n <button id=\"btn\" type=\"button\">Click me</button>\n <span id=\"count\">Clicked 0 times</span>\n</main>\n<script>\n let n = 0;\n document.getElementById('btn').addEventListener('click', () => {\n n++;\n document.getElementById('count').textContent = 'Clicked ' + n + (n === 1 ? ' time' : ' times');\n });\n</script>\n</body></html>`;\n}\n\n/** Programs the demo pretends to have, so a bogus preview command fails the way it would for real. */\nconst DEMO_PROGRAMS = ['npm', 'npx', 'node', 'pnpm', 'yarn', 'bun', 'deno', 'vite', 'next', 'python', 'python3', 'py', 'php', 'ruby', 'go', 'cargo', 'dotnet'];\n\n/**\n * No git, no npm: short fake delays through the real statuses, then a placeholder page on the floor's port.\n * Floors made in the demo have nothing to run until they get a command, and a command whose program isn't in\n * DEMO_PROGRAMS fails, so the viewer's unconfigured and error states can be tried out.\n */\nconst demoPreviews: PreviewBackend = {\n hasDefault: async (fullName) => !bareRepos.has(fullName),\n start(job, cb) {\n let stopped = false;\n let server: http.Server | null = null;\n const timers: NodeJS.Timeout[] = [];\n const later = (ms: number, fn: () => void) => timers.push(setTimeout(() => !stopped && fn(), ms));\n const hue = [...job.fullName].reduce((h, c) => (h * 31 + c.charCodeAt(0)) % 360, 7);\n const sha = (job.pr ? repos.get(job.fullName)?.pulls.find((p) => p.number === job.pr)?.headRefName ?? String(job.pr) : job.fullName + job.defaultBranch)\n .split('')\n .reduce((h, c) => (h * 33 + c.charCodeAt(0)) >>> 0, 5381)\n .toString(16)\n .padStart(7, '0')\n .slice(0, 7);\n\n cb.status('preparing');\n later(700, () => {\n cb.commit(sha);\n cb.log([`HEAD is now at ${sha} (${job.pr ? `PR #${job.pr}` : job.defaultBranch})`]);\n if (!job.command && bareRepos.has(job.fullName)) {\n stopped = true;\n cb.failed('Nothing to run: this floor has no preview command and no package.json.', true);\n return;\n }\n cb.status('installing');\n cb.log(['$ npm ci', 'added 214 packages in 1s (demo)']);\n });\n later(1600, () => {\n cb.status('starting');\n cb.log([`$ ${job.command ?? 'npm run dev'}`.replaceAll('{port}', String(job.port))]);\n const program = job.command?.trim().split(/\\s+/)[0] ?? 'npm';\n if (!DEMO_PROGRAMS.includes(program.toLowerCase())) {\n later(400, () => {\n cb.log([`'${program}' is not recognized as an internal or external command,`, 'operable program or batch file.']);\n stopped = true;\n cb.failed(`The app exited (code 1) before it listened on port ${job.port}.`);\n });\n return;\n }\n server = http.createServer((req, res) => {\n if (req.url !== '/' && !req.url?.startsWith('/?')) return void res.writeHead(404).end('Not found');\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });\n res.end(placeholderPage(job.title, hue));\n });\n server.once('error', (err) => {\n if (stopped) return;\n stopped = true;\n cb.failed(`Could not listen on port ${job.port}: ${err.message}`);\n });\n server.listen(job.port, '127.0.0.1', () => {\n if (stopped) return void server?.close();\n later(500, () => {\n cb.log([` \u279C Local: http://localhost:${job.port}/`]);\n cb.status('running');\n });\n });\n });\n\n return {\n async stop() {\n stopped = true;\n timers.forEach(clearTimeout);\n const s = server;\n server = null;\n if (!s?.listening) return;\n s.closeAllConnections();\n await new Promise<void>((resolve) => s.close(() => resolve()));\n },\n };\n },\n};\n\n// ---------- the demo CEO ----------\n\ninterface Profile {\n summary: string;\n qa: string;\n qaTitle: string;\n qaJob: string;\n devTitle: string;\n devSpecialty: string;\n devJob: string;\n hires: { title: string; specialty: string; job_description: string; reason: string }[];\n}\n\nconst PROFILES: Record<string, Profile> = {\n 'pixel-todo': {\n summary: 'Todo web app \u00B7 React + Vite + TypeScript',\n qa: '- Add, complete, edit and delete todos; they survive a reload\\n- Keyboard only: every action reachable, focus always visible\\n- Phone width (375px): nothing overflows or gets cut off\\n- No errors in the browser console',\n qaTitle: 'UI QA tester',\n qaJob: 'You test every PR the way a picky user would: click through the whole flow, try it on a phone-sized screen and with the keyboard only.',\n devTitle: 'React UI engineer',\n devSpecialty: 'frontend',\n devJob: 'You own the React components and styling. Keep components small, reuse the existing hooks, and check every change at desktop and phone widths.',\n hires: [\n {\n title: 'Accessibility engineer',\n specialty: 'a11y',\n job_description:\n 'You make the app work for **everyone**:\\n\\n- Keyboard navigation and focus management\\n- ARIA roles, checked with `axe`\\n- Colour contrast (WCAG AA)\\n\\nTest with the keyboard only. The [WAI-ARIA practices](https://www.w3.org/WAI/ARIA/apg/) are your reference.',\n reason: 'Keyboard shortcuts and drag-and-drop are in the backlog, and both are *easy to get wrong* for keyboard and screen-reader users.',\n },\n ],\n },\n 'weather-api': {\n summary: 'REST API \u00B7 Node + Express',\n qa: '- Every endpoint: happy path, bad input (400), unknown city (404)\\n- Response shapes match the OpenAPI document\\n- Rate limiting returns 429 with Retry-After\\n- Tests and lint pass',\n qaTitle: 'API QA tester',\n qaJob: 'You test the API from the outside: curl every endpoint, try bad input and edge cases, and compare responses with the OpenAPI document.',\n devTitle: 'Backend engineer',\n devSpecialty: 'backend',\n devJob: 'You own the routes and data layer. Validate input at the edge, return consistent error shapes, and add tests for every endpoint you touch.',\n hires: [\n {\n title: 'API reliability engineer',\n specialty: 'reliability',\n job_description: 'You own rate limiting, caching and error handling. Measure before you optimise and document every limit in the OpenAPI spec.',\n reason: 'Rate limiting is in the backlog and the forecast endpoint will call an upstream service that needs caching and timeouts.',\n },\n ],\n },\n};\n\nconst GENERIC: Profile = {\n summary: 'Web project \u00B7 early stage',\n qa: '- The app builds and starts\\n- The changed feature works end to end in the browser\\n- Phone width: nothing overflows\\n- No console errors',\n qaTitle: 'QA tester',\n qaJob: 'You check every PR end to end in the browser, at desktop and phone widths.',\n devTitle: 'Full-stack engineer',\n devSpecialty: 'fullstack',\n devJob: 'You build features end to end, from the UI down to the data.',\n hires: [\n {\n title: 'Frontend engineer',\n specialty: 'frontend',\n job_description: 'You own the UI:\\n\\n1. Layout and components\\n2. Styling, checked at **desktop and phone** widths',\n reason: 'The project needs someone who owns the UI from the start.',\n },\n ],\n};\n\ninterface DemoFloor {\n floor: number;\n repo: string;\n brief: string | null;\n team: { id: string; name: string; role: string; specialty: string | null; status: string }[];\n backlog: unknown[];\n pullRequests: unknown[];\n seats: Record<'dev' | 'qa', { free: number }>;\n}\n\n/** A scripted CEO that uses the real office tools, so proposals, profiles and issues behave exactly as in the real thing. */\nfunction ceoSession(opts: SessionOptions, cb: SessionCallbacks): SessionHandle {\n const office = opts.office!;\n const timers: NodeJS.Timeout[] = [];\n let stopped = false;\n let done = false;\n const wait = (ms: number) => new Promise<void>((resolve) => timers.push(setTimeout(resolve, ms)));\n const step = async (entries: LogEntry[], ms = 900 + Math.random() * 1500) => {\n if (stopped) throw new Error('Stopped by manager');\n cb.tool(entries.find((e) => e.tool)?.tool ?? null);\n cb.log(entries);\n await wait(ms);\n };\n const status = async () => {\n await step([{ kind: 'tool', tool: 'mcp__office__company_status', text: `\u23FA ${describeOfficeTool('company_status', {})}` }]);\n const s = JSON.parse(await office.call('company_status', {})) as { floors: DemoFloor[]; pendingProposals: unknown[] };\n const people = s.floors.reduce((n, f) => n + f.team.length, 0);\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\n const free = s.floors.reduce((n, f) => n + f.seats.dev.free + f.seats.qa.free, 0);\n cb.log([{ kind: 'result', text: ` \u23BF ${s.floors.length} floors \u00B7 ${people} people \u00B7 ${free} free seats \u00B7 ${issues} open issues \u00B7 ${s.pendingProposals.length} proposals pending` }]);\n return s;\n };\n const use = async (name: string, args: Record<string, unknown>) => {\n await step([{ kind: 'tool', tool: `mcp__office__${name}`, text: `\u23FA ${describeOfficeTool(name, args)}` }]);\n const out = await office.call(name, args);\n cb.log([{ kind: out.startsWith('Refused') ? 'error' : 'result', text: ` \u23BF ${out.split('\\n')[0].slice(0, 170)}` }]);\n return out;\n };\n const read = (file: string, lines: number) => step([{ kind: 'tool', tool: 'Read', text: `\u23FA Read ${file}` }, { kind: 'result', text: ` \u23BF Read ${lines} lines` }]);\n const think = (text: string) => step([{ kind: 'thinking', text: '\u273B Thinking\u2026' }, { kind: 'text', text: `\u25CF ${text}` }], 1800);\n const short = (s: string, n = 48) => (s.length > n ? `${s.slice(0, n - 1).trim()}\u2026` : s);\n\n const planIssues = async (floor: number, mission: string, team: DemoFloor['team']) => {\n const first = await use('file_issue', {\n floor,\n title: 'Set up the project skeleton',\n body: `Scaffold the app so the rest of the milestone has something to build on.\\n\\nBrief: ${mission}\\n\\nAcceptance criteria:\\n- The dev server starts\\n- A placeholder home page renders\\n- Lint, tests and build scripts exist`,\n specialty: 'frontend',\n });\n const n = Number(first.match(/#(\\d+)/)?.[1] ?? 0);\n await use('file_issue', {\n floor,\n title: `Build the core: ${short(mission, 60)}`,\n body: `${n ? `Depends on #${n}\\n\\n` : ''}Implement the heart of the brief.\\n\\nAcceptance criteria:\\n- The main flow works end to end\\n- Covered by tests`,\n specialty: 'frontend',\n });\n await use('file_issue', {\n floor,\n title: 'Polish: phone layout and empty states',\n body: `${n ? `Depends on #${n}\\n\\n` : ''}Make every screen work at 375px and add friendly empty states.`,\n specialty: 'frontend',\n });\n if (!team.some((a) => a.specialty === 'frontend')) {\n await use('propose_hire', { floor, role: 'dev', ...GENERIC.hires[0], reason: 'All three issues are UI work and nobody on the floor owns the frontend yet.' });\n }\n return n;\n };\n\n const scripts = {\n async onboard(floor: number, fullName: string) {\n const s = await status();\n const f = s.floors.find((x) => x.floor === floor);\n if (!f) return 'That floor has gone, so there was nothing to onboard.';\n const p = PROFILES[fullName.split('/')[1] ?? ''] ?? GENERIC;\n await read(`${f.repo}/README.md`, 48);\n await step([{ kind: 'tool', tool: 'Glob', text: '\u23FA Glob src/**/*' }, { kind: 'result', text: ' \u23BF Found 23 files' }]);\n await read('package.json', 36);\n await think(`${p.summary}. Let me shape the team around that.`);\n await use('set_floor_profile', { floor, summary: p.summary, qa_brief: p.qa });\n const qa = f.team.find((a) => a.role === 'qa');\n if (qa) {\n await step([{ kind: 'tool', tool: 'mcp__office__agent_detail', text: `\u23FA ${describeOfficeTool('agent_detail', { agent_id: qa.id })}` }]);\n const d = JSON.parse(await office.call('agent_detail', { agent_id: qa.id })) as { title: string; jobDescription: string | null };\n cb.log([{ kind: 'result', text: ` \u23BF ${d.title} \u00B7 job description ${d.jobDescription?.length ?? 0} chars` }]);\n await use('update_job', { agent_id: qa.id, title: p.qaTitle, job_description: p.qaJob });\n }\n const dev = f.team.find((a) => a.role === 'dev' && !a.specialty);\n if (dev) await use('update_job', { agent_id: dev.id, title: p.devTitle, specialty: p.devSpecialty, job_description: p.devJob });\n const proposed: string[] = [];\n for (const h of p.hires) if (!(await use('propose_hire', { floor, role: 'dev', ...h })).startsWith('Refused')) proposed.push(h.title);\n let planned = '';\n if (f.brief && f.backlog.length === 0) {\n const n = await planIssues(floor, f.brief, f.team);\n planned = ` I also turned your brief into three issues; #${n} sets up the skeleton and the other two wait for it.`;\n }\n return [\n `Floor ${floor}: ${p.summary}.`,\n `I wrote a QA brief for it${qa ? `, made ${qa.name} our ${p.qaTitle}` : ''}${dev ? ` and ${dev.name} our ${p.devTitle}` : ''}.`,\n proposed.length ? `I've proposed hiring: ${proposed.join(', ')}. The resume${proposed.length === 1 ? ' is' : 's are'} waiting on your phone.` : '',\n planned,\n ]\n .filter(Boolean)\n .join(' ');\n },\n async plan(floor: number, mission: string) {\n const s = await status();\n const f = s.floors.find((x) => x.floor === floor);\n if (!f) return 'That floor has gone, so there was nothing to plan.';\n await read(`${f.repo}/README.md`, 12);\n await think(\"Foundation first, so the parallel work doesn't collide.\");\n const n = await planIssues(floor, mission, f.team);\n return `I turned the brief into three issues on floor ${floor}. #${n} sets up the skeleton; the other two say \"Depends on #${n}\", so nobody starts them early.`;\n },\n async review() {\n const s = await status();\n await think('Checking each floor for idle people and stuck work.');\n for (const f of s.floors) {\n const idle = f.team.filter((a) => a.role === 'dev' && !a.specialty && (a.status === 'idle' || a.status === 'done'));\n const devs = f.team.filter((a) => a.role === 'dev').length;\n if (devs >= 6 && idle.length >= 2 && f.backlog.length < devs) {\n await use('propose_let_go', { agent_id: idle[idle.length - 1].id, reason: `Floor ${f.floor} has ${devs} developers for ${f.backlog.length} open issues; ${idle.length} of them are idle.` });\n return `Floor ${f.floor} is overstaffed: ${devs} developers for ${f.backlog.length} open issues. I suggest letting ${idle[idle.length - 1].name} go; it's on your phone.`;\n }\n }\n // An issue nobody routed while the floor has a specialist: re-route it rather than file a duplicate.\n for (const f of s.floors) {\n const specialist = f.team.find((a) => a.role === 'dev' && a.specialty);\n const unrouted = (f.backlog as { number: number; specialty: string | null; inProgress: boolean }[]).find((i) => !i.specialty && !i.inProgress);\n if (!specialist || !unrouted) continue;\n const out = await use('route_issue', { floor: f.floor, number: unrouted.number, specialty: specialist.specialty });\n if (!out.startsWith('Refused')) return `Floor ${f.floor}: #${unrouted.number} had no specialty, so I routed it to ${specialist.specialty}, ${specialist.name}'s lane.`;\n }\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\n const prs = s.floors.reduce((n, f) => n + f.pullRequests.length, 0);\n return `All ${s.floors.length} floors look healthy: ${issues} open issues and ${prs} pull requests in flight. No changes needed.`;\n },\n async chat(text: string) {\n const s = await status();\n await think('Reading your message.');\n const people = s.floors.reduce((n, f) => n + f.team.length, 0);\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\n const pending = s.pendingProposals.length;\n // Real CEOs answer in Markdown, so the demo one does too: every element the phone renders.\n const rows = s.floors.map((f) => `| ${f.floor} | \\`${f.repo.split('/').pop()}\\` | ${f.team.length} | ${f.backlog.length} | ${f.pullRequests.length} |`);\n return [\n `**Quick status:** ${s.floors.length} floor${s.floors.length === 1 ? '' : 's'}, ${people} people and ${issues} open issues.`,\n '',\n '- The team is *heads down* on the backlog',\n `- ${pending ? `**${pending}** proposal${pending === 1 ? ' is' : 's are'} waiting for you in Hires` : 'No hiring decisions waiting on you'}`,\n ' - QA re-tests every PR after a fix',\n '',\n '| Floor | Repo | People | Issues | PRs |',\n '| ---: | --- | ---: | ---: | ---: |',\n ...(rows.length ? rows : ['| \u2013 | no projects yet | 0 | 0 | 0 |']),\n '',\n 'What I would do next:',\n '',\n '1. Merge anything that passed QA',\n '2. Run `npm run build` on each floor before the next milestone',\n '3. Hire only where the backlog is piling up',\n '',\n '```bash',\n 'SWARM_HOME=/tmp/cubefarm-demo SWARM_PORT=5260 node --import tsx server/index.ts --demo',\n '```',\n '',\n `> I'm the demo CEO, so I can't act on \"${short(text)}\", but the real one would. See the [Claude Code docs](https://docs.claude.com/en/docs/claude-code/overview).`,\n ].join('\\n');\n },\n };\n\n const prompt = opts.prompt;\n const where = prompt.match(/[Ff]loor (\\d+) \\(([^,)]+)/);\n const run = /just joined the company/.test(prompt)\n ? () => scripts.onboard(Number(where?.[1]), where?.[2] ?? '')\n : /has a brief for floor/.test(prompt)\n ? () => scripts.plan(Number(where?.[1]), prompt.match(/\"\"\"([\\s\\S]*?)\"\"\"/)?.[1]?.trim() ?? '')\n : /Periodic review/.test(prompt)\n ? () => scripts.review()\n : () => scripts.chat(prompt.split('\\n').slice(1).join(' ').trim() || prompt);\n\n const finish = (ok: boolean, text: string, error?: string) => {\n if (done) return;\n done = true;\n cb.tool(null);\n cb.finished({ ok, text, costUsd: ok ? 0.4 + Math.random() : 0.05, turns: 6 + Math.floor(Math.random() * 10), errors: error ? [error] : [] });\n };\n\n timers.push(\n setTimeout(async () => {\n try {\n cb.log([{ kind: 'system', text: `\u273B Claude Code (demo) \u00B7 ${opts.model} \u00B7 ${opts.effort} effort \u00B7 CEO` }]);\n const reply = await run();\n cb.log([{ kind: 'text', text: `\u25CF ${reply}` }]);\n cb.turn?.(reply);\n finish(true, reply);\n } catch (err) {\n finish(false, '', stopped ? 'Stopped by manager' : (err as Error).message);\n }\n }, 500),\n );\n\n return {\n send(text) {\n timers.push(\n setTimeout(() => {\n if (stopped || done) return;\n const said = text.split('\\n').slice(1).join(' ').trim() || text;\n cb.log([{ kind: 'text', text: `\u25CF Noted: \"${short(said, 70)}\"` }]);\n cb.turn?.(`Noted, I'll factor that in: \"${short(said, 90)}\"`);\n }, 1500),\n );\n },\n stop() {\n stopped = true;\n timers.forEach(clearTimeout);\n finish(false, '', 'Stopped by manager');\n },\n };\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport type { WebSocket } from 'ws';\nimport type { Backend } from './backend.ts';\nimport type { LogEntry, SessionHandle, SessionResult } from './agentRunner.ts';\nimport type { PrDetails } from './github.ts';\nimport { defaultProjectsDir, DESK_SWEEP_INTERVAL_MS, HOME_DIR, LOG_BUFFER, SCHEDULER_INTERVAL_MS, STATE_FILE, SYNC_INTERVAL_MS, WORKSPACE_ROOT } from './config.ts';\nimport { ceoJobPrompt, ceoSystemPrompt, checkPendingLimit, createOfficeTools, FLOOR_DESKS, IssueCap, jobLabel, MAX_PENDING_PROPOSALS, planRoute, seatCount, specialtyLabel, specialtySlug, type CeoJob, type OfficeTools } from './ceo.ts';\nimport { fixOutcome } from './fixOutcome.ts';\nimport { HttpError } from './httpError.ts';\nimport { issuesResolvedBy, issueTaken } from './issueClaims.ts';\nimport { CHECKS_ALERT_MS, MAX_MERGE_FIXES, MERGE_RETRY_MS, mergeStep } from './mergeGate.ts';\nimport { orphanedQa } from './qaOrphans.ts';\nimport { followKeptCli, resumeNote, resumesAfterRestart } from './restartRecovery.ts';\nimport { DEFAULT_PREVIEW, Previews, parsePreviewPatch } from './previews.ts';\nimport { PREVIEW_SLUG } from './previewRunner.ts';\nimport { ceoPromptPreview, devBranch, devPromptPreview, devSystemPrompt, qaBranch, qaPromptPreview, qaSystemPrompt } from './prompts.ts';\nimport { drainDecision, lastUpdateMessage, POSTPONE_MS, type DrainInput, type LastUpdate } from './officeUpdate.ts';\nimport { clampPacingSessions, DEFAULT_PACING_SESSIONS, mayStart, PACING_MS, pacingMessage, usageLabel, usageView, type UsageWarning, type WorkKind } from './pacing.ts';\nimport { isCli } from './clis.ts';\nimport { AgentTerminal } from './terminal.ts';\nimport { blockers, holdUps, issueSpecialty } from '../shared/issues.ts';\nimport { effectiveModel } from '../shared/models.ts';\nimport { CEO_ID } from '../shared/types.ts';\nimport type {\n AgentCli,\n AgentLook,\n AgentPromptView,\n AgentRole,\n AgentStatus,\n AgentTask,\n AgentView,\n CeoInfo,\n CliView,\n EffortLevel,\n HireRequestView,\n IssueInfo,\n LogLine,\n OfficeUpdateView,\n PhoneMessage,\n PreviewConfig,\n PreviewView,\n ProjectFolderView,\n PullInfo,\n QaCheck,\n QaView,\n RepoView,\n ServerEvent,\n SwarmSettings,\n WorldSnapshot,\n} from '../shared/types.ts';\n\n// ---------- persisted shape ----------\n\ninterface PersistedRepo {\n id: string;\n fullName: string;\n description: string;\n url: string;\n defaultBranch: string;\n floor: number;\n color: string;\n autoAssign: boolean;\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\n browserTesting: boolean;\n links: string[]; // other connected repos this floor's agents may read\n localPath: string | null; // the manager's own project folder (null: a clone under WORKSPACE_ROOT)\n mission: string;\n summary: string;\n qaBrief: string;\n preview: PreviewConfig; // how the floor's app runs for the preview monitor\n addedAt: number;\n}\n\ninterface PersistedAgent {\n id: string;\n name: string;\n repoId: string; // '' for the CEO, who works in the lobby\n role: AgentRole;\n title: string;\n specialty: string;\n brief: string;\n hiredBy: 'manager' | 'ceo';\n look: AgentLook;\n task: AgentTask | null;\n desk: number;\n color: string;\n hair: string;\n skin: string;\n model: string;\n effort: EffortLevel | '';\n cli: AgentCli | ''; // '' = the office's default CLI\n status: AgentStatus;\n issueNumber: number | null;\n issueTitle: string | null;\n branch: string | null;\n prNumber: number | null;\n prUrl: string | null;\n startedAt: number | null;\n endedAt: number | null;\n costUsd: number;\n turns: number;\n sessionId: string | null;\n sessionCli: AgentCli | null; // the CLI whose session sessionId is: only it can resume it\n lastError: string | null;\n logTail: LogLine[];\n}\n\n/** A pull request's trip through QA. */\ninterface QaRecord extends QaView {\n issueNumber: number | null;\n devSessionId: string | null; // the dev's Claude Code session, resumed to fix QA findings\n fixInstructions: string | null;\n sessionFailures: number;\n testedSha: string | null; // the head commit QA is testing\n passedSha: string | null; // the head commit QA signed off on: auto-merge merges exactly that\n fixReason: 'qa' | 'checks' | 'conflict' | null; // why it was last sent back to a developer\n mergeFixes: number; // times it went back for failing checks or conflicts\n retests: number; // QA rounds caused by merge fixes or new commits rather than by QA failing it\n pendingSince: number | null; // when auto-merge started waiting on its checks\n mergeRetryAt: number | null; // GitHub refused the merge: try again after this\n alerted: boolean; // the manager has been told it's stuck\n}\n\n/** Choices made when a project moves into the office. */\ninterface FloorOptions {\n mission?: string; // brief for the CEO to plan from\n autoAssign?: boolean; // free developers pick up backlog issues as soon as they're filed\n}\n\ninterface CeoState {\n queue: CeoJob[];\n job: CeoJob | null; // the job the CEO is on right now\n lastReviewAt: number | null;\n lastFingerprint: string | null; // company state at the last review; unchanged means the next review is skipped\n}\n\ninterface Persisted {\n settings: SwarmSettings;\n repos: PersistedRepo[];\n agents: PersistedAgent[];\n qa: QaRecord[];\n requests: HireRequestView[];\n ceo: CeoState;\n messages: PhoneMessage[];\n phoneReadAt: number;\n}\n\ninterface Shot {\n data: Buffer;\n mime: string;\n url: string | null;\n at: number;\n}\n\ninterface AgentRuntime {\n log: LogLine[];\n pending: LogLine[];\n session: SessionHandle | null;\n currentTool: string | null;\n browserUrl: string | null;\n screenshot: { data: Buffer; mime: string; at: number } | null;\n shots: Shot[]; // every screenshot of the current session (QA evidence)\n terminal: AgentTerminal | null; // their terminal, once they've run in the terminal runtime\n}\n\ninterface RepoRuntime {\n issues: IssueInfo[];\n pulls: PullInfo[];\n lastSync: number | null;\n syncError?: string;\n syncing: boolean;\n cloneStatus: RepoView['cloneStatus'];\n cloneError?: string;\n fetchedAt?: number; // when the latest issues/PRs fetch started\n lastMergedAt: string | null; // newest merge seen: a newer one means the folder needs a sync\n folderSync: string | null;\n merging: boolean;\n}\n\ninterface QaReport {\n verdict: 'pass' | 'fail';\n summary: string;\n checks: QaCheck[];\n commands: { command: string; result: string }[];\n screenshots: string[];\n fixInstructions?: string;\n}\n\n// ---------- flavour ----------\n\nconst FLOOR_COLORS = ['#ff8a5b', '#4fb3e8', '#8fd14f', '#c77dff', '#ffc93c', '#ff6fb5', '#2ec4b6', '#f25f5c'];\nconst SHIRTS = ['#e63946', '#457b9d', '#2a9d8f', '#f4a261', '#9b5de5', '#f15bb5', '#00bbf9', '#06d6a0', '#ffbe0b', '#8338ec', '#fb5607', '#3a86ff'];\nconst HAIR = ['#2b2118', '#6b4226', '#c68642', '#f2d16b', '#d94f30', '#1c1c1c', '#8e8e8e', '#5b3cc4', '#e76f51'];\nconst SKIN = ['#ffdbac', '#f1c27d', '#e0ac69', '#c68642', '#8d5524', '#ffe0bd'];\nconst DEV_NAMES = [\n 'Ada', 'Linus', 'Grace', 'Alan', 'Margaret', 'Dennis', 'Barbara', 'Ken', 'Radia', 'Guido', 'Hedy', 'Tim', 'Katherine',\n 'Bjarne', 'Frances', 'Edsger', 'Anita', 'Donald', 'Sophie', 'Yukihiro', 'Jean', 'Niklaus', 'Karen', 'Brendan',\n];\nconst QA_NAMES = ['Sherlock', 'Marple', 'Poirot', 'Nancy', 'Columbo', 'Fletcher', 'Watson', 'Morse', 'Holmes', 'Maigret'];\n\n// Names that get the feminine character look: everyone in the name pools above, plus common first names\n// for agents the manager names themselves. The manager can always change an agent's look in the console.\nconst FEMININE_NAMES = new Set(\n (\n 'ada grace margaret barbara radia hedy katherine frances anita sophie jean karen marple nancy fletcher ' +\n 'alice amanda amelia amy ana anna anne aisha astrid ava bella beth carla caroline charlotte chloe claire clara ' +\n 'diana elena elizabeth ella ellie emily emma eva fatima fiona freya georgia hannah harper helen holly ingrid iris ' +\n 'isabella ivy jane jasmine jessica julia kate laura leah leila lena lily linda lisa lucy maria marie mary maya mei ' +\n 'mia mila monica naomi natalie nina nora olivia paula priya rachel rose ruby sandra sara sarah scarlett sofia ' +\n 'stella susan tess tessa tina vera victoria yuki zara zoe'\n ).split(' '),\n);\nconst lookFor = (name: string): AgentLook => (FEMININE_NAMES.has(name.trim().split(/\\s+/)[0].toLowerCase()) ? 'feminine' : 'masculine');\nconst LOOKS: AgentLook[] = ['feminine', 'masculine'];\nconst MAX_DESKS: Record<AgentRole, number> = { ...FLOOR_DESKS, ceo: 1 };\nconst MAX_QA_ROUNDS = 3;\n// Every agent runs Claude Opus 5.5 at medium effort unless the manager overrides it.\nconst DEFAULT_MODEL = 'claude-opus-5-5';\nconst EFFORTS: EffortLevel[] = ['low', 'medium', 'high', 'xhigh', 'max'];\n// The CEO thinks harder than the staff: Opus 5.5 at xhigh effort unless the manager changes it.\nconst CEO_MODEL = 'claude-opus-5-5';\nconst CEO_EFFORT: EffortLevel = 'xhigh';\nconst CEO_NAME = 'Morgan';\n// The CEO's own folder: its notes about the company live here. Repos are read through their clones.\nconst CEO_DIR = path.join(HOME_DIR, 'ceo');\nconst DEFAULT_PROJECTS_DIR = defaultProjectsDir(path.resolve(import.meta.dirname, '..'));\nconst MAX_ISSUES_PER_JOB = 12;\nconst KEEP_MESSAGES = 200;\nconst KEEP_DECIDED_REQUESTS = 40;\n\nconst pick = <T>(arr: T[]) => arr[Math.floor(Math.random() * arr.length)];\nconst slugify = (s: string) =>\n s\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 40) || 'agent';\n\nconst BUSY: AgentStatus[] = ['preparing', 'working'];\nconst FREE: AgentStatus[] = ['idle', 'done'];\n// An agent whose session failed sits out this long before taking new work, so a broken setup can't burn through the queue.\nconst ERROR_COOLDOWN_MS = 2 * 60_000;\n// Auto-assign stops retrying an issue after this many failed sessions; the manager can still assign it by hand.\nconst MAX_ISSUE_FAILURES = 2;\n// How long the office waits after Claude's usage limit is hit when Claude doesn't say when it resets.\nconst LIMIT_PAUSE_MS = 15 * 60_000;\nconst oneLine = (err: unknown) => (err instanceof Error ? err.message : String(err)).split(/\\r?\\n/)[0].slice(0, 200);\n\n// The latest browser screenshot per agent is kept on disk so monitors survive a server restart.\nconst SCREENS_DIR = path.join(HOME_DIR, 'screens');\nconst MIME_EXT: Record<string, string> = { 'image/png': 'png', 'image/jpeg': 'jpg', 'image/webp': 'webp', 'image/svg+xml': 'svg' };\nconst screenFile = (agentId: string, mime: string) => path.join(SCREENS_DIR, `${agentId}.${MIME_EXT[mime] ?? 'img'}`);\n\nasync function loadScreen(agentId: string): Promise<{ data: Buffer; mime: string; at: number } | null> {\n for (const [mime, ext] of Object.entries(MIME_EXT)) {\n const file = path.join(SCREENS_DIR, `${agentId}.${ext}`);\n try {\n const [data, stat] = await Promise.all([fs.readFile(file), fs.stat(file)]);\n return { data, mime, at: stat.mtimeMs };\n } catch {\n // try the next extension\n }\n }\n return null;\n}\n\nasync function removeScreens(agentId: string) {\n await Promise.all(Object.values(MIME_EXT).map((ext) => fs.rm(path.join(SCREENS_DIR, `${agentId}.${ext}`), { force: true })));\n}\n\n// Each agent's terminal (screen and scrollback) is saved too, so the office shows what they did after a restart.\nconst TERMINALS_DIR = path.join(HOME_DIR, 'terminals');\nconst terminalFile = (agentId: string) => path.join(TERMINALS_DIR, `${agentId}.ansi`);\nconst TERMINAL_SAVE_MS = 20_000;\n\n// ---------- QA report ----------\n\nconst QA_SCHEMA: Record<string, unknown> = {\n type: 'object',\n additionalProperties: false,\n required: ['verdict', 'summary', 'checks', 'commands', 'screenshots'],\n properties: {\n verdict: { type: 'string', enum: ['pass', 'fail'], description: 'pass only if the change works and meets the issue requirements' },\n summary: { type: 'string', description: 'Two to four sentences for the pull request comment.' },\n checks: {\n type: 'array',\n description: 'Each acceptance criterion, test run or scenario you verified.',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'result', 'details'],\n properties: {\n name: { type: 'string' },\n result: { type: 'string', enum: ['pass', 'fail', 'skip'] },\n details: { type: 'string', description: 'What you did and what you observed.' },\n },\n },\n },\n commands: {\n type: 'array',\n description: 'Test suites, linters, builds and other commands you ran.',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['command', 'result'],\n properties: { command: { type: 'string' }, result: { type: 'string', description: 'e.g. \"42 passed, 0 failed\"' } },\n },\n },\n screenshots: {\n type: 'array',\n description: 'One short caption per screenshot you took with browser_take_screenshot, in the order you took them.',\n items: { type: 'string' },\n },\n fixInstructions: { type: 'string', description: 'When the verdict is fail: precise, actionable instructions for the developer.' },\n },\n};\n\nfunction parseReport(result: SessionResult): QaReport | null {\n let raw: unknown = result.structured;\n if (!raw && result.text) {\n // Terminal agents end their last message with the report, usually in a ```json block.\n const fenced = [...result.text.matchAll(/```(?:json)?\\s*(\\{[\\s\\S]*?\\})\\s*```/g)].map((m) => m[1]).reverse();\n for (const json of [...fenced, result.text.match(/\\{[\\s\\S]*\\}/)?.[0]].filter((j): j is string => !!j)) {\n try {\n raw = JSON.parse(json);\n break;\n } catch {\n raw = null;\n }\n }\n }\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Partial<QaReport>;\n if (r.verdict !== 'pass' && r.verdict !== 'fail') return null;\n return {\n verdict: r.verdict,\n summary: String(r.summary ?? ''),\n checks: Array.isArray(r.checks) ? r.checks.map((c) => ({ name: String(c.name ?? ''), result: c.result === 'fail' ? 'fail' : c.result === 'skip' ? 'skip' : 'pass', details: String(c.details ?? '') })) : [],\n commands: Array.isArray(r.commands) ? r.commands.map((c) => ({ command: String(c.command ?? ''), result: String(c.result ?? '') })) : [],\n screenshots: Array.isArray(r.screenshots) ? r.screenshots.map(String) : [],\n fixInstructions: r.fixInstructions ? String(r.fixInstructions) : undefined,\n };\n}\n\nconst cell = (s: string) => s.replace(/\\|/g, '\\\\|').replace(/\\r?\\n/g, '<br>');\nconst ICON = { pass: '\u2705', fail: '\u274C', skip: '\u23ED\uFE0F' } as const;\n\nexport { HttpError };\n\nexport class Swarm {\n private state: Persisted = {\n settings: {\n sessionLimit: 0,\n defaultModel: DEFAULT_MODEL,\n defaultEffort: 'medium',\n runtime: 'terminal',\n defaultCli: 'claude',\n hiring: 'approve',\n teamCap: 6,\n ceoHeartbeatMin: 60,\n managerName: '',\n companyName: '',\n projectsDir: DEFAULT_PROJECTS_DIR,\n setupDone: false,\n tutorialStep: 0,\n autoUpdate: true,\n pacingSessions: DEFAULT_PACING_SESSIONS,\n },\n repos: [],\n agents: [],\n qa: [],\n requests: [],\n ceo: { queue: [], job: null, lastReviewAt: null, lastFingerprint: null },\n messages: [],\n phoneReadAt: 0,\n };\n /**\n * The CEO's office tools. Every session gets its own server: one can only be connected to one session at a time, so\n * a shared one left the next session connected but without any tools while an earlier session still held it.\n */\n private officeTools(): OfficeTools {\n return createOfficeTools({\n companyStatus: () => this.companyStatus(),\n agentDetail: (a) => this.agentDetail(a),\n setFloorProfile: (a) => this.setFloorProfile(a),\n updateJob: (a) => this.updateJob(a),\n proposeHire: (a) => this.proposeHire(a),\n proposeLetGo: (a) => this.proposeLetGo(a),\n fileIssue: (a) => this.fileIssue(a),\n routeIssue: (a) => this.routeIssue(a),\n });\n }\n private ceoIssues = new IssueCap(MAX_ISSUES_PER_JOB); // issues filed during the current CEO job\n private messageSeq = 1;\n private agentRt = new Map<string, AgentRuntime>();\n private repoRt = new Map<string, RepoRuntime>();\n private clients = new Set<WebSocket>();\n private user: string | null = null;\n private ghError: string | undefined;\n private saveTimer: NodeJS.Timeout | null = null;\n private flushTimer: NodeJS.Timeout | null = null;\n private logSeq = 1;\n private previews: Previews;\n private officeHead: string | null = null; // the commit the office runs (null: not a git checkout, so no self-update)\n private officeUpdate = {\n behind: 0,\n requested: false,\n postponedUntil: null as number | null,\n postponedBehind: 0,\n failed: null as string | null,\n failedBehind: null as number | null,\n drainingSince: null as number | null,\n sent: false,\n handedOver: false, // sessions cut off by the hand-over are the restarted office's to recover\n };\n private lastOfficeView = '';\n private clis: CliView[] = []; // coding-agent CLIs found on this machine (detected at startup)\n\n constructor(private backend: Backend) {\n this.previews = new Previews(backend, {\n emit: (id) => {\n const r = this.state.repos.find((x) => x.id === id);\n if (r && this.repoRt.has(id)) this.emitRepo(r);\n },\n pulls: (id) => this.repoRt.get(id)?.pulls ?? [],\n });\n }\n\n // ---------- lifecycle ----------\n\n async init() {\n try {\n const raw = await fs.readFile(STATE_FILE, 'utf8');\n const loaded = JSON.parse(raw) as Partial<Persisted>;\n this.state = {\n settings: { ...this.state.settings, ...loaded.settings },\n repos: (loaded.repos ?? []).map((r) => ({\n ...r,\n autoMerge: r.autoMerge ?? true,\n links: r.links ?? [],\n mission: r.mission ?? '',\n summary: r.summary ?? '',\n qaBrief: r.qaBrief ?? '',\n localPath: r.localPath ?? null,\n preview: { command: r.preview?.command ?? null, env: { ...r.preview?.env } },\n })),\n agents: (loaded.agents ?? []).map((a) => ({\n ...a,\n effort: a.effort ?? '',\n role: a.role ?? 'dev',\n title: a.title ?? '',\n specialty: a.specialty ?? '',\n brief: a.brief ?? '',\n hiredBy: a.hiredBy ?? 'manager',\n look: a.look ?? lookFor(a.name),\n task: a.task ?? (a.issueNumber ? 'issue' : null),\n cli: isCli(a.cli) ? a.cli : '',\n sessionCli: a.sessionCli ?? (a.sessionId ? 'claude' : null),\n })),\n qa: (loaded.qa ?? []).map((q) => ({\n ...q,\n testedSha: q.testedSha ?? null,\n passedSha: q.passedSha ?? null,\n fixReason: q.fixReason ?? null,\n mergeFixes: q.mergeFixes ?? 0,\n retests: q.retests ?? 0,\n pendingSince: q.pendingSince ?? null,\n mergeRetryAt: q.mergeRetryAt ?? null,\n alerted: q.alerted ?? false,\n mergeNote: null,\n })),\n requests: loaded.requests ?? [],\n ceo: { ...this.state.ceo, ...loaded.ceo },\n messages: loaded.messages ?? [],\n phoneReadAt: loaded.phoneReadAt ?? 0,\n };\n for (const m of this.state.messages) this.messageSeq = Math.max(this.messageSeq, m.id + 1);\n if (!EFFORTS.includes(this.state.settings.defaultEffort)) this.state.settings.defaultEffort = 'medium';\n if (this.state.settings.runtime !== 'sdk') this.state.settings.runtime = 'terminal';\n if (!isCli(this.state.settings.defaultCli)) this.state.settings.defaultCli = 'claude';\n if (!this.state.settings.defaultModel && this.state.settings.defaultCli === 'claude') this.state.settings.defaultModel = DEFAULT_MODEL;\n // \"Max concurrent sessions\" (default 4) became an optional session limit. The old default goes; a limit the manager chose stays.\n const old = this.state.settings as SwarmSettings & { maxConcurrent?: number; permissionMode?: string };\n if (old.maxConcurrent !== undefined) {\n if (loaded.settings?.sessionLimit === undefined) old.sessionLimit = old.maxConcurrent === 4 ? 0 : old.maxConcurrent;\n delete old.maxConcurrent;\n }\n delete old.permissionMode; // the office's rules are instructions now, not a permission mode\n // Offices that were set up before the setup wizard existed skip it.\n if (loaded.settings && loaded.settings.setupDone === undefined && this.state.repos.length > 0) {\n Object.assign(this.state.settings, { setupDone: true, tutorialStep: -1 });\n }\n } catch {\n // first run\n }\n for (const r of this.state.repos) if (r.localPath) this.backend.setLocalPath(r.fullName, r.localPath);\n const interrupted: PersistedAgent[] = [];\n for (const a of this.state.agents) {\n const tail = a.logTail ?? [];\n for (const l of tail) this.logSeq = Math.max(this.logSeq, l.id + 1);\n this.agentRt.set(a.id, { log: tail, pending: [], session: null, currentTool: null, browserUrl: null, screenshot: await loadScreen(a.id), shots: [], terminal: await this.loadTerminal(a.id) });\n }\n // CLIs the terminal keeper kept running through the restart go back into their terminals, and busy ones carry on.\n // (The CEO's session is resumed instead: its office tools live in this process.)\n const back = await this.backend\n .reconnectClis((id) => {\n const a = this.state.agents.find((x) => x.id === id);\n return a && a.role !== 'ceo' ? this.terminalFor(a) : null;\n })\n .catch((err) => {\n console.warn('could not reconnect to the terminal keeper', err);\n return [];\n });\n const carryOn: PersistedAgent[] = [];\n const preparing = new Set<PersistedAgent>(); // their task's session hadn't started: nothing of it to resume\n for (const a of this.state.agents) {\n if (!BUSY.includes(a.status)) continue;\n if (followKeptCli(a, back.find((c) => c.agentId === a.id))) {\n carryOn.push(a);\n continue;\n }\n if (a.status === 'preparing') preparing.add(a);\n a.status = 'stopped';\n a.lastError = 'The swarm server restarted while this agent was working.';\n interrupted.push(a);\n }\n for (const c of back) if (c.busy && !carryOn.some((a) => a.id === c.agentId)) this.agentRt.get(c.agentId)?.terminal?.releaseIdle?.();\n for (const r of this.state.repos) this.repoRt.set(r.id, { issues: [], pulls: [], lastSync: null, syncing: false, cloneStatus: 'pending', lastMergedAt: null, folderSync: null, merging: false });\n for (const a of carryOn) this.reattachSession(a);\n this.backend.hooksReady();\n\n try {\n this.user = await this.backend.user();\n } catch (err) {\n this.ghError = `GitHub CLI is not ready: ${(err as Error).message}. Run \"gh auth login\".`;\n console.warn(this.ghError);\n }\n\n if (this.backend.demo && this.state.repos.length === 0) {\n // The demo opens on a busy office; the tutorial still runs so it can be tried.\n Object.assign(this.state.settings, { setupDone: true, managerName: 'Demo Manager', companyName: 'Demo Co.' });\n for (const r of await this.backend.listMyRepos()) {\n const repo = await this.connectRepo(r.nameWithOwner);\n for (let i = 0; i < (repo.floor === 1 ? 5 : 3); i++) this.hireAgent(repo.id, {});\n this.updateRepo(repo.id, { autoAssign: true });\n }\n }\n for (const r of this.state.repos) this.ensureQaTester(r);\n this.ensureCeo(interrupted);\n\n for (const r of this.state.repos) void this.cloneRepo(r.id);\n await Promise.all(this.state.repos.map((r) => this.syncRepo(r.id)));\n // Anything still alive in a desk (or a preview) is left over from before the restart, except around the CLIs that\n // kept running through it: their dev servers and commands are theirs.\n await Promise.all([\n ...this.state.agents.map((a) => {\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n if (!repo || back.some((c) => c.agentId === a.id)) return undefined;\n return this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined);\n }),\n this.previews.clearOrphans(this.state.repos),\n ]);\n for (const r of this.state.repos) void this.previews.refreshDefault(r);\n this.recover(interrupted, preparing);\n // A PR the restart left in \"testing\" with nobody on it: test it again (the result, if any, was lost).\n for (const rec of orphanedQa(this.state.qa, this.state.agents, BUSY)) this.setQa(rec, { status: 'queued', qaAgentId: null });\n this.officeHead = await this.backend.office.head();\n const updated = await this.backend.office.takeLastUpdate().catch(() => null);\n if (updated) await this.reportUpdate(updated);\n setInterval(() => this.state.repos.forEach((r, i) => setTimeout(() => void this.syncRepo(r.id), i * 1500)), SYNC_INTERVAL_MS);\n setInterval(() => this.schedule(), SCHEDULER_INTERVAL_MS);\n setInterval(() => void this.saveTerminals(), TERMINAL_SAVE_MS);\n setInterval(() => this.state.repos.forEach((r, i) => setTimeout(() => void this.sweepFloor(r.id), i * 1500)), DESK_SWEEP_INTERVAL_MS);\n void this.backend\n .detectClis()\n .then((clis) => {\n this.clis = clis;\n this.broadcast({ type: 'clis', clis });\n })\n .catch((err) => console.warn('could not look for agent CLIs', err));\n this.save();\n setTimeout(() => this.schedule(), 1000);\n }\n\n /**\n * Agents cut off by a server restart pick their session back up, told what they were doing. QA, demo agents and\n * tasks still being prepared start over from the queue.\n */\n private recover(agents: PersistedAgent[], preparing: Set<PersistedAgent>) {\n for (const a of agents) {\n const fix = a.task === 'fix' ? this.state.qa.find((q) => q.devAgentId === a.id && q.status === 'fixing') : undefined;\n if (!resumesAfterRestart(a, preparing.has(a), this.backend.demo)) {\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Starting over from the queue.' }]);\n const rec = a.task === 'qa' ? this.state.qa.find((q) => q.qaAgentId === a.id && q.status === 'testing') : undefined;\n if (rec) this.setQa(rec, { status: 'queued' });\n if (fix) this.setQa(fix, { status: 'failed' });\n this.clearTask(a);\n continue;\n }\n if (this.slotsFull()) continue; // stays 'stopped'; the manager can resume it later\n void this.message(a.id, resumeNote(a, fix)).catch((err) => console.warn(`could not resume ${a.name}`, err));\n }\n }\n\n // ---------- views ----------\n\n private repoView(r: PersistedRepo): RepoView {\n const rt = this.repoRt.get(r.id)!;\n return {\n id: r.id,\n fullName: r.fullName,\n description: r.description,\n url: r.url,\n defaultBranch: r.defaultBranch,\n floor: r.floor,\n color: r.color,\n autoAssign: r.autoAssign,\n autoMerge: r.autoMerge,\n folderSync: rt.folderSync,\n browserTesting: r.browserTesting,\n links: r.links,\n mission: r.mission,\n summary: r.summary,\n qaBrief: r.qaBrief,\n localPath: r.localPath,\n checkoutPath: this.backend.mainDir(r.fullName),\n cloneStatus: rt.cloneStatus,\n cloneError: rt.cloneError,\n issues: rt.issues,\n pulls: rt.pulls,\n lastSync: rt.lastSync,\n syncError: rt.syncError,\n previewConfig: r.preview,\n preview: this.previews.view(r),\n };\n }\n\n private agentView(a: PersistedAgent, withLog: boolean): AgentView {\n const rt = this.agentRt.get(a.id)!;\n return {\n id: a.id,\n name: a.name,\n repoId: a.repoId,\n role: a.role,\n title: a.title,\n specialty: a.specialty,\n brief: a.brief,\n hiredBy: a.hiredBy,\n look: a.look,\n task: a.task,\n desk: a.desk,\n color: a.color,\n hair: a.hair,\n skin: a.skin,\n model: a.model,\n effort: a.effort,\n cli: a.cli,\n terminal: !!rt.terminal,\n status: a.status,\n issueNumber: a.issueNumber,\n issueTitle: a.issueTitle,\n branch: a.branch,\n prNumber: a.prNumber,\n prUrl: a.prUrl,\n currentTool: rt.currentTool,\n startedAt: a.startedAt,\n endedAt: a.endedAt,\n costUsd: a.costUsd,\n turns: a.turns,\n browserUrl: rt.browserUrl,\n hasScreenshot: !!rt.screenshot,\n screenshotAt: rt.screenshot?.at ?? null,\n lastError: a.lastError,\n log: withLog ? rt.log : [],\n };\n }\n\n private qaView(q: QaRecord): QaView {\n return {\n repoId: q.repoId,\n prNumber: q.prNumber,\n status: q.status,\n round: q.round,\n devAgentId: q.devAgentId,\n qaAgentId: q.qaAgentId,\n summary: q.summary,\n checks: q.checks,\n commentUrl: q.commentUrl,\n mergeNote: q.mergeNote,\n updatedAt: q.updatedAt,\n };\n }\n\n snapshot(): WorldSnapshot {\n return {\n user: this.user,\n ghReady: !this.ghError,\n ghError: this.ghError,\n demo: this.backend.demo,\n workspaceRoot: WORKSPACE_ROOT,\n settings: this.state.settings,\n repos: this.state.repos.map((r) => this.repoView(r)),\n agents: this.state.agents.map((a) => this.agentView(a, true)),\n qa: this.state.qa.map((q) => this.qaView(q)),\n requests: this.state.requests,\n ceo: this.ceoInfo(),\n messages: this.state.messages.slice(-100),\n phoneReadAt: this.state.phoneReadAt,\n usage: this.usageNow(),\n clis: this.clis,\n officeCommit: this.officeHead?.slice(0, 7) ?? null,\n officeUpdate: this.officeHead ? this.officeUpdateView() : undefined,\n };\n }\n\n screenshot(agentId: string) {\n return this.agentRt.get(agentId)?.screenshot ?? null;\n }\n\n // ---------- clients ----------\n\n addClient(ws: WebSocket) {\n this.clients.add(ws);\n ws.on('close', () => this.clients.delete(ws));\n this.send(ws, { type: 'snapshot', data: this.snapshot() });\n }\n\n private send(ws: WebSocket, ev: ServerEvent) {\n if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(ev));\n }\n\n private broadcast(ev: ServerEvent) {\n const msg = JSON.stringify(ev);\n for (const ws of this.clients) if (ws.readyState === ws.OPEN) ws.send(msg);\n }\n\n private toast(level: 'info' | 'success' | 'error', text: string) {\n this.broadcast({ type: 'toast', level, text });\n }\n\n private emitRepo(r: PersistedRepo) {\n this.broadcast({ type: 'repo', repo: this.repoView(r) });\n }\n\n private emitAgent(a: PersistedAgent) {\n // A session can finish after its agent was let go (their floor disconnected mid-task); they're gone, so say nothing.\n if (!this.agentRt.has(a.id)) return;\n const { log: _log, ...rest } = this.agentView(a, false);\n this.broadcast({ type: 'agent', agent: rest });\n }\n\n private setQa(rec: QaRecord, patch: Partial<QaRecord>) {\n Object.assign(rec, patch, { updatedAt: Date.now() });\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\n this.save();\n }\n\n private appendLog(a: PersistedAgent, entries: LogEntry[]) {\n const rt = this.agentRt.get(a.id);\n if (!rt) return;\n const t = Date.now();\n for (const e of entries) {\n const line: LogLine = { id: this.logSeq++, t, kind: e.kind, text: e.text, tool: e.tool };\n rt.log.push(line);\n rt.pending.push(line);\n }\n if (rt.log.length > LOG_BUFFER) rt.log.splice(0, rt.log.length - LOG_BUFFER);\n if (!this.flushTimer) this.flushTimer = setTimeout(() => this.flushLogs(), 120);\n }\n\n private flushLogs() {\n this.flushTimer = null;\n for (const [agentId, rt] of this.agentRt) {\n if (rt.pending.length === 0) continue;\n this.broadcast({ type: 'log', agentId, lines: rt.pending });\n rt.pending = [];\n }\n this.save();\n }\n\n // ---------- persistence ----------\n\n private save() {\n if (this.saveTimer) return;\n this.saveTimer = setTimeout(() => void this.writeState().catch((err) => console.warn('could not save the state', err)), 1500);\n }\n\n /** Write the state file now, e.g. before the office stops or hands itself to the launcher. */\n private async writeState() {\n if (this.saveTimer) clearTimeout(this.saveTimer);\n this.saveTimer = null;\n for (const a of this.state.agents) a.logTail = (this.agentRt.get(a.id)?.log ?? []).slice(-200);\n await fs.mkdir(path.dirname(STATE_FILE), { recursive: true });\n const tmp = `${STATE_FILE}.tmp`;\n await fs.writeFile(tmp, JSON.stringify(this.state, null, 2));\n await fs.rename(tmp, STATE_FILE);\n }\n\n // ---------- lookups ----------\n\n private repo(id: string) {\n const r = this.state.repos.find((x) => x.id === id);\n if (!r) throw new HttpError(404, `Repo ${id} is not connected`);\n return r;\n }\n\n private agent(id: string) {\n const a = this.state.agents.find((x) => x.id === id);\n if (!a) throw new HttpError(404, `No agent ${id}`);\n return a;\n }\n\n private running() {\n return this.state.agents.filter((a) => BUSY.includes(a.status)).length;\n }\n\n /** True when the manager has set a session limit and every slot is taken. */\n private slotsFull() {\n const limit = this.state.settings.sessionLimit;\n return limit > 0 && this.running() >= limit;\n }\n\n private agentSlug(a: PersistedAgent) {\n return `${slugify(a.name)}-${a.id.slice(0, 4)}`;\n }\n\n private clearTask(a: PersistedAgent) {\n Object.assign(a, { status: 'idle', task: null, issueNumber: null, issueTitle: null, branch: null, prNumber: null, prUrl: null, lastError: null });\n this.emitAgent(a);\n }\n\n // ---------- GitHub / repos ----------\n\n listGithubRepos(owner?: string) {\n return this.backend.listMyRepos(owner);\n }\n\n /**\n * Give a GitHub repo a floor. Its main checkout is one of your own folders: the one you picked, else the folder in\n * your projects folder that already has it as origin, else a fresh clone into your projects folder.\n */\n async connectRepo(fullName: string, opts: FloorOptions & { localPath?: string } = {}): Promise<RepoView> {\n const existing = this.state.repos.find((r) => r.id.toLowerCase() === fullName.toLowerCase());\n if (existing) throw new HttpError(409, `${fullName} is already floor ${existing.floor}`);\n const meta = await this.backend.repoMeta(fullName);\n const folder = opts.localPath ?? (await this.projectFolderFor(meta.nameWithOwner));\n const floor = this.state.repos.reduce((m, r) => Math.max(m, r.floor), 0) + 1;\n const repo: PersistedRepo = {\n id: meta.nameWithOwner,\n fullName: meta.nameWithOwner,\n description: meta.description,\n url: meta.url,\n defaultBranch: meta.defaultBranch,\n floor,\n color: FLOOR_COLORS[(floor - 1) % FLOOR_COLORS.length],\n autoAssign: !!opts.autoAssign,\n autoMerge: true,\n browserTesting: true,\n links: [],\n localPath: folder,\n mission: (opts.mission ?? '').trim().slice(0, 4000),\n summary: '',\n qaBrief: '',\n preview: { ...DEFAULT_PREVIEW, env: {} },\n addedAt: Date.now(),\n };\n this.backend.setLocalPath(repo.fullName, folder);\n this.state.repos.push(repo);\n this.repoRt.set(repo.id, { issues: [], pulls: [], lastSync: null, syncing: false, cloneStatus: 'pending', lastMergedAt: null, folderSync: null, merging: false });\n this.save();\n this.emitRepo(repo);\n this.toast('success', `${repo.fullName} moved into floor ${floor}`);\n this.ensureQaTester(repo);\n void this.cloneRepo(repo.id);\n void this.syncRepo(repo.id);\n // The CEO studies every new floor and proposes the team it needs.\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\n return this.repoView(repo);\n }\n\n /** Where a GitHub repo's checkout goes when you connect it without picking a folder. */\n private async projectFolderFor(fullName: string): Promise<string> {\n const root = this.state.settings.projectsDir;\n const folders = await this.backend.scanProjects(root).catch(() => []);\n const match = folders.find((f) => f.github?.toLowerCase() === fullName.toLowerCase());\n if (match) return match.path;\n const name = fullName.split('/')[1];\n const taken = folders.find((f) => f.name.toLowerCase() === name.toLowerCase());\n if (taken) throw new HttpError(409, `${taken.path} already exists and isn't a clone of ${fullName}. Connect that folder instead, or rename it first.`);\n return path.join(root, name); // cloned there when the floor opens\n }\n\n /** A brand-new project: a folder in your projects folder, pushed to a new GitHub repo. */\n async createRepo(name: string, opts: FloorOptions & { description?: string; visibility: 'private' | 'public'; owner?: string }) {\n if (!/^[A-Za-z0-9._-]+$/.test(name)) throw new HttpError(400, 'Project names may only contain letters, numbers, \".\", \"-\" and \"_\"');\n const created = await this.backend.createProject(this.state.settings.projectsDir, name, opts).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n return this.connectRepo(created.fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: created.path });\n }\n\n /** The folders in your projects folder (or another folder you point at), and which are floors already. */\n async listProjectFolders(dir?: string): Promise<{ root: string; folders: ProjectFolderView[] }> {\n const root = dir?.trim() ? path.resolve(dir.trim()) : this.state.settings.projectsDir;\n const folders = await this.backend.scanProjects(root).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n const same = (a: string, b: string) => path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase();\n const floorOf = (f: { path: string; github: string | null }) =>\n this.state.repos.find((r) => (r.localPath && same(r.localPath, f.path)) || (f.github && r.id.toLowerCase() === f.github.toLowerCase()))?.floor ?? null;\n return { root, folders: folders.map((f) => ({ name: f.name, path: f.path, git: f.git, github: f.github, floor: floorOf(f) })) };\n }\n\n /** Give one of your folders a floor. It must already be on GitHub; otherwise publish it first. */\n async connectFolder(dir: string, opts: FloorOptions = {}) {\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n if (!f.github) throw new HttpError(400, `${f.name} ${f.git ? \"isn't on GitHub yet\" : \"isn't a git repository yet\"}. Publish it to GitHub first.`);\n return this.connectRepo(f.github, { ...opts, localPath: f.path });\n }\n\n /** Put one of your folders on GitHub (only what's committed goes up), then give it a floor. */\n async publishFolder(dir: string, opts: FloorOptions & { name?: string; visibility: 'private' | 'public'; description?: string }) {\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n const name = (opts.name?.trim() || f.name).replace(/[^A-Za-z0-9._-]+/g, '-');\n const fullName = await this.backend.publishFolder(f.path, { name, visibility: opts.visibility, description: opts.description }).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n return this.connectRepo(fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: f.path });\n }\n\n disconnectRepo(id: string) {\n const repo = this.repo(id);\n this.state.ceo.queue = this.state.ceo.queue.filter((j) => j.repoId !== id);\n for (const r of this.state.requests.filter((x) => x.repoId === id && x.status === 'pending')) {\n this.decide(r, { status: 'rejected', note: 'The floor was disconnected.', decidedBy: null });\n }\n for (const a of this.state.agents.filter((x) => x.repoId === id)) this.fireAgent(a.id, true);\n void this.previews.remove({ ...repo });\n this.state.repos = this.state.repos.filter((r) => r.id !== id);\n for (const q of this.state.qa.filter((x) => x.repoId === id)) this.broadcast({ type: 'qaRemoved', repoId: id, prNumber: q.prNumber });\n this.state.qa = this.state.qa.filter((q) => q.repoId !== id);\n for (const r of this.state.repos) r.links = r.links.filter((l) => l !== id);\n this.repoRt.delete(id);\n // Keep floors contiguous.\n this.state.repos.sort((a, b) => a.floor - b.floor).forEach((r, i) => (r.floor = i + 1));\n this.backend.setLocalPath(repo.fullName, null);\n this.save();\n this.broadcast({ type: 'repoRemoved', repoId: id });\n for (const r of this.state.repos) this.emitRepo(r);\n this.toast('info', repo.localPath ? `${repo.fullName} left the building. Your folder ${repo.localPath} is untouched.` : `${repo.fullName} disconnected (its clone stays on disk)`);\n }\n\n updateRepo(\n id: string,\n patch: Partial<Pick<PersistedRepo, 'autoAssign' | 'autoMerge' | 'browserTesting' | 'color' | 'links' | 'mission' | 'summary' | 'qaBrief'>> & { previewCommand?: unknown; previewEnv?: unknown },\n ) {\n const repo = this.repo(id);\n const preview = parsePreviewPatch(patch.previewCommand, patch.previewEnv);\n repo.preview = { ...repo.preview, ...preview };\n if (preview.command === null) void this.previews.refreshDefault(repo);\n if (patch.autoAssign !== undefined) repo.autoAssign = !!patch.autoAssign;\n if (patch.autoMerge !== undefined) {\n repo.autoMerge = !!patch.autoMerge;\n if (repo.autoMerge) void this.syncRepo(repo.id);\n }\n if (patch.browserTesting !== undefined) repo.browserTesting = !!patch.browserTesting;\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) repo.color = patch.color;\n if (Array.isArray(patch.links)) repo.links = patch.links.filter((l) => l !== id && this.state.repos.some((r) => r.id === l));\n if (typeof patch.mission === 'string') repo.mission = patch.mission.trim().slice(0, 4000);\n if (typeof patch.summary === 'string') repo.summary = patch.summary.trim().slice(0, 140);\n if (typeof patch.qaBrief === 'string') repo.qaBrief = patch.qaBrief.trim().slice(0, 2500);\n this.save();\n this.emitRepo(repo);\n setTimeout(() => this.schedule(), 200);\n return this.repoView(repo);\n }\n\n // ---------- auto-merge ----------\n\n /**\n * Auto-merge (floors with it on): a swarm PR merges itself once QA has signed off on its latest commit and GitHub's\n * checks are green. Failing checks and merge conflicts go back to a developer; new commits after QA's sign-off send\n * it back to QA. Merging deletes the remote branch, and the floor's folder then fast-forwards (syncRepo sees the merge).\n */\n private async advanceMerges(repo: PersistedRepo) {\n const rt = this.repoRt.get(repo.id);\n if (!rt || !repo.autoMerge || rt.merging) return;\n rt.merging = true;\n let merged = false;\n try {\n for (const rec of this.state.qa.filter((q) => q.repoId === repo.id && q.status === 'passed')) {\n const pr = rt.pulls.find((p) => p.number === rec.prNumber && p.state === 'OPEN');\n if (!pr || !pr.headRefName.startsWith('swarm/')) continue; // people's own PRs are theirs to merge\n // Only act on PR data fetched after the record last changed (a fix may have just pushed).\n if ((rt.fetchedAt ?? 0) < rec.updatedAt) continue;\n try {\n if (await this.advanceMerge(repo, rec, pr)) merged = true;\n } catch (err) {\n console.warn(`auto-merge of ${repo.fullName}#${pr.number} failed`, err);\n this.mergeNote(rec, `auto-merge hit a problem: ${oneLine(err)}`);\n }\n }\n } finally {\n rt.merging = false;\n }\n if (merged) {\n await this.syncRepo(repo.id);\n setTimeout(() => this.schedule(), 200);\n }\n }\n\n /** One step toward merging a QA-passed PR. Returns true when it merged. */\n private async advanceMerge(repo: PersistedRepo, rec: QaRecord, pr: PullInfo): Promise<boolean> {\n let step = mergeStep(pr, rec, Date.now(), { base: repo.defaultBranch });\n if (step.do === 'details') {\n // GitHub works mergeability out lazily and lists often say UNKNOWN; asking about the PR itself gets an answer.\n const d = await this.backend.prDetails(repo.fullName, pr.number);\n pr = { ...pr, headSha: d.headSha, mergeable: d.mergeable, mergeState: d.mergeState };\n step = mergeStep(pr, rec, Date.now(), { base: repo.defaultBranch, detailed: true });\n }\n Object.assign(rec, step.set);\n if (step.do === 'requeue') {\n // Commits arrived after QA's sign-off: they get tested too.\n this.setQa(rec, { status: 'queued', round: rec.round + 1, retests: rec.retests + 1, mergeNote: null, pendingSince: null });\n setTimeout(() => this.schedule(), 200);\n return false;\n }\n if (step.do === 'send-back') return this.sendBack(repo, rec, step.reason, step.instructions, step.needsHuman);\n if (step.do === 'wait') {\n if (step.alert) {\n this.postMessage('office', `\u23F3 PR #${pr.number} on ${repo.fullName} passed QA, but its checks (${pr.pendingChecks.join(', ')}) have been running for over ${CHECKS_ALERT_MS / 60_000} minutes. It merges as soon as they finish.`);\n }\n return step.note === undefined ? false : this.mergeNote(rec, step.note);\n }\n if (step.do === 'update-branch') {\n // The repo only merges up-to-date branches. GitHub merges the base in cleanly (or refuses); CI checks the result.\n this.mergeNote(rec, `updating the branch with ${repo.defaultBranch}`);\n await this.backend.updateBranch(repo.fullName, pr.number);\n const details = await this.backend.prDetails(repo.fullName, pr.number);\n this.setQa(rec, { passedSha: details.headSha });\n return false;\n }\n if (step.do !== 'merge') return false;\n this.mergeNote(rec, 'merging\u2026');\n let error = '';\n for (const method of ['squash', 'merge', 'rebase'] as const) {\n try {\n await this.backend.mergePull(repo.fullName, pr.number, method, rec.passedSha ?? pr.headSha);\n error = '';\n break;\n } catch (err) {\n error = oneLine(err).replace(/^gh .*? failed: /, '');\n if (!/not allowed/i.test(error)) break; // only a merge method the repo turned off is worth another try\n }\n }\n if (error && /head (branch|commit)/i.test(error)) return this.mergeNote(rec, 'new commits arrived; QA checks them first'); // the next sync re-queues it\n if (error) {\n rec.mergeRetryAt = Date.now() + MERGE_RETRY_MS;\n if (!rec.alerted) {\n rec.alerted = true;\n this.postMessage('office', `\u26A0\uFE0F PR #${pr.number} on ${repo.fullName} passed QA and its checks, but GitHub won't merge it: ${error}. The office retries every ${MERGE_RETRY_MS / 60_000} minutes; merge it yourself, or change the repo's merge rules, if it keeps failing.`);\n }\n return this.mergeNote(rec, `merge blocked: ${error}`);\n }\n this.toast('success', `\uD83D\uDD00 Merged PR #${pr.number} into ${repo.defaultBranch}: ${pr.title}`);\n await this.closeResolvedIssues(repo, pr.number, pr);\n return true;\n }\n\n /**\n * After the office merges a PR: close the issues it resolves now rather than waiting for GitHub's \"Closes #N\" (which\n * lags, and never comes when the link wasn't recognised), so the scheduler doesn't hand them out again. Never throws.\n */\n private async closeResolvedIssues(repo: PersistedRepo, prNumber: number, pr: Pick<PullInfo, 'headRefName' | 'closesIssues'>) {\n const numbers = issuesResolvedBy(pr);\n const rt = this.repoRt.get(repo.id);\n if (rt && rt.issues.some((i) => numbers.includes(i.number))) {\n rt.issues = rt.issues.filter((i) => !numbers.includes(i.number));\n this.emitRepo(repo);\n }\n for (const n of numbers) {\n try {\n if ((await this.backend.issueState(repo.fullName, n)) !== 'OPEN') continue;\n await this.backend.closeIssue(repo.fullName, n, `Shipped in #${prNumber}`);\n } catch (err) {\n console.warn(`could not close ${repo.fullName}#${n} after merging #${prNumber}`, err);\n }\n }\n }\n\n /** Show where auto-merge stands on a PR's card. Doesn't count as a change to the record. */\n private mergeNote(rec: QaRecord, text: string | null) {\n if (rec.mergeNote !== text) {\n rec.mergeNote = text;\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\n }\n return false;\n }\n\n /** QA passed, but the PR can't merge as it is: a developer fixes it, and QA re-tests if the code changed. */\n private sendBack(repo: PersistedRepo, rec: QaRecord, reason: 'checks' | 'conflict', fixInstructions: string, needsHuman: boolean) {\n if (needsHuman) {\n this.setQa(rec, { status: 'needs-human', mergeNote: null });\n this.postMessage('office', `\u26A0\uFE0F PR #${rec.prNumber} on ${repo.fullName} still ${reason === 'conflict' ? `conflicts with ${repo.defaultBranch}` : 'fails its checks'} after ${MAX_MERGE_FIXES} fixes, so it needs you.`);\n return false;\n }\n this.setQa(rec, { status: 'failed', fixReason: reason, fixInstructions, mergeFixes: rec.mergeFixes + 1, mergeNote: null, pendingSince: null });\n setTimeout(() => this.schedule(), 200);\n return false;\n }\n\n /** Fast-forward the floor's main checkout (usually your own project folder) and report how it stands. */\n private async syncFolder(repo: PersistedRepo) {\n const rt = this.repoRt.get(repo.id);\n if (!rt || rt.cloneStatus !== 'ready') return rt?.folderSync ?? null;\n const own = this.backend.office.isOwnFolder(this.backend.mainDir(repo.fullName)); // updating the running office restarts it mid-work\n const sync = await this.backend.syncMain(repo.fullName, repo.defaultBranch, { touch: !own }).catch((err) => ({ status: `sync failed: ${oneLine(err)}`, behind: 0, updatable: false }));\n const status = sync?.status ?? null;\n if (own && sync) this.setOfficeBehind(sync.updatable ? sync.behind : 0);\n if (!this.repoRt.has(repo.id)) return null;\n const before = rt.folderSync;\n rt.folderSync = status;\n this.emitRepo(repo);\n if (status && status !== before) {\n const name = repo.localPath ? path.basename(repo.localPath) : repo.fullName;\n if (status.startsWith('updated')) this.toast('success', `\uD83D\uDCC1 ${name}: ${status}`);\n else if (/behind|diverged|failed/.test(status)) this.toast('info', `\uD83D\uDCC1 ${name} wasn't updated: ${status}`);\n }\n return status;\n }\n\n /** The manager's \"Sync now\". */\n async syncFolderNow(repoId: string) {\n return { folderSync: await this.syncFolder(this.repo(repoId)) };\n }\n\n /** Remove the floor's desks, desk folders and swarm/qa branches nobody uses any more; say so when something went. */\n private async sweepFloor(repoId: string) {\n const repo = this.state.repos.find((r) => r.id === repoId);\n const rt = this.repoRt.get(repoId);\n if (!repo || !rt || rt.cloneStatus !== 'ready') return;\n try {\n const pulls = rt.lastSync ? rt.pulls : await this.backend.listPulls(repo.fullName);\n const agents = this.state.agents.filter((a) => a.repoId === repo.id);\n const keep = {\n desks: [...agents.map((a) => this.agentSlug(a)), PREVIEW_SLUG],\n branches: [...agents.flatMap((a) => (a.branch ? [a.branch] : [])), ...pulls.filter((p) => p.state === 'OPEN').map((p) => p.headRefName)],\n };\n const r = await this.backend.sweepDesks(repo.fullName, keep);\n const desks = r.desks + r.folders;\n const saved = r.patches.length ? ` (${r.patches.length} patch${r.patches.length === 1 ? '' : 'es'} saved to ${path.dirname(r.patches[0])})` : '';\n console.log(`desk sweep ${repo.fullName}: ${desks} desks, ${r.branches} branches removed${saved}${r.skipped.length ? `, ${r.skipped.length} still in use` : ''}`);\n if (!desks && !r.branches) return;\n const removed = [desks && `${desks} old desk${desks === 1 ? '' : 's'}`, r.branches && `${r.branches} finished branch${r.branches === 1 ? '' : 'es'}`].filter(Boolean).join(' and ');\n const text = `\uD83E\uDDF9 ${repo.fullName.split('/')[1]}: removed ${removed}${saved}`;\n this.toast('info', text);\n this.postMessage('office', text);\n } catch (err) {\n console.warn(`desk sweep ${repo.fullName} failed: ${oneLine(err)}`);\n }\n }\n\n // ---------- the floor's app (preview monitor) ----------\n\n /** Run the floor's app from its preview worktree: the default branch, or an open PR. Replaces what it is running now. */\n async startPreview(id: string, pr?: number | null): Promise<PreviewView> {\n const repo = this.repo(id);\n return this.previews.start(repo, `${repo.fullName.split('/')[1]} app`, pr);\n }\n\n stopPreview(id: string): Promise<PreviewView> {\n return this.previews.stop(this.repo(id));\n }\n\n /**\n * Server shutdown: stop every floor's app so nothing is left holding a preview port. Agents' CLIs keep working\n * through a restart (the terminal keeper holds them for the next start) and stop when the office quits.\n */\n async shutdown(restart = false): Promise<void> {\n await this.writeState().catch((err) => console.warn('could not save the state', err));\n await this.backend.releaseClis(restart); // before the terminals are saved: whatever they print next waits in the keeper\n await this.saveTerminals(true);\n await this.previews.stopAll(this.state.repos);\n }\n\n private async cloneRepo(id: string) {\n const repo = this.state.repos.find((r) => r.id === id);\n const rt = this.repoRt.get(id);\n if (!repo || !rt || rt.cloneStatus === 'cloning') return;\n rt.cloneStatus = 'cloning';\n rt.cloneError = undefined;\n this.emitRepo(repo);\n try {\n await this.backend.ensureClone(repo.fullName);\n rt.cloneStatus = 'ready';\n void this.previews.refreshDefault(repo);\n void this.sweepFloor(id);\n } catch (err) {\n rt.cloneStatus = 'error';\n rt.cloneError = (err as Error).message;\n this.toast('error', `Could not clone ${repo.fullName}: ${rt.cloneError}`);\n }\n if (this.repoRt.has(id)) this.emitRepo(repo);\n }\n\n async syncRepo(id: string) {\n const repo = this.state.repos.find((r) => r.id === id);\n const rt = this.repoRt.get(id);\n if (!repo || !rt || rt.syncing) return;\n rt.syncing = true;\n try {\n const started = Date.now();\n const [issues, pulls] = await Promise.all([this.backend.listIssues(repo.fullName), this.backend.listPulls(repo.fullName)]);\n rt.issues = issues;\n rt.pulls = pulls;\n rt.lastSync = Date.now();\n rt.fetchedAt = started;\n rt.syncError = undefined;\n this.reconcilePulls(repo, pulls);\n // Something was merged since the last look (by the office or anyone else): bring the folder up to date.\n const newest = pulls.reduce<string | null>((m, p) => (p.mergedAt && (!m || p.mergedAt > m) ? p.mergedAt : m), null);\n if (newest !== rt.lastMergedAt) {\n rt.lastMergedAt = newest;\n void this.syncFolder(repo);\n }\n void this.advanceMerges(repo);\n } catch (err) {\n rt.syncError = (err as Error).message;\n } finally {\n rt.syncing = false;\n }\n if (this.repoRt.has(id)) this.emitRepo(repo);\n }\n\n /** Keep agents and QA records in step with what happened to PRs on GitHub. */\n private reconcilePulls(repo: PersistedRepo, pulls: PullInfo[]) {\n for (const a of this.state.agents) {\n if (a.repoId !== repo.id || a.role !== 'dev' || a.prNumber == null || BUSY.includes(a.status) || a.status === 'idle') continue;\n const pr = pulls.find((p) => p.number === a.prNumber);\n if (!pr || pr.state === 'OPEN') continue;\n if (a.task === 'qa') {\n this.clearTask(a); // they only tested it\n continue;\n }\n this.appendLog(a, [{ kind: 'done', text: pr.state === 'MERGED' ? `\uD83C\uDF89 PR #${pr.number} was merged. Ready for the next issue.` : `PR #${pr.number} was closed without merging.` }]);\n this.clearTask(a);\n }\n\n // Finished PRs leave QA.\n for (const q of this.state.qa.filter((x) => x.repoId === repo.id)) {\n const pr = pulls.find((p) => p.number === q.prNumber);\n if (pr && pr.state !== 'OPEN' && q.status !== 'testing' && q.status !== 'fixing') {\n this.state.qa = this.state.qa.filter((x) => x !== q);\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: q.prNumber });\n }\n }\n\n // Every swarm PR goes through QA, including ones opened before QA existed or while the server was down.\n for (const pr of pulls) {\n if (pr.state !== 'OPEN' || pr.isDraft || !pr.headRefName.startsWith('swarm/')) continue;\n if (this.state.qa.some((q) => q.repoId === repo.id && q.prNumber === pr.number)) continue;\n const dev = this.state.agents.find((a) => a.repoId === repo.id && a.role === 'dev' && a.task !== 'qa' && (a.prNumber === pr.number || a.branch === pr.headRefName));\n this.queueQa(repo, pr.number, dev ?? null, pr.closesIssues[0] ?? null);\n }\n this.save();\n }\n\n async createIssue(repoId: string, title: string, body: string, assignTo?: string, specialty?: string) {\n const repo = this.repo(repoId);\n if (!title.trim()) throw new HttpError(400, 'An issue needs a title');\n const slug = specialtySlug(specialty);\n const number = await this.backend.createIssue(repo.fullName, title.trim(), body, slug ? [specialtyLabel(slug)] : []);\n await this.syncRepo(repo.id);\n this.toast('success', `Issue #${number} filed on ${repo.fullName}`);\n if (assignTo) await this.assign(assignTo, number);\n else setTimeout(() => this.schedule(), 200);\n return number;\n }\n\n async mergePull(repoId: string, number: number, method: 'squash' | 'merge' | 'rebase' = 'squash') {\n const repo = this.repo(repoId);\n const pr = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === number) ?? (await this.backend.prDetails(repo.fullName, number));\n await this.backend.mergePull(repo.fullName, number, method);\n this.toast('success', `Merged PR #${number} into ${repo.defaultBranch}`);\n await this.closeResolvedIssues(repo, number, pr);\n await this.syncRepo(repo.id);\n setTimeout(() => this.schedule(), 200);\n }\n\n async closePull(repoId: string, number: number) {\n const repo = this.repo(repoId);\n await this.backend.closePull(repo.fullName, number);\n await this.syncRepo(repo.id);\n }\n\n // ---------- agents ----------\n\n hireAgent(\n repoId: string,\n opts: {\n name?: string;\n model?: string;\n effort?: string;\n role?: string;\n look?: string;\n title?: string;\n specialty?: string;\n brief?: string;\n cli?: string;\n hiredBy?: 'manager' | 'ceo';\n appearance?: { color: string; hair: string; skin: string };\n },\n ) {\n const repo = this.repo(repoId);\n const role: AgentRole = opts.role === 'qa' ? 'qa' : 'dev';\n const used = new Set(this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).map((a) => a.desk));\n let desk = 0;\n while (used.has(desk)) desk++;\n if (desk >= MAX_DESKS[role]) {\n throw new HttpError(400, role === 'qa' ? `The QA lab on floor ${repo.floor} is full (${MAX_DESKS.qa} stations)` : `Floor ${repo.floor} is full (${MAX_DESKS.dev} desks)`);\n }\n const name = opts.name?.trim() || this.freeName(role);\n const agent: PersistedAgent = {\n id: crypto.randomUUID(),\n name,\n repoId: repo.id,\n role,\n title: String(opts.title ?? '').trim().slice(0, 60),\n specialty: specialtySlug(opts.specialty),\n brief: String(opts.brief ?? '').trim().slice(0, 2500),\n hiredBy: opts.hiredBy ?? 'manager',\n look: LOOKS.includes(opts.look as AgentLook) ? (opts.look as AgentLook) : lookFor(name),\n task: null,\n desk,\n color: opts.appearance?.color ?? pick(SHIRTS),\n hair: opts.appearance?.hair ?? pick(HAIR),\n skin: opts.appearance?.skin ?? pick(SKIN),\n model: opts.model ?? '',\n effort: EFFORTS.includes(opts.effort as EffortLevel) ? (opts.effort as EffortLevel) : '',\n cli: isCli(opts.cli) ? opts.cli : '',\n status: 'idle',\n issueNumber: null,\n issueTitle: null,\n branch: null,\n prNumber: null,\n prUrl: null,\n startedAt: null,\n endedAt: null,\n costUsd: 0,\n turns: 0,\n sessionId: null,\n sessionCli: null,\n lastError: null,\n logTail: [],\n };\n this.state.agents.push(agent);\n this.agentRt.set(agent.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [], terminal: null });\n this.appendLog(agent, [\n { kind: 'system', text: role === 'qa' ? `\uD83D\uDD0D ${name} joined the QA lab on floor ${repo.floor} (${repo.fullName}).` : `\uD83D\uDC4B ${name} joined floor ${repo.floor} (${repo.fullName}).` },\n ...(agent.title ? [{ kind: 'system' as const, text: `\uD83E\uDEAA ${agent.title}${agent.specialty ? ` \u00B7 takes swarm:${agent.specialty} issues first` : ''}` }] : []),\n ]);\n this.save();\n this.broadcast({ type: 'agent', agent: this.agentView(agent, false) });\n setTimeout(() => this.schedule(), 200);\n return this.agentView(agent, true);\n }\n\n /** Every floor has at least one QA tester. */\n private ensureQaTester(repo: PersistedRepo) {\n if (this.state.agents.some((a) => a.repoId === repo.id && a.role === 'qa')) return;\n this.hireAgent(repo.id, { role: 'qa' });\n }\n\n /** A name from the role's pool that no agent or pending candidate has. */\n private freeName(role: 'dev' | 'qa') {\n const taken = new Set([...this.state.agents.map((a) => a.name), ...this.state.requests.filter((r) => r.status === 'pending').map((r) => r.name)]);\n const pool = role === 'qa' ? QA_NAMES : DEV_NAMES;\n return pool.find((n) => !taken.has(n)) || `${role === 'qa' ? 'Tester' : 'Agent'} ${this.state.agents.length + 1}`;\n }\n\n updateAgent(\n id: string,\n patch: { name?: string; model?: string; effort?: string; cli?: string; look?: string; title?: string; specialty?: string; brief?: string; color?: string; hair?: string },\n ) {\n const a = this.agent(id);\n if (patch.cli !== undefined && a.role !== 'ceo') a.cli = isCli(patch.cli) ? patch.cli : '';\n if (patch.name?.trim() && patch.name.trim() !== a.name) {\n a.name = patch.name.trim().slice(0, 24);\n a.look = lookFor(a.name);\n }\n if (LOOKS.includes(patch.look as AgentLook)) a.look = patch.look as AgentLook;\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) a.color = patch.color;\n if (patch.hair && /^#[0-9a-f]{6}$/i.test(patch.hair)) a.hair = patch.hair;\n if (patch.model !== undefined) a.model = String(patch.model).trim();\n if (patch.effort !== undefined) a.effort = EFFORTS.includes(patch.effort as EffortLevel) ? (patch.effort as EffortLevel) : '';\n if (a.role !== 'ceo') {\n if (patch.title !== undefined) a.title = String(patch.title).trim().slice(0, 60);\n if (patch.specialty !== undefined) a.specialty = specialtySlug(patch.specialty);\n if (patch.brief !== undefined) a.brief = String(patch.brief).trim().slice(0, 2500);\n }\n this.save();\n this.emitAgent(a);\n }\n\n fireAgent(id: string, force = false) {\n const a = this.agent(id);\n if (a.role === 'ceo') throw new HttpError(409, `${a.name} runs the company and can't be let go.`);\n if (!force && a.role === 'qa' && this.state.agents.filter((x) => x.repoId === a.repoId && x.role === 'qa').length <= 1) {\n throw new HttpError(409, `${a.name} is the only QA tester on this floor, and every floor needs at least one.`);\n }\n for (const r of this.state.requests.filter((x) => x.kind === 'let-go' && x.agentId === id && x.status === 'pending')) {\n this.decide(r, { status: 'approved', note: 'They were let go directly.', decidedBy: 'manager' });\n }\n\n this.agentRt.get(id)?.session?.stop();\n this.agentRt.get(id)?.terminal?.releaseIdle?.();\n this.agentRt.get(id)?.terminal?.dispose();\n void removeScreens(id);\n void fs.rm(terminalFile(id), { force: true }).catch(() => undefined);\n for (const q of this.state.qa) {\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\n if (q.devAgentId === id) q.devAgentId = null;\n if (q.devAgentId === null && q.status === 'fixing') this.setQa(q, { status: 'failed' });\n }\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n if (repo) {\n const slug = this.agentSlug(a);\n const main = this.backend.mainDir(repo.fullName); // now: a disconnect points the floor elsewhere before this runs\n void this.backend\n .releaseDesk(repo.fullName, slug, this.port(a))\n .then(() => this.backend.removeDesk(repo.fullName, slug, main))\n .catch(() => undefined)\n .then(() => this.sweepFloor(repo.id));\n }\n this.state.agents = this.state.agents.filter((x) => x.id !== id);\n this.agentRt.delete(id);\n this.save();\n this.broadcast({ type: 'agentRemoved', agentId: id });\n }\n\n stopAgent(id: string) {\n const a = this.agent(id);\n if (!BUSY.includes(a.status)) return;\n a.status = 'stopped';\n a.lastError = 'Stopped by manager';\n this.appendLog(a, [{ kind: 'manager', text: '\u25A0 Manager stopped this session.' }]);\n this.agentRt.get(id)?.session?.stop();\n this.emitAgent(a);\n this.save();\n }\n\n /** An agent whose CLI kept working through the office's restart: the office follows its session again. */\n private reattachSession(a: PersistedAgent) {\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n if (!repo) return;\n this.appendLog(a, [{ kind: 'system', text: '\u21BB The office restarted; their CLI kept working and the office is following it again.' }]);\n this.startAgentSession(a, repo, this.backend.deskDir(repo.fullName, this.agentSlug(a)), '', '', a.sessionId ?? undefined, undefined, 'reattach');\n }\n\n /** The manager pressed Esc in the agent's terminal and the CLI stopped its turn: a Stop that leaves the CLI to them. */\n private interrupted(a: PersistedAgent) {\n if (!BUSY.includes(a.status)) return;\n a.status = 'stopped';\n a.lastError = 'Interrupted in the terminal';\n this.appendLog(a, [{ kind: 'manager', text: '\u25A0 Interrupted in the terminal. Type there to carry on.' }]);\n }\n\n resetAgent(id: string) {\n const a = this.agent(id);\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is busy; stop them first`);\n for (const q of this.state.qa) {\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\n if (q.devAgentId === id && q.status === 'fixing') this.setQa(q, { status: 'failed' });\n }\n this.agentRt.get(id)?.terminal?.releaseIdle?.();\n this.clearTask(a);\n this.appendLog(a, [{ kind: 'system', text: '\u21BA Cleared desk. Ready for new work.' }]);\n this.save();\n }\n\n private issueTaken(repo: PersistedRepo, n: number) {\n return issueTaken(\n n,\n this.state.agents.filter((a) => a.repoId === repo.id),\n this.repoRt.get(repo.id)?.pulls ?? [],\n Date.now(),\n );\n }\n\n private ensureSlot() {\n if (this.slotsFull()) {\n throw new HttpError(429, `All ${this.state.settings.sessionLimit} session slots are busy. Raise or clear the session limit in the manager's console, or wait.`);\n }\n }\n\n async assign(agentId: string, issueNumber: number, note?: string) {\n const a = this.agent(agentId);\n const repo = this.repo(a.repoId);\n if (a.role === 'qa') throw new HttpError(400, `${a.name} is a QA tester; they test pull requests rather than issues.`);\n if (a.role === 'ceo') throw new HttpError(400, `${a.name} runs the company; give issues to the developers.`);\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is already working on #${a.issueNumber}`);\n this.ensureSlot();\n const issue = this.repoRt.get(repo.id)?.issues.find((i) => i.number === issueNumber);\n if (!issue) throw new HttpError(404, `Issue #${issueNumber} is not open on ${repo.fullName}`);\n const holder = this.state.agents.find((x) => x.id !== a.id && x.repoId === repo.id && x.issueNumber === issueNumber && BUSY.includes(x.status));\n if (holder) throw new HttpError(409, `${holder.name} is already working on #${issueNumber}`);\n void this.runTask(a, repo, issue, note);\n return this.agentView(a, false);\n }\n\n private port(a: PersistedAgent) {\n return 5200 + (parseInt(a.id.slice(0, 4), 16) % 700);\n }\n\n private linkedRepos(repo: PersistedRepo) {\n return repo.links.map((id) => this.state.repos.find((r) => r.id === id)).filter((r): r is PersistedRepo => !!r);\n }\n\n /**\n * How an agent's next session runs: the CLI in their terminal (the terminal runtime), or Claude Code through the\n * SDK. A session can only be resumed by the CLI that made it, so a follow-up stays with that CLI.\n */\n private sessionRuntime(a: PersistedAgent, resume?: string): { terminal?: AgentTerminal; cli?: AgentCli; label?: string; resumeSessionId?: string } {\n const inTerminal = this.state.settings.runtime === 'terminal' && this.backend.terminals;\n let cli: AgentCli = a.role === 'ceo' ? 'claude' : a.cli || this.state.settings.defaultCli;\n if (resume && a.sessionCli && a.sessionCli !== cli) {\n if (inTerminal) cli = a.sessionCli;\n else if (a.sessionCli !== 'claude') resume = undefined;\n }\n if (!inTerminal) return { resumeSessionId: resume };\n const what = a.role === 'ceo' ? a.issueTitle : a.task === 'qa' ? `QA \u00B7 PR #${a.prNumber}` : a.task === 'fix' ? `fixing PR #${a.prNumber}` : a.issueNumber ? `#${a.issueNumber} ${a.issueTitle ?? ''}` : null;\n return { terminal: this.terminalFor(a), cli, label: `${a.name}${what ? ` \u00B7 ${what}` : ''}`.slice(0, 80).trim(), resumeSessionId: resume };\n }\n\n /** The model to ask for (the Agent SDK runs Claude Code). '' lets another coding agent use its own default. */\n private modelFor(a: PersistedAgent, cli: AgentCli | undefined) {\n return effectiveModel(a.model, cli ?? 'claude', this.state.settings, DEFAULT_MODEL);\n }\n\n // ---------- terminals ----------\n\n private async loadTerminal(agentId: string): Promise<AgentTerminal | null> {\n if (!(await fs.stat(terminalFile(agentId)).catch(() => null))) return null;\n const t = this.newTerminal(agentId);\n await t.load(terminalFile(agentId));\n return t;\n }\n\n /** The agent's terminal, made the first time they run in the terminal runtime. */\n private terminalFor(a: PersistedAgent): AgentTerminal {\n const rt = this.agentRt.get(a.id)!;\n rt.terminal ??= this.newTerminal(a.id);\n return rt.terminal;\n }\n\n private newTerminal(agentId: string) {\n const t = new AgentTerminal();\n // Typed at a CLI waiting at its prompt after its task: a follow-up, which starts synchronously when it can.\n t.onIdlePrompt = (text) => {\n void this.message(agentId, text, true).catch(() => undefined);\n return !!this.agentRt.get(agentId)?.session;\n };\n return t;\n }\n\n private async saveTerminals(all = false) {\n for (const [id, rt] of this.agentRt) {\n if (rt.terminal && (all || rt.terminal.dirty)) await rt.terminal.save(terminalFile(id)).catch((err) => console.warn('could not save a terminal', err));\n }\n }\n\n /** A browser opened an agent's terminal (/ws/term?agent=<id>). */\n attachTerminal(agentId: string, ws: WebSocket) {\n const t = this.agentRt.get(agentId)?.terminal;\n if (!t) return ws.close(4404, 'That agent has no terminal');\n t.attach(ws);\n }\n\n private buildSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, fixing?: { pr: number; headRef: string }) {\n return devSystemPrompt({ agent: a, repo, port: this.port(a), cwd, branch, linked: this.linkedDirs(repo), fixing });\n }\n\n private linkedDirs(repo: PersistedRepo) {\n return this.linkedRepos(repo).map((r) => ({ fullName: r.fullName, dir: this.backend.mainDir(r.fullName) }));\n }\n\n /** What an agent is told on a task, previewed with placeholders for the task's details. */\n agentPrompt(id: string): AgentPromptView {\n const a = this.agent(id);\n if (a.role === 'ceo') return ceoPromptPreview(ceoSystemPrompt(this.ceoPromptInput(a)));\n const repo = this.repo(a.repoId);\n const base = { agent: a, repo, port: this.port(a), slug: slugify(a.name) };\n return a.role === 'qa' ? qaPromptPreview(base) : devPromptPreview({ ...base, linked: this.linkedDirs(repo) });\n }\n\n private beginTask(a: PersistedAgent, patch: Partial<PersistedAgent>, banner: string, preparing: string) {\n const rt = this.agentRt.get(a.id)!;\n Object.assign(a, {\n status: 'preparing' as AgentStatus,\n startedAt: Date.now(),\n endedAt: null,\n costUsd: 0,\n turns: 0,\n lastError: null,\n ...patch,\n });\n rt.screenshot = null;\n rt.browserUrl = null;\n rt.shots = [];\n void removeScreens(a.id);\n this.appendLog(a, [\n { kind: 'system', text: '' },\n { kind: 'system', text: `\u2501\u2501\u2501 ${banner} \u2501\u2501\u2501` },\n { kind: 'system', text: preparing },\n ]);\n this.emitAgent(a);\n this.save();\n }\n\n private async prepare(a: PersistedAgent, repo: PersistedRepo, base: { pr?: number }, branch: string): Promise<string | null> {\n try {\n if (this.repoRt.get(repo.id)?.cloneStatus !== 'ready') await this.cloneRepo(repo.id);\n await this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a));\n const cwd = await this.backend.prepareDesk(repo.fullName, { defaultBranch: repo.defaultBranch, pr: base.pr }, this.agentSlug(a), branch);\n return a.status === 'preparing' ? cwd : null; // null: stopped or fired while preparing\n } catch (err) {\n if (a.status !== 'preparing') return null;\n a.status = 'error';\n a.endedAt = Date.now();\n a.lastError = (err as Error).message;\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n this.emitAgent(a);\n this.save();\n return null;\n }\n }\n\n private async runTask(a: PersistedAgent, repo: PersistedRepo, issue: IssueInfo, note?: string) {\n const branch = devBranch(issue.number, slugify(a.name));\n this.beginTask(\n a,\n { task: 'issue', issueNumber: issue.number, issueTitle: issue.title, branch, prNumber: null, prUrl: null, sessionId: null },\n `Issue #${issue.number}: ${issue.title}`,\n `Preparing worktree on ${branch}\u2026`,\n );\n const cwd = await this.prepare(a, repo, {}, branch);\n if (!cwd) return;\n\n const prompt = [\n `Please resolve GitHub issue #${issue.number}: ${issue.title}`,\n `URL: ${issue.url}`,\n issue.labels.length ? `Labels: ${issue.labels.join(', ')}` : '',\n '',\n issue.body?.trim() || '(The issue has no description.)',\n note ? `\\nNote from the manager: ${note}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\n this.startAgentSession(a, repo, cwd, prompt, this.buildSystemAppend(a, repo, cwd, branch));\n }\n\n private startAgentSession(\n a: PersistedAgent,\n repo: PersistedRepo,\n cwd: string,\n prompt: string,\n systemAppend: string,\n resumeSessionId?: string,\n outputSchema?: Record<string, unknown>,\n /** typed: the manager typed the prompt at the CLI; reattach: follow the CLI that kept working through a restart. */\n mode: 'typed' | 'reattach' | null = null,\n ) {\n const rt = this.agentRt.get(a.id)!;\n a.status = 'working';\n const how = this.sessionRuntime(a, resumeSessionId);\n this.emitAgent(a);\n rt.session = this.backend.startSession(\n {\n cwd,\n prompt,\n systemAppend,\n model: this.modelFor(a, how.cli),\n effort: a.effort || this.state.settings.defaultEffort,\n browserTesting: repo.browserTesting,\n additionalDirectories: this.linkedRepos(repo).map((r) => this.backend.mainDir(r.fullName)),\n role: a.task === 'qa' ? 'qa' : a.role, // a developer covering QA works under QA's rules\n outputSchema,\n // A developer's CLI stays at its prompt afterwards, for the manager and for follow-ups; QA's closes.\n keepAlive: a.task !== 'qa',\n typed: mode === 'typed',\n reattach: mode === 'reattach',\n agentId: a.id,\n ...how,\n },\n {\n log: (entries) => this.appendLog(a, entries),\n tool: (name) => {\n if (rt.currentTool === name) return;\n rt.currentTool = name;\n this.emitAgent(a);\n },\n sessionId: (id) => {\n a.sessionId = id;\n a.sessionCli = id ? (how.cli ?? 'claude') : null;\n },\n browserUrl: (url) => {\n rt.browserUrl = url;\n this.emitAgent(a);\n },\n screenshot: (data, mime) => {\n const at = Date.now();\n rt.screenshot = { data, mime, at };\n rt.shots.push({ data, mime, url: rt.browserUrl, at });\n if (rt.shots.length > 12) rt.shots.shift();\n this.broadcast({ type: 'screen', agentId: a.id, url: rt.browserUrl, at });\n void removeScreens(a.id)\n .then(() => fs.mkdir(SCREENS_DIR, { recursive: true }))\n .then(() => fs.writeFile(screenFile(a.id, mime), data))\n .catch((err) => console.warn('could not save screenshot', err));\n },\n limited: (at) => this.pauseForLimit(at),\n usageWarning: (info) => this.paceForWarning(info),\n finished: (result) => void this.onFinished(a, repo, result),\n },\n );\n }\n\n private async onFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const rt = this.agentRt.get(a.id);\n if (!rt || !this.state.agents.includes(a)) return; // fired\n if (this.officeUpdate.handedOver) return; // stopped for the office's update: recovered like after a restart\n rt.session = null;\n rt.currentTool = null;\n a.endedAt = Date.now();\n a.costUsd += result.costUsd;\n a.turns += result.turns;\n // Dev servers the agent forgot to stop would otherwise keep its port and lock its desk folder.\n void this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined);\n if (result.interrupted) this.interrupted(a);\n\n if (a.task === 'qa') await this.onQaFinished(a, repo, result);\n else if (a.task === 'fix') await this.onFixFinished(a, repo, result);\n else await this.onIssueFinished(a, repo, result);\n\n this.emitAgent(a);\n this.save();\n void this.syncRepo(repo.id);\n setTimeout(() => this.schedule(), 500);\n }\n\n private minutes(a: PersistedAgent) {\n return a.startedAt && a.endedAt ? Math.max(1, Math.round((a.endedAt - a.startedAt) / 60000)) : 0;\n }\n\n private fail(a: PersistedAgent, result: SessionResult, what: string) {\n a.status = 'error';\n a.lastError = result.errors.join('; ') || 'Session failed';\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n this.toast('error', `${a.name} hit a problem on ${what}: ${a.lastError.slice(0, 120)}`);\n }\n\n private async onIssueFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const escaped = repo.fullName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const m = result.text.match(new RegExp(`https://github\\\\.com/${escaped}/pull/(\\\\d+)`, 'i'));\n if (m) {\n a.prNumber = Number(m[1]);\n a.prUrl = m[0];\n } else if (a.branch) {\n const pr = await this.backend.prForBranch(repo.fullName, a.branch).catch(() => null);\n if (pr) {\n a.prNumber = pr.number;\n a.prUrl = pr.url;\n }\n }\n\n if (a.status === 'stopped') return; // the manager already logged the stop\n if (!result.ok) {\n this.issueFailed(repo, a.issueNumber);\n return this.fail(a, result, `#${a.issueNumber}`);\n }\n this.issueFailures.delete(`${repo.id}#${a.issueNumber}`);\n a.status = 'done';\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Finished in ${this.minutes(a)}m \u00B7 ${a.turns} turns${a.prNumber ? ` \u00B7 PR #${a.prNumber}` : ' \u00B7 no PR found'}` }]);\n if (a.prNumber) {\n this.queueQa(repo, a.prNumber, a, a.issueNumber);\n this.appendLog(a, [{ kind: 'system', text: `\uD83D\uDCE8 Handed PR #${a.prNumber} to QA.` }]);\n this.toast('success', `${a.name} opened PR #${a.prNumber} for #${a.issueNumber}; it's off to QA`);\n } else {\n this.noPullRequest(a, repo);\n }\n }\n\n /**\n * An issue session ended without a PR, which would leave the issue \"taken\" with nobody on it. The same developer,\n * who has the context and the worktree, is asked once to finish; after that the issue goes back on the board.\n */\n private noPullRequest(a: PersistedAgent, repo: PersistedRepo) {\n const key = `${repo.id}#${a.issueNumber}`;\n if (this.nudged.has(key)) return this.releaseIssue(a, repo);\n this.nudged.add(key);\n // message() starts the session before its first await, so the scheduler can't hand this developer other work first.\n void this.message(\n a.id,\n `You finished without opening a pull request for #${a.issueNumber}. Finish the remaining steps now: commit, push your branch and open the PR with \"Closes #${a.issueNumber}\". If the issue can't be done, open a draft PR that explains why.`,\n ).catch(() => this.releaseIssue(a, repo));\n }\n\n private releaseIssue(a: PersistedAgent, repo: PersistedRepo) {\n const n = a.issueNumber;\n this.clearTask(a);\n this.postMessage('office', `\u26A0\uFE0F ${a.name} finished #${n} on ${repo.fullName} without opening a pull request, so it's back on the board for anyone.`);\n }\n\n // ---------- QA ----------\n\n private queueQa(repo: PersistedRepo, prNumber: number, dev: PersistedAgent | null, issueNumber: number | null) {\n let rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\n if (rec) {\n if (rec.status === 'testing') return;\n this.setQa(rec, { status: 'queued', devAgentId: dev?.id ?? rec.devAgentId, devSessionId: dev?.sessionId ?? rec.devSessionId });\n } else {\n rec = {\n repoId: repo.id,\n prNumber,\n status: 'queued',\n round: 1,\n devAgentId: dev?.id ?? null,\n qaAgentId: null,\n summary: null,\n checks: [],\n commentUrl: null,\n updatedAt: Date.now(),\n issueNumber,\n devSessionId: dev && dev.prNumber === prNumber ? dev.sessionId : null,\n fixInstructions: null,\n sessionFailures: 0,\n mergeNote: null,\n testedSha: null,\n passedSha: null,\n fixReason: null,\n mergeFixes: 0,\n retests: 0,\n pendingSince: null,\n mergeRetryAt: null,\n alerted: false,\n };\n this.state.qa.push(rec);\n this.setQa(rec, {});\n }\n setTimeout(() => this.schedule(), 200);\n }\n\n /** Manager's \"send to QA\" for any open PR (including ones opened by people). */\n async sendToQa(repoId: string, prNumber: number) {\n const repo = this.repo(repoId);\n const pr = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === prNumber && p.state === 'OPEN');\n if (!pr) throw new HttpError(404, `PR #${prNumber} is not open on ${repo.fullName}`);\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\n if (rec?.status === 'testing' || rec?.status === 'fixing') throw new HttpError(409, `PR #${prNumber} is already ${rec.status}`);\n if (rec && (rec.status === 'needs-human' || rec.status === 'passed' || rec.status === 'failed')) {\n // a fresh start: the manager decided it deserves another round\n rec.round += 1;\n rec.sessionFailures = 0;\n rec.mergeNote = null;\n }\n const dev = this.state.agents.find((a) => a.repoId === repo.id && a.role === 'dev' && a.task !== 'qa' && (a.prNumber === prNumber || a.branch === pr.headRefName));\n this.queueQa(repo, prNumber, dev ?? null, pr.closesIssues[0] ?? null);\n this.toast('info', `PR #${prNumber} is queued for QA`);\n }\n\n private buildQaSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, pr: PrDetails) {\n return qaSystemPrompt({ agent: a, repo, port: this.port(a), cwd, branch, pr });\n }\n\n private async runQa(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\n const branch = qaBranch(rec.prNumber, slugify(a.name));\n this.setQa(rec, { status: 'testing', qaAgentId: a.id });\n this.beginTask(\n a,\n { task: 'qa', issueNumber: rec.issueNumber, issueTitle: `PR #${rec.prNumber}`, branch, prNumber: rec.prNumber, prUrl: null, sessionId: null },\n `QA \u00B7 PR #${rec.prNumber} \u00B7 round ${rec.round}`,\n `Checking out PR #${rec.prNumber}\u2026`,\n );\n\n let pr: PrDetails;\n let issue: { title: string; body: string } | null = null;\n try {\n pr = await this.backend.prDetails(repo.fullName, rec.prNumber);\n const issueNumber = rec.issueNumber ?? pr.closesIssues[0] ?? null;\n if (issueNumber) issue = await this.backend.issueDetails(repo.fullName, issueNumber).catch(() => null);\n Object.assign(a, { issueTitle: pr.title, prUrl: pr.url });\n rec.testedSha = pr.headSha;\n this.emitAgent(a);\n } catch (err) {\n a.status = 'error';\n a.endedAt = Date.now();\n a.lastError = (err as Error).message;\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n this.setQa(rec, { status: 'queued', qaAgentId: null });\n this.emitAgent(a);\n return;\n }\n if (pr.state !== 'OPEN') {\n this.appendLog(a, [{ kind: 'system', text: `PR #${pr.number} is ${pr.state.toLowerCase()}; nothing to test.` }]);\n this.state.qa = this.state.qa.filter((q) => q !== rec);\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: rec.prNumber });\n this.clearTask(a);\n return;\n }\n\n const cwd = await this.prepare(a, repo, { pr: rec.prNumber }, branch);\n if (!cwd) {\n if (this.state.qa.includes(rec) && rec.status === 'testing') this.setQa(rec, { status: 'queued', qaAgentId: null });\n return;\n }\n\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\n const prompt = [\n `Please QA pull request #${pr.number}: ${pr.title}`,\n `URL: ${pr.url}`,\n `Author: ${dev ? `${dev.name} (developer agent)` : 'a teammate'} \u00B7 QA round ${rec.round}`,\n rec.fixReason === 'conflict'\n ? `\\nQA passed it before, but since then the branch was updated with ${repo.defaultBranch} to resolve merge conflicts. Re-check everything, especially where this change meets the newly merged work.`\n : rec.fixReason === 'checks'\n ? '\\nQA passed it before, but since then the developer changed the code to fix failing GitHub checks. Re-check everything.'\n : rec.round > 1 && rec.summary\n ? `\\nThis is a re-test after fixes. Last round's findings:\\n${rec.summary}\\n${rec.fixInstructions ?? ''}\\nCheck those first, then re-check everything else.`\n : '',\n '',\n 'PR description:',\n pr.body.trim() || '(empty)',\n issue ? `\\nLinked issue: ${issue.title}\\n${issue.body.trim() || '(no description)'}` : '',\n ]\n .filter((l) => l !== '')\n .join('\\n');\n\n this.startAgentSession(a, repo, cwd, prompt, this.buildQaSystemAppend(a, repo, cwd, branch, pr), undefined, QA_SCHEMA);\n }\n\n private async onQaFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\n const rt = this.agentRt.get(a.id)!;\n const report = result.ok ? parseReport(result) : null;\n\n if (a.status === 'stopped' || !report) {\n if (a.status !== 'stopped') this.fail(a, { ...result, errors: result.errors.length ? result.errors : ['QA finished without a usable report'] }, `QA of PR #${a.prNumber}`);\n if (rec) {\n const failures = rec.sessionFailures + (this.limited() ? 0 : 1); // the usage limit isn't the PR's fault\n this.setQa(rec, {\n status: a.status === 'stopped' || failures >= 2 ? 'needs-human' : 'queued',\n qaAgentId: null,\n sessionFailures: failures,\n summary: a.status === 'stopped' ? 'QA was stopped by the manager.' : rec.summary,\n });\n }\n return;\n }\n\n a.status = 'done';\n const pass = report.verdict === 'pass';\n this.appendLog(a, [{ kind: pass ? 'done' : 'error', text: `${pass ? '\u2705 QA passed' : '\u274C QA failed'} PR #${a.prNumber} \u00B7 ${report.checks.length} checks \u00B7 ${rt.shots.length} screenshots` }]);\n\n // Evidence + comment on the PR\n let commentUrl: string | null = null;\n if (rec) {\n try {\n this.appendLog(a, [{ kind: 'system', text: '\uD83D\uDCCE Uploading evidence and posting the QA report on the PR\u2026' }]);\n const body = await this.renderQaComment(a, repo, rec, report, rt.shots);\n commentUrl = (await this.backend.commentPull(repo.fullName, rec.prNumber, body)) || null;\n this.appendLog(a, [{ kind: 'system', text: ` \u23BF ${commentUrl ?? 'comment posted'}` }]);\n } catch (err) {\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF Could not post the QA report: ${(err as Error).message}` }]);\n }\n const qaRounds = rec.round - rec.retests; // rounds QA itself asked for\n const nextStatus = pass ? 'passed' : qaRounds >= MAX_QA_ROUNDS ? 'needs-human' : 'failed';\n this.setQa(rec, {\n status: nextStatus,\n summary: report.summary,\n checks: report.checks,\n commentUrl: commentUrl ?? rec.commentUrl,\n fixInstructions: report.fixInstructions ?? report.checks.filter((c) => c.result === 'fail').map((c) => `${c.name}: ${c.details}`).join('\\n'),\n sessionFailures: 0,\n fixReason: pass ? null : 'qa',\n passedSha: pass ? rec.testedSha : null,\n mergeNote: null,\n pendingSince: null,\n mergeRetryAt: null,\n alerted: false,\n });\n this.toast(\n pass ? 'success' : 'error',\n pass\n ? `\u2705 ${a.name} passed PR #${rec.prNumber}${repo.autoMerge ? \"; it merges once GitHub's checks are green\" : ': ready to merge'}`\n : nextStatus === 'needs-human'\n ? `\u274C PR #${rec.prNumber} failed QA ${qaRounds} times and needs a human`\n : `\u274C ${a.name} failed PR #${rec.prNumber}; sending it back to the developer`,\n );\n }\n }\n\n private async renderQaComment(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord, report: QaReport, shots: Shot[]) {\n const pass = report.verdict === 'pass';\n const images: string[] = [];\n const evidence = shots.slice(-8);\n const offset = shots.length - evidence.length;\n const folder = `pr-${rec.prNumber}/round-${rec.round}-${Date.now().toString(36)}`;\n for (const [i, shot] of evidence.entries()) {\n const n = offset + i + 1;\n const ext = MIME_EXT[shot.mime] ?? 'png';\n const file = `${folder}/${String(n).padStart(2, '0')}.${ext}`;\n try {\n const url = await this.backend.uploadEvidence(repo.fullName, file, shot.data);\n const caption = report.screenshots[n - 1] ?? `Screenshot ${n}`;\n images.push(`**${n}. ${caption}**${shot.url ? ` \u00B7 \\`${shot.url}\\`` : ''}\\n\\n<img src=\"${url}\" alt=\"${caption.replace(/\"/g, \"'\")}\" width=\"760\">`);\n } catch (err) {\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF screenshot ${n} upload failed: ${(err as Error).message.slice(0, 120)}` }]);\n }\n }\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\n const lines = [\n `## \uD83D\uDD0D QA report: ${pass ? '\u2705 Passed' : '\u274C Failed'}`,\n `**Tester:** ${a.name} (cubefarm QA agent) \u00B7 **Round:** ${rec.round}${dev ? ` \u00B7 **Author:** ${dev.name}` : ''}`,\n '',\n report.summary,\n '',\n '| | Check | Details |',\n '|---|---|---|',\n ...report.checks.map((c) => `| ${ICON[c.result]} | ${cell(c.name)} | ${cell(c.details)} |`),\n ];\n if (report.commands.length) {\n lines.push('', '<details><summary>\uD83E\uDDEA Commands run</summary>', '', '| Command | Result |', '|---|---|', ...report.commands.map((c) => `| \\`${cell(c.command)}\\` | ${cell(c.result)} |`), '', '</details>');\n }\n if (!pass && report.fixInstructions) lines.push('', '### \uD83D\uDD27 What needs fixing', '', report.fixInstructions);\n if (images.length) lines.push('', '### \uD83D\uDCF8 Evidence', '', ...images.flatMap((img) => [img, '']));\n else lines.push('', '_No browser screenshots were taken in this round._');\n const merge = repo.autoMerge ? \"merges automatically once GitHub's checks pass\" : 'ready for the manager to merge';\n lines.push('', `<sub>Posted by cubefarm \u00B7 ${pass ? merge : rec.round - rec.retests >= MAX_QA_ROUNDS ? 'needs a human decision' : 'sent back to the developer for fixes'}</sub>`);\n return lines.join('\\n');\n }\n\n /** Send a failed PR back to the developer who wrote it (or any free developer on the floor). */\n private async runFix(dev: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\n const original = rec.devAgentId === dev.id;\n const pull = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === rec.prNumber);\n const headRef = pull?.headRefName ?? dev.branch ?? `pr-${rec.prNumber}`;\n const qaAgent = rec.qaAgentId ? this.state.agents.find((x) => x.id === rec.qaAgentId) : null;\n this.setQa(rec, { status: 'fixing', devAgentId: dev.id });\n this.beginTask(\n dev,\n // The session they held was another task's (QA, say); the author's own is resumed below, from rec.devSessionId.\n { task: 'fix', issueNumber: rec.issueNumber, issueTitle: pull?.title ?? `PR #${rec.prNumber}`, branch: headRef, prNumber: rec.prNumber, prUrl: pull?.url ?? null, sessionId: null },\n rec.fixReason === 'conflict' ? `Resolving conflicts on PR #${rec.prNumber}` : rec.fixReason === 'checks' ? `Fixing checks on PR #${rec.prNumber}` : `Fixing PR #${rec.prNumber} after QA round ${rec.round}`,\n `Checking out PR #${rec.prNumber}\u2026`,\n );\n const cwd = await this.prepare(dev, repo, { pr: rec.prNumber }, headRef);\n if (!cwd) {\n if (rec.status === 'fixing') this.setQa(rec, { status: 'failed' });\n return;\n }\n const failed = rec.checks.filter((c) => c.result === 'fail');\n const takeover = original ? '' : ' A teammate wrote it, so read the PR and the linked issue first.';\n const push = `push to the same branch: git push origin HEAD:${headRef}`;\n const mergeFix =\n rec.fixReason === 'conflict'\n ? [\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but it now conflicts with ${repo.defaultBranch} because other work was merged first.${takeover}`,\n '',\n `Bring it up to date: git fetch origin && git merge origin/${repo.defaultBranch}. Resolve the conflicts so both this change and the newly merged work keep working, run the project's checks, and ${push}`,\n ]\n : rec.fixReason === 'checks'\n ? [\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but GitHub checks failed on it.${takeover}`,\n '',\n `Failed checks:\\n${rec.fixInstructions ?? ''}`,\n '',\n `Read the logs with gh pr checks ${rec.prNumber} -R ${repo.fullName} (for GitHub Actions: gh run view <run id> -R ${repo.fullName} --log-failed). Fix the cause, run the same checks locally where you can, and ${push}`,\n `If a failure clearly has nothing to do with this change (a flaky test or a service outage), re-run it instead with gh run rerun <run id> -R ${repo.fullName} --failed, and say so.`,\n ]\n : null;\n const qaFix = [\n original\n ? `QA tester ${qaAgent?.name ?? 'QA'} tested your pull request #${rec.prNumber} and it FAILED (round ${rec.round}).`\n : `You are taking over pull request #${rec.prNumber} (${pull?.url ?? ''}), written by a teammate, because QA failed it (round ${rec.round}). Read the PR and the linked issue first.`,\n '',\n `QA summary: ${rec.summary ?? ''}`,\n failed.length ? `Failed checks:\\n${failed.map((c) => `- ${c.name}: ${c.details}`).join('\\n')}` : '',\n rec.fixInstructions ? `\\nWhat needs fixing:\\n${rec.fixInstructions}` : '',\n rec.commentUrl ? `\\nFull report with screenshots: ${rec.commentUrl}` : '',\n '',\n `Fix these problems, re-run the relevant checks, and push to the same branch: git push origin HEAD:${headRef}`,\n 'Then reply with a short summary of what you changed. Do not open a new pull request; QA will re-test automatically.',\n ];\n const mergeEnd = 'Then reply with a short summary of what you did. Do not open a new pull request; the office merges it once the checks pass, after another QA round if the code changed.';\n const prompt = (mergeFix ? [...mergeFix, '', mergeEnd] : qaFix).filter((l) => l !== '').join('\\n');\n const resume = original && rec.devSessionId ? rec.devSessionId : undefined;\n this.startAgentSession(dev, repo, cwd, prompt, this.buildSystemAppend(dev, repo, cwd, headRef, { pr: rec.prNumber, headRef }), resume);\n }\n\n private async onFixFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\n // Did it push anything? A checks fix may only re-run a flaky check, so only QA and conflict fixes are asked.\n const head = rec && result.ok && a.status !== 'stopped' && rec.fixReason !== 'checks' ? await this.prHead(a, repo, rec.prNumber) : null;\n if (a.status === 'stopped') {\n if (rec?.status === 'fixing') this.setQa(rec, { status: 'failed' });\n return;\n }\n if (!result.ok) {\n this.fail(a, result, `the fix for PR #${a.prNumber}`);\n // Someone else gets a go before it lands on the manager.\n const failures = rec ? rec.sessionFailures + (this.limited() ? 0 : 1) : 0;\n if (rec) this.setQa(rec, { status: failures >= 2 ? 'needs-human' : 'failed', sessionFailures: failures });\n return;\n }\n if (!rec || !this.state.qa.includes(rec)) {\n a.status = 'done';\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Fix pushed for PR #${a.prNumber} in ${this.minutes(a)}m. Back to QA.` }]);\n return;\n }\n const step = fixOutcome(rec, head, this.minutes(a), !this.limited());\n if (!step.pushed) {\n // Like a failed session: someone gets another go, with the same instructions, before it lands on the manager.\n const needsHuman = step.set.status === 'needs-human';\n a.status = 'error';\n a.lastError = `No new commits were pushed for PR #${rec.prNumber}`;\n this.appendLog(a, [step.log]);\n this.setQa(rec, step.set);\n this.toast('error', `${a.name} ended the fix for PR #${rec.prNumber} without pushing a commit${needsHuman ? '; it needs you' : '; it goes back for another try'}`);\n if (needsHuman) {\n this.postMessage('office', `\u26A0\uFE0F PR #${rec.prNumber} on ${repo.fullName} went back for fixes, but ${step.set.sessionFailures} fix sessions in a row ended without pushing a commit, so it needs you.`);\n }\n return;\n }\n a.status = 'done';\n this.appendLog(a, [step.log]);\n this.setQa(rec, { ...step.set, devSessionId: a.sessionId ?? rec.devSessionId });\n this.toast(\n 'info',\n step.set.status === 'passed' ? `${a.name} fixed PR #${rec.prNumber}; it merges once it passes again` : `${a.name} pushed fixes for PR #${rec.prNumber}; QA round ${rec.round} is queued`,\n );\n }\n\n /** The PR's head commit now; null (with a warning in the agent's log) when GitHub can't be asked. */\n private async prHead(a: PersistedAgent, repo: PersistedRepo, prNumber: number): Promise<string | null> {\n try {\n return (await this.backend.prDetails(repo.fullName, prNumber)).headSha;\n } catch (err) {\n console.warn(`could not read the head of ${repo.fullName}#${prNumber}`, err);\n this.appendLog(a, [{ kind: 'system', text: `\u26A0 Could not check PR #${prNumber} for new commits (${oneLine(err)}); taking the fix at its word.` }]);\n return null;\n }\n }\n\n /** A message for an agent: sent into their running session, or a follow-up that resumes it. typed: the manager typed it at their CLI's prompt, where it's already running. */\n async message(id: string, text: string, typed = false) {\n const a = this.agent(id);\n if (a.role === 'ceo') return this.messageCeo(text);\n const repo = this.repo(a.repoId);\n if (!text.trim()) throw new HttpError(400, 'Empty message');\n const rt = this.agentRt.get(id)!;\n if (rt.session) {\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\n if (!typed) rt.session.send(text);\n return;\n }\n if (a.role === 'qa') throw new HttpError(409, `${a.name} isn't testing anything right now. Send a PR to QA from the Kanban board.`);\n if (a.status === 'preparing') throw new HttpError(409, `${a.name} is still setting up; try again in a moment`);\n if (!a.sessionId || !a.branch || a.task === 'qa') throw new HttpError(409, `${a.name} has no session to continue. Assign an issue instead.`);\n this.ensureSlot();\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\n const cwd = this.backend.deskDir(repo.fullName, this.agentSlug(a));\n a.lastError = null;\n a.startedAt = Date.now();\n if (a.task === null) a.task = 'issue';\n const fixing = a.task === 'fix' && a.prNumber ? { pr: a.prNumber, headRef: a.branch } : undefined;\n this.startAgentSession(a, repo, cwd, text, this.buildSystemAppend(a, repo, cwd, a.branch, fixing), a.sessionId, undefined, typed ? 'typed' : null);\n }\n\n updateSettings(patch: Partial<SwarmSettings>) {\n const s = this.state.settings;\n if (patch.sessionLimit !== undefined) s.sessionLimit = Math.max(0, Math.round(Number(patch.sessionLimit)) || 0);\n // The default model belongs to the default coding agent: a new agent starts on its own default.\n if (isCli(patch.defaultCli) && patch.defaultCli !== s.defaultCli) {\n s.defaultCli = patch.defaultCli;\n if (patch.defaultModel === undefined) s.defaultModel = s.defaultCli === 'claude' ? DEFAULT_MODEL : '';\n }\n if (patch.defaultModel !== undefined) s.defaultModel = String(patch.defaultModel).trim() || (s.defaultCli === 'claude' ? DEFAULT_MODEL : '');\n if (patch.defaultEffort !== undefined && EFFORTS.includes(patch.defaultEffort)) s.defaultEffort = patch.defaultEffort;\n if (patch.runtime === 'terminal' || patch.runtime === 'sdk') s.runtime = patch.runtime;\n if (patch.hiring === 'approve' || patch.hiring === 'auto') s.hiring = patch.hiring;\n if (patch.teamCap !== undefined) s.teamCap = Math.max(1, Math.min(15, Math.round(Number(patch.teamCap)) || 1));\n if (patch.ceoHeartbeatMin !== undefined) s.ceoHeartbeatMin = Math.max(0, Math.min(1440, Math.round(Number(patch.ceoHeartbeatMin)) || 0));\n if (typeof patch.managerName === 'string') s.managerName = patch.managerName.trim().slice(0, 40);\n if (typeof patch.companyName === 'string') s.companyName = patch.companyName.trim().slice(0, 60);\n if (typeof patch.projectsDir === 'string' && patch.projectsDir.trim()) s.projectsDir = path.resolve(patch.projectsDir.trim());\n if (typeof patch.setupDone === 'boolean') s.setupDone = patch.setupDone;\n if (patch.tutorialStep !== undefined) s.tutorialStep = Math.max(-1, Math.round(Number(patch.tutorialStep)) || 0);\n if (typeof patch.autoUpdate === 'boolean') s.autoUpdate = patch.autoUpdate;\n if (patch.pacingSessions !== undefined) s.pacingSessions = clampPacingSessions(patch.pacingSessions);\n this.save();\n this.broadcast({ type: 'settings', settings: s });\n this.emitCeo();\n setTimeout(() => this.schedule(), 200);\n return s;\n }\n\n /** The setup wizard: who you are, the company, and your CEO. */\n setup(x: { managerName?: string; companyName?: string; hiring?: string; ceoName?: string; ceoLook?: string; ceoColor?: string }) {\n this.updateSettings({\n managerName: x.managerName,\n companyName: x.companyName,\n ...(x.hiring === 'auto' || x.hiring === 'approve' ? { hiring: x.hiring } : {}),\n });\n const ceo = this.ceo();\n this.updateAgent(ceo.id, { name: x.ceoName, color: x.ceoColor });\n if (LOOKS.includes(x.ceoLook as AgentLook)) this.updateAgent(ceo.id, { look: x.ceoLook });\n return this.state.settings;\n }\n\n // ---------- scheduling ----------\n\n /**\n * Agents on a floor who can take work now. One whose last session failed sits out a short cooldown, then gets work\n * like everyone else instead of waiting for the manager to reset them.\n */\n private available(repo: PersistedRepo, role: AgentRole) {\n const now = Date.now();\n return this.state.agents\n .filter((a) => a.repoId === repo.id && a.role === role && (FREE.includes(a.status) || (a.status === 'error' && now - (a.endedAt ?? 0) >= ERROR_COOLDOWN_MS)))\n .sort((x, y) => x.desk - y.desk);\n }\n\n private scheduleOffset = 0;\n private issueFailures = new Map<string, number>(); // `${repoId}#${issue}` \u2192 failed sessions on it\n private nudged = new Set<string>(); // `${repoId}#${issue}`: its developer was asked once to finish the missing PR\n private pausedUntil = 0; // Claude's usage limit was hit: nothing new starts before this\n private pacingUntil = 0; // Claude warned about usage: new issues are paced until this\n private lastUsage = '';\n\n /** Backlog issues that can start now, most urgent first: the ones holding up the longest chain of other issues, then the oldest. */\n private readyIssues(repo: PersistedRepo) {\n const issues = this.repoRt.get(repo.id)!.issues;\n const open = new Set(issues.map((i) => i.number));\n const weight = holdUps(issues);\n return issues\n .filter(\n (i) =>\n !i.labels.some((l) => /^(swarm:skip|wontfix|question)$/i.test(l)) &&\n !this.issueTaken(repo, i.number) &&\n blockers(i.body, open).length === 0 &&\n (this.issueFailures.get(`${repo.id}#${i.number}`) ?? 0) < MAX_ISSUE_FAILURES,\n )\n .map((issue) => ({ issue, want: issueSpecialty(issue.labels), ...weight.get(issue.number)! }))\n .sort((x, y) => y.chain - x.chain || y.waiting - x.waiting || x.issue.number - y.issue.number);\n }\n\n /**\n * The free developer to put on a job: one it `suits` first, then whoever is least needed elsewhere (fewest ready\n * issues in their specialty, then the least open work in it), so specialists stay free for their own lane.\n */\n private pickDev(repo: PersistedRepo, devs: PersistedAgent[], suits: (a: PersistedAgent) => boolean) {\n if (devs.length <= 1) return devs[0];\n const ready = this.readyIssues(repo).map((r) => r.want);\n const open = this.repoRt.get(repo.id)!.issues.map((i) => issueSpecialty(i.labels));\n const rank = (a: PersistedAgent) => {\n const s = a.specialty.toLowerCase();\n return [suits(a) ? 0 : 1, ready.filter((w) => w === s).length, open.filter((w) => w === s).length, a.desk];\n };\n return devs\n .map((a) => ({ a, r: rank(a) }))\n .sort((x, y) => x.r[0] - y.r[0] || x.r[1] - y.r[1] || x.r[2] - y.r[2] || x.r[3] - y.r[3])[0].a;\n }\n\n /**\n * Finish work in flight: test queued PRs (oldest first) and get failed ones fixed. Returns true if work started.\n * QA testers test; when they're all busy, a free developer who didn't write the PR covers for them, so QA never\n * holds up the floor. A failed PR goes back to its author when they're free, and otherwise to any free developer.\n */\n private startPipelineWork(repo: PersistedRepo): boolean {\n const devs = this.available(repo, 'dev');\n const testers = this.available(repo, 'qa');\n const waiting = (status: QaRecord['status']) => this.state.qa.filter((q) => q.repoId === repo.id && q.status === status).sort((x, y) => x.updatedAt - y.updatedAt);\n for (const rec of waiting('queued')) {\n const tester =\n testers[0] ??\n this.pickDev(\n repo,\n devs.filter((a) => a.id !== rec.devAgentId),\n (a) => /test|qa/i.test(a.specialty),\n );\n if (!tester) continue;\n void this.runQa(tester, repo, rec);\n return true;\n }\n for (const rec of waiting('failed')) {\n const issue = this.repoRt.get(repo.id)!.issues.find((i) => i.number === rec.issueNumber);\n const want = issue ? issueSpecialty(issue.labels) : null;\n const dev = devs.find((a) => a.id === rec.devAgentId) ?? this.pickDev(repo, devs, (a) => a.specialty.toLowerCase() === want);\n if (!dev) break;\n void this.runFix(dev, repo, rec);\n return true;\n }\n return false;\n }\n\n /**\n * Give a free developer the next backlog issue (auto-assign floors only). Returns true if work started.\n * Issues that say \"Depends on #N\" wait until #N is closed; the rest go in readyIssues() order. A swarm:<specialty>\n * label is a preference, not a lock: a free specialist gets first pick, and otherwise the issue goes to whichever\n * free developer is least needed elsewhere, so nobody sits idle while there is work that can start.\n */\n private startIssueWork(repo: PersistedRepo): boolean {\n if (!repo.autoAssign || !this.mayStart('issue')) return false;\n const free = this.available(repo, 'dev');\n const ready = free.length ? this.readyIssues(repo) : [];\n if (ready.length === 0) return false;\n const fits = (a: PersistedAgent, want: string) => a.specialty.toLowerCase() === want;\n // Of the issues holding up the most, take one a free specialist fits.\n const pick = ready.find((r) => r.chain === ready[0].chain && free.some((a) => fits(a, r.want))) ?? ready[0];\n const agent = this.pickDev(repo, free, (a) => fits(a, pick.want))!;\n // assign() flips the agent to 'preparing' synchronously, so the next pass sees it as busy.\n void this.assign(agent.id, pick.issue.number).catch((err) => console.warn('auto-assign failed', err));\n return agent.status === 'preparing';\n }\n\n private limited() {\n return Date.now() < this.pausedUntil;\n }\n\n /** Claude turned a session away for the usage limit: start nothing new until it resets, rather than failing agent after agent. */\n private pauseForLimit(resetsAt: number | null) {\n const until = (resetsAt ?? Date.now() + LIMIT_PAUSE_MS) + 30_000;\n if (until <= this.pausedUntil) return;\n const fresh = Date.now() >= this.pausedUntil;\n this.pausedUntil = until;\n if (fresh) this.postMessage('office', `\u23F8 Claude's usage limit was reached. The office starts no new work until ${new Date(until).toLocaleTimeString()}; sessions already running carry on.`);\n this.emitUsage();\n }\n\n /** Claude warned that usage is getting high: pace new issues until the window resets, rather than run into the limit. */\n private paceForWarning(info: UsageWarning) {\n const now = Date.now();\n const until = info.resetsAt && info.resetsAt > now ? info.resetsAt : now + PACING_MS;\n if (until <= this.pacingUntil) return;\n const fresh = now >= this.pacingUntil;\n this.pacingUntil = until;\n if (fresh) this.postMessage('office', pacingMessage(info, until, this.state.settings.pacingSessions, now));\n this.emitUsage();\n }\n\n /** May work of this kind start now, as far as Claude's usage goes? */\n private mayStart(kind: WorkKind) {\n return mayStart(kind, { now: Date.now(), pausedUntil: this.pausedUntil, pacingUntil: this.pacingUntil, running: this.running(), pacingSessions: this.state.settings.pacingSessions });\n }\n\n private usageNow() {\n return usageView({ now: Date.now(), pausedUntil: this.pausedUntil, pacingUntil: this.pacingUntil });\n }\n\n private emitUsage() {\n const usage = this.usageNow();\n const key = JSON.stringify(usage);\n if (key === this.lastUsage) return;\n this.lastUsage = key;\n this.broadcast({ type: 'usage', usage });\n }\n\n /** Pacing and pauses run out on their own: say so when pacing ends. */\n private tickUsage() {\n if (this.pacingUntil && Date.now() >= this.pacingUntil) {\n this.pacingUntil = 0;\n this.postMessage('office', \"\u2705 Claude's usage is back to normal. The office starts new work at full speed again.\");\n }\n this.emitUsage();\n }\n\n /** A failed session releases its issue for someone else; an issue that keeps failing waits for the manager. */\n private issueFailed(repo: PersistedRepo, n: number | null) {\n if (n == null || this.limited()) return; // the usage limit isn't the issue's fault\n const key = `${repo.id}#${n}`;\n const failures = (this.issueFailures.get(key) ?? 0) + 1;\n this.issueFailures.set(key, failures);\n if (failures === MAX_ISSUE_FAILURES) {\n this.postMessage('office', `\u26A0\uFE0F Issue #${n} on ${repo.fullName} failed ${failures} sessions in a row, so auto-assign skips it now. Assign it to someone by hand once it's sorted.`);\n }\n }\n\n /**\n * Hand out work for free session slots. Finishing beats starting: QA and QA fixes on every floor go before any new issue.\n * Within each phase floors take turns (one job per floor per pass), and the starting floor rotates between calls,\n * so no repo can hog the slots.\n */\n private schedule() {\n this.tickUsage();\n if (this.officeUpdateTick()) return; // draining for the office's own update\n if (this.limited()) return;\n // Management first: the CEO's jobs are short and shape everyone else's work.\n this.maybeHeartbeat();\n this.startCeoWork();\n const repos = this.state.repos.filter((r) => {\n const rt = this.repoRt.get(r.id);\n return rt && rt.lastSync != null && rt.cloneStatus !== 'error';\n });\n if (repos.length === 0) return;\n this.scheduleOffset = (this.scheduleOffset + 1) % repos.length;\n const order = [...repos.slice(this.scheduleOffset), ...repos.slice(0, this.scheduleOffset)];\n for (const start of [(r: PersistedRepo) => this.startPipelineWork(r), (r: PersistedRepo) => this.startIssueWork(r)]) {\n let progress = true;\n while (progress) {\n progress = false;\n for (const repo of order) {\n if (this.slotsFull()) return;\n if (start(repo)) progress = true;\n }\n }\n }\n }\n\n // ---------- the office's own update ----------\n\n private drainInput(): DrainInput {\n const u = this.officeUpdate;\n return {\n now: Date.now(),\n behind: this.officeHead ? u.behind : 0,\n launcher: this.backend.office.launcher,\n autoUpdate: this.state.settings.autoUpdate !== false,\n requested: u.requested,\n postponedUntil: u.postponedUntil,\n postponedBehind: u.postponedBehind,\n failed: u.failed,\n failedBehind: u.failedBehind,\n drainingSince: u.drainingSince,\n sent: u.sent,\n running: this.running(),\n };\n }\n\n private officeUpdateView(): OfficeUpdateView {\n const u = this.officeUpdate;\n const input = this.drainInput();\n const d = drainDecision(input);\n const until = u.postponedUntil ? new Date(u.postponedUntil).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : '';\n const detail = d.state === 'failed' ? u.failed : d.state === 'waiting' ? `Postponed until ${until}, or until a newer commit lands.` : null;\n return { state: d.state, behind: input.behind, launcher: input.launcher, drainingSince: u.drainingSince ?? d.drainingSince, running: input.running, detail };\n }\n\n private emitOfficeUpdate() {\n if (!this.officeHead) return;\n const view = this.officeUpdateView();\n const key = JSON.stringify(view);\n if (key === this.lastOfficeView) return;\n this.lastOfficeView = key;\n this.broadcast({ type: 'officeUpdate', officeUpdate: view });\n }\n\n /** The own-folder check found the office this many commits behind GitHub. */\n private setOfficeBehind(behind: number) {\n const u = this.officeUpdate;\n if (u.failed && u.failedBehind === null) u.failedBehind = behind; // only a newer commit retries a failed update by itself\n u.behind = behind;\n if (behind === 0) Object.assign(u, { requested: false, failed: null, failedBehind: null });\n this.officeUpdateTick();\n }\n\n /**\n * Take the office's own update one step (see drainDecision): drain, and once nothing is running, or the drain timed\n * out, hand it to the launcher. True while nothing new may start.\n */\n private officeUpdateTick(): boolean {\n if (!this.officeHead) return false;\n const u = this.officeUpdate;\n const d = drainDecision(this.drainInput());\n if (d.state === 'draining' && u.drainingSince === null) {\n const running = this.running();\n this.postMessage(\n 'office',\n `\u2B06\uFE0F Updating the office (${u.behind} new commit${u.behind === 1 ? '' : 's'}). Nothing new starts${running ? ` while ${running} running session${running === 1 ? '' : 's'} finish` : ''}; then it installs and restarts.`,\n );\n }\n u.drainingSince = d.drainingSince;\n if (d.send) void this.handOver(d.timedOut);\n this.emitOfficeUpdate();\n return d.state === 'draining' || d.state === 'updating';\n }\n\n /** Drained: hand the update to the launcher. Sessions still running after the timeout stop the way a restart stops them. */\n private async handOver(timedOut: boolean) {\n const u = this.officeUpdate;\n const from = this.officeHead!;\n u.sent = true;\n const busy = this.state.agents.filter((a) => BUSY.includes(a.status));\n if (timedOut) this.postMessage('office', `\u23F1 ${busy.length} session${busy.length === 1 ? ' was' : 's were'} still running after 20 minutes. Stopped; the work goes back to the queue after the update.`);\n this.emitOfficeUpdate();\n u.handedOver = true;\n await this.writeState().catch((err) => console.warn('could not save the state', err)); // still \"working\": the restarted office recovers them\n for (const a of busy) this.agentRt.get(a.id)?.session?.stop();\n try {\n const result = await this.backend.office.update(from);\n if (result) await this.afterUpdate(result); // the demo: nothing restarts\n } catch (err) {\n await this.afterUpdate({ from, to: from, ok: false, error: `the launcher didn't take the update: ${oneLine(err)}`, installed: false, built: false, at: Date.now() });\n }\n }\n\n /** An update that didn't restart the office (the demo, or a failed hand-over): recover like a restart would, then report it. */\n private async afterUpdate(result: LastUpdate) {\n const u = this.officeUpdate;\n Object.assign(u, { sent: false, handedOver: false, requested: false, drainingSince: null });\n const interrupted = this.state.agents.filter((a) => BUSY.includes(a.status));\n const preparing = new Set(interrupted.filter((a) => a.status === 'preparing'));\n for (const a of interrupted) {\n Object.assign(a, { status: 'stopped', lastError: 'The office updated itself while this agent was working.' });\n const rt = this.agentRt.get(a.id);\n if (rt) Object.assign(rt, { session: null, currentTool: null });\n }\n this.ensureCeo(interrupted);\n this.recover(interrupted, preparing);\n interrupted.forEach((a) => this.emitAgent(a));\n await this.reportUpdate(result);\n if (!result.ok) u.failedBehind = u.behind;\n const own = this.state.repos.find((r) => this.backend.office.isOwnFolder(this.backend.mainDir(r.fullName)));\n if (own) await this.syncFolder(own);\n this.emitCeo();\n this.save();\n setTimeout(() => this.schedule(), 300);\n }\n\n /** One phone message about the last update (the launcher's last-update.json, or the demo's fake). */\n private async reportUpdate(result: LastUpdate) {\n const commits = result.ok && result.to ? await this.backend.office.commitsBetween(result.from, result.to) : null;\n this.postMessage('office', lastUpdateMessage(result, commits));\n Object.assign(this.officeUpdate, { failed: result.ok ? null : result.error || 'unknown error', failedBehind: null });\n }\n\n /** The manager's Update now (drain now, even with automatic updates off) or Later (not for 2 hours, or until a newer commit). */\n updateOffice(action: unknown): OfficeUpdateView {\n if (action !== 'now' && action !== 'later') throw new HttpError(400, 'action must be \"now\" or \"later\"');\n const u = this.officeUpdate;\n if (!this.officeHead || !this.backend.office.launcher) throw new HttpError(409, 'The office can only update itself when its launcher started it (npm run dev or npm start).');\n if (u.sent) throw new HttpError(409, 'The update is already under way.');\n if (u.behind <= 0) throw new HttpError(409, 'The office is up to date: there is nothing to update.');\n if (action === 'now') Object.assign(u, { requested: true, postponedUntil: null });\n else Object.assign(u, { requested: false, postponedUntil: Date.now() + POSTPONE_MS, postponedBehind: u.behind });\n this.officeUpdateTick();\n setTimeout(() => this.schedule(), 200);\n return this.officeUpdateView();\n }\n\n // ---------- the CEO ----------\n\n private ceo() {\n return this.state.agents.find((a) => a.id === CEO_ID)!;\n }\n\n /** The company always has a CEO. One cut off by a server restart picks its job back up. */\n private ensureCeo(interrupted: PersistedAgent[]) {\n let a = this.state.agents.find((x) => x.id === CEO_ID);\n if (!a) {\n a = {\n id: CEO_ID,\n name: CEO_NAME,\n repoId: '',\n role: 'ceo',\n title: 'Chief Executive Officer',\n specialty: '',\n brief: '',\n hiredBy: 'manager',\n look: lookFor(CEO_NAME),\n task: null,\n desk: 0,\n color: '#e63946',\n hair: '#2b2118',\n skin: pick(SKIN),\n model: CEO_MODEL,\n effort: CEO_EFFORT,\n cli: 'claude',\n status: 'idle',\n issueNumber: null,\n issueTitle: null,\n branch: null,\n prNumber: null,\n prUrl: null,\n startedAt: null,\n endedAt: null,\n costUsd: 0,\n turns: 0,\n sessionId: null,\n sessionCli: null,\n lastError: null,\n logTail: [],\n };\n this.state.agents.push(a);\n this.agentRt.set(a.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [], terminal: null });\n this.appendLog(a, [{ kind: 'system', text: `\uD83C\uDFDB\uFE0F ${a.name} moved into the corner office. The CEO studies every floor, shapes its team and plans its work.` }]);\n }\n const i = interrupted.indexOf(a);\n if (i >= 0) {\n interrupted.splice(i, 1);\n a.status = 'idle';\n a.lastError = null;\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Picking the job back up.' }]);\n }\n if (this.state.ceo.job) {\n this.state.ceo.queue.unshift(this.state.ceo.job);\n this.state.ceo.job = null;\n }\n this.state.ceo.lastReviewAt ??= Date.now(); // the first review comes one heartbeat after the office opens\n }\n\n private ceoFloor(repoId?: string) {\n const repo = repoId ? this.state.repos.find((r) => r.id === repoId) : undefined;\n if (!repo) return null;\n return { floor: repo.floor, fullName: repo.fullName, clone: this.backend.mainDir(repo.fullName), mission: repo.mission, backlog: this.repoRt.get(repo.id)?.issues.length ?? 0 };\n }\n\n private ceoInfo(): CeoInfo {\n const c = this.state.ceo;\n const view = (j: CeoJob) => ({ kind: j.kind, label: jobLabel(j, this.ceoFloor(j.repoId)) });\n const min = this.state.settings.ceoHeartbeatMin;\n return {\n queue: c.queue.map(view),\n job: c.job ? view(c.job) : null,\n lastReviewAt: c.lastReviewAt,\n nextReviewAt: min > 0 && c.lastReviewAt ? c.lastReviewAt + min * 60_000 : null,\n };\n }\n\n private emitCeo() {\n this.broadcast({ type: 'ceo', ceo: this.ceoInfo() });\n }\n\n /** Queue a job for the CEO: one onboarding or plan per floor, one review, and chat messages merge into one reply. */\n private enqueueCeo(job: CeoJob) {\n const q = this.state.ceo.queue;\n if (job.kind === 'plan' && q.some((j) => j.kind === 'onboard' && j.repoId === job.repoId)) return; // onboarding plans from the brief too\n const same = q.findIndex((j) => j.kind === job.kind && (job.kind === 'review' || job.kind === 'chat' || j.repoId === job.repoId));\n if (same >= 0) q[same] = job.kind === 'chat' ? { ...q[same], text: `${q[same].text}\\n${job.text}` } : job;\n else q.push(job);\n this.emitCeo();\n this.save();\n setTimeout(() => this.schedule(), 150);\n }\n\n /** Start the CEO's next job when they're free and a session slot is open. Replies to the manager go first. */\n private startCeoWork(): void {\n const a = this.state.agents.find((x) => x.id === CEO_ID);\n const c = this.state.ceo;\n if (!a || BUSY.includes(a.status) || c.job || c.queue.length === 0) return;\n if (this.slotsFull()) return;\n const rank: Record<CeoJob['kind'], number> = { chat: 0, onboard: 1, plan: 1, review: 2 };\n // A floor's jobs wait for its clone and first sync, so the CEO has something to read.\n const ready = (j: CeoJob) => {\n const rt = j.repoId ? this.repoRt.get(j.repoId) : undefined;\n return !rt || rt.cloneStatus === 'error' || (rt.cloneStatus === 'ready' && rt.lastSync != null);\n };\n const job = [...c.queue].sort((x, y) => rank[x.kind] - rank[y.kind]).find(ready);\n if (!job) return;\n c.queue.splice(c.queue.indexOf(job), 1);\n const rt = job.repoId ? this.repoRt.get(job.repoId) : undefined;\n if (job.repoId && (!rt || rt.cloneStatus === 'error')) {\n const repo = this.state.repos.find((r) => r.id === job.repoId);\n if (repo) this.postMessage('office', `\u26A0\uFE0F ${a.name} couldn't study floor ${repo.floor}: the repository clone failed (${rt?.cloneError ?? 'unknown error'}).`);\n this.emitCeo();\n this.save();\n return this.startCeoWork();\n }\n void this.runCeoJob(a, job);\n }\n\n private ceoPromptInput(a: PersistedAgent): Parameters<typeof ceoSystemPrompt>[0] {\n const s = this.state.settings;\n return { name: a.name, company: s.companyName, manager: s.managerName, notesFile: path.join(CEO_DIR, 'NOTES.md'), sessionLimit: s.sessionLimit, teamCap: s.teamCap, hiring: s.hiring };\n }\n\n private async runCeoJob(a: PersistedAgent, job: CeoJob) {\n const rt = this.agentRt.get(a.id)!;\n const floor = this.ceoFloor(job.repoId);\n const label = jobLabel(job, floor);\n this.state.ceo.job = job;\n Object.assign(a, { status: 'working' as AgentStatus, task: null, issueNumber: null, issueTitle: label, startedAt: Date.now(), endedAt: null, costUsd: 0, turns: 0, lastError: null });\n this.appendLog(a, [\n { kind: 'system', text: '' },\n { kind: 'system', text: `\u2501\u2501\u2501 ${label} \u2501\u2501\u2501` },\n ]);\n if (job.kind === 'chat') this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${job.text}` }]);\n if (job.kind === 'review') {\n this.state.ceo.lastReviewAt = Date.now();\n this.state.ceo.lastFingerprint = this.fingerprint();\n }\n this.ceoIssues = new IssueCap(MAX_ISSUES_PER_JOB);\n this.emitAgent(a);\n this.emitCeo();\n this.save();\n await fs.mkdir(CEO_DIR, { recursive: true }).catch(() => undefined);\n if (a.status !== 'working') {\n // stopped before the session started\n this.state.ceo.job = null;\n this.emitCeo();\n return;\n }\n // A chat carries on from the CEO's last session, so \"why did you propose that?\" has an answer.\n const how = this.sessionRuntime(a, job.kind === 'chat' ? (a.sessionId ?? undefined) : undefined);\n rt.session = this.backend.startSession(\n {\n cwd: CEO_DIR,\n prompt: ceoJobPrompt(job, floor),\n systemAppend: ceoSystemPrompt(this.ceoPromptInput(a)),\n model: a.model || CEO_MODEL,\n effort: a.effort || CEO_EFFORT,\n browserTesting: false,\n additionalDirectories: this.state.repos.filter((r) => this.repoRt.get(r.id)?.cloneStatus === 'ready').map((r) => this.backend.mainDir(r.fullName)),\n role: 'ceo',\n office: this.officeTools(),\n ...how,\n },\n {\n log: (entries) => this.appendLog(a, entries),\n tool: (name) => {\n if (rt.currentTool === name) return;\n rt.currentTool = name;\n this.emitAgent(a);\n },\n sessionId: (id) => {\n a.sessionId = id;\n a.sessionCli = id ? 'claude' : null;\n },\n browserUrl: () => undefined,\n screenshot: () => undefined,\n turn: (text) => this.postMessage('ceo', text),\n limited: (at) => this.pauseForLimit(at),\n usageWarning: (info) => this.paceForWarning(info),\n finished: (result) => this.onCeoFinished(a, result),\n },\n );\n }\n\n private onCeoFinished(a: PersistedAgent, result: SessionResult) {\n const rt = this.agentRt.get(a.id);\n if (!rt || this.officeUpdate.handedOver) return;\n rt.session = null;\n rt.currentTool = null;\n a.endedAt = Date.now();\n a.costUsd += result.costUsd;\n a.turns += result.turns;\n const job = this.state.ceo.job;\n this.state.ceo.job = null;\n if (result.interrupted) this.interrupted(a);\n if (a.status === 'stopped') {\n // the manager already logged the stop\n } else if (!result.ok) {\n a.status = 'error';\n a.lastError = result.errors.join('; ') || 'Session failed';\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n const what = job ? jobLabel(job, this.ceoFloor(job.repoId)).toLowerCase() : 'working';\n this.postMessage('office', `\u26A0\uFE0F ${a.name} hit a problem while ${what}: ${a.lastError.slice(0, 240)}`);\n } else {\n a.status = 'done';\n const filed = this.ceoIssues.total ? ` \u00B7 ${this.ceoIssues.total} issue${this.ceoIssues.total === 1 ? '' : 's'} filed` : '';\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Done in ${this.minutes(a)}m \u00B7 ${a.turns} turns${filed}` }]);\n }\n for (const id of this.ceoIssues.repos) void this.syncRepo(id);\n this.emitAgent(a);\n this.emitCeo();\n this.save();\n setTimeout(() => this.schedule(), 300);\n }\n\n /** The manager's phone \u2192 the CEO. Injected into a running session, otherwise the CEO picks it up next. */\n async messageCeo(text: string) {\n const t = text.trim().slice(0, 4000);\n if (!t) throw new HttpError(400, 'Empty message');\n const a = this.ceo();\n this.postMessage('manager', t);\n const rt = this.agentRt.get(a.id)!;\n if (rt.session) {\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${t}` }]);\n this.ceoIssues.managerMessage(); // a new request: the issue cap counts from here\n rt.session.send(`Message from the manager (they read your reply on their phone, so keep it short):\\n${t}`);\n return;\n }\n this.enqueueCeo({ kind: 'chat', text: t, at: Date.now() });\n }\n\n requestReview() {\n if (this.state.repos.length === 0) throw new HttpError(400, 'Connect a repo first: the CEO needs a floor to review.');\n this.enqueueCeo({ kind: 'review', at: Date.now() });\n }\n\n onboardFloor(repoId: string) {\n const repo = this.repo(repoId);\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\n }\n\n /** The manager hands the CEO a brief for a floor; the CEO turns it into issues and a team. */\n planFloor(repoId: string, mission?: string) {\n const repo = this.repo(repoId);\n if (typeof mission === 'string') {\n repo.mission = mission.trim().slice(0, 4000);\n this.emitRepo(repo);\n }\n if (!repo.mission) throw new HttpError(400, 'Write a brief first: what should this floor build?');\n this.enqueueCeo({ kind: 'plan', repoId: repo.id, at: Date.now() });\n }\n\n /** Everything the heartbeat cares about. When it hasn't changed since the last review, the review is skipped. */\n private fingerprint() {\n const data = {\n repos: this.state.repos.map((r) => {\n const rt = this.repoRt.get(r.id);\n return [r.id, r.mission, r.summary, rt?.issues.map((i) => i.number), rt?.pulls.filter((p) => p.state === 'OPEN').map((p) => p.number)];\n }),\n agents: this.state.agents.filter((a) => a.role !== 'ceo').map((a) => [a.id, FREE.includes(a.status) ? 'free' : a.status]),\n qa: this.state.qa.map((q) => [q.repoId, q.prNumber, q.status]),\n requests: this.state.requests.filter((r) => r.status === 'pending').map((r) => r.id),\n };\n return crypto.createHash('sha1').update(JSON.stringify(data)).digest('hex');\n }\n\n private maybeHeartbeat() {\n const min = this.state.settings.ceoHeartbeatMin;\n const c = this.state.ceo;\n if (!min || this.state.repos.length === 0 || c.job?.kind === 'review' || c.queue.some((j) => j.kind === 'review')) return;\n if (Date.now() < (c.lastReviewAt ?? 0) + min * 60_000) return;\n if (this.fingerprint() === c.lastFingerprint) {\n c.lastReviewAt = Date.now(); // nothing changed since the last review\n this.emitCeo();\n this.save();\n return;\n }\n this.enqueueCeo({ kind: 'review', at: Date.now() });\n }\n\n // ---------- the phone ----------\n\n private postMessage(from: PhoneMessage['from'], text: string, requestId?: string) {\n const m: PhoneMessage = { id: this.messageSeq++, from, text: text.trim().slice(0, 6000), at: Date.now(), ...(requestId ? { requestId } : {}) };\n this.state.messages.push(m);\n if (this.state.messages.length > KEEP_MESSAGES) this.state.messages.splice(0, this.state.messages.length - KEEP_MESSAGES);\n this.broadcast({ type: 'message', message: m });\n this.save();\n return m;\n }\n\n markPhoneRead(at: number) {\n const t = Math.min(Number(at) || Date.now(), Date.now());\n if (t <= this.state.phoneReadAt) return;\n this.state.phoneReadAt = t;\n this.broadcast({ type: 'phoneRead', at: t });\n this.save();\n }\n\n // ---------- hire and let-go proposals ----------\n\n private addRequest(req: HireRequestView) {\n this.state.requests.push(req);\n const decided = this.state.requests.filter((r) => r.status !== 'pending');\n if (decided.length > KEEP_DECIDED_REQUESTS) {\n const drop = new Set(decided.slice(0, decided.length - KEEP_DECIDED_REQUESTS));\n this.state.requests = this.state.requests.filter((r) => !drop.has(r));\n }\n this.broadcast({ type: 'request', request: req });\n this.save();\n }\n\n private decide(req: HireRequestView, patch: Pick<HireRequestView, 'status' | 'note' | 'decidedBy'>) {\n Object.assign(req, patch, { decidedAt: Date.now() });\n this.broadcast({ type: 'request', request: req });\n this.save();\n }\n\n approveRequest(id: string, overrides: { name?: string; model?: string; effort?: string } = {}, by: 'manager' | 'auto' = 'manager') {\n const req = this.state.requests.find((r) => r.id === id);\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\n const repo = this.repo(req.repoId);\n if (req.kind === 'hire') {\n const name = overrides.name?.trim() || req.name;\n const agent = this.hireAgent(repo.id, {\n name,\n role: req.role,\n model: overrides.model ?? req.model,\n effort: overrides.effort ?? req.effort,\n look: name === req.name ? req.look : undefined,\n title: req.title,\n specialty: req.specialty,\n brief: req.brief,\n hiredBy: 'ceo',\n appearance: { color: req.color, hair: req.hair, skin: req.skin },\n });\n req.agentId = agent.id;\n req.name = agent.name;\n this.decide(req, { status: 'approved', note: '', decidedBy: by });\n this.postMessage(\n 'office',\n by === 'auto' ? `\uD83E\uDD16 Auto-approved: ${agent.name} joined floor ${repo.floor} as ${req.title}.` : `\u2705 You hired ${agent.name} as ${req.title} on floor ${repo.floor}.`,\n req.id,\n );\n this.toast('success', `${agent.name} (${req.title}) joined floor ${repo.floor}`);\n return;\n }\n const a = req.agentId ? this.state.agents.find((x) => x.id === req.agentId) : undefined;\n this.decide(req, { status: 'approved', note: a ? '' : 'They had already left.', decidedBy: by });\n if (a) {\n try {\n this.fireAgent(a.id);\n } catch (err) {\n this.decide(req, { status: 'pending', note: '', decidedBy: null });\n throw err;\n }\n }\n this.postMessage('office', `\uD83D\uDC4B ${req.name} left floor ${repo.floor}${by === 'auto' ? ' (auto-approved)' : ''}.`, req.id);\n }\n\n rejectRequest(id: string, note = '') {\n const req = this.state.requests.find((r) => r.id === id);\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\n this.decide(req, { status: 'rejected', note: note.trim().slice(0, 400), decidedBy: 'manager' });\n const what = req.kind === 'hire' ? `${req.name} (${req.title})` : `letting ${req.name} go`;\n this.postMessage('office', `\u270B You declined ${what}${req.note ? `: \"${req.note}\"` : '.'}`, req.id);\n }\n\n // ---------- the CEO's office tools ----------\n\n private floorRepo(floor: number) {\n const r = this.state.repos.find((x) => x.floor === Number(floor));\n if (!r) throw new Error(`There is no floor ${floor}. Floors: ${this.state.repos.map((x) => `${x.floor} (${x.fullName})`).join(', ') || 'none'}.`);\n return r;\n }\n\n private agentByRef(ref: string) {\n const r = String(ref ?? '').trim().toLowerCase();\n const a = this.state.agents.find((x) => x.id === ref || x.name.toLowerCase() === r);\n if (!a) throw new Error(`No agent \"${ref}\". Use the ids from company_status.`);\n return a;\n }\n\n private agentDoing(a: PersistedAgent) {\n return !BUSY.includes(a.status) ? null : a.task === 'qa' ? `testing PR #${a.prNumber}` : a.task === 'fix' ? `fixing PR #${a.prNumber}` : `issue #${a.issueNumber}`;\n }\n\n private companyStatus() {\n const s = this.state.settings;\n const doing = (a: PersistedAgent) => this.agentDoing(a);\n // Keep the status compact, but make the cut visible so the CEO knows to read agent_detail before rewriting.\n const jobDescription = (brief: string) => {\n if (brief.length <= 400) return brief;\n const mark = `\u2026 (truncated, ${brief.length} chars; see agent_detail)`;\n return brief.slice(0, 400 - mark.length).trimEnd() + mark;\n };\n const pending = this.state.requests.filter((r) => r.status === 'pending');\n const seats = (r: PersistedRepo, role: 'dev' | 'qa') =>\n seatCount(\n MAX_DESKS[role],\n this.state.agents.filter((a) => a.repoId === r.id && a.role === role).length,\n pending.filter((p) => p.kind === 'hire' && p.repoId === r.id && p.role === role).length,\n );\n const floors = [...this.state.repos]\n .sort((x, y) => x.floor - y.floor)\n .map((r) => {\n const rt = this.repoRt.get(r.id)!;\n const open = new Set(rt.issues.map((i) => i.number));\n return {\n floor: r.floor,\n repo: r.fullName,\n description: r.description,\n clone: rt.cloneStatus === 'ready' ? this.backend.mainDir(r.fullName) : `(not available: clone ${rt.cloneStatus})`,\n brief: r.mission || null,\n profile: r.summary || null,\n qaBrief: r.qaBrief || null,\n preview: { command: r.preview.command, env: r.preview.env, status: this.previews.view(r).status },\n autoAssign: r.autoAssign,\n autoMerge: r.autoMerge,\n folderSync: rt.folderSync,\n seats: { dev: seats(r, 'dev'), qa: seats(r, 'qa') },\n capacity: {\n developers: this.state.agents.filter((a) => a.repoId === r.id && a.role === 'dev').length,\n developersFree: this.available(r, 'dev').length,\n issuesReadyToStart: this.readyIssues(r).length,\n issuesWaitingOnOthers: rt.issues.filter((i) => blockers(i.body, open).length > 0).length,\n longestDependencyChain: Math.max(0, ...[...holdUps(rt.issues).values()].map((w) => w.chain)),\n },\n team: this.state.agents\n .filter((a) => a.repoId === r.id)\n .map((a) => ({\n id: a.id,\n name: a.name,\n role: a.role,\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\n specialty: a.specialty || null,\n status: a.status,\n doing: doing(a),\n hiredBy: a.hiredBy,\n jobDescription: a.brief ? jobDescription(a.brief) : null,\n })),\n backlog: rt.issues.map((i) => ({\n number: i.number,\n title: i.title,\n specialty: issueSpecialty(i.labels) || null,\n waitsFor: blockers(i.body, open),\n inProgress: this.issueTaken(r, i.number),\n })),\n pullRequests: rt.pulls\n .filter((p) => p.state === 'OPEN')\n .map((p) => {\n const q = this.state.qa.find((x) => x.repoId === r.id && x.prNumber === p.number);\n return { number: p.number, title: p.title, qa: q ? `${q.status}${q.round > 1 ? ` (round ${q.round})` : ''}` : 'not tested', merge: q?.mergeNote ?? null, checks: p.checks };\n }),\n mergedRecently: rt.pulls.filter((p) => p.state === 'MERGED').map((p) => `#${p.number} ${p.title}`),\n };\n });\n const req = (r: HireRequestView) => ({\n id: r.id,\n kind: r.kind,\n floor: this.state.repos.find((x) => x.id === r.repoId)?.floor ?? null,\n role: r.role,\n name: r.name,\n title: r.title,\n specialty: r.specialty || null,\n reason: r.reason,\n status: r.status,\n managerNote: r.note || null,\n });\n return JSON.stringify(\n {\n company: {\n ceo: this.ceo().name,\n hiring: s.hiring === 'auto' ? `auto-approved while a floor has fewer than ${s.teamCap} people` : 'the manager approves every proposal',\n teamCap: s.teamCap,\n sessionLimit: s.sessionLimit || 'none',\n sessionsRunning: this.running(),\n usage: usageLabel(this.usageNow(), Date.now()),\n deskLimits: { dev: MAX_DESKS.dev, qa: MAX_DESKS.qa },\n proposalLimit: { pending: pending.length, max: MAX_PENDING_PROPOSALS },\n },\n floors,\n pendingProposals: pending.map(req),\n recentDecisions: this.state.requests.filter((r) => r.status !== 'pending').slice(-10).map(req),\n },\n null,\n 1,\n );\n }\n\n private agentDetail(x: { agent_id: string }) {\n const a = this.agentByRef(x.agent_id);\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n const ceo = a.role === 'ceo';\n return JSON.stringify(\n {\n id: a.id,\n name: a.name,\n floor: repo?.floor ?? null,\n role: a.role,\n title: a.title || (a.role === 'qa' ? 'QA tester' : a.role === 'dev' ? 'Developer' : 'CEO'),\n specialty: a.specialty || null,\n status: a.status,\n doing: this.agentDoing(a),\n issue: a.issueNumber ? { number: a.issueNumber, title: a.issueTitle } : null,\n pullRequest: a.prNumber ? { number: a.prNumber, url: a.prUrl } : null,\n codingAgent: ceo ? 'claude' : a.cli || this.state.settings.defaultCli,\n model: ceo ? a.model || CEO_MODEL : this.modelFor(a, a.cli || this.state.settings.defaultCli) || 'the coding agent default',\n effort: a.effort || (ceo ? CEO_EFFORT : this.state.settings.defaultEffort),\n hiredBy: a.hiredBy,\n jobDescription: a.brief || null,\n },\n null,\n 1,\n );\n }\n\n private setFloorProfile(x: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }) {\n const r = this.floorRepo(x.floor);\n const preview = parsePreviewPatch(x.preview_command, x.preview_env);\n if (x.summary !== undefined) r.summary = String(x.summary).trim().slice(0, 140);\n if (x.qa_brief !== undefined) r.qaBrief = String(x.qa_brief).trim().slice(0, 2500);\n r.preview = { ...r.preview, ...preview };\n if (preview.command === null) void this.previews.refreshDefault(r);\n this.emitRepo(r);\n this.save();\n return `Saved floor ${r.floor}'s profile.`;\n }\n\n private updateJob(x: { agent_id: string; title?: string; specialty?: string; job_description?: string }) {\n const a = this.agentByRef(x.agent_id);\n if (a.role === 'ceo') throw new Error(\"That's you.\");\n this.updateAgent(a.id, { title: x.title, specialty: x.specialty, brief: x.job_description });\n const title = a.title || (a.role === 'qa' ? 'QA tester' : 'Developer');\n this.appendLog(a, [{ kind: 'system', text: `\uD83E\uDEAA ${this.ceo().name} updated ${a.name}'s job: ${title}${a.specialty ? ` \u00B7 swarm:${a.specialty}` : ''}` }]);\n return `Updated ${a.name}: ${title}${a.specialty ? ` (specialty ${a.specialty})` : ''}.`;\n }\n\n private proposeHire(x: { floor: number; role: 'dev' | 'qa'; title: string; specialty: string; job_description: string; reason: string; model?: string; effort?: string }) {\n const repo = this.floorRepo(x.floor);\n const role = x.role === 'qa' ? 'qa' : 'dev';\n const title = String(x.title ?? '').trim().slice(0, 60);\n if (!title) throw new Error('A hire needs a job title.');\n const specialty = specialtySlug(x.specialty);\n const pending = this.state.requests.filter((r) => r.status === 'pending');\n checkPendingLimit(pending.length);\n const dup =pending.find((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role && r.specialty === specialty);\n if (dup) throw new Error(`${dup.name} (${dup.title}) is already proposed for floor ${repo.floor} with that specialty.`);\n const seated = this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).length;\n const waiting = pending.filter((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role).length;\n if (seated + waiting >= MAX_DESKS[role]) throw new Error(role === 'qa' ? `The QA lab on floor ${repo.floor} is full.` : `Floor ${repo.floor} has no free desks.`);\n const name = this.freeName(role);\n const req: HireRequestView = {\n id: crypto.randomUUID(),\n kind: 'hire',\n repoId: repo.id,\n role,\n agentId: null,\n name,\n title,\n specialty,\n brief: String(x.job_description ?? '').trim().slice(0, 2500),\n reason: String(x.reason ?? '').trim().slice(0, 600),\n model: String(x.model ?? '').trim(),\n effort: EFFORTS.includes(x.effort as EffortLevel) ? (x.effort as EffortLevel) : '',\n look: lookFor(name),\n color: pick(SHIRTS),\n hair: pick(HAIR),\n skin: pick(SKIN),\n status: 'pending',\n note: '',\n createdAt: Date.now(),\n decidedAt: null,\n decidedBy: null,\n };\n this.addRequest(req);\n const s = this.state.settings;\n if (s.hiring === 'auto' && this.state.agents.filter((a) => a.repoId === repo.id).length < s.teamCap) {\n this.approveRequest(req.id, {}, 'auto');\n return `Hired ${req.name} as ${title} on floor ${repo.floor} (auto-approved; agent id ${req.agentId}).`;\n }\n this.postMessage('ceo', `\uD83D\uDCC4 New candidate for floor ${repo.floor}: ${name}, ${title}. ${req.reason}`, req.id);\n return `Proposed ${name} as ${title} on floor ${repo.floor}. The manager will approve or decline (request ${req.id}).`;\n }\n\n private proposeLetGo(x: { agent_id: string; reason: string }) {\n const a = this.agentByRef(x.agent_id);\n if (a.role === 'ceo') throw new Error(\"You can't let yourself go.\");\n const repo = this.repo(a.repoId);\n if (a.role === 'qa' && this.state.agents.filter((y) => y.repoId === repo.id && y.role === 'qa').length <= 1) {\n throw new Error(`${a.name} is floor ${repo.floor}'s only QA tester, and every floor keeps one.`);\n }\n const pending = this.state.requests.filter((r) => r.status === 'pending');\n if (pending.some((r) => r.kind === 'let-go' && r.agentId === a.id)) throw new Error(`Letting ${a.name} go is already proposed.`);\n checkPendingLimit(pending.length);\n const req: HireRequestView = {\n id: crypto.randomUUID(),\n kind: 'let-go',\n repoId: repo.id,\n role: a.role,\n agentId: a.id,\n name: a.name,\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\n specialty: a.specialty,\n brief: a.brief,\n reason: String(x.reason ?? '').trim().slice(0, 600),\n model: a.model,\n effort: a.effort,\n look: a.look,\n color: a.color,\n hair: a.hair,\n skin: a.skin,\n status: 'pending',\n note: '',\n createdAt: Date.now(),\n decidedAt: null,\n decidedBy: null,\n };\n this.addRequest(req);\n if (this.state.settings.hiring === 'auto' && FREE.includes(a.status)) {\n this.approveRequest(req.id, {}, 'auto');\n return `Let ${a.name} go (auto-approved).`;\n }\n this.postMessage('ceo', `\uD83D\uDC4B I suggest letting ${a.name} (${req.title}, floor ${repo.floor}) go. ${req.reason}`, req.id);\n return `Proposed letting ${a.name} go. The manager will decide (request ${req.id}).`;\n }\n\n private async fileIssue(x: { floor: number; title: string; body: string; specialty?: string }) {\n const repo = this.floorRepo(x.floor);\n this.ceoIssues.check();\n const title = String(x.title ?? '').trim().slice(0, 120);\n if (!title) throw new Error('An issue needs a title.');\n const slug = specialtySlug(x.specialty);\n const body = `${String(x.body ?? '').trim()}\\n\\n---\\n_Filed by ${this.ceo().name}, the cubefarm CEO._`;\n const n = await this.backend.createIssue(repo.fullName, title, body, slug ? [specialtyLabel(slug)] : []);\n this.ceoIssues.record(repo.id);\n return `Filed #${n} on floor ${repo.floor}: ${title}${slug ? ` (routed to ${slug})` : ''}.`;\n }\n\n /** Change an open issue's specialty and/or dependencies (see planRoute for what is refused). */\n private async routeIssue(x: { floor: number; number: number; specialty?: string; depends_on?: number[] }) {\n const repo = this.floorRepo(x.floor);\n const issues = this.repoRt.get(repo.id)?.issues ?? [];\n const asked = [Number(x.number), ...(x.depends_on ?? []).map(Number)].filter((n) => !issues.some((i) => i.number === n));\n const states = new Map(await Promise.all([...new Set(asked)].map(async (n) => [n, await this.backend.issueState(repo.fullName, n).catch(() => null)] as const)));\n const specialties = [\n ...this.state.agents.filter((a) => a.repoId === repo.id && a.specialty).map((a) => a.specialty.toLowerCase()),\n ...this.state.requests.filter((r) => r.status === 'pending' && r.kind === 'hire' && r.repoId === repo.id && r.specialty).map((r) => r.specialty),\n ];\n const plan = planRoute({\n floor: repo.floor,\n number: Number(x.number),\n specialty: x.specialty,\n dependsOn: x.depends_on,\n issues,\n closed: (n) => states.get(n) === 'CLOSED',\n inProgress: this.issueTaken(repo, Number(x.number)),\n specialties,\n });\n if (plan.body !== null || plan.addLabels.length || plan.removeLabels.length) {\n await this.backend.editIssue(repo.fullName, Number(x.number), { body: plan.body ?? undefined, addLabels: plan.addLabels, removeLabels: plan.removeLabels });\n await this.syncRepo(repo.id); // the scheduler sees the new routing right away\n }\n return plan.summary;\n }\n}\n", "import { createSdkMcpServer, tool, type McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';\nimport { z } from 'zod';\nimport { blockers, holdUps, setDependsOn } from '../shared/issues.ts';\nimport type { CeoJobKind } from '../shared/types.ts';\n\n// The CEO: a Claude Code session in the lobby that runs the company instead of writing code.\n// It studies each floor's repo, shapes the team (hire / let-go proposals the manager approves),\n// plans work as GitHub issues, and writes each floor's QA brief. Everything it changes goes\n// through the office tools below, so the swarm stays the single source of truth.\n\nexport interface CeoJob {\n kind: CeoJobKind;\n repoId?: string; // onboard / plan\n text?: string; // chat: the manager's message(s)\n at: number;\n}\n\n/** What the CEO's tools do. Implemented by the swarm; errors are returned to the CEO as tool errors. */\nexport interface OfficeHandlers {\n companyStatus(): string;\n agentDetail(a: { agent_id: string }): string;\n setFloorProfile(a: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }): string;\n updateJob(a: { agent_id: string; title?: string; specialty?: string; job_description?: string }): string;\n proposeHire(a: {\n floor: number;\n role: 'dev' | 'qa';\n title: string;\n specialty: string;\n job_description: string;\n reason: string;\n model?: string;\n effort?: string;\n }): string;\n proposeLetGo(a: { agent_id: string; reason: string }): string;\n fileIssue(a: { floor: number; title: string; body: string; specialty?: string }): Promise<string>;\n routeIssue(a: { floor: number; number: number; specialty?: string; depends_on?: number[] }): Promise<string>;\n}\n\nexport interface OfficeTools {\n server: McpSdkServerConfigWithInstance;\n /** A fresh MCP server with the same tools, for one request from a CEO running in a terminal (served over HTTP). */\n serve(): McpSdkServerConfigWithInstance['instance'];\n /** Run a tool without a model in the loop (the demo CEO). */\n call(name: string, args: Record<string, unknown>): Promise<string>;\n}\n\nconst EFFORT = z.enum(['low', 'medium', 'high', 'xhigh', 'max']);\n\nexport function createOfficeTools(h: OfficeHandlers): OfficeTools {\n const run = async (fn: () => string | Promise<string>) => {\n try {\n return { content: [{ type: 'text' as const, text: await fn() }] };\n } catch (err) {\n return { content: [{ type: 'text' as const, text: `Refused: ${(err as Error).message}` }], isError: true };\n }\n };\n const defs = [\n tool(\n 'company_status',\n 'Everything about the company right now: settings, every floor (repo, clone path, brief, profile, QA brief), its free seats, team, backlog, pull requests and QA, pending proposals and recent decisions by the manager. Call this first.',\n {},\n () => run(() => h.companyStatus()),\n ),\n tool(\n 'agent_detail',\n \"One agent in full: title, specialty, role, status, current task, model and effort, and their complete job description (company_status shortens long ones). Read it before rewriting someone's job description.\",\n { agent_id: z.string().describe('An id (or name) from company_status') },\n (a) => run(() => h.agentDetail(a)),\n ),\n tool(\n 'set_floor_profile',\n \"Record your read of a floor's project: a one-line summary (kind of project and stack), the QA brief that tells QA testers what to check for this kind of project, and how to run the app for the floor's preview monitor.\",\n {\n floor: z.number().int().describe('Floor number'),\n summary: z.string().max(140).optional().describe('e.g. \"3D browser game \u00B7 Three.js + Vite + TypeScript\"'),\n qa_brief: z.string().max(2500).optional().describe('What QA must check on every PR for this project, as short bullet points'),\n preview_command: z\n .string()\n .max(2000)\n .optional()\n .describe(\n 'Shell command that serves the app on port {port} from a fresh checkout after npm install, e.g. \"npm run dev -- --port {port} --strictPort\". PORT={port} is always set. {tmp} is a scratch folder. Empty string: back to the default (npm run dev, else start, else preview). Only set it when the default would not serve the app on PORT.',\n ),\n // Not z.record(): the SDK can't turn it into JSON Schema, and one bad tool empties the whole tools/list.\n preview_env: z\n .object({})\n .catchall(z.string())\n .optional()\n .describe('Extra environment variables for the preview; {port} and {tmp} are replaced in the values. Replaces the whole set.'),\n },\n (a) => run(() => h.setFloorProfile(a)),\n ),\n tool(\n 'update_job',\n \"Change an existing agent's job title, specialty or job description so it fits the project. Takes effect from their next task.\",\n {\n agent_id: z.string(),\n title: z.string().max(60).optional(),\n specialty: z.string().max(24).optional().describe('Short lowercase slug, e.g. \"graphics\"; \"\" for a generalist'),\n job_description: z.string().max(2500).optional(),\n },\n (a) => run(() => h.updateJob(a)),\n ),\n tool(\n 'propose_hire',\n 'Propose hiring a developer or QA tester for a floor. The manager approves or declines (or it is auto-approved if hiring is set to auto and the floor is under its team cap).',\n {\n floor: z.number().int(),\n role: z.enum(['dev', 'qa']).describe('dev = builds issues into pull requests; qa = tests pull requests'),\n title: z.string().max(60).describe('Specific job title, e.g. \"Three.js graphics engineer\"'),\n specialty: z.string().max(24).describe('Short lowercase slug used to label issues swarm:<specialty>, e.g. \"graphics\"'),\n job_description: z.string().max(2500).describe('What this person owns on this project and how they should work. Written to them, second person.'),\n reason: z.string().max(600).describe('Why the floor needs them now. The manager reads this.'),\n model: z.string().optional().describe('Leave out to use the default model'),\n effort: EFFORT.optional().describe('Leave out to use the default effort'),\n },\n (a) => run(() => h.proposeHire(a)),\n ),\n tool(\n 'propose_let_go',\n 'Propose letting an agent go (overstaffed floor, specialty no longer needed). The manager decides.',\n { agent_id: z.string(), reason: z.string().max(600) },\n (a) => run(() => h.proposeLetGo(a)),\n ),\n tool(\n 'file_issue',\n 'File a GitHub issue on a floor. A specialty routes it to that specialist first; when none is free, any free developer takes it. Write \"Depends on #N\" in the body only when it cannot start until #N is merged: the office will not start it until #N is closed.',\n {\n floor: z.number().int(),\n title: z.string().max(120),\n body: z.string().max(6000).describe('Context, what to build, acceptance criteria'),\n specialty: z.string().max(24).optional(),\n },\n (a) => run(() => h.fileIssue(a)),\n ),\n tool(\n 'route_issue',\n 'Fix the routing of an open issue instead of filing a duplicate: change its specialty, rewrite its \"Depends on #N\" line, or both. The rest of the body stays as it is.',\n {\n floor: z.number().int(),\n number: z.number().int().positive().describe('The issue number'),\n specialty: z.string().max(24).optional().describe('Sets swarm:<specialty> and removes any other; \"\" for none. Someone on the floor, or a pending proposal, must have it.'),\n depends_on: z.array(z.number().int().positive()).max(10).optional().describe('Issues it waits for; [] for none. Not for an issue in progress.'),\n },\n (a) => run(() => h.routeIssue(a)),\n ),\n ];\n const server = createSdkMcpServer({ name: 'office', version: '1.0.0', tools: defs });\n return {\n server,\n serve: () => createSdkMcpServer({ name: 'office', version: '1.0.0', tools: defs }).instance,\n async call(name, args) {\n const def = defs.find((d) => d.name === name);\n if (!def) throw new Error(`No office tool ${name}`);\n const res = (await def.handler(args as never, undefined)) as { content: { text?: string }[] };\n return res.content.map((c) => c.text ?? '').join('\\n');\n },\n };\n}\n\n// ---------- seats ----------\n\n/** Desks per floor. client/src/world/layout.ts draws the same number (ceo.test.ts checks they match). */\nexport const FLOOR_DESKS = { dev: 12, qa: 3 } as const;\n/** Pending proposals the manager can have waiting: enough to staff one empty floor in one go. */\nexport const MAX_PENDING_PROPOSALS = FLOOR_DESKS.dev + FLOOR_DESKS.qa;\n\nexport interface SeatCount {\n total: number;\n taken: number;\n /** Pending hire proposals for these seats. */\n proposed: number;\n free: number;\n}\n\nexport const seatCount = (total: number, taken: number, proposed: number): SeatCount => ({ total, taken, proposed, free: Math.max(0, total - taken - proposed) });\n\n/** Refuses a proposal while the manager already has the most they can be asked to decide on. */\nexport function checkPendingLimit(pending: number, max = MAX_PENDING_PROPOSALS) {\n if (pending >= max) throw new Error(`${pending} proposals are already waiting for the manager; propose the rest after they decide.`);\n}\n\n// ---------- prompts ----------\n\nexport function ceoSystemPrompt(o: {\n name: string;\n company: string;\n manager: string;\n notesFile: string;\n sessionLimit: number;\n teamCap: number;\n hiring: 'approve' | 'auto';\n}) {\n const manager = o.manager ? `the manager, ${o.manager}` : 'the human manager';\n return [\n `You are ${o.name}, the CEO of ${o.company || 'an autonomous software company'}, run from an office building called cubefarm. You work from the corner office in the lobby.`,\n `Every floor of the building is one GitHub repository with its own team of AI coding agents. Developers pick up GitHub issues, each in their own git worktree, and open pull requests. QA testers review and verify every pull request (code review, tests, build, and a real browser via Playwright); when every tester is busy, a free developer who didn't write the PR covers QA. On floors with auto-merge on, the office merges a PR by itself once QA passes and GitHub's checks are green, and sends failing checks or merge conflicts back to a developer; on the others, ${manager} merges. The manager is your board: they approve hires and let-gos.`,\n '',\n 'Your job is to run the company, not to write code:',\n '- Understand each project: what it is, its stack, how far along it is, and what kind of people it needs. Projects differ a lot. A static marketing site, a 3D browser game and a REST API need different specialists and different QA.',\n `- Shape each floor's team. Propose specialists with a specific title and a job description written for this project. Keep teams lean: agents on the same coding agent share one subscription's usage limits${o.sessionLimit ? ` and at most ${o.sessionLimit} sessions run at once` : ''}, so a floor rarely needs more than ${o.teamCap} people. When the manager asks for a bigger team, follow that, up to the floor's free seats (seats in company_status). Propose letting people go when a floor is clearly overstaffed or a specialty is no longer needed.`,\n \"- Plan the work: turn a floor's brief into small, well-specified GitHub issues, one agent-session each, with acceptance criteria. Route each to a specialty. The office hands issues out itself: a free specialist gets first pick of their specialty, and otherwise any free developer takes the next issue that can start, so a specialty is a preference, not a lock.\",\n \"- Write each floor's QA brief: what QA testers must check for this kind of project (for a 3D game: the canvas renders, controls respond, frame rate is smooth; for a website: links, phone layout, accessibility; for an API: status codes, validation, error cases).\",\n '',\n 'How you work:',\n '- Call mcp__office__company_status first. It lists every floor, its clone path, team, backlog, pull requests and your pending proposals.',\n '- Read the repositories through their clone paths with Read, Glob and Grep. They are read-only to you. You cannot run shell commands.',\n `- Keep durable notes about the company in ${o.notesFile}: read it at the start, and update it at the end with decisions and anything worth remembering next time.`,\n '- Change things only through the mcp__office__ tools.',\n \"- Before update_job rewrites someone's job description, read the full one with mcp__office__agent_detail and keep what still applies, especially its safety rules.\",\n '',\n 'Rules:',\n '- Every floor keeps at least one QA tester.',\n '- Titles are specific (\"Three.js graphics engineer\", not \"Developer\"). A specialty is a short lowercase slug (\"graphics\", \"gameplay\", \"frontend\", \"backend\", \"content\", \"a11y\", \"devops\"). Only route an issue to a specialty that someone on the floor has, or that you are proposing to hire.',\n '- Before proposing a hire, check the floor and the pending proposals for someone who already covers it. If the manager declined a similar proposal (recentDecisions), do not propose it again unless something has changed, and say what.',\n `- ${o.hiring === 'auto' ? 'Hiring is on auto: proposals within the team cap are approved immediately, so be deliberate.' : 'The manager approves every hire, so explain each reason in a sentence or two they can decide on.'}`,\n '- Issues: plan for parallel work. What keeps a floor busy is the number of issues that can start right now (capacity.issuesReadyToStart in company_status); aim for at least one per developer. Write \"Depends on #N\" only when an issue truly cannot start until #N\\'s code is merged, because it waits until #N is closed. Keep dependency chains to two steps at most, keep foundation issues small, and split big pieces into parts that can be built side by side. The office starts the issues that hold up others first. Do not duplicate open issues: fix an existing issue\\'s specialty or dependencies with route_issue. File at most 12 issues per job, or per message from the manager.',\n \"- When company.usage in company_status says pacing or paused, Claude's usage is running low and the office is finishing open work first: file only what is needed next, not a whole milestone.\",\n '- Your final message goes straight to the manager\\'s phone. Keep it short and plain: what you found, what you proposed, what you filed, and any question you need answered. No headings, no tables.',\n ].join('\\n');\n}\n\nexport function ceoJobPrompt(job: CeoJob, floor: { floor: number; fullName: string; clone: string; mission: string; backlog: number } | null): string {\n switch (job.kind) {\n case 'onboard':\n if (!floor) return 'A floor was added but has since been removed. Reply \"Nothing to do.\"';\n return [\n `Floor ${floor.floor} (${floor.fullName}) just joined the company. Its read-only clone is at ${floor.clone}.`,\n 'Study it: README, package manifest, source layout, tests, and how far along it is. Then:',\n \"1. set_floor_profile with a one-line summary and a QA brief for this project. If npm run dev / start / preview wouldn't serve the app on PORT, also set preview_command (and preview_env) so the floor's preview monitor can run it.\",\n '2. update_job for the people already on the floor so their titles, specialties and job descriptions fit this project (every floor starts with a generalist QA tester).',\n '3. Propose the hires this project needs. Usually two to four developers with distinct specialties is plenty.',\n floor.mission\n ? `4. The manager's brief for this floor: \"\"\"${floor.mission}\"\"\"\\n${floor.backlog === 0 ? 'The backlog is empty: plan the first milestone as issues.' : `There are ${floor.backlog} open issues: add issues only for what the brief needs and the backlog does not cover.`}`\n : floor.backlog === 0\n ? '4. There is no brief and the backlog is empty. Do not invent work; suggest in your final message what the manager might want next.'\n : `4. There are ${floor.backlog} open issues. Label nothing retroactively; just make sure the team can cover them.`,\n ].join('\\n');\n case 'plan':\n if (!floor) return 'A floor you were asked to plan has been removed. Reply \"Nothing to do.\"';\n return [\n `The manager has a brief for floor ${floor.floor} (${floor.fullName}, clone at ${floor.clone}):`,\n `\"\"\"${floor.mission}\"\"\"`,\n '',\n 'Plan the next milestone toward it:',\n `- Read the current code and the ${floor.backlog} open issues first, so you build on what exists and do not duplicate anything.`,\n '- If the repository is empty or nearly empty, the first issue sets up a small project skeleton, and the others depend on it. Everything after that should be able to run side by side.',\n '- File the issues, each routed to a specialty.',\n '- Make sure the floor has the specialists those issues need; propose hires if not.',\n '- Update the floor profile and QA brief if the brief changes what the project is.',\n ].join('\\n');\n case 'review':\n return [\n 'Periodic review of the company. For every floor, look at:',\n '- floors without a profile or QA brief: study them and write one',\n '- backlog against the team (capacity): fewer issues ready to start than free developers, long dependency chains, a specialty with a long queue (fix those with route_issue)',\n '- pull requests stuck in QA or marked as needing a human',\n '- floors with a brief and an empty backlog: plan the next milestone',\n 'Propose hires or let-gos only when clearly justified. If nothing needs doing, reply with one short sentence saying so.',\n ].join('\\n');\n case 'chat':\n return `Message from the manager (they're reading your reply on their phone):\\n${job.text ?? ''}`;\n }\n}\n\nexport function jobLabel(job: CeoJob, floor: { floor: number; fullName: string } | null) {\n const where = floor ? `floor ${floor.floor} \u00B7 ${floor.fullName.split('/')[1] ?? floor.fullName}` : 'a removed floor';\n switch (job.kind) {\n case 'onboard':\n return `Onboarding ${where}`;\n case 'plan':\n return `Planning ${where}`;\n case 'review':\n return 'Reviewing the company';\n case 'chat':\n return 'Replying to you';\n }\n}\n\n// ---------- issues ----------\n\n/**\n * The CEO's issue cap: at most `max` issues per request from the manager. A manager message that arrives while the\n * job runs is a new request, so it resets the count.\n */\nexport class IssueCap {\n filed = 0; // since the job started or the manager's last message\n total = 0; // in the whole job\n readonly repos = new Set<string>(); // floors that got issues, to refresh when the job ends\n constructor(readonly max: number) {}\n\n check() {\n if (this.filed >= this.max) throw new Error(`You already filed ${this.max} issues in this job. That's plenty for one milestone. The manager's next message allows more.`);\n }\n\n record(repoId: string) {\n this.filed++;\n this.total++;\n this.repos.add(repoId);\n }\n\n managerMessage() {\n this.filed = 0;\n }\n}\n\nexport interface RouteRequest {\n floor: number;\n number: number;\n specialty?: string; // '' = no specialty\n dependsOn?: number[]; // [] = no dependencies\n issues: { number: number; body: string; labels: string[] }[]; // the floor's open issues\n closed: (n: number) => boolean; // for numbers that aren't open: closed, rather than unknown\n inProgress: boolean;\n specialties: string[]; // held by someone on the floor or by a pending hire proposal for it\n}\n\nexport interface RoutePlan {\n addLabels: string[];\n removeLabels: string[];\n body: string | null; // null: leave the body alone\n summary: string;\n}\n\n/** Longest chain of open issues this one waits for, one step per \"Depends on\". */\nfunction waitsDepth(n: number, deps: Map<number, number[]>, seen = new Set<number>()): number {\n if (seen.has(n)) return 0;\n seen.add(n);\n const depth = Math.max(0, ...(deps.get(n) ?? []).map((d) => waitsDepth(d, deps, seen) + 1));\n seen.delete(n);\n return depth;\n}\n\n/**\n * What route_issue changes, or why it refuses: a closed or unknown issue, a specialty nobody on the floor has,\n * dependencies on an issue in progress, a dependency on itself, on a closed or unknown issue, a cycle, or a chain\n * deeper than two steps.\n */\nexport function planRoute(r: RouteRequest): RoutePlan {\n const issue = r.issues.find((i) => i.number === r.number);\n if (!issue) throw new Error(r.closed(r.number) ? `#${r.number} is closed.` : `There is no open issue #${r.number} on floor ${r.floor}.`);\n if (r.specialty === undefined && r.dependsOn === undefined) throw new Error('Nothing to change: pass specialty, depends_on or both.');\n const plan: RoutePlan = { addLabels: [], removeLabels: [], body: null, summary: '' };\n const done: string[] = [];\n\n if (r.specialty !== undefined) {\n const slug = specialtySlug(r.specialty);\n if (r.specialty.trim() && !slug) throw new Error(`\"${r.specialty}\" is not a specialty. Use a short lowercase slug, or \"\" for none.`);\n if (slug && !r.specialties.includes(slug)) {\n const have = [...new Set(r.specialties)].join(', ') || 'none';\n throw new Error(`Nobody on floor ${r.floor} has the specialty \"${slug}\", and no pending proposal does. Specialties there: ${have}.`);\n }\n const label = slug ? specialtyLabel(slug) : null;\n plan.removeLabels = issue.labels.filter((l) => /^swarm:/i.test(l) && !/^swarm:skip$/i.test(l) && l !== label);\n if (label && !issue.labels.includes(label)) plan.addLabels = [label];\n done.push(slug ? `routed to ${slug}` : 'no specialty');\n }\n\n if (r.dependsOn !== undefined) {\n if (r.inProgress) throw new Error(`#${r.number} is already in progress, so its dependencies can't change. Changing its specialty is fine.`);\n const deps = [...new Set(r.dependsOn.map(Number))];\n const open = new Set(r.issues.map((i) => i.number));\n for (const d of deps) {\n if (d === r.number) throw new Error(`#${r.number} can't depend on itself.`);\n if (!open.has(d)) throw new Error(r.closed(d) ? `#${d} is closed, so there's nothing to wait for.` : `There is no open issue #${d} on floor ${r.floor}.`);\n }\n const body = setDependsOn(issue.body, deps);\n const after = r.issues.map((i) => (i.number === r.number ? { ...i, body } : i));\n const waits = new Map(after.map((i) => [i.number, blockers(i.body, open)]));\n const loop = deps.find((d) => reaches(d, r.number, waits));\n if (loop !== undefined) throw new Error(`#${loop} already waits for #${r.number}, directly or through other issues, so that would be a cycle.`);\n const depth = waitsDepth(r.number, waits) + (holdUps(after).get(r.number)?.chain ?? 0);\n if (depth > 2) throw new Error(`That makes a dependency chain ${depth} steps deep through #${r.number}. Keep chains to 2 steps at most: split the work so more of it can start side by side.`);\n if (body !== issue.body) plan.body = body;\n done.push(deps.length ? `depends on ${deps.map((d) => `#${d}`).join(', ')}` : 'no dependencies');\n }\n\n plan.summary = `#${r.number} on floor ${r.floor}: ${done.join(', ')}.`;\n return plan;\n}\n\n/** Does `from` wait for `to`, directly or through other issues? */\nfunction reaches(from: number, to: number, waits: Map<number, number[]>, seen = new Set<number>()): boolean {\n if (from === to) return true;\n if (seen.has(from)) return false;\n seen.add(from);\n return (waits.get(from) ?? []).some((n) => reaches(n, to, waits, seen));\n}\n\n/** Short lowercase slug for a specialty (\"Three.js graphics\" -> \"three-js-graphics\"). */\nexport function specialtySlug(s: string | undefined) {\n const slug = String(s ?? '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 24);\n return slug === 'skip' ? '' : slug;\n}\n\nexport const specialtyLabel = (slug: string) => `swarm:${slug}`;\n", "// Issue conventions shared by the server's scheduler and the client's whiteboard.\n\n/** The specialty an issue is routed to, from its swarm:<specialty> label ('' = anyone). */\nexport function issueSpecialty(labels: string[]) {\n const l = labels.find((x) => /^swarm:/i.test(x) && !/^swarm:skip$/i.test(x));\n return l ? l.slice(6).toLowerCase() : '';\n}\n\n/** Open issues this issue waits for, from \"Depends on #3\" / \"Blocked by #4, #5\" in its body. */\nexport function blockers(body: string, open: Set<number>) {\n const out = new Set<number>();\n for (const m of (body ?? '').matchAll(/\\b(?:depends\\s+on|blocked\\s+by)\\s*:?\\s*((?:#\\d+(?:\\s*(?:,|and|&)\\s*)?)+)/gi)) {\n for (const n of m[1].matchAll(/#(\\d+)/g)) if (open.has(Number(n[1]))) out.add(Number(n[1]));\n }\n return [...out];\n}\n\nconst DEPENDENCY = /\\b(?:depends\\s+on|blocked\\s+by)\\s*:?\\s*(?:#\\d+(?:\\s*(?:,|and|&)\\s*)?)+/gi;\nconst STATEMENT = new RegExp(`\\\\s*${DEPENDENCY.source}[.;,]?`, 'gi'); // with the space before it and a full stop after\n\n/**\n * An issue body with its \"Depends on #N\" / \"Blocked by #N\" statements replaced by one \"Depends on #a, #b\" line at the\n * top ([] removes them). A line that only said that goes; the rest of the body is left alone.\n */\nexport function setDependsOn(body: string, deps: number[]) {\n const lines: string[] = [];\n let dropped = false;\n for (const line of (body ?? '').split(/\\r?\\n/)) {\n const rest = line.match(DEPENDENCY) ? line.replace(STATEMENT, '').trimEnd() : line;\n if (rest !== line && !/[\\p{L}\\p{N}]/u.test(rest)) {\n dropped = true;\n continue;\n }\n // A dropped line between two paragraphs doesn't leave a double gap.\n if (dropped && !rest.trim() && !lines[lines.length - 1]?.trim()) continue;\n dropped = false;\n lines.push(rest);\n }\n while (lines.length && !lines[0].trim()) lines.shift();\n const rest = lines.join('\\n');\n if (deps.length === 0) return rest;\n return `Depends on ${deps.map((n) => `#${n}`).join(', ')}${rest ? `\\n\\n${rest}` : ''}`;\n}\n\n/**\n * How much of the backlog each open issue holds up: the longest chain of open issues waiting on it (`chain`) and how\n * many wait on it directly or indirectly (`waiting`). Starting the issues with the most behind them first lets the\n * most work run in parallel later.\n */\nexport function holdUps(issues: { number: number; body: string }[]) {\n const open = new Set(issues.map((i) => i.number));\n const waiters = new Map<number, number[]>();\n for (const i of issues) for (const b of blockers(i.body, open)) waiters.set(b, [...(waiters.get(b) ?? []), i.number]);\n const chains = new Map<number, number>();\n const visiting = new Set<number>();\n const chain = (n: number): number => {\n const known = chains.get(n);\n if (known !== undefined) return known;\n if (visiting.has(n)) return 0; // a dependency cycle\n visiting.add(n);\n const longest = Math.max(0, ...(waiters.get(n) ?? []).map((w) => chain(w) + 1));\n visiting.delete(n);\n chains.set(n, longest);\n return longest;\n };\n const out = new Map<number, { chain: number; waiting: number }>();\n for (const i of issues) {\n const seen = new Set<number>();\n const stack = [...(waiters.get(i.number) ?? [])];\n while (stack.length) {\n const n = stack.pop()!;\n if (n === i.number || seen.has(n)) continue;\n seen.add(n);\n stack.push(...(waiters.get(n) ?? []));\n }\n out.set(i.number, { chain: chain(i.number), waiting: seen.size });\n }\n return out;\n}\n", "// After a fix session that ended well: did it push anything? A QA fix or a conflict resolution that left the PR's head\n// where it was fixed nothing, so it counts as a failed session: QA doesn't re-test the same commit, and the manager\n// hears \"nothing was pushed\" rather than another identical QA report. A checks fix may rightly push nothing (it can\n// re-run a flaky check).\n\n/** Failed fix sessions in a row (unpushed ones included) before the PR goes to the manager. */\nexport const MAX_FIX_FAILURES = 2;\n\n/** The parts of a QA record a finished fix reads. */\nexport interface FixRecord {\n prNumber: number;\n round: number;\n sessionFailures: number;\n testedSha: string | null;\n passedSha: string | null;\n fixReason: 'qa' | 'checks' | 'conflict' | null;\n}\n\nexport type FixPatch = Partial<{ status: 'queued' | 'passed' | 'failed' | 'needs-human'; round: number; sessionFailures: number; mergeNote: string | null }>;\n\nexport interface FixOutcome {\n set: FixPatch;\n log: { kind: 'done' | 'error'; text: string };\n pushed: boolean;\n}\n\n/**\n * What a fix session that ended well did to its PR. head: the PR's head commit now (null: GitHub couldn't be asked,\n * so the session is taken at its word). counts: false while Claude's usage limit is hit, which isn't the PR's fault.\n */\nexport function fixOutcome(rec: FixRecord, head: string | null, minutes: number, counts = true): FixOutcome {\n const pr = rec.prNumber;\n // The commit the fix started from: the one QA failed, or the one QA passed (and auto-merge kept) for a conflict.\n const before = rec.fixReason === 'conflict' ? (rec.passedSha ?? rec.testedSha) : rec.testedSha;\n if (rec.fixReason !== 'checks' && head && before && head === before) {\n const sessionFailures = rec.sessionFailures + (counts ? 1 : 0);\n const needsHuman = sessionFailures >= MAX_FIX_FAILURES;\n return {\n set: needsHuman\n ? { status: 'needs-human', sessionFailures, mergeNote: rec.fixReason === 'conflict' ? 'the conflict was never resolved' : 'the fix was never pushed' }\n : { status: 'failed', sessionFailures },\n log: { kind: 'error', text: `\u2717 No new commits were pushed for PR #${pr}` },\n pushed: false,\n };\n }\n if (rec.fixReason === 'checks' || rec.fixReason === 'conflict') {\n // Back in line to merge: new commits go through QA again first, a re-run of flaky checks doesn't.\n return { set: { status: 'passed', sessionFailures: 0, mergeNote: 'waiting for fresh checks' }, log: { kind: 'done', text: `\u2714 PR #${pr} fixed in ${minutes}m. Back in line to merge.` }, pushed: true };\n }\n return { set: { status: 'queued', round: rec.round + 1, sessionFailures: 0 }, log: { kind: 'done', text: `\u2714 Fix pushed for PR #${pr} in ${minutes}m. Back to QA.` }, pushed: true };\n}\n", "/** An error the REST layer turns into this status with a JSON { error } body. */\nexport class HttpError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message);\n }\n}\n", "import type { PullInfo } from '../shared/types.ts';\n\n// Whether an issue is still free work. A merged PR's issue stays open on GitHub until \"Closes #N\" catches up (or for\n// good, when the link wasn't recognised), so an issue counts as taken while a PR is open for it and as done for a\n// while after one merged. The office also closes what it merges itself (issuesResolvedBy).\n\n/** How long a merged PR keeps its issues off the market, however long GitHub takes to close them. */\nexport const RECENT_MERGE_MS = 6 * 60 * 60_000;\n\nexport type ClaimPull = Pick<PullInfo, 'state' | 'headRefName' | 'closesIssues' | 'mergedAt'>;\n\nexport interface ClaimAgent {\n role: string;\n task: string | null;\n issueNumber: number | null;\n status: string;\n}\n\n/** The issue a swarm/issue-<n>-\u2026 branch was cut for. */\nexport function branchIssue(headRefName: string): number | null {\n const m = /^swarm\\/issue-(\\d+)-/.exec(headRefName);\n return m ? Number(m[1]) : null;\n}\n\n/** Issues a PR resolves: the ones it formally links, plus its swarm/issue-<n>-\u2026 branch's (people's branches only link). */\nexport function issuesResolvedBy(pr: Pick<PullInfo, 'headRefName' | 'closesIssues'>): number[] {\n const n = branchIssue(pr.headRefName);\n return [...new Set(n == null ? pr.closesIssues : [...pr.closesIssues, n])];\n}\n\n/** Issue n is taken (a developer is on it, or a PR is open for it) or done (a PR for it merged recently). */\nexport function issueTaken(n: number, agents: ClaimAgent[], pulls: ClaimPull[], now: number): boolean {\n if (agents.some((a) => a.role === 'dev' && a.task !== 'qa' && a.issueNumber === n && a.status !== 'idle' && a.status !== 'error')) return true;\n return pulls.some((p) => {\n if (p.state === 'CLOSED') return false; // closed without merging: the issue is free again\n if (p.state === 'MERGED' && (!p.mergedAt || now - Date.parse(p.mergedAt) > RECENT_MERGE_MS)) return false;\n return issuesResolvedBy(p).includes(n);\n });\n}\n", "import type { PullInfo } from '../shared/types.ts';\n\n// Auto-merge: fixes for failing checks or conflicts before a PR needs the manager, how long checks may run before\n// the manager hears about it, and how long to wait before retrying a merge GitHub refused.\nexport const MAX_MERGE_FIXES = 3;\nexport const CHECKS_ALERT_MS = 30 * 60_000;\nexport const MERGE_RETRY_MS = 10 * 60_000;\n\n/** The parts of a QA record the merge gate reads. */\nexport interface MergeRecord {\n passedSha: string | null;\n mergeFixes: number;\n pendingSince: number | null;\n mergeRetryAt: number | null;\n alerted: boolean;\n}\n\n/** Bookkeeping the caller writes onto the record as it is (it doesn't count as a change to the record). */\nexport type MergeBookkeeping = Partial<Pick<MergeRecord, 'passedSha' | 'pendingSince' | 'alerted'>>;\n\nexport type MergePull = Pick<PullInfo, 'isDraft' | 'mergeable' | 'mergeState' | 'headSha' | 'checks' | 'failedChecks' | 'pendingChecks'>;\n\n/** What auto-merge does next with a QA-passed PR. */\nexport type MergeStep = { set: MergeBookkeeping } & (\n | { do: 'wait'; note?: string; alert?: boolean } // no note: leave the card as it is; alert: tell the manager checks are slow\n | { do: 'details' } // GitHub hasn't worked out mergeability: ask about the PR itself, then decide again with `detailed`\n | { do: 'requeue' } // commits arrived after QA's sign-off: QA tests them too\n | { do: 'send-back'; reason: 'checks' | 'conflict'; instructions: string; needsHuman: boolean } // needsHuman: the fix budget ran out\n | { do: 'update-branch' } // the repo only merges up-to-date branches\n | { do: 'merge' }\n);\n\n/**\n * Decide the next step toward merging a PR QA has passed. Pure: advanceMerge (swarm.ts) does the talking to GitHub\n * and the office. `detailed` means the PR's mergeability has already been asked for, so UNKNOWN is waited out.\n */\nexport function mergeStep(pr: MergePull, rec: MergeRecord, now: number, opts: { base: string; detailed?: boolean }): MergeStep {\n if (pr.isDraft) return { do: 'wait', note: 'a draft: waiting', set: {} };\n if (!opts.detailed && (pr.mergeable === 'UNKNOWN' || pr.mergeState === 'UNKNOWN')) return { do: 'details', set: {} };\n const set: MergeBookkeeping = {};\n if (rec.passedSha == null) set.passedSha = pr.headSha; // signed off before the office tracked commits\n if (pr.headSha !== (set.passedSha ?? rec.passedSha)) return { do: 'requeue', set };\n const needsHuman = rec.mergeFixes >= MAX_MERGE_FIXES;\n if (pr.mergeable === 'CONFLICTING' || pr.mergeState === 'DIRTY') {\n return { do: 'send-back', reason: 'conflict', instructions: `It conflicts with ${opts.base}.`, needsHuman, set };\n }\n if (pr.checks === 'failing') {\n const instructions = pr.failedChecks.map((c) => `- ${c.name}${c.url ? `: ${c.url}` : ''}`).join('\\n');\n return { do: 'send-back', reason: 'checks', instructions, needsHuman, set };\n }\n if (pr.checks === 'pending') {\n const since = rec.pendingSince ?? now;\n if (rec.pendingSince == null) set.pendingSince = since;\n const alert = now - since > CHECKS_ALERT_MS && !rec.alerted;\n if (alert) set.alerted = true;\n return { do: 'wait', note: `waiting for checks: ${pr.pendingChecks.join(', ') || 'running'}`, alert, set };\n }\n set.pendingSince = null;\n if (pr.mergeable === 'UNKNOWN') return { do: 'wait', note: 'GitHub is checking it can merge', set };\n if (pr.mergeState === 'BEHIND') return { do: 'update-branch', set };\n if (rec.mergeRetryAt && now < rec.mergeRetryAt) return { do: 'wait', set };\n return { do: 'merge', set };\n}\n", "// QA a restart left behind. A tester is marked done before their report is posted, and the PR only leaves \"testing\"\n// once it is: an office that stops in between comes back with a PR in \"testing\" that nobody is testing. Startup\n// recovery only looks at agents that were busy, the scheduler and \"Send to QA\" both skip a PR in \"testing\", and the\n// board offers no button for it, so the PR would sit there for good.\n\nexport interface OrphanQaRecord {\n repoId: string;\n prNumber: number;\n status: string;\n qaAgentId: string | null;\n}\n\nexport interface OrphanQaAgent {\n id: string;\n repoId: string;\n status: string;\n task: string | null;\n prNumber: number | null;\n}\n\n/**\n * The QA records marked \"testing\" that no busy agent is testing. Only meaningful when nothing can be mid-way through\n * finishing a QA session, i.e. at startup: while the office runs, a finished tester's report may still be posting.\n */\nexport function orphanedQa<R extends OrphanQaRecord>(qa: readonly R[], agents: readonly OrphanQaAgent[], busy: readonly string[]): R[] {\n return qa.filter(\n (q) =>\n q.status === 'testing' &&\n !agents.some((a) => a.id === q.qaAgentId && busy.includes(a.status) && a.task === 'qa' && a.repoId === q.repoId && a.prNumber === q.prNumber),\n );\n}\n", "// After an office restart: whose work picks up where it was, and what they're told. An agent still preparing a task\n// hadn't started that task's session yet, so the session it remembers, or a CLI still busy in its terminal, belongs to\n// an earlier task: resuming it would do that task again (a QA verdict posted twice) and pass the result off as this one.\n\nexport interface RestartAgent {\n status: string;\n task: 'issue' | 'qa' | 'fix' | null;\n sessionId: string | null;\n branch: string | null;\n issueNumber: number | null;\n issueTitle: string | null;\n prNumber: number | null;\n}\n\n/** A CLI the terminal keeper kept running through the restart. resumeId: the session it is on, when known. */\nexport interface KeptCli {\n busy: boolean;\n resumeId: string | null;\n}\n\n/** The office follows a CLI that kept working through the restart only when it is on the agent's current task. */\nexport function followKeptCli(a: RestartAgent, cli: KeptCli | undefined): boolean {\n if (!cli?.busy || a.status === 'preparing') return false;\n return !(a.sessionId && cli.resumeId && cli.resumeId !== a.sessionId);\n}\n\n/**\n * An agent cut off by the restart resumes its session (true), or its work goes back in line: QA, the demo, and a task\n * that was still being prepared (preparing: its status when the office stopped), whose session never started.\n */\nexport function resumesAfterRestart(a: RestartAgent, preparing: boolean, demo: boolean): boolean {\n return !demo && !preparing && a.task !== 'qa' && !!a.sessionId && !!a.branch;\n}\n\n/** What a resumed agent is told: the job it was on, not just \"carry on\". */\nexport function resumeNote(a: RestartAgent, fix?: { round: number; fixReason: 'qa' | 'checks' | 'conflict' | null } | null): string {\n const yours = 'Uncommitted changes in your worktree are yours to finish.';\n if (a.task === 'fix' && a.prNumber && a.branch) {\n const job =\n fix?.fixReason === 'conflict'\n ? `resolving the merge conflicts on PR #${a.prNumber}`\n : fix?.fixReason === 'checks'\n ? `fixing the failing checks on PR #${a.prNumber}`\n : `fixing PR #${a.prNumber}${fix ? ` after QA round ${fix.round}` : ''}`;\n return `The office server restarted while you were ${job}. Finish the fix, commit, and push with: git push origin HEAD:${a.branch}. ${yours}`;\n }\n if (a.task === 'issue' && a.issueNumber && a.branch) {\n const pr = a.prNumber\n ? `push with: git push origin ${a.branch} to update PR #${a.prNumber}`\n : `push with: git push -u origin ${a.branch}, and open the pull request with \"Closes #${a.issueNumber}\" (or push to it if it's already open)`;\n return `The office server restarted while you were working on issue #${a.issueNumber}${a.issueTitle ? ` (${a.issueTitle})` : ''} on branch ${a.branch}. Finish it, commit, ${pr}. ${yours}`;\n }\n return 'The office server restarted while you were working. Check the state of your worktree and continue where you left off.';\n}\n", "import type { Backend } from './backend.ts';\nimport { PORT } from './config.ts';\nimport { HttpError } from './httpError.ts';\nimport { PREVIEW_SLUG, portOpen, type PreviewHandle } from './previewRunner.ts';\nimport type { PreviewConfig, PreviewStatus, PreviewView, PullInfo } from '../shared/types.ts';\n\n// One preview per floor: the floor's app, run from its own worktree on a port reserved for the floor.\n// Only the config is persisted; after a restart every preview reads 'stopped'.\n\n/** What the previews need to know about a floor. */\nexport interface PreviewFloor {\n id: string;\n fullName: string;\n defaultBranch: string;\n floor: number;\n preview: PreviewConfig;\n}\n\ninterface Run {\n status: PreviewStatus;\n port: number | null; // the port of the current or last run\n ref: string | null;\n pr: number | null;\n commit: string | null;\n startedAt: number | null;\n error: string | null;\n log: string[];\n handle: PreviewHandle | null;\n gen: number; // bumped by every start / stop; callbacks from older runs are ignored\n}\n\nconst PREVIEW_BASE_PORT = 6300;\nconst LOG_KEEP = 200;\nconst LOG_VIEW = 40;\nconst ACTIVE: PreviewStatus[] = ['preparing', 'installing', 'starting', 'running'];\n\n/** Never the office itself, the other office port, or the agents' range. */\nconst forbidden = (p: number) => p === PORT || p === 4317 || p === 5317 || (p >= 5200 && p <= 5899);\n\nexport const DEFAULT_PREVIEW: PreviewConfig = { command: null, env: {} };\n\n/** Check a previewCommand / previewEnv patch; throws 400 on bad input. undefined: not in the patch. */\nexport function parsePreviewPatch(command: unknown, env: unknown): Partial<PreviewConfig> {\n const out: Partial<PreviewConfig> = {};\n if (command !== undefined) {\n if (command !== null && typeof command !== 'string') throw new HttpError(400, 'previewCommand must be a string or null');\n const c = (command ?? '').trim();\n if (c.length > 2000) throw new HttpError(400, 'previewCommand is too long');\n out.command = c || null;\n }\n if (env !== undefined) {\n if (env === null) out.env = {};\n else {\n if (typeof env !== 'object' || Array.isArray(env)) throw new HttpError(400, 'previewEnv must be an object of string values');\n const entries = Object.entries(env as Record<string, unknown>);\n if (entries.length > 50) throw new HttpError(400, 'previewEnv has too many variables');\n for (const [k, v] of entries) {\n if (typeof v !== 'string') throw new HttpError(400, `previewEnv.${k} must be a string`);\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) throw new HttpError(400, `\"${k}\" is not a valid environment variable name`);\n if (/^(ANTHROPIC_|CLAUDE)/i.test(k)) throw new HttpError(400, `${k} can't be set on a preview: Claude credentials never reach the apps the office runs`);\n if (v.length > 4000) throw new HttpError(400, `previewEnv.${k} is too long`);\n }\n out.env = Object.fromEntries(entries) as Record<string, string>;\n }\n }\n return out;\n}\n\nexport class Previews {\n private runs = new Map<string, Run>();\n private hasDefault = new Map<string, boolean>(); // floor id -> package.json in its checkout\n private emitTimers = new Map<string, NodeJS.Timeout>();\n\n constructor(\n private backend: Backend,\n private hooks: { emit(repoId: string): void; pulls(repoId: string): PullInfo[] },\n ) {}\n\n private run(id: string): Run {\n let r = this.runs.get(id);\n if (!r) {\n r = { status: 'stopped', port: null, ref: null, pr: null, commit: null, startedAt: null, error: null, log: [], handle: null, gen: 0 };\n this.runs.set(id, r);\n }\n return r;\n }\n\n /** The floor's reserved port: 6300 + floor, moved up by 100 while it clashes with the office or another preview. */\n portFor(f: PreviewFloor): number {\n const active = this.runs.get(f.id);\n if (active?.port && ACTIVE.includes(active.status)) return active.port;\n const taken = new Set([...this.runs.entries()].filter(([id, r]) => id !== f.id && r.port && ACTIVE.includes(r.status)).map(([, r]) => r.port!));\n let p = PREVIEW_BASE_PORT + f.floor;\n while (forbidden(p) || taken.has(p)) p += 100;\n return p;\n }\n\n view(f: PreviewFloor): PreviewView {\n const r = this.runs.get(f.id);\n let status: PreviewStatus = r?.status ?? 'stopped';\n if (status === 'stopped' && !f.preview.command && this.hasDefault.get(f.id) === false) status = 'unconfigured';\n const port = r?.port ?? this.portFor(f);\n return {\n status,\n port,\n url: status === 'running' ? `http://localhost:${port}/` : null,\n ref: r?.ref ?? null,\n pr: r?.pr ?? null,\n commit: r?.commit ?? null,\n startedAt: r?.startedAt ?? null,\n error: r?.error ?? null,\n logTail: (r?.log ?? []).slice(-LOG_VIEW),\n };\n }\n\n /** Re-check whether a floor without a command has a package.json to fall back on. */\n async refreshDefault(f: PreviewFloor) {\n const has = await this.backend.previews.hasDefault(f.fullName).catch(() => true);\n if (this.hasDefault.get(f.id) === has) return;\n this.hasDefault.set(f.id, has);\n this.hooks.emit(f.id);\n }\n\n /** Start the floor's preview on the default branch or an open PR, replacing whatever it is running now. */\n async start(f: PreviewFloor, title: string, pr?: number | null): Promise<PreviewView> {\n if (pr !== undefined && pr !== null && (!Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, `Invalid pull request number: ${pr}`);\n if (pr) await this.checkOpen(f, pr);\n const r = this.run(f.id);\n const gen = ++r.gen;\n await this.halt(f, r);\n if (gen !== r.gen) return this.view(f); // another start or a stop came in meanwhile\n\n const port = this.portFor(f);\n const ref = pr ? `PR #${pr}` : f.defaultBranch;\n Object.assign(r, { port, ref, pr: pr ?? null, commit: null, startedAt: Date.now(), error: null, log: [] });\n if (await portOpen(port)) {\n if (gen !== r.gen) return this.view(f);\n Object.assign(r, { status: 'error', error: `Port ${port} is already in use by another program. The office won't stop it; free the port and try again.` });\n this.hooks.emit(f.id);\n throw new HttpError(409, r.error!);\n }\n if (gen !== r.gen) return this.view(f);\n r.status = 'preparing';\n this.hooks.emit(f.id);\n\n const live = () => gen === r.gen;\n r.handle = this.backend.previews.start(\n { fullName: f.fullName, defaultBranch: f.defaultBranch, pr: pr ?? null, port, command: f.preview.command, env: { ...f.preview.env }, title: `${title} \u00B7 ${ref}` },\n {\n status: (s) => {\n if (!live()) return;\n r.status = s;\n this.hooks.emit(f.id);\n },\n commit: (sha) => {\n if (!live()) return;\n r.commit = sha || null;\n this.hooks.emit(f.id);\n },\n log: (lines) => {\n if (!live()) return;\n r.log.push(...lines.map((l) => l.slice(0, 500)));\n if (r.log.length > LOG_KEEP) r.log.splice(0, r.log.length - LOG_KEEP);\n this.emitSoon(f.id);\n },\n failed: (message, unconfigured) => {\n if (!live()) return;\n r.handle = null;\n Object.assign(r, { status: unconfigured ? 'unconfigured' : 'error', error: message });\n if (unconfigured) this.hasDefault.set(f.id, false);\n this.hooks.emit(f.id);\n // Anything the app left behind in its worktree or on its port goes too.\n void this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, port).catch(() => undefined);\n },\n },\n );\n return this.view(f);\n }\n\n /** Stop the floor's preview and free its port. */\n async stop(f: PreviewFloor): Promise<PreviewView> {\n const r = this.run(f.id);\n r.gen++;\n await this.halt(f, r);\n Object.assign(r, { status: 'stopped', error: null, startedAt: null });\n this.hooks.emit(f.id);\n return this.view(f);\n }\n\n /** The floor is leaving the building: stop its preview and remove the preview worktree. */\n async remove(f: PreviewFloor) {\n const main = this.backend.mainDir(f.fullName); // now: the floor points away from its folder before the preview stops\n const r = this.runs.get(f.id);\n if (r) {\n r.gen++;\n await this.halt(f, r);\n }\n this.runs.delete(f.id);\n this.hasDefault.delete(f.id);\n clearTimeout(this.emitTimers.get(f.id));\n await this.backend.removeDesk(f.fullName, PREVIEW_SLUG, main).catch(() => undefined);\n }\n\n /** Server shutdown: stop every running preview. */\n async stopAll(floors: PreviewFloor[]) {\n await Promise.all(\n floors.map((f) => {\n const r = this.runs.get(f.id);\n if (!r) return;\n r.gen++;\n return this.halt(f, r);\n }),\n );\n }\n\n /** Server start: nothing is running yet, so anything alive in a preview worktree or on a preview port is an orphan. */\n async clearOrphans(floors: PreviewFloor[]) {\n await Promise.all(floors.map((f) => this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, this.portFor(f)).catch(() => undefined)));\n }\n\n private async halt(f: PreviewFloor, r: Run) {\n const handle = r.handle;\n r.handle = null;\n if (!handle) return;\n await handle.stop().catch(() => undefined);\n if (!r.port) return;\n await this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, r.port).catch(() => undefined);\n // Windows can take a moment to let go of a killed process's socket.\n for (let i = 0; i < 20 && (await portOpen(r.port)); i++) await new Promise((res) => setTimeout(res, 250));\n }\n\n private async checkOpen(f: PreviewFloor, pr: number) {\n const known = this.hooks.pulls(f.id).find((p) => p.number === pr);\n const state = known?.state ?? (await this.backend.prDetails(f.fullName, pr).then((d) => d.state).catch(() => null));\n if (!state) throw new HttpError(404, `${f.fullName} has no pull request #${pr}`);\n if (state !== 'OPEN') throw new HttpError(400, `Pull request #${pr} is ${state.toLowerCase()}, not open`);\n }\n\n /** Log lines arrive in bursts (npm install); send them at most once a second. */\n private emitSoon(id: string) {\n if (this.emitTimers.has(id)) return;\n this.emitTimers.set(\n id,\n setTimeout(() => {\n this.emitTimers.delete(id);\n if (this.runs.has(id)) this.hooks.emit(id);\n }, 1000),\n );\n }\n}\n", "// What developers and QA testers are told on every task: the system prompt the office appends for each session, as\n// pure functions, so the manager can preview it (GET /api/agents/:id/prompt) without a live task. The job\n// description is the one part the manager edits; the rest carries the office's workflow and safety rules.\n\nimport type { AgentPromptView, AgentRole, PromptPart } from '../shared/types.ts';\n\nexport interface PromptAgent {\n name: string;\n role: AgentRole;\n title: string;\n brief: string;\n}\n\nexport interface PromptFloor {\n fullName: string;\n defaultBranch: string;\n autoMerge: boolean;\n browserTesting: boolean;\n summary: string;\n mission: string;\n qaBrief: string;\n}\n\ninterface PromptBase {\n agent: PromptAgent;\n repo: PromptFloor;\n /** Their dev-server port, reserved per agent. */\n port: number;\n cwd: string;\n branch: string;\n}\n\nexport interface DevPromptInput extends PromptBase {\n /** Connected repositories they may read, with their clone paths. */\n linked: { fullName: string; dir: string }[];\n /** Fixing an open pull request rather than starting an issue. */\n fixing?: { pr: number; headRef: string };\n}\n\nexport interface QaPromptInput extends PromptBase {\n pr: { number: number | string; title: string; headRefName: string; url: string };\n}\n\n/** Stand-ins for a task's details in a preview. */\nexport const PLACEHOLDERS = {\n worktree: '<your worktree>',\n issue: '<issue>',\n pr: '<PR>',\n prTitle: '<PR title>',\n prUrl: '<PR URL>',\n branch: '<branch>',\n} as const;\n\nexport const devBranch = (issue: number | string, slug: string) => `swarm/issue-${issue}-${slug}`;\nexport const qaBranch = (pr: number | string, slug: string) => `qa/pr-${pr}-${slug}`;\n\nexport function devSystemPrompt({ agent: a, repo, port, cwd, branch, linked, fixing }: DevPromptInput) {\n const push = fixing ? `git push origin HEAD:${fixing.headRef}` : `git push -u origin ${branch}`;\n const links = linked.map((r) => `- ${r.fullName}: read-only reference clone at ${r.dir}`);\n return [\n `You are ${a.name}, ${a.title ? `the team's ${a.title},` : 'a software engineer'} on an autonomous agent team (\"cubefarm\"). Several teammates work in parallel on other issues of the same repository, each in their own git worktree. Nobody is watching live to answer questions, so make sensible decisions yourself and record assumptions in the PR description. The manager may occasionally send you messages; follow their instructions.`,\n `Every pull request is reviewed and tested by a QA teammate. ${repo.autoMerge ? \"Once they sign off and GitHub's checks pass, the office merges it by itself\" : 'Once they sign off, the manager merges it'}. If they find problems, or checks fail, or it conflicts with the default branch, you will get the details; fix them on the same branch.`,\n a.brief ? `\\nYour job description:\\n${a.brief}` : '',\n '',\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\n repo.summary ? `Project: ${repo.summary}` : '',\n repo.mission ? `What the team is building (the manager's brief): ${repo.mission}` : '',\n `Your worktree: ${cwd}`,\n fixing\n ? `You are fixing pull request #${fixing.pr}. Its code is checked out on local branch ${branch}; push fixes with: ${push}. Do not open a new pull request.`\n : `Your branch: ${branch} (already checked out, created from origin/${repo.defaultBranch})`,\n links.length ? `Related repositories you may read for context (do not modify them):\\n${links.join('\\n')}` : '',\n '',\n 'Workflow:',\n '1. Read the issue and explore the relevant code before changing anything.',\n '2. Implement the change with focused commits and clear messages.',\n \"3. Run the project's existing tests, linters and build (if any) and fix what you broke. Install dependencies first if needed.\",\n repo.browserTesting\n ? `4. If the project has a web UI, start its dev server in the background on port ${port} (reserved for you, so you don't collide with teammates), then check your change with the Playwright browser tools (mcp__playwright__browser_navigate, browser_snapshot, browser_click, browser_take_screenshot). Stop the dev server when you're done.`\n : '4. Verify the behaviour you changed as directly as you can.',\n `5. Push: ${push}`,\n fixing\n ? '6. Reply with a short summary of what you fixed.'\n : `6. Open a pull request with the GitHub CLI: gh pr create --base ${repo.defaultBranch} --head ${branch} --title \"<concise title>\" --body \"<what changed, how you verified it, assumptions>\". The body must contain \"Closes #<issue number>\".`,\n fixing ? '' : '7. End your final message with the pull request URL on its own line.',\n '',\n 'Rules: never push to the default branch, never force-push, never merge pull requests yourself (the office merges them once QA and the checks pass), and never edit files outside your worktree. If you cannot finish, open a draft PR (gh pr create --draft) explaining what is left and why.',\n ]\n .filter((l) => l !== '')\n .join('\\n');\n}\n\nexport function qaSystemPrompt({ agent: a, repo, port, cwd, branch, pr }: QaPromptInput) {\n return [\n `You are ${a.name}, ${a.title ? `the team's ${a.title},` : 'a QA engineer'} on an autonomous agent team (\"cubefarm\"). Developers open pull requests; you review and independently verify each one before it is merged. Your sign-off is the review: ${repo.autoMerge ? \"on this floor a PR you pass merges by itself as soon as GitHub's checks are green, so nobody else reads the code after you. \" : ''}Be thorough and skeptical, but fair: fail a PR only for real problems (broken behaviour, failing tests or build, the issue's requirements not met, obvious regressions), not for style preferences.`,\n ...(a.brief ? ['', `Your job description:\\n${a.brief}`] : []),\n ...(a.role === 'dev' ? ['', \"You're a developer covering for the QA lab while its testers are busy. You didn't write this pull request: test it as an independent QA engineer would.\"] : []),\n '',\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\n ...(repo.summary ? [`Project: ${repo.summary}`] : []),\n ...(repo.mission ? [`What the team is building (the manager's brief): ${repo.mission}`] : []),\n ...(repo.qaBrief ? [`What to check on this project (from the CEO):\\n${repo.qaBrief}`] : []),\n `Pull request #${pr.number} \"${pr.title}\" from branch ${pr.headRefName}: ${pr.url}`,\n `Your worktree: ${cwd}. It has the pull request's code checked out on local branch ${branch}.`,\n '',\n 'How to test:',\n '1. Read the PR description and the linked issue, and work out the acceptance criteria.',\n `2. Review the code as a careful reviewer would: git diff origin/${repo.defaultBranch}...HEAD. Look for bugs, unhandled errors and edge cases, security problems, leftover debug code, and new logic without tests.`,\n \"3. Install dependencies if needed, then run the project's test suite, linters, type checks and build (whichever exist).\",\n repo.browserTesting\n ? `4. If the project has a UI, start it in the background on port ${port} (reserved for you) and exercise the change in a real browser with the Playwright tools: navigate, click, type, resize to a phone size, try edge cases, and check the console for errors. Take a screenshot with browser_take_screenshot (no filename) of every important state: the screenshots are attached to the PR as evidence. Stop the server afterwards.`\n : '4. Exercise the changed behaviour directly (run the program, call the API, write a quick script).',\n '5. You may write throwaway scripts to probe behaviour, but do not commit them.',\n '',\n 'Rules: do not modify the code under test, do not commit, push, comment on, review or merge anything on GitHub. The office posts your report on the pull request. Finish with the structured QA report: verdict, summary, the checks you performed, the commands you ran and one caption per screenshot.',\n ].join('\\n');\n}\n\n// ---------- previews ----------\n\nconst OFFICE = 'Office instructions';\n// Stands in for the job description while the prompt is built, so the parts split exactly around it.\nconst MARK = '\\u0000job description\\u0000';\n\n/** Splits a prompt around the job description, which is the one editable part. */\nexport function promptParts(build: (brief: string) => string, brief: string): PromptPart[] {\n if (!brief) return [{ label: OFFICE, text: build(''), editable: false }];\n const [before, after] = build(MARK).split(MARK);\n return [\n { label: OFFICE, text: before, editable: false },\n { label: 'Job description', text: brief, editable: true },\n { label: OFFICE, text: after, editable: false },\n ].filter((p) => p.text !== '');\n}\n\nconst view = (kind: AgentPromptView['kind'], parts: PromptPart[]): AgentPromptView => ({ kind, text: parts.map((p) => p.text).join(''), parts });\n\ntype PreviewInput = Omit<PromptBase, 'cwd' | 'branch'> & { slug: string };\n\n/** What a developer is told when they start an issue, with placeholders for the issue and their worktree. */\nexport function devPromptPreview({ slug, ...i }: PreviewInput & Pick<DevPromptInput, 'linked'>): AgentPromptView {\n const branch = devBranch(PLACEHOLDERS.issue, slug);\n return view('dev', promptParts((brief) => devSystemPrompt({ ...i, agent: { ...i.agent, brief }, cwd: PLACEHOLDERS.worktree, branch }), i.agent.brief));\n}\n\n/** What a QA tester is told when they test a pull request, with placeholders for the PR and their worktree. */\nexport function qaPromptPreview({ slug, ...i }: PreviewInput): AgentPromptView {\n const pr = { number: PLACEHOLDERS.pr, title: PLACEHOLDERS.prTitle, headRefName: PLACEHOLDERS.branch, url: PLACEHOLDERS.prUrl };\n const branch = qaBranch(PLACEHOLDERS.pr, slug);\n return view('qa', promptParts((brief) => qaSystemPrompt({ ...i, agent: { ...i.agent, brief }, cwd: PLACEHOLDERS.worktree, branch, pr }), i.agent.brief));\n}\n\n/** The CEO's prompt has no job description of theirs in it: all of it is the office's. */\nexport const ceoPromptPreview = (text: string): AgentPromptView => view('ceo', [{ label: OFFICE, text, editable: false }]);\n", "import type { UsageView } from '../shared/types.ts';\n\n// Pacing new work on Claude's usage warnings (#40). Every agent shares one subscription. When Claude warns that\n// usage is getting high, the office slows down instead of running into the hard limit: finishing beats starting.\n// QA, QA fixes and CEO jobs start as normal; new issues only while fewer than settings.pacingSessions sessions run.\n\n/** How long pacing lasts when Claude doesn't say when the window resets. */\nexport const PACING_MS = 60 * 60_000;\nexport const DEFAULT_PACING_SESSIONS = 3;\n\n/** What a session is started for. Only new issues are held back while pacing. */\nexport type WorkKind = 'issue' | 'qa' | 'fix' | 'ceo';\n\nexport interface UsageClock {\n now: number;\n pausedUntil: number; // Claude rejected a session for the usage limit: nothing new starts before this\n pacingUntil: number; // Claude warned about usage: new issues are paced until this\n}\n\n/** May work of this kind start now? A rejection pauses everything; pacing caps new issues at `pacingSessions` running. */\nexport function mayStart(kind: WorkKind, c: UsageClock & { running: number; pacingSessions: number }): boolean {\n if (c.now < c.pausedUntil) return false;\n if (kind === 'issue' && c.now < c.pacingUntil) return c.running < c.pacingSessions;\n return true;\n}\n\n/** The usage state for the snapshot. */\nexport function usageView(c: UsageClock): UsageView {\n if (c.now < c.pausedUntil) return { state: 'paused', until: c.pausedUntil };\n if (c.now < c.pacingUntil) return { state: 'pacing', until: c.pacingUntil };\n return { state: 'normal', until: null };\n}\n\n/** \"14:30\", with the weekday when it isn't today. */\nexport function clock(at: number, now: number): string {\n const d = new Date(at);\n const hm = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;\n return d.toDateString() === new Date(now).toDateString() ? hm : `${d.toLocaleDateString('en-US', { weekday: 'short' })} ${hm}`;\n}\n\n/** company.usage for the CEO: \"normal\", \"pacing until 14:30\" or \"paused until 14:30\". */\nexport function usageLabel(u: UsageView, now: number): string {\n return u.state === 'normal' || u.until === null ? 'normal' : `${u.state} until ${clock(u.until, now)}`;\n}\n\n/** Clamp the pacing cap from the settings (1-32, default 3). */\nexport function clampPacingSessions(v: unknown): number {\n const n = Math.round(Number(v));\n return Number.isFinite(n) && n > 0 ? Math.min(32, n) : DEFAULT_PACING_SESSIONS;\n}\n\nconst LIMIT_NAMES: Record<string, string> = {\n five_hour: '5-hour limit',\n seven_day: 'weekly limit',\n seven_day_opus: 'weekly Opus limit',\n seven_day_sonnet: 'weekly Sonnet limit',\n};\n\n/** A usage warning as the SDK reports it. utilization may be a fraction (0.82) or a percentage (82). */\nexport interface UsageWarning {\n resetsAt: number | null; // epoch ms\n rateLimitType: string | null;\n utilization: number | null;\n}\n\n/** The phone message when pacing starts. */\nexport function pacingMessage(w: UsageWarning, until: number, sessions: number, now: number): string {\n const pct = w.utilization === null ? null : Math.round(w.utilization <= 1 ? w.utilization * 100 : w.utilization);\n const what = [w.rateLimitType ? (LIMIT_NAMES[w.rateLimitType] ?? w.rateLimitType.replace(/_/g, ' ')) : null, pct === null ? null : `${pct}%`].filter(Boolean).join(', ');\n return `\uD83D\uDC22 Claude's usage is getting high${what ? ` (${what})` : ''}. Until ${clock(until, now)} the office finishes open work first and starts at most ${sessions} session${sessions === 1 ? '' : 's'} at a time.`;\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport xtermHeadless from '@xterm/headless';\nimport xtermSerialize from '@xterm/addon-serialize';\nimport type { WebSocket } from 'ws';\nimport type { TermClientMessage, TermServerMessage } from '../shared/types.ts';\n\n// An agent's terminal: a headless xterm that mirrors everything its CLI printed, so a browser that opens it late (or\n// reconnects) gets the same screen and scrollback, plus the viewers watching it live. The CLI itself is bound as the\n// sink: keystrokes and resizes from viewers go to whichever CLI process is running in it right now.\n\nconst { Terminal } = xtermHeadless;\nconst { SerializeAddon } = xtermSerialize;\n\nexport const TERM_COLS = 120;\nexport const TERM_ROWS = 32;\nconst SCROLLBACK = 5000;\n/** A viewer this far behind stops getting output and is sent a fresh snapshot once it catches up. */\nconst STALE_BYTES = 4 * 1024 * 1024;\n/** The mouse encodings (SGR, SGR pixels) the serialize addon doesn't restore on its own. */\nconst MOUSE_ENCODINGS = [1006, 1016];\n\n/** Where a terminal's keystrokes and size go: the running CLI. */\nexport interface TerminalSink {\n write(data: string): void;\n resize(cols: number, rows: number): void;\n}\n\nconst clamp = (n: unknown, lo: number, hi: number, dflt: number) => {\n const v = Math.round(Number(n));\n return Number.isFinite(v) ? Math.max(lo, Math.min(hi, v)) : dflt;\n};\n\nexport class AgentTerminal {\n cols = TERM_COLS;\n rows = TERM_ROWS;\n /** Output arrived since the last save. */\n dirty = false;\n /** Closes a CLI left waiting at its prompt after its task (set by the runtime that left it there). */\n releaseIdle: (() => void) | null = null;\n /** Something the manager typed at that waiting prompt: the office takes it on as a follow-up (true) or refuses. */\n onIdlePrompt: ((text: string) => boolean) | null = null;\n /** Keys a viewer typed, after they went to the CLI (the runtime watches for Esc interrupting a turn). */\n onInput: ((data: string) => void) | null = null;\n private term = new Terminal({ cols: TERM_COLS, rows: TERM_ROWS, scrollback: SCROLLBACK, allowProposedApi: true, scrollOnEraseInDisplay: true });\n private ser = new SerializeAddon();\n private viewers = new Map<WebSocket, { stale: boolean; queued: string[] | null }>();\n private sink: TerminalSink | null = null;\n private mouseEncoding: number | null = null;\n private resync: NodeJS.Timeout | null = null;\n\n constructor() {\n this.term.loadAddon(this.ser);\n const decset = (on: boolean) => (params: (number | number[])[]) => {\n for (const p of params) if (typeof p === 'number' && MOUSE_ENCODINGS.includes(p)) this.mouseEncoding = on ? p : null;\n return false; // xterm still switches the mode itself\n };\n this.term.parser.registerCsiHandler({ prefix: '?', final: 'h' }, decset(true));\n this.term.parser.registerCsiHandler({ prefix: '?', final: 'l' }, decset(false));\n }\n\n /** Output from the CLI (or a note from the office): into the mirror and out to everyone watching. */\n write(data: string) {\n if (!data) return;\n this.term.write(data);\n this.dirty = true;\n this.send({ t: 'data', data });\n }\n\n /** A dim line from the office itself, e.g. between sessions. */\n note(text: string) {\n this.write(`\\r\\n\\x1b[2m${text}\\x1b[0m\\r\\n`);\n }\n\n get live() {\n return this.sink !== null;\n }\n\n /** The CLI asked for application cursor keys: arrows are sent as ESC O A\u2026 rather than ESC [ A\u2026 */\n get appCursor() {\n return this.term.modes.applicationCursorKeysMode;\n }\n\n /** The running CLI, or null when it exits. */\n bind(sink: TerminalSink | null) {\n this.sink = sink;\n sink?.resize(this.cols, this.rows);\n this.send({ t: 'live', live: sink !== null });\n }\n\n resize(cols: number, rows: number) {\n const c = clamp(cols, 20, 400, this.cols);\n const r = clamp(rows, 5, 200, this.rows);\n if (c === this.cols && r === this.rows) return;\n this.cols = c;\n this.rows = r;\n this.term.resize(c, r);\n this.sink?.resize(c, r);\n }\n\n /** Everything a fresh terminal needs to show the same screen: scrollback, colours, cursor and modes. */\n snapshot(): string {\n return this.ser.serialize({ scrollback: SCROLLBACK }) + (this.mouseEncoding ? `\\x1b[?${this.mouseEncoding}h` : '');\n }\n\n /** The visible rows as plain text, for spotting prompts the CLI is waiting on. */\n screen(): string {\n const b = this.term.buffer.active;\n const rows: string[] = [];\n for (let i = b.viewportY; i < b.viewportY + this.rows; i++) rows.push(b.getLine(i)?.translateToString(true) ?? '');\n return rows.join('\\n');\n }\n\n /** Written to disk so a restarted office still shows what each agent did. */\n /** Resolves once everything written so far is parsed (xterm parses asynchronously). */\n flush(): Promise<void> {\n return new Promise((resolve) => this.term.write('', resolve));\n }\n\n async save(file: string) {\n this.dirty = false;\n await this.flush();\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(`${file}.tmp`, this.snapshot());\n await fs.rename(`${file}.tmp`, file);\n }\n\n async load(file: string) {\n const data = await fs.readFile(file, 'utf8').catch(() => '');\n if (!data) return;\n this.term.write(data);\n this.note('(the office restarted)');\n this.dirty = false;\n }\n\n // ---------- viewers ----------\n\n attach(ws: WebSocket) {\n // xterm parses writes asynchronously: snapshot once everything written so far is parsed, and hold back what\n // arrives meanwhile so it follows the snapshot instead of going missing.\n const viewer = { stale: false, queued: [] as string[] | null };\n this.viewers.set(ws, viewer);\n this.term.write('', () => {\n const queued = viewer.queued ?? [];\n viewer.queued = null;\n this.sendTo(ws, { t: 'snapshot', data: this.snapshot(), cols: this.cols, rows: this.rows, live: this.live });\n for (const json of queued) if (ws.readyState === ws.OPEN) ws.send(json);\n });\n ws.on('message', (raw) => {\n let msg: TermClientMessage;\n try {\n msg = JSON.parse(String(raw)) as TermClientMessage;\n } catch {\n return;\n }\n if (msg.t === 'input' && typeof msg.data === 'string') {\n const data = msg.data.slice(0, 64 * 1024);\n this.sink?.write(data);\n this.onInput?.(data);\n } else if (msg.t === 'resize') {\n this.resize(msg.cols, msg.rows);\n for (const other of this.viewers.keys()) if (other !== ws) this.sendTo(other, { t: 'size', cols: this.cols, rows: this.rows });\n }\n });\n ws.on('close', () => this.viewers.delete(ws));\n }\n\n dispose() {\n for (const ws of this.viewers.keys()) ws.close();\n this.viewers.clear();\n if (this.resync) clearTimeout(this.resync);\n this.sink = null;\n this.term.dispose();\n }\n\n private send(msg: TermServerMessage) {\n if (this.viewers.size === 0) return;\n const json = JSON.stringify(msg);\n for (const [ws, v] of this.viewers) {\n if (ws.readyState !== ws.OPEN || v.stale) continue;\n if (v.queued) {\n v.queued.push(json);\n continue;\n }\n if (ws.bufferedAmount > STALE_BYTES) {\n v.stale = true;\n this.scheduleResync();\n continue;\n }\n ws.send(json);\n }\n }\n\n private sendTo(ws: WebSocket, msg: TermServerMessage) {\n if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(msg));\n }\n\n /** Viewers that fell behind get a fresh snapshot once their socket has drained, instead of an ever-growing backlog. */\n private scheduleResync() {\n if (this.resync) return;\n this.resync = setTimeout(() => {\n this.resync = null;\n let waiting = false;\n for (const [ws, v] of this.viewers) {\n if (!v.stale) continue;\n if (ws.bufferedAmount > STALE_BYTES / 4) {\n waiting = true;\n continue;\n }\n v.stale = false;\n this.sendTo(ws, { t: 'snapshot', data: this.snapshot(), cols: this.cols, rows: this.rows, live: this.live });\n }\n if (waiting) this.scheduleResync();\n }, 1000);\n }\n}\n", "import type { AgentCli } from './types.ts';\n\n// Which model an agent's session asks for. The office's default model belongs to its default coding agent, and each\n// worker can name their own; a model only goes to an agent that understands it (no Claude model for Codex).\n\n/** Claude Code's model names and aliases. */\nexport const isClaudeModel = (model: string) => /^(claude|opus|sonnet|haiku|fable|default|best|opusplan)\\b/i.test(model.trim());\n\n/**\n * The model for a worker on `cli`: their own if it suits that agent, else the office default when `cli` is the\n * default agent, else `claudeDefault` for Claude Code, or '' to let any other agent use its own default.\n */\nexport function effectiveModel(own: string, cli: AgentCli, office: { defaultCli: AgentCli; defaultModel: string }, claudeDefault: string): string {\n const suits = (m: string) => m.trim() !== '' && (cli === 'claude') === isClaudeModel(m);\n if (suits(own)) return own.trim();\n if (cli === office.defaultCli && suits(office.defaultModel)) return office.defaultModel.trim();\n return cli === 'claude' ? claudeDefault : '';\n}\n\n/** Claude Code models offered as suggestions in the office's model fields. */\nexport const CLAUDE_MODELS = ['claude-opus-5-5', 'claude-opus-5', 'claude-fable-5-1', 'claude-sonnet-5', 'claude-haiku-4-5'];\n\n/** Model suggestions for a coding agent; any other name can still be typed. OpenCode names are `provider/model`. */\nexport function modelSuggestions(cli: AgentCli): string[] {\n if (cli === 'claude') return CLAUDE_MODELS;\n if (cli === 'codex') return ['gpt-5.5-codex', 'gpt-5.5'];\n return CLAUDE_MODELS.map((m) => `anthropic/${m}`);\n}\n", "// Types shared between the swarm server and the 3D client.\n\nexport type AgentStatus =\n | 'idle' // at desk, nothing assigned\n | 'preparing' // setting up the git worktree\n | 'working' // Claude Code session running\n | 'done' // finished, PR opened (or finished without one)\n | 'error' // session failed\n | 'stopped'; // manager stopped it\n\nexport type LogKind = 'text' | 'tool' | 'result' | 'system' | 'error' | 'manager' | 'done' | 'thinking';\n\nexport interface LogLine {\n id: number;\n t: number; // epoch ms\n kind: LogKind;\n text: string;\n tool?: string; // tool name for kind === 'tool'\n}\n\nexport interface IssueInfo {\n number: number;\n title: string;\n body: string;\n url: string;\n labels: string[];\n createdAt: string;\n}\n\nexport interface PullInfo {\n number: number;\n title: string;\n url: string;\n headRefName: string;\n state: 'OPEN' | 'CLOSED' | 'MERGED';\n isDraft: boolean;\n mergeable: string; // MERGEABLE | CONFLICTING | UNKNOWN\n reviewDecision: string | null;\n closesIssues: number[];\n createdAt: string;\n mergedAt: string | null;\n additions: number;\n deletions: number;\n checks: 'pending' | 'passing' | 'failing' | 'none';\n headSha: string;\n mergeState: string; // GitHub's mergeStateStatus: CLEAN | BEHIND | BLOCKED | DIRTY | UNSTABLE | DRAFT | UNKNOWN \u2026\n failedChecks: { name: string; url: string | null }[];\n pendingChecks: string[];\n}\n\nexport interface RepoView {\n id: string; // \"owner/name\"\n fullName: string;\n description: string;\n url: string;\n defaultBranch: string;\n floor: number; // 1-based floor number in the building\n color: string; // accent color for the floor\n autoAssign: boolean;\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\n folderSync: string | null; // how the floor's main checkout stands against GitHub: \"in sync\", \"updated to abc1234\", \"2 behind: local changes\" \u2026\n browserTesting: boolean;\n links: string[]; // ids of related repos this floor's agents can read for context\n mission: string; // the manager's brief: what this floor is building\n summary: string; // the CEO's one-line read of the project, e.g. \"3D browser game \u00B7 Three.js + Vite\"\n qaBrief: string; // how QA should test this kind of project (written by the CEO, editable)\n localPath: string | null; // the manager's own project folder, when the floor lives in one\n checkoutPath: string; // where the floor's main checkout is on disk (localPath, or a clone the office manages)\n cloneStatus: 'pending' | 'cloning' | 'ready' | 'error';\n cloneError?: string;\n issues: IssueInfo[]; // open issues\n pulls: PullInfo[]; // open + recently merged PRs\n lastSync: number | null;\n syncError?: string;\n previewConfig: PreviewConfig;\n preview: PreviewView;\n}\n\n/**\n * How a floor's app is run for the preview monitor. {port} and {tmp} are replaced in the command and env values;\n * PORT={port} is always set. command null: npm run dev, else start, else preview from package.json.\n */\nexport interface PreviewConfig {\n command: string | null;\n env: Record<string, string>;\n}\n\nexport type PreviewStatus =\n | 'unconfigured' // no command and no package.json\n | 'stopped'\n | 'preparing' // checking out the ref in the preview worktree\n | 'installing' // npm ci / npm install\n | 'starting' // command started, waiting for the port\n | 'running'\n | 'error';\n\n/** The floor's running app, served from its own worktree on a port reserved for the floor. */\nexport interface PreviewView {\n status: PreviewStatus;\n port: number;\n url: string | null; // set while running\n ref: string | null; // the default branch's name, or \"PR #n\"\n pr: number | null;\n commit: string | null; // short sha\n startedAt: number | null;\n error: string | null;\n logTail: string[]; // the last 40 lines of install / app output\n}\n\n/** A folder in the manager's projects folder, as offered when adding a floor. */\nexport interface ProjectFolderView {\n name: string;\n path: string;\n git: boolean;\n github: string | null; // owner/name of its GitHub origin\n floor: number | null; // already a floor in the office\n}\n\n/** dev and qa are the two pipeline lanes on every floor; the one CEO works in the lobby and runs the company. */\nexport type AgentRole = 'dev' | 'qa' | 'ceo';\n\n/** Fixed id of the CEO agent. */\nexport const CEO_ID = 'ceo';\n\n/** How the cartoon character is drawn. Picked from the agent's name when hired; the manager can change it. */\nexport type AgentLook = 'feminine' | 'masculine';\n\n/** What an agent is currently doing: implementing an issue, testing a PR, or fixing a PR after QA. */\nexport type AgentTask = 'issue' | 'qa' | 'fix';\n\n/**\n * How agents run. terminal: each agent is the real coding-agent CLI in its own terminal, shown live in the office.\n * sdk: Claude Code through the Agent SDK, its stream turned into log lines.\n */\nexport type AgentRuntime = 'terminal' | 'sdk';\n\n/** The coding-agent CLI an agent runs in its terminal. The CEO is always Claude Code. */\nexport type AgentCli = 'claude' | 'codex' | 'opencode';\n\n/** A coding-agent CLI the office knows how to run, and whether it's installed on this machine. */\nexport interface CliView {\n id: AgentCli;\n label: string;\n installed: boolean;\n version: string | null;\n /** Hooks report every tool call and enforce the guard rails; the others report only when a turn ends. */\n integrated: boolean;\n}\n\n/** Messages on an agent's terminal socket (/ws/term?agent=<id>), server to browser. */\nexport type TermServerMessage =\n | { t: 'snapshot'; data: string; cols: number; rows: number; live: boolean } // the screen and scrollback so far\n | { t: 'data'; data: string }\n | { t: 'size'; cols: number; rows: number } // another viewer resized the terminal\n | { t: 'live'; live: boolean }; // a CLI is (or is no longer) running in it\n\n/** Browser to server: keystrokes go to the running CLI; the size is the viewer's fitted terminal. */\nexport type TermClientMessage = { t: 'input'; data: string } | { t: 'resize'; cols: number; rows: number };\n\nexport interface AgentView {\n id: string;\n name: string;\n repoId: string;\n role: AgentRole;\n title: string; // job title, e.g. \"Three.js graphics engineer\" ('' = plain developer / QA tester)\n specialty: string; // routes issues labelled swarm:<specialty> to this agent first ('' = generalist)\n brief: string; // job description for this project, added to the agent's instructions\n hiredBy: 'manager' | 'ceo';\n look: AgentLook;\n task: AgentTask | null;\n desk: number; // desk slot on the floor (dev desks and QA lab stations are numbered separately)\n color: string; // shirt color\n hair: string; // hair color\n skin: string;\n model: string; // '' = use the swarm default model, or a model id / alias\n effort: EffortLevel | ''; // '' = use the swarm default effort\n cli: AgentCli | ''; // the CLI they run in the terminal runtime ('' = the office default)\n terminal: boolean; // they have a terminal to watch (the terminal runtime); otherwise their log lines are the screen\n status: AgentStatus;\n issueNumber: number | null; // devs: the issue being worked on\n issueTitle: string | null; // devs: issue title; QA: title of the PR under test\n branch: string | null;\n prNumber: number | null; // devs: the PR they opened; QA: the PR under test\n prUrl: string | null;\n currentTool: string | null;\n startedAt: number | null;\n endedAt: number | null;\n costUsd: number;\n turns: number;\n browserUrl: string | null;\n hasScreenshot: boolean;\n screenshotAt: number | null;\n lastError: string | null;\n log: LogLine[]; // tail of the terminal log (full buffer on snapshot)\n}\n\n/** One piece of an agent's prompt; the parts' texts concatenated are the whole prompt. */\nexport interface PromptPart {\n label: string;\n text: string;\n /** The manager can change it (the job description); the rest is the office's workflow and safety rules. */\n editable: boolean;\n}\n\n/** GET /api/agents/:id/prompt: what the agent is told on a task, with placeholders for the task's details. */\nexport interface AgentPromptView {\n kind: 'dev' | 'qa' | 'ceo';\n text: string;\n parts: PromptPart[];\n}\n\nexport type EffortLevel = 'low' | 'medium' | 'high' | 'xhigh' | 'max';\n\nexport type QaStatus =\n | 'queued' // waiting for a free QA tester\n | 'testing' // a QA tester is on it\n | 'passed' // ready to merge\n | 'failed' // failed; waiting for the dev who wrote it to be free\n | 'fixing' // the dev is fixing what QA found\n | 'needs-human'; // failed too many rounds, or nobody can fix it automatically\n\nexport interface QaCheck {\n name: string;\n result: 'pass' | 'fail' | 'skip';\n details: string;\n}\n\nexport interface QaView {\n repoId: string;\n prNumber: number;\n status: QaStatus;\n round: number; // 1-based QA round\n devAgentId: string | null; // who wrote it (null for PRs opened outside the swarm)\n qaAgentId: string | null; // who is testing / last tested it\n summary: string | null; // latest QA summary\n checks: QaCheck[];\n commentUrl: string | null; // the PR comment with the latest QA report\n mergeNote: string | null; // where auto-merge stands once QA passed, e.g. \"waiting for checks: Vercel\"\n updatedAt: number;\n}\n\nexport interface SwarmSettings {\n sessionLimit: number; // most Claude Code sessions running at once; 0 = no limit\n defaultModel: string;\n defaultEffort: EffortLevel;\n runtime: AgentRuntime;\n defaultCli: AgentCli; // what developers and QA testers run in their terminals unless they have their own\n hiring: 'approve' | 'auto'; // CEO proposals wait for the manager, or go through while the floor is under teamCap\n teamCap: number; // most agents per floor the CEO may reach without the manager's approval (auto mode)\n ceoHeartbeatMin: number; // minutes between the CEO's periodic reviews; 0 = off\n managerName: string; // what the office calls you\n companyName: string;\n projectsDir: string; // where your project folders live; new projects are created here\n setupDone: boolean; // the first-run setup wizard has been completed or skipped\n tutorialStep: number; // index of the current tutorial step; -1 when finished or skipped\n autoUpdate?: boolean; // update the office itself once it's quiet (absent on servers without self-update)\n pacingSessions: number; // after Claude warns about usage, new issues start only while fewer sessions than this run\n}\n\n/** Claude's subscription usage: normal, pacing new work after a usage warning, or paused at the limit until `until`. */\nexport interface UsageView {\n state: 'normal' | 'pacing' | 'paused';\n until: number | null;\n}\n\n/**\n * Where the office's own update stands. none: up to date \u00B7 available: new commits on GitHub \u00B7 waiting / draining:\n * starting nothing new while running sessions finish \u00B7 updating: handed to the launcher \u00B7 failed: see detail.\n */\nexport type OfficeUpdateState = 'none' | 'available' | 'waiting' | 'draining' | 'updating' | 'failed';\n\nexport interface OfficeUpdateView {\n state: OfficeUpdateState;\n behind: number; // commits the office's folder is behind GitHub\n launcher: boolean; // started by npm run dev / npm start, which can install the update and restart the office\n drainingSince: number | null;\n running: number; // sessions still running\n detail: string | null;\n}\n\n/** A CEO proposal to hire someone or let someone go. The manager (the board) decides. */\nexport interface HireRequestView {\n id: string;\n kind: 'hire' | 'let-go';\n repoId: string;\n role: 'dev' | 'qa';\n agentId: string | null; // let-go: who; hire: who was hired once approved\n name: string; // the candidate's name (let-go: the agent's name)\n title: string;\n specialty: string;\n brief: string;\n reason: string;\n model: string;\n effort: EffortLevel | '';\n look: AgentLook;\n color: string;\n hair: string;\n skin: string;\n status: 'pending' | 'approved' | 'rejected';\n note: string; // the manager's reason when rejecting\n createdAt: number;\n decidedAt: number | null;\n decidedBy: 'manager' | 'auto' | null;\n}\n\n/** One message in the phone thread between the manager and the CEO. */\nexport interface PhoneMessage {\n id: number;\n from: 'ceo' | 'manager' | 'office'; // office = notes from the building itself (decisions, errors)\n text: string;\n at: number;\n requestId?: string; // a hire / let-go proposal this message is about\n}\n\nexport type CeoJobKind = 'onboard' | 'plan' | 'review' | 'chat';\n\nexport interface CeoInfo {\n queue: { kind: CeoJobKind; label: string }[]; // jobs waiting for the CEO\n job: { kind: CeoJobKind; label: string } | null; // what the CEO is doing now\n lastReviewAt: number | null;\n nextReviewAt: number | null; // null when the heartbeat is off\n}\n\nexport interface WorldSnapshot {\n user: string | null; // gh login\n ghReady: boolean;\n ghError?: string;\n demo: boolean;\n workspaceRoot: string;\n settings: SwarmSettings;\n repos: RepoView[];\n agents: AgentView[];\n qa: QaView[];\n requests: HireRequestView[];\n ceo: CeoInfo;\n messages: PhoneMessage[];\n phoneReadAt: number; // CEO messages newer than this are unread\n officeCommit?: string | null; // short sha the server started on (absent on servers without self-update)\n officeUpdate?: OfficeUpdateView;\n usage: UsageView;\n clis: CliView[];\n}\n\nexport type ServerEvent =\n | { type: 'snapshot'; data: WorldSnapshot }\n | { type: 'repo'; repo: RepoView }\n | { type: 'repoRemoved'; repoId: string }\n | { type: 'agent'; agent: Omit<AgentView, 'log'> }\n | { type: 'agentRemoved'; agentId: string }\n | { type: 'log'; agentId: string; lines: LogLine[] }\n | { type: 'screen'; agentId: string; url: string | null; at: number }\n | { type: 'qa'; qa: QaView }\n | { type: 'qaRemoved'; repoId: string; prNumber: number }\n | { type: 'settings'; settings: SwarmSettings }\n | { type: 'request'; request: HireRequestView }\n | { type: 'ceo'; ceo: CeoInfo }\n | { type: 'message'; message: PhoneMessage }\n | { type: 'phoneRead'; at: number }\n | { type: 'officeUpdate'; officeUpdate: OfficeUpdateView }\n | { type: 'usage'; usage: UsageView }\n | { type: 'clis'; clis: CliView[] }\n | { type: 'toast'; level: 'info' | 'success' | 'error'; text: string };\n\nexport interface GhRepoSummary {\n nameWithOwner: string;\n description: string;\n visibility: string;\n updatedAt: string;\n}\n"],
5
- "mappings": "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",
6
- "names": ["http", "path", "fs", "repos", "fs", "path", "path", "fs", "fs", "path", "fs", "os", "path", "fs", "path", "now", "found", "tool", "toolInput", "crypto", "fs", "path", "fs", "createRequire", "path", "path", "fs", "createRequire", "bundled", "found", "crypto", "fs", "path", "path", "onMessage", "path", "fs", "crypto", "p", "path", "route", "server", "fs", "exists", "crypto", "path", "l", "fs", "prompt", "launch", "spawn", "crypto", "fs", "net", "path", "net", "sleep", "fs", "killTree", "spawn", "path", "code", "crypto", "fs", "path", "path", "fs", "crypto", "path", "crypto", "path", "tool", "git", "server", "pending", "run", "fs", "path", "crypto", "rest", "run", "server", "pending", "repoId", "issue", "now", "now", "issue", "now", "fs", "path", "path", "fs", "fs", "path", "repoId", "crypto", "issue", "inTerminal", "failed", "now", "pick", "repos", "view", "rt", "pending", "path", "fs", "http"]
3
+ "sources": ["../server/index.ts", "../server/config.ts", "../server/exec.ts", "../server/github.ts", "../server/workspace.ts", "../server/agentRunner.ts", "../server/browser.ts", "../server/cliRunner.ts", "../server/clis.ts", "../server/ptyClient.ts", "../server/ptyProtocol.ts", "../server/deps.ts", "../server/previewRunner.ts", "../server/officeUpdate.ts", "../server/voice.ts", "../shared/speech.ts", "../server/httpError.ts", "../server/elevenlabs.ts", "../server/backend.ts", "../server/demo.ts", "../server/screenReply.ts", "../server/sendBack.ts", "../server/mergeGate.ts", "../server/qaOutcome.ts", "../server/swarm.ts", "../server/ceo.ts", "../shared/issues.ts", "../server/deskSetup.ts", "../server/fixOutcome.ts", "../server/issueClaims.ts", "../server/qaOrphans.ts", "../server/qaPrompt.ts", "../server/restartRecovery.ts", "../server/previews.ts", "../server/prompts.ts", "../server/pacing.ts", "../server/terminal.ts", "../shared/models.ts", "../shared/types.ts"],
4
+ "sourcesContent": ["import http from 'node:http';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport express, { type NextFunction, type Request, type Response } from 'express';\nimport type { AddressInfo } from 'node:net';\nimport { WebSocketServer } from 'ws';\nimport { z } from 'zod';\nimport { DEMO, PORT, STATE_FILE, WORKSPACE_ROOT } from './config.ts';\nimport { realBackend } from './backend.ts';\nimport { handleHook, handleMcp, setOfficeUrl } from './cliRunner.ts';\nimport { createDemoBackend } from './demo.ts';\nimport { underLauncher } from './officeUpdate.ts';\nimport { screenStatus } from './screenReply.ts';\nimport { parseSendBackNote } from './sendBack.ts';\nimport { HttpError, Swarm } from './swarm.ts';\n\nconst swarm = new Swarm(DEMO ? createDemoBackend() : realBackend);\n// Sessions the office picks back up while it starts need the address their CLIs call back on before it listens.\nif (PORT) setOfficeUrl(`http://127.0.0.1:${PORT}`);\nawait swarm.init();\n\nconst app = express();\n// Agent CLIs calling back: hooks (a tool result can be a large screenshot, hence the limit) and the CEO's office tools.\n// The token in the path is the session's; unknown tokens get an empty answer.\napp.post('/api/hooks/:token', express.json({ limit: '64mb' }), (req, res) => void res.json(handleHook(String(req.params.token), req.body)));\napp.post('/api/mcp/:token', express.json({ limit: '4mb' }), (req, res, next) => void handleMcp(String(req.params.token), req, res).catch(next));\napp.all('/api/mcp/:token', (_req, res) => void res.status(405).set('Allow', 'POST').end());\napp.use(express.json({ limit: '1mb' }));\n\ntype Handler = (req: Request, res: Response) => Promise<unknown> | unknown;\nconst route = (fn: Handler) => async (req: Request, res: Response, next: NextFunction) => {\n try {\n const out = await fn(req, res);\n if (!res.headersSent) res.json(out ?? { ok: true });\n } catch (err) {\n next(err);\n }\n};\nconst num = (v: unknown) => {\n const n = Number(v);\n if (!Number.isInteger(n) || n <= 0) throw new HttpError(400, `Invalid number: ${v}`);\n return n;\n};\nconst str = (v: unknown) => (typeof v === 'string' ? v : '');\n// Repo ids contain a slash (\"owner/name\"), so they travel URL-encoded as a single segment.\nconst repoId = (req: Request) => decodeURIComponent(String(req.params.repo));\n\napp.get('/api/state', route(() => swarm.snapshot()));\n\napp.get('/api/github/repos', route((req) => swarm.listGithubRepos(str(req.query.owner) || undefined)));\n\n// What happens once a project moves in: the CEO's brief, and whether work starts on its own.\nconst floorOptions = (req: Request) => ({ mission: str(req.body.mission), autoAssign: req.body.autoAssign === true });\n\napp.post('/api/repos', route((req) => swarm.connectRepo(str(req.body.fullName).trim(), floorOptions(req))));\n\n// Your projects folder\napp.get('/api/folders', route((req) => swarm.listProjectFolders(str(req.query.dir) || undefined)));\napp.post('/api/folders/connect', route((req) => swarm.connectFolder(str(req.body.path), floorOptions(req))));\napp.post(\n '/api/folders/publish',\n route((req) =>\n swarm.publishFolder(str(req.body.path), {\n ...floorOptions(req),\n name: str(req.body.name) || undefined,\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\n description: str(req.body.description),\n }),\n ),\n);\napp.post(\n '/api/setup',\n route((req) =>\n swarm.setup({\n managerName: str(req.body.managerName),\n companyName: str(req.body.companyName),\n hiring: str(req.body.hiring),\n ceoName: str(req.body.ceoName),\n ceoLook: str(req.body.ceoLook),\n ceoColor: str(req.body.ceoColor),\n }),\n ),\n);\napp.post(\n '/api/repos/new',\n route((req) =>\n swarm.createRepo(str(req.body.name).trim(), {\n ...floorOptions(req),\n description: str(req.body.description),\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\n owner: str(req.body.owner).trim() || undefined,\n }),\n ),\n);\napp.patch('/api/repos/:repo', route((req) => swarm.updateRepo(repoId(req), req.body ?? {})));\napp.delete('/api/repos/:repo', route((req) => swarm.disconnectRepo(repoId(req))));\napp.post('/api/repos/:repo/sync', route((req) => swarm.syncRepo(repoId(req))));\napp.post('/api/repos/:repo/sync-folder', route((req) => swarm.syncFolderNow(repoId(req))));\napp.post(\n '/api/repos/:repo/issues',\n route(async (req) => ({\n number: await swarm.createIssue(repoId(req), str(req.body.title), str(req.body.body), str(req.body.assignTo) || undefined, str(req.body.specialty) || undefined),\n })),\n);\napp.post('/api/repos/:repo/plan', route((req) => swarm.planFloor(repoId(req), typeof req.body?.mission === 'string' ? req.body.mission : undefined)));\napp.post('/api/repos/:repo/onboard', route((req) => swarm.onboardFloor(repoId(req))));\n// The floor's app, for the preview monitor\napp.post(\n '/api/repos/:repo/preview',\n route((req) => {\n const pr = req.body?.pr;\n if (pr !== undefined && pr !== null && (typeof pr !== 'number' || !Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, 'pr must be a positive integer');\n return swarm.startPreview(repoId(req), pr ?? null);\n }),\n);\napp.delete('/api/repos/:repo/preview', route((req) => swarm.stopPreview(repoId(req))));\napp.post('/api/repos/:repo/pulls/:n/merge', route((req) => swarm.mergePull(repoId(req), num(req.params.n), req.body?.method ?? 'squash')));\napp.post('/api/repos/:repo/pulls/:n/close', route((req) => swarm.closePull(repoId(req), num(req.params.n))));\napp.post('/api/repos/:repo/pulls/:n/qa', route((req) => swarm.sendToQa(repoId(req), num(req.params.n))));\napp.post('/api/repos/:repo/pulls/:n/fix', route((req) => swarm.sendBackToDev(repoId(req), num(req.params.n), parseSendBackNote(req.body))));\napp.post(\n '/api/repos/:repo/agents',\n route((req) =>\n swarm.hireAgent(repoId(req), {\n name: str(req.body.name),\n model: str(req.body.model),\n effort: str(req.body.effort),\n role: str(req.body.role),\n look: str(req.body.look),\n title: str(req.body.title),\n specialty: str(req.body.specialty),\n brief: str(req.body.brief),\n }),\n ),\n);\n\napp.patch('/api/agents/:id', route((req) => swarm.updateAgent(String(req.params.id), req.body ?? {})));\napp.delete('/api/agents/:id', route((req) => swarm.fireAgent(String(req.params.id))));\napp.post('/api/agents/:id/assign', route((req) => swarm.assign(String(req.params.id), num(req.body.issueNumber), str(req.body.note) || undefined)));\napp.post('/api/agents/:id/stop', route((req) => swarm.stopAgent(String(req.params.id))));\napp.post('/api/agents/:id/reset', route((req) => swarm.resetAgent(String(req.params.id))));\napp.post('/api/agents/:id/message', route((req) => swarm.message(String(req.params.id), str(req.body.text))));\napp.get('/api/agents/:id/prompt', route((req) => swarm.agentPrompt(String(req.params.id))));\napp.get('/api/agents/:id/screen', (req, res) => {\n const shot = swarm.screenshot(String(req.params.id));\n res.setHeader('Cache-Control', 'no-store');\n if (!shot) return void res.status(screenStatus(shot)).end();\n res.setHeader('Content-Type', shot.mime);\n res.end(shot.data);\n});\n\napp.patch('/api/settings', route((req) => swarm.updateSettings(req.body ?? {})));\n\n// Phone messages read aloud (docs/voice.md). The key goes in and never comes back out.\nconst parse = <T>(schema: z.ZodType<T>, value: unknown): T => {\n const r = schema.safeParse(value);\n if (!r.success) throw new HttpError(400, r.error.issues.map((i) => `${i.path.join('.') || 'request'}: ${i.message}`).join('; '));\n return r.data;\n};\nconst sendAudio = (res: Response, audio: Buffer) => {\n // Real clips are mp3; the demo's chime is a WAV.\n res.setHeader('Content-Type', audio.subarray(0, 4).toString('latin1') === 'RIFF' ? 'audio/wav' : 'audio/mpeg');\n res.setHeader('Cache-Control', 'private, max-age=3600');\n res.end(audio);\n};\napp.put('/api/voice/key', route((req) => swarm.voice.setKey(parse(z.object({ key: z.string().max(400) }), req.body).key)));\napp.get('/api/voice/voices', route(() => swarm.voice.voices()));\napp.get(\n '/api/voice/messages/:id',\n route(async (req, res) => sendAudio(res, await swarm.voice.messageAudio(parse(z.object({ id: z.coerce.number().int().positive() }), req.params).id))),\n);\napp.get(\n '/api/voice/sample',\n route(async (req, res) => sendAudio(res, await swarm.voice.sampleAudio(parse(z.object({ voiceId: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/, 'not a voice id').optional() }), req.query).voiceId))),\n);\n// The office's own update: Update now / Later\napp.post('/api/office/update', route((req) => swarm.updateOffice(req.body?.action)));\n\n// The CEO and the manager's phone\napp.post('/api/ceo/message', route((req) => swarm.messageCeo(str(req.body.text))));\napp.post('/api/ceo/review', route(() => swarm.requestReview()));\napp.post('/api/phone/read', route((req) => swarm.markPhoneRead(Number(req.body?.at) || Date.now())));\napp.post(\n '/api/requests/:id/approve',\n route((req) => swarm.approveRequest(String(req.params.id), { name: str(req.body?.name) || undefined, model: typeof req.body?.model === 'string' ? req.body.model : undefined, effort: typeof req.body?.effort === 'string' ? req.body.effort : undefined })),\n);\napp.post('/api/requests/:id/reject', route((req) => swarm.rejectRequest(String(req.params.id), str(req.body?.note))));\n\n// Serve the built client: the published package, or `npm start` after `npm run build`.\nconst dist = path.resolve(import.meta.dirname, '../dist');\nif (fs.existsSync(dist)) {\n app.use(express.static(dist));\n app.get(/^(?!\\/api).*/, (_req, res) => res.sendFile(path.join(dist, 'index.html')));\n}\n\napp.use((err: unknown, _req: Request, res: Response, _next: NextFunction) => {\n // express.json() flags malformed bodies with a 4xx status of its own.\n const parserStatus = (err as { status?: unknown })?.status;\n const status = err instanceof HttpError ? err.status : typeof parserStatus === 'number' && parserStatus >= 400 && parserStatus < 500 ? parserStatus : 500;\n const message = err instanceof Error ? err.message : String(err);\n if (status >= 500) console.error(err);\n res.status(status).json({ error: message });\n});\n\nconst server = http.createServer(app);\n// Two sockets: /ws carries the office's state to every tab, /ws/term?agent=<id> one agent's terminal to whoever opened it.\nconst wss = new WebSocketServer({ noServer: true });\nconst terms = new WebSocketServer({ noServer: true });\nwss.on('connection', (ws) => swarm.addClient(ws));\nterms.on('connection', (ws, req) => swarm.attachTerminal(new URL(req.url ?? '', 'http://localhost').searchParams.get('agent') ?? '', ws));\nserver.on('upgrade', (req, socket, head) => {\n const { pathname } = new URL(req.url ?? '', 'http://localhost');\n const target = pathname === '/ws' ? wss : pathname === '/ws/term' ? terms : null;\n if (!target) return void socket.destroy();\n target.handleUpgrade(req, socket, head, (ws) => target.emit('connection', ws, req));\n});\n\nserver.listen(PORT, '127.0.0.1', () => {\n setOfficeUrl(`http://127.0.0.1:${(server.address() as AddressInfo).port}`);\n console.log(`\\n \uD83C\uDFE2 cubefarm on http://localhost:${PORT}${DEMO ? ' (DEMO MODE: fake GitHub + fake agents)' : ''}`);\n console.log(` state: ${STATE_FILE}`);\n console.log(` workspaces: ${WORKSPACE_ROOT}\\n`);\n});\n\n// Floors' apps don't outlive the office. (A hard kill skips this; the next start clears the orphans.) Agents' CLIs\n// carry on through a restart and stop when the office quits.\nlet closing = false;\nconst shutdown = (signal: string) => {\n if (closing) return;\n closing = true;\n console.log(`\\n ${signal}: stopping floor previews\u2026`);\n const force = setTimeout(() => process.exit(0), 15_000);\n void swarm\n .shutdown(signal === 'restart')\n .catch((err) => console.error(err))\n .finally(() => {\n clearTimeout(force);\n process.exit(0);\n });\n};\nprocess.once('SIGINT', () => shutdown('SIGINT'));\nprocess.once('SIGTERM', () => shutdown('SIGTERM'));\nprocess.once('SIGHUP', () => shutdown('SIGHUP')); // its terminal window closed (macOS, Linux; Windows' console too)\n// The launcher asks the office to stop: to restart it (an update, a code change) unless it says it's quitting.\nif (underLauncher()) {\n process.on('message', (msg) => {\n const m = msg as { type?: unknown; restart?: unknown } | null;\n if (m?.type === 'office:shutdown') shutdown(m.restart === false ? 'stop' : 'restart');\n });\n}\n", "import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nexport const PORT = Number(process.env.SWARM_PORT ?? 4317);\n// package.json sits one folder up both from server/ and from the published dist-server/.\nexport const VERSION: string = JSON.parse(fs.readFileSync(path.resolve(import.meta.dirname, '..', 'package.json'), 'utf8')).version;\n\n// Everything the swarm writes lives outside this project so that agents working in\n// cloned repos never pick up this project's CLAUDE.md or settings by walking up the tree.\nexport const HOME_DIR = process.env.SWARM_HOME ?? path.join(os.homedir(), '.cubefarm');\nexport const WORKSPACE_ROOT = path.join(HOME_DIR, 'workspaces');\nexport const DEMO = process.argv.includes('--demo') || process.env.SWARM_DEMO === '1' || process.env.SWARM_DEMO === 'true';\nexport const STATE_FILE = path.join(HOME_DIR, DEMO ? 'demo-state.json' : 'state.json');\n\n// How often each connected repo's issues and PRs are refreshed from GitHub.\nexport const SYNC_INTERVAL_MS = 45_000;\n// How often idle agents on auto-assign floors look for new work.\nexport const SCHEDULER_INTERVAL_MS = 8_000;\n// How often each floor's desks and finished branches are swept (also at start and after a let-go).\nexport const DESK_SWEEP_INTERVAL_MS = 30 * 60_000;\n// Terminal lines kept per agent.\nexport const LOG_BUFFER = 600;\n\n/**\n * Where new projects go unless the manager picks another folder. Run from a checkout, that's the folder the app sits\n * in (C:\\Projects\\cubefarm \u2192 C:\\Projects). Installed from npm the app lives in node_modules, so it's the usual\n * projects folder in your home instead.\n */\nexport function defaultProjectsDir(appDir: string, home = os.homedir()): string {\n if (!appDir.split(/[\\\\/]/).includes('node_modules')) return path.resolve(appDir, '..');\n const names = ['Projects', 'projects', 'code', 'Code', 'dev', 'Developer', 'src', 'repos', 'git', 'GitHub'];\n return names.map((n) => path.join(home, n)).find((d) => fs.existsSync(d)) ?? path.join(home, 'Projects');\n}\n", "import { execFile } from 'node:child_process';\n\nexport class CommandError extends Error {\n constructor(\n message: string,\n public readonly stderr: string,\n public readonly code: number | null,\n ) {\n super(message);\n }\n}\n\n/** Run a CLI (gh, git) without a shell and return trimmed stdout. */\nexport function run(cmd: string, args: string[], opts: { cwd?: string; timeoutMs?: number; input?: string } = {}): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = execFile(\n cmd,\n args,\n {\n cwd: opts.cwd,\n timeout: opts.timeoutMs ?? 120_000,\n maxBuffer: 32 * 1024 * 1024,\n windowsHide: true,\n env: { ...process.env, GH_PROMPT_DISABLED: '1', GIT_TERMINAL_PROMPT: '0', NO_COLOR: '1' },\n },\n (err, stdout, stderr) => {\n if (err) {\n const detail = (stderr || err.message).toString().trim();\n reject(new CommandError(`${cmd} ${args.slice(0, 3).join(' ')} failed: ${detail}`, stderr?.toString() ?? '', (err as { code?: number }).code ?? null));\n return;\n }\n resolve(stdout.toString().trim());\n },\n );\n if (opts.input !== undefined) {\n child.stdin?.end(opts.input);\n }\n });\n}\n\nexport const gh = (args: string[], opts?: { cwd?: string; timeoutMs?: number; input?: string }) => run('gh', args, opts);\nexport const git = (args: string[], opts?: { cwd?: string; timeoutMs?: number }) => run('git', args, opts);\n\nexport async function ghJson<T>(args: string[], opts?: { cwd?: string; timeoutMs?: number }): Promise<T> {\n const out = await gh(args, opts);\n return (out ? JSON.parse(out) : null) as T;\n}\n", "import { gh, ghJson } from './exec.ts';\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\n\n// All GitHub access goes through the gh CLI so it reuses the user's existing `gh auth login`.\n\nexport async function currentUser(): Promise<string> {\n return gh(['api', 'user', '--jq', '.login']);\n}\n\nexport async function listMyRepos(owner?: string): Promise<GhRepoSummary[]> {\n const args = ['repo', 'list'];\n if (owner) args.push(owner);\n args.push('--limit', '200', '--json', 'nameWithOwner,description,visibility,updatedAt');\n const repos = await ghJson<GhRepoSummary[]>(args);\n return repos.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n}\n\nexport interface RepoMeta {\n nameWithOwner: string;\n description: string;\n url: string;\n defaultBranch: string;\n}\n\nexport async function repoMeta(fullName: string): Promise<RepoMeta> {\n const raw = await ghJson<{ nameWithOwner: string; description: string | null; url: string; defaultBranchRef: { name: string } | null }>([\n 'repo',\n 'view',\n fullName,\n '--json',\n 'nameWithOwner,description,url,defaultBranchRef',\n ]);\n return {\n nameWithOwner: raw.nameWithOwner,\n description: raw.description ?? '',\n url: raw.url,\n defaultBranch: raw.defaultBranchRef?.name || 'main',\n };\n}\n\nexport async function listIssues(fullName: string): Promise<IssueInfo[]> {\n const raw = await ghJson<\n { number: number; title: string; body: string; url: string; labels: { name: string }[]; createdAt: string }[]\n >(['issue', 'list', '-R', fullName, '--state', 'open', '--limit', '100', '--json', 'number,title,body,url,labels,createdAt']);\n return raw\n .map((i) => ({ number: i.number, title: i.title, body: i.body ?? '', url: i.url, labels: i.labels.map((l) => l.name), createdAt: i.createdAt }))\n .sort((a, b) => a.number - b.number);\n}\n\ninterface RawPull {\n number: number;\n title: string;\n url: string;\n headRefName: string;\n state: 'OPEN' | 'CLOSED' | 'MERGED';\n isDraft: boolean;\n mergeable: string;\n reviewDecision: string | null;\n closingIssuesReferences: { number: number }[] | null;\n createdAt: string;\n mergedAt: string | null;\n additions: number;\n deletions: number;\n headRefOid: string;\n mergeStateStatus: string;\n // check runs (GitHub Actions\u2026) carry name/status/conclusion/detailsUrl; commit statuses (Vercel\u2026) carry context/state/targetUrl\n statusCheckRollup: { name?: string; context?: string; status?: string; conclusion?: string; state?: string; detailsUrl?: string; targetUrl?: string }[] | null;\n}\n\nconst PR_FIELDS =\n 'number,title,url,headRefName,headRefOid,state,isDraft,mergeable,mergeStateStatus,reviewDecision,closingIssuesReferences,createdAt,mergedAt,additions,deletions,statusCheckRollup';\n\ntype Check = NonNullable<RawPull['statusCheckRollup']>[number];\nconst BAD = ['FAILURE', 'ERROR', 'CANCELLED', 'TIMED_OUT', 'ACTION_REQUIRED', 'STARTUP_FAILURE'];\nconst failed = (c: Check) => BAD.includes(c.conclusion ?? '') || BAD.includes(c.state ?? '');\nconst pending = (c: Check) => (!!c.status && c.status !== 'COMPLETED') || c.state === 'PENDING' || c.state === 'EXPECTED';\nconst checkName = (c: Check) => c.name || c.context || 'check';\n\nfunction checksOf(rollup: RawPull['statusCheckRollup']): PullInfo['checks'] {\n if (!rollup || rollup.length === 0) return 'none';\n if (rollup.some(failed)) return 'failing';\n if (rollup.some(pending)) return 'pending';\n return 'passing';\n}\n\nfunction toPull(p: RawPull): PullInfo {\n return {\n number: p.number,\n title: p.title,\n url: p.url,\n headRefName: p.headRefName,\n state: p.state,\n isDraft: p.isDraft,\n mergeable: p.mergeable,\n reviewDecision: p.reviewDecision || null,\n closesIssues: (p.closingIssuesReferences ?? []).map((r) => r.number),\n createdAt: p.createdAt,\n mergedAt: p.mergedAt,\n additions: p.additions,\n deletions: p.deletions,\n checks: checksOf(p.statusCheckRollup),\n headSha: p.headRefOid,\n mergeState: p.mergeStateStatus || 'UNKNOWN',\n failedChecks: (p.statusCheckRollup ?? []).filter(failed).map((c) => ({ name: checkName(c), url: c.detailsUrl || c.targetUrl || null })),\n pendingChecks: (p.statusCheckRollup ?? []).filter(pending).map(checkName),\n };\n}\n\nexport async function listPulls(fullName: string): Promise<PullInfo[]> {\n const [open, merged] = await Promise.all([\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'open', '--limit', '50', '--json', PR_FIELDS]),\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'merged', '--limit', '8', '--json', PR_FIELDS]),\n ]);\n return [...open, ...merged].map(toPull);\n}\n\n// swarm:<specialty> labels route issues to specialists. gh refuses unknown labels, so they're created on first use.\nconst labelsMade = new Set<string>();\n\nasync function ensureLabel(fullName: string, name: string) {\n const key = `${fullName}#${name}`;\n if (labelsMade.has(key)) return;\n await gh(['label', 'create', name, '-R', fullName, '--color', 'c77dff', '--description', 'cubefarm: routed to this specialty', '--force']);\n labelsMade.add(key);\n}\n\nexport async function createIssue(fullName: string, title: string, body: string, labels: string[] = []): Promise<number> {\n for (const l of labels) await ensureLabel(fullName, l);\n const args = ['issue', 'create', '-R', fullName, '--title', title, '--body-file', '-'];\n for (const l of labels) args.push('--label', l);\n const out = await gh(args, { input: body || ' ' });\n const match = out.match(/\\/issues\\/(\\d+)/);\n if (!match) throw new Error(`Could not read the new issue number from gh output: ${out}`);\n return Number(match[1]);\n}\n\n/** OPEN or CLOSED; null when the repo has no such issue. */\nexport async function issueState(fullName: string, number: number): Promise<'OPEN' | 'CLOSED' | null> {\n try {\n const raw = await ghJson<{ state: string }>(['issue', 'view', String(number), '-R', fullName, '--json', 'state']);\n return raw.state === 'OPEN' ? 'OPEN' : 'CLOSED';\n } catch {\n return null;\n }\n}\n\n/** Close an issue as completed, with a comment saying why. */\nexport async function closeIssue(fullName: string, number: number, comment: string): Promise<void> {\n await gh(['issue', 'close', String(number), '-R', fullName, '--reason', 'completed', '--comment', comment]);\n}\n\n/** Replace an issue's body and/or add and remove labels. */\nexport async function editIssue(fullName: string, number: number, edit: { body?: string; addLabels?: string[]; removeLabels?: string[] }): Promise<void> {\n const args = ['issue', 'edit', String(number), '-R', fullName];\n if (edit.body !== undefined) args.push('--body-file', '-');\n for (const l of edit.addLabels ?? []) {\n await ensureLabel(fullName, l);\n args.push('--add-label', l);\n }\n for (const l of edit.removeLabels ?? []) args.push('--remove-label', l);\n if (args.length === 5) return;\n await gh(args, edit.body !== undefined ? { input: edit.body || ' ' } : undefined);\n}\n\n/** Merge a PR. With headSha, GitHub refuses if anything was pushed after that commit (e.g. after QA signed it off). */\nexport async function mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void> {\n const pr = await ghJson<{ headRefName: string; isCrossRepository: boolean }>(['pr', 'view', String(number), '-R', fullName, '--json', 'headRefName,isCrossRepository']);\n await gh(['pr', 'merge', String(number), '-R', fullName, `--${method}`, ...(headSha ? ['--match-head-commit', headSha] : [])], { timeoutMs: 60_000 });\n // Tidy up the swarm branch on the remote; the local worktree is cleaned when the agent takes its next issue.\n if (!pr.isCrossRepository && pr.headRefName.startsWith('swarm/')) {\n await gh(['api', '-X', 'DELETE', `repos/${fullName}/git/refs/heads/${pr.headRefName}`]).catch(() => undefined);\n }\n}\n\n/** Merge the base branch into a PR's branch on GitHub, for repos that only merge up-to-date branches. */\nexport async function updateBranch(fullName: string, number: number): Promise<void> {\n await gh(['pr', 'update-branch', String(number), '-R', fullName], { timeoutMs: 60_000 });\n}\n\nexport async function closePull(fullName: string, number: number): Promise<void> {\n await gh(['pr', 'close', String(number), '-R', fullName]);\n}\n\nexport async function prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null> {\n const list = await ghJson<{ number: number; url: string }[]>(['pr', 'list', '-R', fullName, '--head', branch, '--state', 'all', '--json', 'number,url', '--limit', '1']);\n return list[0] ?? null;\n}\n\n// ---------- QA support ----------\n\nexport interface PrDetails {\n number: number;\n title: string;\n body: string;\n url: string;\n headRefName: string;\n headSha: string;\n isCrossRepository: boolean;\n closesIssues: number[];\n state: 'OPEN' | 'CLOSED' | 'MERGED';\n mergeable: string;\n mergeState: string;\n checks: PullInfo['checks'];\n checkNames: string[]; // every check on the head commit, once each\n failedChecks: string[];\n pendingChecks: string[];\n}\n\nconst uniqueNames = (checks: Check[]) => [...new Set(checks.map(checkName))];\n\nexport async function prDetails(fullName: string, number: number): Promise<PrDetails> {\n const raw = await ghJson<{\n number: number;\n title: string;\n body: string;\n url: string;\n headRefName: string;\n headRefOid: string;\n isCrossRepository: boolean;\n closingIssuesReferences: { number: number }[] | null;\n state: PrDetails['state'];\n mergeable: string;\n mergeStateStatus: string;\n statusCheckRollup: RawPull['statusCheckRollup'];\n }>(['pr', 'view', String(number), '-R', fullName, '--json', 'number,title,body,url,headRefName,headRefOid,isCrossRepository,closingIssuesReferences,state,mergeable,mergeStateStatus,statusCheckRollup']);\n const rollup = raw.statusCheckRollup ?? [];\n return {\n number: raw.number,\n title: raw.title,\n body: raw.body ?? '',\n url: raw.url,\n headRefName: raw.headRefName,\n headSha: raw.headRefOid,\n isCrossRepository: raw.isCrossRepository,\n closesIssues: (raw.closingIssuesReferences ?? []).map((r) => r.number),\n state: raw.state,\n mergeable: raw.mergeable,\n mergeState: raw.mergeStateStatus || 'UNKNOWN',\n checks: checksOf(rollup),\n checkNames: uniqueNames(rollup),\n failedChecks: uniqueNames(rollup.filter(failed)),\n pendingChecks: uniqueNames(rollup.filter(pending)),\n };\n}\n\nexport async function issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }> {\n const raw = await ghJson<{ title: string; body: string }>(['issue', 'view', String(number), '-R', fullName, '--json', 'title,body']);\n return { title: raw.title, body: raw.body ?? '' };\n}\n\nexport async function commentPull(fullName: string, number: number, body: string): Promise<string> {\n const out = await gh(['pr', 'comment', String(number), '-R', fullName, '--body-file', '-'], { input: body });\n return out.match(/https:\\/\\/github\\.com\\/\\S+/)?.[0] ?? '';\n}\n\n// QA screenshots live on an orphan branch so evidence never lands in the default branch when a PR is merged.\nexport const EVIDENCE_BRANCH = 'swarm-qa-evidence';\nconst evidenceReady = new Set<string>();\n\nconst ghApiJson = <T>(method: string, endpoint: string, body: unknown) =>\n gh(['api', '-X', method, endpoint, '-H', 'Content-Type: application/json', '--input', '-'], { input: JSON.stringify(body), timeoutMs: 120_000 }).then(\n (out) => (out ? JSON.parse(out) : null) as T,\n );\n\nasync function ensureEvidenceBranch(fullName: string) {\n if (evidenceReady.has(fullName)) return;\n try {\n await gh(['api', `repos/${fullName}/git/ref/heads/${EVIDENCE_BRANCH}`]);\n } catch {\n const readme =\n '# QA evidence\\n\\nScreenshots attached to pull request QA reports by cubefarm QA agents.\\nThis branch has no shared history with the code and is never merged.\\n';\n const newTree = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/trees`, {\n tree: [{ path: 'README.md', mode: '100644', type: 'blob', content: readme }],\n });\n const commit = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/commits`, { message: 'QA evidence branch (cubefarm)', tree: newTree.sha, parents: [] });\n await ghApiJson('POST', `repos/${fullName}/git/refs`, { ref: `refs/heads/${EVIDENCE_BRANCH}`, sha: commit.sha });\n }\n evidenceReady.add(fullName);\n}\n\n/** Upload one evidence file and return a URL that renders inside PR comments (also for private repos). */\nexport async function uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string> {\n await ensureEvidenceBranch(fullName);\n await ghApiJson('PUT', `repos/${fullName}/contents/${filePath}`, {\n message: `QA evidence: ${filePath}`,\n content: data.toString('base64'),\n branch: EVIDENCE_BRANCH,\n });\n return `https://github.com/${fullName}/raw/${EVIDENCE_BRANCH}/${filePath}`;\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { HOME_DIR, WORKSPACE_ROOT } from './config.ts';\nimport { type CommandError, gh, git, run } from './exec.ts';\n\n// Layout on disk:\n// <your projects folder>/<repo> the floor's main checkout: your own folder, only fetched and fast-forwarded (syncMain)\n// <WORKSPACE_ROOT>/<owner>__<repo>/desks/<agent> one git worktree per agent, reused from task to task\n// Desks stay outside your project so its dev server, tsc and linters never see them.\n// Floors connected before project folders existed keep their clone at <WORKSPACE_ROOT>/<owner>__<repo>/main.\n\nconst locks = new Map<string, Promise<unknown>>();\nconst localRoots = new Map<string, string>(); // lowercased owner/name -> the user's project folder\n\n/** Serialise git operations per repo so concurrent worktree adds don't fight over index locks. */\nfunction withRepoLock<T>(fullName: string, fn: () => Promise<T>): Promise<T> {\n const prev = locks.get(fullName) ?? Promise.resolve();\n const next = prev.catch(() => undefined).then(fn);\n locks.set(fullName, next);\n return next;\n}\n\nexport const repoDir = (fullName: string) => path.join(WORKSPACE_ROOT, fullName.replace('/', '__'));\nexport const mainDir = (fullName: string) => localRoots.get(fullName.toLowerCase()) ?? path.join(repoDir(fullName), 'main');\nexport const deskDir = (fullName: string, agentSlug: string) => path.join(repoDir(fullName), 'desks', agentSlug);\n\n/** Use the user's own folder as a floor's main checkout (null: back to a clone the office manages). */\nexport function setLocalPath(fullName: string, dir: string | null) {\n if (dir) localRoots.set(fullName.toLowerCase(), path.resolve(dir));\n else localRoots.delete(fullName.toLowerCase());\n}\n\nasync function exists(p: string) {\n return fs\n .access(p)\n .then(() => true)\n .catch(() => false);\n}\n\n// Tool droppings that should never be committed from a desk (shared by all worktrees of the clone).\n// .preview-tmp/ is the preview worktree's {tmp} scratch folder.\nconst LOCAL_EXCLUDES = ['.playwright-mcp/', '.preview-tmp/'];\n\nasync function addLocalExcludes(main: string) {\n const file = path.join(main, '.git', 'info', 'exclude');\n const current = await fs.readFile(file, 'utf8').catch(() => '');\n const missing = LOCAL_EXCLUDES.filter((l) => !current.split(/\\r?\\n/).includes(l));\n if (missing.length === 0) return;\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.appendFile(file, `${current && !current.endsWith('\\n') ? '\\n' : ''}# added by cubefarm\\n${missing.join('\\n')}\\n`);\n}\n\n/** Make sure the floor's worktrees keep LOCAL_EXCLUDES out of git status. */\nexport const ensureLocalExcludes = (fullName: string) => addLocalExcludes(mainDir(fullName));\n\nexport function ensureClone(fullName: string): Promise<void> {\n return withRepoLock(fullName, async () => {\n const dir = mainDir(fullName);\n if (await exists(path.join(dir, '.git'))) {\n // Only remote-tracking refs change: your checkout, branch and uncommitted work are left alone.\n await git(['fetch', 'origin', '--prune'], { cwd: dir, timeoutMs: 180_000 });\n } else {\n await fs.mkdir(path.dirname(dir), { recursive: true });\n await gh(['repo', 'clone', fullName, dir], { timeoutMs: 600_000 });\n }\n await addLocalExcludes(dir);\n });\n}\n\nconst installs = new Map<string, Promise<unknown>>();\n\n/** npm install in a folder, one at a time per folder. */\nfunction npmInstall(dir: string) {\n const prev = installs.get(dir) ?? Promise.resolve();\n const opts = { cwd: dir, timeoutMs: 600_000 };\n const next = prev\n .catch(() => undefined)\n .then(() => (process.platform === 'win32' ? run('cmd.exe', ['/d', '/s', '/c', 'npm install --no-audit --no-fund'], opts) : run('npm', ['install', '--no-audit', '--no-fund'], opts)));\n installs.set(dir, next);\n return next;\n}\n\n/**\n * The paths in `git status --porcelain` output, as git prints them (repo-relative, forward slashes); for a rename\n * or copy (`old -> new`) the new path. Tolerates a first line whose leading space was trimmed (exec trims stdout).\n */\nexport function porcelainPaths(porcelain: string): string[] {\n return porcelain\n .split(/\\r?\\n/)\n .map((line) => /^([ MTADRCU?!]{1,2}) (.+)$/.exec(line))\n .filter((m): m is RegExpExecArray => m !== null)\n .map(([, xy, file]) => (/[RC]/.test(xy) ? (/^(?:\"(?:[^\"\\\\]|\\\\.)*\"|.*?) -> (.+)$/.exec(file)?.[1] ?? file) : file));\n}\n\n/** The paths git lists (tab-indented) under \"... would be overwritten by merge:\" in a failed merge's stderr. */\nexport function overwrittenPaths(stderr: string): string[] {\n const lines = stderr.split(/\\r?\\n/);\n const start = lines.findIndex((l) => /would be overwritten by/.test(l));\n if (start < 0) return [];\n const files: string[] = [];\n for (const line of lines.slice(start + 1)) {\n if (!line.startsWith('\\t')) break;\n files.push(line.trim());\n }\n return files.filter(Boolean);\n}\n\n/** The first few paths, then \"+K more\": \"a, b, c +2 more\", kept to about `maxChars` so a status stays short. */\nexport function fileList(files: string[], max = 3, maxChars = 120): string {\n const shown: string[] = [];\n let length = 0;\n for (const file of files.slice(0, max)) {\n const name = file.length > maxChars ? `\u2026${file.slice(-(maxChars - 1))}` : file;\n const add = name.length + (shown.length ? 2 : 0);\n if (shown.length && length + add > maxChars) break;\n shown.push(name);\n length += add;\n }\n const more = files.length - shown.length;\n return `${shown.join(', ')}${more ? ` +${more} more` : ''}`;\n}\n\n/** How a floor's main checkout stands after syncMain. */\nexport interface MainSync {\n status: string; // e.g. \"in sync\", \"updated to abc1234\", \"update ready (3 commits)\" or \"2 behind: local changes in README.md\"\n behind: number; // commits it is still behind GitHub's default branch\n updatable: boolean; // on the default branch without local commits, so a fast-forward would bring it up to date\n}\n\n/**\n * Bring a floor's main checkout up to date with GitHub. It only ever fast-forwards, and only when the checkout is on\n * the default branch with no local changes: nothing is stashed, reset or discarded, and anything else leaves the\n * folder as it is. Installs dependencies when package.json or the lockfile changed. With `touch: false` it only\n * reports (the office's own folder). Returns how the checkout stands; null when there is no checkout yet.\n */\nexport async function syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<MainSync | null> {\n const dir = mainDir(fullName);\n const result = await withRepoLock(fullName, async (): Promise<(MainSync & { install?: boolean }) | null> => {\n if (!(await exists(path.join(dir, '.git')))) return null;\n const g = (args: string[], timeoutMs?: number) => git(args, { cwd: dir, timeoutMs });\n let behind = 0;\n try {\n await g(['fetch', 'origin', '--prune'], 180_000);\n const target = `origin/${defaultBranch}`;\n behind = Number(await g(['rev-list', '--count', `HEAD..${target}`]));\n const commits = `${behind} commit${behind === 1 ? '' : 's'}`;\n const branch = await g(['symbolic-ref', '--short', '-q', 'HEAD']).catch(() => '');\n const stays = (status: string) => ({ status, behind, updatable: false });\n if (branch !== defaultBranch) return stays(`on ${branch ? `branch ${branch}` : 'a detached HEAD'}${behind ? ` (${defaultBranch} is ${commits} ahead)` : ''}`);\n if (behind === 0) return stays('in sync');\n if (Number(await g(['rev-list', '--count', `${target}..HEAD`])) > 0) return stays(`diverged: local commits, and ${commits} to pull`);\n if (!opts.touch) return { status: `update ready (${commits})`, behind, updatable: true };\n const dirty = await g(['status', '--porcelain', '--untracked-files=no']);\n if (dirty) {\n const files = porcelainPaths(dirty);\n return { status: `${behind} behind: local changes${files.length ? ` in ${fileList(files)}` : ''}`, behind, updatable: true };\n }\n const before = await g(['rev-parse', 'HEAD']);\n try {\n await g(['merge', '--ff-only', target], 120_000);\n } catch (err) {\n const files = overwrittenPaths((err as CommandError).stderr ?? '');\n return { status: `${behind} behind: local files are in the way${files.length ? `: ${fileList(files)}` : ''}`, behind, updatable: true };\n }\n const changed = (await g(['diff', '--name-only', before, 'HEAD'])).split(/\\r?\\n/);\n const install = changed.some((f) => f === 'package.json' || f === 'package-lock.json') && (await exists(path.join(dir, 'package.json')));\n return { status: `updated to ${await g(['rev-parse', '--short', 'HEAD'])}`, behind: 0, updatable: false, install };\n } catch (err) {\n return { status: `sync failed: ${(err as Error).message.split(/\\r?\\n/)[0].slice(0, 160)}`, behind, updatable: false };\n }\n });\n if (!result?.install) return result;\n const { install: _install, ...sync } = result;\n // Outside the repo lock: agents' worktrees don't wait for npm.\n try {\n await npmInstall(dir);\n return { ...sync, status: `${sync.status} \u00B7 dependencies installed` };\n } catch (err) {\n console.warn(`npm install in ${dir} failed:`, (err as Error).message);\n return { ...sync, status: `${sync.status} \u00B7 npm install failed` };\n }\n}\n\n// ---------- your projects folder ----------\n\nexport interface LocalFolder {\n name: string;\n path: string;\n git: boolean;\n github: string | null; // owner/name of its GitHub origin\n modified: number;\n}\n\n/** owner/name from a git config's origin URL, if it points at GitHub. */\nfunction githubFromConfig(config: string): string | null {\n const url = config.match(/\\[remote \"origin\"\\][^[]*?url\\s*=\\s*(\\S+)/)?.[1];\n const m = url?.match(/github\\.com[:/]([^/\\s]+)\\/([^/\\s]+?)(?:\\.git)?\\/?$/i);\n return m ? `${m[1]}/${m[2]}` : null;\n}\n\n/** What a folder is: a git repo? with a GitHub origin? Reads .git/config directly, so scanning is quick. */\nexport async function inspectFolder(dir: string): Promise<LocalFolder> {\n const full = path.resolve(dir);\n const stat = await fs.stat(full).catch(() => null);\n if (!stat?.isDirectory()) throw new Error(`${full} is not a folder`);\n const dotGit = path.join(full, '.git');\n const gitStat = await fs.stat(dotGit).catch(() => null);\n let config = '';\n if (gitStat?.isDirectory()) config = await fs.readFile(path.join(dotGit, 'config'), 'utf8').catch(() => '');\n else if (gitStat) {\n // a worktree or submodule: .git is a file pointing at the real git dir\n const ref = (await fs.readFile(dotGit, 'utf8').catch(() => '')).match(/gitdir:\\s*(.+)/)?.[1]?.trim();\n if (ref) {\n const gitDir = path.resolve(full, ref);\n config = await fs.readFile(path.join(gitDir, 'config'), 'utf8').catch(() => fs.readFile(path.join(gitDir, '..', '..', 'config'), 'utf8').catch(() => ''));\n }\n }\n return { name: path.basename(full), path: full, git: !!gitStat, github: githubFromConfig(config), modified: stat.mtimeMs };\n}\n\n/** The folders directly inside the projects folder, most recently changed first. */\nexport async function scanProjects(root: string): Promise<LocalFolder[]> {\n const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => {\n throw new Error(`Can't read the projects folder ${root}`);\n });\n const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules');\n const folders = await Promise.all(dirs.map((e) => inspectFolder(path.join(root, e.name)).catch(() => null)));\n return folders.filter((f): f is LocalFolder => !!f).sort((a, b) => b.modified - a.modified);\n}\n\nasync function commitReadme(dir: string, title: string, description: string) {\n const readme = path.join(dir, 'README.md');\n if (!(await exists(readme))) await fs.writeFile(readme, `# ${title}\\n\\n${description.trim()}\\n`);\n await git(['add', 'README.md'], { cwd: dir });\n try {\n await git(['commit', '-m', 'Initial commit'], { cwd: dir });\n } catch (err) {\n if (!/tell me who you are|user\\.(name|email)/i.test((err as Error).message)) throw err;\n // No git identity on this machine: commit as the GitHub account gh is signed in to.\n const login = await gh(['api', 'user', '--jq', '.login']);\n await git(['-c', `user.name=${login}`, '-c', `user.email=${login}@users.noreply.github.com`, 'commit', '-m', 'Initial commit'], { cwd: dir });\n }\n}\n\n/**\n * Put a folder on GitHub (gh repo create --source --push). Only what's already committed is pushed. A folder with\n * no commits yet gets a README commit, but only when it's empty: the office never decides which of your files go public.\n */\nexport async function publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string> {\n const full = path.resolve(dir);\n const info = await inspectFolder(full);\n if (info.github) return info.github;\n if (!info.git) await git(['init', '-b', 'main'], { cwd: full });\n const hasCommit = await git(['rev-parse', '--verify', 'HEAD'], { cwd: full }).then(\n () => true,\n () => false,\n );\n if (!hasCommit) {\n const files = (await fs.readdir(full)).filter((f) => f !== '.git' && f !== 'README.md');\n if (files.length) {\n throw new Error(`${info.name} has files but no commits yet. Commit what you want on GitHub first (git add, git commit), then publish it.`);\n }\n await commitReadme(full, opts.name, opts.description ?? '');\n }\n const origin = await git(['remote', 'get-url', 'origin'], { cwd: full }).catch(() => '');\n if (origin) throw new Error(`${info.name}'s origin (${origin}) isn't on GitHub. cubefarm needs GitHub for issues and pull requests.`);\n const target = opts.owner ? `${opts.owner}/${opts.name}` : opts.name;\n const args = ['repo', 'create', target, `--${opts.visibility}`, '--source', full, '--remote', 'origin', '--push'];\n if (opts.description) args.push('--description', opts.description);\n const out = await gh(args, { cwd: full, timeoutMs: 120_000 });\n return out.match(/github\\.com\\/([^/\\s]+\\/[^/\\s]+?)(?:\\.git)?(?:\\s|$)/)?.[1] ?? (await inspectFolder(full)).github ?? target;\n}\n\n/** A brand-new project: <root>/<name> with a README, pushed to a new GitHub repo. */\nexport async function createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }) {\n const dir = path.join(root, name);\n if (await exists(dir)) {\n const inside = await fs.readdir(dir).catch(() => ['?']);\n if (inside.length) throw new Error(`${dir} already exists. Pick another name, or connect that folder instead.`);\n }\n await fs.mkdir(dir, { recursive: true });\n await git(['init', '-b', 'main'], { cwd: dir });\n await commitReadme(dir, name, opts.description ?? '');\n const fullName = await publishFolder(dir, { name, ...opts });\n return { fullName, path: dir };\n}\n\nexport interface DeskBase {\n defaultBranch: string;\n /** Start from a pull request's head instead of the default branch (QA testing, fixes after QA). */\n pr?: number;\n}\n\n/** Remove a directory, retrying while Windows still has handles open in it. */\nasync function removeDir(dir: string) {\n await fs.rm(dir, { recursive: true, force: true, maxRetries: 8, retryDelay: 250 });\n}\n\n/** A git lock file this old was left by a git that died: nothing still running holds it. */\nconst STALE_LOCK_MS = 10 * 60_000;\n\n/** A worktree's index.lock (in its gitdir, which its .git file points at) when it is stale, else null. */\nasync function staleIndexLock(wt: string): Promise<string | null> {\n const ref = (await fs.readFile(path.join(wt, '.git'), 'utf8').catch(() => '')).match(/gitdir:\\s*(.+)/)?.[1]?.trim();\n if (!ref) return null;\n const lock = path.join(path.resolve(wt, ref), 'index.lock');\n const stat = await fs.stat(lock).catch(() => null);\n return stat && Date.now() - stat.mtimeMs > STALE_LOCK_MS ? lock : null;\n}\n\n/** Put an existing desk worktree on `branch` at `ref`, keeping ignored files (node_modules, build caches). */\nasync function reuseDesk(wt: string, branch: string, ref: string) {\n await git(['checkout', '--force', '-B', branch, ref], { cwd: wt });\n await git(['reset', '--hard', ref], { cwd: wt });\n // Untracked leftovers from the last task go; ignored files (node_modules, build caches) stay.\n await git(['clean', '-fd'], { cwd: wt }).catch(() => undefined);\n}\n\n/**\n * Empty a desk's folder for a fresh worktree. On Windows a folder can't be removed while a process has it as its\n * working directory; if everything inside it is gone, that's fine: `git worktree add` takes an empty folder.\n */\nasync function clearDeskFolder(wt: string) {\n try {\n await removeDir(wt);\n } catch (err) {\n const left = await fs.readdir(wt).catch(() => null);\n if (left?.length !== 0) {\n throw new Error(\n `Could not clear the desk folder ${wt}: ${(err as Error).message}. A program started by the previous task is probably still running there. Close it and try again.`,\n );\n }\n }\n}\n\n/** `note` hears why the desk couldn't be reused in place, when it has to be rebuilt. */\nexport function prepareDesk(fullName: string, base: DeskBase, agentSlug: string, branch: string, note?: (text: string) => void): Promise<string> {\n return withRepoLock(fullName, async () => {\n const main = mainDir(fullName);\n await git(['fetch', 'origin', '--prune'], { cwd: main, timeoutMs: 180_000 });\n let ref = `origin/${base.defaultBranch}`;\n if (base.pr) {\n // refs/pull/N/head works for branches in this repo and for forks alike\n ref = `origin/pr/${base.pr}`;\n await git(['fetch', 'origin', `+refs/pull/${base.pr}/head:refs/remotes/${ref}`], { cwd: main, timeoutMs: 180_000 });\n }\n try {\n await git(['rev-parse', '--verify', ref], { cwd: main });\n } catch {\n throw new Error(\n base.pr\n ? `Could not fetch pull request #${base.pr} of ${fullName}.`\n : `${fullName} has no ${base.defaultBranch} branch yet. Push an initial commit (or create the repo with a README) before assigning work.`,\n );\n }\n\n const wt = deskDir(fullName, agentSlug);\n\n // Reuse the desk's worktree in place. Deleting it fails on Windows while any process (a dev server\n // the agent left running, a browser) still has its working directory inside, and reuse keeps\n // node_modules warm between tasks.\n if (await exists(path.join(wt, '.git'))) {\n try {\n try {\n await reuseDesk(wt, branch, ref);\n } catch (err) {\n // A git that died mid-command (a crash, a killed CLI) leaves index.lock behind, and every git after it fails.\n const lock = /index\\.lock/.test((err as Error).message) ? await staleIndexLock(wt) : null;\n if (!lock) throw err;\n await fs.rm(lock, { force: true, maxRetries: 3 });\n note?.(`Removed a stale git lock (${lock}) left in the desk.`);\n await reuseDesk(wt, branch, ref);\n }\n return wt;\n } catch (err) {\n // Rebuild the worktree from scratch, but say why: the rebuild can fail in its own way.\n const why = `Couldn't reuse the desk in place, so it's rebuilt: ${(err as Error).message}`;\n console.warn(`${wt}: ${why}`);\n note?.(why);\n }\n }\n\n if (await exists(wt)) {\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\n await clearDeskFolder(wt);\n }\n await git(['worktree', 'prune'], { cwd: main });\n await fs.mkdir(path.dirname(wt), { recursive: true });\n await git(['worktree', 'add', '-B', branch, wt, ref], { cwd: main });\n return wt;\n });\n}\n\n/** `main`: the floor's checkout when it was let go (a disconnect points mainDir elsewhere before this runs). */\nexport function removeDesk(fullName: string, agentSlug: string, main = mainDir(fullName)): Promise<void> {\n return withRepoLock(fullName, async () => {\n const wt = deskDir(fullName, agentSlug);\n if (!(await exists(wt))) return;\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\n await removeDir(wt).catch(() => undefined);\n await git(['worktree', 'prune'], { cwd: main }).catch(() => undefined);\n });\n}\n\n// ---------- desk sweep ----------\n\n// Homes the office lived in before (Office Swarm became cubefarm): desks there can still be registered in a checkout.\nconst OLD_HOMES = ['.office-swarm'];\nconst OFFICE_BRANCH = /^(swarm\\/issue-|qa\\/pr-)/;\n\nexport interface WorktreeEntry {\n path: string;\n /** The branch it has checked out (null: a detached HEAD). */\n branch: string | null;\n locked: boolean;\n}\n\n/** The worktrees in `git worktree list --porcelain` output, the main worktree first. */\nexport function parseWorktrees(porcelain: string): WorktreeEntry[] {\n const out: WorktreeEntry[] = [];\n for (const line of porcelain.split(/\\r?\\n/)) {\n if (line.startsWith('worktree ')) out.push({ path: path.resolve(line.slice(9)), branch: null, locked: false });\n else if (!out.length) continue;\n else if (line.startsWith('branch ')) out[out.length - 1].branch = line.slice(7).replace(/^refs\\/heads\\//, '');\n else if (line === 'locked' || line.startsWith('locked ')) out[out.length - 1].locked = true;\n }\n return out;\n}\n\n/** What a sweep must leave alone. */\nexport interface SweepKeep {\n /** Desks in use: the floor's agents' slugs and its preview's. */\n desks: string[];\n /** Branches in use: agents' current branches and open PRs' heads. */\n branches: string[];\n}\n\nexport interface SweepInput {\n fullName: string;\n /** The office's workspaces folder (WORKSPACE_ROOT). */\n root: string;\n /** The main checkout's worktrees (parseWorktrees), the main worktree first. */\n worktrees: WorktreeEntry[];\n /** The main checkout's local branches. */\n branches: string[];\n /** The folder names in this floor's desks folder under `root`. */\n folders: string[];\n}\n\nexport interface SweepPlan {\n /** Office desks still registered that nobody uses any more. */\n worktrees: WorktreeEntry[];\n /** Folders in the desks folder that are no worktree and nobody's desk. */\n folders: string[];\n /** Finished swarm/issue-* and qa/pr-* branches. */\n branches: string[];\n}\n\nconst samePath = (a: string, b: string) => (process.platform === 'win32' ? a.toLowerCase() === b.toLowerCase() : a === b);\n\n/** A worktree is an office desk when it sits at <root>/<owner>__<repo>/desks/<name>, under this home or an older one. */\nfunction isOfficeDesk(p: string, fullName: string, root: string) {\n const desks = path.dirname(p);\n const repo = path.dirname(desks);\n const workspaces = path.dirname(repo);\n if (!samePath(path.basename(desks), 'desks') || !samePath(path.basename(repo), fullName.replace('/', '__'))) return false;\n if (samePath(workspaces, path.resolve(root))) return true;\n return path.basename(workspaces) === 'workspaces' && OLD_HOMES.some((h) => samePath(path.basename(path.dirname(workspaces)), h));\n}\n\n/**\n * What a sweep removes: office desks nobody uses (never the main worktree or one outside a desks folder), stray\n * folders in the desks folder, and swarm/issue-* / qa/pr-* branches that no remaining worktree has checked out and\n * nothing in `keep` names. Pure, so it can be tested apart from git.\n */\nexport function planSweep(input: SweepInput, keep: SweepKeep): SweepPlan {\n const deskRoot = path.join(path.resolve(input.root), input.fullName.replace('/', '__'), 'desks');\n const kept = (p: string) => keep.desks.some((slug) => samePath(p, path.join(deskRoot, slug)));\n const worktrees = input.worktrees.slice(1).filter((w) => !w.locked && isOfficeDesk(w.path, input.fullName, input.root) && !kept(w.path));\n const stays = input.worktrees.filter((w) => !worktrees.includes(w));\n const folders = input.folders.filter((name) => {\n const p = path.join(deskRoot, name);\n return !kept(p) && !input.worktrees.some((w) => samePath(w.path, p));\n });\n const branches = input.branches.filter((b) => OFFICE_BRANCH.test(b) && !keep.branches.includes(b) && !stays.some((w) => w.branch === b));\n return { worktrees, folders, branches };\n}\n\nexport interface SweepResult {\n desks: number;\n folders: number;\n branches: number;\n /** Patches saved from removed desks (work that was on no remote branch). */\n patches: string[];\n /** Folders still in use by some process: tried again on the next sweep. */\n skipped: string[];\n}\n\n/** Windows won't rename a folder a process still has open (its working directory, an open file): skip those. */\nasync function inUse(dir: string) {\n const probe = `${dir}.sweep`;\n try {\n await fs.rename(dir, probe);\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ENOENT';\n }\n await fs.rename(probe, dir);\n return false;\n}\n\nconst stamp = (d: Date) => `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;\n\n/**\n * Save a desk's modified tracked files and the commits that are on no remote branch to\n * <HOME_DIR>/leftovers/<owner>__<repo>/<desk>-<YYYYMMDD>.patch (format-patch, then `git diff HEAD`). Null: nothing to save.\n */\nasync function saveLeftovers(fullName: string, desk: string): Promise<string | null> {\n const g = (args: string[]) => git(args, { cwd: desk, timeoutMs: 60_000 });\n if (!(await g(['rev-parse', '--verify', '-q', 'HEAD']).catch(() => ''))) return null;\n const dirty = await g(['status', '--porcelain', '--untracked-files=no']);\n const commits = Number(await g(['rev-list', '--count', 'HEAD', '--not', '--remotes']));\n if (!dirty && !commits) return null;\n const dir = path.join(HOME_DIR, 'leftovers', fullName.replace('/', '__'));\n await fs.mkdir(dir, { recursive: true });\n const tmp = await fs.mkdtemp(path.join(dir, '.tmp-'));\n try {\n // Written to files, not read from stdout: exec trims it, and a patch's trailing whitespace matters.\n if (commits) await g(['format-patch', '-q', '-o', tmp, 'HEAD', '--not', '--remotes']);\n if (dirty) await g(['diff', 'HEAD', '--binary', `--output=${path.join(tmp, 'zz-uncommitted.patch')}`]);\n const parts = (await fs.readdir(tmp)).sort();\n const base = `${path.basename(desk)}-${stamp(new Date())}`;\n let file = path.join(dir, `${base}.patch`);\n for (let n = 2; await exists(file); n++) file = path.join(dir, `${base}-${n}.patch`);\n await fs.writeFile(file, Buffer.concat(await Promise.all(parts.map((p) => fs.readFile(path.join(tmp, p))))));\n return file;\n } finally {\n await removeDir(tmp).catch(() => undefined);\n }\n}\n\n/**\n * Clean up after agents who left: their desks (work on no remote branch is saved as a patch first), stray folders in\n * the desks folder, and finished swarm/issue-* / qa/pr-* branches in the main checkout. Only touches what the office\n * made, never kills a process, and skips a folder that is still in use (the next sweep tries again).\n */\nexport function sweepDesks(fullName: string, keep: SweepKeep): Promise<SweepResult> {\n return withRepoLock(fullName, async () => {\n const result: SweepResult = { desks: 0, folders: 0, branches: 0, patches: [], skipped: [] };\n const main = mainDir(fullName);\n if (!(await exists(path.join(main, '.git')))) return result;\n const g = (args: string[]) => git(args, { cwd: main, timeoutMs: 60_000 });\n await g(['worktree', 'prune']);\n // Real paths on both sides: git may print a path another way than the office spells it (8.3 names, symlinks).\n const real = (p: string) => fs.realpath(p).catch(() => p);\n const worktrees = await Promise.all(parseWorktrees(await g(['worktree', 'list', '--porcelain'])).map(async (w) => ({ ...w, path: await real(w.path) })));\n const refs = await g(['for-each-ref', '--format=%(refname)', 'refs/heads/swarm', 'refs/heads/qa']);\n const branches = refs.split(/\\r?\\n/).filter(Boolean).map((r) => r.replace(/^refs\\/heads\\//, ''));\n const root = await real(WORKSPACE_ROOT);\n const deskRoot = path.join(root, fullName.replace('/', '__'), 'desks');\n const folders = (await fs.readdir(deskRoot, { withFileTypes: true }).catch(() => [])).filter((e) => e.isDirectory()).map((e) => e.name);\n const plan = planSweep({ fullName, root, worktrees, branches, folders }, keep);\n\n const held = new Set<string>(); // branches of desks that stay this time\n for (const wt of plan.worktrees) {\n try {\n if (await inUse(wt.path)) throw new Error('in use');\n const patch = await saveLeftovers(fullName, wt.path);\n if (patch) result.patches.push(patch);\n await g(['worktree', 'remove', '--force', wt.path]).catch(() => undefined);\n await removeDir(wt.path);\n result.desks++;\n } catch {\n result.skipped.push(wt.path);\n if (wt.branch) held.add(wt.branch);\n }\n }\n await g(['worktree', 'prune']).catch(() => undefined);\n for (const name of plan.folders) {\n const dir = path.join(deskRoot, name);\n try {\n if (await inUse(dir)) throw new Error('in use');\n await removeDir(dir);\n result.folders++;\n } catch {\n result.skipped.push(dir);\n }\n }\n const doomed = plan.branches.filter((b) => !held.has(b));\n // A few dozen per command (a floor can have hundreds); git deletes what it can and complains about the rest.\n for (let i = 0; i < doomed.length; i += 40) await g(['branch', '-D', ...doomed.slice(i, i + 40)]).catch(() => undefined);\n if (doomed.length) {\n const left = new Set((await g(['for-each-ref', '--format=%(refname)', 'refs/heads/swarm', 'refs/heads/qa'])).split(/\\r?\\n/));\n result.branches = doomed.filter((b) => !left.has(`refs/heads/${b}`)).length;\n }\n return result;\n });\n}\n\n// ---------- leftover processes ----------\n\n// Only these kinds of processes are stopped when walking up from a leftover to its (orphaned) launcher.\nconst LAUNCHERS = ['node.exe', 'cmd.exe', 'bash.exe', 'sh.exe', 'conhost.exe', 'python.exe', 'npm.exe', 'npx.exe', 'bun.exe', 'deno.exe'];\n\n/** What a desk clean-up leaves alone: the office's own processes, and command lines that carry these paths. */\nexport interface OfficeProcesses {\n /** The office, its terminal keeper and every CLI running in an agent's terminal. */\n pids: number[];\n /** Paths only the CLIs' own command lines carry (the office's session files): those are agents, not leftovers. */\n markers: string[];\n}\n\n/** A path as it can appear in a command line: as is, with forward slashes, and JSON-escaped (Codex's -c values). */\nexport const pathForms = (p: string) => [...new Set([p, p.replaceAll('\\\\', '/'), p.replaceAll('\\\\', '\\\\\\\\')])];\n\n/** The processes of a `ps -A -ww -o pid=,args=` listing whose command line points into a desk, except the office's. */\nexport function leftoversInDesk(listing: string, desk: string, keep: OfficeProcesses): number[] {\n const out: number[] = [];\n for (const line of listing.split('\\n')) {\n const m = line.trim().match(/^(\\d+)\\s+(.*)$/);\n if (!m) continue;\n const [pid, args] = [Number(m[1]), m[2]];\n if (keep.pids.includes(pid) || keep.markers.some((mark) => pathForms(mark).some((f) => args.includes(f)))) continue;\n if (pathForms(desk).some((f) => args.includes(f))) out.push(pid);\n }\n return out;\n}\n\n/**\n * Stop what an agent left running: anything listening on its reserved port or whose command line points into its\n * desk, plus the shell/node chain that launched it. Never the office's own processes (the keeper, the CLIs in agents'\n * terminals): the walk up from a leftover stops at them.\n */\nexport async function releaseDesk(fullName: string, agentSlug: string, port: number, keep: OfficeProcesses = { pids: [], markers: [] }): Promise<void> {\n const desk = deskDir(fullName, agentSlug);\n const spare = [process.pid, ...keep.pids];\n if (process.platform === 'win32') {\n const psList = (paths: string[]) => paths.flatMap(pathForms).map((d) => `'${d.toLowerCase().replaceAll(\"'\", \"''\")}'`).join(', ');\n const script = `\n$ErrorActionPreference = 'SilentlyContinue'\n$spare = @(${spare.join(', ')})\n$seed = @()\nGet-NetTCPConnection -LocalPort ${port} -State Listen | ForEach-Object { $seed += [int]$_.OwningProcess }\n$desks = @(${psList([desk])})\n$marks = @(${psList(keep.markers)})\n$all = Get-CimInstance Win32_Process\n$byId = @{}; foreach ($p in $all) { $byId[[int]$p.ProcessId] = $p }\nforeach ($p in $all) {\n if (-not $p.CommandLine) { continue }\n $cmd = $p.CommandLine.ToLower()\n $ours = $false\n foreach ($m in $marks) { if ($cmd.Contains($m)) { $ours = $true } }\n if ($ours) { continue }\n foreach ($d in $desks) { if ($cmd.Contains($d)) { $seed += [int]$p.ProcessId } }\n}\n$launchers = @(${LAUNCHERS.map((n) => `'${n}'`).join(', ')})\n$kill = New-Object 'System.Collections.Generic.HashSet[int]'\nforeach ($id in $seed) {\n $cur = $byId[$id]\n $first = $true\n while ($cur -and -not ($spare -contains [int]$cur.ProcessId) -and ($first -or $launchers -contains $cur.Name.ToLower())) {\n [void]$kill.Add([int]$cur.ProcessId)\n $first = $false\n $cur = $byId[[int]$cur.ParentProcessId]\n }\n}\nforeach ($id in $kill) { taskkill /PID $id /T /F 2>&1 | Out-Null }\nWrite-Output $kill.Count`;\n await run('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], { timeoutMs: 30_000 }).catch(() => undefined);\n return;\n }\n const listening = await run('sh', ['-c', `lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null || true`]).catch(() => '');\n const listing = await run('ps', ['-A', '-ww', '-o', 'pid=,args=']).catch(() => '');\n const pids = new Set([...listening.split(/\\s+/).map(Number), ...leftoversInDesk(listing, desk, keep)]);\n for (const pid of pids) {\n if (!pid || spare.includes(pid)) continue;\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n // already gone\n }\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { query, type CanUseTool, type Options, type SDKMessage, type SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { AgentCli, AgentRole, EffortLevel, LogKind } from '../shared/types.ts';\nimport type { OfficeTools } from './ceo.ts';\nimport type { UsageWarning } from './pacing.ts';\nimport type { AgentTerminal } from './terminal.ts';\nimport { browserProblem, playwrightMcp } from './browser.ts';\nimport { VERSION } from './config.ts';\n\n// One Claude Code instance (via the Claude Agent SDK) working one issue in its own git worktree.\n// The CEO runs through here too, with the office tools instead of a shell.\n\nexport interface SessionOptions {\n cwd: string;\n prompt: string;\n systemAppend: string;\n model: string; // e.g. 'claude-opus-5-5'\n effort: EffortLevel;\n browserTesting: boolean;\n additionalDirectories: string[]; // read-only reference clones of linked repos\n role: AgentRole;\n /** JSON schema for a structured final answer (QA reports). */\n outputSchema?: Record<string, unknown>;\n resumeSessionId?: string;\n /** The CEO's in-process MCP server (mcp__office__*). */\n office?: OfficeTools;\n /** The terminal runtime: the agent's terminal and the CLI to run in it. Without one: an Agent SDK session. */\n terminal?: AgentTerminal;\n cli?: AgentCli;\n /** Who and on what, for the CLI's session name and status line, e.g. \"Ada \u00B7 #12 Add dark mode\". */\n label?: string;\n /** Leave the CLI waiting at its prompt when the task is done, for the manager and for follow-ups. */\n keepAlive?: boolean;\n /** The prompt was typed at the CLI's prompt by the manager: it's already running, so it isn't sent again. */\n typed?: boolean;\n /** Whose terminal it is (the terminal keeper holds this, for the office that picks the CLI up after a restart). */\n agentId?: string;\n /** Follow the session of the CLI still running in the terminal after the office restarted; start nothing. */\n reattach?: boolean;\n}\n\nexport interface LogEntry {\n kind: LogKind;\n text: string;\n tool?: string;\n}\n\nexport interface SessionResult {\n ok: boolean;\n text: string;\n costUsd: number;\n turns: number;\n errors: string[];\n structured?: unknown;\n /** The manager interrupted the turn in the agent's terminal (Esc). */\n interrupted?: boolean;\n}\n\nexport interface SessionCallbacks {\n log(entries: LogEntry[]): void;\n tool(name: string | null): void;\n /** The session to resume next time; null: there's none to resume (the next session starts a new one). */\n sessionId(id: string | null): void;\n browserUrl(url: string): void;\n screenshot(data: Buffer, mime: string): void;\n /** The final text of each turn: the reply to the prompt and to every message sent while it ran. */\n turn?(text: string): void;\n /** Claude turned the session away for the subscription's usage limit (epoch ms when it resets, if known). */\n limited?(resetsAt: number | null): void;\n /** Claude warned that the subscription's usage is getting high (not while on overage). */\n usageWarning?(info: UsageWarning): void;\n finished(result: SessionResult): void;\n}\n\nexport interface SessionHandle {\n send(text: string): void;\n stop(): void;\n}\n\n/** Async queue used as the streaming-input prompt so the manager can message a running agent. */\nclass InputQueue implements AsyncIterable<SDKUserMessage> {\n private items: SDKUserMessage[] = [];\n private waiters: ((r: IteratorResult<SDKUserMessage>) => void)[] = [];\n private closed = false;\n\n push(text: string) {\n if (this.closed) return;\n const msg: SDKUserMessage = { type: 'user', message: { role: 'user', content: text }, parent_tool_use_id: null };\n const waiter = this.waiters.shift();\n if (waiter) waiter({ value: msg, done: false });\n else this.items.push(msg);\n }\n\n close() {\n this.closed = true;\n for (const w of this.waiters.splice(0)) w({ value: undefined, done: true });\n }\n\n [Symbol.asyncIterator](): AsyncIterator<SDKUserMessage> {\n return {\n next: () => {\n const item = this.items.shift();\n if (item) return Promise.resolve({ value: item, done: false });\n if (this.closed) return Promise.resolve({ value: undefined, done: true });\n return new Promise((resolve) => this.waiters.push(resolve));\n },\n };\n }\n}\n\n// ---------- permissions and screenshots ----------\n\n// Agents work like the manager's own CLI, but nobody may be watching to answer a permission question: every tool call\n// is approved. The office's rules (branches, pull requests, QA leaving GitHub alone) are in their instructions only.\nconst allowAll: CanUseTool = async (_toolName, input) => ({ behavior: 'allow', updatedInput: input });\n\n/**\n * A Playwright screenshot saved to a file (browser_take_screenshot with a filename) comes back as a link, not an\n * image: the file, read from the agent's worktree, so it still counts as QA evidence.\n */\nexport function screenshotFile(cwd: string, text: string): { data: Buffer; mime: string } | null {\n const file = text.match(/\\]\\(([^)\\s]+\\.(png|jpe?g))\\)/i);\n if (!file) return null;\n try {\n return { data: fs.readFileSync(path.resolve(cwd, file[1])), mime: /png$/i.test(file[2]) ? 'image/png' : 'image/jpeg' };\n } catch {\n return null;\n }\n}\n\nconst IMAGE_MIME: Record<string, string> = { '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg' };\n\n/**\n * Screenshots in a browser's output folder that aren't in `seen` yet, oldest first (Playwright names them\n * page-<timestamp>). Files changed in the last second may still be being written, so they wait for the next look.\n */\nexport function newScreenshots(dir: string, seen: Set<string>, now = Date.now()): { name: string; file: string; mime: string }[] {\n let names: string[];\n try {\n names = fs.readdirSync(dir);\n } catch {\n return [];\n }\n const found: { name: string; file: string; mime: string }[] = [];\n for (const name of names.sort()) {\n const mime = IMAGE_MIME[path.extname(name).toLowerCase()];\n const file = path.join(dir, name);\n if (!mime || seen.has(name)) continue;\n try {\n if (now - fs.statSync(file).mtimeMs < 1000) continue;\n } catch {\n continue;\n }\n found.push({ name, file, mime });\n }\n return found;\n}\n\n// ---------- formatting the stream into terminal lines ----------\n\nexport const clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 1)}\u2026` : s);\n\nfunction rel(cwd: string, p: unknown) {\n const s = String(p ?? '');\n if (!s) return '';\n const r = path.relative(cwd, path.resolve(cwd, s)); // a relative path (Codex's patches) is the agent's, not ours\n return r && !r.startsWith('..') ? r.replaceAll('\\\\', '/') : s;\n}\n\nconst escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** Agents often prefix commands with `cd \"<worktree>\" &&` and print absolute paths; show them relative instead. */\nexport function tidyPaths(cwd: string, text: string): string {\n let out = text;\n for (const v of new Set([cwd, cwd.replaceAll('\\\\', '/')])) {\n out = out.replace(new RegExp(`^cd\\\\s+\"?${escapeRe(v)}\"?\\\\s*(&&|;)\\\\s*`, 'i'), '');\n out = out.replace(new RegExp(`${escapeRe(v)}[\\\\\\\\/]?`, 'gi'), './');\n }\n return out;\n}\n\nexport function describeTool(cwd: string, name: string, input: Record<string, unknown>): string {\n switch (name) {\n case 'Bash':\n case 'PowerShell':\n return `$ ${clip(tidyPaths(cwd, String(input.command ?? '')).split('\\n')[0], 220)}`;\n case 'Read':\n return `Read ${rel(cwd, input.file_path)}`;\n case 'Write':\n return `Write ${rel(cwd, input.file_path)}`;\n case 'Edit':\n case 'MultiEdit':\n return `Edit ${rel(cwd, input.file_path)}`;\n case 'Glob':\n return `Glob ${input.pattern}`;\n case 'Grep':\n return `Grep \"${clip(String(input.pattern ?? ''), 80)}\"`;\n case 'WebFetch':\n return `Fetch ${input.url}`;\n case 'WebSearch':\n return `Search \"${input.query}\"`;\n case 'Task':\n case 'Agent':\n return `Subagent: ${input.description ?? ''}`;\n case 'TodoWrite':\n return 'Update todo list';\n case 'ToolSearch':\n return `Load tools ${String(input.query ?? '').replace(/^select:/, '')}`;\n case 'apply_patch': {\n // Codex's file edits: \"*** Add File: a.ts\", \"*** Update File: b.ts\", \"*** Delete File: c.ts\"\n const files = [...String(input.command ?? '').matchAll(/^\\*\\*\\* (Add|Update|Delete) File: (.+)$/gm)].map((m) => `${m[1] === 'Update' ? '' : `${m[1].toLowerCase()} `}${rel(cwd, m[2].trim())}`);\n return `Edit ${clip(files.join(', ') || 'files', 200)}`;\n }\n }\n if (name.startsWith('mcp__playwright__')) {\n const action = name.replace('mcp__playwright__browser_', '').replace('mcp__playwright__', '');\n const detail = input.url ?? input.element ?? input.text ?? '';\n return `\uD83C\uDF10 ${action}${detail ? ` ${clip(String(detail), 120)}` : ''}`;\n }\n if (name.startsWith('mcp__office__')) return describeOfficeTool(name.slice('mcp__office__'.length), input);\n return `${name}(${clip(JSON.stringify(input), 140)})`;\n}\n\nexport function describeOfficeTool(action: string, input: Record<string, unknown>): string {\n const floor = input.floor != null ? ` \u2192 floor ${input.floor}` : '';\n switch (action) {\n case 'company_status':\n return '\uD83C\uDFE2 company_status';\n case 'agent_detail':\n return `\uD83D\uDD0E agent_detail ${String(input.agent_id ?? '')}`;\n case 'set_floor_profile':\n return `\uD83D\uDDC2\uFE0F set_floor_profile${floor}${input.summary ? `: ${clip(String(input.summary), 90)}` : ''}`;\n case 'update_job':\n return `\uD83E\uDEAA update_job ${input.title ? `\"${clip(String(input.title), 60)}\"` : String(input.agent_id ?? '')}`;\n case 'propose_hire':\n return `\uD83E\uDD1D propose_hire ${input.role === 'qa' ? 'QA ' : ''}\"${clip(String(input.title ?? ''), 60)}\"${floor}`;\n case 'propose_let_go':\n return `\uD83D\uDC4B propose_let_go ${String(input.agent_id ?? '')}`;\n case 'file_issue':\n return `\uD83D\uDCDD file_issue \"${clip(String(input.title ?? ''), 70)}\"${floor}${input.specialty ? ` \u00B7 ${input.specialty}` : ''}`;\n case 'route_issue':\n return `\uD83D\uDD00 route_issue #${String(input.number ?? '?')}${floor}${input.specialty !== undefined ? ` \u00B7 ${input.specialty || 'no specialty'}` : ''}${Array.isArray(input.depends_on) ? ` \u00B7 depends on ${input.depends_on.map((n) => `#${n}`).join(', ') || 'nothing'}` : ''}`;\n }\n return `\uD83C\uDFE2 ${action}(${clip(JSON.stringify(input), 120)})`;\n}\n\nexport function todoLines(input: Record<string, unknown>): LogEntry[] {\n const todos = Array.isArray(input.todos) ? (input.todos as { content?: string; status?: string }[]) : [];\n return todos.slice(0, 12).map((t) => ({\n kind: 'result' as const,\n text: ` ${t.status === 'completed' ? '\u2612' : t.status === 'in_progress' ? '\u25D0' : '\u2610'} ${clip(t.content ?? '', 150)}`,\n }));\n}\n\nexport function resultText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n return content\n .filter((b): b is { type: 'text'; text: string } => b?.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n }\n return '';\n}\n\nconst lineCount = (text: string) => text.replace(/\\r/g, '').split('\\n').filter((l) => l.trim() !== '').length;\n\nexport function summariseResult(cwd: string, tool: string, text: string): LogEntry[] {\n // Claude Code-style one-liners for the chatty file tools\n if (tool === 'Edit' || tool === 'MultiEdit' || tool === 'NotebookEdit') return [{ kind: 'result', text: ' \u23BF Updated' }];\n if (tool === 'apply_patch' && /Success\\. Updated the following files/.test(text)) return [{ kind: 'result', text: ' \u23BF Updated' }];\n if (tool === 'Write') return [{ kind: 'result', text: ' \u23BF Saved' }];\n if (tool === 'Read') return [{ kind: 'result', text: ` \u23BF Read ${lineCount(text)} lines` }];\n if (tool === 'Glob') return [{ kind: 'result', text: ` \u23BF Found ${lineCount(text)} files` }];\n const lines = tidyPaths(cwd, text).replace(/\\r/g, '').split('\\n').filter((l) => l.trim() !== '');\n if (lines.length === 0) return [{ kind: 'result', text: ' \u23BF (no output)' }];\n const shown = lines.slice(0, 3).map((l, i) => ({ kind: 'result' as const, text: `${i === 0 ? ' \u23BF ' : ' '}${clip(l, 170)}` }));\n if (lines.length > 3) shown.push({ kind: 'result', text: ` \u2026 +${lines.length - 3} lines` });\n return shown;\n}\n\n// ---------- the session ----------\n\nexport function startSession(opts: SessionOptions, callbacks: SessionCallbacks): SessionHandle {\n let done = false;\n const cb: SessionCallbacks = {\n ...callbacks,\n finished: (r) => {\n if (done) return;\n done = true;\n callbacks.finished(r);\n },\n };\n const input = new InputQueue();\n const abort = new AbortController();\n let pendingTurns = 1;\n let stopped = false;\n let lastCost = 0;\n let lastTurns = 0;\n const toolNames = new Map<string, string>();\n\n input.push(opts.prompt);\n\n // Each agent must be a clean Claude Code instance on the subscription Claude Code is logged into.\n // Drop API keys (they would switch billing to the API) and any CLAUDE_* / ANTHROPIC_* variables\n // inherited from a parent Claude Code session (base URL proxies, session sockets, effort overrides\u2026).\n const env: Record<string, string | undefined> = {};\n for (const [k, v] of Object.entries(process.env)) {\n if (/^(ANTHROPIC_|CLAUDE)/i.test(k) && k !== 'CLAUDE_CONFIG_DIR') continue;\n env[k] = v;\n }\n env.CLAUDE_AGENT_SDK_CLIENT_APP = `cubefarm/${VERSION}`;\n\n const mcpServers: Options['mcpServers'] = {};\n if (opts.browserTesting) {\n const browser = playwrightMcp();\n if (browser) mcpServers.playwright = browser;\n const problem = browserProblem(browser);\n if (problem) cb.log([{ kind: 'error', text: problem }]);\n }\n if (opts.office) mcpServers.office = opts.office.server;\n // The CEO reads repositories and acts through the office tools; it never runs commands.\n const disallowedTools = ['AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode'];\n if (opts.role === 'ceo') disallowedTools.push('Bash', 'PowerShell', 'NotebookEdit');\n\n const options: Options = {\n cwd: opts.cwd,\n additionalDirectories: opts.additionalDirectories,\n abortController: abort,\n env,\n model: opts.model || undefined,\n effort: opts.effort,\n // The manager's own setup (settings, skills, plugins, MCP servers, connectors), plus the office's servers below.\n settingSources: ['user', 'project', 'local'],\n systemPrompt: { type: 'preset', preset: 'claude_code', append: opts.systemAppend },\n mcpServers,\n disallowedTools,\n resume: opts.resumeSessionId,\n stderr: (data) => {\n const line = data.trim();\n if (line && /error|fail/i.test(line)) cb.log([{ kind: 'error', text: clip(line, 200) }]);\n },\n permissionMode: 'acceptEdits',\n canUseTool: allowAll,\n ...(opts.outputSchema ? { outputFormat: { type: 'json_schema' as const, schema: opts.outputSchema } } : {}),\n };\n\n // The office's prompts are answered one result each. See the 'result' case for results that answer none of them.\n let emptyTurn: NodeJS.Timeout | undefined;\n const answered = (msg: Extract<SDKMessage, { type: 'result' }>) => {\n pendingTurns -= 1;\n if (pendingTurns > 0) return;\n input.close();\n const ok = msg.subtype === 'success' && !msg.is_error;\n cb.finished({\n ok,\n text: msg.subtype === 'success' ? msg.result : '',\n costUsd: lastCost,\n turns: lastTurns,\n errors: msg.subtype === 'success' ? [] : msg.errors,\n structured: msg.subtype === 'success' ? msg.structured_output : undefined,\n });\n };\n\n const handle = (msg: SDKMessage) => {\n clearTimeout(emptyTurn);\n if (done && msg.type === 'assistant' && !stopped) {\n // The office already treated this session as finished and no longer follows it.\n stopped = true;\n cb.log([{ kind: 'system', text: '\u25A0 This session kept working after it had finished, so it was stopped.' }]);\n abort.abort();\n return;\n }\n switch (msg.type) {\n case 'system': {\n if (msg.subtype === 'init') {\n cb.sessionId(msg.session_id);\n const mcp = msg.mcp_servers.map((s) => `${s.name}:${s.status}`).join(', ');\n cb.log([\n { kind: 'system', text: `\u273B Claude Code ${msg.claude_code_version} \u00B7 ${msg.model} \u00B7 ${msg.effort ?? opts.effort} effort` },\n { kind: 'system', text: ` cwd ${msg.cwd}${mcp ? ` \u00B7 mcp ${mcp}` : ''}` },\n ]);\n } else if (msg.subtype === 'api_retry') {\n cb.log([{ kind: 'system', text: `\u2026 API retry ${msg.attempt}/${msg.max_retries} in ${Math.round(msg.retry_delay_ms / 1000)}s` }]);\n } else if (msg.subtype === 'compact_boundary') {\n cb.log([{ kind: 'system', text: '\u273B Conversation compacted' }]);\n }\n break;\n }\n case 'rate_limit_event': {\n const info = msg.rate_limit_info;\n if (info.status !== 'allowed') {\n const when = info.resetsAt ? new Date(info.resetsAt * 1000).toLocaleTimeString() : 'later';\n cb.log([{ kind: 'error', text: `\u26A0 Subscription usage ${info.status === 'rejected' ? 'limit reached' : 'warning'} (${info.rateLimitType ?? 'limit'}) \u00B7 resets ${when}` }]);\n const overage = info.isUsingOverage || info.overageStatus === 'allowed' || info.overageStatus === 'allowed_warning';\n if (info.status === 'rejected' && !overage) cb.limited?.(info.resetsAt ? info.resetsAt * 1000 : null);\n if (info.status === 'allowed_warning' && !overage) {\n cb.usageWarning?.({ resetsAt: info.resetsAt ? info.resetsAt * 1000 : null, rateLimitType: info.rateLimitType ?? null, utilization: info.utilization ?? null });\n }\n }\n break;\n }\n case 'assistant': {\n if (msg.parent_tool_use_id) break; // subagent chatter stays off the main screen\n const out: LogEntry[] = [];\n for (const block of msg.message.content) {\n if (block.type === 'text' && block.text.trim()) {\n const lines = block.text.trim().split('\\n');\n lines.slice(0, 30).forEach((l, i) => out.push({ kind: 'text', text: `${i === 0 ? '\u25CF ' : ' '}${l}` }));\n if (lines.length > 30) out.push({ kind: 'text', text: ` \u2026 (${lines.length - 30} more lines)` });\n } else if (block.type === 'thinking') {\n out.push({ kind: 'thinking', text: '\u273B Thinking\u2026' });\n } else if (block.type === 'tool_use') {\n const toolInput = (block.input ?? {}) as Record<string, unknown>;\n toolNames.set(block.id, block.name);\n out.push({ kind: 'tool', tool: block.name, text: `\u23FA ${describeTool(opts.cwd, block.name, toolInput)}` });\n if (block.name === 'TodoWrite') out.push(...todoLines(toolInput));\n cb.tool(block.name);\n if (block.name === 'mcp__playwright__browser_navigate' && typeof toolInput.url === 'string') cb.browserUrl(toolInput.url);\n }\n }\n if (out.length) cb.log(out);\n break;\n }\n case 'user': {\n if (msg.parent_tool_use_id) break;\n const content = msg.message.content;\n if (!Array.isArray(content)) break;\n const out: LogEntry[] = [];\n for (const block of content) {\n if (block.type !== 'tool_result') continue;\n const name = toolNames.get(block.tool_use_id) ?? '';\n const text = resultText(block.content);\n let images = 0;\n if (Array.isArray(block.content)) {\n for (const part of block.content) {\n if (part.type === 'image' && part.source.type === 'base64') {\n images += 1;\n cb.screenshot(Buffer.from(part.source.data, 'base64'), part.source.media_type);\n }\n }\n }\n const saved = name === 'mcp__playwright__browser_take_screenshot' && !images ? screenshotFile(opts.cwd, text) : null;\n if (saved) cb.screenshot(saved.data, saved.mime);\n if (name.startsWith('mcp__playwright__')) {\n const url = text.match(/Page URL:\\s*(\\S+)/);\n if (url) cb.browserUrl(url[1]);\n }\n if (name === 'TodoWrite') continue;\n if (block.is_error) out.push({ kind: 'error', text: ` \u23BF ${clip(tidyPaths(opts.cwd, text).split('\\n')[0] || 'Error', 200)}` });\n else out.push(...summariseResult(opts.cwd, name, text));\n }\n cb.tool(null);\n if (out.length) cb.log(out);\n break;\n }\n case 'result': {\n lastCost = msg.total_cost_usd;\n lastTurns = msg.num_turns;\n if (msg.subtype === 'success' && !msg.is_error && msg.num_turns === 0) {\n // A resumed session can first replay a turn left over from before an office restart: an empty \"success\"\n // that answers none of our prompts, with the real turn right behind it. Counting it ended the session\n // while the real turn ran on without its permission channel. If nothing follows, it was the answer.\n emptyTurn = setTimeout(() => answered(msg), 30_000);\n break;\n }\n if (msg.subtype === 'success' && !msg.is_error && msg.result.trim()) cb.turn?.(msg.result.trim());\n answered(msg);\n break;\n }\n }\n };\n\n (async () => {\n try {\n for await (const msg of query({ prompt: input, options })) handle(msg);\n if (pendingTurns > 0) {\n cb.finished({ ok: false, text: '', costUsd: lastCost, turns: lastTurns, errors: [stopped ? 'Stopped by manager' : 'Session ended unexpectedly'] });\n }\n } catch (err) {\n input.close();\n const message = stopped ? 'Stopped by manager' : err instanceof Error ? err.message : String(err);\n cb.finished({ ok: false, text: '', costUsd: lastCost, turns: lastTurns, errors: [message] });\n }\n })();\n\n return {\n send(text) {\n pendingTurns += 1;\n input.push(text);\n },\n stop() {\n stopped = true;\n clearTimeout(emptyTurn);\n input.close();\n abort.abort();\n },\n };\n}\n", "import fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport os from 'node:os';\nimport path from 'node:path';\n\n// The agents' test browser: the Playwright MCP server pinned in package.json, started with node from the installed\n// package (no npx, no npm registry, no surprise browser download at session start), driving the installed Google\n// Chrome the README asks for.\n\nexport interface McpCommand {\n command: string;\n args: string[];\n}\n\n/** The pinned Playwright MCP's CLI script, resolved from cubefarm's own dependencies; null when it isn't installed. */\nexport function playwrightMcpCli(): string | null {\n try {\n const pkgFile = createRequire(import.meta.url).resolve('@playwright/mcp/package.json');\n const bin = (JSON.parse(fs.readFileSync(pkgFile, 'utf8')) as { bin?: Record<string, string> }).bin?.['playwright-mcp'] ?? 'cli.js';\n return path.join(path.dirname(pkgFile), bin);\n } catch {\n return null;\n }\n}\n\n/**\n * The MCP server command: node on the CLI script, each path its own argument (no shell, so spaces need no quoting).\n * browser-init.js keeps pages from taking the real mouse with pointer lock (headless Chrome does on Windows).\n * `outputDir` gets snapshots and unnamed screenshots (the terminal runtime collects them from there).\n */\nexport function playwrightMcpCommand(cli: string, initScript: string, outputDir?: string, node = process.execPath): McpCommand {\n return { command: node, args: [cli, '--headless', '--isolated', ...(outputDir ? ['--output-dir', outputDir] : []), '--init-script', initScript] };\n}\n\n/** The office's Playwright MCP server for a session, or null when the pinned package can't be found. */\nexport function playwrightMcp(outputDir?: string): McpCommand | null {\n const cli = playwrightMcpCli();\n return cli ? playwrightMcpCommand(cli, path.join(import.meta.dirname, 'browser-init.js'), outputDir) : null;\n}\n\n/** Where Playwright's \"chrome\" channel looks for Google Chrome (bin/cubefarm.js doctor checks the same places). */\nexport function chromePaths(platform: NodeJS.Platform = process.platform, env: NodeJS.ProcessEnv = process.env, home = os.homedir()): string[] {\n if (platform === 'win32') {\n return [env.LOCALAPPDATA, env.PROGRAMFILES, env['PROGRAMFILES(X86)']].filter((d): d is string => !!d).map((d) => path.win32.join(d, 'Google', 'Chrome', 'Application', 'chrome.exe'));\n }\n if (platform === 'darwin') return ['/Applications/Google Chrome.app', path.posix.join(home, 'Applications', 'Google Chrome.app')];\n return ['/opt/google/chrome/chrome', '/usr/bin/google-chrome', '/usr/bin/google-chrome-stable'];\n}\n\nexport const hasChrome = () => chromePaths().some((p) => fs.existsSync(p));\n\n/** The one line a session's log shows when browser testing can't work on this machine, or null when it can. */\nexport function browserProblem(mcp: McpCommand | null, chrome = hasChrome()): string | null {\n if (!mcp) return '\u26A0 The browser tool (@playwright/mcp) is not installed with cubefarm: reinstall it, or run npx cubefarm doctor';\n if (!chrome) return '\u26A0 Google Chrome not found, so this session cannot test in a browser: install it, or run npx cubefarm doctor';\n return null;\n}\n", "import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { Request, Response } from 'express';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { browserProblem, playwrightMcp } from './browser.ts';\nimport { HOME_DIR } from './config.ts';\nimport { cliLabel, CODEX_HOOK_SOURCE, codexThread, commandFor, hookReviewKey, interruptions, isCli, launchArgs, NOTIFY_SOURCE, OPENCODE_PLUGIN_SOURCE, STATUSLINE_SOURCE, trustKey } from './clis.ts';\nimport { adoptPty, discardPty, hooksReady, keeperHookUrl, keeperPid, leaveKeeper, spawnPty, startKeeper, terminalsAvailable, type Pty } from './ptyClient.ts';\nimport {\n clip,\n describeTool,\n newScreenshots,\n resultText,\n screenshotFile,\n summariseResult,\n tidyPaths,\n todoLines,\n type LogEntry,\n type SessionCallbacks,\n type SessionHandle,\n type SessionOptions,\n type SessionResult,\n} from './agentRunner.ts';\nimport type { OfficeTools } from './ceo.ts';\nimport type { AgentTerminal } from './terminal.ts';\nimport type { AgentCli } from '../shared/types.ts';\n\n// One agent session as the real CLI in a pseudo-terminal: the same contract as the Agent SDK runner (log lines, the\n// current tool, the final text, finished), so the rest of the office doesn't care which runtime an agent uses.\n//\n// Claude Code reports through HTTP hooks passed with --settings: every tool call (PreToolUse also approves it, so the\n// CLI never stops to ask), each finished turn (Stop, with the final text), failures (StopFailure) and, through its\n// status line, cost and usage limits. Codex says when a turn ends (notify) and, once the manager trusts the office's\n// hooks in its /hooks, reports its steps through them too. OpenCode's plugin only says when a turn ends.\n//\n// The CLIs run in the office's terminal keeper (ptyClient.ts) and call their hooks there, so an office restart doesn't\n// stop them: the office picks them up again when it's back (reconnectClis).\n\nexport { terminalsAvailable };\n\nconst SESSIONS_DIR = path.join(HOME_DIR, 'sessions');\nconst BIN_DIR = path.join(HOME_DIR, 'bin');\n/** After a turn ends the CLI may still pick up a queued message: only an idle prompt this long means it's done. */\nconst FINISH_GRACE_MS = 3000;\n/** Starting up: how long before the office says the CLI seems to be waiting on something. */\nconst BOOT_MS = 60_000;\n/** Claude's usage warning, the way the SDK's allowed_warning is used: pace new work from here. */\nconst USAGE_WARN_PCT = 90;\n/** Prompts longer than this go in a file: Windows caps a command line at 32K characters. */\nconst INLINE_PROMPT_MAX = 8000;\n\n// ---------- routing the CLIs' calls back to their sessions ----------\n\nlet officeUrl = '';\n\n/** The office's own address, for the hook and MCP endpoints the CLIs call back on. Set once the server listens. */\nexport function setOfficeUrl(url: string) {\n officeUrl = url;\n}\n\ninterface Route {\n hook(body: Record<string, unknown>): Record<string, unknown>;\n office?: OfficeTools;\n}\nconst routes = new Map<string, Route>();\n\n/** A hook, status line or notify call from a CLI (POST /api/hooks/:token). The answer is the hook's output. */\nexport function handleHook(token: string, body: unknown): Record<string, unknown> {\n const route = routes.get(token);\n if (!route || !body || typeof body !== 'object' || Array.isArray(body)) return {};\n try {\n return route.hook(body as Record<string, unknown>);\n } catch (err) {\n console.warn('hook failed', err);\n return {};\n }\n}\n\n/** The CEO's office tools over MCP (Streamable HTTP, stateless: a fresh server per request). */\nexport async function handleMcp(token: string, req: Request, res: Response) {\n const office = routes.get(token)?.office;\n if (!office) {\n res.status(404).json({ jsonrpc: '2.0', error: { code: -32001, message: 'This session has ended.' }, id: null });\n return;\n }\n const server = office.serve();\n const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true });\n res.on('close', () => {\n void transport.close();\n void server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n}\n\n// ---------- helper scripts ----------\n\nlet helpersWritten = false;\n\n/** The status line, notify and plugin scripts the CLIs run. Rewritten once per office start, so updates reach them. */\nfunction writeHelpers() {\n if (helpersWritten) return;\n fs.mkdirSync(BIN_DIR, { recursive: true });\n fs.writeFileSync(path.join(BIN_DIR, 'statusline.cjs'), STATUSLINE_SOURCE);\n fs.writeFileSync(path.join(BIN_DIR, 'notify.cjs'), NOTIFY_SOURCE);\n fs.writeFileSync(path.join(BIN_DIR, 'codex-hook.cjs'), CODEX_HOOK_SOURCE);\n fs.writeFileSync(path.join(BIN_DIR, 'opencode-plugin.mjs'), OPENCODE_PLUGIN_SOURCE);\n helpersWritten = true;\n}\n\n/** A command line for Claude Code's shell (Git Bash on Windows): forward slashes, quoted. */\nconst shellArg = (p: string) => `\"${p.replaceAll('\\\\', '/')}\"`;\n\n// ---------- plumbing ----------\n\nconst HOOK_EVENTS = ['UserPromptSubmit', 'PreToolUse', 'PostToolUse', 'PostToolUseFailure', 'Stop', 'StopFailure', 'Notification'];\n\n/** What a tool call returned, as text, and any images in it (Playwright screenshots). */\nfunction toolOutput(response: unknown): { text: string; images: { data: string; mime: string }[] } {\n const images: { data: string; mime: string }[] = [];\n const blocks = Array.isArray(response) ? response : Array.isArray((response as { content?: unknown })?.content) ? (response as { content: unknown[] }).content : null;\n if (blocks) {\n for (const b of blocks as Record<string, unknown>[]) {\n const source = b?.source as { type?: string; data?: string; media_type?: string } | undefined;\n if (b?.type === 'image' && source?.type === 'base64' && source.data) images.push({ data: source.data, mime: source.media_type ?? 'image/png' });\n else if (b?.type === 'image' && typeof b.data === 'string') images.push({ data: b.data, mime: String(b.mimeType ?? 'image/png') });\n }\n return { text: resultText(blocks), images };\n }\n if (typeof response === 'string') return { text: response, images };\n const r = response as { stdout?: unknown; stderr?: unknown; file?: { content?: unknown }; filenames?: unknown } | null;\n if (r && typeof r === 'object') {\n if (typeof r.stdout === 'string' || typeof r.stderr === 'string') return { text: [r.stdout, r.stderr].filter((s) => typeof s === 'string' && s).join('\\n'), images };\n if (typeof r.file?.content === 'string') return { text: r.file.content, images };\n if (Array.isArray(r.filenames)) return { text: r.filenames.join('\\n'), images };\n }\n return { text: '', images };\n}\n\n/** A pseudo-terminal whose CLI just died throws on writes and resizes before it reports the exit: ignore that. */\nfunction quietly(fn: () => void) {\n try {\n fn();\n } catch {\n // the CLI is gone; its exit is on the way\n }\n}\n\n// ---------- CLIs that outlive their session ----------\n\n/**\n * A CLI running in an agent's terminal. It can outlive the office session that started it: when a developer's task\n * is done their CLI waits at its prompt, so the manager can keep using it, and a follow-up picks it up again. It also\n * outlives an office restart, held by the terminal keeper.\n */\ninterface LiveCli {\n agentId: string;\n cli: AgentCli;\n term: AgentTerminal;\n proc: Pty | null;\n token: string;\n dir: string;\n resumeId: string | null; // the session a follow-up resumes\n statusLine: string;\n /** Browser screenshots already passed on (Codex and OpenCode: collected from the browser's output folder). */\n shots: Set<string>;\n /** The office session driving it; null while it waits at its prompt. */\n session: { hook(b: Record<string, unknown>): Record<string, unknown>; exited(code: number): void } | null;\n idleTimer?: NodeJS.Timeout;\n}\nconst lives = new Map<AgentTerminal, LiveCli>();\n/** How to trust Codex's hooks was said once this run (Codex asks at the start of every session until they are). */\nlet hooksHinted = false;\n/** A CLI left at its prompt this long is closed; its session can still be resumed. */\nconst IDLE_MS = 30 * 60_000;\n\n/** PreToolUse's answer: nobody may be watching to answer a permission question, so every tool call is approved. */\nconst ALLOW = { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow', permissionDecisionReason: 'Approved by cubefarm' } };\n\nconst toolInput = (b: Record<string, unknown>) => (b.tool_input && typeof b.tool_input === 'object' ? b.tool_input : {}) as Record<string, unknown>;\n\n/** The CLI has exited, or has had a few seconds to. */\nconst exitOf = (p: Pty) =>\n new Promise<void>((resolve) => {\n p.onExit(() => resolve());\n setTimeout(resolve, 5000);\n });\n\n/** Close a CLI for good; settles once it has exited. A Codex thread is archived once its CLI is gone (see codexThread). */\nfunction endLive(live: LiveCli): Promise<void> {\n if (lives.get(live.term) !== live) return Promise.resolve();\n lives.delete(live.term);\n clearTimeout(live.idleTimer);\n routes.delete(live.token);\n live.term.releaseIdle = null;\n live.term.bind(null);\n const gone = live.proc ? exitOf(live.proc) : Promise.resolve();\n live.proc?.kill();\n live.proc = null;\n live.term.note(`\u2500\u2500 ${cliLabel(live.cli)} session ended \u2500\u2500`);\n fs.rm(live.dir, { recursive: true, force: true, maxRetries: 5 }, () => undefined);\n if (live.cli === 'codex' && live.resumeId) void codexThread('archive', live.resumeId, gone);\n return gone;\n}\n\n/** What the keeper holds with a CLI's terminal, so the office can pick it up again after a restart. */\ninterface CliMeta {\n agentId: string;\n cli: AgentCli;\n token: string;\n dir: string;\n resumeId: string | null;\n /** An office session was driving it (not waiting at its prompt). */\n busy: boolean;\n}\n\nconst metaOf = (l: LiveCli): CliMeta => ({ agentId: l.agentId, cli: l.cli, token: l.token, dir: l.dir, resumeId: l.resumeId, busy: !!l.session });\nconst remember = (l: LiveCli) => l.proc?.setMeta(metaOf(l));\n\n/** A CLI is running in its terminal: its output, its keys and its hooks are connected. */\nfunction wire(l: LiveCli, office?: OfficeTools) {\n const p = l.proc!;\n lives.set(l.term, l);\n routes.set(l.token, { hook: (b) => (l.session ? l.session.hook(b) : idleHook(l, b)), office });\n l.term.bind({ write: (d) => quietly(() => p.write(d)), resize: (c, r) => quietly(() => p.resize(c, r)) });\n p.onData((data) => {\n if (lives.get(l.term) === l) l.term.write(data);\n });\n p.onExit((code) => {\n l.proc = null;\n if (lives.get(l.term) !== l) return; // already replaced or closed\n if (l.session) l.session.exited(code);\n else endLive(l); // quit while waiting at its prompt\n });\n}\n\n/** The task is done but the CLI stays at its prompt for the manager (or a follow-up), for a while. */\nfunction waitAtPrompt(l: LiveCli) {\n clearTimeout(l.idleTimer);\n l.idleTimer = setTimeout(() => endLive(l), IDLE_MS);\n l.term.releaseIdle = () => endLive(l);\n remember(l);\n}\n\nexport interface ReconnectedCli {\n agentId: string;\n cli: AgentCli;\n resumeId: string | null;\n /** It was working on a task: the office should follow its session again. */\n busy: boolean;\n}\n\n/**\n * The office started: connect to the terminal keeper and take back the CLIs it kept running through the restart, each\n * into its agent's terminal. They wait at their prompt until the office follows their session again (busy ones) or\n * the manager uses them. Ones whose agent is gone, or that exited while the office was away, are stopped: the office\n * resumes those sessions itself. Call hooksReady() once the busy ones are followed again.\n */\nexport async function reconnectClis(terminalFor: (agentId: string) => AgentTerminal | null): Promise<ReconnectedCli[]> {\n const held = await startKeeper(HOME_DIR, handleHook);\n const back: ReconnectedCli[] = [];\n for (const h of held) {\n const meta = (h.meta ?? {}) as Partial<CliMeta>;\n const term = meta.agentId ? terminalFor(meta.agentId) : null;\n if (h.exit !== null || !term || lives.has(term) || !isCli(meta.cli) || !meta.token || !meta.dir || !meta.agentId) {\n discardPty(h);\n if (meta.cli === 'codex' && meta.resumeId) void codexThread('archive', meta.resumeId, h.exit === null ? new Promise((r) => setTimeout(r, 5000)) : undefined);\n continue;\n }\n const l: LiveCli = { agentId: meta.agentId, cli: meta.cli, term, proc: adoptPty(h), token: meta.token, dir: meta.dir, resumeId: meta.resumeId ?? null, statusLine: '\uD83C\uDFE2 cubefarm', shots: new Set(), session: null };\n wire(l);\n waitAtPrompt(l);\n // Resizing makes the CLI draw its whole screen again, over whatever the saved copy of the terminal missed.\n setTimeout(() => quietly(() => (l.proc?.resize(term.cols - 1, term.rows), l.proc?.resize(term.cols, term.rows))), 500);\n back.push({ agentId: l.agentId, cli: l.cli, resumeId: l.resumeId, busy: !!meta.busy });\n }\n return back;\n}\n\nexport { hooksReady };\n\n/**\n * What a desk clean-up (releaseDesk) must leave alone: the keeper, every CLI in a terminal, and the office's session\n * files, which only the CLIs' own command lines carry (Codex's instructions name the worktree, for one).\n */\nexport function officeProcesses(): { pids: number[]; markers: string[] } {\n const pids = [keeperPid(), ...[...lives.values()].map((l) => l.proc?.pid ?? 0)].filter((p) => p > 0);\n return { pids, markers: [SESSIONS_DIR, BIN_DIR] };\n}\n\n/**\n * The office is stopping. On a restart its CLIs carry on in the terminal keeper, which holds their output and hooks\n * until it's back; when it quits for good they stop with it (once they're gone, their Codex threads are archived).\n */\nexport async function releaseClis(restart: boolean): Promise<void> {\n if (!restart) await Promise.all([...lives.values()].map(endLive)); // their exits come through the keeper\n leaveKeeper();\n}\n\n/** A CLI waiting at its prompt: what the manager types there becomes a follow-up. */\nfunction idleHook(live: LiveCli, b: Record<string, unknown>): Record<string, unknown> {\n switch (String(b.hook_event_name ?? '')) {\n case 'PreToolUse':\n return ALLOW;\n case 'UserPromptSubmit': {\n const text = String(b.prompt ?? '').trim();\n if (!text || live.term.onIdlePrompt?.(text)) return {};\n return { decision: 'block', reason: \"The office couldn't take that on as a follow-up right now (see the agent's panel). Nothing was sent.\" };\n }\n case 'StatusLine':\n return { statusLine: live.statusLine };\n }\n return {};\n}\n\n// ---------- the session ----------\n\n/**\n * The Claude Code session a hook reports, once its conversation is on disk: only then can --resume pick it up. Claude\n * writes the file during the first turn, after SessionStart and UserPromptSubmit, so a session the office keeps any\n * earlier could be one that never existed.\n */\nexport function resumableSession(b: Record<string, unknown>, exists: (file: string) => boolean): string | null {\n const id = typeof b.session_id === 'string' ? b.session_id : '';\n const file = typeof b.transcript_path === 'string' ? b.transcript_path : '';\n return id && file && exists(file) ? id : null;\n}\n\n/** Claude Code was told to resume a conversation that isn't on disk (it says so and exits 1). */\nexport const lostConversation = (screen: string) => /No conversation found with session ID/i.test(screen);\n\nexport function startCliSession(opts: SessionOptions, callbacks: SessionCallbacks): SessionHandle {\n const term = opts.terminal!;\n // A follow-up to the session a CLI is still waiting in picks that CLI up again, and so does an office that restarted\n // while it worked (reattach); anything else replaces it.\n const prev = lives.get(term);\n const waiting = !!prev?.proc && !prev.session;\n const adopt = waiting && (!!opts.reattach || (prev!.cli === (opts.cli ?? 'claude') && !!opts.resumeSessionId && prev!.resumeId === opts.resumeSessionId));\n if (prev && !adopt) endLive(prev);\n let live: LiveCli | null = adopt ? prev! : null;\n const cli = live?.cli ?? opts.cli ?? 'claude';\n const label = cliLabel(cli);\n\n const token = crypto.randomUUID();\n const sessionId = opts.resumeSessionId ?? crypto.randomUUID();\n const dir = path.join(SESSIONS_DIR, token);\n const started = Date.now();\n const statusLine = `\uD83C\uDFE2 cubefarm${opts.label ? ` \u00B7 ${opts.label}` : ''}`;\n const toolNames = new Map<string, string>();\n const officePrompts: string[] = []; // prompts the office typed, so the ones the manager typed are told apart\n const launched: string[] = []; // every prompt the CLI was given, as given (Codex: finds its main thread)\n let mainThread: string | null = opts.resumeSessionId ?? null;\n let kept: string | null = opts.resumeSessionId ?? null; // the Claude session the agent has saved to resume\n const usageResets = new Map<string, number | null>();\n const warned = new Set<string>();\n let done = false;\n let costUsd = 0;\n let turns = 0;\n let lastText = '';\n let turnError: string | null = null; // the turn failed (OpenCode reports errors separately from going idle)\n let begun = false; // the CLI took its first prompt\n let finishTimer: NodeJS.Timeout | undefined;\n let bootTimer: NodeJS.Timeout | undefined;\n let screenTimer: NodeJS.Timeout | undefined;\n let shotTimer: NodeJS.Timeout | undefined;\n const nudged = new Set<string>();\n let trustKeys = 0; // keys pressed on a folder-trust question (a few at most)\n let trustedAt = 0;\n\n const cb: SessionCallbacks = { ...callbacks };\n const log = (entries: LogEntry[]) => entries.length && cb.log(entries);\n\n /** Codex and OpenCode don't report tool results: pass on the screenshots their browser saved instead. all: the last look. */\n const collectShots = (all = false) => {\n const l = live;\n if (!l || cli === 'claude' || !opts.browserTesting) return;\n for (const shot of newScreenshots(path.join(l.dir, 'browser'), l.shots, all ? Infinity : Date.now())) {\n l.shots.add(shot.name);\n try {\n cb.screenshot(fs.readFileSync(shot.file), shot.mime);\n } catch {\n // removed before we got to it\n }\n }\n };\n\n /** The session is over. A developer's CLI that ended its turn normally stays at its prompt (keep); others close. */\n const finish = (r: Omit<SessionResult, 'costUsd' | 'turns'>, keep = false) => {\n if (done) return;\n done = true;\n for (const t of [finishTimer, bootTimer]) clearTimeout(t);\n clearInterval(screenTimer);\n clearInterval(shotTimer);\n collectShots(true);\n if (term.onInput === watchKeys) term.onInput = null;\n const l = live;\n if (l && lives.get(term) === l) {\n l.session = null;\n if (keep && opts.keepAlive && l.proc) waitAtPrompt(l);\n else endLive(l);\n }\n cb.tool(null);\n cb.finished({ ...r, costUsd, turns });\n };\n\n /** A turn ended: finished, unless the CLI picks up another prompt within the grace period. */\n const turnEnded = (text: string) => {\n lastText = text;\n cb.tool(null);\n clearTimeout(finishTimer);\n finishTimer = setTimeout(() => finish({ ok: !turnError, text: lastText, errors: turnError ? [turnError] : [] }, true), FINISH_GRACE_MS);\n };\n const busy = () => {\n begun = true;\n clearTimeout(finishTimer);\n };\n\n /** The turn was interrupted from the terminal: the office treats it like Stop, and the CLI waits for the manager. */\n const interrupted = () => finish({ ok: false, text: lastText, errors: ['Interrupted in the terminal'], interrupted: true }, true);\n\n /** Esc typed in the terminal while the agent works: if the CLI then says it interrupted the turn, it's over. */\n const watchKeys = (data: string) => {\n if (data !== '\\x1b' || done || !begun) return;\n const before = interruptions(term.screen());\n let looks = 0;\n const look = () => {\n if (done) return;\n if (interruptions(term.screen()) > before) interrupted();\n else if (++looks < 4) setTimeout(look, 1000);\n };\n setTimeout(look, 800);\n };\n term.onInput = watchKeys;\n\n const assistantLines = (text: string): LogEntry[] => {\n const lines = text.split('\\n');\n const out: LogEntry[] = lines.slice(0, 30).map((l, i) => ({ kind: 'text', text: `${i === 0 ? '\u25CF ' : ' '}${l}` }));\n if (lines.length > 30) out.push({ kind: 'text', text: ` \u2026 (${lines.length - 30} more lines)` });\n return out;\n };\n\n const onStatus = (b: Record<string, unknown>) => {\n const cost = Number((b.cost as { total_cost_usd?: unknown } | undefined)?.total_cost_usd);\n if (Number.isFinite(cost)) costUsd = cost;\n const limits = (b.rate_limits ?? {}) as Record<string, { used_percentage?: unknown; resets_at?: unknown } | null>;\n for (const [type, l] of Object.entries(limits)) {\n const used = Number(l?.used_percentage);\n if (!Number.isFinite(used)) continue;\n const resetsAt = Number(l?.resets_at) > 0 ? Number(l?.resets_at) * 1000 : null;\n usageResets.set(type, used >= 100 ? resetsAt : null);\n if (used >= USAGE_WARN_PCT && used < 100 && !warned.has(type)) {\n warned.add(type);\n cb.usageWarning?.({ resetsAt, rateLimitType: type, utilization: used / 100 });\n }\n }\n return { statusLine };\n };\n\n const hook = (b: Record<string, unknown>): Record<string, unknown> => {\n const event = String(b.hook_event_name ?? '');\n const sub = typeof b.agent_id === 'string' && b.agent_id !== ''; // a subagent's call: kept off the log\n if (cli === 'claude' && !sub && b.session_id !== kept) {\n const id = resumableSession(b, fs.existsSync);\n if (id) {\n kept = id;\n cb.sessionId(id);\n }\n }\n switch (event) {\n case 'PreToolUse': {\n const name = String(b.tool_name ?? '');\n const input = toolInput(b);\n if (!sub) {\n busy();\n turns += 1;\n toolNames.set(String(b.tool_use_id ?? ''), name);\n log([{ kind: 'tool', tool: name, text: `\u23FA ${describeTool(opts.cwd, name, input)}` }, ...(name === 'TodoWrite' ? todoLines(input) : [])]);\n cb.tool(name);\n if (name === 'mcp__playwright__browser_navigate' && typeof input.url === 'string') cb.browserUrl(input.url);\n }\n return ALLOW;\n }\n case 'PostToolUse':\n case 'PostToolUseFailure': {\n if (sub) return {};\n const name = toolNames.get(String(b.tool_use_id ?? '')) ?? String(b.tool_name ?? '');\n const out = toolOutput(b.tool_response);\n // Codex's unnamed screenshots are collected from the browser's folder (its hooks may not be trusted yet).\n if (cli === 'claude') for (const img of out.images) cb.screenshot(Buffer.from(img.data, 'base64'), img.mime);\n const saved = name === 'mcp__playwright__browser_take_screenshot' && !out.images.length ? screenshotFile(opts.cwd, out.text) : null;\n if (saved) cb.screenshot(saved.data, saved.mime);\n if (name.startsWith('mcp__playwright__')) {\n const url = out.text.match(/Page URL:\\s*(\\S+)/);\n if (url) cb.browserUrl(url[1]);\n }\n if (event === 'PostToolUseFailure') log([{ kind: 'error', text: ` \u23BF ${clip(tidyPaths(opts.cwd, String(b.error ?? out.text ?? 'Error')).split('\\n')[0] || 'Error', 200)}` }]);\n else if (name !== 'TodoWrite') log(summariseResult(opts.cwd, name, out.text));\n cb.tool(null);\n return {};\n }\n case 'UserPromptSubmit': {\n if (sub) return {};\n busy();\n const prompt = String(b.prompt ?? '').trim();\n const i = officePrompts.findIndex((p) => p.slice(0, 60) === prompt.slice(0, 60));\n if (i >= 0) officePrompts.splice(i, 1);\n else if (prompt) log([{ kind: 'manager', text: `\u25B6 Typed in the terminal: ${clip(prompt.split('\\n')[0], 200)}` }]);\n return {};\n }\n case 'Stop': {\n const text = String(b.last_assistant_message ?? '').trim();\n turns += 1;\n if (text) {\n log(assistantLines(text));\n cb.turn?.(text);\n }\n turnEnded(text);\n return {};\n }\n case 'StopFailure': {\n const error = String(b.error ?? 'unknown');\n const details = String(b.error_details ?? '').trim();\n if (error === 'rate_limit') cb.limited?.([...usageResets.values()].find((t) => t !== null) ?? null);\n finish({ ok: false, text: lastText, errors: [`${label} stopped: ${error.replace(/_/g, ' ')}${details ? ` (${clip(details, 160)})` : ''}`] }, true);\n return {};\n }\n case 'Notification': {\n if (b.notification_type === 'permission_prompt') log([{ kind: 'error', text: `\u26A0 ${label} is waiting for a permission answer: open the terminal to answer it.` }]);\n return {};\n }\n case 'StatusLine':\n return onStatus(b);\n case 'Interrupt': // Codex: Esc in its terminal\n if (!sub) interrupted();\n return {};\n // Codex's notify program and the OpenCode plugin\n case 'TurnComplete': {\n const thread = typeof b.session_id === 'string' ? b.session_id : '';\n if (cli === 'codex' && thread !== mainThread) {\n // Codex also runs side threads (it titles each task in one): the main thread is the one given our prompt.\n const input = String(b.input ?? '').trim();\n if (mainThread || !launched.some((p) => input.startsWith(p.slice(0, 40)))) return {};\n mainThread = thread;\n }\n if (thread) {\n cb.sessionId(thread);\n if (live && live.resumeId !== thread) {\n live.resumeId = thread;\n remember(live);\n }\n }\n const text = String(b.last_assistant_message ?? '').trim();\n turns += 1;\n if (text) {\n log(assistantLines(text));\n cb.turn?.(text);\n }\n turnEnded(text);\n return {};\n }\n case 'TurnError':\n turnError = `${label}: ${clip(String(b.error ?? 'error'), 200)}`;\n log([{ kind: 'error', text: `\u2717 ${turnError}` }]);\n return {};\n }\n return {};\n };\n\n /** The CLI quit on its own: /exit typed in the terminal, a crash, or it couldn't start (not signed in, bad flag\u2026). */\n const exited = (exitCode: number) => {\n if (cli === 'claude' && opts.resumeSessionId && !begun && lostConversation(term.screen())) {\n cb.sessionId(null);\n finish({ ok: false, text: '', errors: [`${label} couldn't find the conversation it was resuming, so the next session starts a new one.`] });\n return;\n }\n const ok = exitCode === 0 && (lastText !== '' || (cli !== 'claude' && Date.now() - started > 20_000));\n finish({ ok, text: lastText, errors: ok ? [] : [`${label} exited${exitCode ? ` with code ${exitCode}` : ''} before finishing.`] });\n };\n\n const handle: SessionHandle = {\n send(text) {\n const proc = live?.proc;\n if (done || !proc) return;\n busy();\n turnError = null;\n officePrompts.push(text.trim());\n // Pasted, so newlines stay in the message instead of sending it early; then Enter.\n const clean = text.replace(/\\x1b\\[20[01]~/g, '').replace(/\\r\\n?/g, '\\n');\n launched.push(clean.trim());\n quietly(() => proc.write(`\\x1b[200~${clean}\\x1b[201~`));\n setTimeout(() => quietly(() => live?.proc?.write('\\r')), 150);\n },\n stop() {\n finish({ ok: false, text: '', errors: ['Stopped by manager'] });\n },\n };\n\n if (adopt && live) {\n // Back in the CLI that was waiting at its prompt: same conversation, same terminal.\n clearTimeout(live.idleTimer);\n term.releaseIdle = null;\n live.session = { hook, exited };\n Object.assign(live, { statusLine });\n remember(live);\n if (live.resumeId) cb.sessionId(live.resumeId);\n if (opts.typed || opts.reattach) busy(); // typed at the prompt, or still at it after a restart: already running\n else handle.send(opts.prompt);\n shotTimer = setInterval(collectShots, 2000);\n return handle;\n }\n if (opts.reattach) {\n // Its CLI didn't make it through the restart after all.\n setTimeout(() => finish({ ok: false, text: '', errors: [`${label} stopped while the office restarted.`] }), 0);\n return handle;\n }\n\n // ---------- a new CLI: files for this session, and the command line ----------\n\n const cmd = commandFor(cli);\n if (!terminalsAvailable || !cmd) {\n const why = !terminalsAvailable ? 'the terminal module could not be loaded on this machine' : `${label} isn't installed (no \"${cli}\" on PATH)`;\n setTimeout(() => finish({ ok: false, text: '', errors: [`Could not start ${label}: ${why}.`] }), 0);\n return handle;\n }\n\n // Through the keeper, a hook waits while the office restarts instead of failing: the CLIs allow it longer.\n const keeper = keeperHookUrl();\n const hookUrl = `${keeper ?? officeUrl}/api/hooks/${token}`;\n // The browser for a session. Its snapshots and unnamed screenshots go to the session's folder, not the worktree.\n const browser = opts.browserTesting ? playwrightMcp(path.join(dir, 'browser')) : null;\n const browserIssue = opts.browserTesting ? browserProblem(browser) : null;\n if (browserIssue) log([{ kind: 'error', text: browserIssue }]);\n let prompt = opts.prompt;\n if (opts.outputSchema) {\n prompt += `\\n\\nWhen you are done, end your final message with your report as one JSON object in a \\`\\`\\`json block, matching this JSON schema:\\n${JSON.stringify(opts.outputSchema)}`;\n }\n let files: { settings: string; mcp: string | null; system: string };\n try {\n writeHelpers();\n fs.mkdirSync(dir, { recursive: true });\n const settings = {\n hooks: Object.fromEntries(HOOK_EVENTS.map((e) => [e, [{ hooks: [{ type: 'http', url: hookUrl, timeout: keeper ? 120 : 30 }] }]])),\n statusLine: { type: 'command', command: `${shellArg(process.execPath)} ${shellArg(path.join(BIN_DIR, 'statusline.cjs'))} ${shellArg(hookUrl)}`, padding: 0 },\n };\n const servers: Record<string, unknown> = {};\n if (browser) servers.playwright = browser;\n if (opts.office) servers.office = { type: 'http', url: `${officeUrl}/api/mcp/${token}` };\n files = { settings: path.join(dir, 'settings.json'), mcp: Object.keys(servers).length ? path.join(dir, 'mcp.json') : null, system: path.join(dir, 'instructions.md') };\n fs.writeFileSync(files.settings, JSON.stringify(settings, null, 2));\n if (files.mcp) fs.writeFileSync(files.mcp, JSON.stringify({ mcpServers: servers }, null, 2));\n fs.writeFileSync(files.system, opts.systemAppend);\n if (prompt.length > INLINE_PROMPT_MAX) {\n const file = path.join(dir, 'task.md');\n fs.writeFileSync(file, prompt);\n prompt = `Your task is in ${file}. Read all of it first, then do what it says.`;\n }\n } catch (err) {\n setTimeout(() => finish({ ok: false, text: '', errors: [`Could not prepare ${label}: ${(err as Error).message}`] }), 0);\n return handle;\n }\n officePrompts.push(prompt.trim()); // as given: a long one is a pointer to its file\n launched.push(prompt.trim());\n\n const launch = launchArgs(cli, {\n prompt,\n systemAppend: opts.systemAppend,\n model: opts.model,\n effort: opts.effort,\n resumeId: opts.resumeSessionId,\n sessionId,\n name: opts.label ?? 'cubefarm',\n role: opts.role,\n additionalDirectories: opts.additionalDirectories,\n files,\n notify: { script: path.join(BIN_DIR, 'notify.cjs'), url: hookUrl },\n codexHook: path.join(BIN_DIR, 'codex-hook.cjs'),\n plugin: pathToFileURL(path.join(BIN_DIR, 'opencode-plugin.mjs')).href,\n browser,\n });\n\n // Each agent must be a clean instance on the account its CLI is logged into: no API keys (they would switch Claude\n // Code's billing to the API) and nothing inherited from a Claude Code session the office itself was started from.\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(process.env)) {\n if (v === undefined) continue;\n if (/^(ANTHROPIC_|CLAUDE)/i.test(k) && k !== 'CLAUDE_CONFIG_DIR') continue;\n if (/^(NO_COLOR|FORCE_COLOR|TERM_PROGRAM|TERM_PROGRAM_VERSION|CODEX_THREAD_ID|OPENCODE_CONFIG_CONTENT)$/i.test(k)) continue;\n env[k] = v;\n }\n Object.assign(env, { TERM: 'xterm-256color', COLORTERM: 'truecolor' }, launch.env);\n\n if (cli === 'claude' && opts.resumeSessionId) cb.sessionId(sessionId);\n term.note(`\u2500\u2500 ${label}${opts.label ? ` \u00B7 ${opts.label}` : ''} \u2500\u2500`);\n const resumeId = cli === 'claude' ? sessionId : (opts.resumeSessionId ?? null);\n const l: LiveCli = { agentId: opts.agentId ?? '', cli, term, proc: null, token, dir, resumeId, statusLine, shots: new Set(), session: { hook, exited } };\n const begin = () => {\n if (done) return; // stopped while its thread was being unarchived\n let p: Pty;\n try {\n p = spawnPty(cmd.file, [...cmd.args, ...launch.args], { cols: term.cols, rows: term.rows, cwd: opts.cwd, env }, metaOf(l));\n } catch (err) {\n setTimeout(() => finish({ ok: false, text: '', errors: [`Could not start ${label}: ${(err as Error).message}`] }), 0);\n return;\n }\n l.proc = p;\n live = l;\n wire(l, opts.office);\n shotTimer = setInterval(collectShots, 2000);\n\n // Starting up: answer the folder-trust question for the office's own worktrees (the answer that trusts it), and\n // say so when a CLI is waiting on something only the manager can do (signing in).\n screenTimer = setInterval(() => {\n if (done || Date.now() - started > BOOT_MS * 2) return clearInterval(screenTimer);\n const screen = term.screen();\n const review = hookReviewKey(screen);\n const key = trustKeys < 12 && Date.now() - trustedAt > 3000 ? (trustKey(screen) ?? review) : null;\n if (key === 'down') {\n trustKeys += 1;\n quietly(() => p.write(term.appCursor ? '\\x1bOB' : '\\x1b[B'));\n } else if (key === 'enter') {\n trustKeys += 1;\n trustedAt = Date.now(); // the question takes a moment to go: don't answer it twice\n if (!review) log([{ kind: 'system', text: `\u2713 Trusted the worktree for ${label}.` }]);\n else if (!hooksHinted) {\n hooksHinted = true;\n log([{ kind: 'system', text: `\u2139 To see ${label}'s steps here, trust the office's hooks once: in this terminal, type /hooks and press t. Until then the office shows its task.` }]);\n }\n quietly(() => p.write('\\r'));\n }\n if (!nudged.has('login') && /Not logged in|run \\/login|Select login method|Sign in with ChatGPT|Please login|Invalid API key/i.test(screen)) {\n nudged.add('login');\n log([{ kind: 'error', text: `\u26A0 ${label} needs you to sign in: open the terminal and sign in there, or run \"${cli}\" in a terminal of your own.` }]);\n } else if (!nudged.has('setup') && !trustKey(screen) && Date.now() - trustedAt > 5000 && /Choose the text style|Press Enter to continue|Bypass Permissions mode|Settings Error/i.test(screen)) {\n // First-run screens only the manager should answer: the CLI waits for them in the terminal.\n nudged.add('setup');\n log([{ kind: 'error', text: `\u26A0 ${label} is waiting on a setup screen: open the terminal to answer it.` }]);\n }\n }, 1000);\n bootTimer = setTimeout(() => {\n if (!done && !begun && cli === 'claude') log([{ kind: 'error', text: `\u26A0 ${label} hasn't started on the task yet. Open the terminal to see what it's waiting for.` }]);\n }, BOOT_MS);\n };\n // Codex won't resume a thread the office archived (see codexThread): it's unarchived first.\n if (cli === 'codex' && opts.resumeSessionId) void codexThread('unarchive', opts.resumeSessionId).then(begin);\n else begin();\n\n return handle;\n}\n", "import fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { run } from './exec.ts';\nimport type { AgentCli, CliView, EffortLevel } from '../shared/types.ts';\n\n// The coding-agent CLIs an agent can run in its terminal, how to find them on this machine, and how to start one on\n// a task. Claude Code is fully wired in: its hooks report every tool call to the office.\n// The others start on the same prompt and report only when a turn ends (Codex's notify program, an OpenCode plugin);\n// the office shows their task instead of their tool calls.\n\nexport interface CliDef {\n id: AgentCli;\n label: string;\n command: string;\n integrated: boolean;\n}\n\nexport const CLIS: CliDef[] = [\n { id: 'claude', label: 'Claude Code', command: 'claude', integrated: true },\n { id: 'codex', label: 'Codex', command: 'codex', integrated: false },\n { id: 'opencode', label: 'OpenCode', command: 'opencode', integrated: false },\n];\n\nexport const isCli = (v: unknown): v is AgentCli => CLIS.some((c) => c.id === v);\nexport const cliLabel = (id: AgentCli) => CLIS.find((c) => c.id === id)?.label ?? id;\n\n// ---------- finding a CLI ----------\n\nconst WIN = process.platform === 'win32';\n\n/** The executable for a command name on PATH: on Windows only .exe/.cmd/.bat/.com, never an extensionless sh shim. */\nexport function resolveCommand(name: string, env: NodeJS.ProcessEnv = process.env): string | null {\n const key = Object.keys(env).find((k) => k.toUpperCase() === 'PATH') ?? 'PATH';\n const dirs = (env[key] ?? '').split(path.delimiter).filter(Boolean);\n const exts = WIN ? (env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD').split(';').filter((e) => /^\\.(exe|cmd|bat|com)$/i.test(e)) : [''];\n for (const dir of dirs) {\n for (const ext of exts) {\n const file = path.join(dir, name + ext.toLowerCase());\n try {\n const st = fs.statSync(file);\n if (st.isFile() && (WIN || (st.mode & 0o111) !== 0)) return file;\n } catch {\n // not here\n }\n }\n }\n return null;\n}\n\n/**\n * npm installs Windows CLIs as .cmd shims. Running one puts every argument through cmd.exe, which expands %VARS% and\n * trips over quotes in a prompt, so run what the shim runs instead: the package's .exe, or node on its script.\n */\nexport function unwrapCmdShim(shimPath: string, text: string): { file: string; args: string[] } | null {\n const line = text.split(/\\r?\\n/).find((l) => /%\\*\\s*$/.test(l));\n if (!line) return null;\n const dir = path.dirname(shimPath);\n const targets = [...line.matchAll(/\"%dp0%\\\\([^\"]+)\"/g)].map((m) => path.join(dir, m[1]));\n const target = targets[targets.length - 1];\n if (!target) return null;\n if (/\\.exe$/i.test(target)) return { file: target, args: [] };\n if (!/\\.[cm]?js$/i.test(target)) return null;\n const between = line.slice(line.indexOf('\"%_prog%\"') + '\"%_prog%\"'.length, line.lastIndexOf(`\"%dp0%\\\\`));\n const nodeFlags = line.includes('\"%_prog%\"') ? between.trim().split(/\\s+/).filter((f) => f.startsWith('--')) : [];\n const localNode = path.join(dir, 'node.exe');\n return { file: fs.existsSync(localNode) ? localNode : process.execPath, args: [...nodeFlags, target] };\n}\n\n/**\n * The Claude Code the Agent SDK ships as a per-platform package (the one `cubefarm login` signs in with), so the\n * terminal runtime works without Claude Code installed, on the version the office was tested with. Same lookup as\n * the SDK's own and bin/cubefarm.js.\n */\nlet bundled: string | null | undefined;\n\nfunction bundledClaude(): string | null {\n if (bundled !== undefined) return bundled;\n bundled = null;\n let sdk: string;\n try {\n sdk = createRequire(import.meta.url).resolve('@anthropic-ai/claude-agent-sdk');\n } catch {\n return null;\n }\n const { platform, arch } = process;\n // Only Linux needs the report (glibc or musl). On Windows it walks every native handle, and with pseudo-consoles\n // closing on other threads that takes the whole office down.\n const report = platform === 'linux' ? (process.report?.getReport() as { header?: { glibcVersionRuntime?: string } } | undefined) : undefined;\n const musl = platform === 'linux' && !report?.header?.glibcVersionRuntime;\n const targets = platform === 'linux' ? (musl ? [`linux-${arch}-musl`, `linux-${arch}`] : [`linux-${arch}`, `linux-${arch}-musl`]) : [`${platform}-${arch}`];\n for (const target of targets) {\n try {\n bundled = createRequire(sdk).resolve(`@anthropic-ai/claude-agent-sdk-${target}/claude${WIN ? '.exe' : ''}`);\n return bundled;\n } catch {\n // not installed for this target\n }\n }\n return null;\n}\n\n/** How to start a CLI: the program and the arguments that come before the office's own. */\nexport function commandFor(id: AgentCli): { file: string; args: string[] } | null {\n const bundled = id === 'claude' ? bundledClaude() : null;\n if (bundled) return { file: bundled, args: [] };\n const def = CLIS.find((c) => c.id === id);\n const found = def && resolveCommand(def.command);\n if (!found) return null;\n if (WIN && /\\.(cmd|bat)$/i.test(found)) {\n try {\n return unwrapCmdShim(found, fs.readFileSync(found, 'utf8')) ?? { file: found, args: [] };\n } catch {\n return { file: found, args: [] };\n }\n }\n return { file: found, args: [] };\n}\n\n/** Which CLIs this machine has, with their versions. */\nexport async function detectClis(): Promise<CliView[]> {\n return Promise.all(\n CLIS.map(async (c) => {\n const cmd = commandFor(c.id);\n const version = cmd ? await run(cmd.file, [...cmd.args, '--version'], { timeoutMs: 20_000 }).catch(() => null) : null;\n return { id: c.id, label: c.label, installed: !!cmd, version: version?.split(/\\r?\\n/)[0].trim().slice(0, 60) || null, integrated: c.integrated };\n }),\n );\n}\n\n// ---------- starting one on a task ----------\n\nexport interface LaunchContext {\n prompt: string;\n systemAppend: string;\n model: string; // '' = the CLI's own default\n effort: EffortLevel | '';\n resumeId?: string;\n sessionId: string; // the id the office gives a new Claude Code session\n name: string; // shown in Claude Code's prompt box and the terminal title\n role: 'dev' | 'qa' | 'ceo';\n additionalDirectories: string[];\n /** Files the office wrote for this session (settings, MCP config, instructions). */\n files: { settings: string; mcp: string | null; system: string };\n /** Where the CLI's turn-complete signal goes (Codex notify, the OpenCode plugin). */\n notify: { script: string; url: string };\n /** Codex's hook program: forwards each hook to the office (notify.url). */\n codexHook: string;\n plugin: string; // file URL of the OpenCode plugin\n /** The Playwright MCP server, when the floor tests in a browser. Claude Code gets it through its MCP config file. */\n browser: { command: string; args: string[] } | null;\n}\n\nexport interface Launch {\n args: string[];\n env: Record<string, string>;\n}\n\nconst EFFORT_CODEX: Record<EffortLevel, string> = { low: 'low', medium: 'medium', high: 'high', xhigh: 'xhigh', max: 'xhigh' };\n\n/** Codex hooks the office listens to: its steps, and Esc interrupting a turn. Turn endings come from notify. */\nexport const CODEX_HOOK_EVENTS = ['SessionStart', 'UserPromptSubmit', 'PreToolUse', 'PostToolUse', 'Interrupt'];\n\n/**\n * The command Codex runs for each hook. It never changes (the office's address travels in CUBEFARM_HOOK_URL), so the\n * manager trusts the hooks once in Codex's /hooks and that holds for every session. On Windows, Codex runs it through\n * PowerShell or cmd depending on its version, and a command starting with a quote fails in both: plain `node` (on the\n * PATH the office gave it) and the script in double quotes work in either. Elsewhere it goes through the shell.\n */\nexport function codexHookCommand(node: string, script: string, win = WIN): string {\n return win ? `node \"${script}\"` : [node, script].map((s) => `'${s.replaceAll(\"'\", `'\"'\"'`)}'`).join(' ');\n}\n\nexport function launchArgs(id: AgentCli, ctx: LaunchContext): Launch {\n switch (id) {\n case 'claude': {\n const disallowed = ['AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode', ...(ctx.role === 'ceo' ? ['Bash', 'PowerShell', 'NotebookEdit'] : [])];\n const args = [\n ...(ctx.resumeId ? ['--resume', ctx.resumeId] : ['--session-id', ctx.sessionId]),\n ...(ctx.model ? ['--model', ctx.model] : []),\n ...(ctx.effort ? ['--effort', ctx.effort] : []),\n // The office's PreToolUse hook answers every permission question (allow, or deny with an office rule).\n '--permission-mode',\n 'acceptEdits',\n // On top of the manager's own setup (settings, skills, plugins, MCP servers): the office's hooks and servers.\n '--settings',\n ctx.files.settings,\n ...(ctx.files.mcp ? ['--mcp-config', ctx.files.mcp] : []),\n '--append-system-prompt-file',\n ctx.files.system,\n '--name',\n ctx.name,\n ...ctx.additionalDirectories.flatMap((d) => ['--add-dir', d]),\n '--disallowedTools',\n ...disallowed,\n '--',\n ctx.prompt,\n ];\n return { args, env: { DISABLE_AUTOUPDATER: '1' } }; // the office's own copy: agents mustn't each try to update it\n }\n case 'codex': {\n const toml = (s: string) => JSON.stringify(s); // a JSON string is a valid TOML basic string\n const args = [\n '--no-alt-screen',\n '-c',\n `notify=[${[process.execPath, ctx.notify.script, ctx.notify.url].map(toml).join(',')}]`,\n '-c',\n `developer_instructions=${toml(ctx.systemAppend)}`,\n ...(ctx.model ? ['-m', ctx.model] : []),\n ...(ctx.effort ? ['-c', `model_reasoning_effort=${toml(EFFORT_CODEX[ctx.effort])}`] : []),\n ...(ctx.browser ? ['-c', `mcp_servers.playwright={command=${toml(ctx.browser.command)},args=[${ctx.browser.args.map(toml).join(',')}]}`] : []),\n ...CODEX_HOOK_EVENTS.flatMap((e) => ['-c', `hooks.${e}=[{hooks=[{type=\"command\",command=${toml(codexHookCommand(process.execPath, ctx.codexHook))},timeout=10}]}]`]),\n // Like the manager's own Codex, but it can't stop to ask: no approvals and no sandbox (its sandbox can't reach\n // the credential store, so git and gh fail in it).\n '--dangerously-bypass-approvals-and-sandbox',\n ];\n return { args: ctx.resumeId ? ['resume', ...args, ctx.resumeId, ctx.prompt] : [...args, '--', ctx.prompt], env: { CUBEFARM_HOOK_URL: ctx.notify.url } };\n }\n case 'opencode': {\n const config = {\n plugin: [ctx.plugin],\n instructions: [ctx.files.system],\n autoupdate: false, // several agents starting at once must not each reinstall it\n permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' }, // it can't stop to ask either\n ...(ctx.browser ? { mcp: { playwright: { type: 'local', command: [ctx.browser.command, ...ctx.browser.args], enabled: true } } } : {}),\n };\n // No project argument: it starts in its terminal's folder, and a desk path in its command line would make the\n // desk clean-up take it for a leftover.\n const args = [\n '--auto',\n ...(ctx.model ? ['--model', ctx.model] : []),\n ...(ctx.resumeId ? ['--session', ctx.resumeId] : []),\n '--prompt',\n ctx.prompt,\n ];\n return { args, env: { OPENCODE_CONFIG_CONTENT: JSON.stringify(config), CUBEFARM_NOTIFY_URL: ctx.notify.url } };\n }\n }\n}\n\n// ---------- Codex's saved threads ----------\n\n/** Runs each key's steps one after another; one that fails doesn't hold up the next. */\nexport function oneAtATime() {\n const tails = new Map<string, Promise<void>>();\n return (key: string, step: () => Promise<unknown>): Promise<void> => {\n const next = (tails.get(key) ?? Promise.resolve()).then(step).then(\n () => undefined,\n () => undefined,\n );\n tails.set(key, next);\n void next.then(() => tails.get(key) === next && tails.delete(key));\n return next;\n };\n}\n\nconst threadSteps = oneAtATime();\n\n/**\n * Codex saves every terminal session where the manager's own Codex and ChatGPT apps list it with their chats. The\n * office archives its threads there once their CLI is gone (`after`), and unarchives one before resuming it: Codex\n * won't resume an archived thread. A thread's steps run in order; one with nothing to do (already archived) fails.\n */\nexport function codexThread(action: 'archive' | 'unarchive', id: string, after?: Promise<unknown>): Promise<void> {\n return threadSteps(id, async () => {\n await after;\n const cmd = commandFor('codex');\n if (cmd) await run(cmd.file, [...cmd.args, action, id], { timeoutMs: 30_000 });\n });\n}\n\n// ---------- prompts the office answers ----------\n\nconst TRUST_PROMPT = /Quick safety check|Do you trust the (files|contents) (in|of) this|trust this folder|allow Codex to work in this folder/i;\n\n/**\n * The key that moves a CLI's folder-trust question toward trusting the office's own worktree: Enter when the\n * selected option says yes, Down when it says no (Claude Code selects \"No, exit\" first), null when there's no such\n * question on screen.\n */\nexport function trustKey(screen: string): 'enter' | 'down' | null {\n if (!TRUST_PROMPT.test(screen)) return null;\n const selected = screen.match(/^\\s*[\u276F\u203A]\\s*(?:\\d+\\.\\s*)?(.+)$/m)?.[1] ?? '';\n if (/^(yes|trust|continue|proceed)\\b/i.test(selected.trim())) return 'enter';\n if (/^(no|exit|quit|cancel)\\b/i.test(selected.trim())) return 'down';\n return null;\n}\n\n/**\n * Codex asks to review new hooks before it starts. They only show the office Codex's steps, so trusting them is the\n * manager's call (once, in /hooks): the office moves to \"Continue without trusting\" (Down) and takes it (Enter).\n */\nexport function hookReviewKey(screen: string): 'enter' | 'down' | null {\n if (!/Hooks need review/i.test(screen)) return null;\n const selected = screen.match(/^\\s*[\u276F\u203A]\\s*(?:\\d+\\.\\s*)?(.+)$/m)?.[1] ?? '';\n return /^continue without trusting/i.test(selected.trim()) ? 'enter' : 'down';\n}\n\n/**\n * Lines on screen where a CLI says it interrupted a turn (Claude Code: \"Interrupted \u00B7 What should Claude do\n * instead?\", Codex: \"Conversation interrupted\"). Esc fires no hook in Claude Code, so a new one is how the office\n * knows the manager stopped the turn from the terminal.\n */\nexport function interruptions(screen: string): number {\n return screen.split('\\n').filter((l) => /\\binterrupted\\b/i.test(l)).length;\n}\n\n// ---------- helper scripts the CLIs run ----------\n\n/** Claude Code's status line: posts its data (cost, usage limits) to the office and shows the office's line. */\nexport const STATUSLINE_SOURCE = String.raw`// cubefarm: Claude Code's status line. Forwards the session's status to the office and prints the office's line.\nconst url = process.argv[2];\nlet body = '';\nprocess.stdin.on('data', (c) => (body += c));\nprocess.stdin.on('end', async () => {\n try {\n const status = JSON.parse(body);\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ hook_event_name: 'StatusLine', session_id: status.session_id, cost: status.cost, rate_limits: status.rate_limits }),\n signal: AbortSignal.timeout(2000),\n });\n const out = await res.json();\n process.stdout.write(String(out.statusLine ?? ''));\n } catch {\n process.stdout.write('cubefarm');\n }\n});\n`;\n\n/** Codex's notify program: Codex runs it with a JSON argument when a turn completes. */\nexport const NOTIFY_SOURCE = String.raw`// cubefarm: Codex's notify program. Tells the office a turn is complete.\nconst [url, payload] = process.argv.slice(2);\nlet event = {};\ntry {\n event = JSON.parse(payload ?? '{}');\n} catch {}\nif (event.type === 'agent-turn-complete') {\n const input = String((event['input-messages'] ?? [])[0] ?? '').slice(0, 300);\n fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ hook_event_name: 'TurnComplete', session_id: event['thread-id'] ?? null, last_assistant_message: event['last-assistant-message'] ?? '', input }),\n signal: AbortSignal.timeout(3000),\n }).catch(() => {});\n}\n`;\n\n/** Codex's hook program: passes what Codex tells a hook on to the office and answers nothing, so Codex carries on as usual. */\nexport const CODEX_HOOK_SOURCE = String.raw`// cubefarm: Codex's hooks. Tells the office what Codex is doing; never changes what it does.\nconst url = process.env.CUBEFARM_HOOK_URL;\nconst chunks = [];\nprocess.stdin.on('data', (c) => chunks.push(c));\nprocess.stdin.on('end', async () => {\n try {\n if (url) await fetch(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: Buffer.concat(chunks), signal: AbortSignal.timeout(5000) });\n } catch {}\n process.stdout.write('{}');\n});\n`;\n\n/** OpenCode plugin: reports its session and when it goes idle (a turn is complete). No imports: loaded from a file. */\nexport const OPENCODE_PLUGIN_SOURCE = String.raw`// cubefarm: tells the office when OpenCode's session goes idle.\nexport default async function CubefarmPlugin({ client } = {}) {\n const url = process.env.CUBEFARM_NOTIFY_URL;\n if (!url) return {};\n let root;\n const post = (body) =>\n fetch(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body), signal: AbortSignal.timeout(3000) }).catch(() => {});\n const lastReply = async (id) => {\n try {\n const res = await client.session.messages({ path: { id } });\n const reply = (res?.data ?? []).filter((m) => m?.info?.role === 'assistant').pop();\n return (reply?.parts ?? []).filter((p) => p?.type === 'text').map((p) => p.text).join('\\n').trim();\n } catch {\n return '';\n }\n };\n return {\n event: async ({ event }) => {\n const props = event?.properties ?? {};\n if (event?.type === 'session.created' && !props.info?.parentID && !root) root = props.info?.id;\n const sessionID = props.sessionID ?? props.info?.id;\n if (event?.type === 'session.idle' && (!root || sessionID === root)) {\n post({ hook_event_name: 'TurnComplete', session_id: sessionID ?? null, last_assistant_message: sessionID ? await lastReply(sessionID) : '' });\n }\n if (event?.type === 'session.error') post({ hook_event_name: 'TurnError', session_id: sessionID ?? null, error: String(props.error?.data?.message ?? props.error?.name ?? 'error') });\n },\n };\n}\n`;\n", "import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport net from 'node:net';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { IPty } from '@lydell/node-pty';\nimport { encode, hostSocket, PTY_PROTOCOL, readMessages, type FromHost, type HeldPty } from './ptyProtocol.ts';\n\n// The office's side of its terminal keeper (ptyHost.ts): CLIs start in terminals the keeper holds, so they outlive an\n// office restart, and the office picks them up again when it comes back. If the keeper can't start, terminals run in\n// the office's own process and stop with it.\n\nconst nodePty = await import('@lydell/node-pty').catch((err: unknown) => {\n console.warn(` terminals unavailable: ${(err as Error).message}`);\n return null;\n});\n\n/** The native terminal module loaded, so the terminal runtime can run. */\nexport const terminalsAvailable = nodePty !== null;\n\n/** A CLI's pseudo-terminal, held by the keeper or by this process. */\nexport interface Pty {\n readonly pid: number;\n write(data: string): void;\n resize(cols: number, rows: number): void;\n /** Stop the CLI and everything it started. */\n kill(): void;\n /** Kept with the terminal, for the office that picks it up after a restart. */\n setMeta(meta: unknown): void;\n onData(cb: (data: string) => void): void;\n onExit(cb: (code: number) => void): void;\n}\n\nexport interface PtyOptions {\n cols: number;\n rows: number;\n cwd: string;\n env: Record<string, string>;\n}\n\nlet conn: net.Socket | null = null;\nlet leaving = false; // the office is closing its connection on purpose (a restart): the terminals carry on\nlet hookPort = 0;\nlet hostPid = 0;\nlet found: HeldPty[] = [];\nconst remote = new Map<string, RemotePty>();\nlet hookHandler: (token: string, body: unknown) => unknown = () => ({});\n\nconst send = (m: Parameters<typeof encode>[0]) => {\n if (conn && !conn.destroyed) conn.write(encode(m));\n};\n\nclass RemotePty implements Pty {\n pid = 0;\n private dataFns: ((data: string) => void)[] = [];\n private exitFns: ((code: number) => void)[] = [];\n private done = false;\n constructor(readonly id: string) {\n remote.set(id, this);\n }\n write(data: string) {\n send({ op: 'write', id: this.id, data });\n }\n resize(cols: number, rows: number) {\n send({ op: 'resize', id: this.id, cols, rows });\n }\n kill() {\n send({ op: 'kill', id: this.id });\n }\n setMeta(meta: unknown) {\n send({ op: 'meta', id: this.id, meta });\n }\n onData(cb: (data: string) => void) {\n this.dataFns.push(cb);\n }\n onExit(cb: (code: number) => void) {\n this.exitFns.push(cb);\n }\n data(data: string) {\n for (const fn of this.dataFns) fn(data);\n }\n exit(code: number) {\n if (this.done) return;\n this.done = true;\n remote.delete(this.id);\n for (const fn of this.exitFns) fn(code);\n }\n}\n\nfunction onMessage(m: FromHost) {\n switch (m.op) {\n case 'spawned': {\n const p = remote.get(m.id);\n if (p) p.pid = m.pid;\n return;\n }\n case 'failed':\n console.warn(` could not start a terminal: ${m.error}`);\n return remote.get(m.id)?.exit(-1);\n case 'data':\n return remote.get(m.id)?.data(m.data);\n case 'exit':\n return remote.get(m.id)?.exit(m.code);\n case 'hook':\n void Promise.resolve()\n .then(() => hookHandler(m.token, m.body))\n .catch(() => ({}))\n .then((answer) => send({ op: 'hookReply', rid: m.rid, answer }));\n return;\n }\n}\n\n// ---------- connecting ----------\n\ntype Ready = Extract<FromHost, { op: 'ready' }>;\n\n/** Say hello to a keeper: its answer and the open socket, or null when none answers. */\nfunction connect(socket: string, secret: string): Promise<{ ready: Ready; sock: net.Socket } | null> {\n return new Promise((resolve) => {\n const sock = net.connect(socket);\n let ready = false;\n const fail = () => {\n clearTimeout(timer);\n sock.destroy();\n resolve(null);\n };\n const timer = setTimeout(fail, 2000);\n sock.once('error', fail);\n sock.once('connect', () => sock.write(encode({ op: 'hello', secret, version: PTY_PROTOCOL })));\n readMessages<FromHost>(sock, (m) => {\n if (ready) return onMessage(m);\n if (m.op !== 'ready') return;\n ready = true;\n clearTimeout(timer);\n sock.removeListener('error', fail);\n sock.on('error', () => undefined);\n resolve({ ready: m, sock });\n });\n sock.on('close', () => {\n if (conn !== sock) return;\n conn = null;\n if (leaving) return;\n // The keeper is gone, and its terminals with it.\n console.warn(' the terminal keeper stopped; running agents lost their terminals');\n for (const p of [...remote.values()]) p.exit(-1);\n });\n });\n}\n\n/** Node flags the office runs with that the keeper needs too (tsx in development), not debugging or watching. */\nconst runtimeFlags = () => process.execArgv.filter((a, i, all) => !/^--(inspect|watch|debug)/.test(a) && !/^--(inspect|watch|debug)/.test(all[i - 1] ?? ''));\n\nfunction launch(socket: string, secretFile: string) {\n const entry = path.join(import.meta.dirname, `ptyHost${path.extname(import.meta.filename)}`);\n spawn(process.execPath, [...runtimeFlags(), entry, 'launch', socket, secretFile], { detached: true, stdio: 'ignore', windowsHide: true })\n .once('error', () => undefined)\n .unref();\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\n/**\n * Connect to the office's terminal keeper, starting one if there's none (or replacing one on another version).\n * Returns the terminals it still holds from before a restart. Without a keeper, terminals run in this process.\n */\nexport async function startKeeper(home: string, onHook: (token: string, body: unknown) => unknown): Promise<HeldPty[]> {\n hookHandler = onHook;\n if (!nodePty) return [];\n const socket = hostSocket(home);\n const secretFile = path.join(home, 'pty.secret');\n try {\n if (!fs.existsSync(secretFile)) {\n fs.mkdirSync(home, { recursive: true });\n fs.writeFileSync(secretFile, crypto.randomBytes(24).toString('hex'), { mode: 0o600 });\n }\n } catch (err) {\n console.warn(` terminal keeper unavailable: ${(err as Error).message}`);\n return [];\n }\n const secret = fs.readFileSync(secretFile, 'utf8').trim();\n let hello = await connect(socket, secret);\n if (hello && hello.ready.version !== PTY_PROTOCOL) {\n // A keeper from another version of the office: its terminals can't be picked up, so they stop and it goes.\n console.log(` replacing the terminal keeper (v${hello.ready.version}); the ${hello.ready.ptys.length} terminal(s) it held are stopped`);\n hello.sock.end(encode({ op: 'shutdown' }));\n hello = null;\n await sleep(3500);\n }\n if (!hello) {\n launch(socket, secretFile);\n for (let i = 0; i < 30 && !hello; i++) {\n await sleep(200);\n hello = await connect(socket, secret);\n }\n }\n if (!hello) {\n console.warn(\" terminal keeper unavailable: agents' terminals run in the office and stop when it restarts\");\n return [];\n }\n conn = hello.sock;\n leaving = false;\n hookPort = hello.ready.hookPort;\n hostPid = hello.ready.pid ?? 0;\n found = hello.ready.ptys;\n return found;\n}\n\n/** The keeper's process (0 when there's none, or it didn't say): desk clean-ups must never stop it. */\nexport const keeperPid = () => (conn ? hostPid : 0);\n\n// ---------- terminals ----------\n\n/** Where the CLIs' hooks go: the keeper, which holds them while the office restarts. null: straight to the office. */\nexport function keeperHookUrl(): string | null {\n return conn ? `http://127.0.0.1:${hookPort}` : null;\n}\n\n/** A CLI in a new pseudo-terminal: in the keeper when there is one, else in this process (throws if it can't start). */\nexport function spawnPty(file: string, args: string[], o: PtyOptions, meta: unknown): Pty {\n if (conn) {\n const p = new RemotePty(crypto.randomUUID());\n send({ op: 'spawn', id: p.id, file, args, cwd: o.cwd, env: o.env, cols: o.cols, rows: o.rows, meta });\n return p;\n }\n if (!nodePty) throw new Error('the terminal module could not be loaded on this machine');\n // useConptyDll: Windows' own console host lingers after each CLI exits (one conhost.exe per terminal); the one\n // node-pty ships goes with its terminal. Ignored elsewhere.\n const p = nodePty.spawn(file, args, { name: 'xterm-256color', cols: o.cols, rows: o.rows, cwd: o.cwd, env: o.env, useConptyDll: true });\n return {\n get pid() {\n return p.pid;\n },\n write: (data) => p.write(data),\n resize: (cols, rows) => p.resize(cols, rows),\n kill: () => killTree(p),\n setMeta: () => undefined,\n onData: (cb) => void p.onData(cb),\n onExit: (cb) => void p.onExit(({ exitCode }) => cb(exitCode)),\n };\n}\n\n/** Take over a terminal the keeper held through a restart: what it printed meanwhile, then everything live. */\nexport function adoptPty(held: HeldPty): Pty {\n const p = new RemotePty(held.id);\n p.pid = held.pid;\n queueMicrotask(() => send({ op: 'attach', id: held.id })); // once the caller has its listeners on\n return p;\n}\n\n/** A held terminal nobody picks up: its CLI is stopped. */\nexport function discardPty(held: HeldPty) {\n send({ op: 'kill', id: held.id });\n}\n\n/** The office has picked up its terminals and their sessions: hooks that waited for it can come in. */\nexport function hooksReady() {\n send({ op: 'hooksReady' });\n}\n\n/** The office is restarting: its terminals stay with the keeper, which holds their output until it's back. */\nexport function leaveKeeper() {\n leaving = true;\n conn?.end();\n}\n\nfunction killTree(proc: IPty) {\n if (process.platform === 'win32') {\n const tk = spawn('taskkill', ['/PID', String(proc.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' });\n tk.once('error', () => undefined);\n return;\n }\n try {\n process.kill(-proc.pid, 'SIGTERM'); // the CLI leads its own session: take its MCP servers and tools with it\n } catch {\n proc.kill();\n }\n}\n", "import crypto from 'node:crypto';\nimport path from 'node:path';\nimport type { Socket } from 'node:net';\n\n// What the office and its terminal keeper (ptyHost.ts) say to each other over their local socket: one JSON message\n// per line. Kept free of the rest of the server so the keeper stays small and starts fast.\n\n/** Bumped when the messages change: an office that finds a keeper on another version replaces it. */\nexport const PTY_PROTOCOL = 1;\n\n/** A terminal the keeper holds, as it reports it to an office that (re)connects. */\nexport interface HeldPty {\n id: string;\n pid: number;\n /** What the office stored with it (who it belongs to, its session). */\n meta: unknown;\n /** The CLI has exited (while no office was listening): its exit code. */\n exit: number | null;\n}\n\nexport type ToHost =\n | { op: 'hello'; secret: string; version: number }\n | { op: 'hooksReady' } // the office has picked up its terminals: hooks that waited for it can come in now\n | { op: 'spawn'; id: string; file: string; args: string[]; cwd: string; env: Record<string, string>; cols: number; rows: number; meta: unknown }\n | { op: 'attach'; id: string } // an office picking up a terminal it found: what it missed, then everything live\n | { op: 'write'; id: string; data: string }\n | { op: 'resize'; id: string; cols: number; rows: number }\n | { op: 'meta'; id: string; meta: unknown }\n | { op: 'kill'; id: string }\n | { op: 'hookReply'; rid: number; answer: unknown }\n | { op: 'shutdown' }; // stop every terminal and exit (a keeper on another version)\n\nexport type FromHost =\n | { op: 'ready'; version: number; hookPort: number; ptys: HeldPty[]; pid?: number }\n | { op: 'spawned'; id: string; pid: number }\n | { op: 'failed'; id: string; error: string }\n | { op: 'data'; id: string; data: string }\n | { op: 'exit'; id: string; code: number }\n | { op: 'hook'; rid: number; token: string; body: unknown };\n\n/** The keeper's socket for an office home: a named pipe on Windows, a Unix socket in the home elsewhere. */\nexport function hostSocket(home: string, platform = process.platform): string {\n if (platform !== 'win32') return path.join(home, 'pty.sock');\n const tag = crypto.createHash('sha1').update(path.resolve(home).toLowerCase()).digest('hex').slice(0, 12);\n return `\\\\\\\\.\\\\pipe\\\\cubefarm-pty-${tag}`;\n}\n\nexport const encode = (m: ToHost | FromHost) => `${JSON.stringify(m)}\\n`;\n\n/** Calls back with each message a socket sends (newline-delimited JSON); a line that isn't JSON is skipped. */\nexport function readMessages<T>(sock: Socket, onMessage: (m: T) => void) {\n let buf = '';\n sock.setEncoding('utf8');\n sock.on('data', (chunk: string) => {\n buf += chunk;\n let nl: number;\n while ((nl = buf.indexOf('\\n')) >= 0) {\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + 1);\n if (!line) continue;\n let m: T;\n try {\n m = JSON.parse(line) as T;\n } catch {\n continue;\n }\n onMessage(m);\n }\n });\n}\n", "import { spawn, type ChildProcess } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\n// A checkout's npm dependencies, installed by the office before an agent (or a preview) needs them: package.json and\n// package-lock.json are hashed into a marker in node_modules, so an unchanged checkout skips the install.\n\n/** Named for the preview, where it started; desks share it. */\nexport const INSTALL_MARKER = '.cubefarm-preview-install';\nexport const INSTALL_TIMEOUT_MS = 15 * 60_000;\n/** Desk installs running at once, office-wide; the rest queue. */\nexport const MAX_DESK_INSTALLS = 2;\n\n/** What a checkout's dependencies look like on disk. */\nexport interface DepsState {\n /** package.json's text; null when there is none. */\n pkg: string | null;\n /** package-lock.json's text; null when there is none. */\n lock: string | null;\n /** package.json + lockfile hash. */\n hash: string;\n /** The marker the last install left in node_modules ('' when there is none). */\n marker: string;\n nodeModules: boolean;\n}\n\nexport const depsHash = (pkg: string, lock: string | null) => crypto.createHash('sha256').update(pkg).update('\\0').update(lock ?? '').digest('hex');\n\nexport async function readDeps(dir: string): Promise<DepsState> {\n const read = (file: string) => fs.readFile(path.join(dir, file), 'utf8').catch(() => null);\n const [pkg, lock, marker, nodeModules] = await Promise.all([\n read('package.json'),\n read('package-lock.json'),\n read(path.join('node_modules', INSTALL_MARKER)),\n fs\n .stat(path.join(dir, 'node_modules'))\n .then((s) => s.isDirectory())\n .catch(() => false),\n ]);\n return { pkg, lock, hash: depsHash(pkg ?? '', lock), marker: marker ?? '', nodeModules };\n}\n\n/** Whether node_modules was installed from exactly this package.json and lockfile. */\nexport const depsCurrent = (s: DepsState) => s.nodeModules && s.marker === s.hash;\n\nexport const writeMarker = (dir: string, hash: string) => fs.writeFile(path.join(dir, 'node_modules', INSTALL_MARKER), hash).catch(() => undefined);\n\n/**\n * What the office does for a desk: nothing without a package.json; leave it to the agent without a lockfile (so the\n * office never creates one that ends up in a PR); skip when node_modules matches; otherwise npm ci.\n */\nexport function deskDepsPlan(s: DepsState): 'none' | 'agent' | 'skip' | 'install' {\n if (s.pkg === null) return 'none';\n if (s.lock === null) return 'agent';\n return depsCurrent(s) ? 'skip' : 'install';\n}\n\nexport type DepsOutcome = 'none' | 'agent' | 'skipped' | 'installed' | 'failed';\n\n/** The line for the agent's instructions ('' when the office left the dependencies alone). */\nexport function depsPromptLine(outcome: DepsOutcome | null | undefined): string {\n if (outcome === 'installed' || outcome === 'skipped') return 'Dependencies are already installed for this checkout; run npm install only if you change package.json.';\n if (outcome === 'failed') return \"The office couldn't install this checkout's dependencies: run npm install yourself first.\";\n return '';\n}\n\n/** Run at most `max` tasks at once; the rest wait their turn, in order. */\nexport function createLimiter(max: number) {\n let active = 0;\n const waiting: (() => void)[] = [];\n return async function limit<T>(fn: () => Promise<T>): Promise<T> {\n if (active >= max) await new Promise<void>((r) => waiting.push(r));\n else active++;\n try {\n return await fn();\n } finally {\n const next = waiting.shift();\n if (next) next(); // the slot passes straight on\n else active--;\n }\n };\n}\n\nconst deskInstalls = createLimiter(MAX_DESK_INSTALLS);\n\n/** Kill a process and its children. */\nexport function killTree(child: ChildProcess): Promise<void> {\n if (child.pid === undefined || child.exitCode !== null || child.signalCode !== null) return Promise.resolve();\n if (process.platform === 'win32') {\n return new Promise((resolve) => {\n const tk = spawn('taskkill', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' });\n tk.once('error', () => resolve());\n tk.once('close', () => resolve());\n });\n }\n try {\n process.kill(-child.pid, 'SIGKILL'); // the whole process group (spawned detached)\n } catch {\n child.kill('SIGKILL');\n }\n return Promise.resolve();\n}\n\n/** npm ci in a folder (on Windows through cmd.exe); rejects on failure, and kills the tree after `timeoutMs`. */\nexport function npmCi(dir: string, timeoutMs = INSTALL_TIMEOUT_MS): Promise<void> {\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(process.env)) {\n // Same rule as the agents and previews: no Claude credentials or config, and not the office's own settings.\n if (v !== undefined && !/^(ANTHROPIC_|CLAUDE|SWARM_)/i.test(k)) env[k] = v;\n }\n env.NO_COLOR = '1';\n const win = process.platform === 'win32';\n const child = win\n ? spawn('cmd.exe', ['/d', '/s', '/c', 'npm ci --no-audit --no-fund'], { cwd: dir, env, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] })\n : spawn('npm', ['ci', '--no-audit', '--no-fund'], { cwd: dir, env, windowsHide: true, detached: true, stdio: ['ignore', 'pipe', 'pipe'] });\n let tail = '';\n const keep = (buf: Buffer) => (tail = (tail + buf.toString()).slice(-4000));\n child.stdout?.on('data', keep);\n child.stderr?.on('data', keep);\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n void killTree(child);\n reject(new Error(`npm ci took longer than ${Math.round(timeoutMs / 60_000)} minutes`));\n }, timeoutMs);\n child.once('error', (err) => {\n clearTimeout(timer);\n reject(err);\n });\n child.once('close', (code) => {\n clearTimeout(timer);\n if (code === 0) return resolve();\n const last = tail.split(/\\r?\\n/).filter((l) => l.trim()).slice(-3).join(' \u00B7 ');\n reject(new Error(`npm ci failed (code ${code})${last ? `: ${last.slice(0, 300)}` : ''}`));\n });\n });\n}\n\nexport interface DepsCallbacks {\n log(lines: string[]): void;\n /** An install is about to start (possibly waiting for a free slot): nothing matched. */\n installing(): void;\n}\n\n/**\n * Install a desk's dependencies before its agent starts, at most MAX_DESK_INSTALLS at once office-wide. Never throws:\n * a failure is logged and reported as 'failed', and the agent is told to install them itself.\n */\nexport async function installDesk(dir: string, cb: DepsCallbacks, install: (dir: string) => Promise<void> = npmCi): Promise<DepsOutcome> {\n const { log } = cb;\n try {\n const state = await readDeps(dir);\n const plan = deskDepsPlan(state);\n if (plan === 'none') return 'none';\n if (plan === 'agent') {\n log(['No package-lock.json; leaving the dependencies to the agent.']);\n return 'agent';\n }\n if (plan === 'skip') {\n log(['Dependencies unchanged since the last install; skipping it.']);\n return 'skipped';\n }\n log(['Installing dependencies\u2026']);\n cb.installing();\n await deskInstalls(async () => {\n log(['$ npm ci']);\n await install(dir);\n });\n await writeMarker(dir, state.hash);\n log(['Dependencies installed.']);\n return 'installed';\n } catch (err) {\n log([`\u26A0 Could not install the dependencies (${(err as Error).message.split(/\\r?\\n/)[0].slice(0, 300)}); the agent will run npm install itself.`]);\n return 'failed';\n }\n}\n", "import { spawn, type ChildProcess } from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport net from 'node:net';\nimport path from 'node:path';\nimport { depsCurrent, INSTALL_TIMEOUT_MS, killTree, readDeps, writeMarker } from './deps.ts';\nimport { git } from './exec.ts';\nimport * as workspace from './workspace.ts';\n\n// A floor's app, run for the preview monitor: checked out in its own worktree (never the floor's main checkout,\n// which for floor 1 is the folder the live office runs from), installed, started, and watched until its port answers.\n\nexport const PREVIEW_SLUG = 'preview';\nexport const PREVIEW_BRANCH = 'swarm-preview';\n/** Scratch folder inside the preview worktree, offered to commands and env as {tmp}; excluded from git status. */\nexport const PREVIEW_TMP = '.preview-tmp';\nconst START_TIMEOUT_MS = 3 * 60_000;\n\nexport interface PreviewJob {\n fullName: string;\n defaultBranch: string;\n pr: number | null;\n port: number;\n command: string | null;\n env: Record<string, string>;\n /** \"<floor> app \u00B7 <ref>\", for the demo's placeholder page. */\n title: string;\n}\n\nexport interface PreviewCallbacks {\n status(status: 'preparing' | 'installing' | 'starting' | 'running'): void;\n commit(sha: string): void;\n log(lines: string[]): void;\n /** The run ended by itself: failed to start, or the app exited. unconfigured: there was nothing to run. */\n failed(message: string, unconfigured?: boolean): void;\n}\n\nexport interface PreviewHandle {\n /** Stop the app (and anything it started). Safe to call in any phase. */\n stop(): Promise<void>;\n}\n\nexport interface PreviewBackend {\n start(job: PreviewJob, cb: PreviewCallbacks): PreviewHandle;\n /** Whether there is something to run with no command set (a package.json in the floor's checkout). */\n hasDefault(fullName: string): Promise<boolean>;\n}\n\n/** Replace {port} and {tmp}. */\nexport const fillPlaceholders = (s: string, port: number, tmp: string) => s.replaceAll('{port}', String(port)).replaceAll('{tmp}', tmp);\n\n/**\n * The environment a preview runs with: the office's, minus Claude credentials and config (same rule as the agents,\n * with no exceptions) and minus the office's own SWARM_* settings, so an app that is itself an office never\n * inherits the live office's home or port. Then the floor's env, then PORT.\n */\nexport function previewEnv(extra: Record<string, string>, port: number, tmp: string): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(process.env)) {\n if (v === undefined || /^(ANTHROPIC_|CLAUDE|SWARM_)/i.test(k)) continue;\n env[k] = v;\n }\n env.BROWSER = 'none'; // dev servers that open a browser tab on start shouldn't\n for (const [k, v] of Object.entries(extra)) env[k] = fillPlaceholders(v, port, tmp);\n env.PORT = String(port);\n return env;\n}\n\n/** Whether something accepts TCP connections on the port (IPv4 or IPv6 loopback). */\nexport async function portOpen(port: number): Promise<boolean> {\n const probe = (host: string) =>\n new Promise<boolean>((resolve) => {\n const sock = net.connect({ port, host });\n const done = (ok: boolean) => {\n sock.destroy();\n resolve(ok);\n };\n sock.setTimeout(800, () => done(false));\n sock.once('connect', () => done(true));\n sock.once('error', () => done(false));\n });\n const [v4, v6] = await Promise.all([probe('127.0.0.1'), probe('::1')]);\n return v4 || v6;\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nasync function readJson(file: string): Promise<{ scripts?: Record<string, string> } | null> {\n try {\n return JSON.parse(await fs.readFile(file, 'utf8'));\n } catch {\n return null;\n }\n}\n\n/** npm run dev, else start, else preview. Vite ignores PORT, so it is told the port when the script is plain vite. */\nexport function defaultCommand(pkg: { scripts?: Record<string, string> } | null): string | null {\n const scripts = pkg?.scripts ?? {};\n const name = ['dev', 'start', 'preview'].find((s) => typeof scripts[s] === 'string' && scripts[s].trim());\n if (!name) return null;\n const script = scripts[name];\n const vite = /^\\s*vite(\\s|$)/.test(script) && !/--port\\b/.test(script);\n return `npm run ${name}${vite ? ' -- --port {port} --strictPort' : ''}`;\n}\n\nclass Stopped extends Error {}\n\n/** One run of a floor's app, from checkout to a listening port. */\nclass RealPreview implements PreviewHandle {\n private child: ChildProcess | null = null;\n private stopped = false;\n private partial = '';\n\n constructor(\n private job: PreviewJob,\n private cb: PreviewCallbacks,\n ) {\n void this.run().catch((err) => {\n if (this.stopped || err instanceof Stopped) return;\n this.stopped = true;\n if (this.child) void killTree(this.child);\n this.cb.failed((err as Error).message);\n });\n }\n\n async stop() {\n this.stopped = true;\n if (this.child) await killTree(this.child);\n }\n\n private check() {\n if (this.stopped) throw new Stopped();\n }\n\n private async run() {\n const { job, cb } = this;\n cb.status('preparing');\n const wt = await workspace.prepareDesk(job.fullName, { defaultBranch: job.defaultBranch, pr: job.pr ?? undefined }, PREVIEW_SLUG, PREVIEW_BRANCH);\n this.check();\n await workspace.ensureLocalExcludes(job.fullName).catch(() => undefined);\n cb.commit(await git(['rev-parse', '--short', 'HEAD'], { cwd: wt }).catch(() => ''));\n const tmp = path.join(wt, PREVIEW_TMP);\n await fs.mkdir(tmp, { recursive: true });\n\n const pkg = await readJson(path.join(wt, 'package.json'));\n const command = job.command ?? defaultCommand(pkg);\n if (!command) {\n this.stopped = true;\n cb.failed(\n pkg\n ? 'package.json has no dev, start or preview script. Set a preview command for this floor.'\n : 'Nothing to run: this floor has no preview command and no package.json.',\n true,\n );\n return;\n }\n const env = previewEnv(job.env, job.port, tmp);\n\n if (pkg) {\n cb.status('installing');\n await this.install(wt, env);\n this.check();\n }\n\n cb.status('starting');\n const cmd = fillPlaceholders(command, job.port, tmp);\n cb.log([`$ ${cmd}`]);\n const exited = this.spawn(cmd, wt, env);\n const deadline = Date.now() + START_TIMEOUT_MS;\n let exitCode: number | null | undefined;\n void exited.then((code) => (exitCode = code));\n while (!(await portOpen(job.port))) {\n this.check();\n if (exitCode !== undefined) throw new Error(`The app exited (code ${exitCode}) before it listened on port ${job.port}.`);\n if (Date.now() > deadline) throw new Error(`The app did not listen on port ${job.port} within 3 minutes. Does the command use PORT or {port}?`);\n await sleep(700);\n }\n this.check();\n cb.status('running');\n const code = await exited;\n // Some launchers exit while the server they started keeps serving: it's only over once the port closes.\n while (!this.stopped && (await portOpen(job.port))) await sleep(3000);\n if (this.stopped) return;\n this.stopped = true;\n cb.failed(`The app stopped (exit code ${code}).`);\n }\n\n /** npm ci (or npm install without a lockfile), skipped when package.json and the lockfile haven't changed. */\n private async install(wt: string, env: Record<string, string>) {\n const deps = await readDeps(wt);\n if (depsCurrent(deps)) {\n this.cb.log(['Dependencies unchanged since the last install; skipping it.']);\n return;\n }\n const cmd = deps.lock !== null ? 'npm ci' : 'npm install';\n this.cb.log([`$ ${cmd}`]);\n const code = await Promise.race([this.spawn(cmd, wt, env), sleep(INSTALL_TIMEOUT_MS).then(() => 'timeout' as const)]);\n this.check();\n if (code === 'timeout') {\n if (this.child) await killTree(this.child);\n throw new Error(`${cmd} took longer than ${INSTALL_TIMEOUT_MS / 60_000} minutes.`);\n }\n if (code !== 0) throw new Error(`${cmd} failed (code ${code}).`);\n this.child = null;\n await writeMarker(wt, deps.hash);\n }\n\n /** Run a command line through the platform shell; resolves with its exit code. */\n private spawn(cmd: string, cwd: string, env: Record<string, string>): Promise<number | null> {\n this.check();\n const child = spawn(cmd, { cwd, env, shell: true, windowsHide: true, detached: process.platform !== 'win32', stdio: ['ignore', 'pipe', 'pipe'] });\n this.child = child;\n const onData = (buf: Buffer) => {\n const text = this.partial + buf.toString().replace(/\\x1b\\[[0-9;?]*[A-Za-z]/g, '');\n const lines = text.split(/\\r?\\n|\\r/);\n this.partial = lines.pop() ?? '';\n const out = lines.filter((l) => l.trim());\n if (out.length) this.cb.log(out);\n };\n child.stdout?.on('data', onData);\n child.stderr?.on('data', onData);\n return new Promise((resolve) => {\n child.once('error', (err) => {\n this.cb.log([err.message]);\n resolve(-1);\n });\n child.once('close', (code) => {\n if (this.partial.trim()) this.cb.log([this.partial]);\n this.partial = '';\n resolve(code);\n });\n });\n }\n}\n\nexport const realPreviews: PreviewBackend = {\n start: (job, cb) => new RealPreview(job, cb),\n hasDefault: async (fullName) =>\n fs\n .access(path.join(workspace.mainDir(fullName), 'package.json'))\n .then(() => true)\n .catch(() => false),\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { HOME_DIR } from './config.ts';\nimport { git } from './exec.ts';\nimport type { OfficeUpdateState } from '../shared/types.ts';\n\n// The office updating itself (#37). The server only decides when: it drains (starts nothing new, lets running\n// sessions finish) and then hands the update to the launcher (scripts/office.mjs), which pulls, installs, builds and\n// restarts it. Contract with the launcher:\n// server \u2192 launcher { type: 'office:update', from: '<full HEAD sha>' } once drained\n// launcher \u2192 server { type: 'office:shutdown', restart } run shutdown(), then exit 0\n// (restart: false when the office quits; agents' CLIs stop instead of waiting in the keeper)\n// <SWARM_HOME>/last-update.json = { from, to, ok, error?, installed, built, at }, read and deleted on startup\n\n/** Sessions still running this long after draining started are stopped, and the update goes ahead. */\nexport const DRAIN_TIMEOUT_MS = 20 * 60_000;\n/** Later: ask again after this long, or sooner when a newer commit lands. */\nexport const POSTPONE_MS = 2 * 60 * 60_000;\n\n/** Started by the launcher: an IPC channel and SWARM_LAUNCHER=1. Anything else (tsx, the demo, QA) only reports. */\nexport function underLauncher(proc: { send?: unknown; env: Record<string, string | undefined> } = process): boolean {\n return typeof proc.send === 'function' && proc.env.SWARM_LAUNCHER === '1';\n}\n\nexport interface DrainInput {\n now: number;\n behind: number; // commits the office's folder can fast-forward by (0: nothing to update)\n launcher: boolean;\n autoUpdate: boolean;\n requested: boolean; // the manager pressed Update now\n postponedUntil: number | null; // the manager pressed Later\n postponedBehind: number; // how far behind it was then: a newer commit ends the postponement\n failed: string | null; // the last update's error\n failedBehind: number | null; // how far behind it was after that failure: only a newer commit retries on its own\n drainingSince: number | null;\n sent: boolean; // handed to the launcher\n running: number; // sessions still running\n}\n\nexport interface DrainDecision {\n state: OfficeUpdateState;\n drainingSince: number | null;\n /** Hand the update to the launcher now: nothing is running, or the drain timed out (`timedOut`). */\n send: boolean;\n timedOut: boolean;\n}\n\n/**\n * Where the office's own update stands and what to do about it. Draining (start nothing new, let running sessions\n * finish) happens when there is an update, a launcher, and either autoUpdate is on or the manager pressed Update now.\n * Later holds an automatic update back for POSTPONE_MS or until a newer commit lands ('waiting'); a failed update is\n * only retried automatically for a newer commit.\n */\nexport function drainDecision(s: DrainInput): DrainDecision {\n const idle = (state: OfficeUpdateState): DrainDecision => ({ state, drainingSince: null, send: false, timedOut: false });\n if (s.sent) return { state: 'updating', drainingSince: s.drainingSince, send: false, timedOut: false };\n if (s.behind <= 0) return idle('none');\n if (!s.launcher) return idle(s.failed ? 'failed' : 'available');\n const postponed = s.postponedUntil !== null && s.now < s.postponedUntil && s.behind <= s.postponedBehind;\n const failedHold = s.failed !== null && s.behind <= (s.failedBehind ?? Infinity);\n const due = s.requested || (s.autoUpdate && !postponed && !failedHold);\n if (!due) return idle(s.failed ? 'failed' : s.autoUpdate && postponed ? 'waiting' : 'available');\n const since = s.drainingSince ?? s.now;\n const timedOut = s.running > 0 && s.now - since >= DRAIN_TIMEOUT_MS;\n return { state: 'draining', drainingSince: since, send: s.running === 0 || timedOut, timedOut };\n}\n\n/** What the launcher leaves behind after an update. */\nexport interface LastUpdate {\n from: string;\n to: string;\n ok: boolean;\n error?: string;\n installed: boolean;\n built: boolean;\n at: number;\n}\n\n/** Parse last-update.json; null when it isn't one. */\nexport function parseLastUpdate(raw: string): LastUpdate | null {\n try {\n const u = JSON.parse(raw) as Partial<LastUpdate>;\n if (!u || typeof u.from !== 'string' || typeof u.ok !== 'boolean') return null;\n return {\n from: u.from,\n to: typeof u.to === 'string' ? u.to : '',\n ok: u.ok,\n error: typeof u.error === 'string' ? u.error : undefined,\n installed: !!u.installed,\n built: !!u.built,\n at: Number(u.at) || Date.now(),\n };\n } catch {\n return null;\n }\n}\n\n/** Read and delete <home>/last-update.json, so its phone message is posted once. */\nexport async function takeLastUpdate(home: string): Promise<LastUpdate | null> {\n const file = path.join(home, 'last-update.json');\n const raw = await fs.readFile(file, 'utf8').catch(() => null);\n if (raw === null) return null;\n await fs.rm(file, { force: true, maxRetries: 3 }).catch(() => undefined);\n return parseLastUpdate(raw);\n}\n\n/** The phone message for an update: \"Updated the office from abc1234 to def5678 (3 commits)\" or why it failed. */\nexport function lastUpdateMessage(u: LastUpdate, commits: number | null): string {\n if (!u.ok) return `\u26A0\uFE0F Update failed and was rolled back: ${u.error || 'unknown error'}`;\n const n = commits === null ? '' : ` (${commits} commit${commits === 1 ? '' : 's'})`;\n return `\u2B06\uFE0F Updated the office from ${u.from.slice(0, 7)} to ${u.to.slice(0, 7)}${n}`;\n}\n\n// ---------- the running office ----------\n\n/** The running office's own checkout and its launcher. The demo fakes it. */\nexport interface OfficeHost {\n launcher: boolean;\n /** Full sha of the commit the office runs, or null when it doesn't run from a git checkout (e.g. installed from npm). */\n head(): Promise<string | null>;\n /** Is this floor checkout the office's own folder? Syncing it would restart the office mid-work, so it's only reported. */\n isOwnFolder(dir: string): boolean;\n /** Commits between two shas of the office's folder, or null when git can't tell. */\n commitsBetween(from: string, to: string): Promise<number | null>;\n /** Read and delete the result the launcher left from the last update. */\n takeLastUpdate(): Promise<LastUpdate | null>;\n /** Hand the drained office to the launcher, which restarts it (resolves null). The demo resolves with a fake result. */\n update(from: string): Promise<LastUpdate | null>;\n}\n\nconst OFFICE_DIR = path.resolve(import.meta.dirname, '..');\nconst isSamePath = (a: string, b: string) => (process.platform === 'win32' ? path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase() : path.resolve(a) === path.resolve(b));\n\nexport const realOffice: OfficeHost = {\n launcher: underLauncher(),\n head: () => git(['rev-parse', 'HEAD'], { cwd: OFFICE_DIR }).catch(() => null),\n isOwnFolder: (dir) => isSamePath(dir, OFFICE_DIR),\n commitsBetween: (from, to) =>\n git(['rev-list', '--count', `${from}..${to}`], { cwd: OFFICE_DIR })\n .then(Number)\n .catch(() => null),\n takeLastUpdate: () => takeLastUpdate(HOME_DIR),\n async update(from) {\n if (!underLauncher()) throw new Error('The office was not started by the launcher');\n await new Promise<void>((resolve, reject) => process.send!({ type: 'office:update', from }, undefined, {}, (err) => (err ? reject(err) : resolve())));\n return null;\n },\n};\n", "// Phone messages read aloud by ElevenLabs: the manager's key (kept in its own secrets file, never in the state, the\n// snapshot, events or agents' environments), the voice list, and spoken messages cached as mp3 under <SWARM_HOME>/voice.\nimport crypto from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { SAMPLE_LINE, speechText } from '../shared/speech.ts';\nimport type { PhoneMessage, VoiceOption, VoiceSettings } from '../shared/types.ts';\nimport { HttpError } from './httpError.ts';\n\n/** ElevenLabs' fastest, cheapest model (~75 ms, half the price per character of Multilingual v2). */\nexport const DEFAULT_VOICE_MODEL = 'eleven_flash_v2_5';\nexport const VOICES_TTL_MS = 10 * 60_000;\nexport const SYNTH_TIMEOUT_MS = 20_000;\nexport const CACHE_MAX_FILES = 200;\nexport const CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60_000;\nexport const KEY_REJECTED_NOTE = \"\uD83D\uDD07 ElevenLabs rejected the key, so messages aren't read aloud until you set a new one in the voice settings.\";\n\ntype Labels = VoiceOption['labels'];\nconst voice = (id: string, name: string, description: string, accent = ''): VoiceOption => ({\n id,\n name,\n category: 'library',\n labels: { accent, gender: '', age: '', description, use_case: 'conversational' },\n previewUrl: null,\n recommended: true,\n});\n\n/**\n * docs/voice.md's shortlist for a calm, friendly CEO: ElevenLabs' replacements for its Default voices, which expire on\n * 31 December 2026. They're in the Voice Library, usable by id without saving them (paid plans).\n */\nexport const RECOMMENDED_VOICES: VoiceOption[] = [\n voice('OZ0L6eISlOejga3XjDFt', 'Talia', 'warm soft guide'),\n voice('l7kNoIfnJKPg7779LI2t', 'Eddie', 'helpful and comforting'),\n voice('AaOhDHYJ1XLZk74lXhdE', 'Caleb', 'trusted guide'),\n voice('gOupLcAkjEnguROwi4oS', 'Darian', 'warm grounded storyteller'),\n voice('BFd5oBc2DDna33pSi4Gf', 'Alicia', 'polished global anchor'),\n voice('QtY3JBOUKEB5xzrRfOKc', 'Maisie', 'friendly casual neighbor'),\n voice('FrS6cKLB1wg4WYgPa9GW', 'Wyatt', 'seasoned mentor'),\n voice('6WwXjDDEMyNmFG95zycZ', 'Eldrin', 'crisp baritone', 'british'),\n];\n\nexport const DEFAULT_VOICE: VoiceSettings = {\n provider: 'off',\n voiceId: RECOMMENDED_VOICES[0].id,\n voiceName: RECOMMENDED_VOICES[0].name,\n model: DEFAULT_VOICE_MODEL,\n speakOffice: false,\n};\n\nconst VOICE_ID = /^[A-Za-z0-9_-]{1,64}$/;\nconst MODEL_ID = /^[a-z0-9_.-]{1,64}$/;\n\n/** Voice settings from a saved state or a PATCH /api/settings, field by field; anything invalid keeps `base`. */\nexport function voiceSettings(base: VoiceSettings, patch: unknown): VoiceSettings {\n const p = (patch && typeof patch === 'object' ? patch : {}) as Partial<Record<keyof VoiceSettings, unknown>>;\n const out = { ...base };\n if (p.provider === 'off' || p.provider === 'browser' || p.provider === 'elevenlabs') out.provider = p.provider;\n // The browser's voices are named rather than numbered (\"Google UK English Female\"), so any short name goes.\n if (typeof p.voiceId === 'string' && p.voiceId.trim() && p.voiceId.length <= 200) out.voiceId = p.voiceId.trim();\n if (typeof p.voiceName === 'string') out.voiceName = p.voiceName.trim().slice(0, 80);\n if (typeof p.model === 'string' && MODEL_ID.test(p.model.trim())) out.model = p.model.trim();\n if (typeof p.speakOffice === 'boolean') out.speakOffice = p.speakOffice;\n return out;\n}\n\n/** Which cached clips to delete: anything older than `maxAgeMs`, then the oldest beyond `max`. */\nexport function cacheToPrune(files: { name: string; mtimeMs: number }[], now: number, max = CACHE_MAX_FILES, maxAgeMs = CACHE_MAX_AGE_MS): string[] {\n const fresh = files.filter((f) => now - f.mtimeMs <= maxAgeMs).sort((a, b) => b.mtimeMs - a.mtimeMs);\n const keep = new Set(fresh.slice(0, max).map((f) => f.name));\n return files.filter((f) => !keep.has(f.name)).map((f) => f.name);\n}\n\n/** The phone messages that are spoken: the CEO's, and the office's own notes when the manager asked for them. */\nexport function speaks(m: PhoneMessage, s: VoiceSettings): boolean {\n return m.from === 'ceo' || (m.from === 'office' && s.speakOffice);\n}\n\n/** An ElevenLabs call that failed; status 0 when it never answered. */\nexport class VoiceApiError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message);\n }\n}\n\n/** ElevenLabs (server/elevenlabs.ts), or demo.ts's fake. */\nexport interface VoiceApi {\n checkKey(key: string): Promise<void>;\n listVoices(key: string): Promise<Omit<VoiceOption, 'recommended'>[]>;\n synthesize(key: string, req: { voiceId: string; model: string; text: string }, signal: AbortSignal): Promise<Buffer>;\n}\n\nexport interface VoiceKeyView {\n voiceKeySet: boolean;\n voiceKeyHint: string;\n}\n\nexport interface VoiceDeps {\n api: VoiceApi;\n secretsFile: string;\n cacheDir: string;\n settings(): VoiceSettings;\n message(id: number): PhoneMessage | undefined;\n /** Posts an office message on the manager's phone. */\n officeNote(text: string): void;\n keyChanged(view: VoiceKeyView): void;\n now?(): number;\n}\n\ninterface Secrets {\n elevenlabsKey?: string;\n elevenlabsKeyRejected?: boolean;\n}\n\nexport class Voice {\n private key = '';\n private rejected = false; // ElevenLabs said 401: no more calls until the key changes\n private voicesCache: { at: number; list: VoiceOption[] } | null = null;\n private making = new Map<string, Promise<Buffer>>();\n private queue: Promise<unknown> = Promise.resolve();\n private writing: Promise<unknown> = Promise.resolve(); // secrets-file writes, one after another\n\n constructor(private deps: VoiceDeps) {}\n\n async init() {\n const s = await this.readSecrets();\n this.key = typeof s.elevenlabsKey === 'string' ? s.elevenlabsKey : '';\n this.rejected = !!this.key && s.elevenlabsKeyRejected === true;\n await this.prune().catch(() => undefined);\n }\n\n keyView(): VoiceKeyView {\n return { voiceKeySet: !!this.key, voiceKeyHint: this.key.slice(-4) };\n }\n\n /** PUT /api/voice/key: '' removes the key; anything else must pass one cheap ElevenLabs call first. */\n async setKey(raw: string): Promise<VoiceKeyView> {\n const key = raw.trim();\n if (key) {\n if (key.length > 200 || /\\s/.test(key)) throw new HttpError(400, \"That doesn't look like an ElevenLabs API key.\");\n try {\n await this.deps.api.checkKey(key);\n } catch (err) {\n if (err instanceof VoiceApiError && err.status === 401) throw new HttpError(400, 'ElevenLabs rejected that key. Copy it again from elevenlabs.io \u2192 Developers \u2192 API Keys.');\n if (err instanceof VoiceApiError && err.status === 403) throw new HttpError(400, 'That key may not read voices. Give it the Voices (read) and Text to Speech permissions on elevenlabs.io.');\n throw new HttpError(502, `Couldn't check the key with ElevenLabs: ${(err as Error).message}`);\n }\n }\n this.key = key;\n this.rejected = false;\n this.voicesCache = null;\n await this.writeSecrets({ elevenlabsKey: key || undefined, elevenlabsKeyRejected: undefined });\n const view = this.keyView();\n this.deps.keyChanged(view);\n return view;\n }\n\n /** GET /api/voice/voices: the account's voices plus the shortlist, shortlist first. Cached for 10 minutes. */\n async voices(): Promise<VoiceOption[]> {\n this.requireKey();\n const now = this.now();\n if (this.voicesCache && now - this.voicesCache.at < VOICES_TTL_MS) return this.voicesCache.list;\n const key = this.key;\n const mine = await this.deps.api.listVoices(key).catch((err) => this.failed(err, key, 'list the voices'));\n const recommended = new Map(RECOMMENDED_VOICES.map((v) => [v.id, v]));\n const list: VoiceOption[] = [\n ...RECOMMENDED_VOICES.map((r) => {\n const own = mine.find((v) => v.id === r.id);\n return own ? { ...own, labels: fill(own.labels, r.labels), recommended: true } : r;\n }),\n ...mine.filter((v) => !recommended.has(v.id)).map((v) => ({ ...v, recommended: false })).sort((a, b) => a.name.localeCompare(b.name)),\n ];\n if (this.key === key) this.voicesCache = { at: now, list };\n return list;\n }\n\n /** GET /api/voice/messages/:id: a phone message as mp3, made once and cached. */\n async messageAudio(id: number): Promise<Buffer> {\n const s = this.deps.settings();\n if (s.provider !== 'elevenlabs') throw new HttpError(404, \"Messages aren't read by ElevenLabs right now.\");\n const m = this.deps.message(id);\n if (!m || !speaks(m, s)) throw new HttpError(404, `No spoken message ${id}`);\n const text = speechText(m.text);\n if (!text) throw new HttpError(404, `Message ${id} has nothing to say aloud`);\n return this.audio(String(m.id), s.voiceId, s.model, text);\n }\n\n /** GET /api/voice/sample: the settings' Test button, in `voiceId` (default: the chosen voice). */\n async sampleAudio(voiceId?: string): Promise<Buffer> {\n const s = this.deps.settings();\n return this.audio('sample', voiceId || s.voiceId, s.model, SAMPLE_LINE);\n }\n\n private async audio(name: string, voiceId: string, model: string, text: string): Promise<Buffer> {\n if (!VOICE_ID.test(voiceId)) throw new HttpError(400, 'Pick an ElevenLabs voice first.');\n // The voice, model and words are in the file name, so a new voice or a reused message id never plays stale audio.\n const hash = crypto.createHash('sha256').update(`${voiceId}\\n${model}\\n${text}`).digest('hex').slice(0, 12);\n const file = path.join(this.deps.cacheDir, `${name}-${hash}.mp3`);\n const cached = await fs.readFile(file).catch(() => null);\n if (cached) return cached;\n this.requireKey();\n const busy = this.making.get(file);\n if (busy) return busy;\n const made = this.oneAtATime(() => this.synthesize(file, { voiceId, model, text })).finally(() => this.making.delete(file));\n this.making.set(file, made);\n return made;\n }\n\n private oneAtATime<T>(fn: () => Promise<T>): Promise<T> {\n const run = this.queue.then(fn, fn);\n this.queue = run.catch(() => undefined);\n return run;\n }\n\n private async synthesize(file: string, req: { voiceId: string; model: string; text: string }): Promise<Buffer> {\n this.requireKey(); // the key may have been rejected or removed while this waited its turn\n const key = this.key;\n const audio = await this.deps.api.synthesize(key, req, AbortSignal.timeout(SYNTH_TIMEOUT_MS)).catch((err) => this.failed(err, key, 'speak the message'));\n await fs.mkdir(this.deps.cacheDir, { recursive: true });\n const tmp = `${file}.${process.pid}.tmp`;\n await fs.writeFile(tmp, audio);\n await fs.rename(tmp, file);\n await this.prune().catch(() => undefined);\n return audio;\n }\n\n /** An ElevenLabs failure as a short 502. A 401 also stops every call until the key changes, and says so once. */\n private async failed(err: unknown, key: string, what: string): Promise<never> {\n if (err instanceof VoiceApiError && err.status === 401 && key === this.key && !this.rejected) {\n this.rejected = true;\n this.deps.officeNote(KEY_REJECTED_NOTE);\n await this.writeSecrets({ elevenlabsKeyRejected: true }).catch(() => undefined);\n }\n if (err instanceof VoiceApiError && err.status === 401) throw new HttpError(502, 'ElevenLabs rejected the key.');\n throw new HttpError(502, `ElevenLabs couldn't ${what}: ${(err as Error).message}`.slice(0, 240));\n }\n\n private requireKey() {\n if (!this.key) throw new HttpError(409, 'Add an ElevenLabs API key first.');\n if (this.rejected) throw new HttpError(502, 'ElevenLabs rejected the key. Set a new one in the voice settings.');\n }\n\n private async prune() {\n const names = (await fs.readdir(this.deps.cacheDir).catch(() => [] as string[])).filter((n) => n.endsWith('.mp3'));\n const files = await Promise.all(names.map(async (name) => ({ name, mtimeMs: (await fs.stat(path.join(this.deps.cacheDir, name)).catch(() => null))?.mtimeMs ?? 0 })));\n for (const name of cacheToPrune(files, this.now())) await fs.rm(path.join(this.deps.cacheDir, name), { force: true, maxRetries: 3 });\n }\n\n private now() {\n return this.deps.now?.() ?? Date.now();\n }\n\n private async readSecrets(): Promise<Secrets & Record<string, unknown>> {\n try {\n const s = JSON.parse(await fs.readFile(this.deps.secretsFile, 'utf8')) as unknown;\n return s && typeof s === 'object' ? (s as Secrets & Record<string, unknown>) : {};\n } catch {\n return {};\n }\n }\n\n /** Merge into the secrets file (other secrets stay), owner-only where the OS has file modes. */\n private writeSecrets(patch: Secrets): Promise<void> {\n const write = this.writing.then(() => this.mergeSecrets(patch));\n this.writing = write.catch(() => undefined);\n return write;\n }\n\n private async mergeSecrets(patch: Secrets) {\n const next: Record<string, unknown> = { ...(await this.readSecrets()), ...patch };\n for (const k of Object.keys(next)) if (next[k] === undefined) delete next[k];\n await fs.mkdir(path.dirname(this.deps.secretsFile), { recursive: true });\n const tmp = `${this.deps.secretsFile}.tmp`;\n await fs.writeFile(tmp, JSON.stringify(next, null, 2), { mode: 0o600 });\n await fs.rename(tmp, this.deps.secretsFile);\n await fs.chmod(this.deps.secretsFile, 0o600).catch(() => undefined);\n }\n}\n\n/** The account's labels, with the shortlist's description where ElevenLabs has none. */\nfunction fill(own: Labels, ours: Labels): Labels {\n return { ...own, description: own.description || ours.description };\n}\n", "// What a phone message sounds like read aloud: markdown and emoji out, issue numbers and links said the way a person\n// would. Used by the server's ElevenLabs voice and by the browser's own voice, so both read the same words.\n\n/** About how much of a message is spoken; the cut lands on a sentence end. */\nexport const SPEECH_MAX_CHARS = 1500;\n\n/** What the settings' Test button says, in ElevenLabs' voice or the browser's. */\nexport const SAMPLE_LINE = \"Hi! This is how I'll sound when I message you from the office.\";\n\nconst EMOJI = /[\\p{Extended_Pictographic}\\p{Regional_Indicator}\\u{1F3FB}-\\u{1F3FF}\u200D\uFE0E\uFE0F\u20E3]/gu;\nconst URL = /\\b(?:https?:\\/\\/|www\\.)[^\\s<>()]+[^\\s<>().,;:!?'\"]/gi;\n\n/** The words to speak for a message: plain sentences, at most about `max` characters. */\nexport function speechText(text: string, max = SPEECH_MAX_CHARS): string {\n let s = text.replace(/\\r\\n?/g, '\\n');\n s = s.replace(/```[\\s\\S]*?(```|$)/g, '\\n'); // code blocks aren't worth hearing\n s = s.replace(/`([^`\\n]*)`/g, '$1');\n s = s.replace(/!\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1');\n s = s.replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1');\n s = s.replace(/<(https?:[^>\\s]+)>/g, '$1');\n s = s.replace(/<\\/?[a-z][^>]*>/gi, '');\n s = s.replace(URL, 'a link');\n s = s.replace(EMOJI, '');\n s = s.replace(/(\\*\\*|__)(.+?)\\1/g, '$2');\n s = s.replace(/(^|[^\\w*])\\*(?!\\s)([^*\\n]+?)\\*(?!\\w)/g, '$1$2');\n s = s.replace(/(^|[^\\w])_(?!\\s)([^_\\n]+?)_(?!\\w)/g, '$1$2');\n s = s.replace(/~~(.+?)~~/g, '$1');\n s = s.replace(/#(\\d+)\\b/g, 'number $1');\n\n const lines: string[] = [];\n for (let line of s.split('\\n')) {\n line = line\n .replace(/^\\s*#{1,6}\\s+/, '') // headings\n .replace(/^\\s*>+\\s?/, '') // quotes\n .replace(/^\\s*[-*+\u2022]\\s+/, '') // bullets\n .replace(/^\\s*\\|?\\s*:?-{3,}:?\\s*(\\|\\s*:?-{3,}:?\\s*)*\\|?\\s*$/, '') // table rules\n .replace(/^\\s*([-*_]\\s*){3,}$/, '') // horizontal rules\n .replace(/\\s*\\|\\s*/g, ', ')\n .replace(/^[,\\s]+|[,\\s]+$/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n if (!line) continue;\n // A line without its own punctuation (a list item, a heading) still gets a pause.\n lines.push(/[.!?:;,\u2026]$/.test(line) ? line : `${line}.`);\n }\n return cut(lines.join(' ').replace(/\\s+([.,!?;:])/g, '$1'), max);\n}\n\n/** Cut at the last sentence end within `max`; with none in its second half, at the last word, with an ellipsis. */\nfunction cut(s: string, max: number): string {\n if (s.length <= max) return s;\n const head = s.slice(0, max + 1);\n const ends = [...head.matchAll(/[.!?\u2026](?=\\s|$)/g)];\n const end = ends.length ? ends[ends.length - 1].index + 1 : -1;\n if (end >= max / 2) return s.slice(0, end);\n const space = s.lastIndexOf(' ', max);\n return `${s.slice(0, space > 0 ? space : max).replace(/[,;:\\s]+$/, '')}\u2026`;\n}\n", "/** An error the REST layer turns into this status with a JSON { error } body. */\nexport class HttpError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message);\n }\n}\n", "// ElevenLabs' REST API through Node's fetch: checking a key, listing the account's voices, speaking a message.\n// The key travels only in the xi-api-key header; error messages are ElevenLabs' own words, never the key.\nimport type { VoiceOption } from '../shared/types.ts';\nimport { VoiceApiError, type VoiceApi } from './voice.ts';\n\nconst API = 'https://api.elevenlabs.io';\nconst CHECK_TIMEOUT_MS = 10_000;\nconst MAX_VOICE_PAGES = 5; // 100 voices a page\n\nasync function call(key: string, pathname: string, init: RequestInit, signal: AbortSignal): Promise<Response> {\n let res: Response;\n try {\n res = await fetch(`${API}${pathname}`, { ...init, signal, headers: { ...init.headers, 'xi-api-key': key } });\n } catch (err) {\n throw new VoiceApiError(0, signal.aborted ? 'it took too long to answer' : `it couldn't be reached (${(err as Error).message})`);\n }\n if (!res.ok) throw new VoiceApiError(res.status, await reason(res));\n return res;\n}\n\n/** ElevenLabs' errors carry `detail` as a string, as { message, status }, or as a list of validation errors. */\nasync function reason(res: Response): Promise<string> {\n const body = await res.text().catch(() => '');\n let text = '';\n try {\n const d = (JSON.parse(body) as { detail?: unknown }).detail;\n if (typeof d === 'string') text = d;\n else if (Array.isArray(d)) text = d.map((x) => (x as { msg?: unknown })?.msg).filter(Boolean).join('; ');\n else if (d && typeof d === 'object') text = String((d as { message?: unknown }).message ?? (d as { status?: unknown }).status ?? '');\n } catch {\n // not JSON\n }\n return `${res.status}${text ? `: ${text}` : ''}`.slice(0, 200);\n}\n\nconst s = (v: unknown) => (typeof v === 'string' ? v : '');\n\ninterface ApiVoice {\n voice_id?: unknown;\n name?: unknown;\n category?: unknown;\n labels?: Record<string, unknown> | null;\n preview_url?: unknown;\n}\n\nfunction voiceOption(v: ApiVoice): Omit<VoiceOption, 'recommended'> {\n const l = v.labels ?? {};\n return {\n id: s(v.voice_id),\n name: s(v.name),\n category: s(v.category),\n labels: { accent: s(l.accent), gender: s(l.gender), age: s(l.age), description: s(l.description) || s(l.descriptive), use_case: s(l.use_case) || s(l['use case']) },\n previewUrl: s(v.preview_url) || null,\n };\n}\n\nexport const elevenLabs: VoiceApi = {\n // The cheapest call a voices-reading key can make: one voice.\n async checkKey(key) {\n await call(key, '/v2/voices?page_size=1&include_total_count=false', {}, AbortSignal.timeout(CHECK_TIMEOUT_MS));\n },\n\n async listVoices(key) {\n const out: Omit<VoiceOption, 'recommended'>[] = [];\n let token = '';\n for (let page = 0; page < MAX_VOICE_PAGES; page++) {\n const q = new URLSearchParams({ page_size: '100', include_total_count: 'false', ...(token ? { next_page_token: token } : {}) });\n const res = await call(key, `/v2/voices?${q}`, {}, AbortSignal.timeout(CHECK_TIMEOUT_MS));\n const body = (await res.json()) as { voices?: ApiVoice[]; has_more?: boolean; next_page_token?: string | null };\n for (const v of body.voices ?? []) if (s(v.voice_id)) out.push(voiceOption(v));\n token = s(body.next_page_token);\n if (!body.has_more || !token) break;\n }\n return out;\n },\n\n async synthesize(key, { voiceId, model, text }, signal) {\n const res = await call(\n key,\n `/v1/text-to-speech/${encodeURIComponent(voiceId)}?output_format=mp3_44100_128`,\n { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'audio/mpeg' }, body: JSON.stringify({ text, model_id: model }) },\n signal,\n );\n return Buffer.from(await res.arrayBuffer());\n },\n};\n", "import * as github from './github.ts';\nimport * as workspace from './workspace.ts';\nimport { startSession, type SessionCallbacks, type SessionHandle, type SessionOptions } from './agentRunner.ts';\nimport { hooksReady, officeProcesses, reconnectClis, releaseClis, startCliSession, terminalsAvailable, type ReconnectedCli } from './cliRunner.ts';\nimport { detectClis } from './clis.ts';\nimport { installDesk, type DepsCallbacks, type DepsOutcome } from './deps.ts';\nimport { realPreviews, type PreviewBackend } from './previewRunner.ts';\nimport { realOffice, type OfficeHost } from './officeUpdate.ts';\nimport { elevenLabs } from './elevenlabs.ts';\nimport type { VoiceApi } from './voice.ts';\nimport type { AgentTerminal } from './terminal.ts';\nimport type { CliView, GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\n\n/** Everything the swarm needs from the outside world. The demo backend fakes all of it. */\nexport interface Backend {\n demo: boolean;\n user(): Promise<string>;\n listMyRepos(owner?: string): Promise<GhRepoSummary[]>;\n repoMeta(fullName: string): Promise<github.RepoMeta>;\n listIssues(fullName: string): Promise<IssueInfo[]>;\n listPulls(fullName: string): Promise<PullInfo[]>;\n createIssue(fullName: string, title: string, body: string, labels?: string[]): Promise<number>;\n /** OPEN or CLOSED; null when there is no such issue. */\n issueState(fullName: string, number: number): Promise<'OPEN' | 'CLOSED' | null>;\n editIssue(fullName: string, number: number, edit: { body?: string; addLabels?: string[]; removeLabels?: string[] }): Promise<void>;\n /** Close an issue as completed, with a comment. */\n closeIssue(fullName: string, number: number, comment: string): Promise<void>;\n mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void>;\n updateBranch(fullName: string, number: number): Promise<void>;\n closePull(fullName: string, number: number): Promise<void>;\n prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null>;\n prDetails(fullName: string, number: number): Promise<github.PrDetails>;\n issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }>;\n commentPull(fullName: string, number: number, body: string): Promise<string>;\n uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string>;\n ensureClone(fullName: string): Promise<void>;\n /** Fast-forward the floor's main checkout to GitHub when that is safe; returns how it stands. */\n syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<workspace.MainSync | null>;\n /** Point a floor at the user's own project folder (null: a clone the office manages). */\n setLocalPath(fullName: string, dir: string | null): void;\n scanProjects(root: string): Promise<workspace.LocalFolder[]>;\n inspectFolder(dir: string): Promise<workspace.LocalFolder>;\n publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string>;\n createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<{ fullName: string; path: string }>;\n mainDir(fullName: string): string;\n deskDir(fullName: string, agentSlug: string): string;\n /** `note` hears why the desk couldn't be reused in place, when it has to be rebuilt. */\n prepareDesk(fullName: string, base: workspace.DeskBase, agentSlug: string, branch: string, note?: (text: string) => void): Promise<string>;\n /** npm ci in a prepared desk unless nothing changed since the last one; never throws (see deps.ts installDesk). */\n installDeps(dir: string, cb: DepsCallbacks): Promise<DepsOutcome>;\n /** `main`: the floor's checkout as it was when the desk was let go (default: mainDir now). */\n removeDesk(fullName: string, agentSlug: string, main?: string): Promise<void>;\n /** Remove desks, stray desk folders and finished swarm/qa branches nothing in `keep` uses. */\n sweepDesks(fullName: string, keep: workspace.SweepKeep): Promise<workspace.SweepResult>;\n /** Stop processes an agent left running (dev servers on its port, anything started in its desk). */\n releaseDesk(fullName: string, agentSlug: string, port: number): Promise<void>;\n /** An agent session: the real CLI in the agent's terminal when opts.terminal is set, else an Agent SDK session. */\n startSession(opts: SessionOptions, cb: SessionCallbacks): SessionHandle;\n /** Terminals can run here (the native pseudo-terminal module loaded). */\n terminals: boolean;\n /** The office started: the CLIs its terminal keeper kept running through a restart, back in their agents' terminals. */\n reconnectClis(terminalFor: (agentId: string) => AgentTerminal | null): Promise<ReconnectedCli[]>;\n /** The office follows those CLIs' sessions again: hooks that waited for it can come in. */\n hooksReady(): void;\n /** The office is stopping: its CLIs carry on in the keeper through a restart (true), or stop with it. */\n releaseClis(restart: boolean): Promise<void>;\n /** The coding-agent CLIs installed on this machine. */\n detectClis(): Promise<CliView[]>;\n /** Run a floor's app for the preview monitor (its own worktree, its own port). */\n previews: PreviewBackend;\n /** The running office's own folder and its launcher, for the office's self-update. */\n office: OfficeHost;\n /** Text to speech for the manager's phone (ElevenLabs). */\n voice: VoiceApi;\n}\n\nexport const realBackend: Backend = {\n demo: false,\n user: github.currentUser,\n listMyRepos: github.listMyRepos,\n repoMeta: github.repoMeta,\n listIssues: github.listIssues,\n listPulls: github.listPulls,\n createIssue: github.createIssue,\n issueState: github.issueState,\n editIssue: github.editIssue,\n closeIssue: github.closeIssue,\n mergePull: github.mergePull,\n updateBranch: github.updateBranch,\n closePull: github.closePull,\n prForBranch: github.prForBranch,\n prDetails: github.prDetails,\n issueDetails: github.issueDetails,\n commentPull: github.commentPull,\n uploadEvidence: github.uploadEvidence,\n ensureClone: workspace.ensureClone,\n syncMain: workspace.syncMain,\n setLocalPath: workspace.setLocalPath,\n scanProjects: workspace.scanProjects,\n inspectFolder: workspace.inspectFolder,\n publishFolder: workspace.publishFolder,\n createProject: workspace.createProject,\n mainDir: workspace.mainDir,\n deskDir: workspace.deskDir,\n prepareDesk: workspace.prepareDesk,\n installDeps: (dir, cb) => installDesk(dir, cb),\n removeDesk: workspace.removeDesk,\n sweepDesks: workspace.sweepDesks,\n releaseDesk: (fullName, agentSlug, port) => workspace.releaseDesk(fullName, agentSlug, port, officeProcesses()),\n startSession: (opts, cb) => (opts.terminal ? startCliSession(opts, cb) : startSession(opts, cb)),\n terminals: terminalsAvailable,\n reconnectClis: (terminalFor) => (terminalsAvailable ? reconnectClis(terminalFor) : Promise.resolve([])),\n hooksReady,\n releaseClis,\n detectClis,\n previews: realPreviews,\n office: realOffice,\n voice: elevenLabs,\n};\n", "import crypto from 'node:crypto';\nimport http from 'node:http';\nimport path from 'node:path';\nimport type { Backend } from './backend.ts';\nimport type { PreviewBackend } from './previewRunner.ts';\nimport { describeOfficeTool, type LogEntry, type SessionCallbacks, type SessionHandle, type SessionOptions } from './agentRunner.ts';\nimport { CLIS } from './clis.ts';\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\nimport type { LocalFolder } from './workspace.ts';\nimport { HOME_DIR } from './config.ts';\nimport { takeLastUpdate, underLauncher, type OfficeHost } from './officeUpdate.ts';\nimport { VoiceApiError, type VoiceApi } from './voice.ts';\n\n// `npm run demo`: a fake GitHub and fake Claude Code sessions, so the office (including the\n// dev \u2192 QA \u2192 fix loop) can be explored without spending any usage or touching real repos.\n\ninterface FakeRepo {\n fullName: string;\n description: string;\n issues: IssueInfo[];\n pulls: PullInfo[];\n nextNumber: number;\n}\n\nconst now = () => new Date().toISOString();\n\nfunction issue(n: number, title: string, body: string, fullName: string, labels: string[] = []): IssueInfo {\n return { number: n, title, body, url: `https://github.com/${fullName}/issues/${n}`, labels, createdAt: now() };\n}\n\nconst repos = new Map<string, FakeRepo>();\n/** Repos made in the demo (new projects, published folders): empty, so no package.json for the preview to fall back on. */\nconst bareRepos = new Set<string>();\nconst mergedSinceSync = new Map<string, number>(); // merges the fake project folder hasn't pulled yet\nconst closedIssues = new Set<string>(); // `${fullName}#${n}`: issues closed by a merge\n\nconst fakeSha = () => crypto.randomBytes(20).toString('hex');\n\n/** Fake CI: checks run for a while after every push, and now and then one fails so the fix loop shows. */\nfunction runChecks(pr: PullInfo, fail = Math.random() < 0.2) {\n Object.assign(pr, { checks: 'pending', pendingChecks: ['CI / build', 'Vercel'], failedChecks: [] });\n setTimeout(() => {\n Object.assign(pr, {\n checks: fail ? 'failing' : 'passing',\n pendingChecks: [],\n failedChecks: fail ? [{ name: 'CI / build', url: `${pr.url}/checks` }] : [],\n });\n }, 12_000 + Math.random() * 10_000);\n}\n\nfunction seed(fullName: string, description: string, titles: [string, string][]) {\n const r: FakeRepo = { fullName, description, issues: [], pulls: [], nextNumber: 1 };\n for (const [title, body] of titles) r.issues.push(issue(r.nextNumber++, title, body, fullName));\n repos.set(fullName, r);\n}\n\nseed('demo-co/pixel-todo', 'A cheerful todo app', [\n ['Add dark mode toggle', 'Users want a dark theme. Persist the choice in localStorage.'],\n ['Todos should support due dates', 'Add an optional due date and highlight overdue items.'],\n ['Drag and drop to reorder', 'Let users reorder todos by dragging.'],\n ['Empty state illustration', 'Show a friendly illustration when the list is empty.'],\n ['Keyboard shortcuts', 'N for new todo, / to search, ? for help.'],\n ['Fix: completed count off by one', 'The footer shows one more completed item than there is.'],\n]);\nseed('demo-co/weather-api', 'Tiny weather REST API', [\n ['Add /forecast endpoint', 'Return a 5-day forecast for a city.'],\n ['Rate limit anonymous callers', '60 requests per minute per IP.'],\n ['OpenAPI spec', 'Publish an OpenAPI 3.1 document at /openapi.json.'],\n]);\n\nfunction screenshotSvg(title: string, url: string, hue: number) {\n const safe = (s: string) => s.replace(/[<>&\"]/g, '');\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"640\" height=\"400\" viewBox=\"0 0 640 400\">\n <rect width=\"640\" height=\"400\" fill=\"hsl(${hue},60%,97%)\"/>\n <rect width=\"640\" height=\"56\" fill=\"hsl(${hue},70%,55%)\"/>\n <text x=\"24\" y=\"37\" font-family=\"Segoe UI, Arial\" font-size=\"22\" font-weight=\"700\" fill=\"#fff\">${safe(title)}</text>\n <text x=\"620\" y=\"36\" text-anchor=\"end\" font-family=\"Segoe UI, Arial\" font-size=\"13\" fill=\"#fff\">${safe(url)}</text>\n ${[0, 1, 2, 3]\n .map(\n (i) => `<rect x=\"24\" y=\"${84 + i * 70}\" width=\"592\" height=\"56\" rx=\"10\" fill=\"#fff\" stroke=\"hsl(${hue},40%,85%)\"/>\n <circle cx=\"54\" cy=\"${112 + i * 70}\" r=\"11\" fill=\"none\" stroke=\"hsl(${hue},60%,55%)\" stroke-width=\"3\"/>\n <rect x=\"80\" y=\"${104 + i * 70}\" width=\"${180 + ((i * 97) % 220)}\" height=\"14\" rx=\"7\" fill=\"hsl(${hue},25%,80%)\"/>`,\n )\n .join('\\n')}\n</svg>`;\n}\n\ntype Step = LogEntry[] | (() => void);\n\nfunction devScript(opts: SessionOptions, cb: SessionCallbacks, issueNumber: number, issueTitle: string): Step[] {\n const branch = path.basename(opts.cwd);\n const hue = (issueNumber * 67) % 360;\n const file = ['src/App.tsx', 'src/components/TodoList.tsx', 'src/api/routes.ts', 'src/styles.css'][issueNumber % 4];\n const port = 5200 + (issueNumber % 50);\n return [\n [{ kind: 'text', text: `\u25CF I'll start by getting familiar with the codebase for \"${issueTitle}\".` }],\n [{ kind: 'tool', tool: 'Glob', text: '\u23FA Glob src/**/*.{ts,tsx}' }, { kind: 'result', text: ' \u23BF Found 23 files' }],\n [{ kind: 'tool', tool: 'Read', text: `\u23FA Read ${file}` }, { kind: 'result', text: ' \u23BF Read 184 lines' }],\n [{ kind: 'thinking', text: '\u273B Thinking\u2026' }],\n [\n { kind: 'tool', tool: 'TodoWrite', text: '\u23FA Update todo list' },\n { kind: 'result', text: ' \u25D0 Understand current behaviour' },\n { kind: 'result', text: ' \u2610 Implement the change' },\n { kind: 'result', text: ' \u2610 Add tests' },\n { kind: 'result', text: ' \u2610 Verify in the browser' },\n ],\n [{ kind: 'tool', tool: 'Grep', text: '\u23FA Grep \"useTodos\"' }, { kind: 'result', text: ' \u23BF Found 6 matches in 4 files' }],\n [{ kind: 'text', text: \"\u25CF The state lives in a single hook. I'll extend it and keep the API backwards compatible.\" }],\n [{ kind: 'tool', tool: 'Edit', text: `\u23FA Edit ${file}` }, { kind: 'result', text: ' \u23BF Updated' }],\n [{ kind: 'tool', tool: 'Write', text: '\u23FA Write src/__tests__/feature.test.ts' }, { kind: 'result', text: ' \u23BF Saved' }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm test -- --run' }],\n [\n { kind: 'result', text: ' \u23BF \u2713 src/__tests__/feature.test.ts (4 tests) 38ms' },\n { kind: 'result', text: ' Test Files 7 passed (7)' },\n ],\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ npm run dev -- --port ${port} &` }, { kind: 'result', text: ' \u23BF VITE ready in 412 ms' }],\n () => cb.browserUrl(`http://localhost:${port}/`),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_navigate', text: `\u23FA \uD83C\uDF10 navigate http://localhost:${port}/` }, { kind: 'result', text: ` \u23BF Page URL: http://localhost:${port}/` }],\n () => cb.screenshot(Buffer.from(screenshotSvg(issueTitle, `localhost:${port}`, hue)), 'image/svg+xml'),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_take_screenshot', text: '\u23FA \uD83C\uDF10 take_screenshot' }, { kind: 'result', text: ' \u23BF Took a screenshot of the current page' }],\n [{ kind: 'text', text: '\u25CF Looks right in the browser. Committing and opening a PR.' }],\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ git commit -am \"feat: ${issueTitle.toLowerCase()}\"` }, { kind: 'result', text: ` \u23BF [${branch} 3f2a91c] feat: ${issueTitle.toLowerCase()}` }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git push -u origin HEAD' }, { kind: 'result', text: ' \u23BF branch set up to track origin' }],\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ gh pr create --title \"${issueTitle}\" --body \"Closes #${issueNumber}\"` }],\n ];\n}\n\nfunction qaScript(cb: SessionCallbacks, pr: number, title: string, round: number, checks: string): Step[] {\n const port = 5600 + (pr % 50);\n const hue = (pr * 41) % 360;\n // With GitHub checks on the PR, QA reads what they cover instead of re-running the suite.\n const verify: Step[] = checks.endsWith(': none')\n ? [\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm ci && npm test -- --run' }],\n [\n { kind: 'result', text: ' \u23BF Test Files 8 passed (8)' },\n { kind: 'result', text: ' Tests 41 passed (41)' },\n ],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm run lint && npm run build' }, { kind: 'result', text: ' \u23BF \u2713 built in 1.84s' }],\n ]\n : [\n [{ kind: 'tool', tool: 'Read', text: '\u23FA Read .github/workflows/ci.yml' }, { kind: 'result', text: ' \u23BF Read 41 lines' }],\n [{ kind: 'text', text: '\u25CF CI already runs the tests, lint and build, so I only need a build to start the app.' }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm ci && npm run build' }, { kind: 'result', text: ' \u23BF \u2713 built in 1.84s' }],\n ];\n return [\n [{ kind: 'text', text: `\u25CF Testing PR #${pr} \"${title}\" (round ${round}). ${checks}. First, the acceptance criteria from the issue.` }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git diff origin/main...HEAD --stat' }, { kind: 'result', text: ' \u23BF 3 files changed, 82 insertions(+), 9 deletions(-)' }],\n ...verify,\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ npm run preview -- --port ${port} &` }, { kind: 'result', text: ` \u23BF Local: http://localhost:${port}/` }],\n () => cb.browserUrl(`http://localhost:${port}/`),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_navigate', text: `\u23FA \uD83C\uDF10 navigate http://localhost:${port}/` }, { kind: 'result', text: ` \u23BF Page URL: http://localhost:${port}/` }],\n () => cb.screenshot(Buffer.from(screenshotSvg(`QA \u00B7 ${title}`, `localhost:${port}`, hue)), 'image/svg+xml'),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_take_screenshot', text: '\u23FA \uD83C\uDF10 take_screenshot' }, { kind: 'result', text: ' \u23BF Took a screenshot of the current page' }],\n [{ kind: 'tool', tool: 'mcp__playwright__browser_click', text: '\u23FA \uD83C\uDF10 click \"Add todo\" button' }, { kind: 'result', text: ' \u23BF Clicked' }],\n [{ kind: 'tool', tool: 'mcp__playwright__browser_resize', text: '\u23FA \uD83C\uDF10 resize 375x740' }, { kind: 'result', text: ' \u23BF Resized' }],\n () => cb.screenshot(Buffer.from(screenshotSvg(`QA \u00B7 mobile \u00B7 ${title}`, `localhost:${port}`, (hue + 40) % 360)), 'image/svg+xml'),\n [{ kind: 'tool', tool: 'mcp__playwright__browser_take_screenshot', text: '\u23FA \uD83C\uDF10 take_screenshot' }, { kind: 'result', text: ' \u23BF Took a screenshot of the current page' }],\n [{ kind: 'tool', tool: 'mcp__playwright__browser_console_messages', text: '\u23FA \uD83C\uDF10 console_messages' }, { kind: 'result', text: ' \u23BF No errors' }],\n ];\n}\n\nfunction fixScript(pr: number, pushes: boolean): Step[] {\n return [\n [{ kind: 'text', text: `\u25CF Reading the QA report for PR #${pr}. The toolbar overflows on phones; I'll let it wrap.` }],\n [{ kind: 'tool', tool: 'Read', text: '\u23FA Read src/styles.css' }, { kind: 'result', text: ' \u23BF Read 212 lines' }],\n [{ kind: 'tool', tool: 'Edit', text: '\u23FA Edit src/styles.css' }, { kind: 'result', text: ' \u23BF Updated' }],\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm test -- --run' }, { kind: 'result', text: ' \u23BF Test Files 8 passed (8)' }],\n pushes\n ? [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git commit -am \"fix: wrap toolbar on narrow screens\" && git push origin HEAD' }, { kind: 'result', text: ' \u23BF pushed' }]\n : [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git status --short' }, { kind: 'result', text: ' \u23BF M src/styles.css' }],\n ];\n}\n\nfunction fakeSession(opts: SessionOptions, cb: SessionCallbacks, fullName: string): SessionHandle {\n const timers: NodeJS.Timeout[] = [];\n let stopped = false;\n const kind = opts.role === 'qa' ? 'qa' : /FAILED|taking over pull request|git push origin HEAD:/.test(opts.prompt) ? 'fix' : 'issue';\n const prMatch = opts.prompt.match(/pull request #(\\d+)(?::\\s*(.+))?/);\n const issueMatch = opts.prompt.match(/#(\\d+):\\s*(.+)/);\n const number = Number((kind === 'issue' ? issueMatch?.[1] : prMatch?.[1]) ?? 0);\n const title = (kind === 'issue' ? issueMatch?.[2] : prMatch?.[2])?.trim() ?? 'follow-up';\n const round = Number(opts.prompt.match(/QA round (\\d+)/)?.[1] ?? 1);\n // Now and then a QA fix ends without pushing, so the office's \"no new commits\" check can be seen.\n const pushes = kind !== 'fix' || !/FAILED|taking over pull request/.test(opts.prompt) || Math.random() > 0.25;\n\n const header: Step = [\n { kind: 'system', text: `\u273B Claude Code (demo) \u00B7 ${opts.model} \u00B7 ${opts.effort} effort` },\n { kind: 'system', text: ` cwd ${opts.cwd}` },\n ];\n const checks = opts.prompt.match(/^GitHub checks right now: .*$/m)?.[0] ?? 'GitHub checks right now: none';\n const body = kind === 'qa' ? qaScript(cb, number, title, round, checks) : kind === 'fix' ? fixScript(number, pushes) : devScript(opts, cb, number, title);\n const script = [header, ...body];\n\n const finish = () => {\n const costUsd = 0.3 + Math.random();\n const turns = 15 + Math.floor(Math.random() * 20);\n cb.tool(null);\n if (kind === 'qa') {\n // Most first rounds pass; some fail so the fix loop can be seen in action.\n const pass = round > 1 || Math.random() > 0.35;\n cb.log([{ kind: 'text', text: pass ? '\u25CF Everything checks out. Writing up the report.' : '\u25CF The toolbar overflows on a 375px screen. Failing this round.' }]);\n cb.finished({\n ok: true,\n text: '',\n costUsd,\n turns,\n errors: [],\n structured: {\n verdict: pass ? 'pass' : 'fail',\n summary: pass\n ? 'The change does what the issue asks: the feature works on desktop and mobile, all 41 tests pass, and lint and build are clean.'\n : 'The feature works on desktop, but on a 375px-wide screen the toolbar overflows and the new button is cut off.',\n checks: [\n { name: 'Unit tests', result: 'pass', details: '41 passed, 0 failed' },\n { name: 'Lint + build', result: 'pass', details: 'No lint errors; production build succeeds' },\n { name: 'Feature works on desktop', result: 'pass', details: 'Clicked through the new flow at 1280x800' },\n { name: 'Mobile layout (375px)', result: pass ? 'pass' : 'fail', details: pass ? 'Layout wraps correctly' : 'Toolbar overflows horizontally; button unreachable' },\n { name: 'Console errors', result: 'pass', details: 'None' },\n ],\n commands: [\n { command: 'npm test -- --run', result: '41 passed' },\n { command: 'npm run lint && npm run build', result: 'clean, built in 1.84s' },\n ],\n screenshots: ['Desktop view after the change', 'Mobile view at 375px'],\n fixInstructions: pass ? undefined : 'Make the toolbar wrap (flex-wrap: wrap) below 480px so every button stays visible.',\n },\n });\n return;\n }\n if (kind === 'fix') {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (pr && pushes) {\n pr.headSha = fakeSha();\n pr.mergeState = 'CLEAN';\n pr.mergeable = 'MERGEABLE';\n runChecks(pr, false);\n }\n cb.log([{ kind: 'text', text: pushes ? `\u25CF Fixed PR #${number} and pushed. Ready for another QA round.` : `\u25CF The toolbar wraps on narrow screens now. Ready for another QA round.` }]);\n cb.finished({ ok: true, text: '', costUsd, turns, errors: [] });\n return;\n }\n const repo = repos.get(fullName);\n let url = '';\n if (repo && number) {\n const n = repo.nextNumber++;\n url = `https://github.com/${fullName}/pull/${n}`;\n repo.pulls.unshift({\n number: n,\n title,\n url,\n headRefName: `swarm/issue-${number}-${path.basename(opts.cwd).replace(/-[0-9a-f]{4}$/, '')}`,\n state: 'OPEN',\n isDraft: false,\n mergeable: 'MERGEABLE',\n reviewDecision: null,\n closesIssues: [number],\n createdAt: now(),\n mergedAt: null,\n additions: 40 + ((number * 13) % 200),\n deletions: (number * 7) % 40,\n checks: 'pending',\n headSha: fakeSha(),\n mergeState: 'CLEAN',\n failedChecks: [],\n pendingChecks: [],\n });\n runChecks(repo.pulls[0]);\n cb.log([{ kind: 'result', text: ` \u23BF ${url}` }]);\n }\n cb.log([{ kind: 'text', text: `\u25CF Opened ${url || 'the pull request'}. It closes #${number} and includes tests.` }]);\n cb.finished({ ok: true, text: url, costUsd, turns, errors: [] });\n };\n\n let i = 0;\n const step = () => {\n if (stopped) return;\n if (i >= script.length) return finish();\n const s = script[i++];\n if (typeof s === 'function') s();\n else {\n const tool = s.find((e) => e.kind === 'tool');\n cb.tool(tool?.tool ?? null);\n cb.log(s);\n }\n timers.push(setTimeout(step, 1600 + Math.random() * 3800));\n };\n timers.push(setTimeout(step, 600));\n\n return {\n send(text) {\n timers.push(\n setTimeout(() => {\n if (stopped) return;\n cb.log([{ kind: 'text', text: `\u25CF Got it \u2014 \"${text.slice(0, 60)}\". Adjusting my approach.` }]);\n }, 1500),\n );\n },\n stop() {\n stopped = true;\n timers.forEach(clearTimeout);\n cb.finished({ ok: false, text: '', costUsd: 0.1, turns: i, errors: ['Stopped by manager'] });\n },\n };\n}\n\n// ---------- the terminal runtime ----------\n\nconst ANSI: Record<LogEntry['kind'], (text: string) => string> = {\n text: (t) => t.replace(/^\u25CF /, '\\x1b[97m\u25CF\\x1b[0m '),\n tool: (t) => `\\x1b[32m\u25CF\\x1b[0m \\x1b[1m${t.replace(/^\u23FA /, '')}\\x1b[0m`,\n result: (t) => `\\x1b[2m${t}\\x1b[0m`,\n thinking: (t) => `\\x1b[35m${t}\\x1b[0m`,\n error: (t) => `\\x1b[31m${t}\\x1b[0m`,\n system: (t) => `\\x1b[2m${t}\\x1b[0m`,\n manager: (t) => `\\x1b[36m${t.replace(/^\u25B6 /, '\u276F ')}\\x1b[0m`,\n done: (t) => `\\x1b[32m${t}\\x1b[0m`,\n};\n\n/**\n * With a terminal (the terminal runtime), the fake session's lines are drawn there the way Claude Code draws them,\n * and what the manager types into it is taken as a message.\n */\nfunction inTerminal(opts: SessionOptions, cb: SessionCallbacks, start: (cb: SessionCallbacks) => SessionHandle): SessionHandle {\n const term = opts.terminal;\n if (!term) return start(cb);\n const name = CLIS.find((c) => c.id === (opts.cli ?? 'claude'))?.label ?? 'Claude Code';\n term.note(`\u2500\u2500 ${name}${opts.label ? ` \u00B7 ${opts.label}` : ''} \u2500\u2500`);\n term.write(\n [\n '',\n ` \\x1b[38;5;209m\u2590\u259B\u2588\u2588\u2588\u259C\u258C\\x1b[0m \\x1b[1m${name}\\x1b[0m (demo)`,\n `\\x1b[38;5;209m\u259D\u259C\u2588\u2588\u2588\u2588\u2588\u259B\u2598\\x1b[0m ${opts.model || 'default model'} \u00B7 ${opts.effort} effort`,\n `\\x1b[38;5;209m \u2598\u2598 \u259D\u259D\\x1b[0m \\x1b[2m${opts.cwd}\\x1b[0m`,\n '',\n `\\x1b[36m\u276F\\x1b[0m ${opts.prompt.split('\\n')[0].slice(0, 200)}`,\n '',\n ].join('\\r\\n'),\n );\n let handle: SessionHandle | null = null;\n let line = '';\n term.bind({\n write: (data) => {\n for (const ch of data.replace(/\\x1b\\[[0-9;?]*[A-Za-z~]|\\x1b./g, '')) {\n if (ch === '\\r') {\n const text = line.trim();\n line = '';\n term.write('\\r\\n');\n if (text && handle) {\n cb.log([{ kind: 'manager', text: `\u25B6 Typed in the terminal: ${text}` }]);\n handle.send(text);\n }\n } else if (ch === '\\x7f' || ch === '\\b') {\n if (line) term.write('\\b \\b');\n line = line.slice(0, -1);\n } else if (ch >= ' ') {\n line += ch;\n term.write(ch);\n }\n }\n },\n resize: () => undefined,\n });\n handle = start({\n ...cb,\n log: (entries) => {\n cb.log(entries);\n for (const e of entries) term.write(`${e.kind === 'tool' || (e.kind === 'text' && e.text.startsWith('\u25CF')) ? '\\r\\n' : ''}${ANSI[e.kind](e.text)}\\r\\n`);\n },\n finished: (r) => {\n term.bind(null);\n term.note(`\u2500\u2500 ${name} session ended \u2500\u2500`);\n cb.finished(r);\n },\n });\n return handle;\n}\n\n// Claude's usage warning, faked once so the office can be seen pacing new work: the 4th session gets it, and the\n// window \"resets\" 5 minutes later.\nconst USAGE_WARNING_AT = 4;\nconst USAGE_WARNING_MS = 5 * 60_000;\nlet sessionsStarted = 0;\n\nfunction fakeUsageWarning(cb: SessionCallbacks) {\n setTimeout(() => {\n const resetsAt = Date.now() + USAGE_WARNING_MS;\n cb.log([{ kind: 'error', text: `\u26A0 Subscription usage warning (five_hour) \u00B7 resets ${new Date(resetsAt).toLocaleTimeString()} (demo)` }]);\n cb.usageWarning?.({ resetsAt, rateLimitType: 'five_hour', utilization: 0.82 });\n }, 3000);\n}\n\nexport function createDemoBackend(): Backend {\n // Tie each fake session back to its repo via the desk directory name.\n const deskRepo = new Map<string, string>();\n // Desks whose pretend dependencies are installed: the first task on a desk installs, the next ones skip.\n const installedDesks = new Set<string>();\n // A pretend projects folder: the demo repos, one git folder that isn't on GitHub yet, and one plain folder.\n const folders = new Map<string, LocalFolder>();\n const addFolder = (name: string, github: string | null, git = true) =>\n folders.set(name, { name, path: `/demo/projects/${name}`, git, github, modified: Date.now() - folders.size * 3_600_000 });\n for (const r of repos.values()) addFolder(r.fullName.split('/')[1], r.fullName);\n addFolder('sketchbook', null);\n addFolder('recipe-notes', null, false);\n const newRepo = (name: string, description = '') => {\n const fullName = `demo-co/${name}`;\n if (!repos.has(fullName)) {\n repos.set(fullName, { fullName, description, issues: [], pulls: [], nextNumber: 1 });\n bareRepos.add(fullName);\n }\n addFolder(name, fullName);\n return fullName;\n };\n const folderOf = (dir: string) => {\n const f = folders.get(dir.replace(/\\\\/g, '/').split('/').pop() ?? '');\n if (!f) throw new Error(`${dir} is not a folder`);\n return f;\n };\n return {\n demo: true,\n user: async () => 'demo-manager',\n listMyRepos: async (): Promise<GhRepoSummary[]> =>\n [...repos.values()].map((r) => ({ nameWithOwner: r.fullName, description: r.description, visibility: 'PUBLIC', updatedAt: now() })),\n repoMeta: async (fullName) => {\n const r = repos.get(fullName);\n if (!r) throw new Error(`Unknown demo repo ${fullName}`);\n return { nameWithOwner: fullName, description: r.description, url: `https://github.com/${fullName}`, defaultBranch: 'main' };\n },\n setLocalPath: () => undefined,\n scanProjects: async () => [...folders.values()].sort((a, b) => b.modified - a.modified),\n inspectFolder: async (dir) => folderOf(dir),\n publishFolder: async (dir, opts) => {\n const f = folderOf(dir);\n return f.github ?? newRepo(f.name, opts.description);\n },\n createProject: async (_root, name, opts) => {\n if (folders.has(name)) throw new Error(`/demo/projects/${name} already exists. Pick another name, or connect that folder instead.`);\n return { fullName: newRepo(name, opts.description), path: `/demo/projects/${name}` };\n },\n listIssues: async (fullName) => [...(repos.get(fullName)?.issues ?? [])],\n listPulls: async (fullName) => [...(repos.get(fullName)?.pulls ?? [])],\n createIssue: async (fullName, title, body, labels = []) => {\n const r = repos.get(fullName);\n if (!r) throw new Error('Unknown repo');\n const n = r.nextNumber++;\n r.issues.push(issue(n, title, body, fullName, labels));\n return n;\n },\n issueState: async (fullName, number) => {\n const r = repos.get(fullName);\n return r?.issues.some((i) => i.number === number) ? 'OPEN' : closedIssues.has(`${fullName}#${number}`) ? 'CLOSED' : null;\n },\n editIssue: async (fullName, number, edit) => {\n const i = repos.get(fullName)?.issues.find((x) => x.number === number);\n if (!i) throw new Error(`Unknown issue #${number}`);\n if (edit.body !== undefined) i.body = edit.body;\n i.labels = [...i.labels.filter((l) => !edit.removeLabels?.includes(l)), ...(edit.addLabels ?? []).filter((l) => !i.labels.includes(l))];\n },\n mergePull: async (fullName, number, _method, headSha) => {\n const r = repos.get(fullName);\n const pr = r?.pulls.find((p) => p.number === number);\n if (!r || !pr) throw new Error('Unknown PR');\n if (headSha && pr.headSha !== headSha) throw new Error('Head branch was modified. Review and try the merge again.');\n mergedSinceSync.set(fullName, (mergedSinceSync.get(fullName) ?? 0) + 1);\n pr.state = 'MERGED';\n pr.mergedAt = now();\n // GitHub closes what \"Closes #N\" links a little after the merge, not straight away.\n setTimeout(() => {\n for (const n of pr.closesIssues) closedIssues.add(`${fullName}#${n}`);\n r.issues = r.issues.filter((i) => !pr.closesIssues.includes(i.number));\n }, 20_000).unref();\n },\n closeIssue: async (fullName, number) => {\n const r = repos.get(fullName);\n if (!r?.issues.some((i) => i.number === number)) throw new Error(`Issue #${number} is not open`);\n closedIssues.add(`${fullName}#${number}`);\n r.issues = r.issues.filter((i) => i.number !== number);\n },\n updateBranch: async (fullName, number) => {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (!pr) throw new Error('Unknown PR');\n Object.assign(pr, { headSha: fakeSha(), mergeState: 'CLEAN' });\n runChecks(pr, false);\n },\n closePull: async (fullName, number) => {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (pr) pr.state = 'CLOSED';\n },\n prForBranch: async () => null,\n prDetails: async (fullName, number) => {\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\n if (!pr) throw new Error(`Unknown PR #${number}`);\n return {\n number,\n title: pr.title,\n body: `Implements the change.\\n\\nCloses #${pr.closesIssues[0] ?? '?'}`,\n url: pr.url,\n headRefName: pr.headRefName,\n headSha: pr.headSha,\n isCrossRepository: false,\n closesIssues: pr.closesIssues,\n state: pr.state,\n mergeable: pr.mergeable,\n mergeState: pr.mergeState,\n checks: pr.checks,\n checkNames: pr.checks === 'none' ? [] : ['CI / build', 'Vercel'],\n failedChecks: pr.failedChecks.map((c) => c.name),\n pendingChecks: pr.pendingChecks,\n };\n },\n issueDetails: async (fullName, number) => {\n const i = repos.get(fullName)?.issues.find((x) => x.number === number);\n return { title: i?.title ?? `Issue #${number}`, body: i?.body ?? '' };\n },\n commentPull: async (fullName, number) => `https://github.com/${fullName}/pull/${number}#issuecomment-${Date.now()}`,\n uploadEvidence: async (fullName, filePath) => `https://github.com/${fullName}/raw/swarm-qa-evidence/${filePath}`,\n ensureClone: async () => new Promise((r) => setTimeout(r, 400)),\n syncMain: async (fullName, _branch, { touch }) => {\n const behind = mergedSinceSync.get(fullName) ?? 0;\n if (behind === 0) return { status: 'in sync', behind: 0, updatable: false };\n if (!touch) return { status: `update ready (${behind} commit${behind === 1 ? '' : 's'})`, behind, updatable: true };\n mergedSinceSync.set(fullName, 0);\n return { status: `updated to ${fakeSha().slice(0, 7)}`, behind: 0, updatable: false };\n },\n mainDir: (fullName) => `/demo/${fullName}/main`,\n deskDir: (fullName, slug) => `/demo/${fullName}/desks/${slug}`,\n prepareDesk: async (fullName, _base, slug) => {\n await new Promise((r) => setTimeout(r, 900));\n const dir = `/demo/${fullName}/desks/${slug}`;\n deskRepo.set(dir, fullName);\n return dir;\n },\n installDeps: async (dir, cb) => {\n if (installedDesks.has(dir)) {\n cb.log(['Dependencies unchanged since the last install; skipping it.']);\n return 'skipped';\n }\n cb.log(['Installing dependencies\u2026', '$ npm ci']);\n cb.installing();\n await new Promise((r) => setTimeout(r, 1500));\n cb.log(['Dependencies installed.']);\n installedDesks.add(dir);\n return 'installed';\n },\n removeDesk: async () => undefined,\n sweepDesks: async () => ({ desks: 0, folders: 0, branches: 0, patches: [], skipped: [] }),\n releaseDesk: async () => undefined,\n startSession: (opts, cb) => {\n if (++sessionsStarted === USAGE_WARNING_AT) fakeUsageWarning(cb);\n return inTerminal(opts, cb, (c) => (opts.role === 'ceo' ? ceoSession(opts, c) : fakeSession(opts, c, deskRepo.get(opts.cwd) ?? [...repos.keys()][0])));\n },\n terminals: true,\n reconnectClis: async () => [], // fake sessions end with the office\n hooksReady: () => undefined,\n releaseClis: async () => undefined,\n detectClis: async () =>\n CLIS.map((c) => ({ id: c.id, label: c.label, installed: true, version: 'demo', integrated: c.integrated })),\n previews: demoPreviews,\n office: demoOffice,\n voice: demoVoice,\n };\n}\n\n// ---------- the office's own update ----------\n\n/**\n * Floor 1's folder plays the office's own folder, so merges there make an update ready. There is a launcher when\n * the real one started the demo, or with SWARM_DEMO_LAUNCHER=1; either way the update is faked: a short pause, then\n * the result message, and nothing restarts.\n */\nconst OFFICE_REPO = 'demo-co/pixel-todo';\nconst DEMO_HEAD = `0ff1ce5${'0'.repeat(33)}`;\nconst lastFakeUpdate = { to: '', commits: 0 };\nconst demoOffice: OfficeHost = {\n launcher: underLauncher() || process.env.SWARM_DEMO_LAUNCHER === '1',\n head: async () => DEMO_HEAD,\n isOwnFolder: (dir) => dir === `/demo/${OFFICE_REPO}/main`,\n // Only its own fake updates have a count; one the real launcher did (u) gets no count rather than a wrong one.\n commitsBetween: async (_from, to) => (to === lastFakeUpdate.to ? lastFakeUpdate.commits : null),\n takeLastUpdate: () => takeLastUpdate(HOME_DIR),\n async update(from) {\n await new Promise((r) => setTimeout(r, 4000));\n lastFakeUpdate.commits = mergedSinceSync.get(OFFICE_REPO) ?? 0;\n mergedSinceSync.set(OFFICE_REPO, 0);\n lastFakeUpdate.to = fakeSha();\n return { from, to: lastFakeUpdate.to, ok: true, installed: true, built: true, at: Date.now() };\n },\n};\n\n// ---------- the demo preview ----------\n\nfunction placeholderPage(title: string, hue: number) {\n const safe = title.replace(/[<>&\"]/g, '');\n return `<!doctype html>\n<html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>${safe}</title><link rel=\"icon\" href=\"data:,\">\n<style>\n body { margin: 0; min-height: 100vh; display: grid; place-items: center; font-family: 'Segoe UI', Arial, sans-serif; background: hsl(${hue},60%,96%); color: #222; }\n main { text-align: center; padding: 32px 40px; background: #fff; border-radius: 18px; box-shadow: 0 8px 30px hsla(${hue},50%,40%,.18); }\n h1 { margin: 0 0 6px; font-size: 26px; color: hsl(${hue},60%,38%); }\n p { margin: 0 0 22px; color: #666; }\n button { font: inherit; font-size: 18px; padding: 10px 26px; border: 0; border-radius: 999px; background: hsl(${hue},70%,55%); color: #fff; cursor: pointer; }\n button:active { transform: scale(.97); }\n #count { display: block; margin-top: 16px; font-size: 15px; color: #444; }\n</style></head>\n<body><main>\n <h1>${safe}</h1>\n <p>A placeholder app served by the demo office.</p>\n <button id=\"btn\" type=\"button\">Click me</button>\n <span id=\"count\">Clicked 0 times</span>\n</main>\n<script>\n let n = 0;\n document.getElementById('btn').addEventListener('click', () => {\n n++;\n document.getElementById('count').textContent = 'Clicked ' + n + (n === 1 ? ' time' : ' times');\n });\n</script>\n</body></html>`;\n}\n\n/** Programs the demo pretends to have, so a bogus preview command fails the way it would for real. */\nconst DEMO_PROGRAMS = ['npm', 'npx', 'node', 'pnpm', 'yarn', 'bun', 'deno', 'vite', 'next', 'python', 'python3', 'py', 'php', 'ruby', 'go', 'cargo', 'dotnet'];\n\n/**\n * No git, no npm: short fake delays through the real statuses, then a placeholder page on the floor's port.\n * Floors made in the demo have nothing to run until they get a command, and a command whose program isn't in\n * DEMO_PROGRAMS fails, so the viewer's unconfigured and error states can be tried out.\n */\nconst demoPreviews: PreviewBackend = {\n hasDefault: async (fullName) => !bareRepos.has(fullName),\n start(job, cb) {\n let stopped = false;\n let server: http.Server | null = null;\n const timers: NodeJS.Timeout[] = [];\n const later = (ms: number, fn: () => void) => timers.push(setTimeout(() => !stopped && fn(), ms));\n const hue = [...job.fullName].reduce((h, c) => (h * 31 + c.charCodeAt(0)) % 360, 7);\n const sha = (job.pr ? repos.get(job.fullName)?.pulls.find((p) => p.number === job.pr)?.headRefName ?? String(job.pr) : job.fullName + job.defaultBranch)\n .split('')\n .reduce((h, c) => (h * 33 + c.charCodeAt(0)) >>> 0, 5381)\n .toString(16)\n .padStart(7, '0')\n .slice(0, 7);\n\n cb.status('preparing');\n later(700, () => {\n cb.commit(sha);\n cb.log([`HEAD is now at ${sha} (${job.pr ? `PR #${job.pr}` : job.defaultBranch})`]);\n if (!job.command && bareRepos.has(job.fullName)) {\n stopped = true;\n cb.failed('Nothing to run: this floor has no preview command and no package.json.', true);\n return;\n }\n cb.status('installing');\n cb.log(['$ npm ci', 'added 214 packages in 1s (demo)']);\n });\n later(1600, () => {\n cb.status('starting');\n cb.log([`$ ${job.command ?? 'npm run dev'}`.replaceAll('{port}', String(job.port))]);\n const program = job.command?.trim().split(/\\s+/)[0] ?? 'npm';\n if (!DEMO_PROGRAMS.includes(program.toLowerCase())) {\n later(400, () => {\n cb.log([`'${program}' is not recognized as an internal or external command,`, 'operable program or batch file.']);\n stopped = true;\n cb.failed(`The app exited (code 1) before it listened on port ${job.port}.`);\n });\n return;\n }\n server = http.createServer((req, res) => {\n if (req.url !== '/' && !req.url?.startsWith('/?')) return void res.writeHead(404).end('Not found');\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });\n res.end(placeholderPage(job.title, hue));\n });\n server.once('error', (err) => {\n if (stopped) return;\n stopped = true;\n cb.failed(`Could not listen on port ${job.port}: ${err.message}`);\n });\n server.listen(job.port, '127.0.0.1', () => {\n if (stopped) return void server?.close();\n later(500, () => {\n cb.log([` \u279C Local: http://localhost:${job.port}/`]);\n cb.status('running');\n });\n });\n });\n\n return {\n async stop() {\n stopped = true;\n timers.forEach(clearTimeout);\n const s = server;\n server = null;\n if (!s?.listening) return;\n s.closeAllConnections();\n await new Promise<void>((resolve) => s.close(() => resolve()));\n },\n };\n },\n};\n\n// ---------- the demo CEO ----------\n\ninterface Profile {\n summary: string;\n qa: string;\n qaTitle: string;\n qaJob: string;\n devTitle: string;\n devSpecialty: string;\n devJob: string;\n hires: { title: string; specialty: string; job_description: string; reason: string }[];\n}\n\nconst PROFILES: Record<string, Profile> = {\n 'pixel-todo': {\n summary: 'Todo web app \u00B7 React + Vite + TypeScript',\n qa: '- Add, complete, edit and delete todos; they survive a reload\\n- Keyboard only: every action reachable, focus always visible\\n- Phone width (375px): nothing overflows or gets cut off\\n- No errors in the browser console',\n qaTitle: 'UI QA tester',\n qaJob: 'You test every PR the way a picky user would: click through the whole flow, try it on a phone-sized screen and with the keyboard only.',\n devTitle: 'React UI engineer',\n devSpecialty: 'frontend',\n devJob: 'You own the React components and styling. Keep components small, reuse the existing hooks, and check every change at desktop and phone widths.',\n hires: [\n {\n title: 'Accessibility engineer',\n specialty: 'a11y',\n job_description:\n 'You make the app work for **everyone**:\\n\\n- Keyboard navigation and focus management\\n- ARIA roles, checked with `axe`\\n- Colour contrast (WCAG AA)\\n\\nTest with the keyboard only. The [WAI-ARIA practices](https://www.w3.org/WAI/ARIA/apg/) are your reference.',\n reason: 'Keyboard shortcuts and drag-and-drop are in the backlog, and both are *easy to get wrong* for keyboard and screen-reader users.',\n },\n ],\n },\n 'weather-api': {\n summary: 'REST API \u00B7 Node + Express',\n qa: '- Every endpoint: happy path, bad input (400), unknown city (404)\\n- Response shapes match the OpenAPI document\\n- Rate limiting returns 429 with Retry-After\\n- Tests and lint pass',\n qaTitle: 'API QA tester',\n qaJob: 'You test the API from the outside: curl every endpoint, try bad input and edge cases, and compare responses with the OpenAPI document.',\n devTitle: 'Backend engineer',\n devSpecialty: 'backend',\n devJob: 'You own the routes and data layer. Validate input at the edge, return consistent error shapes, and add tests for every endpoint you touch.',\n hires: [\n {\n title: 'API reliability engineer',\n specialty: 'reliability',\n job_description: 'You own rate limiting, caching and error handling. Measure before you optimise and document every limit in the OpenAPI spec.',\n reason: 'Rate limiting is in the backlog and the forecast endpoint will call an upstream service that needs caching and timeouts.',\n },\n ],\n },\n};\n\nconst GENERIC: Profile = {\n summary: 'Web project \u00B7 early stage',\n qa: '- The app builds and starts\\n- The changed feature works end to end in the browser\\n- Phone width: nothing overflows\\n- No console errors',\n qaTitle: 'QA tester',\n qaJob: 'You check every PR end to end in the browser, at desktop and phone widths.',\n devTitle: 'Full-stack engineer',\n devSpecialty: 'fullstack',\n devJob: 'You build features end to end, from the UI down to the data.',\n hires: [\n {\n title: 'Frontend engineer',\n specialty: 'frontend',\n job_description: 'You own the UI:\\n\\n1. Layout and components\\n2. Styling, checked at **desktop and phone** widths',\n reason: 'The project needs someone who owns the UI from the start.',\n },\n ],\n};\n\ninterface DemoFloor {\n floor: number;\n repo: string;\n brief: string | null;\n team: { id: string; name: string; role: string; specialty: string | null; status: string }[];\n backlog: unknown[];\n pullRequests: unknown[];\n seats: Record<'dev' | 'qa', { free: number }>;\n}\n\n/** A scripted CEO that uses the real office tools, so proposals, profiles and issues behave exactly as in the real thing. */\nfunction ceoSession(opts: SessionOptions, cb: SessionCallbacks): SessionHandle {\n const office = opts.office!;\n const timers: NodeJS.Timeout[] = [];\n let stopped = false;\n let done = false;\n const wait = (ms: number) => new Promise<void>((resolve) => timers.push(setTimeout(resolve, ms)));\n const step = async (entries: LogEntry[], ms = 900 + Math.random() * 1500) => {\n if (stopped) throw new Error('Stopped by manager');\n cb.tool(entries.find((e) => e.tool)?.tool ?? null);\n cb.log(entries);\n await wait(ms);\n };\n const status = async () => {\n await step([{ kind: 'tool', tool: 'mcp__office__company_status', text: `\u23FA ${describeOfficeTool('company_status', {})}` }]);\n const s = JSON.parse(await office.call('company_status', {})) as { floors: DemoFloor[]; pendingProposals: unknown[] };\n const people = s.floors.reduce((n, f) => n + f.team.length, 0);\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\n const free = s.floors.reduce((n, f) => n + f.seats.dev.free + f.seats.qa.free, 0);\n cb.log([{ kind: 'result', text: ` \u23BF ${s.floors.length} floors \u00B7 ${people} people \u00B7 ${free} free seats \u00B7 ${issues} open issues \u00B7 ${s.pendingProposals.length} proposals pending` }]);\n return s;\n };\n const use = async (name: string, args: Record<string, unknown>) => {\n await step([{ kind: 'tool', tool: `mcp__office__${name}`, text: `\u23FA ${describeOfficeTool(name, args)}` }]);\n const out = await office.call(name, args);\n cb.log([{ kind: out.startsWith('Refused') ? 'error' : 'result', text: ` \u23BF ${out.split('\\n')[0].slice(0, 170)}` }]);\n return out;\n };\n const read = (file: string, lines: number) => step([{ kind: 'tool', tool: 'Read', text: `\u23FA Read ${file}` }, { kind: 'result', text: ` \u23BF Read ${lines} lines` }]);\n const think = (text: string) => step([{ kind: 'thinking', text: '\u273B Thinking\u2026' }, { kind: 'text', text: `\u25CF ${text}` }], 1800);\n const short = (s: string, n = 48) => (s.length > n ? `${s.slice(0, n - 1).trim()}\u2026` : s);\n\n const planIssues = async (floor: number, mission: string, team: DemoFloor['team']) => {\n const first = await use('file_issue', {\n floor,\n title: 'Set up the project skeleton',\n body: `Scaffold the app so the rest of the milestone has something to build on.\\n\\nBrief: ${mission}\\n\\nAcceptance criteria:\\n- The dev server starts\\n- A placeholder home page renders\\n- Lint, tests and build scripts exist`,\n specialty: 'frontend',\n });\n const n = Number(first.match(/#(\\d+)/)?.[1] ?? 0);\n await use('file_issue', {\n floor,\n title: `Build the core: ${short(mission, 60)}`,\n body: `${n ? `Depends on #${n}\\n\\n` : ''}Implement the heart of the brief.\\n\\nAcceptance criteria:\\n- The main flow works end to end\\n- Covered by tests`,\n specialty: 'frontend',\n });\n await use('file_issue', {\n floor,\n title: 'Polish: phone layout and empty states',\n body: `${n ? `Depends on #${n}\\n\\n` : ''}Make every screen work at 375px and add friendly empty states.`,\n specialty: 'frontend',\n });\n if (!team.some((a) => a.specialty === 'frontend')) {\n await use('propose_hire', { floor, role: 'dev', ...GENERIC.hires[0], reason: 'All three issues are UI work and nobody on the floor owns the frontend yet.' });\n }\n return n;\n };\n\n const scripts = {\n async onboard(floor: number, fullName: string) {\n const s = await status();\n const f = s.floors.find((x) => x.floor === floor);\n if (!f) return 'That floor has gone, so there was nothing to onboard.';\n const p = PROFILES[fullName.split('/')[1] ?? ''] ?? GENERIC;\n await read(`${f.repo}/README.md`, 48);\n await step([{ kind: 'tool', tool: 'Glob', text: '\u23FA Glob src/**/*' }, { kind: 'result', text: ' \u23BF Found 23 files' }]);\n await read('package.json', 36);\n await think(`${p.summary}. Let me shape the team around that.`);\n await use('set_floor_profile', { floor, summary: p.summary, qa_brief: p.qa });\n const qa = f.team.find((a) => a.role === 'qa');\n if (qa) {\n await step([{ kind: 'tool', tool: 'mcp__office__agent_detail', text: `\u23FA ${describeOfficeTool('agent_detail', { agent_id: qa.id })}` }]);\n const d = JSON.parse(await office.call('agent_detail', { agent_id: qa.id })) as { title: string; jobDescription: string | null };\n cb.log([{ kind: 'result', text: ` \u23BF ${d.title} \u00B7 job description ${d.jobDescription?.length ?? 0} chars` }]);\n await use('update_job', { agent_id: qa.id, title: p.qaTitle, job_description: p.qaJob });\n }\n const dev = f.team.find((a) => a.role === 'dev' && !a.specialty);\n if (dev) await use('update_job', { agent_id: dev.id, title: p.devTitle, specialty: p.devSpecialty, job_description: p.devJob });\n const proposed: string[] = [];\n for (const h of p.hires) if (!(await use('propose_hire', { floor, role: 'dev', ...h })).startsWith('Refused')) proposed.push(h.title);\n let planned = '';\n if (f.brief && f.backlog.length === 0) {\n const n = await planIssues(floor, f.brief, f.team);\n planned = ` I also turned your brief into three issues; #${n} sets up the skeleton and the other two wait for it.`;\n }\n return [\n `Floor ${floor}: ${p.summary}.`,\n `I wrote a QA brief for it${qa ? `, made ${qa.name} our ${p.qaTitle}` : ''}${dev ? ` and ${dev.name} our ${p.devTitle}` : ''}.`,\n proposed.length ? `I've proposed hiring: ${proposed.join(', ')}. The resume${proposed.length === 1 ? ' is' : 's are'} waiting on your phone.` : '',\n planned,\n ]\n .filter(Boolean)\n .join(' ');\n },\n async plan(floor: number, mission: string) {\n const s = await status();\n const f = s.floors.find((x) => x.floor === floor);\n if (!f) return 'That floor has gone, so there was nothing to plan.';\n await read(`${f.repo}/README.md`, 12);\n await think(\"Foundation first, so the parallel work doesn't collide.\");\n const n = await planIssues(floor, mission, f.team);\n return `I turned the brief into three issues on floor ${floor}. #${n} sets up the skeleton; the other two say \"Depends on #${n}\", so nobody starts them early.`;\n },\n async review() {\n const s = await status();\n await think('Checking each floor for idle people and stuck work.');\n for (const f of s.floors) {\n const idle = f.team.filter((a) => a.role === 'dev' && !a.specialty && (a.status === 'idle' || a.status === 'done'));\n const devs = f.team.filter((a) => a.role === 'dev').length;\n if (devs >= 6 && idle.length >= 2 && f.backlog.length < devs) {\n await use('propose_let_go', { agent_id: idle[idle.length - 1].id, reason: `Floor ${f.floor} has ${devs} developers for ${f.backlog.length} open issues; ${idle.length} of them are idle.` });\n return `Floor ${f.floor} is overstaffed: ${devs} developers for ${f.backlog.length} open issues. I suggest letting ${idle[idle.length - 1].name} go; it's on your phone.`;\n }\n }\n // An issue nobody routed while the floor has a specialist: re-route it rather than file a duplicate.\n for (const f of s.floors) {\n const specialist = f.team.find((a) => a.role === 'dev' && a.specialty);\n const unrouted = (f.backlog as { number: number; specialty: string | null; inProgress: boolean }[]).find((i) => !i.specialty && !i.inProgress);\n if (!specialist || !unrouted) continue;\n const out = await use('route_issue', { floor: f.floor, number: unrouted.number, specialty: specialist.specialty });\n if (!out.startsWith('Refused')) return `Floor ${f.floor}: #${unrouted.number} had no specialty, so I routed it to ${specialist.specialty}, ${specialist.name}'s lane.`;\n }\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\n const prs = s.floors.reduce((n, f) => n + f.pullRequests.length, 0);\n return `All ${s.floors.length} floors look healthy: ${issues} open issues and ${prs} pull requests in flight. No changes needed.`;\n },\n async chat(text: string) {\n const s = await status();\n await think('Reading your message.');\n const people = s.floors.reduce((n, f) => n + f.team.length, 0);\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\n const pending = s.pendingProposals.length;\n // Real CEOs answer in Markdown, so the demo one does too: every element the phone renders.\n const rows = s.floors.map((f) => `| ${f.floor} | \\`${f.repo.split('/').pop()}\\` | ${f.team.length} | ${f.backlog.length} | ${f.pullRequests.length} |`);\n return [\n `**Quick status:** ${s.floors.length} floor${s.floors.length === 1 ? '' : 's'}, ${people} people and ${issues} open issues.`,\n '',\n '- The team is *heads down* on the backlog',\n `- ${pending ? `**${pending}** proposal${pending === 1 ? ' is' : 's are'} waiting for you in Hires` : 'No hiring decisions waiting on you'}`,\n ' - QA re-tests every PR after a fix',\n '',\n '| Floor | Repo | People | Issues | PRs |',\n '| ---: | --- | ---: | ---: | ---: |',\n ...(rows.length ? rows : ['| \u2013 | no projects yet | 0 | 0 | 0 |']),\n '',\n 'What I would do next:',\n '',\n '1. Merge anything that passed QA',\n '2. Run `npm run build` on each floor before the next milestone',\n '3. Hire only where the backlog is piling up',\n '',\n '```bash',\n 'SWARM_HOME=/tmp/cubefarm-demo SWARM_PORT=5260 node --import tsx server/index.ts --demo',\n '```',\n '',\n `> I'm the demo CEO, so I can't act on \"${short(text)}\", but the real one would. See the [Claude Code docs](https://docs.claude.com/en/docs/claude-code/overview).`,\n ].join('\\n');\n },\n };\n\n const prompt = opts.prompt;\n const where = prompt.match(/[Ff]loor (\\d+) \\(([^,)]+)/);\n const run = /just joined the company/.test(prompt)\n ? () => scripts.onboard(Number(where?.[1]), where?.[2] ?? '')\n : /has a brief for floor/.test(prompt)\n ? () => scripts.plan(Number(where?.[1]), prompt.match(/\"\"\"([\\s\\S]*?)\"\"\"/)?.[1]?.trim() ?? '')\n : /Periodic review/.test(prompt)\n ? () => scripts.review()\n : () => scripts.chat(prompt.split('\\n').slice(1).join(' ').trim() || prompt);\n\n const finish = (ok: boolean, text: string, error?: string) => {\n if (done) return;\n done = true;\n cb.tool(null);\n cb.finished({ ok, text, costUsd: ok ? 0.4 + Math.random() : 0.05, turns: 6 + Math.floor(Math.random() * 10), errors: error ? [error] : [] });\n };\n\n timers.push(\n setTimeout(async () => {\n try {\n cb.log([{ kind: 'system', text: `\u273B Claude Code (demo) \u00B7 ${opts.model} \u00B7 ${opts.effort} effort \u00B7 CEO` }]);\n const reply = await run();\n cb.log([{ kind: 'text', text: `\u25CF ${reply}` }]);\n cb.turn?.(reply);\n finish(true, reply);\n } catch (err) {\n finish(false, '', stopped ? 'Stopped by manager' : (err as Error).message);\n }\n }, 500),\n );\n\n return {\n send(text) {\n timers.push(\n setTimeout(() => {\n if (stopped || done) return;\n const said = text.split('\\n').slice(1).join(' ').trim() || text;\n cb.log([{ kind: 'text', text: `\u25CF Noted: \"${short(said, 70)}\"` }]);\n cb.turn?.(`Noted, I'll factor that in: \"${short(said, 90)}\"`);\n }, 1500),\n );\n },\n stop() {\n stopped = true;\n timers.forEach(clearTimeout);\n finish(false, '', 'Stopped by manager');\n },\n };\n}\n\n// ---------- voice ----------\n\n/** A short two-note chime as 8 kHz mono WAV: something to hear without ElevenLabs, a little longer for longer text. */\nexport function demoChime(chars: number): Buffer {\n const rate = 8000;\n const seconds = Math.min(0.4 + chars / 400, 2);\n const n = Math.round(rate * seconds);\n const wav = Buffer.alloc(44 + n);\n wav.write('RIFF', 0);\n wav.writeUInt32LE(36 + n, 4);\n wav.write('WAVEfmt ', 8);\n wav.writeUInt32LE(16, 16);\n wav.writeUInt16LE(1, 20); // PCM\n wav.writeUInt16LE(1, 22); // mono\n wav.writeUInt32LE(rate, 24);\n wav.writeUInt32LE(rate, 28);\n wav.writeUInt16LE(1, 32);\n wav.writeUInt16LE(8, 34);\n wav.write('data', 36);\n wav.writeUInt32LE(n, 40);\n for (let i = 0; i < n; i++) {\n const t = i / rate;\n const f = t < seconds / 2 ? 660 : 880;\n const fade = Math.min(1, (seconds - t) * 8, t * 40);\n wav[44 + i] = Math.round(128 + 40 * fade * Math.sin(2 * Math.PI * f * t));\n }\n return wav;\n}\n\nconst demoVoices = [\n { id: 'demoVoiceAvery00001', name: 'Avery', category: 'premade', labels: { accent: 'american', gender: 'female', age: 'middle aged', description: 'calm', use_case: 'conversational' }, previewUrl: null },\n { id: 'demoVoiceBasil00002', name: 'Basil', category: 'premade', labels: { accent: 'british', gender: 'male', age: 'middle aged', description: 'warm', use_case: 'narration' }, previewUrl: null },\n { id: 'demoVoiceCleo000003', name: 'Cleo', category: 'premade', labels: { accent: 'australian', gender: 'female', age: 'young', description: 'friendly', use_case: 'conversational' }, previewUrl: null },\n];\n\n/** No network: any key works except one containing \"bad\", three voices, and a chime for every message. */\nconst demoVoice: VoiceApi = {\n checkKey: async (key) => {\n if (/bad/i.test(key)) throw new VoiceApiError(401, '401: invalid_api_key (demo)');\n },\n listVoices: async () => demoVoices,\n synthesize: async (_key, { text }) => {\n await new Promise((r) => setTimeout(r, 300));\n return demoChime(text.length);\n },\n};\n", "// What GET /api/agents/:id/screen answers. A desk asks for the latest screenshot while a new task may be clearing\n// it, so \"no screenshot right now\" is an ordinary 204, not an error; only an unknown agent is a 404.\n\n/**\n * The status for an agent's screenshot: 200 with the image, 204 when the agent has none right now, 404 when there\n * is no such agent (`undefined`).\n */\nexport function screenStatus(shot: { data: Buffer; mime: string } | null | undefined): 200 | 204 | 404 {\n if (shot === undefined) return 404;\n return shot ? 200 : 204;\n}\n", "import { z } from 'zod';\nimport type { PullInfo, QaView } from '../shared/types.ts';\nimport { HttpError } from './httpError.ts';\nimport { conflictFixInstructions } from './qaOutcome.ts';\n\n// The manager's \"send back to the developer\" on a PR that needs a human (or failed QA): QA's findings are already\n// clear, so a developer fixes it straight away, with the manager's note, instead of spending another QA round first.\n\n/** A note for the developer longer than this is refused. */\nexport const MAX_SEND_BACK_NOTE = 1000;\n\nconst body = z.object({ note: z.string().max(MAX_SEND_BACK_NOTE).optional() });\n\n/** The optional note from a request body; blank means none. Throws HttpError(400) for anything else. */\nexport function parseSendBackNote(input: unknown): string | undefined {\n const parsed = body.safeParse(input ?? {});\n if (!parsed.success) throw new HttpError(400, `note must be text of at most ${MAX_SEND_BACK_NOTE} characters`);\n return parsed.data.note?.trim() || undefined;\n}\n\n/** The parts of a QA record a send-back reads. */\nexport interface SendBackRecord {\n status: QaView['status'];\n fixInstructions: string | null;\n retests: number;\n passedSha: string | null;\n}\n\nexport interface SendBackPatch {\n status: 'failed';\n fixReason: 'qa' | 'conflict';\n fixInstructions: string | null;\n sessionFailures: number;\n retests: number;\n mergeNote: null;\n}\n\n/**\n * What sending PR #n back to a developer does to its QA record. Throws HttpError: 404 for an unknown or closed PR,\n * 409 while it is being tested or fixed, or when it isn't waiting on anyone. The scheduler hands a failed record to\n * its author, or any free developer. The extra QA round is counted as a retest, so the round numbers stay honest.\n * A conflicting PR QA never passed goes out as a QA fix, so its instructions add the merge with base.\n */\nexport function sendBackPatch(\n prNumber: number,\n pr: Pick<PullInfo, 'state' | 'mergeable' | 'mergeState'> | undefined,\n rec: SendBackRecord | undefined,\n base: string,\n note?: string,\n): SendBackPatch {\n if (!pr || pr.state !== 'OPEN') throw new HttpError(404, `PR #${prNumber} is not open`);\n if (rec?.status === 'testing' || rec?.status === 'fixing') throw new HttpError(409, `PR #${prNumber} is already ${rec.status}`);\n if (!rec || (rec.status !== 'needs-human' && rec.status !== 'failed')) {\n throw new HttpError(409, `PR #${prNumber} isn't waiting on you: only a PR that failed QA or needs a human can go back to a developer`);\n }\n const conflict = pr.mergeable === 'CONFLICTING' || pr.mergeState === 'DIRTY';\n const findings = [rec.fixInstructions?.trim(), note?.trim() && `From the manager: ${note.trim()}`].filter(Boolean).join('\\n\\n');\n const addMerge = conflict && !rec.passedSha && !findings.includes(`conflicts with ${base}`);\n const fixInstructions = (addMerge ? conflictFixInstructions(findings, base) : findings) || null;\n return { status: 'failed', fixReason: conflict ? 'conflict' : 'qa', fixInstructions, sessionFailures: 0, retests: rec.retests + 1, mergeNote: null };\n}\n", "import type { PullInfo } from '../shared/types.ts';\n\n// Auto-merge: fixes for failing checks or conflicts before a PR needs the manager, how long checks may run before\n// the manager hears about it, and how long to wait before retrying a merge GitHub refused.\nexport const MAX_MERGE_FIXES = 3;\nexport const CHECKS_ALERT_MS = 30 * 60_000;\nexport const MERGE_RETRY_MS = 10 * 60_000;\n\n/** The parts of a QA record the merge gate reads. */\nexport interface MergeRecord {\n passedSha: string | null;\n mergeFixes: number;\n pendingSince: number | null;\n mergeRetryAt: number | null;\n alerted: boolean;\n}\n\n/** Bookkeeping the caller writes onto the record as it is (it doesn't count as a change to the record). */\nexport type MergeBookkeeping = Partial<Pick<MergeRecord, 'passedSha' | 'pendingSince' | 'alerted'>>;\n\nexport type MergePull = Pick<PullInfo, 'isDraft' | 'mergeable' | 'mergeState' | 'headSha' | 'checks' | 'failedChecks' | 'pendingChecks'>;\n\n/** What auto-merge does next with a QA-passed PR. */\nexport type MergeStep = { set: MergeBookkeeping } & (\n | { do: 'wait'; note?: string; alert?: boolean } // no note: leave the card as it is; alert: tell the manager checks are slow\n | { do: 'details' } // GitHub hasn't worked out mergeability: ask about the PR itself, then decide again with `detailed`\n | { do: 'requeue' } // commits arrived after QA's sign-off: QA tests them too\n | { do: 'send-back'; reason: 'checks' | 'conflict'; instructions: string; needsHuman: boolean } // needsHuman: the fix budget ran out\n | { do: 'update-branch' } // the repo only merges up-to-date branches\n | { do: 'merge' }\n);\n\n/**\n * Decide the next step toward merging a PR QA has passed. Pure: advanceMerge (swarm.ts) does the talking to GitHub\n * and the office. `detailed` means the PR's mergeability has already been asked for, so UNKNOWN is waited out.\n */\nexport function mergeStep(pr: MergePull, rec: MergeRecord, now: number, opts: { base: string; detailed?: boolean }): MergeStep {\n if (pr.isDraft) return { do: 'wait', note: 'a draft: waiting', set: {} };\n if (!opts.detailed && (pr.mergeable === 'UNKNOWN' || pr.mergeState === 'UNKNOWN')) return { do: 'details', set: {} };\n const set: MergeBookkeeping = {};\n if (rec.passedSha == null) set.passedSha = pr.headSha; // signed off before the office tracked commits\n if (pr.headSha !== (set.passedSha ?? rec.passedSha)) return { do: 'requeue', set };\n const needsHuman = rec.mergeFixes >= MAX_MERGE_FIXES;\n if (pr.mergeable === 'CONFLICTING' || pr.mergeState === 'DIRTY') {\n return { do: 'send-back', reason: 'conflict', instructions: `It conflicts with ${opts.base}.`, needsHuman, set };\n }\n if (pr.checks === 'failing') {\n const instructions = pr.failedChecks.map((c) => `- ${c.name}${c.url ? `: ${c.url}` : ''}`).join('\\n');\n return { do: 'send-back', reason: 'checks', instructions, needsHuman, set };\n }\n if (pr.checks === 'pending') {\n const since = rec.pendingSince ?? now;\n if (rec.pendingSince == null) set.pendingSince = since;\n const alert = now - since > CHECKS_ALERT_MS && !rec.alerted;\n if (alert) set.alerted = true;\n return { do: 'wait', note: `waiting for checks: ${pr.pendingChecks.join(', ') || 'running'}`, alert, set };\n }\n set.pendingSince = null;\n if (pr.mergeable === 'UNKNOWN') return { do: 'wait', note: 'GitHub is checking it can merge', set };\n if (pr.mergeState === 'BEHIND') return { do: 'update-branch', set };\n if (rec.mergeRetryAt && now < rec.mergeRetryAt) return { do: 'wait', set };\n return { do: 'merge', set };\n}\n", "import type { PullInfo } from '../shared/types.ts';\nimport { MAX_MERGE_FIXES } from './mergeGate.ts';\n\n// What a finished QA round does to its PR. A conflict with the default branch is the merge gate's job, not QA's: a\n// fail on the last QA round while the PR conflicts goes back for a merge fix (and one more QA round) rather than to\n// the manager, as long as the merge-fix budget lasts.\n\n/** QA rounds that fail before a PR goes to the manager. */\nexport const MAX_QA_ROUNDS = 3;\n\n/** The parts of a QA record a finished QA round reads. */\nexport interface QaRoundRecord {\n round: number;\n retests: number; // rounds the office added (re-tests after merge fixes), not counted against QA's budget\n mergeFixes: number;\n}\n\nexport type QaPull = Pick<PullInfo, 'mergeable' | 'mergeState'>;\n\n/**\n * passed: on to the merge gate (which handles a conflict as it always has). failed: back to the developer.\n * conflict: back to the developer to merge the default branch and fix QA's findings. needs-human: the manager decides.\n */\nexport type QaNext = 'passed' | 'failed' | 'conflict' | 'needs-human';\n\n/** True when a fail now would use up QA's rounds: only then is the PR's mergeability worth asking about. */\nexport function lastQaRound(rec: QaRoundRecord): boolean {\n return rec.round - rec.retests >= MAX_QA_ROUNDS;\n}\n\n/** Decide where a PR goes after QA. pr: its mergeability right now, or null when it wasn't (or couldn't be) asked. */\nexport function qaOutcome(pass: boolean, rec: QaRoundRecord, pr: QaPull | null): QaNext {\n if (pass) return 'passed';\n if (!lastQaRound(rec)) return 'failed';\n const conflicting = pr != null && (pr.mergeable === 'CONFLICTING' || pr.mergeState === 'DIRTY');\n return conflicting && rec.mergeFixes < MAX_MERGE_FIXES ? 'conflict' : 'needs-human';\n}\n\n/** What the developer is told on a conflict send-back: QA's findings first, then the merge. */\nexport function conflictFixInstructions(qaInstructions: string, base: string): string {\n const merge = `It also conflicts with ${base}: bring it up to date (git fetch origin && git merge origin/${base}) and resolve the conflicts so both this change and the newly merged work keep working.`;\n return qaInstructions.trim() ? `${qaInstructions.trim()}\\n\\n${merge}` : merge;\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport type { WebSocket } from 'ws';\nimport type { Backend } from './backend.ts';\nimport type { LogEntry, SessionHandle, SessionResult } from './agentRunner.ts';\nimport type { PrDetails } from './github.ts';\nimport { defaultProjectsDir, DESK_SWEEP_INTERVAL_MS, HOME_DIR, LOG_BUFFER, SCHEDULER_INTERVAL_MS, STATE_FILE, SYNC_INTERVAL_MS, WORKSPACE_ROOT } from './config.ts';\nimport { ceoJobPrompt, ceoSystemPrompt, checkPendingLimit, createOfficeTools, FLOOR_DESKS, IssueCap, jobLabel, MAX_PENDING_PROPOSALS, planRoute, seatCount, specialtyLabel, specialtySlug, type CeoJob, type OfficeTools } from './ceo.ts';\nimport { depsPromptLine, type DepsOutcome } from './deps.ts';\nimport { setUpDesk } from './deskSetup.ts';\nimport { fixOutcome } from './fixOutcome.ts';\nimport { HttpError } from './httpError.ts';\nimport { issuesResolvedBy, issueTaken } from './issueClaims.ts';\nimport { CHECKS_ALERT_MS, MAX_MERGE_FIXES, MERGE_RETRY_MS, mergeStep } from './mergeGate.ts';\nimport { orphanedQa } from './qaOrphans.ts';\nimport { conflictFixInstructions, lastQaRound, qaOutcome, type QaNext } from './qaOutcome.ts';\nimport { qaInstructions } from './qaPrompt.ts';\nimport { followKeptCli, resumeNote, resumesAfterRestart } from './restartRecovery.ts';\nimport { sendBackPatch } from './sendBack.ts';\nimport { DEFAULT_PREVIEW, Previews, parsePreviewPatch } from './previews.ts';\nimport { PREVIEW_SLUG } from './previewRunner.ts';\nimport { ceoPromptPreview, devBranch, devPromptPreview, devSystemPrompt, qaBranch, qaPromptPreview, qaSystemPrompt } from './prompts.ts';\nimport { drainDecision, lastUpdateMessage, POSTPONE_MS, type DrainInput, type LastUpdate } from './officeUpdate.ts';\nimport { clampPacingSessions, DEFAULT_PACING_SESSIONS, mayStart, PACING_MS, pacingMessage, usageLabel, usageView, type UsageWarning, type WorkKind } from './pacing.ts';\nimport { isCli } from './clis.ts';\nimport { AgentTerminal } from './terminal.ts';\nimport { DEFAULT_VOICE, Voice, voiceSettings } from './voice.ts';\nimport { blockers, holdUps, issueSpecialty } from '../shared/issues.ts';\nimport { effectiveModel } from '../shared/models.ts';\nimport { CEO_ID, INSTALL_STEP } from '../shared/types.ts';\nimport type {\n AgentCli,\n AgentLook,\n AgentPromptView,\n AgentRole,\n AgentStatus,\n AgentTask,\n AgentView,\n CeoInfo,\n CliView,\n EffortLevel,\n HireRequestView,\n IssueInfo,\n LogLine,\n OfficeUpdateView,\n PhoneMessage,\n PreviewConfig,\n PreviewView,\n ProjectFolderView,\n PullInfo,\n QaCheck,\n QaView,\n RepoView,\n ServerEvent,\n SwarmSettings,\n WorldSnapshot,\n} from '../shared/types.ts';\n\n// ---------- persisted shape ----------\n\ninterface PersistedRepo {\n id: string;\n fullName: string;\n description: string;\n url: string;\n defaultBranch: string;\n floor: number;\n color: string;\n autoAssign: boolean;\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\n browserTesting: boolean;\n links: string[]; // other connected repos this floor's agents may read\n localPath: string | null; // the manager's own project folder (null: a clone under WORKSPACE_ROOT)\n mission: string;\n summary: string;\n qaBrief: string;\n preview: PreviewConfig; // how the floor's app runs for the preview monitor\n addedAt: number;\n}\n\ninterface PersistedAgent {\n id: string;\n name: string;\n repoId: string; // '' for the CEO, who works in the lobby\n role: AgentRole;\n title: string;\n specialty: string;\n brief: string;\n hiredBy: 'manager' | 'ceo';\n look: AgentLook;\n task: AgentTask | null;\n desk: number;\n color: string;\n hair: string;\n skin: string;\n model: string;\n effort: EffortLevel | '';\n cli: AgentCli | ''; // '' = the office's default CLI\n status: AgentStatus;\n issueNumber: number | null;\n issueTitle: string | null;\n branch: string | null;\n prNumber: number | null;\n prUrl: string | null;\n startedAt: number | null;\n endedAt: number | null;\n costUsd: number;\n turns: number;\n sessionId: string | null;\n sessionCli: AgentCli | null; // the CLI whose session sessionId is: only it can resume it\n lastError: string | null;\n logTail: LogLine[];\n}\n\n/** A pull request's trip through QA. */\ninterface QaRecord extends QaView {\n issueNumber: number | null;\n devSessionId: string | null; // the dev's Claude Code session, resumed to fix QA findings\n fixInstructions: string | null;\n sessionFailures: number;\n testedSha: string | null; // the head commit QA is testing\n passedSha: string | null; // the head commit QA signed off on: auto-merge merges exactly that\n fixReason: 'qa' | 'checks' | 'conflict' | null; // why it was last sent back to a developer\n mergeFixes: number; // times it went back for failing checks or conflicts\n retests: number; // QA rounds caused by merge fixes or new commits rather than by QA failing it\n pendingSince: number | null; // when auto-merge started waiting on its checks\n mergeRetryAt: number | null; // GitHub refused the merge: try again after this\n alerted: boolean; // the manager has been told it's stuck\n}\n\n/** Choices made when a project moves into the office. */\ninterface FloorOptions {\n mission?: string; // brief for the CEO to plan from\n autoAssign?: boolean; // free developers pick up backlog issues as soon as they're filed\n}\n\ninterface CeoState {\n queue: CeoJob[];\n job: CeoJob | null; // the job the CEO is on right now\n lastReviewAt: number | null;\n lastFingerprint: string | null; // company state at the last review; unchanged means the next review is skipped\n}\n\ninterface Persisted {\n settings: SwarmSettings;\n repos: PersistedRepo[];\n agents: PersistedAgent[];\n qa: QaRecord[];\n requests: HireRequestView[];\n ceo: CeoState;\n messages: PhoneMessage[];\n phoneReadAt: number;\n}\n\ninterface Shot {\n data: Buffer;\n mime: string;\n url: string | null;\n at: number;\n}\n\ninterface AgentRuntime {\n log: LogLine[];\n pending: LogLine[];\n session: SessionHandle | null;\n currentTool: string | null;\n browserUrl: string | null;\n screenshot: { data: Buffer; mime: string; at: number } | null;\n shots: Shot[]; // every screenshot of the current session (QA evidence)\n terminal: AgentTerminal | null; // their terminal, once they've run in the terminal runtime\n}\n\ninterface RepoRuntime {\n issues: IssueInfo[];\n pulls: PullInfo[];\n lastSync: number | null;\n syncError?: string;\n syncing: boolean;\n cloneStatus: RepoView['cloneStatus'];\n cloneError?: string;\n fetchedAt?: number; // when the latest issues/PRs fetch started\n lastMergedAt: string | null; // newest merge seen: a newer one means the folder needs a sync\n folderSync: string | null;\n merging: boolean;\n}\n\ninterface QaReport {\n verdict: 'pass' | 'fail';\n summary: string;\n checks: QaCheck[];\n commands: { command: string; result: string }[];\n screenshots: string[];\n fixInstructions?: string;\n}\n\n// ---------- flavour ----------\n\nconst FLOOR_COLORS = ['#ff8a5b', '#4fb3e8', '#8fd14f', '#c77dff', '#ffc93c', '#ff6fb5', '#2ec4b6', '#f25f5c'];\nconst SHIRTS = ['#e63946', '#457b9d', '#2a9d8f', '#f4a261', '#9b5de5', '#f15bb5', '#00bbf9', '#06d6a0', '#ffbe0b', '#8338ec', '#fb5607', '#3a86ff'];\nconst HAIR = ['#2b2118', '#6b4226', '#c68642', '#f2d16b', '#d94f30', '#1c1c1c', '#8e8e8e', '#5b3cc4', '#e76f51'];\nconst SKIN = ['#ffdbac', '#f1c27d', '#e0ac69', '#c68642', '#8d5524', '#ffe0bd'];\nconst DEV_NAMES = [\n 'Ada', 'Linus', 'Grace', 'Alan', 'Margaret', 'Dennis', 'Barbara', 'Ken', 'Radia', 'Guido', 'Hedy', 'Tim', 'Katherine',\n 'Bjarne', 'Frances', 'Edsger', 'Anita', 'Donald', 'Sophie', 'Yukihiro', 'Jean', 'Niklaus', 'Karen', 'Brendan',\n];\nconst QA_NAMES = ['Sherlock', 'Marple', 'Poirot', 'Nancy', 'Columbo', 'Fletcher', 'Watson', 'Morse', 'Holmes', 'Maigret'];\n\n// Names that get the feminine character look: everyone in the name pools above, plus common first names\n// for agents the manager names themselves. The manager can always change an agent's look in the console.\nconst FEMININE_NAMES = new Set(\n (\n 'ada grace margaret barbara radia hedy katherine frances anita sophie jean karen marple nancy fletcher ' +\n 'alice amanda amelia amy ana anna anne aisha astrid ava bella beth carla caroline charlotte chloe claire clara ' +\n 'diana elena elizabeth ella ellie emily emma eva fatima fiona freya georgia hannah harper helen holly ingrid iris ' +\n 'isabella ivy jane jasmine jessica julia kate laura leah leila lena lily linda lisa lucy maria marie mary maya mei ' +\n 'mia mila monica naomi natalie nina nora olivia paula priya rachel rose ruby sandra sara sarah scarlett sofia ' +\n 'stella susan tess tessa tina vera victoria yuki zara zoe'\n ).split(' '),\n);\nconst lookFor = (name: string): AgentLook => (FEMININE_NAMES.has(name.trim().split(/\\s+/)[0].toLowerCase()) ? 'feminine' : 'masculine');\nconst LOOKS: AgentLook[] = ['feminine', 'masculine'];\nconst MAX_DESKS: Record<AgentRole, number> = { ...FLOOR_DESKS, ceo: 1 };\n// Every agent runs Claude Opus 5.5 at medium effort unless the manager overrides it.\nconst DEFAULT_MODEL = 'claude-opus-5-5';\nconst EFFORTS: EffortLevel[] = ['low', 'medium', 'high', 'xhigh', 'max'];\n// The CEO thinks harder than the staff: Opus 5.5 at xhigh effort unless the manager changes it.\nconst CEO_MODEL = 'claude-opus-5-5';\nconst CEO_EFFORT: EffortLevel = 'xhigh';\nconst CEO_NAME = 'Morgan';\n// The CEO's own folder: its notes about the company live here. Repos are read through their clones.\nconst CEO_DIR = path.join(HOME_DIR, 'ceo');\nconst DEFAULT_PROJECTS_DIR = defaultProjectsDir(path.resolve(import.meta.dirname, '..'));\nconst MAX_ISSUES_PER_JOB = 12;\nconst KEEP_MESSAGES = 200;\nconst KEEP_DECIDED_REQUESTS = 40;\n\nconst pick = <T>(arr: T[]) => arr[Math.floor(Math.random() * arr.length)];\nconst slugify = (s: string) =>\n s\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 40) || 'agent';\n\nconst BUSY: AgentStatus[] = ['preparing', 'working'];\nconst FREE: AgentStatus[] = ['idle', 'done'];\n// An agent whose session failed sits out this long before taking new work, so a broken setup can't burn through the queue.\nconst ERROR_COOLDOWN_MS = 2 * 60_000;\n// Auto-assign stops retrying an issue after this many failed sessions; the manager can still assign it by hand.\nconst MAX_ISSUE_FAILURES = 2;\n// How long the office waits after Claude's usage limit is hit when Claude doesn't say when it resets.\nconst LIMIT_PAUSE_MS = 15 * 60_000;\nconst oneLine = (err: unknown) => (err instanceof Error ? err.message : String(err)).split(/\\r?\\n/)[0].slice(0, 200);\n\n// The latest browser screenshot per agent is kept on disk so monitors survive a server restart.\nconst SCREENS_DIR = path.join(HOME_DIR, 'screens');\nconst MIME_EXT: Record<string, string> = { 'image/png': 'png', 'image/jpeg': 'jpg', 'image/webp': 'webp', 'image/svg+xml': 'svg' };\nconst screenFile = (agentId: string, mime: string) => path.join(SCREENS_DIR, `${agentId}.${MIME_EXT[mime] ?? 'img'}`);\n\nasync function loadScreen(agentId: string): Promise<{ data: Buffer; mime: string; at: number } | null> {\n for (const [mime, ext] of Object.entries(MIME_EXT)) {\n const file = path.join(SCREENS_DIR, `${agentId}.${ext}`);\n try {\n const [data, stat] = await Promise.all([fs.readFile(file), fs.stat(file)]);\n return { data, mime, at: stat.mtimeMs };\n } catch {\n // try the next extension\n }\n }\n return null;\n}\n\nasync function removeScreens(agentId: string) {\n await Promise.all(Object.values(MIME_EXT).map((ext) => fs.rm(path.join(SCREENS_DIR, `${agentId}.${ext}`), { force: true })));\n}\n\n// Each agent's terminal (screen and scrollback) is saved too, so the office shows what they did after a restart.\nconst TERMINALS_DIR = path.join(HOME_DIR, 'terminals');\nconst terminalFile = (agentId: string) => path.join(TERMINALS_DIR, `${agentId}.ansi`);\nconst TERMINAL_SAVE_MS = 20_000;\n\n// ---------- QA report ----------\n\nconst QA_SCHEMA: Record<string, unknown> = {\n type: 'object',\n additionalProperties: false,\n required: ['verdict', 'summary', 'checks', 'commands', 'screenshots'],\n properties: {\n verdict: { type: 'string', enum: ['pass', 'fail'], description: 'pass only if the change works and meets the issue requirements' },\n summary: { type: 'string', description: 'Two to four sentences for the pull request comment.' },\n checks: {\n type: 'array',\n description: 'Each acceptance criterion, test run or scenario you verified.',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'result', 'details'],\n properties: {\n name: { type: 'string' },\n result: { type: 'string', enum: ['pass', 'fail', 'skip'] },\n details: { type: 'string', description: 'What you did and what you observed.' },\n },\n },\n },\n commands: {\n type: 'array',\n description: 'Test suites, linters, builds and other commands you ran.',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['command', 'result'],\n properties: { command: { type: 'string' }, result: { type: 'string', description: 'e.g. \"42 passed, 0 failed\"' } },\n },\n },\n screenshots: {\n type: 'array',\n description: 'One short caption per screenshot you took with browser_take_screenshot, in the order you took them.',\n items: { type: 'string' },\n },\n fixInstructions: { type: 'string', description: 'When the verdict is fail: precise, actionable instructions for the developer.' },\n },\n};\n\nfunction parseReport(result: SessionResult): QaReport | null {\n let raw: unknown = result.structured;\n if (!raw && result.text) {\n // Terminal agents end their last message with the report, usually in a ```json block.\n const fenced = [...result.text.matchAll(/```(?:json)?\\s*(\\{[\\s\\S]*?\\})\\s*```/g)].map((m) => m[1]).reverse();\n for (const json of [...fenced, result.text.match(/\\{[\\s\\S]*\\}/)?.[0]].filter((j): j is string => !!j)) {\n try {\n raw = JSON.parse(json);\n break;\n } catch {\n raw = null;\n }\n }\n }\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Partial<QaReport>;\n if (r.verdict !== 'pass' && r.verdict !== 'fail') return null;\n return {\n verdict: r.verdict,\n summary: String(r.summary ?? ''),\n checks: Array.isArray(r.checks) ? r.checks.map((c) => ({ name: String(c.name ?? ''), result: c.result === 'fail' ? 'fail' : c.result === 'skip' ? 'skip' : 'pass', details: String(c.details ?? '') })) : [],\n commands: Array.isArray(r.commands) ? r.commands.map((c) => ({ command: String(c.command ?? ''), result: String(c.result ?? '') })) : [],\n screenshots: Array.isArray(r.screenshots) ? r.screenshots.map(String) : [],\n fixInstructions: r.fixInstructions ? String(r.fixInstructions) : undefined,\n };\n}\n\nconst cell = (s: string) => s.replace(/\\|/g, '\\\\|').replace(/\\r?\\n/g, '<br>');\nconst ICON = { pass: '\u2705', fail: '\u274C', skip: '\u23ED\uFE0F' } as const;\n\nexport { HttpError };\n\nexport class Swarm {\n private state: Persisted = {\n settings: {\n sessionLimit: 0,\n defaultModel: DEFAULT_MODEL,\n defaultEffort: 'medium',\n runtime: 'terminal',\n defaultCli: 'claude',\n hiring: 'approve',\n teamCap: 6,\n ceoHeartbeatMin: 60,\n managerName: '',\n companyName: '',\n projectsDir: DEFAULT_PROJECTS_DIR,\n setupDone: false,\n tutorialStep: 0,\n autoUpdate: true,\n pacingSessions: DEFAULT_PACING_SESSIONS,\n voice: { ...DEFAULT_VOICE },\n },\n repos: [],\n agents: [],\n qa: [],\n requests: [],\n ceo: { queue: [], job: null, lastReviewAt: null, lastFingerprint: null },\n messages: [],\n phoneReadAt: 0,\n };\n /**\n * The CEO's office tools. Every session gets its own server: one can only be connected to one session at a time, so\n * a shared one left the next session connected but without any tools while an earlier session still held it.\n */\n private officeTools(): OfficeTools {\n return createOfficeTools({\n companyStatus: () => this.companyStatus(),\n agentDetail: (a) => this.agentDetail(a),\n setFloorProfile: (a) => this.setFloorProfile(a),\n updateJob: (a) => this.updateJob(a),\n proposeHire: (a) => this.proposeHire(a),\n proposeLetGo: (a) => this.proposeLetGo(a),\n fileIssue: (a) => this.fileIssue(a),\n routeIssue: (a) => this.routeIssue(a),\n });\n }\n private ceoIssues = new IssueCap(MAX_ISSUES_PER_JOB); // issues filed during the current CEO job\n private messageSeq = 1;\n private agentRt = new Map<string, AgentRuntime>();\n private repoRt = new Map<string, RepoRuntime>();\n private deskAlerts = new Map<string, string>(); // agent id -> the desk setup error the manager was last told about\n private clients = new Set<WebSocket>();\n private user: string | null = null;\n private ghError: string | undefined;\n private saveTimer: NodeJS.Timeout | null = null;\n private flushTimer: NodeJS.Timeout | null = null;\n private logSeq = 1;\n private previews: Previews;\n private officeHead: string | null = null; // the commit the office runs (null: not a git checkout, so no self-update)\n private officeUpdate = {\n behind: 0,\n requested: false,\n postponedUntil: null as number | null,\n postponedBehind: 0,\n failed: null as string | null,\n failedBehind: null as number | null,\n drainingSince: null as number | null,\n sent: false,\n handedOver: false, // sessions cut off by the hand-over are the restarted office's to recover\n };\n private lastOfficeView = '';\n private clis: CliView[] = []; // coding-agent CLIs found on this machine (detected at startup)\n /** Phone messages read aloud. The demo keeps its own key and clips, so it never touches the real ones. */\n readonly voice: Voice;\n\n constructor(private backend: Backend) {\n this.voice = new Voice({\n api: backend.voice,\n secretsFile: path.join(HOME_DIR, backend.demo ? 'demo-secrets.json' : 'secrets.json'),\n cacheDir: path.join(HOME_DIR, backend.demo ? 'demo-voice' : 'voice'),\n settings: () => this.state.settings.voice,\n message: (id) => this.state.messages.find((m) => m.id === id),\n officeNote: (text) => this.postMessage('office', text),\n keyChanged: (view) => this.broadcast({ type: 'voiceKey', ...view }),\n });\n this.previews = new Previews(backend, {\n emit: (id) => {\n const r = this.state.repos.find((x) => x.id === id);\n if (r && this.repoRt.has(id)) this.emitRepo(r);\n },\n pulls: (id) => this.repoRt.get(id)?.pulls ?? [],\n });\n }\n\n // ---------- lifecycle ----------\n\n async init() {\n try {\n const raw = await fs.readFile(STATE_FILE, 'utf8');\n const loaded = JSON.parse(raw) as Partial<Persisted>;\n this.state = {\n settings: { ...this.state.settings, ...loaded.settings },\n repos: (loaded.repos ?? []).map((r) => ({\n ...r,\n autoMerge: r.autoMerge ?? true,\n links: r.links ?? [],\n mission: r.mission ?? '',\n summary: r.summary ?? '',\n qaBrief: r.qaBrief ?? '',\n localPath: r.localPath ?? null,\n preview: { command: r.preview?.command ?? null, env: { ...r.preview?.env } },\n })),\n agents: (loaded.agents ?? []).map((a) => ({\n ...a,\n effort: a.effort ?? '',\n role: a.role ?? 'dev',\n title: a.title ?? '',\n specialty: a.specialty ?? '',\n brief: a.brief ?? '',\n hiredBy: a.hiredBy ?? 'manager',\n look: a.look ?? lookFor(a.name),\n task: a.task ?? (a.issueNumber ? 'issue' : null),\n cli: isCli(a.cli) ? a.cli : '',\n sessionCli: a.sessionCli ?? (a.sessionId ? 'claude' : null),\n })),\n qa: (loaded.qa ?? []).map((q) => ({\n ...q,\n testedSha: q.testedSha ?? null,\n passedSha: q.passedSha ?? null,\n fixReason: q.fixReason ?? null,\n mergeFixes: q.mergeFixes ?? 0,\n retests: q.retests ?? 0,\n pendingSince: q.pendingSince ?? null,\n mergeRetryAt: q.mergeRetryAt ?? null,\n alerted: q.alerted ?? false,\n mergeNote: null,\n })),\n requests: loaded.requests ?? [],\n ceo: { ...this.state.ceo, ...loaded.ceo },\n messages: loaded.messages ?? [],\n phoneReadAt: loaded.phoneReadAt ?? 0,\n };\n for (const m of this.state.messages) this.messageSeq = Math.max(this.messageSeq, m.id + 1);\n if (!EFFORTS.includes(this.state.settings.defaultEffort)) this.state.settings.defaultEffort = 'medium';\n if (this.state.settings.runtime !== 'sdk') this.state.settings.runtime = 'terminal';\n if (!isCli(this.state.settings.defaultCli)) this.state.settings.defaultCli = 'claude';\n if (!this.state.settings.defaultModel && this.state.settings.defaultCli === 'claude') this.state.settings.defaultModel = DEFAULT_MODEL;\n // \"Max concurrent sessions\" (default 4) became an optional session limit. The old default goes; a limit the manager chose stays.\n const old = this.state.settings as SwarmSettings & { maxConcurrent?: number; permissionMode?: string };\n if (old.maxConcurrent !== undefined) {\n if (loaded.settings?.sessionLimit === undefined) old.sessionLimit = old.maxConcurrent === 4 ? 0 : old.maxConcurrent;\n delete old.maxConcurrent;\n }\n delete old.permissionMode; // the office's rules are instructions now, not a permission mode\n this.state.settings.voice = voiceSettings(DEFAULT_VOICE, loaded.settings?.voice);\n // Offices that were set up before the setup wizard existed skip it.\n if (loaded.settings && loaded.settings.setupDone === undefined && this.state.repos.length > 0) {\n Object.assign(this.state.settings, { setupDone: true, tutorialStep: -1 });\n }\n } catch {\n // first run\n }\n await this.voice.init();\n for (const r of this.state.repos) if (r.localPath) this.backend.setLocalPath(r.fullName, r.localPath);\n const interrupted: PersistedAgent[] = [];\n for (const a of this.state.agents) {\n const tail = a.logTail ?? [];\n for (const l of tail) this.logSeq = Math.max(this.logSeq, l.id + 1);\n this.agentRt.set(a.id, { log: tail, pending: [], session: null, currentTool: null, browserUrl: null, screenshot: await loadScreen(a.id), shots: [], terminal: await this.loadTerminal(a.id) });\n }\n // CLIs the terminal keeper kept running through the restart go back into their terminals, and busy ones carry on.\n // (The CEO's session is resumed instead: its office tools live in this process.)\n const back = await this.backend\n .reconnectClis((id) => {\n const a = this.state.agents.find((x) => x.id === id);\n return a && a.role !== 'ceo' ? this.terminalFor(a) : null;\n })\n .catch((err) => {\n console.warn('could not reconnect to the terminal keeper', err);\n return [];\n });\n const carryOn: PersistedAgent[] = [];\n const preparing = new Set<PersistedAgent>(); // their task's session hadn't started: nothing of it to resume\n for (const a of this.state.agents) {\n if (!BUSY.includes(a.status)) continue;\n if (followKeptCli(a, back.find((c) => c.agentId === a.id))) {\n carryOn.push(a);\n continue;\n }\n if (a.status === 'preparing') preparing.add(a);\n a.status = 'stopped';\n a.lastError = 'The swarm server restarted while this agent was working.';\n interrupted.push(a);\n }\n for (const c of back) if (c.busy && !carryOn.some((a) => a.id === c.agentId)) this.agentRt.get(c.agentId)?.terminal?.releaseIdle?.();\n for (const r of this.state.repos) this.repoRt.set(r.id, { issues: [], pulls: [], lastSync: null, syncing: false, cloneStatus: 'pending', lastMergedAt: null, folderSync: null, merging: false });\n for (const a of carryOn) this.reattachSession(a);\n this.backend.hooksReady();\n\n try {\n this.user = await this.backend.user();\n } catch (err) {\n this.ghError = `GitHub CLI is not ready: ${(err as Error).message}. Run \"gh auth login\".`;\n console.warn(this.ghError);\n }\n\n if (this.backend.demo && this.state.repos.length === 0) {\n // The demo opens on a busy office; the tutorial still runs so it can be tried.\n Object.assign(this.state.settings, { setupDone: true, managerName: 'Demo Manager', companyName: 'Demo Co.' });\n for (const r of await this.backend.listMyRepos()) {\n const repo = await this.connectRepo(r.nameWithOwner);\n for (let i = 0; i < (repo.floor === 1 ? 5 : 3); i++) this.hireAgent(repo.id, {});\n this.updateRepo(repo.id, { autoAssign: true });\n }\n }\n for (const r of this.state.repos) this.ensureQaTester(r);\n this.ensureCeo(interrupted);\n\n for (const r of this.state.repos) void this.cloneRepo(r.id);\n await Promise.all(this.state.repos.map((r) => this.syncRepo(r.id)));\n // Anything still alive in a desk (or a preview) is left over from before the restart, except around the CLIs that\n // kept running through it: their dev servers and commands are theirs.\n await Promise.all([\n ...this.state.agents.map((a) => {\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n if (!repo || back.some((c) => c.agentId === a.id)) return undefined;\n return this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined);\n }),\n this.previews.clearOrphans(this.state.repos),\n ]);\n for (const r of this.state.repos) void this.previews.refreshDefault(r);\n this.recover(interrupted, preparing);\n // A PR the restart left in \"testing\" with nobody on it: test it again (the result, if any, was lost).\n for (const rec of orphanedQa(this.state.qa, this.state.agents, BUSY)) this.setQa(rec, { status: 'queued', qaAgentId: null });\n this.officeHead = await this.backend.office.head();\n const updated = await this.backend.office.takeLastUpdate().catch(() => null);\n if (updated) await this.reportUpdate(updated);\n setInterval(() => this.state.repos.forEach((r, i) => setTimeout(() => void this.syncRepo(r.id), i * 1500)), SYNC_INTERVAL_MS);\n setInterval(() => this.schedule(), SCHEDULER_INTERVAL_MS);\n setInterval(() => void this.saveTerminals(), TERMINAL_SAVE_MS);\n setInterval(() => this.state.repos.forEach((r, i) => setTimeout(() => void this.sweepFloor(r.id), i * 1500)), DESK_SWEEP_INTERVAL_MS);\n void this.backend\n .detectClis()\n .then((clis) => {\n this.clis = clis;\n this.broadcast({ type: 'clis', clis });\n })\n .catch((err) => console.warn('could not look for agent CLIs', err));\n this.save();\n setTimeout(() => this.schedule(), 1000);\n }\n\n /**\n * Agents cut off by a server restart pick their session back up, told what they were doing. QA, demo agents and\n * tasks still being prepared start over from the queue.\n */\n private recover(agents: PersistedAgent[], preparing: Set<PersistedAgent>) {\n for (const a of agents) {\n const fix = a.task === 'fix' ? this.state.qa.find((q) => q.devAgentId === a.id && q.status === 'fixing') : undefined;\n if (!resumesAfterRestart(a, preparing.has(a), this.backend.demo)) {\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Starting over from the queue.' }]);\n const rec = a.task === 'qa' ? this.state.qa.find((q) => q.qaAgentId === a.id && q.status === 'testing') : undefined;\n if (rec) this.setQa(rec, { status: 'queued' });\n if (fix) this.setQa(fix, { status: 'failed' });\n this.clearTask(a);\n continue;\n }\n if (this.slotsFull()) continue; // stays 'stopped'; the manager can resume it later\n void this.message(a.id, resumeNote(a, fix)).catch((err) => console.warn(`could not resume ${a.name}`, err));\n }\n }\n\n // ---------- views ----------\n\n private repoView(r: PersistedRepo): RepoView {\n const rt = this.repoRt.get(r.id)!;\n return {\n id: r.id,\n fullName: r.fullName,\n description: r.description,\n url: r.url,\n defaultBranch: r.defaultBranch,\n floor: r.floor,\n color: r.color,\n autoAssign: r.autoAssign,\n autoMerge: r.autoMerge,\n folderSync: rt.folderSync,\n browserTesting: r.browserTesting,\n links: r.links,\n mission: r.mission,\n summary: r.summary,\n qaBrief: r.qaBrief,\n localPath: r.localPath,\n checkoutPath: this.backend.mainDir(r.fullName),\n cloneStatus: rt.cloneStatus,\n cloneError: rt.cloneError,\n issues: rt.issues,\n pulls: rt.pulls,\n lastSync: rt.lastSync,\n syncError: rt.syncError,\n previewConfig: r.preview,\n preview: this.previews.view(r),\n };\n }\n\n private agentView(a: PersistedAgent, withLog: boolean): AgentView {\n const rt = this.agentRt.get(a.id)!;\n return {\n id: a.id,\n name: a.name,\n repoId: a.repoId,\n role: a.role,\n title: a.title,\n specialty: a.specialty,\n brief: a.brief,\n hiredBy: a.hiredBy,\n look: a.look,\n task: a.task,\n desk: a.desk,\n color: a.color,\n hair: a.hair,\n skin: a.skin,\n model: a.model,\n effort: a.effort,\n cli: a.cli,\n terminal: !!rt.terminal,\n status: a.status,\n issueNumber: a.issueNumber,\n issueTitle: a.issueTitle,\n branch: a.branch,\n prNumber: a.prNumber,\n prUrl: a.prUrl,\n currentTool: rt.currentTool,\n startedAt: a.startedAt,\n endedAt: a.endedAt,\n costUsd: a.costUsd,\n turns: a.turns,\n browserUrl: rt.browserUrl,\n hasScreenshot: !!rt.screenshot,\n screenshotAt: rt.screenshot?.at ?? null,\n lastError: a.lastError,\n log: withLog ? rt.log : [],\n };\n }\n\n private qaView(q: QaRecord): QaView {\n return {\n repoId: q.repoId,\n prNumber: q.prNumber,\n status: q.status,\n round: q.round,\n devAgentId: q.devAgentId,\n qaAgentId: q.qaAgentId,\n summary: q.summary,\n checks: q.checks,\n commentUrl: q.commentUrl,\n mergeNote: q.mergeNote,\n updatedAt: q.updatedAt,\n };\n }\n\n snapshot(): WorldSnapshot {\n return {\n user: this.user,\n ghReady: !this.ghError,\n ghError: this.ghError,\n demo: this.backend.demo,\n workspaceRoot: WORKSPACE_ROOT,\n settings: this.state.settings,\n repos: this.state.repos.map((r) => this.repoView(r)),\n agents: this.state.agents.map((a) => this.agentView(a, true)),\n qa: this.state.qa.map((q) => this.qaView(q)),\n requests: this.state.requests,\n ceo: this.ceoInfo(),\n messages: this.state.messages.slice(-100),\n phoneReadAt: this.state.phoneReadAt,\n usage: this.usageNow(),\n clis: this.clis,\n ...this.voice.keyView(),\n officeCommit: this.officeHead?.slice(0, 7) ?? null,\n officeUpdate: this.officeHead ? this.officeUpdateView() : undefined,\n };\n }\n\n /** The agent's latest screenshot: null when it has none right now, undefined for an unknown agent. */\n screenshot(agentId: string) {\n const rt = this.agentRt.get(agentId);\n return rt ? rt.screenshot : undefined;\n }\n\n // ---------- clients ----------\n\n addClient(ws: WebSocket) {\n this.clients.add(ws);\n ws.on('close', () => this.clients.delete(ws));\n this.send(ws, { type: 'snapshot', data: this.snapshot() });\n }\n\n private send(ws: WebSocket, ev: ServerEvent) {\n if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(ev));\n }\n\n private broadcast(ev: ServerEvent) {\n const msg = JSON.stringify(ev);\n for (const ws of this.clients) if (ws.readyState === ws.OPEN) ws.send(msg);\n }\n\n private toast(level: 'info' | 'success' | 'error', text: string) {\n this.broadcast({ type: 'toast', level, text });\n }\n\n private emitRepo(r: PersistedRepo) {\n this.broadcast({ type: 'repo', repo: this.repoView(r) });\n }\n\n private emitAgent(a: PersistedAgent) {\n // A session can finish after its agent was let go (their floor disconnected mid-task); they're gone, so say nothing.\n if (!this.agentRt.has(a.id)) return;\n const { log: _log, ...rest } = this.agentView(a, false);\n this.broadcast({ type: 'agent', agent: rest });\n }\n\n private setQa(rec: QaRecord, patch: Partial<QaRecord>) {\n Object.assign(rec, patch, { updatedAt: Date.now() });\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\n this.save();\n }\n\n private appendLog(a: PersistedAgent, entries: LogEntry[]) {\n const rt = this.agentRt.get(a.id);\n if (!rt) return;\n const t = Date.now();\n for (const e of entries) {\n const line: LogLine = { id: this.logSeq++, t, kind: e.kind, text: e.text, tool: e.tool };\n rt.log.push(line);\n rt.pending.push(line);\n }\n if (rt.log.length > LOG_BUFFER) rt.log.splice(0, rt.log.length - LOG_BUFFER);\n if (!this.flushTimer) this.flushTimer = setTimeout(() => this.flushLogs(), 120);\n }\n\n private flushLogs() {\n this.flushTimer = null;\n for (const [agentId, rt] of this.agentRt) {\n if (rt.pending.length === 0) continue;\n this.broadcast({ type: 'log', agentId, lines: rt.pending });\n rt.pending = [];\n }\n this.save();\n }\n\n // ---------- persistence ----------\n\n private save() {\n if (this.saveTimer) return;\n this.saveTimer = setTimeout(() => void this.writeState().catch((err) => console.warn('could not save the state', err)), 1500);\n }\n\n /** Write the state file now, e.g. before the office stops or hands itself to the launcher. */\n private async writeState() {\n if (this.saveTimer) clearTimeout(this.saveTimer);\n this.saveTimer = null;\n for (const a of this.state.agents) a.logTail = (this.agentRt.get(a.id)?.log ?? []).slice(-200);\n await fs.mkdir(path.dirname(STATE_FILE), { recursive: true });\n const tmp = `${STATE_FILE}.tmp`;\n await fs.writeFile(tmp, JSON.stringify(this.state, null, 2));\n await fs.rename(tmp, STATE_FILE);\n }\n\n // ---------- lookups ----------\n\n private repo(id: string) {\n const r = this.state.repos.find((x) => x.id === id);\n if (!r) throw new HttpError(404, `Repo ${id} is not connected`);\n return r;\n }\n\n private agent(id: string) {\n const a = this.state.agents.find((x) => x.id === id);\n if (!a) throw new HttpError(404, `No agent ${id}`);\n return a;\n }\n\n private running() {\n return this.state.agents.filter((a) => BUSY.includes(a.status)).length;\n }\n\n /** True when the manager has set a session limit and every slot is taken. */\n private slotsFull() {\n const limit = this.state.settings.sessionLimit;\n return limit > 0 && this.running() >= limit;\n }\n\n private agentSlug(a: PersistedAgent) {\n return `${slugify(a.name)}-${a.id.slice(0, 4)}`;\n }\n\n private clearTask(a: PersistedAgent) {\n Object.assign(a, { status: 'idle', task: null, issueNumber: null, issueTitle: null, branch: null, prNumber: null, prUrl: null, lastError: null });\n this.emitAgent(a);\n }\n\n // ---------- GitHub / repos ----------\n\n listGithubRepos(owner?: string) {\n return this.backend.listMyRepos(owner);\n }\n\n /**\n * Give a GitHub repo a floor. Its main checkout is one of your own folders: the one you picked, else the folder in\n * your projects folder that already has it as origin, else a fresh clone into your projects folder.\n */\n async connectRepo(fullName: string, opts: FloorOptions & { localPath?: string } = {}): Promise<RepoView> {\n const existing = this.state.repos.find((r) => r.id.toLowerCase() === fullName.toLowerCase());\n if (existing) throw new HttpError(409, `${fullName} is already floor ${existing.floor}`);\n const meta = await this.backend.repoMeta(fullName);\n const folder = opts.localPath ?? (await this.projectFolderFor(meta.nameWithOwner));\n const floor = this.state.repos.reduce((m, r) => Math.max(m, r.floor), 0) + 1;\n const repo: PersistedRepo = {\n id: meta.nameWithOwner,\n fullName: meta.nameWithOwner,\n description: meta.description,\n url: meta.url,\n defaultBranch: meta.defaultBranch,\n floor,\n color: FLOOR_COLORS[(floor - 1) % FLOOR_COLORS.length],\n autoAssign: !!opts.autoAssign,\n autoMerge: true,\n browserTesting: true,\n links: [],\n localPath: folder,\n mission: (opts.mission ?? '').trim().slice(0, 4000),\n summary: '',\n qaBrief: '',\n preview: { ...DEFAULT_PREVIEW, env: {} },\n addedAt: Date.now(),\n };\n this.backend.setLocalPath(repo.fullName, folder);\n this.state.repos.push(repo);\n this.repoRt.set(repo.id, { issues: [], pulls: [], lastSync: null, syncing: false, cloneStatus: 'pending', lastMergedAt: null, folderSync: null, merging: false });\n this.save();\n this.emitRepo(repo);\n this.toast('success', `${repo.fullName} moved into floor ${floor}`);\n this.ensureQaTester(repo);\n void this.cloneRepo(repo.id);\n void this.syncRepo(repo.id);\n // The CEO studies every new floor and proposes the team it needs.\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\n return this.repoView(repo);\n }\n\n /** Where a GitHub repo's checkout goes when you connect it without picking a folder. */\n private async projectFolderFor(fullName: string): Promise<string> {\n const root = this.state.settings.projectsDir;\n const folders = await this.backend.scanProjects(root).catch(() => []);\n const match = folders.find((f) => f.github?.toLowerCase() === fullName.toLowerCase());\n if (match) return match.path;\n const name = fullName.split('/')[1];\n const taken = folders.find((f) => f.name.toLowerCase() === name.toLowerCase());\n if (taken) throw new HttpError(409, `${taken.path} already exists and isn't a clone of ${fullName}. Connect that folder instead, or rename it first.`);\n return path.join(root, name); // cloned there when the floor opens\n }\n\n /** A brand-new project: a folder in your projects folder, pushed to a new GitHub repo. */\n async createRepo(name: string, opts: FloorOptions & { description?: string; visibility: 'private' | 'public'; owner?: string }) {\n if (!/^[A-Za-z0-9._-]+$/.test(name)) throw new HttpError(400, 'Project names may only contain letters, numbers, \".\", \"-\" and \"_\"');\n const created = await this.backend.createProject(this.state.settings.projectsDir, name, opts).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n return this.connectRepo(created.fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: created.path });\n }\n\n /** The folders in your projects folder (or another folder you point at), and which are floors already. */\n async listProjectFolders(dir?: string): Promise<{ root: string; folders: ProjectFolderView[] }> {\n const root = dir?.trim() ? path.resolve(dir.trim()) : this.state.settings.projectsDir;\n const folders = await this.backend.scanProjects(root).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n const same = (a: string, b: string) => path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase();\n const floorOf = (f: { path: string; github: string | null }) =>\n this.state.repos.find((r) => (r.localPath && same(r.localPath, f.path)) || (f.github && r.id.toLowerCase() === f.github.toLowerCase()))?.floor ?? null;\n return { root, folders: folders.map((f) => ({ name: f.name, path: f.path, git: f.git, github: f.github, floor: floorOf(f) })) };\n }\n\n /** Give one of your folders a floor. It must already be on GitHub; otherwise publish it first. */\n async connectFolder(dir: string, opts: FloorOptions = {}) {\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n if (!f.github) throw new HttpError(400, `${f.name} ${f.git ? \"isn't on GitHub yet\" : \"isn't a git repository yet\"}. Publish it to GitHub first.`);\n return this.connectRepo(f.github, { ...opts, localPath: f.path });\n }\n\n /** Put one of your folders on GitHub (only what's committed goes up), then give it a floor. */\n async publishFolder(dir: string, opts: FloorOptions & { name?: string; visibility: 'private' | 'public'; description?: string }) {\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n const name = (opts.name?.trim() || f.name).replace(/[^A-Za-z0-9._-]+/g, '-');\n const fullName = await this.backend.publishFolder(f.path, { name, visibility: opts.visibility, description: opts.description }).catch((err: Error) => {\n throw new HttpError(400, err.message);\n });\n return this.connectRepo(fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: f.path });\n }\n\n disconnectRepo(id: string) {\n const repo = this.repo(id);\n this.state.ceo.queue = this.state.ceo.queue.filter((j) => j.repoId !== id);\n for (const r of this.state.requests.filter((x) => x.repoId === id && x.status === 'pending')) {\n this.decide(r, { status: 'rejected', note: 'The floor was disconnected.', decidedBy: null });\n }\n for (const a of this.state.agents.filter((x) => x.repoId === id)) this.fireAgent(a.id, true);\n void this.previews.remove({ ...repo });\n this.state.repos = this.state.repos.filter((r) => r.id !== id);\n for (const q of this.state.qa.filter((x) => x.repoId === id)) this.broadcast({ type: 'qaRemoved', repoId: id, prNumber: q.prNumber });\n this.state.qa = this.state.qa.filter((q) => q.repoId !== id);\n for (const r of this.state.repos) r.links = r.links.filter((l) => l !== id);\n this.repoRt.delete(id);\n // Keep floors contiguous.\n this.state.repos.sort((a, b) => a.floor - b.floor).forEach((r, i) => (r.floor = i + 1));\n this.backend.setLocalPath(repo.fullName, null);\n this.save();\n this.broadcast({ type: 'repoRemoved', repoId: id });\n for (const r of this.state.repos) this.emitRepo(r);\n this.toast('info', repo.localPath ? `${repo.fullName} left the building. Your folder ${repo.localPath} is untouched.` : `${repo.fullName} disconnected (its clone stays on disk)`);\n }\n\n updateRepo(\n id: string,\n patch: Partial<Pick<PersistedRepo, 'autoAssign' | 'autoMerge' | 'browserTesting' | 'color' | 'links' | 'mission' | 'summary' | 'qaBrief'>> & { previewCommand?: unknown; previewEnv?: unknown },\n ) {\n const repo = this.repo(id);\n const preview = parsePreviewPatch(patch.previewCommand, patch.previewEnv);\n repo.preview = { ...repo.preview, ...preview };\n if (preview.command === null) void this.previews.refreshDefault(repo);\n if (patch.autoAssign !== undefined) repo.autoAssign = !!patch.autoAssign;\n if (patch.autoMerge !== undefined) {\n repo.autoMerge = !!patch.autoMerge;\n if (repo.autoMerge) void this.syncRepo(repo.id);\n }\n if (patch.browserTesting !== undefined) repo.browserTesting = !!patch.browserTesting;\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) repo.color = patch.color;\n if (Array.isArray(patch.links)) repo.links = patch.links.filter((l) => l !== id && this.state.repos.some((r) => r.id === l));\n if (typeof patch.mission === 'string') repo.mission = patch.mission.trim().slice(0, 4000);\n if (typeof patch.summary === 'string') repo.summary = patch.summary.trim().slice(0, 140);\n if (typeof patch.qaBrief === 'string') repo.qaBrief = patch.qaBrief.trim().slice(0, 2500);\n this.save();\n this.emitRepo(repo);\n setTimeout(() => this.schedule(), 200);\n return this.repoView(repo);\n }\n\n // ---------- auto-merge ----------\n\n /**\n * Auto-merge (floors with it on): a swarm PR merges itself once QA has signed off on its latest commit and GitHub's\n * checks are green. Failing checks and merge conflicts go back to a developer; new commits after QA's sign-off send\n * it back to QA. Merging deletes the remote branch, and the floor's folder then fast-forwards (syncRepo sees the merge).\n */\n private async advanceMerges(repo: PersistedRepo) {\n const rt = this.repoRt.get(repo.id);\n if (!rt || !repo.autoMerge || rt.merging) return;\n rt.merging = true;\n let merged = false;\n try {\n for (const rec of this.state.qa.filter((q) => q.repoId === repo.id && q.status === 'passed')) {\n const pr = rt.pulls.find((p) => p.number === rec.prNumber && p.state === 'OPEN');\n if (!pr || !pr.headRefName.startsWith('swarm/')) continue; // people's own PRs are theirs to merge\n // Only act on PR data fetched after the record last changed (a fix may have just pushed).\n if ((rt.fetchedAt ?? 0) < rec.updatedAt) continue;\n try {\n if (await this.advanceMerge(repo, rec, pr)) merged = true;\n } catch (err) {\n console.warn(`auto-merge of ${repo.fullName}#${pr.number} failed`, err);\n this.mergeNote(rec, `auto-merge hit a problem: ${oneLine(err)}`);\n }\n }\n } finally {\n rt.merging = false;\n }\n if (merged) {\n await this.syncRepo(repo.id);\n setTimeout(() => this.schedule(), 200);\n }\n }\n\n /** One step toward merging a QA-passed PR. Returns true when it merged. */\n private async advanceMerge(repo: PersistedRepo, rec: QaRecord, pr: PullInfo): Promise<boolean> {\n let step = mergeStep(pr, rec, Date.now(), { base: repo.defaultBranch });\n if (step.do === 'details') {\n // GitHub works mergeability out lazily and lists often say UNKNOWN; asking about the PR itself gets an answer.\n const d = await this.backend.prDetails(repo.fullName, pr.number);\n pr = { ...pr, headSha: d.headSha, mergeable: d.mergeable, mergeState: d.mergeState };\n step = mergeStep(pr, rec, Date.now(), { base: repo.defaultBranch, detailed: true });\n }\n Object.assign(rec, step.set);\n if (step.do === 'requeue') {\n // Commits arrived after QA's sign-off: they get tested too.\n this.setQa(rec, { status: 'queued', round: rec.round + 1, retests: rec.retests + 1, mergeNote: null, pendingSince: null });\n setTimeout(() => this.schedule(), 200);\n return false;\n }\n if (step.do === 'send-back') return this.sendBack(repo, rec, step.reason, step.instructions, step.needsHuman);\n if (step.do === 'wait') {\n if (step.alert) {\n this.postMessage('office', `\u23F3 PR #${pr.number} on ${repo.fullName} passed QA, but its checks (${pr.pendingChecks.join(', ')}) have been running for over ${CHECKS_ALERT_MS / 60_000} minutes. It merges as soon as they finish.`);\n }\n return step.note === undefined ? false : this.mergeNote(rec, step.note);\n }\n if (step.do === 'update-branch') {\n // The repo only merges up-to-date branches. GitHub merges the base in cleanly (or refuses); CI checks the result.\n this.mergeNote(rec, `updating the branch with ${repo.defaultBranch}`);\n await this.backend.updateBranch(repo.fullName, pr.number);\n const details = await this.backend.prDetails(repo.fullName, pr.number);\n this.setQa(rec, { passedSha: details.headSha });\n return false;\n }\n if (step.do !== 'merge') return false;\n this.mergeNote(rec, 'merging\u2026');\n let error = '';\n for (const method of ['squash', 'merge', 'rebase'] as const) {\n try {\n await this.backend.mergePull(repo.fullName, pr.number, method, rec.passedSha ?? pr.headSha);\n error = '';\n break;\n } catch (err) {\n error = oneLine(err).replace(/^gh .*? failed: /, '');\n if (!/not allowed/i.test(error)) break; // only a merge method the repo turned off is worth another try\n }\n }\n if (error && /head (branch|commit)/i.test(error)) return this.mergeNote(rec, 'new commits arrived; QA checks them first'); // the next sync re-queues it\n if (error) {\n rec.mergeRetryAt = Date.now() + MERGE_RETRY_MS;\n if (!rec.alerted) {\n rec.alerted = true;\n this.postMessage('office', `\u26A0\uFE0F PR #${pr.number} on ${repo.fullName} passed QA and its checks, but GitHub won't merge it: ${error}. The office retries every ${MERGE_RETRY_MS / 60_000} minutes; merge it yourself, or change the repo's merge rules, if it keeps failing.`);\n }\n return this.mergeNote(rec, `merge blocked: ${error}`);\n }\n this.toast('success', `\uD83D\uDD00 Merged PR #${pr.number} into ${repo.defaultBranch}: ${pr.title}`);\n await this.closeResolvedIssues(repo, pr.number, pr);\n return true;\n }\n\n /**\n * After the office merges a PR: close the issues it resolves now rather than waiting for GitHub's \"Closes #N\" (which\n * lags, and never comes when the link wasn't recognised), so the scheduler doesn't hand them out again. Never throws.\n */\n private async closeResolvedIssues(repo: PersistedRepo, prNumber: number, pr: Pick<PullInfo, 'headRefName' | 'closesIssues'>) {\n const numbers = issuesResolvedBy(pr);\n const rt = this.repoRt.get(repo.id);\n if (rt && rt.issues.some((i) => numbers.includes(i.number))) {\n rt.issues = rt.issues.filter((i) => !numbers.includes(i.number));\n this.emitRepo(repo);\n }\n for (const n of numbers) {\n try {\n if ((await this.backend.issueState(repo.fullName, n)) !== 'OPEN') continue;\n await this.backend.closeIssue(repo.fullName, n, `Shipped in #${prNumber}`);\n } catch (err) {\n console.warn(`could not close ${repo.fullName}#${n} after merging #${prNumber}`, err);\n }\n }\n }\n\n /** Show where auto-merge stands on a PR's card. Doesn't count as a change to the record. */\n private mergeNote(rec: QaRecord, text: string | null) {\n if (rec.mergeNote !== text) {\n rec.mergeNote = text;\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\n }\n return false;\n }\n\n /** QA passed, but the PR can't merge as it is: a developer fixes it, and QA re-tests if the code changed. */\n private sendBack(repo: PersistedRepo, rec: QaRecord, reason: 'checks' | 'conflict', fixInstructions: string, needsHuman: boolean) {\n if (needsHuman) {\n this.setQa(rec, { status: 'needs-human', mergeNote: null });\n this.postMessage('office', `\u26A0\uFE0F PR #${rec.prNumber} on ${repo.fullName} still ${reason === 'conflict' ? `conflicts with ${repo.defaultBranch}` : 'fails its checks'} after ${MAX_MERGE_FIXES} fixes, so it needs you.`);\n return false;\n }\n this.setQa(rec, { status: 'failed', fixReason: reason, fixInstructions, mergeFixes: rec.mergeFixes + 1, mergeNote: null, pendingSince: null });\n setTimeout(() => this.schedule(), 200);\n return false;\n }\n\n /** Fast-forward the floor's main checkout (usually your own project folder) and report how it stands. */\n private async syncFolder(repo: PersistedRepo) {\n const rt = this.repoRt.get(repo.id);\n if (!rt || rt.cloneStatus !== 'ready') return rt?.folderSync ?? null;\n const own = this.backend.office.isOwnFolder(this.backend.mainDir(repo.fullName)); // updating the running office restarts it mid-work\n const sync = await this.backend.syncMain(repo.fullName, repo.defaultBranch, { touch: !own }).catch((err) => ({ status: `sync failed: ${oneLine(err)}`, behind: 0, updatable: false }));\n const status = sync?.status ?? null;\n if (own && sync) this.setOfficeBehind(sync.updatable ? sync.behind : 0);\n if (!this.repoRt.has(repo.id)) return null;\n const before = rt.folderSync;\n rt.folderSync = status;\n this.emitRepo(repo);\n if (status && status !== before) {\n const name = repo.localPath ? path.basename(repo.localPath) : repo.fullName;\n if (status.startsWith('updated')) this.toast('success', `\uD83D\uDCC1 ${name}: ${status}`);\n else if (/behind|diverged|failed/.test(status)) this.toast('info', `\uD83D\uDCC1 ${name} wasn't updated: ${status}`);\n }\n return status;\n }\n\n /** The manager's \"Sync now\". */\n async syncFolderNow(repoId: string) {\n return { folderSync: await this.syncFolder(this.repo(repoId)) };\n }\n\n /** Remove the floor's desks, desk folders and swarm/qa branches nobody uses any more; say so when something went. */\n private async sweepFloor(repoId: string) {\n const repo = this.state.repos.find((r) => r.id === repoId);\n const rt = this.repoRt.get(repoId);\n if (!repo || !rt || rt.cloneStatus !== 'ready') return;\n try {\n const pulls = rt.lastSync ? rt.pulls : await this.backend.listPulls(repo.fullName);\n const agents = this.state.agents.filter((a) => a.repoId === repo.id);\n const keep = {\n desks: [...agents.map((a) => this.agentSlug(a)), PREVIEW_SLUG],\n branches: [...agents.flatMap((a) => (a.branch ? [a.branch] : [])), ...pulls.filter((p) => p.state === 'OPEN').map((p) => p.headRefName)],\n };\n const r = await this.backend.sweepDesks(repo.fullName, keep);\n const desks = r.desks + r.folders;\n const saved = r.patches.length ? ` (${r.patches.length} patch${r.patches.length === 1 ? '' : 'es'} saved to ${path.dirname(r.patches[0])})` : '';\n console.log(`desk sweep ${repo.fullName}: ${desks} desks, ${r.branches} branches removed${saved}${r.skipped.length ? `, ${r.skipped.length} still in use` : ''}`);\n if (!desks && !r.branches) return;\n const removed = [desks && `${desks} old desk${desks === 1 ? '' : 's'}`, r.branches && `${r.branches} finished branch${r.branches === 1 ? '' : 'es'}`].filter(Boolean).join(' and ');\n const text = `\uD83E\uDDF9 ${repo.fullName.split('/')[1]}: removed ${removed}${saved}`;\n this.toast('info', text);\n this.postMessage('office', text);\n } catch (err) {\n console.warn(`desk sweep ${repo.fullName} failed: ${oneLine(err)}`);\n }\n }\n\n // ---------- the floor's app (preview monitor) ----------\n\n /** Run the floor's app from its preview worktree: the default branch, or an open PR. Replaces what it is running now. */\n async startPreview(id: string, pr?: number | null): Promise<PreviewView> {\n const repo = this.repo(id);\n return this.previews.start(repo, `${repo.fullName.split('/')[1]} app`, pr);\n }\n\n stopPreview(id: string): Promise<PreviewView> {\n return this.previews.stop(this.repo(id));\n }\n\n /**\n * Server shutdown: stop every floor's app so nothing is left holding a preview port. Agents' CLIs keep working\n * through a restart (the terminal keeper holds them for the next start) and stop when the office quits.\n */\n async shutdown(restart = false): Promise<void> {\n await this.writeState().catch((err) => console.warn('could not save the state', err));\n await this.backend.releaseClis(restart); // before the terminals are saved: whatever they print next waits in the keeper\n await this.saveTerminals(true);\n await this.previews.stopAll(this.state.repos);\n }\n\n private async cloneRepo(id: string) {\n const repo = this.state.repos.find((r) => r.id === id);\n const rt = this.repoRt.get(id);\n if (!repo || !rt || rt.cloneStatus === 'cloning') return;\n rt.cloneStatus = 'cloning';\n rt.cloneError = undefined;\n this.emitRepo(repo);\n try {\n await this.backend.ensureClone(repo.fullName);\n rt.cloneStatus = 'ready';\n void this.previews.refreshDefault(repo);\n void this.sweepFloor(id);\n } catch (err) {\n rt.cloneStatus = 'error';\n rt.cloneError = (err as Error).message;\n this.toast('error', `Could not clone ${repo.fullName}: ${rt.cloneError}`);\n }\n if (this.repoRt.has(id)) this.emitRepo(repo);\n }\n\n async syncRepo(id: string) {\n const repo = this.state.repos.find((r) => r.id === id);\n const rt = this.repoRt.get(id);\n if (!repo || !rt || rt.syncing) return;\n rt.syncing = true;\n try {\n const started = Date.now();\n const [issues, pulls] = await Promise.all([this.backend.listIssues(repo.fullName), this.backend.listPulls(repo.fullName)]);\n rt.issues = issues;\n rt.pulls = pulls;\n rt.lastSync = Date.now();\n rt.fetchedAt = started;\n rt.syncError = undefined;\n this.reconcilePulls(repo, pulls);\n // Something was merged since the last look (by the office or anyone else): bring the folder up to date.\n const newest = pulls.reduce<string | null>((m, p) => (p.mergedAt && (!m || p.mergedAt > m) ? p.mergedAt : m), null);\n if (newest !== rt.lastMergedAt) {\n rt.lastMergedAt = newest;\n void this.syncFolder(repo);\n }\n void this.advanceMerges(repo);\n } catch (err) {\n rt.syncError = (err as Error).message;\n } finally {\n rt.syncing = false;\n }\n if (this.repoRt.has(id)) this.emitRepo(repo);\n }\n\n /** Keep agents and QA records in step with what happened to PRs on GitHub. */\n private reconcilePulls(repo: PersistedRepo, pulls: PullInfo[]) {\n for (const a of this.state.agents) {\n if (a.repoId !== repo.id || a.role !== 'dev' || a.prNumber == null || BUSY.includes(a.status) || a.status === 'idle') continue;\n const pr = pulls.find((p) => p.number === a.prNumber);\n if (!pr || pr.state === 'OPEN') continue;\n if (a.task === 'qa') {\n this.clearTask(a); // they only tested it\n continue;\n }\n this.appendLog(a, [{ kind: 'done', text: pr.state === 'MERGED' ? `\uD83C\uDF89 PR #${pr.number} was merged. Ready for the next issue.` : `PR #${pr.number} was closed without merging.` }]);\n this.clearTask(a);\n }\n\n // Finished PRs leave QA.\n for (const q of this.state.qa.filter((x) => x.repoId === repo.id)) {\n const pr = pulls.find((p) => p.number === q.prNumber);\n if (pr && pr.state !== 'OPEN' && q.status !== 'testing' && q.status !== 'fixing') {\n this.state.qa = this.state.qa.filter((x) => x !== q);\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: q.prNumber });\n }\n }\n\n // Every swarm PR goes through QA, including ones opened before QA existed or while the server was down.\n for (const pr of pulls) {\n if (pr.state !== 'OPEN' || pr.isDraft || !pr.headRefName.startsWith('swarm/')) continue;\n if (this.state.qa.some((q) => q.repoId === repo.id && q.prNumber === pr.number)) continue;\n const dev = this.state.agents.find((a) => a.repoId === repo.id && a.role === 'dev' && a.task !== 'qa' && (a.prNumber === pr.number || a.branch === pr.headRefName));\n this.queueQa(repo, pr.number, dev ?? null, pr.closesIssues[0] ?? null);\n }\n this.save();\n }\n\n async createIssue(repoId: string, title: string, body: string, assignTo?: string, specialty?: string) {\n const repo = this.repo(repoId);\n if (!title.trim()) throw new HttpError(400, 'An issue needs a title');\n const slug = specialtySlug(specialty);\n const number = await this.backend.createIssue(repo.fullName, title.trim(), body, slug ? [specialtyLabel(slug)] : []);\n await this.syncRepo(repo.id);\n this.toast('success', `Issue #${number} filed on ${repo.fullName}`);\n if (assignTo) await this.assign(assignTo, number);\n else setTimeout(() => this.schedule(), 200);\n return number;\n }\n\n async mergePull(repoId: string, number: number, method: 'squash' | 'merge' | 'rebase' = 'squash') {\n const repo = this.repo(repoId);\n const pr = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === number) ?? (await this.backend.prDetails(repo.fullName, number));\n await this.backend.mergePull(repo.fullName, number, method);\n this.toast('success', `Merged PR #${number} into ${repo.defaultBranch}`);\n await this.closeResolvedIssues(repo, number, pr);\n await this.syncRepo(repo.id);\n setTimeout(() => this.schedule(), 200);\n }\n\n async closePull(repoId: string, number: number) {\n const repo = this.repo(repoId);\n await this.backend.closePull(repo.fullName, number);\n await this.syncRepo(repo.id);\n }\n\n // ---------- agents ----------\n\n hireAgent(\n repoId: string,\n opts: {\n name?: string;\n model?: string;\n effort?: string;\n role?: string;\n look?: string;\n title?: string;\n specialty?: string;\n brief?: string;\n cli?: string;\n hiredBy?: 'manager' | 'ceo';\n appearance?: { color: string; hair: string; skin: string };\n },\n ) {\n const repo = this.repo(repoId);\n const role: AgentRole = opts.role === 'qa' ? 'qa' : 'dev';\n const used = new Set(this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).map((a) => a.desk));\n let desk = 0;\n while (used.has(desk)) desk++;\n if (desk >= MAX_DESKS[role]) {\n throw new HttpError(400, role === 'qa' ? `The QA lab on floor ${repo.floor} is full (${MAX_DESKS.qa} stations)` : `Floor ${repo.floor} is full (${MAX_DESKS.dev} desks)`);\n }\n const name = opts.name?.trim() || this.freeName(role);\n const agent: PersistedAgent = {\n id: crypto.randomUUID(),\n name,\n repoId: repo.id,\n role,\n title: String(opts.title ?? '').trim().slice(0, 60),\n specialty: specialtySlug(opts.specialty),\n brief: String(opts.brief ?? '').trim().slice(0, 2500),\n hiredBy: opts.hiredBy ?? 'manager',\n look: LOOKS.includes(opts.look as AgentLook) ? (opts.look as AgentLook) : lookFor(name),\n task: null,\n desk,\n color: opts.appearance?.color ?? pick(SHIRTS),\n hair: opts.appearance?.hair ?? pick(HAIR),\n skin: opts.appearance?.skin ?? pick(SKIN),\n model: opts.model ?? '',\n effort: EFFORTS.includes(opts.effort as EffortLevel) ? (opts.effort as EffortLevel) : '',\n cli: isCli(opts.cli) ? opts.cli : '',\n status: 'idle',\n issueNumber: null,\n issueTitle: null,\n branch: null,\n prNumber: null,\n prUrl: null,\n startedAt: null,\n endedAt: null,\n costUsd: 0,\n turns: 0,\n sessionId: null,\n sessionCli: null,\n lastError: null,\n logTail: [],\n };\n this.state.agents.push(agent);\n this.agentRt.set(agent.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [], terminal: null });\n this.appendLog(agent, [\n { kind: 'system', text: role === 'qa' ? `\uD83D\uDD0D ${name} joined the QA lab on floor ${repo.floor} (${repo.fullName}).` : `\uD83D\uDC4B ${name} joined floor ${repo.floor} (${repo.fullName}).` },\n ...(agent.title ? [{ kind: 'system' as const, text: `\uD83E\uDEAA ${agent.title}${agent.specialty ? ` \u00B7 takes swarm:${agent.specialty} issues first` : ''}` }] : []),\n ]);\n this.save();\n this.broadcast({ type: 'agent', agent: this.agentView(agent, false) });\n setTimeout(() => this.schedule(), 200);\n return this.agentView(agent, true);\n }\n\n /** Every floor has at least one QA tester. */\n private ensureQaTester(repo: PersistedRepo) {\n if (this.state.agents.some((a) => a.repoId === repo.id && a.role === 'qa')) return;\n this.hireAgent(repo.id, { role: 'qa' });\n }\n\n /** A name from the role's pool that no agent or pending candidate has. */\n private freeName(role: 'dev' | 'qa') {\n const taken = new Set([...this.state.agents.map((a) => a.name), ...this.state.requests.filter((r) => r.status === 'pending').map((r) => r.name)]);\n const pool = role === 'qa' ? QA_NAMES : DEV_NAMES;\n return pool.find((n) => !taken.has(n)) || `${role === 'qa' ? 'Tester' : 'Agent'} ${this.state.agents.length + 1}`;\n }\n\n updateAgent(\n id: string,\n patch: { name?: string; model?: string; effort?: string; cli?: string; look?: string; title?: string; specialty?: string; brief?: string; color?: string; hair?: string },\n ) {\n const a = this.agent(id);\n if (patch.cli !== undefined && a.role !== 'ceo') a.cli = isCli(patch.cli) ? patch.cli : '';\n if (patch.name?.trim() && patch.name.trim() !== a.name) {\n a.name = patch.name.trim().slice(0, 24);\n a.look = lookFor(a.name);\n }\n if (LOOKS.includes(patch.look as AgentLook)) a.look = patch.look as AgentLook;\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) a.color = patch.color;\n if (patch.hair && /^#[0-9a-f]{6}$/i.test(patch.hair)) a.hair = patch.hair;\n if (patch.model !== undefined) a.model = String(patch.model).trim();\n if (patch.effort !== undefined) a.effort = EFFORTS.includes(patch.effort as EffortLevel) ? (patch.effort as EffortLevel) : '';\n if (a.role !== 'ceo') {\n if (patch.title !== undefined) a.title = String(patch.title).trim().slice(0, 60);\n if (patch.specialty !== undefined) a.specialty = specialtySlug(patch.specialty);\n if (patch.brief !== undefined) a.brief = String(patch.brief).trim().slice(0, 2500);\n }\n this.save();\n this.emitAgent(a);\n }\n\n fireAgent(id: string, force = false) {\n const a = this.agent(id);\n if (a.role === 'ceo') throw new HttpError(409, `${a.name} runs the company and can't be let go.`);\n if (!force && a.role === 'qa' && this.state.agents.filter((x) => x.repoId === a.repoId && x.role === 'qa').length <= 1) {\n throw new HttpError(409, `${a.name} is the only QA tester on this floor, and every floor needs at least one.`);\n }\n for (const r of this.state.requests.filter((x) => x.kind === 'let-go' && x.agentId === id && x.status === 'pending')) {\n this.decide(r, { status: 'approved', note: 'They were let go directly.', decidedBy: 'manager' });\n }\n\n this.agentRt.get(id)?.session?.stop();\n this.agentRt.get(id)?.terminal?.releaseIdle?.();\n this.agentRt.get(id)?.terminal?.dispose();\n void removeScreens(id);\n void fs.rm(terminalFile(id), { force: true }).catch(() => undefined);\n for (const q of this.state.qa) {\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\n if (q.devAgentId === id) q.devAgentId = null;\n if (q.devAgentId === null && q.status === 'fixing') this.setQa(q, { status: 'failed' });\n }\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n if (repo) {\n const slug = this.agentSlug(a);\n const main = this.backend.mainDir(repo.fullName); // now: a disconnect points the floor elsewhere before this runs\n void this.backend\n .releaseDesk(repo.fullName, slug, this.port(a))\n .then(() => this.backend.removeDesk(repo.fullName, slug, main))\n .catch(() => undefined)\n .then(() => this.sweepFloor(repo.id));\n }\n this.state.agents = this.state.agents.filter((x) => x.id !== id);\n this.agentRt.delete(id);\n this.save();\n this.broadcast({ type: 'agentRemoved', agentId: id });\n }\n\n stopAgent(id: string) {\n const a = this.agent(id);\n if (!BUSY.includes(a.status)) return;\n a.status = 'stopped';\n a.lastError = 'Stopped by manager';\n this.appendLog(a, [{ kind: 'manager', text: '\u25A0 Manager stopped this session.' }]);\n this.agentRt.get(id)?.session?.stop();\n this.emitAgent(a);\n this.save();\n }\n\n /** An agent whose CLI kept working through the office's restart: the office follows its session again. */\n private reattachSession(a: PersistedAgent) {\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n if (!repo) return;\n this.appendLog(a, [{ kind: 'system', text: '\u21BB The office restarted; their CLI kept working and the office is following it again.' }]);\n this.startAgentSession(a, repo, this.backend.deskDir(repo.fullName, this.agentSlug(a)), '', '', a.sessionId ?? undefined, undefined, 'reattach');\n }\n\n /** The manager pressed Esc in the agent's terminal and the CLI stopped its turn: a Stop that leaves the CLI to them. */\n private interrupted(a: PersistedAgent) {\n if (!BUSY.includes(a.status)) return;\n a.status = 'stopped';\n a.lastError = 'Interrupted in the terminal';\n this.appendLog(a, [{ kind: 'manager', text: '\u25A0 Interrupted in the terminal. Type there to carry on.' }]);\n }\n\n resetAgent(id: string) {\n const a = this.agent(id);\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is busy; stop them first`);\n for (const q of this.state.qa) {\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\n if (q.devAgentId === id && q.status === 'fixing') this.setQa(q, { status: 'failed' });\n }\n this.agentRt.get(id)?.terminal?.releaseIdle?.();\n this.clearTask(a);\n this.appendLog(a, [{ kind: 'system', text: '\u21BA Cleared desk. Ready for new work.' }]);\n this.save();\n }\n\n private issueTaken(repo: PersistedRepo, n: number) {\n return issueTaken(\n n,\n this.state.agents.filter((a) => a.repoId === repo.id),\n this.repoRt.get(repo.id)?.pulls ?? [],\n Date.now(),\n );\n }\n\n private ensureSlot() {\n if (this.slotsFull()) {\n throw new HttpError(429, `All ${this.state.settings.sessionLimit} session slots are busy. Raise or clear the session limit in the manager's console, or wait.`);\n }\n }\n\n async assign(agentId: string, issueNumber: number, note?: string) {\n const a = this.agent(agentId);\n const repo = this.repo(a.repoId);\n if (a.role === 'qa') throw new HttpError(400, `${a.name} is a QA tester; they test pull requests rather than issues.`);\n if (a.role === 'ceo') throw new HttpError(400, `${a.name} runs the company; give issues to the developers.`);\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is already working on #${a.issueNumber}`);\n this.ensureSlot();\n const issue = this.repoRt.get(repo.id)?.issues.find((i) => i.number === issueNumber);\n if (!issue) throw new HttpError(404, `Issue #${issueNumber} is not open on ${repo.fullName}`);\n const holder = this.state.agents.find((x) => x.id !== a.id && x.repoId === repo.id && x.issueNumber === issueNumber && BUSY.includes(x.status));\n if (holder) throw new HttpError(409, `${holder.name} is already working on #${issueNumber}`);\n void this.runTask(a, repo, issue, note);\n return this.agentView(a, false);\n }\n\n private port(a: PersistedAgent) {\n return 5200 + (parseInt(a.id.slice(0, 4), 16) % 700);\n }\n\n private linkedRepos(repo: PersistedRepo) {\n return repo.links.map((id) => this.state.repos.find((r) => r.id === id)).filter((r): r is PersistedRepo => !!r);\n }\n\n /**\n * How an agent's next session runs: the CLI in their terminal (the terminal runtime), or Claude Code through the\n * SDK. A session can only be resumed by the CLI that made it, so a follow-up stays with that CLI.\n */\n private sessionRuntime(a: PersistedAgent, resume?: string): { terminal?: AgentTerminal; cli?: AgentCli; label?: string; resumeSessionId?: string } {\n const inTerminal = this.state.settings.runtime === 'terminal' && this.backend.terminals;\n let cli: AgentCli = a.role === 'ceo' ? 'claude' : a.cli || this.state.settings.defaultCli;\n if (resume && a.sessionCli && a.sessionCli !== cli) {\n if (inTerminal) cli = a.sessionCli;\n else if (a.sessionCli !== 'claude') resume = undefined;\n }\n if (!inTerminal) return { resumeSessionId: resume };\n const what = a.role === 'ceo' ? a.issueTitle : a.task === 'qa' ? `QA \u00B7 PR #${a.prNumber}` : a.task === 'fix' ? `fixing PR #${a.prNumber}` : a.issueNumber ? `#${a.issueNumber} ${a.issueTitle ?? ''}` : null;\n return { terminal: this.terminalFor(a), cli, label: `${a.name}${what ? ` \u00B7 ${what}` : ''}`.slice(0, 80).trim(), resumeSessionId: resume };\n }\n\n /** The model to ask for (the Agent SDK runs Claude Code). '' lets another coding agent use its own default. */\n private modelFor(a: PersistedAgent, cli: AgentCli | undefined) {\n return effectiveModel(a.model, cli ?? 'claude', this.state.settings, DEFAULT_MODEL);\n }\n\n // ---------- terminals ----------\n\n private async loadTerminal(agentId: string): Promise<AgentTerminal | null> {\n if (!(await fs.stat(terminalFile(agentId)).catch(() => null))) return null;\n const t = this.newTerminal(agentId);\n await t.load(terminalFile(agentId));\n return t;\n }\n\n /** The agent's terminal, made the first time they run in the terminal runtime. */\n private terminalFor(a: PersistedAgent): AgentTerminal {\n const rt = this.agentRt.get(a.id)!;\n rt.terminal ??= this.newTerminal(a.id);\n return rt.terminal;\n }\n\n private newTerminal(agentId: string) {\n const t = new AgentTerminal();\n // Typed at a CLI waiting at its prompt after its task: a follow-up, which starts synchronously when it can.\n t.onIdlePrompt = (text) => {\n void this.message(agentId, text, true).catch(() => undefined);\n return !!this.agentRt.get(agentId)?.session;\n };\n return t;\n }\n\n private async saveTerminals(all = false) {\n for (const [id, rt] of this.agentRt) {\n if (rt.terminal && (all || rt.terminal.dirty)) await rt.terminal.save(terminalFile(id)).catch((err) => console.warn('could not save a terminal', err));\n }\n }\n\n /** A browser opened an agent's terminal (/ws/term?agent=<id>). */\n attachTerminal(agentId: string, ws: WebSocket) {\n const t = this.agentRt.get(agentId)?.terminal;\n if (!t) return ws.close(4404, 'That agent has no terminal');\n t.attach(ws);\n }\n\n private buildSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, fixing?: { pr: number; headRef: string }, deps?: DepsOutcome) {\n return devSystemPrompt({ agent: a, repo, port: this.port(a), cwd, branch, linked: this.linkedDirs(repo), fixing, depsLine: depsPromptLine(deps) });\n }\n\n private linkedDirs(repo: PersistedRepo) {\n return this.linkedRepos(repo).map((r) => ({ fullName: r.fullName, dir: this.backend.mainDir(r.fullName) }));\n }\n\n /** What an agent is told on a task, previewed with placeholders for the task's details. */\n agentPrompt(id: string): AgentPromptView {\n const a = this.agent(id);\n if (a.role === 'ceo') return ceoPromptPreview(ceoSystemPrompt(this.ceoPromptInput(a)));\n const repo = this.repo(a.repoId);\n const base = { agent: a, repo, port: this.port(a), slug: slugify(a.name) };\n return a.role === 'qa' ? qaPromptPreview(base) : devPromptPreview({ ...base, linked: this.linkedDirs(repo) });\n }\n\n private beginTask(a: PersistedAgent, patch: Partial<PersistedAgent>, banner: string, preparing: string) {\n const rt = this.agentRt.get(a.id)!;\n Object.assign(a, {\n status: 'preparing' as AgentStatus,\n startedAt: Date.now(),\n endedAt: null,\n costUsd: 0,\n turns: 0,\n lastError: null,\n ...patch,\n });\n rt.screenshot = null;\n rt.browserUrl = null;\n rt.shots = [];\n void removeScreens(a.id);\n this.appendLog(a, [\n { kind: 'system', text: '' },\n { kind: 'system', text: `\u2501\u2501\u2501 ${banner} \u2501\u2501\u2501` },\n { kind: 'system', text: preparing },\n ]);\n this.emitAgent(a);\n this.save();\n }\n\n private async prepare(a: PersistedAgent, repo: PersistedRepo, base: { pr?: number }, branch: string): Promise<{ cwd: string; deps: DepsOutcome } | null> {\n try {\n if (this.repoRt.get(repo.id)?.cloneStatus !== 'ready') await this.cloneRepo(repo.id);\n const slug = this.agentSlug(a);\n const note = (text: string) => this.appendLog(a, [{ kind: 'system', text }]);\n const cwd = await setUpDesk(this.agentRt.get(a.id)?.terminal, {\n release: () => this.backend.releaseDesk(repo.fullName, slug, this.port(a)),\n prepare: () => this.backend.prepareDesk(repo.fullName, { defaultBranch: repo.defaultBranch, pr: base.pr }, slug, branch, note),\n });\n this.deskAlerts.delete(a.id);\n if (a.status !== 'preparing') return null; // stopped or fired while preparing\n // Outside the repo's git lock, so other desks keep checking out meanwhile. A failed install never fails the task.\n const deps = await this.installDeps(a, cwd);\n return a.status === 'preparing' ? { cwd, deps } : null;\n } catch (err) {\n if (a.status !== 'preparing') return null;\n a.status = 'error';\n a.endedAt = Date.now();\n a.lastError = (err as Error).message;\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n if (this.deskAlerts.get(a.id) !== a.lastError) {\n // Once per agent and error: retries that fail the same way don't ring the phone again.\n this.deskAlerts.set(a.id, a.lastError);\n this.postMessage('office', `\u26A0\uFE0F ${a.name}'s desk couldn't be set up: ${a.lastError.slice(0, 240)}`);\n }\n this.emitAgent(a);\n this.save();\n return null;\n }\n }\n\n /** The desk's dependencies, shown on the agent's card (\"Installing dependencies\") while npm runs. */\n private async installDeps(a: PersistedAgent, cwd: string): Promise<DepsOutcome> {\n const rt = this.agentRt.get(a.id);\n try {\n return await this.backend.installDeps(cwd, {\n log: (lines) => this.appendLog(a, lines.map((text) => ({ kind: text.startsWith('\u26A0') ? 'error' : 'system', text }))),\n installing: () => {\n if (!rt) return;\n rt.currentTool = INSTALL_STEP;\n this.emitAgent(a);\n },\n });\n } finally {\n if (rt?.currentTool === INSTALL_STEP) {\n rt.currentTool = null;\n this.emitAgent(a);\n }\n }\n }\n\n private async runTask(a: PersistedAgent, repo: PersistedRepo, issue: IssueInfo, note?: string) {\n const branch = devBranch(issue.number, slugify(a.name));\n this.beginTask(\n a,\n { task: 'issue', issueNumber: issue.number, issueTitle: issue.title, branch, prNumber: null, prUrl: null, sessionId: null },\n `Issue #${issue.number}: ${issue.title}`,\n `Preparing worktree on ${branch}\u2026`,\n );\n const desk = await this.prepare(a, repo, {}, branch);\n if (!desk) return;\n const { cwd } = desk;\n\n const prompt = [\n `Please resolve GitHub issue #${issue.number}: ${issue.title}`,\n `URL: ${issue.url}`,\n issue.labels.length ? `Labels: ${issue.labels.join(', ')}` : '',\n '',\n issue.body?.trim() || '(The issue has no description.)',\n note ? `\\nNote from the manager: ${note}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\n this.startAgentSession(a, repo, cwd, prompt, this.buildSystemAppend(a, repo, cwd, branch, undefined, desk.deps));\n }\n\n private startAgentSession(\n a: PersistedAgent,\n repo: PersistedRepo,\n cwd: string,\n prompt: string,\n systemAppend: string,\n resumeSessionId?: string,\n outputSchema?: Record<string, unknown>,\n /** typed: the manager typed the prompt at the CLI; reattach: follow the CLI that kept working through a restart. */\n mode: 'typed' | 'reattach' | null = null,\n ) {\n const rt = this.agentRt.get(a.id)!;\n a.status = 'working';\n const how = this.sessionRuntime(a, resumeSessionId);\n this.emitAgent(a);\n rt.session = this.backend.startSession(\n {\n cwd,\n prompt,\n systemAppend,\n model: this.modelFor(a, how.cli),\n effort: a.effort || this.state.settings.defaultEffort,\n browserTesting: repo.browserTesting,\n additionalDirectories: this.linkedRepos(repo).map((r) => this.backend.mainDir(r.fullName)),\n role: a.task === 'qa' ? 'qa' : a.role, // a developer covering QA works under QA's rules\n outputSchema,\n // A developer's CLI stays at its prompt afterwards, for the manager and for follow-ups; QA's closes.\n keepAlive: a.task !== 'qa',\n typed: mode === 'typed',\n reattach: mode === 'reattach',\n agentId: a.id,\n ...how,\n },\n {\n log: (entries) => this.appendLog(a, entries),\n tool: (name) => {\n if (rt.currentTool === name) return;\n rt.currentTool = name;\n this.emitAgent(a);\n },\n sessionId: (id) => {\n a.sessionId = id;\n a.sessionCli = id ? (how.cli ?? 'claude') : null;\n },\n browserUrl: (url) => {\n rt.browserUrl = url;\n this.emitAgent(a);\n },\n screenshot: (data, mime) => {\n const at = Date.now();\n rt.screenshot = { data, mime, at };\n rt.shots.push({ data, mime, url: rt.browserUrl, at });\n if (rt.shots.length > 12) rt.shots.shift();\n this.broadcast({ type: 'screen', agentId: a.id, url: rt.browserUrl, at });\n void removeScreens(a.id)\n .then(() => fs.mkdir(SCREENS_DIR, { recursive: true }))\n .then(() => fs.writeFile(screenFile(a.id, mime), data))\n .catch((err) => console.warn('could not save screenshot', err));\n },\n limited: (at) => this.pauseForLimit(at),\n usageWarning: (info) => this.paceForWarning(info),\n finished: (result) => void this.onFinished(a, repo, result),\n },\n );\n }\n\n private async onFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const rt = this.agentRt.get(a.id);\n if (!rt || !this.state.agents.includes(a)) return; // fired\n if (this.officeUpdate.handedOver) return; // stopped for the office's update: recovered like after a restart\n rt.session = null;\n rt.currentTool = null;\n a.endedAt = Date.now();\n a.costUsd += result.costUsd;\n a.turns += result.turns;\n // Dev servers the agent forgot to stop would otherwise keep its port and lock its desk folder.\n void this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined);\n if (result.interrupted) this.interrupted(a);\n\n if (a.task === 'qa') await this.onQaFinished(a, repo, result);\n else if (a.task === 'fix') await this.onFixFinished(a, repo, result);\n else await this.onIssueFinished(a, repo, result);\n\n this.emitAgent(a);\n this.save();\n void this.syncRepo(repo.id);\n setTimeout(() => this.schedule(), 500);\n }\n\n private minutes(a: PersistedAgent) {\n return a.startedAt && a.endedAt ? Math.max(1, Math.round((a.endedAt - a.startedAt) / 60000)) : 0;\n }\n\n private fail(a: PersistedAgent, result: SessionResult, what: string) {\n a.status = 'error';\n a.lastError = result.errors.join('; ') || 'Session failed';\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n this.toast('error', `${a.name} hit a problem on ${what}: ${a.lastError.slice(0, 120)}`);\n }\n\n private async onIssueFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const escaped = repo.fullName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const m = result.text.match(new RegExp(`https://github\\\\.com/${escaped}/pull/(\\\\d+)`, 'i'));\n if (m) {\n a.prNumber = Number(m[1]);\n a.prUrl = m[0];\n } else if (a.branch) {\n const pr = await this.backend.prForBranch(repo.fullName, a.branch).catch(() => null);\n if (pr) {\n a.prNumber = pr.number;\n a.prUrl = pr.url;\n }\n }\n\n if (a.status === 'stopped') return; // the manager already logged the stop\n if (!result.ok) {\n this.issueFailed(repo, a.issueNumber);\n return this.fail(a, result, `#${a.issueNumber}`);\n }\n this.issueFailures.delete(`${repo.id}#${a.issueNumber}`);\n a.status = 'done';\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Finished in ${this.minutes(a)}m \u00B7 ${a.turns} turns${a.prNumber ? ` \u00B7 PR #${a.prNumber}` : ' \u00B7 no PR found'}` }]);\n if (a.prNumber) {\n this.queueQa(repo, a.prNumber, a, a.issueNumber);\n this.appendLog(a, [{ kind: 'system', text: `\uD83D\uDCE8 Handed PR #${a.prNumber} to QA.` }]);\n this.toast('success', `${a.name} opened PR #${a.prNumber} for #${a.issueNumber}; it's off to QA`);\n } else {\n this.noPullRequest(a, repo);\n }\n }\n\n /**\n * An issue session ended without a PR, which would leave the issue \"taken\" with nobody on it. The same developer,\n * who has the context and the worktree, is asked once to finish; after that the issue goes back on the board.\n */\n private noPullRequest(a: PersistedAgent, repo: PersistedRepo) {\n const key = `${repo.id}#${a.issueNumber}`;\n if (this.nudged.has(key)) return this.releaseIssue(a, repo);\n this.nudged.add(key);\n // message() starts the session before its first await, so the scheduler can't hand this developer other work first.\n void this.message(\n a.id,\n `You finished without opening a pull request for #${a.issueNumber}. Finish the remaining steps now: commit, push your branch and open the PR with \"Closes #${a.issueNumber}\". If the issue can't be done, open a draft PR that explains why.`,\n ).catch(() => this.releaseIssue(a, repo));\n }\n\n private releaseIssue(a: PersistedAgent, repo: PersistedRepo) {\n const n = a.issueNumber;\n this.clearTask(a);\n this.postMessage('office', `\u26A0\uFE0F ${a.name} finished #${n} on ${repo.fullName} without opening a pull request, so it's back on the board for anyone.`);\n }\n\n // ---------- QA ----------\n\n private queueQa(repo: PersistedRepo, prNumber: number, dev: PersistedAgent | null, issueNumber: number | null) {\n let rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\n if (rec) {\n if (rec.status === 'testing') return;\n this.setQa(rec, { status: 'queued', devAgentId: dev?.id ?? rec.devAgentId, devSessionId: dev?.sessionId ?? rec.devSessionId });\n } else {\n rec = {\n repoId: repo.id,\n prNumber,\n status: 'queued',\n round: 1,\n devAgentId: dev?.id ?? null,\n qaAgentId: null,\n summary: null,\n checks: [],\n commentUrl: null,\n updatedAt: Date.now(),\n issueNumber,\n devSessionId: dev && dev.prNumber === prNumber ? dev.sessionId : null,\n fixInstructions: null,\n sessionFailures: 0,\n mergeNote: null,\n testedSha: null,\n passedSha: null,\n fixReason: null,\n mergeFixes: 0,\n retests: 0,\n pendingSince: null,\n mergeRetryAt: null,\n alerted: false,\n };\n this.state.qa.push(rec);\n this.setQa(rec, {});\n }\n setTimeout(() => this.schedule(), 200);\n }\n\n /** Manager's \"send to QA\" for any open PR (including ones opened by people). */\n async sendToQa(repoId: string, prNumber: number) {\n const repo = this.repo(repoId);\n const pr = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === prNumber && p.state === 'OPEN');\n if (!pr) throw new HttpError(404, `PR #${prNumber} is not open on ${repo.fullName}`);\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\n if (rec?.status === 'testing' || rec?.status === 'fixing') throw new HttpError(409, `PR #${prNumber} is already ${rec.status}`);\n if (rec && (rec.status === 'needs-human' || rec.status === 'passed' || rec.status === 'failed')) {\n // a fresh start: the manager decided it deserves another round\n rec.round += 1;\n rec.sessionFailures = 0;\n rec.mergeNote = null;\n }\n const dev = this.state.agents.find((a) => a.repoId === repo.id && a.role === 'dev' && a.task !== 'qa' && (a.prNumber === prNumber || a.branch === pr.headRefName));\n this.queueQa(repo, prNumber, dev ?? null, pr.closesIssues[0] ?? null);\n this.toast('info', `PR #${prNumber} is queued for QA`);\n }\n\n /** Manager's \"send back to dev\" for a PR that needs a human or failed QA: a developer fixes it, with the note. */\n async sendBackToDev(repoId: string, prNumber: number, note?: string) {\n const repo = this.repo(repoId);\n const find = () => this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\n const listed = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === prNumber);\n sendBackPatch(prNumber, listed, find(), repo.defaultBranch, note); // refuse before asking GitHub\n // The last sync's mergeability may be stale or UNKNOWN: ask about the PR itself whether it conflicts now.\n const details = await this.backend.prDetails(repo.fullName, prNumber).catch(() => null);\n const pr = details && listed ? { ...listed, state: details.state, mergeable: details.mergeable, mergeState: details.mergeState } : listed;\n const rec = find();\n const patch = sendBackPatch(prNumber, pr, rec, repo.defaultBranch, note);\n this.setQa(rec!, patch);\n setTimeout(() => this.schedule(), 200);\n this.toast('info', `PR #${prNumber} goes back to a developer${patch.fixReason === 'conflict' ? ' to resolve its conflicts' : ''}`);\n }\n\n private buildQaSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, pr: PrDetails, testStep: string, deps?: DepsOutcome) {\n return qaSystemPrompt({ agent: a, repo, port: this.port(a), cwd, branch, pr, testStep, depsLine: depsPromptLine(deps) });\n }\n\n private async runQa(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\n const branch = qaBranch(rec.prNumber, slugify(a.name));\n this.setQa(rec, { status: 'testing', qaAgentId: a.id });\n this.beginTask(\n a,\n { task: 'qa', issueNumber: rec.issueNumber, issueTitle: `PR #${rec.prNumber}`, branch, prNumber: rec.prNumber, prUrl: null, sessionId: null },\n `QA \u00B7 PR #${rec.prNumber} \u00B7 round ${rec.round}`,\n `Checking out PR #${rec.prNumber}\u2026`,\n );\n\n let pr: PrDetails;\n let issue: { title: string; body: string } | null = null;\n const lastTestedSha = rec.testedSha;\n try {\n pr = await this.backend.prDetails(repo.fullName, rec.prNumber);\n const issueNumber = rec.issueNumber ?? pr.closesIssues[0] ?? null;\n if (issueNumber) issue = await this.backend.issueDetails(repo.fullName, issueNumber).catch(() => null);\n Object.assign(a, { issueTitle: pr.title, prUrl: pr.url });\n rec.testedSha = pr.headSha;\n this.emitAgent(a);\n } catch (err) {\n a.status = 'error';\n a.endedAt = Date.now();\n a.lastError = (err as Error).message;\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n this.setQa(rec, { status: 'queued', qaAgentId: null });\n this.emitAgent(a);\n return;\n }\n if (pr.state !== 'OPEN') {\n this.appendLog(a, [{ kind: 'system', text: `PR #${pr.number} is ${pr.state.toLowerCase()}; nothing to test.` }]);\n this.state.qa = this.state.qa.filter((q) => q !== rec);\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: rec.prNumber });\n this.clearTask(a);\n return;\n }\n\n const desk = await this.prepare(a, repo, { pr: rec.prNumber }, branch);\n if (!desk) {\n if (this.state.qa.includes(rec) && rec.status === 'testing') this.setQa(rec, { status: 'queued', qaAgentId: null });\n return;\n }\n const { cwd } = desk;\n\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\n // A last-round fail sent back for a merge fix (QA never passed it): QA's findings first, then a full re-check.\n const failedConflict = rec.fixReason === 'conflict' && !rec.passedSha;\n const qa = qaInstructions({\n ...pr,\n round: rec.round,\n fixReason: failedConflict ? 'qa' : rec.fixReason,\n lastTestedSha: failedConflict ? null : lastTestedSha,\n summary: rec.summary,\n fixInstructions: rec.fixInstructions,\n defaultBranch: repo.defaultBranch,\n });\n const prompt = [\n `Please QA pull request #${pr.number}: ${pr.title}`,\n `URL: ${pr.url}`,\n `Author: ${dev ? `${dev.name} (developer agent)` : 'a teammate'} \u00B7 QA round ${rec.round}`,\n qa.checks,\n qa.retest,\n '',\n 'PR description:',\n pr.body.trim() || '(empty)',\n issue ? `\\nLinked issue: ${issue.title}\\n${issue.body.trim() || '(no description)'}` : '',\n ]\n .filter((l) => l !== '')\n .join('\\n');\n\n this.startAgentSession(a, repo, cwd, prompt, this.buildQaSystemAppend(a, repo, cwd, branch, pr, qa.testStep, desk.deps), undefined, QA_SCHEMA);\n }\n\n private async onQaFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\n const rt = this.agentRt.get(a.id)!;\n const report = result.ok ? parseReport(result) : null;\n\n if (a.status === 'stopped' || !report) {\n if (a.status !== 'stopped') this.fail(a, { ...result, errors: result.errors.length ? result.errors : ['QA finished without a usable report'] }, `QA of PR #${a.prNumber}`);\n if (rec) {\n const failures = rec.sessionFailures + (this.limited() ? 0 : 1); // the usage limit isn't the PR's fault\n this.setQa(rec, {\n status: a.status === 'stopped' || failures >= 2 ? 'needs-human' : 'queued',\n qaAgentId: null,\n sessionFailures: failures,\n summary: a.status === 'stopped' ? 'QA was stopped by the manager.' : rec.summary,\n });\n }\n return;\n }\n\n a.status = 'done';\n const pass = report.verdict === 'pass';\n this.appendLog(a, [{ kind: pass ? 'done' : 'error', text: `${pass ? '\u2705 QA passed' : '\u274C QA failed'} PR #${a.prNumber} \u00B7 ${report.checks.length} checks \u00B7 ${rt.shots.length} screenshots` }]);\n\n // Evidence + comment on the PR\n let commentUrl: string | null = null;\n if (rec) {\n // A fail that would use up QA's rounds: a conflict with the default branch is the merge gate's job, not the manager's.\n const pull = !pass && lastQaRound(rec) ? await this.backend.prDetails(repo.fullName, rec.prNumber).catch(() => null) : null;\n const next = qaOutcome(pass, rec, pull);\n try {\n this.appendLog(a, [{ kind: 'system', text: '\uD83D\uDCCE Uploading evidence and posting the QA report on the PR\u2026' }]);\n const body = await this.renderQaComment(a, repo, rec, report, rt.shots, next);\n commentUrl = (await this.backend.commentPull(repo.fullName, rec.prNumber, body)) || null;\n this.appendLog(a, [{ kind: 'system', text: ` \u23BF ${commentUrl ?? 'comment posted'}` }]);\n } catch (err) {\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF Could not post the QA report: ${(err as Error).message}` }]);\n }\n const qaRounds = rec.round - rec.retests; // rounds QA itself asked for\n const nextStatus = next === 'conflict' ? 'failed' : next;\n const fixInstructions = report.fixInstructions ?? report.checks.filter((c) => c.result === 'fail').map((c) => `${c.name}: ${c.details}`).join('\\n');\n this.setQa(rec, {\n status: nextStatus,\n summary: report.summary,\n checks: report.checks,\n commentUrl: commentUrl ?? rec.commentUrl,\n fixInstructions,\n sessionFailures: 0,\n fixReason: pass ? null : 'qa',\n passedSha: pass ? rec.testedSha : null,\n mergeNote: null,\n pendingSince: null,\n mergeRetryAt: null,\n alerted: false,\n });\n // QA's findings travel with the merge fix; the developer's push then gets one more QA round.\n if (next === 'conflict') this.sendBack(repo, rec, 'conflict', conflictFixInstructions(fixInstructions, repo.defaultBranch), false);\n this.toast(\n pass ? 'success' : 'error',\n pass\n ? `\u2705 ${a.name} passed PR #${rec.prNumber}${repo.autoMerge ? \"; it merges once GitHub's checks are green\" : ': ready to merge'}`\n : nextStatus === 'needs-human'\n ? `\u274C PR #${rec.prNumber} failed QA ${qaRounds} times and needs a human`\n : next === 'conflict'\n ? `\u274C ${a.name} failed PR #${rec.prNumber}, and it conflicts with ${repo.defaultBranch}; sending it back to merge and fix`\n : `\u274C ${a.name} failed PR #${rec.prNumber}; sending it back to the developer`,\n );\n }\n }\n\n private async renderQaComment(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord, report: QaReport, shots: Shot[], next: QaNext) {\n const pass = report.verdict === 'pass';\n const images: string[] = [];\n const evidence = shots.slice(-8);\n const offset = shots.length - evidence.length;\n const folder = `pr-${rec.prNumber}/round-${rec.round}-${Date.now().toString(36)}`;\n for (const [i, shot] of evidence.entries()) {\n const n = offset + i + 1;\n const ext = MIME_EXT[shot.mime] ?? 'png';\n const file = `${folder}/${String(n).padStart(2, '0')}.${ext}`;\n try {\n const url = await this.backend.uploadEvidence(repo.fullName, file, shot.data);\n const caption = report.screenshots[n - 1] ?? `Screenshot ${n}`;\n images.push(`**${n}. ${caption}**${shot.url ? ` \u00B7 \\`${shot.url}\\`` : ''}\\n\\n<img src=\"${url}\" alt=\"${caption.replace(/\"/g, \"'\")}\" width=\"760\">`);\n } catch (err) {\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF screenshot ${n} upload failed: ${(err as Error).message.slice(0, 120)}` }]);\n }\n }\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\n const lines = [\n `## \uD83D\uDD0D QA report: ${pass ? '\u2705 Passed' : '\u274C Failed'}`,\n `**Tester:** ${a.name} (cubefarm QA agent) \u00B7 **Round:** ${rec.round}${dev ? ` \u00B7 **Author:** ${dev.name}` : ''}`,\n '',\n report.summary,\n '',\n '| | Check | Details |',\n '|---|---|---|',\n ...report.checks.map((c) => `| ${ICON[c.result]} | ${cell(c.name)} | ${cell(c.details)} |`),\n ];\n if (report.commands.length) {\n lines.push('', '<details><summary>\uD83E\uDDEA Commands run</summary>', '', '| Command | Result |', '|---|---|', ...report.commands.map((c) => `| \\`${cell(c.command)}\\` | ${cell(c.result)} |`), '', '</details>');\n }\n if (!pass && report.fixInstructions) lines.push('', '### \uD83D\uDD27 What needs fixing', '', report.fixInstructions);\n if (images.length) lines.push('', '### \uD83D\uDCF8 Evidence', '', ...images.flatMap((img) => [img, '']));\n else lines.push('', '_No browser screenshots were taken in this round._');\n const merge = repo.autoMerge ? \"merges automatically once GitHub's checks pass\" : 'ready for the manager to merge';\n lines.push('', `<sub>Posted by cubefarm \u00B7 ${pass ? merge : next === 'needs-human' ? 'needs a human decision' : next === 'conflict' ? `sent back to the developer to merge ${repo.defaultBranch} and fix` : 'sent back to the developer for fixes'}</sub>`);\n return lines.join('\\n');\n }\n\n /** Send a failed PR back to the developer who wrote it (or any free developer on the floor). */\n private async runFix(dev: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\n const original = rec.devAgentId === dev.id;\n const pull = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === rec.prNumber);\n const headRef = pull?.headRefName ?? dev.branch ?? `pr-${rec.prNumber}`;\n const qaAgent = rec.qaAgentId ? this.state.agents.find((x) => x.id === rec.qaAgentId) : null;\n this.setQa(rec, { status: 'fixing', devAgentId: dev.id });\n this.beginTask(\n dev,\n // The session they held was another task's (QA, say); the author's own is resumed below, from rec.devSessionId.\n { task: 'fix', issueNumber: rec.issueNumber, issueTitle: pull?.title ?? `PR #${rec.prNumber}`, branch: headRef, prNumber: rec.prNumber, prUrl: pull?.url ?? null, sessionId: null },\n rec.fixReason === 'conflict' ? `Resolving conflicts on PR #${rec.prNumber}` : rec.fixReason === 'checks' ? `Fixing checks on PR #${rec.prNumber}` : `Fixing PR #${rec.prNumber} after QA round ${rec.round}`,\n `Checking out PR #${rec.prNumber}\u2026`,\n );\n const desk = await this.prepare(dev, repo, { pr: rec.prNumber }, headRef);\n if (!desk) {\n if (rec.status === 'fixing') this.setQa(rec, { status: 'failed' });\n return;\n }\n const { cwd } = desk;\n const failed = rec.checks.filter((c) => c.result === 'fail');\n const takeover = original ? '' : ' A teammate wrote it, so read the PR and the linked issue first.';\n const push = `push to the same branch: git push origin HEAD:${headRef}`;\n // A conflict QA never passed (it failed the last round) goes out as a QA fix: its instructions add the merge.\n const mergeFix =\n rec.fixReason === 'conflict' && rec.passedSha\n ? [\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but it now conflicts with ${repo.defaultBranch} because other work was merged first.${takeover}`,\n rec.fixInstructions ? `\\nWhat needs fixing:\\n${rec.fixInstructions}` : '',\n '',\n `Bring it up to date: git fetch origin && git merge origin/${repo.defaultBranch}. Resolve the conflicts so both this change and the newly merged work keep working, run the project's checks, and ${push}`,\n ]\n : rec.fixReason === 'checks'\n ? [\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but GitHub checks failed on it.${takeover}`,\n '',\n `Failed checks:\\n${rec.fixInstructions ?? ''}`,\n '',\n `Read the logs with gh pr checks ${rec.prNumber} -R ${repo.fullName} (for GitHub Actions: gh run view <run id> -R ${repo.fullName} --log-failed). Fix the cause, run the same checks locally where you can, and ${push}`,\n `If a failure clearly has nothing to do with this change (a flaky test or a service outage), re-run it instead with gh run rerun <run id> -R ${repo.fullName} --failed, and say so.`,\n ]\n : null;\n const qaFix = [\n original\n ? `QA tester ${qaAgent?.name ?? 'QA'} tested your pull request #${rec.prNumber} and it FAILED (round ${rec.round}).`\n : `You are taking over pull request #${rec.prNumber} (${pull?.url ?? ''}), written by a teammate, because QA failed it (round ${rec.round}). Read the PR and the linked issue first.`,\n '',\n `QA summary: ${rec.summary ?? ''}`,\n failed.length ? `Failed checks:\\n${failed.map((c) => `- ${c.name}: ${c.details}`).join('\\n')}` : '',\n rec.fixInstructions ? `\\nWhat needs fixing:\\n${rec.fixInstructions}` : '',\n rec.commentUrl ? `\\nFull report with screenshots: ${rec.commentUrl}` : '',\n '',\n `Fix these problems, re-run the relevant checks, and push to the same branch: git push origin HEAD:${headRef}`,\n 'Then reply with a short summary of what you changed. Do not open a new pull request; QA will re-test automatically.',\n ];\n const mergeEnd = 'Then reply with a short summary of what you did. Do not open a new pull request; the office merges it once the checks pass, after another QA round if the code changed.';\n const prompt = (mergeFix ? [...mergeFix, '', mergeEnd] : qaFix).filter((l) => l !== '').join('\\n');\n const resume = original && rec.devSessionId ? rec.devSessionId : undefined;\n this.startAgentSession(dev, repo, cwd, prompt, this.buildSystemAppend(dev, repo, cwd, headRef, { pr: rec.prNumber, headRef }, desk.deps), resume);\n }\n\n private async onFixFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\n // Did it push anything? A checks fix may only re-run a flaky check, so only QA and conflict fixes are asked.\n const head = rec && result.ok && a.status !== 'stopped' && rec.fixReason !== 'checks' ? await this.prHead(a, repo, rec.prNumber) : null;\n if (a.status === 'stopped') {\n if (rec?.status === 'fixing') this.setQa(rec, { status: 'failed' });\n return;\n }\n if (!result.ok) {\n this.fail(a, result, `the fix for PR #${a.prNumber}`);\n // Someone else gets a go before it lands on the manager.\n const failures = rec ? rec.sessionFailures + (this.limited() ? 0 : 1) : 0;\n if (rec) this.setQa(rec, { status: failures >= 2 ? 'needs-human' : 'failed', sessionFailures: failures });\n return;\n }\n if (!rec || !this.state.qa.includes(rec)) {\n a.status = 'done';\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Fix pushed for PR #${a.prNumber} in ${this.minutes(a)}m. Back to QA.` }]);\n return;\n }\n const step = fixOutcome(rec, head, this.minutes(a), !this.limited());\n if (!step.pushed) {\n // Like a failed session: someone gets another go, with the same instructions, before it lands on the manager.\n const needsHuman = step.set.status === 'needs-human';\n a.status = 'error';\n a.lastError = `No new commits were pushed for PR #${rec.prNumber}`;\n this.appendLog(a, [step.log]);\n this.setQa(rec, step.set);\n this.toast('error', `${a.name} ended the fix for PR #${rec.prNumber} without pushing a commit${needsHuman ? '; it needs you' : '; it goes back for another try'}`);\n if (needsHuman) {\n this.postMessage('office', `\u26A0\uFE0F PR #${rec.prNumber} on ${repo.fullName} went back for fixes, but ${step.set.sessionFailures} fix sessions in a row ended without pushing a commit, so it needs you.`);\n }\n return;\n }\n a.status = 'done';\n this.appendLog(a, [step.log]);\n this.setQa(rec, { ...step.set, devSessionId: a.sessionId ?? rec.devSessionId });\n this.toast(\n 'info',\n step.set.status === 'passed' ? `${a.name} fixed PR #${rec.prNumber}; it merges once it passes again` : `${a.name} pushed fixes for PR #${rec.prNumber}; QA round ${rec.round} is queued`,\n );\n }\n\n /** The PR's head commit now; null (with a warning in the agent's log) when GitHub can't be asked. */\n private async prHead(a: PersistedAgent, repo: PersistedRepo, prNumber: number): Promise<string | null> {\n try {\n return (await this.backend.prDetails(repo.fullName, prNumber)).headSha;\n } catch (err) {\n console.warn(`could not read the head of ${repo.fullName}#${prNumber}`, err);\n this.appendLog(a, [{ kind: 'system', text: `\u26A0 Could not check PR #${prNumber} for new commits (${oneLine(err)}); taking the fix at its word.` }]);\n return null;\n }\n }\n\n /** A message for an agent: sent into their running session, or a follow-up that resumes it. typed: the manager typed it at their CLI's prompt, where it's already running. */\n async message(id: string, text: string, typed = false) {\n const a = this.agent(id);\n if (a.role === 'ceo') return this.messageCeo(text);\n const repo = this.repo(a.repoId);\n if (!text.trim()) throw new HttpError(400, 'Empty message');\n const rt = this.agentRt.get(id)!;\n if (rt.session) {\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\n if (!typed) rt.session.send(text);\n return;\n }\n if (a.role === 'qa') throw new HttpError(409, `${a.name} isn't testing anything right now. Send a PR to QA from the Kanban board.`);\n if (a.status === 'preparing') throw new HttpError(409, `${a.name} is still setting up; try again in a moment`);\n if (!a.sessionId || !a.branch || a.task === 'qa') throw new HttpError(409, `${a.name} has no session to continue. Assign an issue instead.`);\n this.ensureSlot();\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\n const cwd = this.backend.deskDir(repo.fullName, this.agentSlug(a));\n a.lastError = null;\n a.startedAt = Date.now();\n if (a.task === null) a.task = 'issue';\n const fixing = a.task === 'fix' && a.prNumber ? { pr: a.prNumber, headRef: a.branch } : undefined;\n this.startAgentSession(a, repo, cwd, text, this.buildSystemAppend(a, repo, cwd, a.branch, fixing), a.sessionId, undefined, typed ? 'typed' : null);\n }\n\n updateSettings(patch: Partial<SwarmSettings>) {\n const s = this.state.settings;\n if (patch.sessionLimit !== undefined) s.sessionLimit = Math.max(0, Math.round(Number(patch.sessionLimit)) || 0);\n // The default model belongs to the default coding agent: a new agent starts on its own default.\n if (isCli(patch.defaultCli) && patch.defaultCli !== s.defaultCli) {\n s.defaultCli = patch.defaultCli;\n if (patch.defaultModel === undefined) s.defaultModel = s.defaultCli === 'claude' ? DEFAULT_MODEL : '';\n }\n if (patch.defaultModel !== undefined) s.defaultModel = String(patch.defaultModel).trim() || (s.defaultCli === 'claude' ? DEFAULT_MODEL : '');\n if (patch.defaultEffort !== undefined && EFFORTS.includes(patch.defaultEffort)) s.defaultEffort = patch.defaultEffort;\n if (patch.runtime === 'terminal' || patch.runtime === 'sdk') s.runtime = patch.runtime;\n if (patch.hiring === 'approve' || patch.hiring === 'auto') s.hiring = patch.hiring;\n if (patch.teamCap !== undefined) s.teamCap = Math.max(1, Math.min(15, Math.round(Number(patch.teamCap)) || 1));\n if (patch.ceoHeartbeatMin !== undefined) s.ceoHeartbeatMin = Math.max(0, Math.min(1440, Math.round(Number(patch.ceoHeartbeatMin)) || 0));\n if (typeof patch.managerName === 'string') s.managerName = patch.managerName.trim().slice(0, 40);\n if (typeof patch.companyName === 'string') s.companyName = patch.companyName.trim().slice(0, 60);\n if (typeof patch.projectsDir === 'string' && patch.projectsDir.trim()) s.projectsDir = path.resolve(patch.projectsDir.trim());\n if (typeof patch.setupDone === 'boolean') s.setupDone = patch.setupDone;\n if (patch.tutorialStep !== undefined) s.tutorialStep = Math.max(-1, Math.round(Number(patch.tutorialStep)) || 0);\n if (typeof patch.autoUpdate === 'boolean') s.autoUpdate = patch.autoUpdate;\n if (patch.pacingSessions !== undefined) s.pacingSessions = clampPacingSessions(patch.pacingSessions);\n if (patch.voice !== undefined) s.voice = voiceSettings(s.voice, patch.voice);\n this.save();\n this.broadcast({ type: 'settings', settings: s });\n this.emitCeo();\n setTimeout(() => this.schedule(), 200);\n return s;\n }\n\n /** The setup wizard: who you are, the company, and your CEO. */\n setup(x: { managerName?: string; companyName?: string; hiring?: string; ceoName?: string; ceoLook?: string; ceoColor?: string }) {\n this.updateSettings({\n managerName: x.managerName,\n companyName: x.companyName,\n ...(x.hiring === 'auto' || x.hiring === 'approve' ? { hiring: x.hiring } : {}),\n });\n const ceo = this.ceo();\n this.updateAgent(ceo.id, { name: x.ceoName, color: x.ceoColor });\n if (LOOKS.includes(x.ceoLook as AgentLook)) this.updateAgent(ceo.id, { look: x.ceoLook });\n return this.state.settings;\n }\n\n // ---------- scheduling ----------\n\n /**\n * Agents on a floor who can take work now. One whose last session failed sits out a short cooldown, then gets work\n * like everyone else instead of waiting for the manager to reset them.\n */\n private available(repo: PersistedRepo, role: AgentRole) {\n const now = Date.now();\n return this.state.agents\n .filter((a) => a.repoId === repo.id && a.role === role && (FREE.includes(a.status) || (a.status === 'error' && now - (a.endedAt ?? 0) >= ERROR_COOLDOWN_MS)))\n .sort((x, y) => x.desk - y.desk);\n }\n\n private scheduleOffset = 0;\n private issueFailures = new Map<string, number>(); // `${repoId}#${issue}` \u2192 failed sessions on it\n private nudged = new Set<string>(); // `${repoId}#${issue}`: its developer was asked once to finish the missing PR\n private pausedUntil = 0; // Claude's usage limit was hit: nothing new starts before this\n private pacingUntil = 0; // Claude warned about usage: new issues are paced until this\n private lastUsage = '';\n\n /** Backlog issues that can start now, most urgent first: the ones holding up the longest chain of other issues, then the oldest. */\n private readyIssues(repo: PersistedRepo) {\n const issues = this.repoRt.get(repo.id)!.issues;\n const open = new Set(issues.map((i) => i.number));\n const weight = holdUps(issues);\n return issues\n .filter(\n (i) =>\n !i.labels.some((l) => /^(swarm:skip|wontfix|question)$/i.test(l)) &&\n !this.issueTaken(repo, i.number) &&\n blockers(i.body, open).length === 0 &&\n (this.issueFailures.get(`${repo.id}#${i.number}`) ?? 0) < MAX_ISSUE_FAILURES,\n )\n .map((issue) => ({ issue, want: issueSpecialty(issue.labels), ...weight.get(issue.number)! }))\n .sort((x, y) => y.chain - x.chain || y.waiting - x.waiting || x.issue.number - y.issue.number);\n }\n\n /**\n * The free developer to put on a job: one it `suits` first, then whoever is least needed elsewhere (fewest ready\n * issues in their specialty, then the least open work in it), so specialists stay free for their own lane.\n */\n private pickDev(repo: PersistedRepo, devs: PersistedAgent[], suits: (a: PersistedAgent) => boolean) {\n if (devs.length <= 1) return devs[0];\n const ready = this.readyIssues(repo).map((r) => r.want);\n const open = this.repoRt.get(repo.id)!.issues.map((i) => issueSpecialty(i.labels));\n const rank = (a: PersistedAgent) => {\n const s = a.specialty.toLowerCase();\n return [suits(a) ? 0 : 1, ready.filter((w) => w === s).length, open.filter((w) => w === s).length, a.desk];\n };\n return devs\n .map((a) => ({ a, r: rank(a) }))\n .sort((x, y) => x.r[0] - y.r[0] || x.r[1] - y.r[1] || x.r[2] - y.r[2] || x.r[3] - y.r[3])[0].a;\n }\n\n /**\n * Finish work in flight: test queued PRs (oldest first) and get failed ones fixed. Returns true if work started.\n * QA testers test; when they're all busy, a free developer who didn't write the PR covers for them, so QA never\n * holds up the floor. A failed PR goes back to its author when they're free, and otherwise to any free developer.\n */\n private startPipelineWork(repo: PersistedRepo): boolean {\n const devs = this.available(repo, 'dev');\n const testers = this.available(repo, 'qa');\n const waiting = (status: QaRecord['status']) => this.state.qa.filter((q) => q.repoId === repo.id && q.status === status).sort((x, y) => x.updatedAt - y.updatedAt);\n for (const rec of waiting('queued')) {\n const tester =\n testers[0] ??\n this.pickDev(\n repo,\n devs.filter((a) => a.id !== rec.devAgentId),\n (a) => /test|qa/i.test(a.specialty),\n );\n if (!tester) continue;\n void this.runQa(tester, repo, rec);\n return true;\n }\n for (const rec of waiting('failed')) {\n const issue = this.repoRt.get(repo.id)!.issues.find((i) => i.number === rec.issueNumber);\n const want = issue ? issueSpecialty(issue.labels) : null;\n const dev = devs.find((a) => a.id === rec.devAgentId) ?? this.pickDev(repo, devs, (a) => a.specialty.toLowerCase() === want);\n if (!dev) break;\n void this.runFix(dev, repo, rec);\n return true;\n }\n return false;\n }\n\n /**\n * Give a free developer the next backlog issue (auto-assign floors only). Returns true if work started.\n * Issues that say \"Depends on #N\" wait until #N is closed; the rest go in readyIssues() order. A swarm:<specialty>\n * label is a preference, not a lock: a free specialist gets first pick, and otherwise the issue goes to whichever\n * free developer is least needed elsewhere, so nobody sits idle while there is work that can start.\n */\n private startIssueWork(repo: PersistedRepo): boolean {\n if (!repo.autoAssign || !this.mayStart('issue')) return false;\n const free = this.available(repo, 'dev');\n const ready = free.length ? this.readyIssues(repo) : [];\n if (ready.length === 0) return false;\n const fits = (a: PersistedAgent, want: string) => a.specialty.toLowerCase() === want;\n // Of the issues holding up the most, take one a free specialist fits.\n const pick = ready.find((r) => r.chain === ready[0].chain && free.some((a) => fits(a, r.want))) ?? ready[0];\n const agent = this.pickDev(repo, free, (a) => fits(a, pick.want))!;\n // assign() flips the agent to 'preparing' synchronously, so the next pass sees it as busy.\n void this.assign(agent.id, pick.issue.number).catch((err) => console.warn('auto-assign failed', err));\n return agent.status === 'preparing';\n }\n\n private limited() {\n return Date.now() < this.pausedUntil;\n }\n\n /** Claude turned a session away for the usage limit: start nothing new until it resets, rather than failing agent after agent. */\n private pauseForLimit(resetsAt: number | null) {\n const until = (resetsAt ?? Date.now() + LIMIT_PAUSE_MS) + 30_000;\n if (until <= this.pausedUntil) return;\n const fresh = Date.now() >= this.pausedUntil;\n this.pausedUntil = until;\n if (fresh) this.postMessage('office', `\u23F8 Claude's usage limit was reached. The office starts no new work until ${new Date(until).toLocaleTimeString()}; sessions already running carry on.`);\n this.emitUsage();\n }\n\n /** Claude warned that usage is getting high: pace new issues until the window resets, rather than run into the limit. */\n private paceForWarning(info: UsageWarning) {\n const now = Date.now();\n const until = info.resetsAt && info.resetsAt > now ? info.resetsAt : now + PACING_MS;\n if (until <= this.pacingUntil) return;\n const fresh = now >= this.pacingUntil;\n this.pacingUntil = until;\n if (fresh) this.postMessage('office', pacingMessage(info, until, this.state.settings.pacingSessions, now));\n this.emitUsage();\n }\n\n /** May work of this kind start now, as far as Claude's usage goes? */\n private mayStart(kind: WorkKind) {\n return mayStart(kind, { now: Date.now(), pausedUntil: this.pausedUntil, pacingUntil: this.pacingUntil, running: this.running(), pacingSessions: this.state.settings.pacingSessions });\n }\n\n private usageNow() {\n return usageView({ now: Date.now(), pausedUntil: this.pausedUntil, pacingUntil: this.pacingUntil });\n }\n\n private emitUsage() {\n const usage = this.usageNow();\n const key = JSON.stringify(usage);\n if (key === this.lastUsage) return;\n this.lastUsage = key;\n this.broadcast({ type: 'usage', usage });\n }\n\n /** Pacing and pauses run out on their own: say so when pacing ends. */\n private tickUsage() {\n if (this.pacingUntil && Date.now() >= this.pacingUntil) {\n this.pacingUntil = 0;\n this.postMessage('office', \"\u2705 Claude's usage is back to normal. The office starts new work at full speed again.\");\n }\n this.emitUsage();\n }\n\n /** A failed session releases its issue for someone else; an issue that keeps failing waits for the manager. */\n private issueFailed(repo: PersistedRepo, n: number | null) {\n if (n == null || this.limited()) return; // the usage limit isn't the issue's fault\n const key = `${repo.id}#${n}`;\n const failures = (this.issueFailures.get(key) ?? 0) + 1;\n this.issueFailures.set(key, failures);\n if (failures === MAX_ISSUE_FAILURES) {\n this.postMessage('office', `\u26A0\uFE0F Issue #${n} on ${repo.fullName} failed ${failures} sessions in a row, so auto-assign skips it now. Assign it to someone by hand once it's sorted.`);\n }\n }\n\n /**\n * Hand out work for free session slots. Finishing beats starting: QA and QA fixes on every floor go before any new issue.\n * Within each phase floors take turns (one job per floor per pass), and the starting floor rotates between calls,\n * so no repo can hog the slots.\n */\n private schedule() {\n this.tickUsage();\n if (this.officeUpdateTick()) return; // draining for the office's own update\n if (this.limited()) return;\n // Management first: the CEO's jobs are short and shape everyone else's work.\n this.maybeHeartbeat();\n this.startCeoWork();\n const repos = this.state.repos.filter((r) => {\n const rt = this.repoRt.get(r.id);\n return rt && rt.lastSync != null && rt.cloneStatus !== 'error';\n });\n if (repos.length === 0) return;\n this.scheduleOffset = (this.scheduleOffset + 1) % repos.length;\n const order = [...repos.slice(this.scheduleOffset), ...repos.slice(0, this.scheduleOffset)];\n for (const start of [(r: PersistedRepo) => this.startPipelineWork(r), (r: PersistedRepo) => this.startIssueWork(r)]) {\n let progress = true;\n while (progress) {\n progress = false;\n for (const repo of order) {\n if (this.slotsFull()) return;\n if (start(repo)) progress = true;\n }\n }\n }\n }\n\n // ---------- the office's own update ----------\n\n private drainInput(): DrainInput {\n const u = this.officeUpdate;\n return {\n now: Date.now(),\n behind: this.officeHead ? u.behind : 0,\n launcher: this.backend.office.launcher,\n autoUpdate: this.state.settings.autoUpdate !== false,\n requested: u.requested,\n postponedUntil: u.postponedUntil,\n postponedBehind: u.postponedBehind,\n failed: u.failed,\n failedBehind: u.failedBehind,\n drainingSince: u.drainingSince,\n sent: u.sent,\n running: this.running(),\n };\n }\n\n private officeUpdateView(): OfficeUpdateView {\n const u = this.officeUpdate;\n const input = this.drainInput();\n const d = drainDecision(input);\n const until = u.postponedUntil ? new Date(u.postponedUntil).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : '';\n const detail = d.state === 'failed' ? u.failed : d.state === 'waiting' ? `Postponed until ${until}, or until a newer commit lands.` : null;\n return { state: d.state, behind: input.behind, launcher: input.launcher, drainingSince: u.drainingSince ?? d.drainingSince, running: input.running, detail };\n }\n\n private emitOfficeUpdate() {\n if (!this.officeHead) return;\n const view = this.officeUpdateView();\n const key = JSON.stringify(view);\n if (key === this.lastOfficeView) return;\n this.lastOfficeView = key;\n this.broadcast({ type: 'officeUpdate', officeUpdate: view });\n }\n\n /** The own-folder check found the office this many commits behind GitHub. */\n private setOfficeBehind(behind: number) {\n const u = this.officeUpdate;\n if (u.failed && u.failedBehind === null) u.failedBehind = behind; // only a newer commit retries a failed update by itself\n u.behind = behind;\n if (behind === 0) Object.assign(u, { requested: false, failed: null, failedBehind: null });\n this.officeUpdateTick();\n }\n\n /**\n * Take the office's own update one step (see drainDecision): drain, and once nothing is running, or the drain timed\n * out, hand it to the launcher. True while nothing new may start.\n */\n private officeUpdateTick(): boolean {\n if (!this.officeHead) return false;\n const u = this.officeUpdate;\n const d = drainDecision(this.drainInput());\n if (d.state === 'draining' && u.drainingSince === null) {\n const running = this.running();\n this.postMessage(\n 'office',\n `\u2B06\uFE0F Updating the office (${u.behind} new commit${u.behind === 1 ? '' : 's'}). Nothing new starts${running ? ` while ${running} running session${running === 1 ? '' : 's'} finish` : ''}; then it installs and restarts.`,\n );\n }\n u.drainingSince = d.drainingSince;\n if (d.send) void this.handOver(d.timedOut);\n this.emitOfficeUpdate();\n return d.state === 'draining' || d.state === 'updating';\n }\n\n /** Drained: hand the update to the launcher. Sessions still running after the timeout stop the way a restart stops them. */\n private async handOver(timedOut: boolean) {\n const u = this.officeUpdate;\n const from = this.officeHead!;\n u.sent = true;\n const busy = this.state.agents.filter((a) => BUSY.includes(a.status));\n if (timedOut) this.postMessage('office', `\u23F1 ${busy.length} session${busy.length === 1 ? ' was' : 's were'} still running after 20 minutes. Stopped; the work goes back to the queue after the update.`);\n this.emitOfficeUpdate();\n u.handedOver = true;\n await this.writeState().catch((err) => console.warn('could not save the state', err)); // still \"working\": the restarted office recovers them\n for (const a of busy) this.agentRt.get(a.id)?.session?.stop();\n try {\n const result = await this.backend.office.update(from);\n if (result) await this.afterUpdate(result); // the demo: nothing restarts\n } catch (err) {\n await this.afterUpdate({ from, to: from, ok: false, error: `the launcher didn't take the update: ${oneLine(err)}`, installed: false, built: false, at: Date.now() });\n }\n }\n\n /** An update that didn't restart the office (the demo, or a failed hand-over): recover like a restart would, then report it. */\n private async afterUpdate(result: LastUpdate) {\n const u = this.officeUpdate;\n Object.assign(u, { sent: false, handedOver: false, requested: false, drainingSince: null });\n const interrupted = this.state.agents.filter((a) => BUSY.includes(a.status));\n const preparing = new Set(interrupted.filter((a) => a.status === 'preparing'));\n for (const a of interrupted) {\n Object.assign(a, { status: 'stopped', lastError: 'The office updated itself while this agent was working.' });\n const rt = this.agentRt.get(a.id);\n if (rt) Object.assign(rt, { session: null, currentTool: null });\n }\n this.ensureCeo(interrupted);\n this.recover(interrupted, preparing);\n interrupted.forEach((a) => this.emitAgent(a));\n await this.reportUpdate(result);\n if (!result.ok) u.failedBehind = u.behind;\n const own = this.state.repos.find((r) => this.backend.office.isOwnFolder(this.backend.mainDir(r.fullName)));\n if (own) await this.syncFolder(own);\n this.emitCeo();\n this.save();\n setTimeout(() => this.schedule(), 300);\n }\n\n /** One phone message about the last update (the launcher's last-update.json, or the demo's fake). */\n private async reportUpdate(result: LastUpdate) {\n const commits = result.ok && result.to ? await this.backend.office.commitsBetween(result.from, result.to) : null;\n this.postMessage('office', lastUpdateMessage(result, commits));\n Object.assign(this.officeUpdate, { failed: result.ok ? null : result.error || 'unknown error', failedBehind: null });\n }\n\n /** The manager's Update now (drain now, even with automatic updates off) or Later (not for 2 hours, or until a newer commit). */\n updateOffice(action: unknown): OfficeUpdateView {\n if (action !== 'now' && action !== 'later') throw new HttpError(400, 'action must be \"now\" or \"later\"');\n const u = this.officeUpdate;\n if (!this.officeHead || !this.backend.office.launcher) throw new HttpError(409, 'The office can only update itself when its launcher started it (npm run dev or npm start).');\n if (u.sent) throw new HttpError(409, 'The update is already under way.');\n if (u.behind <= 0) throw new HttpError(409, 'The office is up to date: there is nothing to update.');\n if (action === 'now') Object.assign(u, { requested: true, postponedUntil: null });\n else Object.assign(u, { requested: false, postponedUntil: Date.now() + POSTPONE_MS, postponedBehind: u.behind });\n this.officeUpdateTick();\n setTimeout(() => this.schedule(), 200);\n return this.officeUpdateView();\n }\n\n // ---------- the CEO ----------\n\n private ceo() {\n return this.state.agents.find((a) => a.id === CEO_ID)!;\n }\n\n /** The company always has a CEO. One cut off by a server restart picks its job back up. */\n private ensureCeo(interrupted: PersistedAgent[]) {\n let a = this.state.agents.find((x) => x.id === CEO_ID);\n if (!a) {\n a = {\n id: CEO_ID,\n name: CEO_NAME,\n repoId: '',\n role: 'ceo',\n title: 'Chief Executive Officer',\n specialty: '',\n brief: '',\n hiredBy: 'manager',\n look: lookFor(CEO_NAME),\n task: null,\n desk: 0,\n color: '#e63946',\n hair: '#2b2118',\n skin: pick(SKIN),\n model: CEO_MODEL,\n effort: CEO_EFFORT,\n cli: 'claude',\n status: 'idle',\n issueNumber: null,\n issueTitle: null,\n branch: null,\n prNumber: null,\n prUrl: null,\n startedAt: null,\n endedAt: null,\n costUsd: 0,\n turns: 0,\n sessionId: null,\n sessionCli: null,\n lastError: null,\n logTail: [],\n };\n this.state.agents.push(a);\n this.agentRt.set(a.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [], terminal: null });\n this.appendLog(a, [{ kind: 'system', text: `\uD83C\uDFDB\uFE0F ${a.name} moved into the corner office. The CEO studies every floor, shapes its team and plans its work.` }]);\n }\n const i = interrupted.indexOf(a);\n if (i >= 0) {\n interrupted.splice(i, 1);\n a.status = 'idle';\n a.lastError = null;\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Picking the job back up.' }]);\n }\n if (this.state.ceo.job) {\n this.state.ceo.queue.unshift(this.state.ceo.job);\n this.state.ceo.job = null;\n }\n this.state.ceo.lastReviewAt ??= Date.now(); // the first review comes one heartbeat after the office opens\n }\n\n private ceoFloor(repoId?: string) {\n const repo = repoId ? this.state.repos.find((r) => r.id === repoId) : undefined;\n if (!repo) return null;\n return { floor: repo.floor, fullName: repo.fullName, clone: this.backend.mainDir(repo.fullName), mission: repo.mission, backlog: this.repoRt.get(repo.id)?.issues.length ?? 0 };\n }\n\n private ceoInfo(): CeoInfo {\n const c = this.state.ceo;\n const view = (j: CeoJob) => ({ kind: j.kind, label: jobLabel(j, this.ceoFloor(j.repoId)) });\n const min = this.state.settings.ceoHeartbeatMin;\n return {\n queue: c.queue.map(view),\n job: c.job ? view(c.job) : null,\n lastReviewAt: c.lastReviewAt,\n nextReviewAt: min > 0 && c.lastReviewAt ? c.lastReviewAt + min * 60_000 : null,\n };\n }\n\n private emitCeo() {\n this.broadcast({ type: 'ceo', ceo: this.ceoInfo() });\n }\n\n /** Queue a job for the CEO: one onboarding or plan per floor, one review, and chat messages merge into one reply. */\n private enqueueCeo(job: CeoJob) {\n const q = this.state.ceo.queue;\n if (job.kind === 'plan' && q.some((j) => j.kind === 'onboard' && j.repoId === job.repoId)) return; // onboarding plans from the brief too\n const same = q.findIndex((j) => j.kind === job.kind && (job.kind === 'review' || job.kind === 'chat' || j.repoId === job.repoId));\n if (same >= 0) q[same] = job.kind === 'chat' ? { ...q[same], text: `${q[same].text}\\n${job.text}` } : job;\n else q.push(job);\n this.emitCeo();\n this.save();\n setTimeout(() => this.schedule(), 150);\n }\n\n /** Start the CEO's next job when they're free and a session slot is open. Replies to the manager go first. */\n private startCeoWork(): void {\n const a = this.state.agents.find((x) => x.id === CEO_ID);\n const c = this.state.ceo;\n if (!a || BUSY.includes(a.status) || c.job || c.queue.length === 0) return;\n if (this.slotsFull()) return;\n const rank: Record<CeoJob['kind'], number> = { chat: 0, onboard: 1, plan: 1, review: 2 };\n // A floor's jobs wait for its clone and first sync, so the CEO has something to read.\n const ready = (j: CeoJob) => {\n const rt = j.repoId ? this.repoRt.get(j.repoId) : undefined;\n return !rt || rt.cloneStatus === 'error' || (rt.cloneStatus === 'ready' && rt.lastSync != null);\n };\n const job = [...c.queue].sort((x, y) => rank[x.kind] - rank[y.kind]).find(ready);\n if (!job) return;\n c.queue.splice(c.queue.indexOf(job), 1);\n const rt = job.repoId ? this.repoRt.get(job.repoId) : undefined;\n if (job.repoId && (!rt || rt.cloneStatus === 'error')) {\n const repo = this.state.repos.find((r) => r.id === job.repoId);\n if (repo) this.postMessage('office', `\u26A0\uFE0F ${a.name} couldn't study floor ${repo.floor}: the repository clone failed (${rt?.cloneError ?? 'unknown error'}).`);\n this.emitCeo();\n this.save();\n return this.startCeoWork();\n }\n void this.runCeoJob(a, job);\n }\n\n private ceoPromptInput(a: PersistedAgent): Parameters<typeof ceoSystemPrompt>[0] {\n const s = this.state.settings;\n return { name: a.name, company: s.companyName, manager: s.managerName, notesFile: path.join(CEO_DIR, 'NOTES.md'), sessionLimit: s.sessionLimit, teamCap: s.teamCap, hiring: s.hiring };\n }\n\n private async runCeoJob(a: PersistedAgent, job: CeoJob) {\n const rt = this.agentRt.get(a.id)!;\n const floor = this.ceoFloor(job.repoId);\n const label = jobLabel(job, floor);\n this.state.ceo.job = job;\n Object.assign(a, { status: 'working' as AgentStatus, task: null, issueNumber: null, issueTitle: label, startedAt: Date.now(), endedAt: null, costUsd: 0, turns: 0, lastError: null });\n this.appendLog(a, [\n { kind: 'system', text: '' },\n { kind: 'system', text: `\u2501\u2501\u2501 ${label} \u2501\u2501\u2501` },\n ]);\n if (job.kind === 'chat') this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${job.text}` }]);\n if (job.kind === 'review') {\n this.state.ceo.lastReviewAt = Date.now();\n this.state.ceo.lastFingerprint = this.fingerprint();\n }\n this.ceoIssues = new IssueCap(MAX_ISSUES_PER_JOB);\n this.emitAgent(a);\n this.emitCeo();\n this.save();\n await fs.mkdir(CEO_DIR, { recursive: true }).catch(() => undefined);\n if (a.status !== 'working') {\n // stopped before the session started\n this.state.ceo.job = null;\n this.emitCeo();\n return;\n }\n // A chat carries on from the CEO's last session, so \"why did you propose that?\" has an answer.\n const how = this.sessionRuntime(a, job.kind === 'chat' ? (a.sessionId ?? undefined) : undefined);\n rt.session = this.backend.startSession(\n {\n cwd: CEO_DIR,\n prompt: ceoJobPrompt(job, floor),\n systemAppend: ceoSystemPrompt(this.ceoPromptInput(a)),\n model: a.model || CEO_MODEL,\n effort: a.effort || CEO_EFFORT,\n browserTesting: false,\n additionalDirectories: this.state.repos.filter((r) => this.repoRt.get(r.id)?.cloneStatus === 'ready').map((r) => this.backend.mainDir(r.fullName)),\n role: 'ceo',\n office: this.officeTools(),\n ...how,\n },\n {\n log: (entries) => this.appendLog(a, entries),\n tool: (name) => {\n if (rt.currentTool === name) return;\n rt.currentTool = name;\n this.emitAgent(a);\n },\n sessionId: (id) => {\n a.sessionId = id;\n a.sessionCli = id ? 'claude' : null;\n },\n browserUrl: () => undefined,\n screenshot: () => undefined,\n turn: (text) => this.postMessage('ceo', text),\n limited: (at) => this.pauseForLimit(at),\n usageWarning: (info) => this.paceForWarning(info),\n finished: (result) => this.onCeoFinished(a, result),\n },\n );\n }\n\n private onCeoFinished(a: PersistedAgent, result: SessionResult) {\n const rt = this.agentRt.get(a.id);\n if (!rt || this.officeUpdate.handedOver) return;\n rt.session = null;\n rt.currentTool = null;\n a.endedAt = Date.now();\n a.costUsd += result.costUsd;\n a.turns += result.turns;\n const job = this.state.ceo.job;\n this.state.ceo.job = null;\n if (result.interrupted) this.interrupted(a);\n if (a.status === 'stopped') {\n // the manager already logged the stop\n } else if (!result.ok) {\n a.status = 'error';\n a.lastError = result.errors.join('; ') || 'Session failed';\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\n const what = job ? jobLabel(job, this.ceoFloor(job.repoId)).toLowerCase() : 'working';\n this.postMessage('office', `\u26A0\uFE0F ${a.name} hit a problem while ${what}: ${a.lastError.slice(0, 240)}`);\n } else {\n a.status = 'done';\n const filed = this.ceoIssues.total ? ` \u00B7 ${this.ceoIssues.total} issue${this.ceoIssues.total === 1 ? '' : 's'} filed` : '';\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Done in ${this.minutes(a)}m \u00B7 ${a.turns} turns${filed}` }]);\n }\n for (const id of this.ceoIssues.repos) void this.syncRepo(id);\n this.emitAgent(a);\n this.emitCeo();\n this.save();\n setTimeout(() => this.schedule(), 300);\n }\n\n /** The manager's phone \u2192 the CEO. Injected into a running session, otherwise the CEO picks it up next. */\n async messageCeo(text: string) {\n const t = text.trim().slice(0, 4000);\n if (!t) throw new HttpError(400, 'Empty message');\n const a = this.ceo();\n this.postMessage('manager', t);\n const rt = this.agentRt.get(a.id)!;\n if (rt.session) {\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${t}` }]);\n this.ceoIssues.managerMessage(); // a new request: the issue cap counts from here\n rt.session.send(`Message from the manager (they read your reply on their phone, so keep it short):\\n${t}`);\n return;\n }\n this.enqueueCeo({ kind: 'chat', text: t, at: Date.now() });\n }\n\n requestReview() {\n if (this.state.repos.length === 0) throw new HttpError(400, 'Connect a repo first: the CEO needs a floor to review.');\n this.enqueueCeo({ kind: 'review', at: Date.now() });\n }\n\n onboardFloor(repoId: string) {\n const repo = this.repo(repoId);\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\n }\n\n /** The manager hands the CEO a brief for a floor; the CEO turns it into issues and a team. */\n planFloor(repoId: string, mission?: string) {\n const repo = this.repo(repoId);\n if (typeof mission === 'string') {\n repo.mission = mission.trim().slice(0, 4000);\n this.emitRepo(repo);\n }\n if (!repo.mission) throw new HttpError(400, 'Write a brief first: what should this floor build?');\n this.enqueueCeo({ kind: 'plan', repoId: repo.id, at: Date.now() });\n }\n\n /** Everything the heartbeat cares about. When it hasn't changed since the last review, the review is skipped. */\n private fingerprint() {\n const data = {\n repos: this.state.repos.map((r) => {\n const rt = this.repoRt.get(r.id);\n return [r.id, r.mission, r.summary, rt?.issues.map((i) => i.number), rt?.pulls.filter((p) => p.state === 'OPEN').map((p) => p.number)];\n }),\n agents: this.state.agents.filter((a) => a.role !== 'ceo').map((a) => [a.id, FREE.includes(a.status) ? 'free' : a.status]),\n qa: this.state.qa.map((q) => [q.repoId, q.prNumber, q.status]),\n requests: this.state.requests.filter((r) => r.status === 'pending').map((r) => r.id),\n };\n return crypto.createHash('sha1').update(JSON.stringify(data)).digest('hex');\n }\n\n private maybeHeartbeat() {\n const min = this.state.settings.ceoHeartbeatMin;\n const c = this.state.ceo;\n if (!min || this.state.repos.length === 0 || c.job?.kind === 'review' || c.queue.some((j) => j.kind === 'review')) return;\n if (Date.now() < (c.lastReviewAt ?? 0) + min * 60_000) return;\n if (this.fingerprint() === c.lastFingerprint) {\n c.lastReviewAt = Date.now(); // nothing changed since the last review\n this.emitCeo();\n this.save();\n return;\n }\n this.enqueueCeo({ kind: 'review', at: Date.now() });\n }\n\n // ---------- the phone ----------\n\n private postMessage(from: PhoneMessage['from'], text: string, requestId?: string) {\n const m: PhoneMessage = { id: this.messageSeq++, from, text: text.trim().slice(0, 6000), at: Date.now(), ...(requestId ? { requestId } : {}) };\n this.state.messages.push(m);\n if (this.state.messages.length > KEEP_MESSAGES) this.state.messages.splice(0, this.state.messages.length - KEEP_MESSAGES);\n this.broadcast({ type: 'message', message: m });\n this.save();\n return m;\n }\n\n markPhoneRead(at: number) {\n const t = Math.min(Number(at) || Date.now(), Date.now());\n if (t <= this.state.phoneReadAt) return;\n this.state.phoneReadAt = t;\n this.broadcast({ type: 'phoneRead', at: t });\n this.save();\n }\n\n // ---------- hire and let-go proposals ----------\n\n private addRequest(req: HireRequestView) {\n this.state.requests.push(req);\n const decided = this.state.requests.filter((r) => r.status !== 'pending');\n if (decided.length > KEEP_DECIDED_REQUESTS) {\n const drop = new Set(decided.slice(0, decided.length - KEEP_DECIDED_REQUESTS));\n this.state.requests = this.state.requests.filter((r) => !drop.has(r));\n }\n this.broadcast({ type: 'request', request: req });\n this.save();\n }\n\n private decide(req: HireRequestView, patch: Pick<HireRequestView, 'status' | 'note' | 'decidedBy'>) {\n Object.assign(req, patch, { decidedAt: Date.now() });\n this.broadcast({ type: 'request', request: req });\n this.save();\n }\n\n approveRequest(id: string, overrides: { name?: string; model?: string; effort?: string } = {}, by: 'manager' | 'auto' = 'manager') {\n const req = this.state.requests.find((r) => r.id === id);\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\n const repo = this.repo(req.repoId);\n if (req.kind === 'hire') {\n const name = overrides.name?.trim() || req.name;\n const agent = this.hireAgent(repo.id, {\n name,\n role: req.role,\n model: overrides.model ?? req.model,\n effort: overrides.effort ?? req.effort,\n look: name === req.name ? req.look : undefined,\n title: req.title,\n specialty: req.specialty,\n brief: req.brief,\n hiredBy: 'ceo',\n appearance: { color: req.color, hair: req.hair, skin: req.skin },\n });\n req.agentId = agent.id;\n req.name = agent.name;\n this.decide(req, { status: 'approved', note: '', decidedBy: by });\n this.postMessage(\n 'office',\n by === 'auto' ? `\uD83E\uDD16 Auto-approved: ${agent.name} joined floor ${repo.floor} as ${req.title}.` : `\u2705 You hired ${agent.name} as ${req.title} on floor ${repo.floor}.`,\n req.id,\n );\n this.toast('success', `${agent.name} (${req.title}) joined floor ${repo.floor}`);\n return;\n }\n const a = req.agentId ? this.state.agents.find((x) => x.id === req.agentId) : undefined;\n this.decide(req, { status: 'approved', note: a ? '' : 'They had already left.', decidedBy: by });\n if (a) {\n try {\n this.fireAgent(a.id);\n } catch (err) {\n this.decide(req, { status: 'pending', note: '', decidedBy: null });\n throw err;\n }\n }\n this.postMessage('office', `\uD83D\uDC4B ${req.name} left floor ${repo.floor}${by === 'auto' ? ' (auto-approved)' : ''}.`, req.id);\n }\n\n rejectRequest(id: string, note = '') {\n const req = this.state.requests.find((r) => r.id === id);\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\n this.decide(req, { status: 'rejected', note: note.trim().slice(0, 400), decidedBy: 'manager' });\n const what = req.kind === 'hire' ? `${req.name} (${req.title})` : `letting ${req.name} go`;\n this.postMessage('office', `\u270B You declined ${what}${req.note ? `: \"${req.note}\"` : '.'}`, req.id);\n }\n\n // ---------- the CEO's office tools ----------\n\n private floorRepo(floor: number) {\n const r = this.state.repos.find((x) => x.floor === Number(floor));\n if (!r) throw new Error(`There is no floor ${floor}. Floors: ${this.state.repos.map((x) => `${x.floor} (${x.fullName})`).join(', ') || 'none'}.`);\n return r;\n }\n\n private agentByRef(ref: string) {\n const r = String(ref ?? '').trim().toLowerCase();\n const a = this.state.agents.find((x) => x.id === ref || x.name.toLowerCase() === r);\n if (!a) throw new Error(`No agent \"${ref}\". Use the ids from company_status.`);\n return a;\n }\n\n private agentDoing(a: PersistedAgent) {\n return !BUSY.includes(a.status) ? null : a.task === 'qa' ? `testing PR #${a.prNumber}` : a.task === 'fix' ? `fixing PR #${a.prNumber}` : `issue #${a.issueNumber}`;\n }\n\n private companyStatus() {\n const s = this.state.settings;\n const doing = (a: PersistedAgent) => this.agentDoing(a);\n // Keep the status compact, but make the cut visible so the CEO knows to read agent_detail before rewriting.\n const jobDescription = (brief: string) => {\n if (brief.length <= 400) return brief;\n const mark = `\u2026 (truncated, ${brief.length} chars; see agent_detail)`;\n return brief.slice(0, 400 - mark.length).trimEnd() + mark;\n };\n const pending = this.state.requests.filter((r) => r.status === 'pending');\n const seats = (r: PersistedRepo, role: 'dev' | 'qa') =>\n seatCount(\n MAX_DESKS[role],\n this.state.agents.filter((a) => a.repoId === r.id && a.role === role).length,\n pending.filter((p) => p.kind === 'hire' && p.repoId === r.id && p.role === role).length,\n );\n const floors = [...this.state.repos]\n .sort((x, y) => x.floor - y.floor)\n .map((r) => {\n const rt = this.repoRt.get(r.id)!;\n const open = new Set(rt.issues.map((i) => i.number));\n return {\n floor: r.floor,\n repo: r.fullName,\n description: r.description,\n clone: rt.cloneStatus === 'ready' ? this.backend.mainDir(r.fullName) : `(not available: clone ${rt.cloneStatus})`,\n brief: r.mission || null,\n profile: r.summary || null,\n qaBrief: r.qaBrief || null,\n preview: { command: r.preview.command, env: r.preview.env, status: this.previews.view(r).status },\n autoAssign: r.autoAssign,\n autoMerge: r.autoMerge,\n folderSync: rt.folderSync,\n seats: { dev: seats(r, 'dev'), qa: seats(r, 'qa') },\n capacity: {\n developers: this.state.agents.filter((a) => a.repoId === r.id && a.role === 'dev').length,\n developersFree: this.available(r, 'dev').length,\n issuesReadyToStart: this.readyIssues(r).length,\n issuesWaitingOnOthers: rt.issues.filter((i) => blockers(i.body, open).length > 0).length,\n longestDependencyChain: Math.max(0, ...[...holdUps(rt.issues).values()].map((w) => w.chain)),\n },\n team: this.state.agents\n .filter((a) => a.repoId === r.id)\n .map((a) => ({\n id: a.id,\n name: a.name,\n role: a.role,\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\n specialty: a.specialty || null,\n status: a.status,\n doing: doing(a),\n hiredBy: a.hiredBy,\n jobDescription: a.brief ? jobDescription(a.brief) : null,\n })),\n backlog: rt.issues.map((i) => ({\n number: i.number,\n title: i.title,\n specialty: issueSpecialty(i.labels) || null,\n waitsFor: blockers(i.body, open),\n inProgress: this.issueTaken(r, i.number),\n })),\n pullRequests: rt.pulls\n .filter((p) => p.state === 'OPEN')\n .map((p) => {\n const q = this.state.qa.find((x) => x.repoId === r.id && x.prNumber === p.number);\n return { number: p.number, title: p.title, qa: q ? `${q.status}${q.round > 1 ? ` (round ${q.round})` : ''}` : 'not tested', merge: q?.mergeNote ?? null, checks: p.checks };\n }),\n mergedRecently: rt.pulls.filter((p) => p.state === 'MERGED').map((p) => `#${p.number} ${p.title}`),\n };\n });\n const req = (r: HireRequestView) => ({\n id: r.id,\n kind: r.kind,\n floor: this.state.repos.find((x) => x.id === r.repoId)?.floor ?? null,\n role: r.role,\n name: r.name,\n title: r.title,\n specialty: r.specialty || null,\n reason: r.reason,\n status: r.status,\n managerNote: r.note || null,\n });\n return JSON.stringify(\n {\n company: {\n ceo: this.ceo().name,\n hiring: s.hiring === 'auto' ? `auto-approved while a floor has fewer than ${s.teamCap} people` : 'the manager approves every proposal',\n teamCap: s.teamCap,\n sessionLimit: s.sessionLimit || 'none',\n sessionsRunning: this.running(),\n usage: usageLabel(this.usageNow(), Date.now()),\n deskLimits: { dev: MAX_DESKS.dev, qa: MAX_DESKS.qa },\n proposalLimit: { pending: pending.length, max: MAX_PENDING_PROPOSALS },\n },\n floors,\n pendingProposals: pending.map(req),\n recentDecisions: this.state.requests.filter((r) => r.status !== 'pending').slice(-10).map(req),\n },\n null,\n 1,\n );\n }\n\n private agentDetail(x: { agent_id: string }) {\n const a = this.agentByRef(x.agent_id);\n const repo = this.state.repos.find((r) => r.id === a.repoId);\n const ceo = a.role === 'ceo';\n return JSON.stringify(\n {\n id: a.id,\n name: a.name,\n floor: repo?.floor ?? null,\n role: a.role,\n title: a.title || (a.role === 'qa' ? 'QA tester' : a.role === 'dev' ? 'Developer' : 'CEO'),\n specialty: a.specialty || null,\n status: a.status,\n doing: this.agentDoing(a),\n issue: a.issueNumber ? { number: a.issueNumber, title: a.issueTitle } : null,\n pullRequest: a.prNumber ? { number: a.prNumber, url: a.prUrl } : null,\n codingAgent: ceo ? 'claude' : a.cli || this.state.settings.defaultCli,\n model: ceo ? a.model || CEO_MODEL : this.modelFor(a, a.cli || this.state.settings.defaultCli) || 'the coding agent default',\n effort: a.effort || (ceo ? CEO_EFFORT : this.state.settings.defaultEffort),\n hiredBy: a.hiredBy,\n jobDescription: a.brief || null,\n },\n null,\n 1,\n );\n }\n\n private setFloorProfile(x: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }) {\n const r = this.floorRepo(x.floor);\n const preview = parsePreviewPatch(x.preview_command, x.preview_env);\n if (x.summary !== undefined) r.summary = String(x.summary).trim().slice(0, 140);\n if (x.qa_brief !== undefined) r.qaBrief = String(x.qa_brief).trim().slice(0, 2500);\n r.preview = { ...r.preview, ...preview };\n if (preview.command === null) void this.previews.refreshDefault(r);\n this.emitRepo(r);\n this.save();\n return `Saved floor ${r.floor}'s profile.`;\n }\n\n private updateJob(x: { agent_id: string; title?: string; specialty?: string; job_description?: string }) {\n const a = this.agentByRef(x.agent_id);\n if (a.role === 'ceo') throw new Error(\"That's you.\");\n this.updateAgent(a.id, { title: x.title, specialty: x.specialty, brief: x.job_description });\n const title = a.title || (a.role === 'qa' ? 'QA tester' : 'Developer');\n this.appendLog(a, [{ kind: 'system', text: `\uD83E\uDEAA ${this.ceo().name} updated ${a.name}'s job: ${title}${a.specialty ? ` \u00B7 swarm:${a.specialty}` : ''}` }]);\n return `Updated ${a.name}: ${title}${a.specialty ? ` (specialty ${a.specialty})` : ''}.`;\n }\n\n private proposeHire(x: { floor: number; role: 'dev' | 'qa'; title: string; specialty: string; job_description: string; reason: string; model?: string; effort?: string }) {\n const repo = this.floorRepo(x.floor);\n const role = x.role === 'qa' ? 'qa' : 'dev';\n const title = String(x.title ?? '').trim().slice(0, 60);\n if (!title) throw new Error('A hire needs a job title.');\n const specialty = specialtySlug(x.specialty);\n const pending = this.state.requests.filter((r) => r.status === 'pending');\n checkPendingLimit(pending.length);\n const dup =pending.find((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role && r.specialty === specialty);\n if (dup) throw new Error(`${dup.name} (${dup.title}) is already proposed for floor ${repo.floor} with that specialty.`);\n const seated = this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).length;\n const waiting = pending.filter((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role).length;\n if (seated + waiting >= MAX_DESKS[role]) throw new Error(role === 'qa' ? `The QA lab on floor ${repo.floor} is full.` : `Floor ${repo.floor} has no free desks.`);\n const name = this.freeName(role);\n const req: HireRequestView = {\n id: crypto.randomUUID(),\n kind: 'hire',\n repoId: repo.id,\n role,\n agentId: null,\n name,\n title,\n specialty,\n brief: String(x.job_description ?? '').trim().slice(0, 2500),\n reason: String(x.reason ?? '').trim().slice(0, 600),\n model: String(x.model ?? '').trim(),\n effort: EFFORTS.includes(x.effort as EffortLevel) ? (x.effort as EffortLevel) : '',\n look: lookFor(name),\n color: pick(SHIRTS),\n hair: pick(HAIR),\n skin: pick(SKIN),\n status: 'pending',\n note: '',\n createdAt: Date.now(),\n decidedAt: null,\n decidedBy: null,\n };\n this.addRequest(req);\n const s = this.state.settings;\n if (s.hiring === 'auto' && this.state.agents.filter((a) => a.repoId === repo.id).length < s.teamCap) {\n this.approveRequest(req.id, {}, 'auto');\n return `Hired ${req.name} as ${title} on floor ${repo.floor} (auto-approved; agent id ${req.agentId}).`;\n }\n this.postMessage('ceo', `\uD83D\uDCC4 New candidate for floor ${repo.floor}: ${name}, ${title}. ${req.reason}`, req.id);\n return `Proposed ${name} as ${title} on floor ${repo.floor}. The manager will approve or decline (request ${req.id}).`;\n }\n\n private proposeLetGo(x: { agent_id: string; reason: string }) {\n const a = this.agentByRef(x.agent_id);\n if (a.role === 'ceo') throw new Error(\"You can't let yourself go.\");\n const repo = this.repo(a.repoId);\n if (a.role === 'qa' && this.state.agents.filter((y) => y.repoId === repo.id && y.role === 'qa').length <= 1) {\n throw new Error(`${a.name} is floor ${repo.floor}'s only QA tester, and every floor keeps one.`);\n }\n const pending = this.state.requests.filter((r) => r.status === 'pending');\n if (pending.some((r) => r.kind === 'let-go' && r.agentId === a.id)) throw new Error(`Letting ${a.name} go is already proposed.`);\n checkPendingLimit(pending.length);\n const req: HireRequestView = {\n id: crypto.randomUUID(),\n kind: 'let-go',\n repoId: repo.id,\n role: a.role,\n agentId: a.id,\n name: a.name,\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\n specialty: a.specialty,\n brief: a.brief,\n reason: String(x.reason ?? '').trim().slice(0, 600),\n model: a.model,\n effort: a.effort,\n look: a.look,\n color: a.color,\n hair: a.hair,\n skin: a.skin,\n status: 'pending',\n note: '',\n createdAt: Date.now(),\n decidedAt: null,\n decidedBy: null,\n };\n this.addRequest(req);\n if (this.state.settings.hiring === 'auto' && FREE.includes(a.status)) {\n this.approveRequest(req.id, {}, 'auto');\n return `Let ${a.name} go (auto-approved).`;\n }\n this.postMessage('ceo', `\uD83D\uDC4B I suggest letting ${a.name} (${req.title}, floor ${repo.floor}) go. ${req.reason}`, req.id);\n return `Proposed letting ${a.name} go. The manager will decide (request ${req.id}).`;\n }\n\n private async fileIssue(x: { floor: number; title: string; body: string; specialty?: string }) {\n const repo = this.floorRepo(x.floor);\n this.ceoIssues.check();\n const title = String(x.title ?? '').trim().slice(0, 120);\n if (!title) throw new Error('An issue needs a title.');\n const slug = specialtySlug(x.specialty);\n const body = `${String(x.body ?? '').trim()}\\n\\n---\\n_Filed by ${this.ceo().name}, the cubefarm CEO._`;\n const n = await this.backend.createIssue(repo.fullName, title, body, slug ? [specialtyLabel(slug)] : []);\n this.ceoIssues.record(repo.id);\n return `Filed #${n} on floor ${repo.floor}: ${title}${slug ? ` (routed to ${slug})` : ''}.`;\n }\n\n /** Change an open issue's specialty and/or dependencies (see planRoute for what is refused). */\n private async routeIssue(x: { floor: number; number: number; specialty?: string; depends_on?: number[] }) {\n const repo = this.floorRepo(x.floor);\n const issues = this.repoRt.get(repo.id)?.issues ?? [];\n const asked = [Number(x.number), ...(x.depends_on ?? []).map(Number)].filter((n) => !issues.some((i) => i.number === n));\n const states = new Map(await Promise.all([...new Set(asked)].map(async (n) => [n, await this.backend.issueState(repo.fullName, n).catch(() => null)] as const)));\n const specialties = [\n ...this.state.agents.filter((a) => a.repoId === repo.id && a.specialty).map((a) => a.specialty.toLowerCase()),\n ...this.state.requests.filter((r) => r.status === 'pending' && r.kind === 'hire' && r.repoId === repo.id && r.specialty).map((r) => r.specialty),\n ];\n const plan = planRoute({\n floor: repo.floor,\n number: Number(x.number),\n specialty: x.specialty,\n dependsOn: x.depends_on,\n issues,\n closed: (n) => states.get(n) === 'CLOSED',\n inProgress: this.issueTaken(repo, Number(x.number)),\n specialties,\n });\n if (plan.body !== null || plan.addLabels.length || plan.removeLabels.length) {\n await this.backend.editIssue(repo.fullName, Number(x.number), { body: plan.body ?? undefined, addLabels: plan.addLabels, removeLabels: plan.removeLabels });\n await this.syncRepo(repo.id); // the scheduler sees the new routing right away\n }\n return plan.summary;\n }\n}\n", "import { createSdkMcpServer, tool, type McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';\nimport { z } from 'zod';\nimport { blockers, holdUps, setDependsOn } from '../shared/issues.ts';\nimport type { CeoJobKind } from '../shared/types.ts';\n\n// The CEO: a Claude Code session in the lobby that runs the company instead of writing code.\n// It studies each floor's repo, shapes the team (hire / let-go proposals the manager approves),\n// plans work as GitHub issues, and writes each floor's QA brief. Everything it changes goes\n// through the office tools below, so the swarm stays the single source of truth.\n\nexport interface CeoJob {\n kind: CeoJobKind;\n repoId?: string; // onboard / plan\n text?: string; // chat: the manager's message(s)\n at: number;\n}\n\n/** What the CEO's tools do. Implemented by the swarm; errors are returned to the CEO as tool errors. */\nexport interface OfficeHandlers {\n companyStatus(): string;\n agentDetail(a: { agent_id: string }): string;\n setFloorProfile(a: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }): string;\n updateJob(a: { agent_id: string; title?: string; specialty?: string; job_description?: string }): string;\n proposeHire(a: {\n floor: number;\n role: 'dev' | 'qa';\n title: string;\n specialty: string;\n job_description: string;\n reason: string;\n model?: string;\n effort?: string;\n }): string;\n proposeLetGo(a: { agent_id: string; reason: string }): string;\n fileIssue(a: { floor: number; title: string; body: string; specialty?: string }): Promise<string>;\n routeIssue(a: { floor: number; number: number; specialty?: string; depends_on?: number[] }): Promise<string>;\n}\n\nexport interface OfficeTools {\n server: McpSdkServerConfigWithInstance;\n /** A fresh MCP server with the same tools, for one request from a CEO running in a terminal (served over HTTP). */\n serve(): McpSdkServerConfigWithInstance['instance'];\n /** Run a tool without a model in the loop (the demo CEO). */\n call(name: string, args: Record<string, unknown>): Promise<string>;\n}\n\nconst EFFORT = z.enum(['low', 'medium', 'high', 'xhigh', 'max']);\n\nexport function createOfficeTools(h: OfficeHandlers): OfficeTools {\n const run = async (fn: () => string | Promise<string>) => {\n try {\n return { content: [{ type: 'text' as const, text: await fn() }] };\n } catch (err) {\n return { content: [{ type: 'text' as const, text: `Refused: ${(err as Error).message}` }], isError: true };\n }\n };\n const defs = [\n tool(\n 'company_status',\n 'Everything about the company right now: settings, every floor (repo, clone path, brief, profile, QA brief), its free seats, team, backlog, pull requests and QA, pending proposals and recent decisions by the manager. Call this first.',\n {},\n () => run(() => h.companyStatus()),\n ),\n tool(\n 'agent_detail',\n \"One agent in full: title, specialty, role, status, current task, model and effort, and their complete job description (company_status shortens long ones). Read it before rewriting someone's job description.\",\n { agent_id: z.string().describe('An id (or name) from company_status') },\n (a) => run(() => h.agentDetail(a)),\n ),\n tool(\n 'set_floor_profile',\n \"Record your read of a floor's project: a one-line summary (kind of project and stack), the QA brief that tells QA testers what to check for this kind of project, and how to run the app for the floor's preview monitor.\",\n {\n floor: z.number().int().describe('Floor number'),\n summary: z.string().max(140).optional().describe('e.g. \"3D browser game \u00B7 Three.js + Vite + TypeScript\"'),\n qa_brief: z.string().max(2500).optional().describe('What QA must check on every PR for this project, as short bullet points'),\n preview_command: z\n .string()\n .max(2000)\n .optional()\n .describe(\n 'Shell command that serves the app on port {port} from a fresh checkout after npm install, e.g. \"npm run dev -- --port {port} --strictPort\". PORT={port} is always set. {tmp} is a scratch folder. Empty string: back to the default (npm run dev, else start, else preview). Only set it when the default would not serve the app on PORT.',\n ),\n // Not z.record(): the SDK can't turn it into JSON Schema, and one bad tool empties the whole tools/list.\n preview_env: z\n .object({})\n .catchall(z.string())\n .optional()\n .describe('Extra environment variables for the preview; {port} and {tmp} are replaced in the values. Replaces the whole set.'),\n },\n (a) => run(() => h.setFloorProfile(a)),\n ),\n tool(\n 'update_job',\n \"Change an existing agent's job title, specialty or job description so it fits the project. Takes effect from their next task.\",\n {\n agent_id: z.string(),\n title: z.string().max(60).optional(),\n specialty: z.string().max(24).optional().describe('Short lowercase slug, e.g. \"graphics\"; \"\" for a generalist'),\n job_description: z.string().max(2500).optional(),\n },\n (a) => run(() => h.updateJob(a)),\n ),\n tool(\n 'propose_hire',\n 'Propose hiring a developer or QA tester for a floor. The manager approves or declines (or it is auto-approved if hiring is set to auto and the floor is under its team cap).',\n {\n floor: z.number().int(),\n role: z.enum(['dev', 'qa']).describe('dev = builds issues into pull requests; qa = tests pull requests'),\n title: z.string().max(60).describe('Specific job title, e.g. \"Three.js graphics engineer\"'),\n specialty: z.string().max(24).describe('Short lowercase slug used to label issues swarm:<specialty>, e.g. \"graphics\"'),\n job_description: z.string().max(2500).describe('What this person owns on this project and how they should work. Written to them, second person.'),\n reason: z.string().max(600).describe('Why the floor needs them now. The manager reads this.'),\n model: z.string().optional().describe('Leave out to use the default model'),\n effort: EFFORT.optional().describe('Leave out to use the default effort'),\n },\n (a) => run(() => h.proposeHire(a)),\n ),\n tool(\n 'propose_let_go',\n 'Propose letting an agent go (overstaffed floor, specialty no longer needed). The manager decides.',\n { agent_id: z.string(), reason: z.string().max(600) },\n (a) => run(() => h.proposeLetGo(a)),\n ),\n tool(\n 'file_issue',\n 'File a GitHub issue on a floor. A specialty routes it to that specialist first; when none is free, any free developer takes it. Write \"Depends on #N\" in the body only when it cannot start until #N is merged: the office will not start it until #N is closed.',\n {\n floor: z.number().int(),\n title: z.string().max(120),\n body: z.string().max(6000).describe('Context, what to build, acceptance criteria'),\n specialty: z.string().max(24).optional(),\n },\n (a) => run(() => h.fileIssue(a)),\n ),\n tool(\n 'route_issue',\n 'Fix the routing of an open issue instead of filing a duplicate: change its specialty, rewrite its \"Depends on #N\" line, or both. The rest of the body stays as it is.',\n {\n floor: z.number().int(),\n number: z.number().int().positive().describe('The issue number'),\n specialty: z.string().max(24).optional().describe('Sets swarm:<specialty> and removes any other; \"\" for none. Someone on the floor, or a pending proposal, must have it.'),\n depends_on: z.array(z.number().int().positive()).max(10).optional().describe('Issues it waits for; [] for none. Not for an issue in progress.'),\n },\n (a) => run(() => h.routeIssue(a)),\n ),\n ];\n const server = createSdkMcpServer({ name: 'office', version: '1.0.0', tools: defs });\n return {\n server,\n serve: () => createSdkMcpServer({ name: 'office', version: '1.0.0', tools: defs }).instance,\n async call(name, args) {\n const def = defs.find((d) => d.name === name);\n if (!def) throw new Error(`No office tool ${name}`);\n const res = (await def.handler(args as never, undefined)) as { content: { text?: string }[] };\n return res.content.map((c) => c.text ?? '').join('\\n');\n },\n };\n}\n\n// ---------- seats ----------\n\n/** Desks per floor. client/src/world/layout.ts draws the same number (ceo.test.ts checks they match). */\nexport const FLOOR_DESKS = { dev: 12, qa: 3 } as const;\n/** Pending proposals the manager can have waiting: enough to staff one empty floor in one go. */\nexport const MAX_PENDING_PROPOSALS = FLOOR_DESKS.dev + FLOOR_DESKS.qa;\n\nexport interface SeatCount {\n total: number;\n taken: number;\n /** Pending hire proposals for these seats. */\n proposed: number;\n free: number;\n}\n\nexport const seatCount = (total: number, taken: number, proposed: number): SeatCount => ({ total, taken, proposed, free: Math.max(0, total - taken - proposed) });\n\n/** Refuses a proposal while the manager already has the most they can be asked to decide on. */\nexport function checkPendingLimit(pending: number, max = MAX_PENDING_PROPOSALS) {\n if (pending >= max) throw new Error(`${pending} proposals are already waiting for the manager; propose the rest after they decide.`);\n}\n\n// ---------- prompts ----------\n\nexport function ceoSystemPrompt(o: {\n name: string;\n company: string;\n manager: string;\n notesFile: string;\n sessionLimit: number;\n teamCap: number;\n hiring: 'approve' | 'auto';\n}) {\n const manager = o.manager ? `the manager, ${o.manager}` : 'the human manager';\n return [\n `You are ${o.name}, the CEO of ${o.company || 'an autonomous software company'}, run from an office building called cubefarm. You work from the corner office in the lobby.`,\n `Every floor of the building is one GitHub repository with its own team of AI coding agents. Developers pick up GitHub issues, each in their own git worktree, and open pull requests. QA testers review and verify every pull request (code review, tests, build, and a real browser via Playwright); when every tester is busy, a free developer who didn't write the PR covers QA. On floors with auto-merge on, the office merges a PR by itself once QA passes and GitHub's checks are green, and sends failing checks or merge conflicts back to a developer; on the others, ${manager} merges. The manager is your board: they approve hires and let-gos.`,\n '',\n 'Your job is to run the company, not to write code:',\n '- Understand each project: what it is, its stack, how far along it is, and what kind of people it needs. Projects differ a lot. A static marketing site, a 3D browser game and a REST API need different specialists and different QA.',\n `- Shape each floor's team. Propose specialists with a specific title and a job description written for this project. Keep teams lean: agents on the same coding agent share one subscription's usage limits${o.sessionLimit ? ` and at most ${o.sessionLimit} sessions run at once` : ''}, so a floor rarely needs more than ${o.teamCap} people. When the manager asks for a bigger team, follow that, up to the floor's free seats (seats in company_status). Propose letting people go when a floor is clearly overstaffed or a specialty is no longer needed.`,\n \"- Plan the work: turn a floor's brief into small, well-specified GitHub issues, one agent-session each, with acceptance criteria. Route each to a specialty. The office hands issues out itself: a free specialist gets first pick of their specialty, and otherwise any free developer takes the next issue that can start, so a specialty is a preference, not a lock.\",\n \"- Write each floor's QA brief: what QA testers must check for this kind of project (for a 3D game: the canvas renders, controls respond, frame rate is smooth; for a website: links, phone layout, accessibility; for an API: status codes, validation, error cases).\",\n '',\n 'How you work:',\n '- Call mcp__office__company_status first. It lists every floor, its clone path, team, backlog, pull requests and your pending proposals.',\n '- Read the repositories through their clone paths with Read, Glob and Grep. They are read-only to you. You cannot run shell commands.',\n `- Keep durable notes about the company in ${o.notesFile}: read it at the start, and update it at the end with decisions and anything worth remembering next time.`,\n '- Change things only through the mcp__office__ tools.',\n \"- Before update_job rewrites someone's job description, read the full one with mcp__office__agent_detail and keep what still applies, especially its safety rules.\",\n '',\n 'Rules:',\n '- Every floor keeps at least one QA tester.',\n '- Titles are specific (\"Three.js graphics engineer\", not \"Developer\"). A specialty is a short lowercase slug (\"graphics\", \"gameplay\", \"frontend\", \"backend\", \"content\", \"a11y\", \"devops\"). Only route an issue to a specialty that someone on the floor has, or that you are proposing to hire.',\n '- Before proposing a hire, check the floor and the pending proposals for someone who already covers it. If the manager declined a similar proposal (recentDecisions), do not propose it again unless something has changed, and say what.',\n `- ${o.hiring === 'auto' ? 'Hiring is on auto: proposals within the team cap are approved immediately, so be deliberate.' : 'The manager approves every hire, so explain each reason in a sentence or two they can decide on.'}`,\n '- Issues: plan for parallel work. What keeps a floor busy is the number of issues that can start right now (capacity.issuesReadyToStart in company_status); aim for at least one per developer. Write \"Depends on #N\" only when an issue truly cannot start until #N\\'s code is merged, because it waits until #N is closed. Keep dependency chains to two steps at most, keep foundation issues small, and split big pieces into parts that can be built side by side. The office starts the issues that hold up others first. Do not duplicate open issues: fix an existing issue\\'s specialty or dependencies with route_issue. File at most 12 issues per job, or per message from the manager.',\n \"- When company.usage in company_status says pacing or paused, Claude's usage is running low and the office is finishing open work first: file only what is needed next, not a whole milestone.\",\n '- Your final message goes straight to the manager\\'s phone. Keep it short and plain: what you found, what you proposed, what you filed, and any question you need answered. No headings, no tables.',\n ].join('\\n');\n}\n\nexport function ceoJobPrompt(job: CeoJob, floor: { floor: number; fullName: string; clone: string; mission: string; backlog: number } | null): string {\n switch (job.kind) {\n case 'onboard':\n if (!floor) return 'A floor was added but has since been removed. Reply \"Nothing to do.\"';\n return [\n `Floor ${floor.floor} (${floor.fullName}) just joined the company. Its read-only clone is at ${floor.clone}.`,\n 'Study it: README, package manifest, source layout, tests, and how far along it is. Then:',\n \"1. set_floor_profile with a one-line summary and a QA brief for this project. If npm run dev / start / preview wouldn't serve the app on PORT, also set preview_command (and preview_env) so the floor's preview monitor can run it.\",\n '2. update_job for the people already on the floor so their titles, specialties and job descriptions fit this project (every floor starts with a generalist QA tester).',\n '3. Propose the hires this project needs. Usually two to four developers with distinct specialties is plenty.',\n floor.mission\n ? `4. The manager's brief for this floor: \"\"\"${floor.mission}\"\"\"\\n${floor.backlog === 0 ? 'The backlog is empty: plan the first milestone as issues.' : `There are ${floor.backlog} open issues: add issues only for what the brief needs and the backlog does not cover.`}`\n : floor.backlog === 0\n ? '4. There is no brief and the backlog is empty. Do not invent work; suggest in your final message what the manager might want next.'\n : `4. There are ${floor.backlog} open issues. Label nothing retroactively; just make sure the team can cover them.`,\n ].join('\\n');\n case 'plan':\n if (!floor) return 'A floor you were asked to plan has been removed. Reply \"Nothing to do.\"';\n return [\n `The manager has a brief for floor ${floor.floor} (${floor.fullName}, clone at ${floor.clone}):`,\n `\"\"\"${floor.mission}\"\"\"`,\n '',\n 'Plan the next milestone toward it:',\n `- Read the current code and the ${floor.backlog} open issues first, so you build on what exists and do not duplicate anything.`,\n '- If the repository is empty or nearly empty, the first issue sets up a small project skeleton, and the others depend on it. Everything after that should be able to run side by side.',\n '- File the issues, each routed to a specialty.',\n '- Make sure the floor has the specialists those issues need; propose hires if not.',\n '- Update the floor profile and QA brief if the brief changes what the project is.',\n ].join('\\n');\n case 'review':\n return [\n 'Periodic review of the company. For every floor, look at:',\n '- floors without a profile or QA brief: study them and write one',\n '- backlog against the team (capacity): fewer issues ready to start than free developers, long dependency chains, a specialty with a long queue (fix those with route_issue)',\n '- pull requests stuck in QA or marked as needing a human',\n '- floors with a brief and an empty backlog: plan the next milestone',\n 'Propose hires or let-gos only when clearly justified. If nothing needs doing, reply with one short sentence saying so.',\n ].join('\\n');\n case 'chat':\n return `Message from the manager (they're reading your reply on their phone):\\n${job.text ?? ''}`;\n }\n}\n\nexport function jobLabel(job: CeoJob, floor: { floor: number; fullName: string } | null) {\n const where = floor ? `floor ${floor.floor} \u00B7 ${floor.fullName.split('/')[1] ?? floor.fullName}` : 'a removed floor';\n switch (job.kind) {\n case 'onboard':\n return `Onboarding ${where}`;\n case 'plan':\n return `Planning ${where}`;\n case 'review':\n return 'Reviewing the company';\n case 'chat':\n return 'Replying to you';\n }\n}\n\n// ---------- issues ----------\n\n/**\n * The CEO's issue cap: at most `max` issues per request from the manager. A manager message that arrives while the\n * job runs is a new request, so it resets the count.\n */\nexport class IssueCap {\n filed = 0; // since the job started or the manager's last message\n total = 0; // in the whole job\n readonly repos = new Set<string>(); // floors that got issues, to refresh when the job ends\n constructor(readonly max: number) {}\n\n check() {\n if (this.filed >= this.max) throw new Error(`You already filed ${this.max} issues in this job. That's plenty for one milestone. The manager's next message allows more.`);\n }\n\n record(repoId: string) {\n this.filed++;\n this.total++;\n this.repos.add(repoId);\n }\n\n managerMessage() {\n this.filed = 0;\n }\n}\n\nexport interface RouteRequest {\n floor: number;\n number: number;\n specialty?: string; // '' = no specialty\n dependsOn?: number[]; // [] = no dependencies\n issues: { number: number; body: string; labels: string[] }[]; // the floor's open issues\n closed: (n: number) => boolean; // for numbers that aren't open: closed, rather than unknown\n inProgress: boolean;\n specialties: string[]; // held by someone on the floor or by a pending hire proposal for it\n}\n\nexport interface RoutePlan {\n addLabels: string[];\n removeLabels: string[];\n body: string | null; // null: leave the body alone\n summary: string;\n}\n\n/** Longest chain of open issues this one waits for, one step per \"Depends on\". */\nfunction waitsDepth(n: number, deps: Map<number, number[]>, seen = new Set<number>()): number {\n if (seen.has(n)) return 0;\n seen.add(n);\n const depth = Math.max(0, ...(deps.get(n) ?? []).map((d) => waitsDepth(d, deps, seen) + 1));\n seen.delete(n);\n return depth;\n}\n\n/**\n * What route_issue changes, or why it refuses: a closed or unknown issue, a specialty nobody on the floor has,\n * dependencies on an issue in progress, a dependency on itself, on a closed or unknown issue, a cycle, or a chain\n * deeper than two steps.\n */\nexport function planRoute(r: RouteRequest): RoutePlan {\n const issue = r.issues.find((i) => i.number === r.number);\n if (!issue) throw new Error(r.closed(r.number) ? `#${r.number} is closed.` : `There is no open issue #${r.number} on floor ${r.floor}.`);\n if (r.specialty === undefined && r.dependsOn === undefined) throw new Error('Nothing to change: pass specialty, depends_on or both.');\n const plan: RoutePlan = { addLabels: [], removeLabels: [], body: null, summary: '' };\n const done: string[] = [];\n\n if (r.specialty !== undefined) {\n const slug = specialtySlug(r.specialty);\n if (r.specialty.trim() && !slug) throw new Error(`\"${r.specialty}\" is not a specialty. Use a short lowercase slug, or \"\" for none.`);\n if (slug && !r.specialties.includes(slug)) {\n const have = [...new Set(r.specialties)].join(', ') || 'none';\n throw new Error(`Nobody on floor ${r.floor} has the specialty \"${slug}\", and no pending proposal does. Specialties there: ${have}.`);\n }\n const label = slug ? specialtyLabel(slug) : null;\n plan.removeLabels = issue.labels.filter((l) => /^swarm:/i.test(l) && !/^swarm:skip$/i.test(l) && l !== label);\n if (label && !issue.labels.includes(label)) plan.addLabels = [label];\n done.push(slug ? `routed to ${slug}` : 'no specialty');\n }\n\n if (r.dependsOn !== undefined) {\n if (r.inProgress) throw new Error(`#${r.number} is already in progress, so its dependencies can't change. Changing its specialty is fine.`);\n const deps = [...new Set(r.dependsOn.map(Number))];\n const open = new Set(r.issues.map((i) => i.number));\n for (const d of deps) {\n if (d === r.number) throw new Error(`#${r.number} can't depend on itself.`);\n if (!open.has(d)) throw new Error(r.closed(d) ? `#${d} is closed, so there's nothing to wait for.` : `There is no open issue #${d} on floor ${r.floor}.`);\n }\n const body = setDependsOn(issue.body, deps);\n const after = r.issues.map((i) => (i.number === r.number ? { ...i, body } : i));\n const waits = new Map(after.map((i) => [i.number, blockers(i.body, open)]));\n const loop = deps.find((d) => reaches(d, r.number, waits));\n if (loop !== undefined) throw new Error(`#${loop} already waits for #${r.number}, directly or through other issues, so that would be a cycle.`);\n const depth = waitsDepth(r.number, waits) + (holdUps(after).get(r.number)?.chain ?? 0);\n if (depth > 2) throw new Error(`That makes a dependency chain ${depth} steps deep through #${r.number}. Keep chains to 2 steps at most: split the work so more of it can start side by side.`);\n if (body !== issue.body) plan.body = body;\n done.push(deps.length ? `depends on ${deps.map((d) => `#${d}`).join(', ')}` : 'no dependencies');\n }\n\n plan.summary = `#${r.number} on floor ${r.floor}: ${done.join(', ')}.`;\n return plan;\n}\n\n/** Does `from` wait for `to`, directly or through other issues? */\nfunction reaches(from: number, to: number, waits: Map<number, number[]>, seen = new Set<number>()): boolean {\n if (from === to) return true;\n if (seen.has(from)) return false;\n seen.add(from);\n return (waits.get(from) ?? []).some((n) => reaches(n, to, waits, seen));\n}\n\n/** Short lowercase slug for a specialty (\"Three.js graphics\" -> \"three-js-graphics\"). */\nexport function specialtySlug(s: string | undefined) {\n const slug = String(s ?? '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 24);\n return slug === 'skip' ? '' : slug;\n}\n\nexport const specialtyLabel = (slug: string) => `swarm:${slug}`;\n", "// Issue conventions shared by the server's scheduler and the client's whiteboard.\n\n/** The specialty an issue is routed to, from its swarm:<specialty> label ('' = anyone). */\nexport function issueSpecialty(labels: string[]) {\n const l = labels.find((x) => /^swarm:/i.test(x) && !/^swarm:skip$/i.test(x));\n return l ? l.slice(6).toLowerCase() : '';\n}\n\n/** Open issues this issue waits for, from \"Depends on #3\" / \"Blocked by #4, #5\" in its body. */\nexport function blockers(body: string, open: Set<number>) {\n const out = new Set<number>();\n for (const m of (body ?? '').matchAll(/\\b(?:depends\\s+on|blocked\\s+by)\\s*:?\\s*((?:#\\d+(?:\\s*(?:,|and|&)\\s*)?)+)/gi)) {\n for (const n of m[1].matchAll(/#(\\d+)/g)) if (open.has(Number(n[1]))) out.add(Number(n[1]));\n }\n return [...out];\n}\n\nconst DEPENDENCY = /\\b(?:depends\\s+on|blocked\\s+by)\\s*:?\\s*(?:#\\d+(?:\\s*(?:,|and|&)\\s*)?)+/gi;\nconst STATEMENT = new RegExp(`\\\\s*${DEPENDENCY.source}[.;,]?`, 'gi'); // with the space before it and a full stop after\n\n/**\n * An issue body with its \"Depends on #N\" / \"Blocked by #N\" statements replaced by one \"Depends on #a, #b\" line at the\n * top ([] removes them). A line that only said that goes; the rest of the body is left alone.\n */\nexport function setDependsOn(body: string, deps: number[]) {\n const lines: string[] = [];\n let dropped = false;\n for (const line of (body ?? '').split(/\\r?\\n/)) {\n const rest = line.match(DEPENDENCY) ? line.replace(STATEMENT, '').trimEnd() : line;\n if (rest !== line && !/[\\p{L}\\p{N}]/u.test(rest)) {\n dropped = true;\n continue;\n }\n // A dropped line between two paragraphs doesn't leave a double gap.\n if (dropped && !rest.trim() && !lines[lines.length - 1]?.trim()) continue;\n dropped = false;\n lines.push(rest);\n }\n while (lines.length && !lines[0].trim()) lines.shift();\n const rest = lines.join('\\n');\n if (deps.length === 0) return rest;\n return `Depends on ${deps.map((n) => `#${n}`).join(', ')}${rest ? `\\n\\n${rest}` : ''}`;\n}\n\n/**\n * How much of the backlog each open issue holds up: the longest chain of open issues waiting on it (`chain`) and how\n * many wait on it directly or indirectly (`waiting`). Starting the issues with the most behind them first lets the\n * most work run in parallel later.\n */\nexport function holdUps(issues: { number: number; body: string }[]) {\n const open = new Set(issues.map((i) => i.number));\n const waiters = new Map<number, number[]>();\n for (const i of issues) for (const b of blockers(i.body, open)) waiters.set(b, [...(waiters.get(b) ?? []), i.number]);\n const chains = new Map<number, number>();\n const visiting = new Set<number>();\n const chain = (n: number): number => {\n const known = chains.get(n);\n if (known !== undefined) return known;\n if (visiting.has(n)) return 0; // a dependency cycle\n visiting.add(n);\n const longest = Math.max(0, ...(waiters.get(n) ?? []).map((w) => chain(w) + 1));\n visiting.delete(n);\n chains.set(n, longest);\n return longest;\n };\n const out = new Map<number, { chain: number; waiting: number }>();\n for (const i of issues) {\n const seen = new Set<number>();\n const stack = [...(waiters.get(i.number) ?? [])];\n while (stack.length) {\n const n = stack.pop()!;\n if (n === i.number || seen.has(n)) continue;\n seen.add(n);\n stack.push(...(waiters.get(n) ?? []));\n }\n out.set(i.number, { chain: chain(i.number), waiting: seen.size });\n }\n return out;\n}\n", "// Setting up an agent's desk for a new task (Swarm.prepare), in the order that keeps the desk folder clearable.\n\n/** An agent's terminal, as far as setting up the desk cares. */\nexport interface IdleCli {\n /** Closes a CLI waiting at its prompt, settling once it has exited; null while a CLI drives a session. */\n releaseIdle: (() => Promise<void>) | null;\n}\n\nexport interface DeskSteps {\n /** Stop what the last task left running (dev servers, anything started in the desk). */\n release(): Promise<void>;\n /** Put the desk on the task's branch; resolves to its folder. */\n prepare(): Promise<string>;\n}\n\n/**\n * Close the agent's idle CLI first: its working directory is the desk, and on Windows a folder can't be removed while\n * a process has it as its working directory. A new task starts a new session anyway (fixes resume theirs by id). A CLI\n * driving a session has no releaseIdle, so it's never closed here.\n */\nexport async function setUpDesk(term: IdleCli | null | undefined, steps: DeskSteps): Promise<string> {\n await term?.releaseIdle?.();\n await steps.release();\n return steps.prepare();\n}\n", "// After a fix session that ended well: did it push anything? A QA fix or a conflict resolution that left the PR's head\n// where it was fixed nothing, so it counts as a failed session: QA doesn't re-test the same commit, and the manager\n// hears \"nothing was pushed\" rather than another identical QA report. A checks fix may rightly push nothing (it can\n// re-run a flaky check).\n\n/** Failed fix sessions in a row (unpushed ones included) before the PR goes to the manager. */\nexport const MAX_FIX_FAILURES = 2;\n\n/** The parts of a QA record a finished fix reads. */\nexport interface FixRecord {\n prNumber: number;\n round: number;\n sessionFailures: number;\n testedSha: string | null;\n passedSha: string | null;\n fixReason: 'qa' | 'checks' | 'conflict' | null;\n}\n\nexport type FixPatch = Partial<{ status: 'queued' | 'passed' | 'failed' | 'needs-human'; round: number; sessionFailures: number; mergeNote: string | null }>;\n\nexport interface FixOutcome {\n set: FixPatch;\n log: { kind: 'done' | 'error'; text: string };\n pushed: boolean;\n}\n\n/**\n * What a fix session that ended well did to its PR. head: the PR's head commit now (null: GitHub couldn't be asked,\n * so the session is taken at its word). counts: false while Claude's usage limit is hit, which isn't the PR's fault.\n */\nexport function fixOutcome(rec: FixRecord, head: string | null, minutes: number, counts = true): FixOutcome {\n const pr = rec.prNumber;\n // The commit the fix started from: the one QA failed, or the one QA passed (and auto-merge kept) for a conflict.\n const before = rec.fixReason === 'conflict' ? (rec.passedSha ?? rec.testedSha) : rec.testedSha;\n if (rec.fixReason !== 'checks' && head && before && head === before) {\n const sessionFailures = rec.sessionFailures + (counts ? 1 : 0);\n const needsHuman = sessionFailures >= MAX_FIX_FAILURES;\n return {\n set: needsHuman\n ? { status: 'needs-human', sessionFailures, mergeNote: rec.fixReason === 'conflict' ? 'the conflict was never resolved' : 'the fix was never pushed' }\n : { status: 'failed', sessionFailures },\n log: { kind: 'error', text: `\u2717 No new commits were pushed for PR #${pr}` },\n pushed: false,\n };\n }\n // A conflict fix for a PR QA failed on its last round (passedSha null) also fixed QA's findings: QA re-tests it.\n if (rec.fixReason === 'checks' || (rec.fixReason === 'conflict' && rec.passedSha)) {\n // Back in line to merge: new commits go through QA again first, a re-run of flaky checks doesn't.\n return { set: { status: 'passed', sessionFailures: 0, mergeNote: 'waiting for fresh checks' }, log: { kind: 'done', text: `\u2714 PR #${pr} fixed in ${minutes}m. Back in line to merge.` }, pushed: true };\n }\n return { set: { status: 'queued', round: rec.round + 1, sessionFailures: 0 }, log: { kind: 'done', text: `\u2714 Fix pushed for PR #${pr} in ${minutes}m. Back to QA.` }, pushed: true };\n}\n", "import type { PullInfo } from '../shared/types.ts';\n\n// Whether an issue is still free work. A merged PR's issue stays open on GitHub until \"Closes #N\" catches up (or for\n// good, when the link wasn't recognised), so an issue counts as taken while a PR is open for it and as done for a\n// while after one merged. The office also closes what it merges itself (issuesResolvedBy).\n\n/** How long a merged PR keeps its issues off the market, however long GitHub takes to close them. */\nexport const RECENT_MERGE_MS = 6 * 60 * 60_000;\n\nexport type ClaimPull = Pick<PullInfo, 'state' | 'headRefName' | 'closesIssues' | 'mergedAt'>;\n\nexport interface ClaimAgent {\n role: string;\n task: string | null;\n issueNumber: number | null;\n status: string;\n}\n\n/** The issue a swarm/issue-<n>-\u2026 branch was cut for. */\nexport function branchIssue(headRefName: string): number | null {\n const m = /^swarm\\/issue-(\\d+)-/.exec(headRefName);\n return m ? Number(m[1]) : null;\n}\n\n/** Issues a PR resolves: the ones it formally links, plus its swarm/issue-<n>-\u2026 branch's (people's branches only link). */\nexport function issuesResolvedBy(pr: Pick<PullInfo, 'headRefName' | 'closesIssues'>): number[] {\n const n = branchIssue(pr.headRefName);\n return [...new Set(n == null ? pr.closesIssues : [...pr.closesIssues, n])];\n}\n\n/** Issue n is taken (a developer is on it, or a PR is open for it) or done (a PR for it merged recently). */\nexport function issueTaken(n: number, agents: ClaimAgent[], pulls: ClaimPull[], now: number): boolean {\n if (agents.some((a) => a.role === 'dev' && a.task !== 'qa' && a.issueNumber === n && a.status !== 'idle' && a.status !== 'error')) return true;\n return pulls.some((p) => {\n if (p.state === 'CLOSED') return false; // closed without merging: the issue is free again\n if (p.state === 'MERGED' && (!p.mergedAt || now - Date.parse(p.mergedAt) > RECENT_MERGE_MS)) return false;\n return issuesResolvedBy(p).includes(n);\n });\n}\n", "// QA a restart left behind. A tester is marked done before their report is posted, and the PR only leaves \"testing\"\n// once it is: an office that stops in between comes back with a PR in \"testing\" that nobody is testing. Startup\n// recovery only looks at agents that were busy, the scheduler and \"Send to QA\" both skip a PR in \"testing\", and the\n// board offers no button for it, so the PR would sit there for good.\n\nexport interface OrphanQaRecord {\n repoId: string;\n prNumber: number;\n status: string;\n qaAgentId: string | null;\n}\n\nexport interface OrphanQaAgent {\n id: string;\n repoId: string;\n status: string;\n task: string | null;\n prNumber: number | null;\n}\n\n/**\n * The QA records marked \"testing\" that no busy agent is testing. Only meaningful when nothing can be mid-way through\n * finishing a QA session, i.e. at startup: while the office runs, a finished tester's report may still be posting.\n */\nexport function orphanedQa<R extends OrphanQaRecord>(qa: readonly R[], agents: readonly OrphanQaAgent[], busy: readonly string[]): R[] {\n return qa.filter(\n (q) =>\n q.status === 'testing' &&\n !agents.some((a) => a.id === q.qaAgentId && busy.includes(a.status) && a.task === 'qa' && a.repoId === q.repoId && a.prNumber === q.prNumber),\n );\n}\n", "// The parts of a QA session's instructions that depend on the PR: what GitHub's checks say (QA doesn't re-run what\n// they already cover) and, on a re-test, how much to look at again (what changed, not the whole plan). Pure, so the\n// wording is tested.\n\nimport type { PrDetails } from './github.ts';\n\nexport interface QaPromptInput extends Pick<PrDetails, 'headSha' | 'checks' | 'checkNames' | 'failedChecks' | 'pendingChecks'> {\n round: number;\n fixReason: 'qa' | 'checks' | 'conflict' | null;\n /** The commit the previous round tested (null on a first round or for records from before commits were tracked). */\n lastTestedSha: string | null;\n summary: string | null; // last round's findings\n fixInstructions: string | null;\n defaultBranch: string;\n}\n\nexport interface QaInstructions {\n /** One line for the prompt: what the checks say right now. */\n checks: string;\n /** Step 3 of \"How to test\". */\n testStep: string;\n /** The re-test paragraph for the prompt, '' on a first round. */\n retest: string;\n}\n\nexport function qaInstructions(i: QaPromptInput): QaInstructions {\n return { checks: checksLine(i), testStep: testStep(i.checks !== 'none'), retest: retest(i) };\n}\n\nfunction checksLine(i: QaPromptInput): string {\n const names = (list: string[]) => list.join(', ') || 'unnamed';\n const state =\n i.checks === 'passing'\n ? `passing (${names(i.checkNames)})`\n : i.checks === 'failing'\n ? `failing: ${names(i.failedChecks)}${i.pendingChecks.length ? `; still running: ${i.pendingChecks.join(', ')}` : ''}`\n : i.checks === 'pending'\n ? `pending: ${names(i.pendingChecks)}`\n : 'none';\n return `GitHub checks right now: ${state}`;\n}\n\nfunction testStep(hasChecks: boolean): string {\n return hasChecks\n ? \"3. GitHub's checks run on this PR, and it merges only once they're green. Read .github/workflows to see what they cover and don't re-run that locally. Run only what you need to exercise the change (for example a build to start the app), anything the checks don't cover, or a failing check to reproduce it. A failing check is a finding: name it.\"\n : \"3. Install dependencies if needed, then run the project's test suite, linters, type checks and build (whichever exist).\";\n}\n\nfunction retest(i: QaPromptInput): string {\n // A retried session (it crashed or the office restarted) already recorded this head: there's no diff to go by.\n const since = i.lastTestedSha && i.lastTestedSha !== i.headSha ? i.lastTestedSha : null;\n const diff = since\n ? `(git diff ${since}..HEAD), plus a quick smoke test of the main flow. Don't repeat the full test plan for parts the change didn't touch.`\n : null;\n // Merging the base can affect anything, so a conflict fix always gets the full re-check.\n if (i.fixReason === 'conflict') {\n return `\\nQA passed it before, but since then the branch was updated with ${i.defaultBranch} to resolve merge conflicts. Re-check everything, especially where this change meets the newly merged work.`;\n }\n if (i.fixReason === 'checks') {\n return `\\nQA passed it before, but since then the developer changed the code to fix failing GitHub checks. ${diff ? `Test what changed since QA passed it ${diff}` : 'Re-check everything.'}`;\n }\n if (i.round > 1 && i.summary) {\n return `\\nThis is a re-test after fixes. Last round's findings:\\n${i.summary}\\n${i.fixInstructions ?? ''}\\nCheck those first, then ${diff ? `test what changed since the last round ${diff}` : 're-check everything else.'}`;\n }\n return '';\n}\n", "// After an office restart: whose work picks up where it was, and what they're told. An agent still preparing a task\n// hadn't started that task's session yet, so the session it remembers, or a CLI still busy in its terminal, belongs to\n// an earlier task: resuming it would do that task again (a QA verdict posted twice) and pass the result off as this one.\n\nexport interface RestartAgent {\n status: string;\n task: 'issue' | 'qa' | 'fix' | null;\n sessionId: string | null;\n branch: string | null;\n issueNumber: number | null;\n issueTitle: string | null;\n prNumber: number | null;\n}\n\n/** A CLI the terminal keeper kept running through the restart. resumeId: the session it is on, when known. */\nexport interface KeptCli {\n busy: boolean;\n resumeId: string | null;\n}\n\n/** The office follows a CLI that kept working through the restart only when it is on the agent's current task. */\nexport function followKeptCli(a: RestartAgent, cli: KeptCli | undefined): boolean {\n if (!cli?.busy || a.status === 'preparing') return false;\n return !(a.sessionId && cli.resumeId && cli.resumeId !== a.sessionId);\n}\n\n/**\n * An agent cut off by the restart resumes its session (true), or its work goes back in line: QA, the demo, and a task\n * that was still being prepared (preparing: its status when the office stopped), whose session never started.\n */\nexport function resumesAfterRestart(a: RestartAgent, preparing: boolean, demo: boolean): boolean {\n return !demo && !preparing && a.task !== 'qa' && !!a.sessionId && !!a.branch;\n}\n\n/** What a resumed agent is told: the job it was on, not just \"carry on\". */\nexport function resumeNote(a: RestartAgent, fix?: { round: number; fixReason: 'qa' | 'checks' | 'conflict' | null } | null): string {\n const yours = 'Uncommitted changes in your worktree are yours to finish.';\n if (a.task === 'fix' && a.prNumber && a.branch) {\n const job =\n fix?.fixReason === 'conflict'\n ? `resolving the merge conflicts on PR #${a.prNumber}`\n : fix?.fixReason === 'checks'\n ? `fixing the failing checks on PR #${a.prNumber}`\n : `fixing PR #${a.prNumber}${fix ? ` after QA round ${fix.round}` : ''}`;\n return `The office server restarted while you were ${job}. Finish the fix, commit, and push with: git push origin HEAD:${a.branch}. ${yours}`;\n }\n if (a.task === 'issue' && a.issueNumber && a.branch) {\n const pr = a.prNumber\n ? `push with: git push origin ${a.branch} to update PR #${a.prNumber}`\n : `push with: git push -u origin ${a.branch}, and open the pull request with \"Closes #${a.issueNumber}\" (or push to it if it's already open)`;\n return `The office server restarted while you were working on issue #${a.issueNumber}${a.issueTitle ? ` (${a.issueTitle})` : ''} on branch ${a.branch}. Finish it, commit, ${pr}. ${yours}`;\n }\n return 'The office server restarted while you were working. Check the state of your worktree and continue where you left off.';\n}\n", "import type { Backend } from './backend.ts';\nimport { PORT } from './config.ts';\nimport { HttpError } from './httpError.ts';\nimport { PREVIEW_SLUG, portOpen, type PreviewHandle } from './previewRunner.ts';\nimport type { PreviewConfig, PreviewStatus, PreviewView, PullInfo } from '../shared/types.ts';\n\n// One preview per floor: the floor's app, run from its own worktree on a port reserved for the floor.\n// Only the config is persisted; after a restart every preview reads 'stopped'.\n\n/** What the previews need to know about a floor. */\nexport interface PreviewFloor {\n id: string;\n fullName: string;\n defaultBranch: string;\n floor: number;\n preview: PreviewConfig;\n}\n\ninterface Run {\n status: PreviewStatus;\n port: number | null; // the port of the current or last run\n ref: string | null;\n pr: number | null;\n commit: string | null;\n startedAt: number | null;\n error: string | null;\n log: string[];\n handle: PreviewHandle | null;\n gen: number; // bumped by every start / stop; callbacks from older runs are ignored\n}\n\nconst PREVIEW_BASE_PORT = 6300;\nconst LOG_KEEP = 200;\nconst LOG_VIEW = 40;\nconst ACTIVE: PreviewStatus[] = ['preparing', 'installing', 'starting', 'running'];\n\n/** Never the office itself, the other office port, or the agents' range. */\nconst forbidden = (p: number) => p === PORT || p === 4317 || p === 5317 || (p >= 5200 && p <= 5899);\n\nexport const DEFAULT_PREVIEW: PreviewConfig = { command: null, env: {} };\n\n/** Check a previewCommand / previewEnv patch; throws 400 on bad input. undefined: not in the patch. */\nexport function parsePreviewPatch(command: unknown, env: unknown): Partial<PreviewConfig> {\n const out: Partial<PreviewConfig> = {};\n if (command !== undefined) {\n if (command !== null && typeof command !== 'string') throw new HttpError(400, 'previewCommand must be a string or null');\n const c = (command ?? '').trim();\n if (c.length > 2000) throw new HttpError(400, 'previewCommand is too long');\n out.command = c || null;\n }\n if (env !== undefined) {\n if (env === null) out.env = {};\n else {\n if (typeof env !== 'object' || Array.isArray(env)) throw new HttpError(400, 'previewEnv must be an object of string values');\n const entries = Object.entries(env as Record<string, unknown>);\n if (entries.length > 50) throw new HttpError(400, 'previewEnv has too many variables');\n for (const [k, v] of entries) {\n if (typeof v !== 'string') throw new HttpError(400, `previewEnv.${k} must be a string`);\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) throw new HttpError(400, `\"${k}\" is not a valid environment variable name`);\n if (/^(ANTHROPIC_|CLAUDE)/i.test(k)) throw new HttpError(400, `${k} can't be set on a preview: Claude credentials never reach the apps the office runs`);\n if (v.length > 4000) throw new HttpError(400, `previewEnv.${k} is too long`);\n }\n out.env = Object.fromEntries(entries) as Record<string, string>;\n }\n }\n return out;\n}\n\nexport class Previews {\n private runs = new Map<string, Run>();\n private hasDefault = new Map<string, boolean>(); // floor id -> package.json in its checkout\n private emitTimers = new Map<string, NodeJS.Timeout>();\n\n constructor(\n private backend: Backend,\n private hooks: { emit(repoId: string): void; pulls(repoId: string): PullInfo[] },\n ) {}\n\n private run(id: string): Run {\n let r = this.runs.get(id);\n if (!r) {\n r = { status: 'stopped', port: null, ref: null, pr: null, commit: null, startedAt: null, error: null, log: [], handle: null, gen: 0 };\n this.runs.set(id, r);\n }\n return r;\n }\n\n /** The floor's reserved port: 6300 + floor, moved up by 100 while it clashes with the office or another preview. */\n portFor(f: PreviewFloor): number {\n const active = this.runs.get(f.id);\n if (active?.port && ACTIVE.includes(active.status)) return active.port;\n const taken = new Set([...this.runs.entries()].filter(([id, r]) => id !== f.id && r.port && ACTIVE.includes(r.status)).map(([, r]) => r.port!));\n let p = PREVIEW_BASE_PORT + f.floor;\n while (forbidden(p) || taken.has(p)) p += 100;\n return p;\n }\n\n view(f: PreviewFloor): PreviewView {\n const r = this.runs.get(f.id);\n let status: PreviewStatus = r?.status ?? 'stopped';\n if (status === 'stopped' && !f.preview.command && this.hasDefault.get(f.id) === false) status = 'unconfigured';\n const port = r?.port ?? this.portFor(f);\n return {\n status,\n port,\n url: status === 'running' ? `http://localhost:${port}/` : null,\n ref: r?.ref ?? null,\n pr: r?.pr ?? null,\n commit: r?.commit ?? null,\n startedAt: r?.startedAt ?? null,\n error: r?.error ?? null,\n logTail: (r?.log ?? []).slice(-LOG_VIEW),\n };\n }\n\n /** Re-check whether a floor without a command has a package.json to fall back on. */\n async refreshDefault(f: PreviewFloor) {\n const has = await this.backend.previews.hasDefault(f.fullName).catch(() => true);\n if (this.hasDefault.get(f.id) === has) return;\n this.hasDefault.set(f.id, has);\n this.hooks.emit(f.id);\n }\n\n /** Start the floor's preview on the default branch or an open PR, replacing whatever it is running now. */\n async start(f: PreviewFloor, title: string, pr?: number | null): Promise<PreviewView> {\n if (pr !== undefined && pr !== null && (!Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, `Invalid pull request number: ${pr}`);\n if (pr) await this.checkOpen(f, pr);\n const r = this.run(f.id);\n const gen = ++r.gen;\n await this.halt(f, r);\n if (gen !== r.gen) return this.view(f); // another start or a stop came in meanwhile\n\n const port = this.portFor(f);\n const ref = pr ? `PR #${pr}` : f.defaultBranch;\n Object.assign(r, { port, ref, pr: pr ?? null, commit: null, startedAt: Date.now(), error: null, log: [] });\n if (await portOpen(port)) {\n if (gen !== r.gen) return this.view(f);\n Object.assign(r, { status: 'error', error: `Port ${port} is already in use by another program. The office won't stop it; free the port and try again.` });\n this.hooks.emit(f.id);\n throw new HttpError(409, r.error!);\n }\n if (gen !== r.gen) return this.view(f);\n r.status = 'preparing';\n this.hooks.emit(f.id);\n\n const live = () => gen === r.gen;\n r.handle = this.backend.previews.start(\n { fullName: f.fullName, defaultBranch: f.defaultBranch, pr: pr ?? null, port, command: f.preview.command, env: { ...f.preview.env }, title: `${title} \u00B7 ${ref}` },\n {\n status: (s) => {\n if (!live()) return;\n r.status = s;\n this.hooks.emit(f.id);\n },\n commit: (sha) => {\n if (!live()) return;\n r.commit = sha || null;\n this.hooks.emit(f.id);\n },\n log: (lines) => {\n if (!live()) return;\n r.log.push(...lines.map((l) => l.slice(0, 500)));\n if (r.log.length > LOG_KEEP) r.log.splice(0, r.log.length - LOG_KEEP);\n this.emitSoon(f.id);\n },\n failed: (message, unconfigured) => {\n if (!live()) return;\n r.handle = null;\n Object.assign(r, { status: unconfigured ? 'unconfigured' : 'error', error: message });\n if (unconfigured) this.hasDefault.set(f.id, false);\n this.hooks.emit(f.id);\n // Anything the app left behind in its worktree or on its port goes too.\n void this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, port).catch(() => undefined);\n },\n },\n );\n return this.view(f);\n }\n\n /** Stop the floor's preview and free its port. */\n async stop(f: PreviewFloor): Promise<PreviewView> {\n const r = this.run(f.id);\n r.gen++;\n await this.halt(f, r);\n Object.assign(r, { status: 'stopped', error: null, startedAt: null });\n this.hooks.emit(f.id);\n return this.view(f);\n }\n\n /** The floor is leaving the building: stop its preview and remove the preview worktree. */\n async remove(f: PreviewFloor) {\n const main = this.backend.mainDir(f.fullName); // now: the floor points away from its folder before the preview stops\n const r = this.runs.get(f.id);\n if (r) {\n r.gen++;\n await this.halt(f, r);\n }\n this.runs.delete(f.id);\n this.hasDefault.delete(f.id);\n clearTimeout(this.emitTimers.get(f.id));\n await this.backend.removeDesk(f.fullName, PREVIEW_SLUG, main).catch(() => undefined);\n }\n\n /** Server shutdown: stop every running preview. */\n async stopAll(floors: PreviewFloor[]) {\n await Promise.all(\n floors.map((f) => {\n const r = this.runs.get(f.id);\n if (!r) return;\n r.gen++;\n return this.halt(f, r);\n }),\n );\n }\n\n /** Server start: nothing is running yet, so anything alive in a preview worktree or on a preview port is an orphan. */\n async clearOrphans(floors: PreviewFloor[]) {\n await Promise.all(floors.map((f) => this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, this.portFor(f)).catch(() => undefined)));\n }\n\n private async halt(f: PreviewFloor, r: Run) {\n const handle = r.handle;\n r.handle = null;\n if (!handle) return;\n await handle.stop().catch(() => undefined);\n if (!r.port) return;\n await this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, r.port).catch(() => undefined);\n // Windows can take a moment to let go of a killed process's socket.\n for (let i = 0; i < 20 && (await portOpen(r.port)); i++) await new Promise((res) => setTimeout(res, 250));\n }\n\n private async checkOpen(f: PreviewFloor, pr: number) {\n const known = this.hooks.pulls(f.id).find((p) => p.number === pr);\n const state = known?.state ?? (await this.backend.prDetails(f.fullName, pr).then((d) => d.state).catch(() => null));\n if (!state) throw new HttpError(404, `${f.fullName} has no pull request #${pr}`);\n if (state !== 'OPEN') throw new HttpError(400, `Pull request #${pr} is ${state.toLowerCase()}, not open`);\n }\n\n /** Log lines arrive in bursts (npm install); send them at most once a second. */\n private emitSoon(id: string) {\n if (this.emitTimers.has(id)) return;\n this.emitTimers.set(\n id,\n setTimeout(() => {\n this.emitTimers.delete(id);\n if (this.runs.has(id)) this.hooks.emit(id);\n }, 1000),\n );\n }\n}\n", "// What developers and QA testers are told on every task: the system prompt the office appends for each session, as\n// pure functions, so the manager can preview it (GET /api/agents/:id/prompt) without a live task. The job\n// description is the one part the manager edits; the rest carries the office's workflow and safety rules.\n\nimport type { AgentPromptView, AgentRole, PromptPart } from '../shared/types.ts';\n\nexport interface PromptAgent {\n name: string;\n role: AgentRole;\n title: string;\n brief: string;\n}\n\nexport interface PromptFloor {\n fullName: string;\n defaultBranch: string;\n autoMerge: boolean;\n browserTesting: boolean;\n summary: string;\n mission: string;\n qaBrief: string;\n}\n\ninterface PromptBase {\n agent: PromptAgent;\n repo: PromptFloor;\n /** Their dev-server port, reserved per agent. */\n port: number;\n cwd: string;\n branch: string;\n /** What the office did about the desk's dependencies (deps.ts depsPromptLine); empty or absent says nothing. */\n depsLine?: string;\n}\n\nexport interface DevPromptInput extends PromptBase {\n /** Connected repositories they may read, with their clone paths. */\n linked: { fullName: string; dir: string }[];\n /** Fixing an open pull request rather than starting an issue. */\n fixing?: { pr: number; headRef: string };\n}\n\nexport interface QaPromptInput extends PromptBase {\n pr: { number: number | string; title: string; headRefName: string; url: string };\n /** Step 3 of \"How to test\" for this PR (see qaPrompt.ts); the default when it has no checks. */\n testStep?: string;\n}\n\n/** Stand-ins for a task's details in a preview. */\nexport const PLACEHOLDERS = {\n worktree: '<your worktree>',\n issue: '<issue>',\n pr: '<PR>',\n prTitle: '<PR title>',\n prUrl: '<PR URL>',\n branch: '<branch>',\n} as const;\n\nexport const devBranch = (issue: number | string, slug: string) => `swarm/issue-${issue}-${slug}`;\nexport const qaBranch = (pr: number | string, slug: string) => `qa/pr-${pr}-${slug}`;\n\nexport function devSystemPrompt({ agent: a, repo, port, cwd, branch, linked, fixing, depsLine }: DevPromptInput) {\n const push = fixing ? `git push origin HEAD:${fixing.headRef}` : `git push -u origin ${branch}`;\n const links = linked.map((r) => `- ${r.fullName}: read-only reference clone at ${r.dir}`);\n return [\n `You are ${a.name}, ${a.title ? `the team's ${a.title},` : 'a software engineer'} on an autonomous agent team (\"cubefarm\"). Several teammates work in parallel on other issues of the same repository, each in their own git worktree. Nobody is watching live to answer questions, so make sensible decisions yourself and record assumptions in the PR description. The manager may occasionally send you messages; follow their instructions.`,\n `Every pull request is reviewed and tested by a QA teammate. ${repo.autoMerge ? \"Once they sign off and GitHub's checks pass, the office merges it by itself\" : 'Once they sign off, the manager merges it'}. If they find problems, or checks fail, or it conflicts with the default branch, you will get the details; fix them on the same branch.`,\n a.brief ? `\\nYour job description:\\n${a.brief}` : '',\n '',\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\n repo.summary ? `Project: ${repo.summary}` : '',\n repo.mission ? `What the team is building (the manager's brief): ${repo.mission}` : '',\n `Your worktree: ${cwd}`,\n depsLine ?? '',\n fixing\n ? `You are fixing pull request #${fixing.pr}. Its code is checked out on local branch ${branch}; push fixes with: ${push}. Do not open a new pull request.`\n : `Your branch: ${branch} (already checked out, created from origin/${repo.defaultBranch})`,\n links.length ? `Related repositories you may read for context (do not modify them):\\n${links.join('\\n')}` : '',\n '',\n 'Workflow:',\n '1. Read the issue and explore the relevant code before changing anything.',\n '2. Implement the change with focused commits and clear messages.',\n \"3. Run the project's existing tests, linters and build (if any) and fix what you broke. Install dependencies first if needed.\",\n repo.browserTesting\n ? `4. If the project has a web UI, start its dev server in the background on port ${port} (reserved for you, so you don't collide with teammates), then check your change with the Playwright browser tools (mcp__playwright__browser_navigate, browser_snapshot, browser_click, browser_take_screenshot). Stop the dev server when you're done.`\n : '4. Verify the behaviour you changed as directly as you can.',\n `5. Push: ${push}`,\n fixing\n ? '6. Reply with a short summary of what you fixed.'\n : `6. Open a pull request with the GitHub CLI: gh pr create --base ${repo.defaultBranch} --head ${branch} --title \"<concise title>\" --body \"<what changed, how you verified it, assumptions>\". The body must contain \"Closes #<issue number>\".`,\n fixing ? '' : '7. End your final message with the pull request URL on its own line.',\n '',\n 'Rules: never push to the default branch, never force-push, never merge pull requests yourself (the office merges them once QA and the checks pass), and never edit files outside your worktree. If you cannot finish, open a draft PR (gh pr create --draft) explaining what is left and why.',\n ]\n .filter((l) => l !== '')\n .join('\\n');\n}\n\nexport function qaSystemPrompt({ agent: a, repo, port, cwd, branch, pr, depsLine, testStep }: QaPromptInput) {\n return [\n `You are ${a.name}, ${a.title ? `the team's ${a.title},` : 'a QA engineer'} on an autonomous agent team (\"cubefarm\"). Developers open pull requests; you review and independently verify each one before it is merged. Your sign-off is the review: ${repo.autoMerge ? \"on this floor a PR you pass merges by itself as soon as GitHub's checks are green, so nobody else reads the code after you. \" : ''}Be thorough and skeptical, but fair: fail a PR only for real problems (broken behaviour, failing tests or build, the issue's requirements not met, obvious regressions), not for style preferences.`,\n ...(a.brief ? ['', `Your job description:\\n${a.brief}`] : []),\n ...(a.role === 'dev' ? ['', \"You're a developer covering for the QA lab while its testers are busy. You didn't write this pull request: test it as an independent QA engineer would.\"] : []),\n '',\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\n ...(repo.summary ? [`Project: ${repo.summary}`] : []),\n ...(repo.mission ? [`What the team is building (the manager's brief): ${repo.mission}`] : []),\n ...(repo.qaBrief ? [`What to check on this project (from the CEO):\\n${repo.qaBrief}`] : []),\n `Pull request #${pr.number} \"${pr.title}\" from branch ${pr.headRefName}: ${pr.url}`,\n `Your worktree: ${cwd}. It has the pull request's code checked out on local branch ${branch}.`,\n ...(depsLine ? [depsLine] : []),\n '',\n 'How to test:',\n '1. Read the PR description and the linked issue, and work out the acceptance criteria.',\n `2. Review the code as a careful reviewer would: git diff origin/${repo.defaultBranch}...HEAD. Look for bugs, unhandled errors and edge cases, security problems, leftover debug code, and new logic without tests.`,\n testStep ?? \"3. Install dependencies if needed, then run the project's test suite, linters, type checks and build (whichever exist).\",\n repo.browserTesting\n ? `4. If the project has a UI, start it in the background on port ${port} (reserved for you) and exercise the change in a real browser with the Playwright tools: navigate, click, type, resize to a phone size, try edge cases, and check the console for errors. Take a screenshot with browser_take_screenshot (no filename) of every important state: the screenshots are attached to the PR as evidence. Stop the server afterwards.`\n : '4. Exercise the changed behaviour directly (run the program, call the API, write a quick script).',\n '5. You may write throwaway scripts to probe behaviour, but do not commit them.',\n \"A merge conflict with the default branch is not a fail: judge the change itself (on a throwaway merge if you need newer work) and pass it if it's good. The office sends conflicting PRs back for a merge fix, then you re-test.\",\n '',\n 'Rules: do not modify the code under test, do not commit, push, comment on, review or merge anything on GitHub. The office posts your report on the pull request. Finish with the structured QA report: verdict, summary, the checks you performed, the commands you ran and one caption per screenshot.',\n ].join('\\n');\n}\n\n// ---------- previews ----------\n\nconst OFFICE = 'Office instructions';\n// Stands in for the job description while the prompt is built, so the parts split exactly around it.\nconst MARK = '\\u0000job description\\u0000';\n\n/** Splits a prompt around the job description, which is the one editable part. */\nexport function promptParts(build: (brief: string) => string, brief: string): PromptPart[] {\n if (!brief) return [{ label: OFFICE, text: build(''), editable: false }];\n const [before, after] = build(MARK).split(MARK);\n return [\n { label: OFFICE, text: before, editable: false },\n { label: 'Job description', text: brief, editable: true },\n { label: OFFICE, text: after, editable: false },\n ].filter((p) => p.text !== '');\n}\n\nconst view = (kind: AgentPromptView['kind'], parts: PromptPart[]): AgentPromptView => ({ kind, text: parts.map((p) => p.text).join(''), parts });\n\ntype PreviewInput = Omit<PromptBase, 'cwd' | 'branch'> & { slug: string };\n\n/** What a developer is told when they start an issue, with placeholders for the issue and their worktree. */\nexport function devPromptPreview({ slug, ...i }: PreviewInput & Pick<DevPromptInput, 'linked'>): AgentPromptView {\n const branch = devBranch(PLACEHOLDERS.issue, slug);\n return view('dev', promptParts((brief) => devSystemPrompt({ ...i, agent: { ...i.agent, brief }, cwd: PLACEHOLDERS.worktree, branch }), i.agent.brief));\n}\n\n/** What a QA tester is told when they test a pull request, with placeholders for the PR and their worktree. */\nexport function qaPromptPreview({ slug, ...i }: PreviewInput): AgentPromptView {\n const pr = { number: PLACEHOLDERS.pr, title: PLACEHOLDERS.prTitle, headRefName: PLACEHOLDERS.branch, url: PLACEHOLDERS.prUrl };\n const branch = qaBranch(PLACEHOLDERS.pr, slug);\n return view('qa', promptParts((brief) => qaSystemPrompt({ ...i, agent: { ...i.agent, brief }, cwd: PLACEHOLDERS.worktree, branch, pr }), i.agent.brief));\n}\n\n/** The CEO's prompt has no job description of theirs in it: all of it is the office's. */\nexport const ceoPromptPreview = (text: string): AgentPromptView => view('ceo', [{ label: OFFICE, text, editable: false }]);\n", "import type { UsageView } from '../shared/types.ts';\n\n// Pacing new work on Claude's usage warnings (#40). Every agent shares one subscription. When Claude warns that\n// usage is getting high, the office slows down instead of running into the hard limit: finishing beats starting.\n// QA, QA fixes and CEO jobs start as normal; new issues only while fewer than settings.pacingSessions sessions run.\n\n/** How long pacing lasts when Claude doesn't say when the window resets. */\nexport const PACING_MS = 60 * 60_000;\nexport const DEFAULT_PACING_SESSIONS = 3;\n\n/** What a session is started for. Only new issues are held back while pacing. */\nexport type WorkKind = 'issue' | 'qa' | 'fix' | 'ceo';\n\nexport interface UsageClock {\n now: number;\n pausedUntil: number; // Claude rejected a session for the usage limit: nothing new starts before this\n pacingUntil: number; // Claude warned about usage: new issues are paced until this\n}\n\n/** May work of this kind start now? A rejection pauses everything; pacing caps new issues at `pacingSessions` running. */\nexport function mayStart(kind: WorkKind, c: UsageClock & { running: number; pacingSessions: number }): boolean {\n if (c.now < c.pausedUntil) return false;\n if (kind === 'issue' && c.now < c.pacingUntil) return c.running < c.pacingSessions;\n return true;\n}\n\n/** The usage state for the snapshot. */\nexport function usageView(c: UsageClock): UsageView {\n if (c.now < c.pausedUntil) return { state: 'paused', until: c.pausedUntil };\n if (c.now < c.pacingUntil) return { state: 'pacing', until: c.pacingUntil };\n return { state: 'normal', until: null };\n}\n\n/** \"14:30\", with the weekday when it isn't today. */\nexport function clock(at: number, now: number): string {\n const d = new Date(at);\n const hm = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;\n return d.toDateString() === new Date(now).toDateString() ? hm : `${d.toLocaleDateString('en-US', { weekday: 'short' })} ${hm}`;\n}\n\n/** company.usage for the CEO: \"normal\", \"pacing until 14:30\" or \"paused until 14:30\". */\nexport function usageLabel(u: UsageView, now: number): string {\n return u.state === 'normal' || u.until === null ? 'normal' : `${u.state} until ${clock(u.until, now)}`;\n}\n\n/** Clamp the pacing cap from the settings (1-32, default 3). */\nexport function clampPacingSessions(v: unknown): number {\n const n = Math.round(Number(v));\n return Number.isFinite(n) && n > 0 ? Math.min(32, n) : DEFAULT_PACING_SESSIONS;\n}\n\nconst LIMIT_NAMES: Record<string, string> = {\n five_hour: '5-hour limit',\n seven_day: 'weekly limit',\n seven_day_opus: 'weekly Opus limit',\n seven_day_sonnet: 'weekly Sonnet limit',\n};\n\n/** A usage warning as the SDK reports it. utilization may be a fraction (0.82) or a percentage (82). */\nexport interface UsageWarning {\n resetsAt: number | null; // epoch ms\n rateLimitType: string | null;\n utilization: number | null;\n}\n\n/** The phone message when pacing starts. */\nexport function pacingMessage(w: UsageWarning, until: number, sessions: number, now: number): string {\n const pct = w.utilization === null ? null : Math.round(w.utilization <= 1 ? w.utilization * 100 : w.utilization);\n const what = [w.rateLimitType ? (LIMIT_NAMES[w.rateLimitType] ?? w.rateLimitType.replace(/_/g, ' ')) : null, pct === null ? null : `${pct}%`].filter(Boolean).join(', ');\n return `\uD83D\uDC22 Claude's usage is getting high${what ? ` (${what})` : ''}. Until ${clock(until, now)} the office finishes open work first and starts at most ${sessions} session${sessions === 1 ? '' : 's'} at a time.`;\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport xtermHeadless from '@xterm/headless';\nimport xtermSerialize from '@xterm/addon-serialize';\nimport type { WebSocket } from 'ws';\nimport type { TermClientMessage, TermServerMessage } from '../shared/types.ts';\n\n// An agent's terminal: a headless xterm that mirrors everything its CLI printed, so a browser that opens it late (or\n// reconnects) gets the same screen and scrollback, plus the viewers watching it live. The CLI itself is bound as the\n// sink: keystrokes and resizes from viewers go to whichever CLI process is running in it right now.\n\nconst { Terminal } = xtermHeadless;\nconst { SerializeAddon } = xtermSerialize;\n\nexport const TERM_COLS = 120;\nexport const TERM_ROWS = 32;\nconst SCROLLBACK = 5000;\n/** A viewer this far behind stops getting output and is sent a fresh snapshot once it catches up. */\nconst STALE_BYTES = 4 * 1024 * 1024;\n/** The mouse encodings (SGR, SGR pixels) the serialize addon doesn't restore on its own. */\nconst MOUSE_ENCODINGS = [1006, 1016];\n\n/** Where a terminal's keystrokes and size go: the running CLI. */\nexport interface TerminalSink {\n write(data: string): void;\n resize(cols: number, rows: number): void;\n}\n\nconst clamp = (n: unknown, lo: number, hi: number, dflt: number) => {\n const v = Math.round(Number(n));\n return Number.isFinite(v) ? Math.max(lo, Math.min(hi, v)) : dflt;\n};\n\nexport class AgentTerminal {\n cols = TERM_COLS;\n rows = TERM_ROWS;\n /** Output arrived since the last save. */\n dirty = false;\n /**\n * Closes a CLI left waiting at its prompt after its task, settling once it has exited (set by the runtime that left\n * it there; null while a CLI drives a session).\n */\n releaseIdle: (() => Promise<void>) | null = null;\n /** Something the manager typed at that waiting prompt: the office takes it on as a follow-up (true) or refuses. */\n onIdlePrompt: ((text: string) => boolean) | null = null;\n /** Keys a viewer typed, after they went to the CLI (the runtime watches for Esc interrupting a turn). */\n onInput: ((data: string) => void) | null = null;\n private term = new Terminal({ cols: TERM_COLS, rows: TERM_ROWS, scrollback: SCROLLBACK, allowProposedApi: true, scrollOnEraseInDisplay: true });\n private ser = new SerializeAddon();\n private viewers = new Map<WebSocket, { stale: boolean; queued: string[] | null }>();\n private sink: TerminalSink | null = null;\n private mouseEncoding: number | null = null;\n private resync: NodeJS.Timeout | null = null;\n\n constructor() {\n this.term.loadAddon(this.ser);\n const decset = (on: boolean) => (params: (number | number[])[]) => {\n for (const p of params) if (typeof p === 'number' && MOUSE_ENCODINGS.includes(p)) this.mouseEncoding = on ? p : null;\n return false; // xterm still switches the mode itself\n };\n this.term.parser.registerCsiHandler({ prefix: '?', final: 'h' }, decset(true));\n this.term.parser.registerCsiHandler({ prefix: '?', final: 'l' }, decset(false));\n }\n\n /** Output from the CLI (or a note from the office): into the mirror and out to everyone watching. */\n write(data: string) {\n if (!data) return;\n this.term.write(data);\n this.dirty = true;\n this.send({ t: 'data', data });\n }\n\n /** A dim line from the office itself, e.g. between sessions. */\n note(text: string) {\n this.write(`\\r\\n\\x1b[2m${text}\\x1b[0m\\r\\n`);\n }\n\n get live() {\n return this.sink !== null;\n }\n\n /** The CLI asked for application cursor keys: arrows are sent as ESC O A\u2026 rather than ESC [ A\u2026 */\n get appCursor() {\n return this.term.modes.applicationCursorKeysMode;\n }\n\n /** The running CLI, or null when it exits. */\n bind(sink: TerminalSink | null) {\n this.sink = sink;\n sink?.resize(this.cols, this.rows);\n this.send({ t: 'live', live: sink !== null });\n }\n\n resize(cols: number, rows: number) {\n const c = clamp(cols, 20, 400, this.cols);\n const r = clamp(rows, 5, 200, this.rows);\n if (c === this.cols && r === this.rows) return;\n this.cols = c;\n this.rows = r;\n this.term.resize(c, r);\n this.sink?.resize(c, r);\n }\n\n /** Everything a fresh terminal needs to show the same screen: scrollback, colours, cursor and modes. */\n snapshot(): string {\n return this.ser.serialize({ scrollback: SCROLLBACK }) + (this.mouseEncoding ? `\\x1b[?${this.mouseEncoding}h` : '');\n }\n\n /** The visible rows as plain text, for spotting prompts the CLI is waiting on. */\n screen(): string {\n const b = this.term.buffer.active;\n const rows: string[] = [];\n for (let i = b.viewportY; i < b.viewportY + this.rows; i++) rows.push(b.getLine(i)?.translateToString(true) ?? '');\n return rows.join('\\n');\n }\n\n /** Written to disk so a restarted office still shows what each agent did. */\n /** Resolves once everything written so far is parsed (xterm parses asynchronously). */\n flush(): Promise<void> {\n return new Promise((resolve) => this.term.write('', resolve));\n }\n\n async save(file: string) {\n this.dirty = false;\n await this.flush();\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(`${file}.tmp`, this.snapshot());\n await fs.rename(`${file}.tmp`, file);\n }\n\n async load(file: string) {\n const data = await fs.readFile(file, 'utf8').catch(() => '');\n if (!data) return;\n this.term.write(data);\n this.note('(the office restarted)');\n this.dirty = false;\n }\n\n // ---------- viewers ----------\n\n attach(ws: WebSocket) {\n // xterm parses writes asynchronously: snapshot once everything written so far is parsed, and hold back what\n // arrives meanwhile so it follows the snapshot instead of going missing.\n const viewer = { stale: false, queued: [] as string[] | null };\n this.viewers.set(ws, viewer);\n this.term.write('', () => {\n const queued = viewer.queued ?? [];\n viewer.queued = null;\n this.sendTo(ws, { t: 'snapshot', data: this.snapshot(), cols: this.cols, rows: this.rows, live: this.live });\n for (const json of queued) if (ws.readyState === ws.OPEN) ws.send(json);\n });\n ws.on('message', (raw) => {\n let msg: TermClientMessage;\n try {\n msg = JSON.parse(String(raw)) as TermClientMessage;\n } catch {\n return;\n }\n if (msg.t === 'input' && typeof msg.data === 'string') {\n const data = msg.data.slice(0, 64 * 1024);\n this.sink?.write(data);\n this.onInput?.(data);\n } else if (msg.t === 'resize') {\n this.resize(msg.cols, msg.rows);\n for (const other of this.viewers.keys()) if (other !== ws) this.sendTo(other, { t: 'size', cols: this.cols, rows: this.rows });\n }\n });\n ws.on('close', () => this.viewers.delete(ws));\n }\n\n dispose() {\n for (const ws of this.viewers.keys()) ws.close();\n this.viewers.clear();\n if (this.resync) clearTimeout(this.resync);\n this.sink = null;\n this.term.dispose();\n }\n\n private send(msg: TermServerMessage) {\n if (this.viewers.size === 0) return;\n const json = JSON.stringify(msg);\n for (const [ws, v] of this.viewers) {\n if (ws.readyState !== ws.OPEN || v.stale) continue;\n if (v.queued) {\n v.queued.push(json);\n continue;\n }\n if (ws.bufferedAmount > STALE_BYTES) {\n v.stale = true;\n this.scheduleResync();\n continue;\n }\n ws.send(json);\n }\n }\n\n private sendTo(ws: WebSocket, msg: TermServerMessage) {\n if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(msg));\n }\n\n /** Viewers that fell behind get a fresh snapshot once their socket has drained, instead of an ever-growing backlog. */\n private scheduleResync() {\n if (this.resync) return;\n this.resync = setTimeout(() => {\n this.resync = null;\n let waiting = false;\n for (const [ws, v] of this.viewers) {\n if (!v.stale) continue;\n if (ws.bufferedAmount > STALE_BYTES / 4) {\n waiting = true;\n continue;\n }\n v.stale = false;\n this.sendTo(ws, { t: 'snapshot', data: this.snapshot(), cols: this.cols, rows: this.rows, live: this.live });\n }\n if (waiting) this.scheduleResync();\n }, 1000);\n }\n}\n", "import type { AgentCli } from './types.ts';\n\n// Which model an agent's session asks for. The office's default model belongs to its default coding agent, and each\n// worker can name their own; a model only goes to an agent that understands it (no Claude model for Codex).\n\n/** Claude Code's model names and aliases. */\nexport const isClaudeModel = (model: string) => /^(claude|opus|sonnet|haiku|fable|default|best|opusplan)\\b/i.test(model.trim());\n\n/**\n * The model for a worker on `cli`: their own if it suits that agent, else the office default when `cli` is the\n * default agent, else `claudeDefault` for Claude Code, or '' to let any other agent use its own default.\n */\nexport function effectiveModel(own: string, cli: AgentCli, office: { defaultCli: AgentCli; defaultModel: string }, claudeDefault: string): string {\n const suits = (m: string) => m.trim() !== '' && (cli === 'claude') === isClaudeModel(m);\n if (suits(own)) return own.trim();\n if (cli === office.defaultCli && suits(office.defaultModel)) return office.defaultModel.trim();\n return cli === 'claude' ? claudeDefault : '';\n}\n\n/** Claude Code models offered as suggestions in the office's model fields. */\nexport const CLAUDE_MODELS = ['claude-opus-5-5', 'claude-opus-5', 'claude-fable-5-1', 'claude-sonnet-5', 'claude-haiku-4-5'];\n\n/** Model suggestions for a coding agent; any other name can still be typed. OpenCode names are `provider/model`. */\nexport function modelSuggestions(cli: AgentCli): string[] {\n if (cli === 'claude') return CLAUDE_MODELS;\n if (cli === 'codex') return ['gpt-5.5-codex', 'gpt-5.5'];\n return CLAUDE_MODELS.map((m) => `anthropic/${m}`);\n}\n", "// Types shared between the swarm server and the 3D client.\n\nexport type AgentStatus =\n | 'idle' // at desk, nothing assigned\n | 'preparing' // setting up the git worktree\n | 'working' // Claude Code session running\n | 'done' // finished, PR opened (or finished without one)\n | 'error' // session failed\n | 'stopped'; // manager stopped it\n\nexport type LogKind = 'text' | 'tool' | 'result' | 'system' | 'error' | 'manager' | 'done' | 'thinking';\n\nexport interface LogLine {\n id: number;\n t: number; // epoch ms\n kind: LogKind;\n text: string;\n tool?: string; // tool name for kind === 'tool'\n}\n\nexport interface IssueInfo {\n number: number;\n title: string;\n body: string;\n url: string;\n labels: string[];\n createdAt: string;\n}\n\nexport interface PullInfo {\n number: number;\n title: string;\n url: string;\n headRefName: string;\n state: 'OPEN' | 'CLOSED' | 'MERGED';\n isDraft: boolean;\n mergeable: string; // MERGEABLE | CONFLICTING | UNKNOWN\n reviewDecision: string | null;\n closesIssues: number[];\n createdAt: string;\n mergedAt: string | null;\n additions: number;\n deletions: number;\n checks: 'pending' | 'passing' | 'failing' | 'none';\n headSha: string;\n mergeState: string; // GitHub's mergeStateStatus: CLEAN | BEHIND | BLOCKED | DIRTY | UNSTABLE | DRAFT | UNKNOWN \u2026\n failedChecks: { name: string; url: string | null }[];\n pendingChecks: string[];\n}\n\nexport interface RepoView {\n id: string; // \"owner/name\"\n fullName: string;\n description: string;\n url: string;\n defaultBranch: string;\n floor: number; // 1-based floor number in the building\n color: string; // accent color for the floor\n autoAssign: boolean;\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\n folderSync: string | null; // how the floor's main checkout stands against GitHub: \"in sync\", \"updated to abc1234\", \"2 behind: local changes\" \u2026\n browserTesting: boolean;\n links: string[]; // ids of related repos this floor's agents can read for context\n mission: string; // the manager's brief: what this floor is building\n summary: string; // the CEO's one-line read of the project, e.g. \"3D browser game \u00B7 Three.js + Vite\"\n qaBrief: string; // how QA should test this kind of project (written by the CEO, editable)\n localPath: string | null; // the manager's own project folder, when the floor lives in one\n checkoutPath: string; // where the floor's main checkout is on disk (localPath, or a clone the office manages)\n cloneStatus: 'pending' | 'cloning' | 'ready' | 'error';\n cloneError?: string;\n issues: IssueInfo[]; // open issues\n pulls: PullInfo[]; // open + recently merged PRs\n lastSync: number | null;\n syncError?: string;\n previewConfig: PreviewConfig;\n preview: PreviewView;\n}\n\n/**\n * How a floor's app is run for the preview monitor. {port} and {tmp} are replaced in the command and env values;\n * PORT={port} is always set. command null: npm run dev, else start, else preview from package.json.\n */\nexport interface PreviewConfig {\n command: string | null;\n env: Record<string, string>;\n}\n\nexport type PreviewStatus =\n | 'unconfigured' // no command and no package.json\n | 'stopped'\n | 'preparing' // checking out the ref in the preview worktree\n | 'installing' // npm ci / npm install\n | 'starting' // command started, waiting for the port\n | 'running'\n | 'error';\n\n/** The floor's running app, served from its own worktree on a port reserved for the floor. */\nexport interface PreviewView {\n status: PreviewStatus;\n port: number;\n url: string | null; // set while running\n ref: string | null; // the default branch's name, or \"PR #n\"\n pr: number | null;\n commit: string | null; // short sha\n startedAt: number | null;\n error: string | null;\n logTail: string[]; // the last 40 lines of install / app output\n}\n\n/** A folder in the manager's projects folder, as offered when adding a floor. */\nexport interface ProjectFolderView {\n name: string;\n path: string;\n git: boolean;\n github: string | null; // owner/name of its GitHub origin\n floor: number | null; // already a floor in the office\n}\n\n/** dev and qa are the two pipeline lanes on every floor; the one CEO works in the lobby and runs the company. */\nexport type AgentRole = 'dev' | 'qa' | 'ceo';\n\n/** Fixed id of the CEO agent. */\nexport const CEO_ID = 'ceo';\n\n/** An agent's currentTool while the office installs their desk's dependencies (status 'preparing'). */\nexport const INSTALL_STEP = 'Installing dependencies';\n\n/** How the cartoon character is drawn. Picked from the agent's name when hired; the manager can change it. */\nexport type AgentLook = 'feminine' | 'masculine';\n\n/** What an agent is currently doing: implementing an issue, testing a PR, or fixing a PR after QA. */\nexport type AgentTask = 'issue' | 'qa' | 'fix';\n\n/**\n * How agents run. terminal: each agent is the real coding-agent CLI in its own terminal, shown live in the office.\n * sdk: Claude Code through the Agent SDK, its stream turned into log lines.\n */\nexport type AgentRuntime = 'terminal' | 'sdk';\n\n/** The coding-agent CLI an agent runs in its terminal. The CEO is always Claude Code. */\nexport type AgentCli = 'claude' | 'codex' | 'opencode';\n\n/** A coding-agent CLI the office knows how to run, and whether it's installed on this machine. */\nexport interface CliView {\n id: AgentCli;\n label: string;\n installed: boolean;\n version: string | null;\n /** Hooks report every tool call and enforce the guard rails; the others report only when a turn ends. */\n integrated: boolean;\n}\n\n/** Messages on an agent's terminal socket (/ws/term?agent=<id>), server to browser. */\nexport type TermServerMessage =\n | { t: 'snapshot'; data: string; cols: number; rows: number; live: boolean } // the screen and scrollback so far\n | { t: 'data'; data: string }\n | { t: 'size'; cols: number; rows: number } // another viewer resized the terminal\n | { t: 'live'; live: boolean }; // a CLI is (or is no longer) running in it\n\n/** Browser to server: keystrokes go to the running CLI; the size is the viewer's fitted terminal. */\nexport type TermClientMessage = { t: 'input'; data: string } | { t: 'resize'; cols: number; rows: number };\n\nexport interface AgentView {\n id: string;\n name: string;\n repoId: string;\n role: AgentRole;\n title: string; // job title, e.g. \"Three.js graphics engineer\" ('' = plain developer / QA tester)\n specialty: string; // routes issues labelled swarm:<specialty> to this agent first ('' = generalist)\n brief: string; // job description for this project, added to the agent's instructions\n hiredBy: 'manager' | 'ceo';\n look: AgentLook;\n task: AgentTask | null;\n desk: number; // desk slot on the floor (dev desks and QA lab stations are numbered separately)\n color: string; // shirt color\n hair: string; // hair color\n skin: string;\n model: string; // '' = use the swarm default model, or a model id / alias\n effort: EffortLevel | ''; // '' = use the swarm default effort\n cli: AgentCli | ''; // the CLI they run in the terminal runtime ('' = the office default)\n terminal: boolean; // they have a terminal to watch (the terminal runtime); otherwise their log lines are the screen\n status: AgentStatus;\n issueNumber: number | null; // devs: the issue being worked on\n issueTitle: string | null; // devs: issue title; QA: title of the PR under test\n branch: string | null;\n prNumber: number | null; // devs: the PR they opened; QA: the PR under test\n prUrl: string | null;\n currentTool: string | null; // while preparing: the setup step (INSTALL_STEP), null for the worktree\n startedAt: number | null;\n endedAt: number | null;\n costUsd: number;\n turns: number;\n browserUrl: string | null;\n hasScreenshot: boolean;\n screenshotAt: number | null;\n lastError: string | null;\n log: LogLine[]; // tail of the terminal log (full buffer on snapshot)\n}\n\n/** One piece of an agent's prompt; the parts' texts concatenated are the whole prompt. */\nexport interface PromptPart {\n label: string;\n text: string;\n /** The manager can change it (the job description); the rest is the office's workflow and safety rules. */\n editable: boolean;\n}\n\n/** GET /api/agents/:id/prompt: what the agent is told on a task, with placeholders for the task's details. */\nexport interface AgentPromptView {\n kind: 'dev' | 'qa' | 'ceo';\n text: string;\n parts: PromptPart[];\n}\n\nexport type EffortLevel = 'low' | 'medium' | 'high' | 'xhigh' | 'max';\n\nexport type QaStatus =\n | 'queued' // waiting for a free QA tester\n | 'testing' // a QA tester is on it\n | 'passed' // ready to merge\n | 'failed' // failed; waiting for the dev who wrote it to be free\n | 'fixing' // the dev is fixing what QA found\n | 'needs-human'; // failed too many rounds, or nobody can fix it automatically\n\nexport interface QaCheck {\n name: string;\n result: 'pass' | 'fail' | 'skip';\n details: string;\n}\n\nexport interface QaView {\n repoId: string;\n prNumber: number;\n status: QaStatus;\n round: number; // 1-based QA round\n devAgentId: string | null; // who wrote it (null for PRs opened outside the swarm)\n qaAgentId: string | null; // who is testing / last tested it\n summary: string | null; // latest QA summary\n checks: QaCheck[];\n commentUrl: string | null; // the PR comment with the latest QA report\n mergeNote: string | null; // where auto-merge stands once QA passed, e.g. \"waiting for checks: Vercel\"\n updatedAt: number;\n}\n\nexport interface SwarmSettings {\n sessionLimit: number; // most Claude Code sessions running at once; 0 = no limit\n defaultModel: string;\n defaultEffort: EffortLevel;\n runtime: AgentRuntime;\n defaultCli: AgentCli; // what developers and QA testers run in their terminals unless they have their own\n hiring: 'approve' | 'auto'; // CEO proposals wait for the manager, or go through while the floor is under teamCap\n teamCap: number; // most agents per floor the CEO may reach without the manager's approval (auto mode)\n ceoHeartbeatMin: number; // minutes between the CEO's periodic reviews; 0 = off\n managerName: string; // what the office calls you\n companyName: string;\n projectsDir: string; // where your project folders live; new projects are created here\n setupDone: boolean; // the first-run setup wizard has been completed or skipped\n tutorialStep: number; // index of the current tutorial step; -1 when finished or skipped\n autoUpdate?: boolean; // update the office itself once it's quiet (absent on servers without self-update)\n pacingSessions: number; // after Claude warns about usage, new issues start only while fewer sessions than this run\n voice: VoiceSettings;\n}\n\n/** Who reads phone messages aloud: nobody, the browser's own voice, or ElevenLabs (with the manager's key). */\nexport type VoiceProvider = 'off' | 'browser' | 'elevenlabs';\n\nexport interface VoiceSettings {\n provider: VoiceProvider;\n voiceId: string; // the ElevenLabs voice (or the browser voice's name)\n voiceName: string;\n model: string; // ElevenLabs model id\n speakOffice: boolean; // read the office's own notes too, not just the CEO's messages\n}\n\n/** GET /api/voice/voices: a voice the manager can pick. recommended: on docs/voice.md's shortlist. */\nexport interface VoiceOption {\n id: string;\n name: string;\n category: string;\n labels: { accent: string; gender: string; age: string; description: string; use_case: string };\n previewUrl: string | null;\n recommended: boolean;\n}\n\n/** Claude's subscription usage: normal, pacing new work after a usage warning, or paused at the limit until `until`. */\nexport interface UsageView {\n state: 'normal' | 'pacing' | 'paused';\n until: number | null;\n}\n\n/**\n * Where the office's own update stands. none: up to date \u00B7 available: new commits on GitHub \u00B7 waiting / draining:\n * starting nothing new while running sessions finish \u00B7 updating: handed to the launcher \u00B7 failed: see detail.\n */\nexport type OfficeUpdateState = 'none' | 'available' | 'waiting' | 'draining' | 'updating' | 'failed';\n\nexport interface OfficeUpdateView {\n state: OfficeUpdateState;\n behind: number; // commits the office's folder is behind GitHub\n launcher: boolean; // started by npm run dev / npm start, which can install the update and restart the office\n drainingSince: number | null;\n running: number; // sessions still running\n detail: string | null;\n}\n\n/** A CEO proposal to hire someone or let someone go. The manager (the board) decides. */\nexport interface HireRequestView {\n id: string;\n kind: 'hire' | 'let-go';\n repoId: string;\n role: 'dev' | 'qa';\n agentId: string | null; // let-go: who; hire: who was hired once approved\n name: string; // the candidate's name (let-go: the agent's name)\n title: string;\n specialty: string;\n brief: string;\n reason: string;\n model: string;\n effort: EffortLevel | '';\n look: AgentLook;\n color: string;\n hair: string;\n skin: string;\n status: 'pending' | 'approved' | 'rejected';\n note: string; // the manager's reason when rejecting\n createdAt: number;\n decidedAt: number | null;\n decidedBy: 'manager' | 'auto' | null;\n}\n\n/** One message in the phone thread between the manager and the CEO. */\nexport interface PhoneMessage {\n id: number;\n from: 'ceo' | 'manager' | 'office'; // office = notes from the building itself (decisions, errors)\n text: string;\n at: number;\n requestId?: string; // a hire / let-go proposal this message is about\n}\n\nexport type CeoJobKind = 'onboard' | 'plan' | 'review' | 'chat';\n\nexport interface CeoInfo {\n queue: { kind: CeoJobKind; label: string }[]; // jobs waiting for the CEO\n job: { kind: CeoJobKind; label: string } | null; // what the CEO is doing now\n lastReviewAt: number | null;\n nextReviewAt: number | null; // null when the heartbeat is off\n}\n\nexport interface WorldSnapshot {\n user: string | null; // gh login\n ghReady: boolean;\n ghError?: string;\n demo: boolean;\n workspaceRoot: string;\n settings: SwarmSettings;\n repos: RepoView[];\n agents: AgentView[];\n qa: QaView[];\n requests: HireRequestView[];\n ceo: CeoInfo;\n messages: PhoneMessage[];\n phoneReadAt: number; // CEO messages newer than this are unread\n officeCommit?: string | null; // short sha the server started on (absent on servers without self-update)\n officeUpdate?: OfficeUpdateView;\n usage: UsageView;\n clis: CliView[];\n voiceKeySet: boolean; // an ElevenLabs key is saved (the key itself never leaves the server)\n voiceKeyHint: string; // its last 4 characters, '' when none\n}\n\nexport type ServerEvent =\n | { type: 'snapshot'; data: WorldSnapshot }\n | { type: 'repo'; repo: RepoView }\n | { type: 'repoRemoved'; repoId: string }\n | { type: 'agent'; agent: Omit<AgentView, 'log'> }\n | { type: 'agentRemoved'; agentId: string }\n | { type: 'log'; agentId: string; lines: LogLine[] }\n | { type: 'screen'; agentId: string; url: string | null; at: number }\n | { type: 'qa'; qa: QaView }\n | { type: 'qaRemoved'; repoId: string; prNumber: number }\n | { type: 'settings'; settings: SwarmSettings }\n | { type: 'request'; request: HireRequestView }\n | { type: 'ceo'; ceo: CeoInfo }\n | { type: 'message'; message: PhoneMessage }\n | { type: 'phoneRead'; at: number }\n | { type: 'officeUpdate'; officeUpdate: OfficeUpdateView }\n | { type: 'usage'; usage: UsageView }\n | { type: 'clis'; clis: CliView[] }\n | { type: 'voiceKey'; voiceKeySet: boolean; voiceKeyHint: string }\n | { type: 'toast'; level: 'info' | 'success' | 'error'; text: string };\n\nexport interface GhRepoSummary {\n nameWithOwner: string;\n description: string;\n visibility: string;\n updatedAt: string;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["http", "path", "fs", "z", "repos", "body", "fs", "path", "path", "fs", "fs", "path", "fs", "os", "path", "fs", "path", "now", "found", "s", "tool", "toolInput", "crypto", "fs", "path", "fs", "createRequire", "path", "path", "fs", "createRequire", "bundled", "found", "s", "crypto", "fs", "path", "path", "onMessage", "path", "fs", "crypto", "p", "path", "body", "route", "server", "fs", "s", "exists", "crypto", "path", "l", "fs", "prompt", "launch", "spawn", "crypto", "fs", "path", "s", "killTree", "spawn", "fs", "net", "path", "s", "net", "sleep", "fs", "killTree", "path", "code", "spawn", "fs", "path", "s", "path", "fs", "crypto", "fs", "path", "URL", "s", "now", "s", "view", "crypto", "path", "fs", "run", "body", "crypto", "path", "body", "crypto", "s", "path", "tool", "git", "server", "pending", "run", "now", "qaInstructions", "fs", "path", "crypto", "z", "body", "rest", "z", "run", "server", "pending", "repoId", "issue", "body", "s", "now", "s", "issue", "testStep", "now", "fs", "path", "path", "s", "fs", "path", "view", "fs", "reason", "repoId", "body", "crypto", "issue", "inTerminal", "testStep", "failed", "s", "now", "pick", "repos", "rt", "pending", "z", "path", "fs", "http"]
7
7
  }