cubefarm 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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/previewRunner.ts", "../server/backend.ts", "../server/demo.ts", "../server/swarm.ts", "../server/ceo.ts", "../server/httpError.ts", "../server/previews.ts", "../shared/issues.ts", "../shared/types.ts"],
4
- "sourcesContent": ["import http from 'node:http';\r\nimport path from 'node:path';\r\nimport fs from 'node:fs';\r\nimport express, { type NextFunction, type Request, type Response } from 'express';\r\nimport { WebSocketServer } from 'ws';\r\nimport { DEMO, PORT, STATE_FILE, WORKSPACE_ROOT } from './config.ts';\r\nimport { realBackend } from './backend.ts';\r\nimport { createDemoBackend } from './demo.ts';\r\nimport { HttpError, Swarm } from './swarm.ts';\r\n\r\nconst swarm = new Swarm(DEMO ? createDemoBackend() : realBackend);\r\nawait swarm.init();\r\n\r\nconst app = express();\r\napp.use(express.json({ limit: '1mb' }));\r\n\r\ntype Handler = (req: Request, res: Response) => Promise<unknown> | unknown;\r\nconst route = (fn: Handler) => async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n const out = await fn(req, res);\r\n if (!res.headersSent) res.json(out ?? { ok: true });\r\n } catch (err) {\r\n next(err);\r\n }\r\n};\r\nconst num = (v: unknown) => {\r\n const n = Number(v);\r\n if (!Number.isInteger(n) || n <= 0) throw new HttpError(400, `Invalid number: ${v}`);\r\n return n;\r\n};\r\nconst str = (v: unknown) => (typeof v === 'string' ? v : '');\r\n// Repo ids contain a slash (\"owner/name\"), so they travel URL-encoded as a single segment.\r\nconst repoId = (req: Request) => decodeURIComponent(String(req.params.repo));\r\n\r\napp.get('/api/state', route(() => swarm.snapshot()));\r\n\r\napp.get('/api/github/repos', route((req) => swarm.listGithubRepos(str(req.query.owner) || undefined)));\r\n\r\n// What happens once a project moves in: the CEO's brief, and whether work starts on its own.\r\nconst floorOptions = (req: Request) => ({ mission: str(req.body.mission), autoAssign: req.body.autoAssign === true });\r\n\r\napp.post('/api/repos', route((req) => swarm.connectRepo(str(req.body.fullName).trim(), floorOptions(req))));\r\n\r\n// Your projects folder\r\napp.get('/api/folders', route((req) => swarm.listProjectFolders(str(req.query.dir) || undefined)));\r\napp.post('/api/folders/connect', route((req) => swarm.connectFolder(str(req.body.path), floorOptions(req))));\r\napp.post(\r\n '/api/folders/publish',\r\n route((req) =>\r\n swarm.publishFolder(str(req.body.path), {\r\n ...floorOptions(req),\r\n name: str(req.body.name) || undefined,\r\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\r\n description: str(req.body.description),\r\n }),\r\n ),\r\n);\r\napp.post(\r\n '/api/setup',\r\n route((req) =>\r\n swarm.setup({\r\n managerName: str(req.body.managerName),\r\n companyName: str(req.body.companyName),\r\n hiring: str(req.body.hiring),\r\n ceoName: str(req.body.ceoName),\r\n ceoLook: str(req.body.ceoLook),\r\n ceoColor: str(req.body.ceoColor),\r\n }),\r\n ),\r\n);\r\napp.post(\r\n '/api/repos/new',\r\n route((req) =>\r\n swarm.createRepo(str(req.body.name).trim(), {\r\n ...floorOptions(req),\r\n description: str(req.body.description),\r\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\r\n owner: str(req.body.owner).trim() || undefined,\r\n }),\r\n ),\r\n);\r\napp.patch('/api/repos/:repo', route((req) => swarm.updateRepo(repoId(req), req.body ?? {})));\r\napp.delete('/api/repos/:repo', route((req) => swarm.disconnectRepo(repoId(req))));\r\napp.post('/api/repos/:repo/sync', route((req) => swarm.syncRepo(repoId(req))));\r\napp.post('/api/repos/:repo/sync-folder', route((req) => swarm.syncFolderNow(repoId(req))));\r\napp.post(\r\n '/api/repos/:repo/issues',\r\n route(async (req) => ({\r\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),\r\n })),\r\n);\r\napp.post('/api/repos/:repo/plan', route((req) => swarm.planFloor(repoId(req), typeof req.body?.mission === 'string' ? req.body.mission : undefined)));\r\napp.post('/api/repos/:repo/onboard', route((req) => swarm.onboardFloor(repoId(req))));\r\n// The floor's app, for the preview monitor\r\napp.post(\r\n '/api/repos/:repo/preview',\r\n route((req) => {\r\n const pr = req.body?.pr;\r\n if (pr !== undefined && pr !== null && (typeof pr !== 'number' || !Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, 'pr must be a positive integer');\r\n return swarm.startPreview(repoId(req), pr ?? null);\r\n }),\r\n);\r\napp.delete('/api/repos/:repo/preview', route((req) => swarm.stopPreview(repoId(req))));\r\napp.post('/api/repos/:repo/pulls/:n/merge', route((req) => swarm.mergePull(repoId(req), num(req.params.n), req.body?.method ?? 'squash')));\r\napp.post('/api/repos/:repo/pulls/:n/close', route((req) => swarm.closePull(repoId(req), num(req.params.n))));\r\napp.post('/api/repos/:repo/pulls/:n/qa', route((req) => swarm.sendToQa(repoId(req), num(req.params.n))));\r\napp.post(\r\n '/api/repos/:repo/agents',\r\n route((req) =>\r\n swarm.hireAgent(repoId(req), {\r\n name: str(req.body.name),\r\n model: str(req.body.model),\r\n effort: str(req.body.effort),\r\n role: str(req.body.role),\r\n look: str(req.body.look),\r\n title: str(req.body.title),\r\n specialty: str(req.body.specialty),\r\n brief: str(req.body.brief),\r\n }),\r\n ),\r\n);\r\n\r\napp.patch('/api/agents/:id', route((req) => swarm.updateAgent(String(req.params.id), req.body ?? {})));\r\napp.delete('/api/agents/:id', route((req) => swarm.fireAgent(String(req.params.id))));\r\napp.post('/api/agents/:id/assign', route((req) => swarm.assign(String(req.params.id), num(req.body.issueNumber), str(req.body.note) || undefined)));\r\napp.post('/api/agents/:id/stop', route((req) => swarm.stopAgent(String(req.params.id))));\r\napp.post('/api/agents/:id/reset', route((req) => swarm.resetAgent(String(req.params.id))));\r\napp.post('/api/agents/:id/message', route((req) => swarm.message(String(req.params.id), str(req.body.text))));\r\napp.get('/api/agents/:id/screen', (req, res) => {\r\n const shot = swarm.screenshot(String(req.params.id));\r\n if (!shot) return void res.status(404).end();\r\n res.setHeader('Content-Type', shot.mime);\r\n res.setHeader('Cache-Control', 'no-store');\r\n res.end(shot.data);\r\n});\r\n\r\napp.patch('/api/settings', route((req) => swarm.updateSettings(req.body ?? {})));\r\n\r\n// The CEO and the manager's phone\r\napp.post('/api/ceo/message', route((req) => swarm.messageCeo(str(req.body.text))));\r\napp.post('/api/ceo/review', route(() => swarm.requestReview()));\r\napp.post('/api/phone/read', route((req) => swarm.markPhoneRead(Number(req.body?.at) || Date.now())));\r\napp.post(\r\n '/api/requests/:id/approve',\r\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 })),\r\n);\r\napp.post('/api/requests/:id/reject', route((req) => swarm.rejectRequest(String(req.params.id), str(req.body?.note))));\r\n\r\n// Serve the built client: the published package, or `npm start` after `npm run build`.\r\nconst dist = path.resolve(import.meta.dirname, '../dist');\r\nif (fs.existsSync(dist)) {\r\n app.use(express.static(dist));\r\n app.get(/^(?!\\/api).*/, (_req, res) => res.sendFile(path.join(dist, 'index.html')));\r\n}\r\n\r\napp.use((err: unknown, _req: Request, res: Response, _next: NextFunction) => {\r\n // express.json() flags malformed bodies with a 4xx status of its own.\r\n const parserStatus = (err as { status?: unknown })?.status;\r\n const status = err instanceof HttpError ? err.status : typeof parserStatus === 'number' && parserStatus >= 400 && parserStatus < 500 ? parserStatus : 500;\r\n const message = err instanceof Error ? err.message : String(err);\r\n if (status >= 500) console.error(err);\r\n res.status(status).json({ error: message });\r\n});\r\n\r\nconst server = http.createServer(app);\r\nconst wss = new WebSocketServer({ server, path: '/ws' });\r\nwss.on('connection', (ws) => swarm.addClient(ws));\r\n\r\nserver.listen(PORT, '127.0.0.1', () => {\r\n console.log(`\\n \uD83C\uDFE2 cubefarm on http://localhost:${PORT}${DEMO ? ' (DEMO MODE: fake GitHub + fake agents)' : ''}`);\r\n console.log(` state: ${STATE_FILE}`);\r\n console.log(` workspaces: ${WORKSPACE_ROOT}\\n`);\r\n});\r\n\r\n// Floors' apps don't outlive the office. (A hard kill skips this; the next start clears the orphans.)\r\nlet closing = false;\r\nconst shutdown = (signal: string) => {\r\n if (closing) return;\r\n closing = true;\r\n console.log(`\\n ${signal}: stopping floor previews\u2026`);\r\n const force = setTimeout(() => process.exit(0), 15_000);\r\n void swarm\r\n .shutdown()\r\n .catch((err) => console.error(err))\r\n .finally(() => {\r\n clearTimeout(force);\r\n process.exit(0);\r\n });\r\n};\r\nprocess.once('SIGINT', () => shutdown('SIGINT'));\r\nprocess.once('SIGTERM', () => shutdown('SIGTERM'));\r\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// 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';\r\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\r\n\r\n// All GitHub access goes through the gh CLI so it reuses the user's existing `gh auth login`.\r\n\r\nexport async function currentUser(): Promise<string> {\r\n return gh(['api', 'user', '--jq', '.login']);\r\n}\r\n\r\nexport async function listMyRepos(owner?: string): Promise<GhRepoSummary[]> {\r\n const args = ['repo', 'list'];\r\n if (owner) args.push(owner);\r\n args.push('--limit', '200', '--json', 'nameWithOwner,description,visibility,updatedAt');\r\n const repos = await ghJson<GhRepoSummary[]>(args);\r\n return repos.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\r\n}\r\n\r\nexport interface RepoMeta {\r\n nameWithOwner: string;\r\n description: string;\r\n url: string;\r\n defaultBranch: string;\r\n}\r\n\r\nexport async function repoMeta(fullName: string): Promise<RepoMeta> {\r\n const raw = await ghJson<{ nameWithOwner: string; description: string | null; url: string; defaultBranchRef: { name: string } | null }>([\r\n 'repo',\r\n 'view',\r\n fullName,\r\n '--json',\r\n 'nameWithOwner,description,url,defaultBranchRef',\r\n ]);\r\n return {\r\n nameWithOwner: raw.nameWithOwner,\r\n description: raw.description ?? '',\r\n url: raw.url,\r\n defaultBranch: raw.defaultBranchRef?.name || 'main',\r\n };\r\n}\r\n\r\nexport async function listIssues(fullName: string): Promise<IssueInfo[]> {\r\n const raw = await ghJson<\r\n { number: number; title: string; body: string; url: string; labels: { name: string }[]; createdAt: string }[]\r\n >(['issue', 'list', '-R', fullName, '--state', 'open', '--limit', '100', '--json', 'number,title,body,url,labels,createdAt']);\r\n return raw\r\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 }))\r\n .sort((a, b) => a.number - b.number);\r\n}\r\n\r\ninterface RawPull {\r\n number: number;\r\n title: string;\r\n url: string;\r\n headRefName: string;\r\n state: 'OPEN' | 'CLOSED' | 'MERGED';\r\n isDraft: boolean;\r\n mergeable: string;\r\n reviewDecision: string | null;\r\n closingIssuesReferences: { number: number }[] | null;\r\n createdAt: string;\r\n mergedAt: string | null;\r\n additions: number;\r\n deletions: number;\r\n headRefOid: string;\r\n mergeStateStatus: string;\r\n // check runs (GitHub Actions\u2026) carry name/status/conclusion/detailsUrl; commit statuses (Vercel\u2026) carry context/state/targetUrl\r\n statusCheckRollup: { name?: string; context?: string; status?: string; conclusion?: string; state?: string; detailsUrl?: string; targetUrl?: string }[] | null;\r\n}\r\n\r\nconst PR_FIELDS =\r\n 'number,title,url,headRefName,headRefOid,state,isDraft,mergeable,mergeStateStatus,reviewDecision,closingIssuesReferences,createdAt,mergedAt,additions,deletions,statusCheckRollup';\r\n\r\ntype Check = NonNullable<RawPull['statusCheckRollup']>[number];\r\nconst BAD = ['FAILURE', 'ERROR', 'CANCELLED', 'TIMED_OUT', 'ACTION_REQUIRED', 'STARTUP_FAILURE'];\r\nconst failed = (c: Check) => BAD.includes(c.conclusion ?? '') || BAD.includes(c.state ?? '');\r\nconst pending = (c: Check) => (!!c.status && c.status !== 'COMPLETED') || c.state === 'PENDING' || c.state === 'EXPECTED';\r\nconst checkName = (c: Check) => c.name || c.context || 'check';\r\n\r\nfunction checksOf(rollup: RawPull['statusCheckRollup']): PullInfo['checks'] {\r\n if (!rollup || rollup.length === 0) return 'none';\r\n if (rollup.some(failed)) return 'failing';\r\n if (rollup.some(pending)) return 'pending';\r\n return 'passing';\r\n}\r\n\r\nfunction toPull(p: RawPull): PullInfo {\r\n return {\r\n number: p.number,\r\n title: p.title,\r\n url: p.url,\r\n headRefName: p.headRefName,\r\n state: p.state,\r\n isDraft: p.isDraft,\r\n mergeable: p.mergeable,\r\n reviewDecision: p.reviewDecision || null,\r\n closesIssues: (p.closingIssuesReferences ?? []).map((r) => r.number),\r\n createdAt: p.createdAt,\r\n mergedAt: p.mergedAt,\r\n additions: p.additions,\r\n deletions: p.deletions,\r\n checks: checksOf(p.statusCheckRollup),\r\n headSha: p.headRefOid,\r\n mergeState: p.mergeStateStatus || 'UNKNOWN',\r\n failedChecks: (p.statusCheckRollup ?? []).filter(failed).map((c) => ({ name: checkName(c), url: c.detailsUrl || c.targetUrl || null })),\r\n pendingChecks: (p.statusCheckRollup ?? []).filter(pending).map(checkName),\r\n };\r\n}\r\n\r\nexport async function listPulls(fullName: string): Promise<PullInfo[]> {\r\n const [open, merged] = await Promise.all([\r\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'open', '--limit', '50', '--json', PR_FIELDS]),\r\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'merged', '--limit', '8', '--json', PR_FIELDS]),\r\n ]);\r\n return [...open, ...merged].map(toPull);\r\n}\r\n\r\n// swarm:<specialty> labels route issues to specialists. gh refuses unknown labels, so they're created on first use.\r\nconst labelsMade = new Set<string>();\r\n\r\nasync function ensureLabel(fullName: string, name: string) {\r\n const key = `${fullName}#${name}`;\r\n if (labelsMade.has(key)) return;\r\n await gh(['label', 'create', name, '-R', fullName, '--color', 'c77dff', '--description', 'cubefarm: routed to this specialty', '--force']);\r\n labelsMade.add(key);\r\n}\r\n\r\nexport async function createIssue(fullName: string, title: string, body: string, labels: string[] = []): Promise<number> {\r\n for (const l of labels) await ensureLabel(fullName, l);\r\n const args = ['issue', 'create', '-R', fullName, '--title', title, '--body-file', '-'];\r\n for (const l of labels) args.push('--label', l);\r\n const out = await gh(args, { input: body || ' ' });\r\n const match = out.match(/\\/issues\\/(\\d+)/);\r\n if (!match) throw new Error(`Could not read the new issue number from gh output: ${out}`);\r\n return Number(match[1]);\r\n}\r\n\r\n/** Merge a PR. With headSha, GitHub refuses if anything was pushed after that commit (e.g. after QA signed it off). */\r\nexport async function mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void> {\r\n const pr = await ghJson<{ headRefName: string; isCrossRepository: boolean }>(['pr', 'view', String(number), '-R', fullName, '--json', 'headRefName,isCrossRepository']);\r\n await gh(['pr', 'merge', String(number), '-R', fullName, `--${method}`, ...(headSha ? ['--match-head-commit', headSha] : [])], { timeoutMs: 60_000 });\r\n // Tidy up the swarm branch on the remote; the local worktree is cleaned when the agent takes its next issue.\r\n if (!pr.isCrossRepository && pr.headRefName.startsWith('swarm/')) {\r\n await gh(['api', '-X', 'DELETE', `repos/${fullName}/git/refs/heads/${pr.headRefName}`]).catch(() => undefined);\r\n }\r\n}\r\n\r\n/** Merge the base branch into a PR's branch on GitHub, for repos that only merge up-to-date branches. */\r\nexport async function updateBranch(fullName: string, number: number): Promise<void> {\r\n await gh(['pr', 'update-branch', String(number), '-R', fullName], { timeoutMs: 60_000 });\r\n}\r\n\r\nexport async function closePull(fullName: string, number: number): Promise<void> {\r\n await gh(['pr', 'close', String(number), '-R', fullName]);\r\n}\r\n\r\nexport async function prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null> {\r\n const list = await ghJson<{ number: number; url: string }[]>(['pr', 'list', '-R', fullName, '--head', branch, '--state', 'all', '--json', 'number,url', '--limit', '1']);\r\n return list[0] ?? null;\r\n}\r\n\r\n// ---------- QA support ----------\r\n\r\nexport interface PrDetails {\r\n number: number;\r\n title: string;\r\n body: string;\r\n url: string;\r\n headRefName: string;\r\n headSha: string;\r\n isCrossRepository: boolean;\r\n closesIssues: number[];\r\n state: 'OPEN' | 'CLOSED' | 'MERGED';\r\n mergeable: string;\r\n mergeState: string;\r\n}\r\n\r\nexport async function prDetails(fullName: string, number: number): Promise<PrDetails> {\r\n const raw = await ghJson<{\r\n number: number;\r\n title: string;\r\n body: string;\r\n url: string;\r\n headRefName: string;\r\n headRefOid: string;\r\n isCrossRepository: boolean;\r\n closingIssuesReferences: { number: number }[] | null;\r\n state: PrDetails['state'];\r\n mergeable: string;\r\n mergeStateStatus: string;\r\n }>(['pr', 'view', String(number), '-R', fullName, '--json', 'number,title,body,url,headRefName,headRefOid,isCrossRepository,closingIssuesReferences,state,mergeable,mergeStateStatus']);\r\n return {\r\n number: raw.number,\r\n title: raw.title,\r\n body: raw.body ?? '',\r\n url: raw.url,\r\n headRefName: raw.headRefName,\r\n headSha: raw.headRefOid,\r\n isCrossRepository: raw.isCrossRepository,\r\n closesIssues: (raw.closingIssuesReferences ?? []).map((r) => r.number),\r\n state: raw.state,\r\n mergeable: raw.mergeable,\r\n mergeState: raw.mergeStateStatus || 'UNKNOWN',\r\n };\r\n}\r\n\r\nexport async function issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }> {\r\n const raw = await ghJson<{ title: string; body: string }>(['issue', 'view', String(number), '-R', fullName, '--json', 'title,body']);\r\n return { title: raw.title, body: raw.body ?? '' };\r\n}\r\n\r\nexport async function commentPull(fullName: string, number: number, body: string): Promise<string> {\r\n const out = await gh(['pr', 'comment', String(number), '-R', fullName, '--body-file', '-'], { input: body });\r\n return out.match(/https:\\/\\/github\\.com\\/\\S+/)?.[0] ?? '';\r\n}\r\n\r\n// QA screenshots live on an orphan branch so evidence never lands in the default branch when a PR is merged.\r\nexport const EVIDENCE_BRANCH = 'swarm-qa-evidence';\r\nconst evidenceReady = new Set<string>();\r\n\r\nconst ghApiJson = <T>(method: string, endpoint: string, body: unknown) =>\r\n gh(['api', '-X', method, endpoint, '-H', 'Content-Type: application/json', '--input', '-'], { input: JSON.stringify(body), timeoutMs: 120_000 }).then(\r\n (out) => (out ? JSON.parse(out) : null) as T,\r\n );\r\n\r\nasync function ensureEvidenceBranch(fullName: string) {\r\n if (evidenceReady.has(fullName)) return;\r\n try {\r\n await gh(['api', `repos/${fullName}/git/ref/heads/${EVIDENCE_BRANCH}`]);\r\n } catch {\r\n const readme =\r\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';\r\n const newTree = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/trees`, {\r\n tree: [{ path: 'README.md', mode: '100644', type: 'blob', content: readme }],\r\n });\r\n const commit = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/commits`, { message: 'QA evidence branch (cubefarm)', tree: newTree.sha, parents: [] });\r\n await ghApiJson('POST', `repos/${fullName}/git/refs`, { ref: `refs/heads/${EVIDENCE_BRANCH}`, sha: commit.sha });\r\n }\r\n evidenceReady.add(fullName);\r\n}\r\n\r\n/** Upload one evidence file and return a URL that renders inside PR comments (also for private repos). */\r\nexport async function uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string> {\r\n await ensureEvidenceBranch(fullName);\r\n await ghApiJson('PUT', `repos/${fullName}/contents/${filePath}`, {\r\n message: `QA evidence: ${filePath}`,\r\n content: data.toString('base64'),\r\n branch: EVIDENCE_BRANCH,\r\n });\r\n return `https://github.com/${fullName}/raw/${EVIDENCE_BRANCH}/${filePath}`;\r\n}\r\n", "import fs from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { WORKSPACE_ROOT } from './config.ts';\r\nimport { gh, git, run } from './exec.ts';\r\n\r\n// Layout on disk:\r\n// <your projects folder>/<repo> the floor's main checkout: your own folder, only fetched and fast-forwarded (syncMain)\r\n// <WORKSPACE_ROOT>/<owner>__<repo>/desks/<agent> one git worktree per agent, reused from task to task\r\n// Desks stay outside your project so its dev server, tsc and linters never see them.\r\n// Floors connected before project folders existed keep their clone at <WORKSPACE_ROOT>/<owner>__<repo>/main.\r\n\r\nconst locks = new Map<string, Promise<unknown>>();\r\nconst localRoots = new Map<string, string>(); // lowercased owner/name -> the user's project folder\r\n\r\n/** Serialise git operations per repo so concurrent worktree adds don't fight over index locks. */\r\nfunction withRepoLock<T>(fullName: string, fn: () => Promise<T>): Promise<T> {\r\n const prev = locks.get(fullName) ?? Promise.resolve();\r\n const next = prev.catch(() => undefined).then(fn);\r\n locks.set(fullName, next);\r\n return next;\r\n}\r\n\r\nexport const repoDir = (fullName: string) => path.join(WORKSPACE_ROOT, fullName.replace('/', '__'));\r\nexport const mainDir = (fullName: string) => localRoots.get(fullName.toLowerCase()) ?? path.join(repoDir(fullName), 'main');\r\nexport const deskDir = (fullName: string, agentSlug: string) => path.join(repoDir(fullName), 'desks', agentSlug);\r\n\r\n/** Use the user's own folder as a floor's main checkout (null: back to a clone the office manages). */\r\nexport function setLocalPath(fullName: string, dir: string | null) {\r\n if (dir) localRoots.set(fullName.toLowerCase(), path.resolve(dir));\r\n else localRoots.delete(fullName.toLowerCase());\r\n}\r\n\r\nasync function exists(p: string) {\r\n return fs\r\n .access(p)\r\n .then(() => true)\r\n .catch(() => false);\r\n}\r\n\r\n// Tool droppings that should never be committed from a desk (shared by all worktrees of the clone).\r\n// .preview-tmp/ is the preview worktree's {tmp} scratch folder.\r\nconst LOCAL_EXCLUDES = ['.playwright-mcp/', '.preview-tmp/'];\r\n\r\nasync function addLocalExcludes(main: string) {\r\n const file = path.join(main, '.git', 'info', 'exclude');\r\n const current = await fs.readFile(file, 'utf8').catch(() => '');\r\n const missing = LOCAL_EXCLUDES.filter((l) => !current.split(/\\r?\\n/).includes(l));\r\n if (missing.length === 0) return;\r\n await fs.mkdir(path.dirname(file), { recursive: true });\r\n await fs.appendFile(file, `${current && !current.endsWith('\\n') ? '\\n' : ''}# added by cubefarm\\n${missing.join('\\n')}\\n`);\r\n}\r\n\r\n/** Make sure the floor's worktrees keep LOCAL_EXCLUDES out of git status. */\r\nexport const ensureLocalExcludes = (fullName: string) => addLocalExcludes(mainDir(fullName));\r\n\r\nexport function ensureClone(fullName: string): Promise<void> {\r\n return withRepoLock(fullName, async () => {\r\n const dir = mainDir(fullName);\r\n if (await exists(path.join(dir, '.git'))) {\r\n // Only remote-tracking refs change: your checkout, branch and uncommitted work are left alone.\r\n await git(['fetch', 'origin', '--prune'], { cwd: dir, timeoutMs: 180_000 });\r\n } else {\r\n await fs.mkdir(path.dirname(dir), { recursive: true });\r\n await gh(['repo', 'clone', fullName, dir], { timeoutMs: 600_000 });\r\n }\r\n await addLocalExcludes(dir);\r\n });\r\n}\r\n\r\nconst installs = new Map<string, Promise<unknown>>();\r\n\r\n/** npm install in a folder, one at a time per folder. */\r\nfunction npmInstall(dir: string) {\r\n const prev = installs.get(dir) ?? Promise.resolve();\r\n const opts = { cwd: dir, timeoutMs: 600_000 };\r\n const next = prev\r\n .catch(() => undefined)\r\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)));\r\n installs.set(dir, next);\r\n return next;\r\n}\r\n\r\n/**\r\n * Bring a floor's main checkout up to date with GitHub. It only ever fast-forwards, and only when the checkout is on\r\n * the default branch with no local changes: nothing is stashed, reset or discarded, and anything else leaves the\r\n * folder as it is. Installs dependencies when package.json or the lockfile changed. With `touch: false` it only\r\n * reports (the office's own folder). Returns the checkout's status, e.g. \"in sync\", \"updated to abc1234\" or\r\n * \"2 behind: local changes\"; null when there is no checkout yet.\r\n */\r\nexport async function syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<string | null> {\r\n const dir = mainDir(fullName);\r\n const result = await withRepoLock(fullName, async () => {\r\n if (!(await exists(path.join(dir, '.git')))) return null;\r\n const g = (args: string[], timeoutMs?: number) => git(args, { cwd: dir, timeoutMs });\r\n try {\r\n await g(['fetch', 'origin', '--prune'], 180_000);\r\n const target = `origin/${defaultBranch}`;\r\n const behind = Number(await g(['rev-list', '--count', `HEAD..${target}`]));\r\n const commits = `${behind} commit${behind === 1 ? '' : 's'}`;\r\n const branch = await g(['symbolic-ref', '--short', '-q', 'HEAD']).catch(() => '');\r\n if (branch !== defaultBranch) return { status: `on ${branch ? `branch ${branch}` : 'a detached HEAD'}${behind ? ` (${defaultBranch} is ${commits} ahead)` : ''}` };\r\n if (behind === 0) return { status: 'in sync' };\r\n if (Number(await g(['rev-list', '--count', `${target}..HEAD`])) > 0) return { status: `diverged: local commits, and ${commits} to pull` };\r\n if (!opts.touch) return { status: `update ready (${commits})` };\r\n if (await g(['status', '--porcelain', '--untracked-files=no'])) return { status: `${behind} behind: local changes` };\r\n const before = await g(['rev-parse', 'HEAD']);\r\n try {\r\n await g(['merge', '--ff-only', target], 120_000);\r\n } catch {\r\n return { status: `${behind} behind: local files are in the way` };\r\n }\r\n const changed = (await g(['diff', '--name-only', before, 'HEAD'])).split(/\\r?\\n/);\r\n const install = changed.some((f) => f === 'package.json' || f === 'package-lock.json') && (await exists(path.join(dir, 'package.json')));\r\n return { status: `updated to ${await g(['rev-parse', '--short', 'HEAD'])}`, install };\r\n } catch (err) {\r\n return { status: `sync failed: ${(err as Error).message.split(/\\r?\\n/)[0].slice(0, 160)}` };\r\n }\r\n });\r\n if (!result?.install) return result?.status ?? null;\r\n // Outside the repo lock: agents' worktrees don't wait for npm.\r\n try {\r\n await npmInstall(dir);\r\n return `${result.status} \u00B7 dependencies installed`;\r\n } catch (err) {\r\n console.warn(`npm install in ${dir} failed:`, (err as Error).message);\r\n return `${result.status} \u00B7 npm install failed`;\r\n }\r\n}\r\n\r\n// ---------- your projects folder ----------\r\n\r\nexport interface LocalFolder {\r\n name: string;\r\n path: string;\r\n git: boolean;\r\n github: string | null; // owner/name of its GitHub origin\r\n modified: number;\r\n}\r\n\r\n/** owner/name from a git config's origin URL, if it points at GitHub. */\r\nfunction githubFromConfig(config: string): string | null {\r\n const url = config.match(/\\[remote \"origin\"\\][^[]*?url\\s*=\\s*(\\S+)/)?.[1];\r\n const m = url?.match(/github\\.com[:/]([^/\\s]+)\\/([^/\\s]+?)(?:\\.git)?\\/?$/i);\r\n return m ? `${m[1]}/${m[2]}` : null;\r\n}\r\n\r\n/** What a folder is: a git repo? with a GitHub origin? Reads .git/config directly, so scanning is quick. */\r\nexport async function inspectFolder(dir: string): Promise<LocalFolder> {\r\n const full = path.resolve(dir);\r\n const stat = await fs.stat(full).catch(() => null);\r\n if (!stat?.isDirectory()) throw new Error(`${full} is not a folder`);\r\n const dotGit = path.join(full, '.git');\r\n const gitStat = await fs.stat(dotGit).catch(() => null);\r\n let config = '';\r\n if (gitStat?.isDirectory()) config = await fs.readFile(path.join(dotGit, 'config'), 'utf8').catch(() => '');\r\n else if (gitStat) {\r\n // a worktree or submodule: .git is a file pointing at the real git dir\r\n const ref = (await fs.readFile(dotGit, 'utf8').catch(() => '')).match(/gitdir:\\s*(.+)/)?.[1]?.trim();\r\n if (ref) {\r\n const gitDir = path.resolve(full, ref);\r\n config = await fs.readFile(path.join(gitDir, 'config'), 'utf8').catch(() => fs.readFile(path.join(gitDir, '..', '..', 'config'), 'utf8').catch(() => ''));\r\n }\r\n }\r\n return { name: path.basename(full), path: full, git: !!gitStat, github: githubFromConfig(config), modified: stat.mtimeMs };\r\n}\r\n\r\n/** The folders directly inside the projects folder, most recently changed first. */\r\nexport async function scanProjects(root: string): Promise<LocalFolder[]> {\r\n const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => {\r\n throw new Error(`Can't read the projects folder ${root}`);\r\n });\r\n const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules');\r\n const folders = await Promise.all(dirs.map((e) => inspectFolder(path.join(root, e.name)).catch(() => null)));\r\n return folders.filter((f): f is LocalFolder => !!f).sort((a, b) => b.modified - a.modified);\r\n}\r\n\r\nasync function commitReadme(dir: string, title: string, description: string) {\r\n const readme = path.join(dir, 'README.md');\r\n if (!(await exists(readme))) await fs.writeFile(readme, `# ${title}\\n\\n${description.trim()}\\n`);\r\n await git(['add', 'README.md'], { cwd: dir });\r\n try {\r\n await git(['commit', '-m', 'Initial commit'], { cwd: dir });\r\n } catch (err) {\r\n if (!/tell me who you are|user\\.(name|email)/i.test((err as Error).message)) throw err;\r\n // No git identity on this machine: commit as the GitHub account gh is signed in to.\r\n const login = await gh(['api', 'user', '--jq', '.login']);\r\n await git(['-c', `user.name=${login}`, '-c', `user.email=${login}@users.noreply.github.com`, 'commit', '-m', 'Initial commit'], { cwd: dir });\r\n }\r\n}\r\n\r\n/**\r\n * Put a folder on GitHub (gh repo create --source --push). Only what's already committed is pushed. A folder with\r\n * no commits yet gets a README commit, but only when it's empty: the office never decides which of your files go public.\r\n */\r\nexport async function publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string> {\r\n const full = path.resolve(dir);\r\n const info = await inspectFolder(full);\r\n if (info.github) return info.github;\r\n if (!info.git) await git(['init', '-b', 'main'], { cwd: full });\r\n const hasCommit = await git(['rev-parse', '--verify', 'HEAD'], { cwd: full }).then(\r\n () => true,\r\n () => false,\r\n );\r\n if (!hasCommit) {\r\n const files = (await fs.readdir(full)).filter((f) => f !== '.git' && f !== 'README.md');\r\n if (files.length) {\r\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.`);\r\n }\r\n await commitReadme(full, opts.name, opts.description ?? '');\r\n }\r\n const origin = await git(['remote', 'get-url', 'origin'], { cwd: full }).catch(() => '');\r\n if (origin) throw new Error(`${info.name}'s origin (${origin}) isn't on GitHub. cubefarm needs GitHub for issues and pull requests.`);\r\n const target = opts.owner ? `${opts.owner}/${opts.name}` : opts.name;\r\n const args = ['repo', 'create', target, `--${opts.visibility}`, '--source', full, '--remote', 'origin', '--push'];\r\n if (opts.description) args.push('--description', opts.description);\r\n const out = await gh(args, { cwd: full, timeoutMs: 120_000 });\r\n return out.match(/github\\.com\\/([^/\\s]+\\/[^/\\s]+?)(?:\\.git)?(?:\\s|$)/)?.[1] ?? (await inspectFolder(full)).github ?? target;\r\n}\r\n\r\n/** A brand-new project: <root>/<name> with a README, pushed to a new GitHub repo. */\r\nexport async function createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }) {\r\n const dir = path.join(root, name);\r\n if (await exists(dir)) {\r\n const inside = await fs.readdir(dir).catch(() => ['?']);\r\n if (inside.length) throw new Error(`${dir} already exists. Pick another name, or connect that folder instead.`);\r\n }\r\n await fs.mkdir(dir, { recursive: true });\r\n await git(['init', '-b', 'main'], { cwd: dir });\r\n await commitReadme(dir, name, opts.description ?? '');\r\n const fullName = await publishFolder(dir, { name, ...opts });\r\n return { fullName, path: dir };\r\n}\r\n\r\nexport interface DeskBase {\r\n defaultBranch: string;\r\n /** Start from a pull request's head instead of the default branch (QA testing, fixes after QA). */\r\n pr?: number;\r\n}\r\n\r\n/** Remove a directory, retrying while Windows still has handles open in it. */\r\nasync function removeDir(dir: string) {\r\n await fs.rm(dir, { recursive: true, force: true, maxRetries: 8, retryDelay: 250 });\r\n}\r\n\r\nexport function prepareDesk(fullName: string, base: DeskBase, agentSlug: string, branch: string): Promise<string> {\r\n return withRepoLock(fullName, async () => {\r\n const main = mainDir(fullName);\r\n await git(['fetch', 'origin', '--prune'], { cwd: main, timeoutMs: 180_000 });\r\n let ref = `origin/${base.defaultBranch}`;\r\n if (base.pr) {\r\n // refs/pull/N/head works for branches in this repo and for forks alike\r\n ref = `origin/pr/${base.pr}`;\r\n await git(['fetch', 'origin', `+refs/pull/${base.pr}/head:refs/remotes/${ref}`], { cwd: main, timeoutMs: 180_000 });\r\n }\r\n try {\r\n await git(['rev-parse', '--verify', ref], { cwd: main });\r\n } catch {\r\n throw new Error(\r\n base.pr\r\n ? `Could not fetch pull request #${base.pr} of ${fullName}.`\r\n : `${fullName} has no ${base.defaultBranch} branch yet. Push an initial commit (or create the repo with a README) before assigning work.`,\r\n );\r\n }\r\n\r\n const wt = deskDir(fullName, agentSlug);\r\n\r\n // Reuse the desk's worktree in place. Deleting it fails on Windows while any process (a dev server\r\n // the agent left running, a browser) still has its working directory inside, and reuse keeps\r\n // node_modules warm between tasks.\r\n if (await exists(path.join(wt, '.git'))) {\r\n try {\r\n await git(['checkout', '--force', '-B', branch, ref], { cwd: wt });\r\n await git(['reset', '--hard', ref], { cwd: wt });\r\n // Untracked leftovers from the last task go; ignored files (node_modules, build caches) stay.\r\n await git(['clean', '-fd'], { cwd: wt }).catch(() => undefined);\r\n return wt;\r\n } catch {\r\n // fall through and rebuild the worktree from scratch\r\n }\r\n }\r\n\r\n if (await exists(wt)) {\r\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\r\n try {\r\n await removeDir(wt);\r\n } catch (err) {\r\n throw new Error(\r\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.`,\r\n );\r\n }\r\n }\r\n await git(['worktree', 'prune'], { cwd: main });\r\n await fs.mkdir(path.dirname(wt), { recursive: true });\r\n await git(['worktree', 'add', '-B', branch, wt, ref], { cwd: main });\r\n return wt;\r\n });\r\n}\r\n\r\nexport function removeDesk(fullName: string, agentSlug: string): Promise<void> {\r\n return withRepoLock(fullName, async () => {\r\n const main = mainDir(fullName);\r\n const wt = deskDir(fullName, agentSlug);\r\n if (!(await exists(wt))) return;\r\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\r\n await removeDir(wt).catch(() => undefined);\r\n await git(['worktree', 'prune'], { cwd: main }).catch(() => undefined);\r\n });\r\n}\r\n\r\n// ---------- leftover processes ----------\r\n\r\n// Only these kinds of processes are stopped when walking up from a leftover to its (orphaned) launcher.\r\nconst LAUNCHERS = ['node.exe', 'cmd.exe', 'bash.exe', 'sh.exe', 'conhost.exe', 'python.exe', 'npm.exe', 'npx.exe', 'bun.exe', 'deno.exe'];\r\n\r\n/**\r\n * Stop what an agent left running: anything listening on its reserved port or whose command line\r\n * points into its desk, plus the shell/node chain that launched it. Called when the agent is not working.\r\n */\r\nexport async function releaseDesk(fullName: string, agentSlug: string, port: number): Promise<void> {\r\n const desk = deskDir(fullName, agentSlug);\r\n if (process.platform === 'win32') {\r\n const variants = [desk, desk.replaceAll('\\\\', '/')].map((d) => `'${d.toLowerCase().replaceAll(\"'\", \"''\")}'`).join(', ');\r\n const script = `\r\n$ErrorActionPreference = 'SilentlyContinue'\r\n$seed = @()\r\nGet-NetTCPConnection -LocalPort ${port} -State Listen | ForEach-Object { $seed += [int]$_.OwningProcess }\r\n$desks = @(${variants})\r\n$all = Get-CimInstance Win32_Process\r\n$byId = @{}; foreach ($p in $all) { $byId[[int]$p.ProcessId] = $p }\r\nforeach ($p in $all) {\r\n if (-not $p.CommandLine) { continue }\r\n $cmd = $p.CommandLine.ToLower()\r\n foreach ($d in $desks) { if ($cmd.Contains($d)) { $seed += [int]$p.ProcessId } }\r\n}\r\n$launchers = @(${LAUNCHERS.map((n) => `'${n}'`).join(', ')})\r\n$kill = New-Object 'System.Collections.Generic.HashSet[int]'\r\nforeach ($id in $seed) {\r\n $cur = $byId[$id]\r\n $first = $true\r\n while ($cur -and [int]$cur.ProcessId -ne ${process.pid} -and ($first -or $launchers -contains $cur.Name.ToLower())) {\r\n [void]$kill.Add([int]$cur.ProcessId)\r\n $first = $false\r\n $cur = $byId[[int]$cur.ParentProcessId]\r\n }\r\n}\r\nforeach ($id in $kill) { taskkill /PID $id /T /F 2>&1 | Out-Null }\r\nWrite-Output $kill.Count`;\r\n await run('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], { timeoutMs: 30_000 }).catch(() => undefined);\r\n return;\r\n }\r\n const pids = await run('sh', ['-c', `lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null; pgrep -f ${JSON.stringify(desk)} 2>/dev/null`]).catch(() => '');\r\n for (const pid of pids.split(/\\s+/).map(Number).filter((p) => p && p !== process.pid)) {\r\n try {\r\n process.kill(pid, 'SIGKILL');\r\n } catch {\r\n // already gone\r\n }\r\n }\r\n}\r\n", "import path from 'node:path';\r\nimport { query, type CanUseTool, type Options, type SDKMessage, type SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';\r\nimport type { AgentRole, EffortLevel, LogKind } from '../shared/types.ts';\r\nimport type { OfficeTools } from './ceo.ts';\r\nimport { VERSION } from './config.ts';\r\n\r\n// One Claude Code instance (via the Claude Agent SDK) working one issue in its own git worktree.\r\n// The CEO runs through here too, with the office tools instead of a shell.\r\n\r\nexport interface SessionOptions {\r\n cwd: string;\r\n prompt: string;\r\n systemAppend: string;\r\n model: string; // e.g. 'claude-opus-5-5'\r\n effort: EffortLevel;\r\n browserTesting: boolean;\r\n permissionMode: 'guarded' | 'bypass';\r\n additionalDirectories: string[]; // read-only reference clones of linked repos\r\n role: AgentRole;\r\n /** JSON schema for a structured final answer (QA reports). */\r\n outputSchema?: Record<string, unknown>;\r\n resumeSessionId?: string;\r\n /** The CEO's in-process MCP server (mcp__office__*). */\r\n office?: OfficeTools;\r\n}\r\n\r\nexport interface LogEntry {\r\n kind: LogKind;\r\n text: string;\r\n tool?: string;\r\n}\r\n\r\nexport interface SessionResult {\r\n ok: boolean;\r\n text: string;\r\n costUsd: number;\r\n turns: number;\r\n errors: string[];\r\n structured?: unknown;\r\n}\r\n\r\nexport interface SessionCallbacks {\r\n log(entries: LogEntry[]): void;\r\n tool(name: string | null): void;\r\n sessionId(id: string): void;\r\n browserUrl(url: string): void;\r\n screenshot(data: Buffer, mime: string): void;\r\n /** The final text of each turn: the reply to the prompt and to every message sent while it ran. */\r\n turn?(text: string): void;\r\n /** Claude turned the session away for the subscription's usage limit (epoch ms when it resets, if known). */\r\n limited?(resetsAt: number | null): void;\r\n finished(result: SessionResult): void;\r\n}\r\n\r\nexport interface SessionHandle {\r\n send(text: string): void;\r\n stop(): void;\r\n}\r\n\r\n/** Async queue used as the streaming-input prompt so the manager can message a running agent. */\r\nclass InputQueue implements AsyncIterable<SDKUserMessage> {\r\n private items: SDKUserMessage[] = [];\r\n private waiters: ((r: IteratorResult<SDKUserMessage>) => void)[] = [];\r\n private closed = false;\r\n\r\n push(text: string) {\r\n if (this.closed) return;\r\n const msg: SDKUserMessage = { type: 'user', message: { role: 'user', content: text }, parent_tool_use_id: null };\r\n const waiter = this.waiters.shift();\r\n if (waiter) waiter({ value: msg, done: false });\r\n else this.items.push(msg);\r\n }\r\n\r\n close() {\r\n this.closed = true;\r\n for (const w of this.waiters.splice(0)) w({ value: undefined, done: true });\r\n }\r\n\r\n [Symbol.asyncIterator](): AsyncIterator<SDKUserMessage> {\r\n return {\r\n next: () => {\r\n const item = this.items.shift();\r\n if (item) return Promise.resolve({ value: item, done: false });\r\n if (this.closed) return Promise.resolve({ value: undefined, done: true });\r\n return new Promise((resolve) => this.waiters.push(resolve));\r\n },\r\n };\r\n }\r\n}\r\n\r\n// ---------- guard rails for the default \"guarded\" permission mode ----------\r\n\r\nconst WRITE_TOOLS = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);\r\n\r\nconst BLOCKED_COMMANDS: { re: RegExp; why: string }[] = [\r\n { re: /\\bgit\\s+push\\b[^\\n]*(\\s--force\\b|\\s-f\\b|\\s--force-with-lease\\b|\\s\\+\\S)/, why: 'force-pushing is not allowed' },\r\n { re: /\\bgh\\s+pr\\s+merge\\b/, why: 'the office merges pull requests once QA and the checks pass, not agents' },\r\n { re: /\\bgh\\s+(repo\\s+(delete|edit|rename|archive)|secret|auth|release\\s+delete|api\\s+-X\\s*DELETE)\\b/, why: 'repository administration is off-limits' },\r\n { re: /\\brm\\s+-[a-zA-Z]*r[a-zA-Z]*f?\\s+(\\/|~|[A-Za-z]:[\\\\/]?)(\\s|$)/, why: 'deleting a filesystem root is not allowed' },\r\n { re: /\\b(shutdown|format\\s+[a-z]:|mkfs|Remove-Item\\s+[^\\n]*-Recurse[^\\n]*[A-Za-z]:\\\\\\s*$)/i, why: 'destructive system command' },\r\n { re: /\\bgit\\s+worktree\\b/, why: 'worktrees are managed by the swarm' },\r\n];\r\n\r\nfunction isInside(child: string, parent: string) {\r\n const rel = path.relative(parent, child);\r\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\r\n}\r\n\r\n// QA testers verify; they never change what's on GitHub. The office posts their report for them.\r\nconst QA_BLOCKED: { re: RegExp; why: string }[] = [\r\n { re: /\\bgit\\s+push\\b/, why: 'QA testers do not push code' },\r\n { re: /\\bgh\\s+(pr|issue)\\s+(merge|close|reopen|review|comment|edit|ready|create)\\b/, why: 'QA testers report back to the office instead of changing PRs or issues' },\r\n];\r\n\r\nfunction guardedCanUseTool(cwd: string, defaultBranchPush: RegExp, role: AgentRole): CanUseTool {\r\n return async (toolName, input, { blockedPath }) => {\r\n if (toolName.startsWith('mcp__') && !toolName.startsWith('mcp__playwright__') && !(role === 'ceo' && toolName.startsWith('mcp__office__'))) {\r\n return { behavior: 'deny', message: 'Only the Playwright browser tools are available to swarm agents.' };\r\n }\r\n if (WRITE_TOOLS.has(toolName)) {\r\n const target = String(input.file_path ?? input.notebook_path ?? '');\r\n if (target && !isInside(path.resolve(cwd, target), cwd)) {\r\n return { behavior: 'deny', message: `You may only edit files inside your worktree (${cwd}).` };\r\n }\r\n }\r\n if (toolName === 'Bash' || toolName === 'PowerShell') {\r\n const cmd = String(input.command ?? '');\r\n for (const rule of role === 'qa' ? [...BLOCKED_COMMANDS, ...QA_BLOCKED] : BLOCKED_COMMANDS) {\r\n if (rule.re.test(cmd)) return { behavior: 'deny', message: `Blocked by cubefarm: ${rule.why}.` };\r\n }\r\n if (defaultBranchPush.test(cmd)) {\r\n return { behavior: 'deny', message: 'Push your own branch and open a PR; pushing to the default branch is not allowed.' };\r\n }\r\n if (blockedPath && /\\b(rm|del|rmdir|mv|move|Remove-Item)\\b/i.test(cmd) && !isInside(path.resolve(blockedPath), cwd)) {\r\n return { behavior: 'deny', message: `That command touches ${blockedPath}, which is outside your worktree.` };\r\n }\r\n }\r\n return { behavior: 'allow', updatedInput: input };\r\n };\r\n}\r\n\r\n// ---------- formatting the stream into terminal lines ----------\r\n\r\nconst clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 1)}\u2026` : s);\r\n\r\nfunction rel(cwd: string, p: unknown) {\r\n const s = String(p ?? '');\r\n if (!s) return '';\r\n const r = path.relative(cwd, s);\r\n return r && !r.startsWith('..') ? r.replaceAll('\\\\', '/') : s;\r\n}\r\n\r\nconst escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n\r\n/** Agents often prefix commands with `cd \"<worktree>\" &&` and print absolute paths; show them relative instead. */\r\nfunction tidyPaths(cwd: string, text: string): string {\r\n let out = text;\r\n for (const v of new Set([cwd, cwd.replaceAll('\\\\', '/')])) {\r\n out = out.replace(new RegExp(`^cd\\\\s+\"?${escapeRe(v)}\"?\\\\s*(&&|;)\\\\s*`, 'i'), '');\r\n out = out.replace(new RegExp(`${escapeRe(v)}[\\\\\\\\/]?`, 'gi'), './');\r\n }\r\n return out;\r\n}\r\n\r\nfunction describeTool(cwd: string, name: string, input: Record<string, unknown>): string {\r\n switch (name) {\r\n case 'Bash':\r\n case 'PowerShell':\r\n return `$ ${clip(tidyPaths(cwd, String(input.command ?? '')).split('\\n')[0], 220)}`;\r\n case 'Read':\r\n return `Read ${rel(cwd, input.file_path)}`;\r\n case 'Write':\r\n return `Write ${rel(cwd, input.file_path)}`;\r\n case 'Edit':\r\n case 'MultiEdit':\r\n return `Edit ${rel(cwd, input.file_path)}`;\r\n case 'Glob':\r\n return `Glob ${input.pattern}`;\r\n case 'Grep':\r\n return `Grep \"${clip(String(input.pattern ?? ''), 80)}\"`;\r\n case 'WebFetch':\r\n return `Fetch ${input.url}`;\r\n case 'WebSearch':\r\n return `Search \"${input.query}\"`;\r\n case 'Task':\r\n case 'Agent':\r\n return `Subagent: ${input.description ?? ''}`;\r\n case 'TodoWrite':\r\n return 'Update todo list';\r\n }\r\n if (name.startsWith('mcp__playwright__')) {\r\n const action = name.replace('mcp__playwright__browser_', '').replace('mcp__playwright__', '');\r\n const detail = input.url ?? input.element ?? input.text ?? '';\r\n return `\uD83C\uDF10 ${action}${detail ? ` ${clip(String(detail), 120)}` : ''}`;\r\n }\r\n if (name.startsWith('mcp__office__')) return describeOfficeTool(name.slice('mcp__office__'.length), input);\r\n return `${name}(${clip(JSON.stringify(input), 140)})`;\r\n}\r\n\r\nexport function describeOfficeTool(action: string, input: Record<string, unknown>): string {\r\n const floor = input.floor != null ? ` \u2192 floor ${input.floor}` : '';\r\n switch (action) {\r\n case 'company_status':\r\n return '\uD83C\uDFE2 company_status';\r\n case 'agent_detail':\r\n return `\uD83D\uDD0E agent_detail ${String(input.agent_id ?? '')}`;\r\n case 'set_floor_profile':\r\n return `\uD83D\uDDC2\uFE0F set_floor_profile${floor}${input.summary ? `: ${clip(String(input.summary), 90)}` : ''}`;\r\n case 'update_job':\r\n return `\uD83E\uDEAA update_job ${input.title ? `\"${clip(String(input.title), 60)}\"` : String(input.agent_id ?? '')}`;\r\n case 'propose_hire':\r\n return `\uD83E\uDD1D propose_hire ${input.role === 'qa' ? 'QA ' : ''}\"${clip(String(input.title ?? ''), 60)}\"${floor}`;\r\n case 'propose_let_go':\r\n return `\uD83D\uDC4B propose_let_go ${String(input.agent_id ?? '')}`;\r\n case 'file_issue':\r\n return `\uD83D\uDCDD file_issue \"${clip(String(input.title ?? ''), 70)}\"${floor}${input.specialty ? ` \u00B7 ${input.specialty}` : ''}`;\r\n }\r\n return `\uD83C\uDFE2 ${action}(${clip(JSON.stringify(input), 120)})`;\r\n}\r\n\r\nfunction todoLines(input: Record<string, unknown>): LogEntry[] {\r\n const todos = Array.isArray(input.todos) ? (input.todos as { content?: string; status?: string }[]) : [];\r\n return todos.slice(0, 12).map((t) => ({\r\n kind: 'result' as const,\r\n text: ` ${t.status === 'completed' ? '\u2612' : t.status === 'in_progress' ? '\u25D0' : '\u2610'} ${clip(t.content ?? '', 150)}`,\r\n }));\r\n}\r\n\r\nfunction resultText(content: unknown): string {\r\n if (typeof content === 'string') return content;\r\n if (Array.isArray(content)) {\r\n return content\r\n .filter((b): b is { type: 'text'; text: string } => b?.type === 'text')\r\n .map((b) => b.text)\r\n .join('\\n');\r\n }\r\n return '';\r\n}\r\n\r\nconst lineCount = (text: string) => text.replace(/\\r/g, '').split('\\n').filter((l) => l.trim() !== '').length;\r\n\r\nfunction summariseResult(cwd: string, tool: string, text: string): LogEntry[] {\r\n // Claude Code-style one-liners for the chatty file tools\r\n if (tool === 'Edit' || tool === 'MultiEdit' || tool === 'NotebookEdit') return [{ kind: 'result', text: ' \u23BF Updated' }];\r\n if (tool === 'Write') return [{ kind: 'result', text: ' \u23BF Saved' }];\r\n if (tool === 'Read') return [{ kind: 'result', text: ` \u23BF Read ${lineCount(text)} lines` }];\r\n if (tool === 'Glob') return [{ kind: 'result', text: ` \u23BF Found ${lineCount(text)} files` }];\r\n const lines = tidyPaths(cwd, text).replace(/\\r/g, '').split('\\n').filter((l) => l.trim() !== '');\r\n if (lines.length === 0) return [{ kind: 'result', text: ' \u23BF (no output)' }];\r\n const shown = lines.slice(0, 3).map((l, i) => ({ kind: 'result' as const, text: `${i === 0 ? ' \u23BF ' : ' '}${clip(l, 170)}` }));\r\n if (lines.length > 3) shown.push({ kind: 'result', text: ` \u2026 +${lines.length - 3} lines` });\r\n return shown;\r\n}\r\n\r\n// ---------- the session ----------\r\n\r\nexport function startSession(opts: SessionOptions, callbacks: SessionCallbacks, defaultBranch: string): SessionHandle {\r\n let done = false;\r\n const cb: SessionCallbacks = {\r\n ...callbacks,\r\n finished: (r) => {\r\n if (done) return;\r\n done = true;\r\n callbacks.finished(r);\r\n },\r\n };\r\n const input = new InputQueue();\r\n const abort = new AbortController();\r\n let pendingTurns = 1;\r\n let stopped = false;\r\n let lastCost = 0;\r\n let lastTurns = 0;\r\n const toolNames = new Map<string, string>();\r\n\r\n input.push(opts.prompt);\r\n\r\n // Each agent must be a clean Claude Code instance on the subscription Claude Code is logged into.\r\n // Drop API keys (they would switch billing to the API) and any CLAUDE_* / ANTHROPIC_* variables\r\n // inherited from a parent Claude Code session (base URL proxies, session sockets, effort overrides\u2026).\r\n const env: Record<string, string | undefined> = {};\r\n for (const [k, v] of Object.entries(process.env)) {\r\n if (/^(ANTHROPIC_|CLAUDE)/i.test(k) && k !== 'CLAUDE_CONFIG_DIR') continue;\r\n env[k] = v;\r\n }\r\n env.CLAUDE_AGENT_SDK_CLIENT_APP = `cubefarm/${VERSION}`;\r\n\r\n const mcpServers: Options['mcpServers'] = {};\r\n if (opts.browserTesting) {\r\n // browser-init.js keeps pages from taking the real mouse with pointer lock (headless Chrome does on Windows).\r\n const args = ['-y', '@playwright/mcp@latest', '--headless', '--isolated', '--init-script', path.join(import.meta.dirname, 'browser-init.js')];\r\n mcpServers.playwright = process.platform === 'win32' ? { command: 'cmd', args: ['/c', 'npx', ...args] } : { command: 'npx', args };\r\n }\r\n if (opts.office) mcpServers.office = opts.office.server;\r\n // The CEO reads repositories and acts through the office tools; it never runs commands.\r\n const disallowedTools = ['AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode'];\r\n if (opts.role === 'ceo') disallowedTools.push('Bash', 'PowerShell', 'NotebookEdit');\r\n\r\n const escaped = defaultBranch.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n const defaultBranchPush = new RegExp(`\\\\bgit\\\\s+push\\\\b[^\\\\n]*\\\\s(HEAD:)?(refs/heads/)?${escaped}(\\\\s|$)`);\r\n\r\n const options: Options = {\r\n cwd: opts.cwd,\r\n additionalDirectories: opts.additionalDirectories,\r\n abortController: abort,\r\n env,\r\n model: opts.model || undefined,\r\n effort: opts.effort,\r\n settingSources: ['project', 'local'],\r\n // Agents get exactly the MCP servers passed below: no claude.ai connectors (Gmail, Drive\u2026),\r\n // no user-level servers or plugins from the host machine.\r\n strictMcpConfig: true,\r\n settings: { disableClaudeAiConnectors: true },\r\n systemPrompt: { type: 'preset', preset: 'claude_code', append: opts.systemAppend },\r\n mcpServers,\r\n disallowedTools,\r\n resume: opts.resumeSessionId,\r\n stderr: (data) => {\r\n const line = data.trim();\r\n if (line && /error|fail/i.test(line)) cb.log([{ kind: 'error', text: clip(line, 200) }]);\r\n },\r\n ...(opts.permissionMode === 'bypass'\r\n ? { permissionMode: 'bypassPermissions' as const, allowDangerouslySkipPermissions: true }\r\n : { permissionMode: 'acceptEdits' as const, canUseTool: guardedCanUseTool(opts.cwd, defaultBranchPush, opts.role) }),\r\n ...(opts.outputSchema ? { outputFormat: { type: 'json_schema' as const, schema: opts.outputSchema } } : {}),\r\n };\r\n\r\n // The office's prompts are answered one result each. See the 'result' case for results that answer none of them.\r\n let emptyTurn: NodeJS.Timeout | undefined;\r\n const answered = (msg: Extract<SDKMessage, { type: 'result' }>) => {\r\n pendingTurns -= 1;\r\n if (pendingTurns > 0) return;\r\n input.close();\r\n const ok = msg.subtype === 'success' && !msg.is_error;\r\n cb.finished({\r\n ok,\r\n text: msg.subtype === 'success' ? msg.result : '',\r\n costUsd: lastCost,\r\n turns: lastTurns,\r\n errors: msg.subtype === 'success' ? [] : msg.errors,\r\n structured: msg.subtype === 'success' ? msg.structured_output : undefined,\r\n });\r\n };\r\n\r\n const handle = (msg: SDKMessage) => {\r\n clearTimeout(emptyTurn);\r\n if (done && msg.type === 'assistant' && !stopped) {\r\n // The office already treated this session as finished, so it can't approve anything the session does.\r\n stopped = true;\r\n cb.log([{ kind: 'system', text: '\u25A0 This session kept working after it had finished, so it was stopped.' }]);\r\n abort.abort();\r\n return;\r\n }\r\n switch (msg.type) {\r\n case 'system': {\r\n if (msg.subtype === 'init') {\r\n cb.sessionId(msg.session_id);\r\n const mcp = msg.mcp_servers.map((s) => `${s.name}:${s.status}`).join(', ');\r\n cb.log([\r\n { kind: 'system', text: `\u273B Claude Code ${msg.claude_code_version} \u00B7 ${msg.model} \u00B7 ${msg.effort ?? opts.effort} effort \u00B7 ${opts.permissionMode}` },\r\n { kind: 'system', text: ` cwd ${msg.cwd}${mcp ? ` \u00B7 mcp ${mcp}` : ''}` },\r\n ]);\r\n } else if (msg.subtype === 'api_retry') {\r\n cb.log([{ kind: 'system', text: `\u2026 API retry ${msg.attempt}/${msg.max_retries} in ${Math.round(msg.retry_delay_ms / 1000)}s` }]);\r\n } else if (msg.subtype === 'compact_boundary') {\r\n cb.log([{ kind: 'system', text: '\u273B Conversation compacted' }]);\r\n }\r\n break;\r\n }\r\n case 'rate_limit_event': {\r\n const info = msg.rate_limit_info;\r\n if (info.status !== 'allowed') {\r\n const when = info.resetsAt ? new Date(info.resetsAt * 1000).toLocaleTimeString() : 'later';\r\n cb.log([{ kind: 'error', text: `\u26A0 Subscription usage ${info.status === 'rejected' ? 'limit reached' : 'warning'} (${info.rateLimitType ?? 'limit'}) \u00B7 resets ${when}` }]);\r\n const overage = info.isUsingOverage || info.overageStatus === 'allowed' || info.overageStatus === 'allowed_warning';\r\n if (info.status === 'rejected' && !overage) cb.limited?.(info.resetsAt ? info.resetsAt * 1000 : null);\r\n }\r\n break;\r\n }\r\n case 'assistant': {\r\n if (msg.parent_tool_use_id) break; // subagent chatter stays off the main screen\r\n const out: LogEntry[] = [];\r\n for (const block of msg.message.content) {\r\n if (block.type === 'text' && block.text.trim()) {\r\n const lines = block.text.trim().split('\\n');\r\n lines.slice(0, 30).forEach((l, i) => out.push({ kind: 'text', text: `${i === 0 ? '\u25CF ' : ' '}${l}` }));\r\n if (lines.length > 30) out.push({ kind: 'text', text: ` \u2026 (${lines.length - 30} more lines)` });\r\n } else if (block.type === 'thinking') {\r\n out.push({ kind: 'thinking', text: '\u273B Thinking\u2026' });\r\n } else if (block.type === 'tool_use') {\r\n const toolInput = (block.input ?? {}) as Record<string, unknown>;\r\n toolNames.set(block.id, block.name);\r\n out.push({ kind: 'tool', tool: block.name, text: `\u23FA ${describeTool(opts.cwd, block.name, toolInput)}` });\r\n if (block.name === 'TodoWrite') out.push(...todoLines(toolInput));\r\n cb.tool(block.name);\r\n if (block.name === 'mcp__playwright__browser_navigate' && typeof toolInput.url === 'string') cb.browserUrl(toolInput.url);\r\n }\r\n }\r\n if (out.length) cb.log(out);\r\n break;\r\n }\r\n case 'user': {\r\n if (msg.parent_tool_use_id) break;\r\n const content = msg.message.content;\r\n if (!Array.isArray(content)) break;\r\n const out: LogEntry[] = [];\r\n for (const block of content) {\r\n if (block.type !== 'tool_result') continue;\r\n const name = toolNames.get(block.tool_use_id) ?? '';\r\n const text = resultText(block.content);\r\n if (Array.isArray(block.content)) {\r\n for (const part of block.content) {\r\n if (part.type === 'image' && part.source.type === 'base64') {\r\n cb.screenshot(Buffer.from(part.source.data, 'base64'), part.source.media_type);\r\n }\r\n }\r\n }\r\n if (name.startsWith('mcp__playwright__')) {\r\n const url = text.match(/Page URL:\\s*(\\S+)/);\r\n if (url) cb.browserUrl(url[1]);\r\n }\r\n if (name === 'TodoWrite') continue;\r\n if (block.is_error) out.push({ kind: 'error', text: ` \u23BF ${clip(tidyPaths(opts.cwd, text).split('\\n')[0] || 'Error', 200)}` });\r\n else out.push(...summariseResult(opts.cwd, name, text));\r\n }\r\n cb.tool(null);\r\n if (out.length) cb.log(out);\r\n break;\r\n }\r\n case 'result': {\r\n lastCost = msg.total_cost_usd;\r\n lastTurns = msg.num_turns;\r\n if (msg.subtype === 'success' && !msg.is_error && msg.num_turns === 0) {\r\n // A resumed session can first replay a turn left over from before an office restart: an empty \"success\"\r\n // that answers none of our prompts, with the real turn right behind it. Counting it ended the session\r\n // while the real turn ran on without its permission channel. If nothing follows, it was the answer.\r\n emptyTurn = setTimeout(() => answered(msg), 30_000);\r\n break;\r\n }\r\n if (msg.subtype === 'success' && !msg.is_error && msg.result.trim()) cb.turn?.(msg.result.trim());\r\n answered(msg);\r\n break;\r\n }\r\n }\r\n };\r\n\r\n (async () => {\r\n try {\r\n for await (const msg of query({ prompt: input, options })) handle(msg);\r\n if (pendingTurns > 0) {\r\n cb.finished({ ok: false, text: '', costUsd: lastCost, turns: lastTurns, errors: [stopped ? 'Stopped by manager' : 'Session ended unexpectedly'] });\r\n }\r\n } catch (err) {\r\n input.close();\r\n const message = stopped ? 'Stopped by manager' : err instanceof Error ? err.message : String(err);\r\n cb.finished({ ok: false, text: '', costUsd: lastCost, turns: lastTurns, errors: [message] });\r\n }\r\n })();\r\n\r\n return {\r\n send(text) {\r\n pendingTurns += 1;\r\n input.push(text);\r\n },\r\n stop() {\r\n stopped = true;\r\n clearTimeout(emptyTurn);\r\n input.close();\r\n abort.abort();\r\n },\r\n };\r\n}\r\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 * as github from './github.ts';\r\nimport * as workspace from './workspace.ts';\r\nimport { startSession, type SessionCallbacks, type SessionHandle, type SessionOptions } from './agentRunner.ts';\r\nimport { realPreviews, type PreviewBackend } from './previewRunner.ts';\r\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\r\n\r\n/** Everything the swarm needs from the outside world. The demo backend fakes all of it. */\r\nexport interface Backend {\r\n demo: boolean;\r\n user(): Promise<string>;\r\n listMyRepos(owner?: string): Promise<GhRepoSummary[]>;\r\n repoMeta(fullName: string): Promise<github.RepoMeta>;\r\n listIssues(fullName: string): Promise<IssueInfo[]>;\r\n listPulls(fullName: string): Promise<PullInfo[]>;\r\n createIssue(fullName: string, title: string, body: string, labels?: string[]): Promise<number>;\r\n mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void>;\r\n updateBranch(fullName: string, number: number): Promise<void>;\r\n closePull(fullName: string, number: number): Promise<void>;\r\n prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null>;\r\n prDetails(fullName: string, number: number): Promise<github.PrDetails>;\r\n issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }>;\r\n commentPull(fullName: string, number: number, body: string): Promise<string>;\r\n uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string>;\r\n ensureClone(fullName: string): Promise<void>;\r\n /** Fast-forward the floor's main checkout to GitHub when that is safe; returns its status. */\r\n syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<string | null>;\r\n /** Point a floor at the user's own project folder (null: a clone the office manages). */\r\n setLocalPath(fullName: string, dir: string | null): void;\r\n scanProjects(root: string): Promise<workspace.LocalFolder[]>;\r\n inspectFolder(dir: string): Promise<workspace.LocalFolder>;\r\n publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string>;\r\n createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<{ fullName: string; path: string }>;\r\n mainDir(fullName: string): string;\r\n deskDir(fullName: string, agentSlug: string): string;\r\n prepareDesk(fullName: string, base: workspace.DeskBase, agentSlug: string, branch: string): Promise<string>;\r\n removeDesk(fullName: string, agentSlug: string): Promise<void>;\r\n /** Stop processes an agent left running (dev servers on its port, anything started in its desk). */\r\n releaseDesk(fullName: string, agentSlug: string, port: number): Promise<void>;\r\n startSession(opts: SessionOptions, cb: SessionCallbacks, defaultBranch: string): SessionHandle;\r\n /** Run a floor's app for the preview monitor (its own worktree, its own port). */\r\n previews: PreviewBackend;\r\n}\r\n\r\nexport const realBackend: Backend = {\r\n demo: false,\r\n user: github.currentUser,\r\n listMyRepos: github.listMyRepos,\r\n repoMeta: github.repoMeta,\r\n listIssues: github.listIssues,\r\n listPulls: github.listPulls,\r\n createIssue: github.createIssue,\r\n mergePull: github.mergePull,\r\n updateBranch: github.updateBranch,\r\n closePull: github.closePull,\r\n prForBranch: github.prForBranch,\r\n prDetails: github.prDetails,\r\n issueDetails: github.issueDetails,\r\n commentPull: github.commentPull,\r\n uploadEvidence: github.uploadEvidence,\r\n ensureClone: workspace.ensureClone,\r\n syncMain: workspace.syncMain,\r\n setLocalPath: workspace.setLocalPath,\r\n scanProjects: workspace.scanProjects,\r\n inspectFolder: workspace.inspectFolder,\r\n publishFolder: workspace.publishFolder,\r\n createProject: workspace.createProject,\r\n mainDir: workspace.mainDir,\r\n deskDir: workspace.deskDir,\r\n prepareDesk: workspace.prepareDesk,\r\n removeDesk: workspace.removeDesk,\r\n releaseDesk: workspace.releaseDesk,\r\n startSession,\r\n previews: realPreviews,\r\n};\r\n", "import crypto from 'node:crypto';\r\nimport http from 'node:http';\r\nimport path from 'node:path';\r\nimport type { Backend } from './backend.ts';\r\nimport type { PreviewBackend } from './previewRunner.ts';\r\nimport { describeOfficeTool, type LogEntry, type SessionCallbacks, type SessionHandle, type SessionOptions } from './agentRunner.ts';\r\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\r\nimport type { LocalFolder } from './workspace.ts';\r\n\r\n// `npm run demo`: a fake GitHub and fake Claude Code sessions, so the office (including the\r\n// dev \u2192 QA \u2192 fix loop) can be explored without spending any usage or touching real repos.\r\n\r\ninterface FakeRepo {\r\n fullName: string;\r\n description: string;\r\n issues: IssueInfo[];\r\n pulls: PullInfo[];\r\n nextNumber: number;\r\n}\r\n\r\nconst now = () => new Date().toISOString();\r\n\r\nfunction issue(n: number, title: string, body: string, fullName: string, labels: string[] = []): IssueInfo {\r\n return { number: n, title, body, url: `https://github.com/${fullName}/issues/${n}`, labels, createdAt: now() };\r\n}\r\n\r\nconst repos = new Map<string, FakeRepo>();\r\n/** Repos made in the demo (new projects, published folders): empty, so no package.json for the preview to fall back on. */\r\nconst bareRepos = new Set<string>();\r\nconst mergedSinceSync = new Map<string, number>(); // merges the fake project folder hasn't pulled yet\r\n\r\nconst fakeSha = () => crypto.randomBytes(20).toString('hex');\r\n\r\n/** Fake CI: checks run for a while after every push, and now and then one fails so the fix loop shows. */\r\nfunction runChecks(pr: PullInfo, fail = Math.random() < 0.2) {\r\n Object.assign(pr, { checks: 'pending', pendingChecks: ['CI / build', 'Vercel'], failedChecks: [] });\r\n setTimeout(() => {\r\n Object.assign(pr, {\r\n checks: fail ? 'failing' : 'passing',\r\n pendingChecks: [],\r\n failedChecks: fail ? [{ name: 'CI / build', url: `${pr.url}/checks` }] : [],\r\n });\r\n }, 12_000 + Math.random() * 10_000);\r\n}\r\n\r\nfunction seed(fullName: string, description: string, titles: [string, string][]) {\r\n const r: FakeRepo = { fullName, description, issues: [], pulls: [], nextNumber: 1 };\r\n for (const [title, body] of titles) r.issues.push(issue(r.nextNumber++, title, body, fullName));\r\n repos.set(fullName, r);\r\n}\r\n\r\nseed('demo-co/pixel-todo', 'A cheerful todo app', [\r\n ['Add dark mode toggle', 'Users want a dark theme. Persist the choice in localStorage.'],\r\n ['Todos should support due dates', 'Add an optional due date and highlight overdue items.'],\r\n ['Drag and drop to reorder', 'Let users reorder todos by dragging.'],\r\n ['Empty state illustration', 'Show a friendly illustration when the list is empty.'],\r\n ['Keyboard shortcuts', 'N for new todo, / to search, ? for help.'],\r\n ['Fix: completed count off by one', 'The footer shows one more completed item than there is.'],\r\n]);\r\nseed('demo-co/weather-api', 'Tiny weather REST API', [\r\n ['Add /forecast endpoint', 'Return a 5-day forecast for a city.'],\r\n ['Rate limit anonymous callers', '60 requests per minute per IP.'],\r\n ['OpenAPI spec', 'Publish an OpenAPI 3.1 document at /openapi.json.'],\r\n]);\r\n\r\nfunction screenshotSvg(title: string, url: string, hue: number) {\r\n const safe = (s: string) => s.replace(/[<>&\"]/g, '');\r\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"640\" height=\"400\" viewBox=\"0 0 640 400\">\r\n <rect width=\"640\" height=\"400\" fill=\"hsl(${hue},60%,97%)\"/>\r\n <rect width=\"640\" height=\"56\" fill=\"hsl(${hue},70%,55%)\"/>\r\n <text x=\"24\" y=\"37\" font-family=\"Segoe UI, Arial\" font-size=\"22\" font-weight=\"700\" fill=\"#fff\">${safe(title)}</text>\r\n <text x=\"620\" y=\"36\" text-anchor=\"end\" font-family=\"Segoe UI, Arial\" font-size=\"13\" fill=\"#fff\">${safe(url)}</text>\r\n ${[0, 1, 2, 3]\r\n .map(\r\n (i) => `<rect x=\"24\" y=\"${84 + i * 70}\" width=\"592\" height=\"56\" rx=\"10\" fill=\"#fff\" stroke=\"hsl(${hue},40%,85%)\"/>\r\n <circle cx=\"54\" cy=\"${112 + i * 70}\" r=\"11\" fill=\"none\" stroke=\"hsl(${hue},60%,55%)\" stroke-width=\"3\"/>\r\n <rect x=\"80\" y=\"${104 + i * 70}\" width=\"${180 + ((i * 97) % 220)}\" height=\"14\" rx=\"7\" fill=\"hsl(${hue},25%,80%)\"/>`,\r\n )\r\n .join('\\n')}\r\n</svg>`;\r\n}\r\n\r\ntype Step = LogEntry[] | (() => void);\r\n\r\nfunction devScript(opts: SessionOptions, cb: SessionCallbacks, issueNumber: number, issueTitle: string): Step[] {\r\n const branch = path.basename(opts.cwd);\r\n const hue = (issueNumber * 67) % 360;\r\n const file = ['src/App.tsx', 'src/components/TodoList.tsx', 'src/api/routes.ts', 'src/styles.css'][issueNumber % 4];\r\n const port = 5200 + (issueNumber % 50);\r\n return [\r\n [{ kind: 'text', text: `\u25CF I'll start by getting familiar with the codebase for \"${issueTitle}\".` }],\r\n [{ kind: 'tool', tool: 'Glob', text: '\u23FA Glob src/**/*.{ts,tsx}' }, { kind: 'result', text: ' \u23BF Found 23 files' }],\r\n [{ kind: 'tool', tool: 'Read', text: `\u23FA Read ${file}` }, { kind: 'result', text: ' \u23BF Read 184 lines' }],\r\n [{ kind: 'thinking', text: '\u273B Thinking\u2026' }],\r\n [\r\n { kind: 'tool', tool: 'TodoWrite', text: '\u23FA Update todo list' },\r\n { kind: 'result', text: ' \u25D0 Understand current behaviour' },\r\n { kind: 'result', text: ' \u2610 Implement the change' },\r\n { kind: 'result', text: ' \u2610 Add tests' },\r\n { kind: 'result', text: ' \u2610 Verify in the browser' },\r\n ],\r\n [{ kind: 'tool', tool: 'Grep', text: '\u23FA Grep \"useTodos\"' }, { kind: 'result', text: ' \u23BF Found 6 matches in 4 files' }],\r\n [{ kind: 'text', text: \"\u25CF The state lives in a single hook. I'll extend it and keep the API backwards compatible.\" }],\r\n [{ kind: 'tool', tool: 'Edit', text: `\u23FA Edit ${file}` }, { kind: 'result', text: ' \u23BF Updated' }],\r\n [{ kind: 'tool', tool: 'Write', text: '\u23FA Write src/__tests__/feature.test.ts' }, { kind: 'result', text: ' \u23BF Saved' }],\r\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm test -- --run' }],\r\n [\r\n { kind: 'result', text: ' \u23BF \u2713 src/__tests__/feature.test.ts (4 tests) 38ms' },\r\n { kind: 'result', text: ' Test Files 7 passed (7)' },\r\n ],\r\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ npm run dev -- --port ${port} &` }, { kind: 'result', text: ' \u23BF VITE ready in 412 ms' }],\r\n () => cb.browserUrl(`http://localhost:${port}/`),\r\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}/` }],\r\n () => cb.screenshot(Buffer.from(screenshotSvg(issueTitle, `localhost:${port}`, hue)), 'image/svg+xml'),\r\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' }],\r\n [{ kind: 'text', text: '\u25CF Looks right in the browser. Committing and opening a PR.' }],\r\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ git commit -am \"feat: ${issueTitle.toLowerCase()}\"` }, { kind: 'result', text: ` \u23BF [${branch} 3f2a91c] feat: ${issueTitle.toLowerCase()}` }],\r\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git push -u origin HEAD' }, { kind: 'result', text: ' \u23BF branch set up to track origin' }],\r\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ gh pr create --title \"${issueTitle}\" --body \"Closes #${issueNumber}\"` }],\r\n ];\r\n}\r\n\r\nfunction qaScript(cb: SessionCallbacks, pr: number, title: string, round: number): Step[] {\r\n const port = 5600 + (pr % 50);\r\n const hue = (pr * 41) % 360;\r\n return [\r\n [{ kind: 'text', text: `\u25CF Testing PR #${pr} \"${title}\" (round ${round}). First, the acceptance criteria from the issue.` }],\r\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ git diff origin/main...HEAD --stat' }, { kind: 'result', text: ' \u23BF 3 files changed, 82 insertions(+), 9 deletions(-)' }],\r\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm ci && npm test -- --run' }],\r\n [\r\n { kind: 'result', text: ' \u23BF Test Files 8 passed (8)' },\r\n { kind: 'result', text: ' Tests 41 passed (41)' },\r\n ],\r\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm run lint && npm run build' }, { kind: 'result', text: ' \u23BF \u2713 built in 1.84s' }],\r\n [{ kind: 'tool', tool: 'Bash', text: `\u23FA $ npm run preview -- --port ${port} &` }, { kind: 'result', text: ` \u23BF Local: http://localhost:${port}/` }],\r\n () => cb.browserUrl(`http://localhost:${port}/`),\r\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}/` }],\r\n () => cb.screenshot(Buffer.from(screenshotSvg(`QA \u00B7 ${title}`, `localhost:${port}`, hue)), 'image/svg+xml'),\r\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' }],\r\n [{ kind: 'tool', tool: 'mcp__playwright__browser_click', text: '\u23FA \uD83C\uDF10 click \"Add todo\" button' }, { kind: 'result', text: ' \u23BF Clicked' }],\r\n [{ kind: 'tool', tool: 'mcp__playwright__browser_resize', text: '\u23FA \uD83C\uDF10 resize 375x740' }, { kind: 'result', text: ' \u23BF Resized' }],\r\n () => cb.screenshot(Buffer.from(screenshotSvg(`QA \u00B7 mobile \u00B7 ${title}`, `localhost:${port}`, (hue + 40) % 360)), 'image/svg+xml'),\r\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' }],\r\n [{ kind: 'tool', tool: 'mcp__playwright__browser_console_messages', text: '\u23FA \uD83C\uDF10 console_messages' }, { kind: 'result', text: ' \u23BF No errors' }],\r\n ];\r\n}\r\n\r\nfunction fixScript(pr: number): Step[] {\r\n return [\r\n [{ kind: 'text', text: `\u25CF Reading the QA report for PR #${pr}. The toolbar overflows on phones; I'll let it wrap.` }],\r\n [{ kind: 'tool', tool: 'Read', text: '\u23FA Read src/styles.css' }, { kind: 'result', text: ' \u23BF Read 212 lines' }],\r\n [{ kind: 'tool', tool: 'Edit', text: '\u23FA Edit src/styles.css' }, { kind: 'result', text: ' \u23BF Updated' }],\r\n [{ kind: 'tool', tool: 'Bash', text: '\u23FA $ npm test -- --run' }, { kind: 'result', text: ' \u23BF Test Files 8 passed (8)' }],\r\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' }],\r\n ];\r\n}\r\n\r\nfunction fakeSession(opts: SessionOptions, cb: SessionCallbacks, fullName: string): SessionHandle {\r\n const timers: NodeJS.Timeout[] = [];\r\n let stopped = false;\r\n const kind = opts.role === 'qa' ? 'qa' : /FAILED|taking over pull request|git push origin HEAD:/.test(opts.prompt) ? 'fix' : 'issue';\r\n const prMatch = opts.prompt.match(/pull request #(\\d+)(?::\\s*(.+))?/);\r\n const issueMatch = opts.prompt.match(/#(\\d+):\\s*(.+)/);\r\n const number = Number((kind === 'issue' ? issueMatch?.[1] : prMatch?.[1]) ?? 0);\r\n const title = (kind === 'issue' ? issueMatch?.[2] : prMatch?.[2])?.trim() ?? 'follow-up';\r\n const round = Number(opts.prompt.match(/QA round (\\d+)/)?.[1] ?? 1);\r\n\r\n const header: Step = [\r\n { kind: 'system', text: `\u273B Claude Code (demo) \u00B7 ${opts.model} \u00B7 ${opts.effort} effort \u00B7 ${opts.permissionMode}` },\r\n { kind: 'system', text: ` cwd ${opts.cwd}` },\r\n ];\r\n const body = kind === 'qa' ? qaScript(cb, number, title, round) : kind === 'fix' ? fixScript(number) : devScript(opts, cb, number, title);\r\n const script = [header, ...body];\r\n\r\n const finish = () => {\r\n const costUsd = 0.3 + Math.random();\r\n const turns = 15 + Math.floor(Math.random() * 20);\r\n cb.tool(null);\r\n if (kind === 'qa') {\r\n // Most first rounds pass; some fail so the fix loop can be seen in action.\r\n const pass = round > 1 || Math.random() > 0.35;\r\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.' }]);\r\n cb.finished({\r\n ok: true,\r\n text: '',\r\n costUsd,\r\n turns,\r\n errors: [],\r\n structured: {\r\n verdict: pass ? 'pass' : 'fail',\r\n summary: pass\r\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.'\r\n : 'The feature works on desktop, but on a 375px-wide screen the toolbar overflows and the new button is cut off.',\r\n checks: [\r\n { name: 'Unit tests', result: 'pass', details: '41 passed, 0 failed' },\r\n { name: 'Lint + build', result: 'pass', details: 'No lint errors; production build succeeds' },\r\n { name: 'Feature works on desktop', result: 'pass', details: 'Clicked through the new flow at 1280x800' },\r\n { name: 'Mobile layout (375px)', result: pass ? 'pass' : 'fail', details: pass ? 'Layout wraps correctly' : 'Toolbar overflows horizontally; button unreachable' },\r\n { name: 'Console errors', result: 'pass', details: 'None' },\r\n ],\r\n commands: [\r\n { command: 'npm test -- --run', result: '41 passed' },\r\n { command: 'npm run lint && npm run build', result: 'clean, built in 1.84s' },\r\n ],\r\n screenshots: ['Desktop view after the change', 'Mobile view at 375px'],\r\n fixInstructions: pass ? undefined : 'Make the toolbar wrap (flex-wrap: wrap) below 480px so every button stays visible.',\r\n },\r\n });\r\n return;\r\n }\r\n if (kind === 'fix') {\r\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\r\n if (pr) {\r\n pr.headSha = fakeSha();\r\n pr.mergeState = 'CLEAN';\r\n pr.mergeable = 'MERGEABLE';\r\n runChecks(pr, false);\r\n }\r\n cb.log([{ kind: 'text', text: `\u25CF Fixed PR #${number} and pushed. Ready for another QA round.` }]);\r\n cb.finished({ ok: true, text: '', costUsd, turns, errors: [] });\r\n return;\r\n }\r\n const repo = repos.get(fullName);\r\n let url = '';\r\n if (repo && number) {\r\n const n = repo.nextNumber++;\r\n url = `https://github.com/${fullName}/pull/${n}`;\r\n repo.pulls.unshift({\r\n number: n,\r\n title,\r\n url,\r\n headRefName: `swarm/issue-${number}-${path.basename(opts.cwd).replace(/-[0-9a-f]{4}$/, '')}`,\r\n state: 'OPEN',\r\n isDraft: false,\r\n mergeable: 'MERGEABLE',\r\n reviewDecision: null,\r\n closesIssues: [number],\r\n createdAt: now(),\r\n mergedAt: null,\r\n additions: 40 + ((number * 13) % 200),\r\n deletions: (number * 7) % 40,\r\n checks: 'pending',\r\n headSha: fakeSha(),\r\n mergeState: 'CLEAN',\r\n failedChecks: [],\r\n pendingChecks: [],\r\n });\r\n runChecks(repo.pulls[0]);\r\n cb.log([{ kind: 'result', text: ` \u23BF ${url}` }]);\r\n }\r\n cb.log([{ kind: 'text', text: `\u25CF Opened ${url || 'the pull request'}. It closes #${number} and includes tests.` }]);\r\n cb.finished({ ok: true, text: url, costUsd, turns, errors: [] });\r\n };\r\n\r\n let i = 0;\r\n const step = () => {\r\n if (stopped) return;\r\n if (i >= script.length) return finish();\r\n const s = script[i++];\r\n if (typeof s === 'function') s();\r\n else {\r\n const tool = s.find((e) => e.kind === 'tool');\r\n cb.tool(tool?.tool ?? null);\r\n cb.log(s);\r\n }\r\n timers.push(setTimeout(step, 1600 + Math.random() * 3800));\r\n };\r\n timers.push(setTimeout(step, 600));\r\n\r\n return {\r\n send(text) {\r\n timers.push(\r\n setTimeout(() => {\r\n if (stopped) return;\r\n cb.log([{ kind: 'text', text: `\u25CF Got it \u2014 \"${text.slice(0, 60)}\". Adjusting my approach.` }]);\r\n }, 1500),\r\n );\r\n },\r\n stop() {\r\n stopped = true;\r\n timers.forEach(clearTimeout);\r\n cb.finished({ ok: false, text: '', costUsd: 0.1, turns: i, errors: ['Stopped by manager'] });\r\n },\r\n };\r\n}\r\n\r\nexport function createDemoBackend(): Backend {\r\n // Tie each fake session back to its repo via the desk directory name.\r\n const deskRepo = new Map<string, string>();\r\n // A pretend projects folder: the demo repos, one git folder that isn't on GitHub yet, and one plain folder.\r\n const folders = new Map<string, LocalFolder>();\r\n const addFolder = (name: string, github: string | null, git = true) =>\r\n folders.set(name, { name, path: `/demo/projects/${name}`, git, github, modified: Date.now() - folders.size * 3_600_000 });\r\n for (const r of repos.values()) addFolder(r.fullName.split('/')[1], r.fullName);\r\n addFolder('sketchbook', null);\r\n addFolder('recipe-notes', null, false);\r\n const newRepo = (name: string, description = '') => {\r\n const fullName = `demo-co/${name}`;\r\n if (!repos.has(fullName)) {\r\n repos.set(fullName, { fullName, description, issues: [], pulls: [], nextNumber: 1 });\r\n bareRepos.add(fullName);\r\n }\r\n addFolder(name, fullName);\r\n return fullName;\r\n };\r\n const folderOf = (dir: string) => {\r\n const f = folders.get(dir.replace(/\\\\/g, '/').split('/').pop() ?? '');\r\n if (!f) throw new Error(`${dir} is not a folder`);\r\n return f;\r\n };\r\n return {\r\n demo: true,\r\n user: async () => 'demo-manager',\r\n listMyRepos: async (): Promise<GhRepoSummary[]> =>\r\n [...repos.values()].map((r) => ({ nameWithOwner: r.fullName, description: r.description, visibility: 'PUBLIC', updatedAt: now() })),\r\n repoMeta: async (fullName) => {\r\n const r = repos.get(fullName);\r\n if (!r) throw new Error(`Unknown demo repo ${fullName}`);\r\n return { nameWithOwner: fullName, description: r.description, url: `https://github.com/${fullName}`, defaultBranch: 'main' };\r\n },\r\n setLocalPath: () => undefined,\r\n scanProjects: async () => [...folders.values()].sort((a, b) => b.modified - a.modified),\r\n inspectFolder: async (dir) => folderOf(dir),\r\n publishFolder: async (dir, opts) => {\r\n const f = folderOf(dir);\r\n return f.github ?? newRepo(f.name, opts.description);\r\n },\r\n createProject: async (_root, name, opts) => {\r\n if (folders.has(name)) throw new Error(`/demo/projects/${name} already exists. Pick another name, or connect that folder instead.`);\r\n return { fullName: newRepo(name, opts.description), path: `/demo/projects/${name}` };\r\n },\r\n listIssues: async (fullName) => [...(repos.get(fullName)?.issues ?? [])],\r\n listPulls: async (fullName) => [...(repos.get(fullName)?.pulls ?? [])],\r\n createIssue: async (fullName, title, body, labels = []) => {\r\n const r = repos.get(fullName);\r\n if (!r) throw new Error('Unknown repo');\r\n const n = r.nextNumber++;\r\n r.issues.push(issue(n, title, body, fullName, labels));\r\n return n;\r\n },\r\n mergePull: async (fullName, number, _method, headSha) => {\r\n const r = repos.get(fullName);\r\n const pr = r?.pulls.find((p) => p.number === number);\r\n if (!r || !pr) throw new Error('Unknown PR');\r\n if (headSha && pr.headSha !== headSha) throw new Error('Head branch was modified. Review and try the merge again.');\r\n mergedSinceSync.set(fullName, (mergedSinceSync.get(fullName) ?? 0) + 1);\r\n pr.state = 'MERGED';\r\n pr.mergedAt = now();\r\n r.issues = r.issues.filter((i) => !pr.closesIssues.includes(i.number));\r\n },\r\n updateBranch: async (fullName, number) => {\r\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\r\n if (!pr) throw new Error('Unknown PR');\r\n Object.assign(pr, { headSha: fakeSha(), mergeState: 'CLEAN' });\r\n runChecks(pr, false);\r\n },\r\n closePull: async (fullName, number) => {\r\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\r\n if (pr) pr.state = 'CLOSED';\r\n },\r\n prForBranch: async () => null,\r\n prDetails: async (fullName, number) => {\r\n const pr = repos.get(fullName)?.pulls.find((p) => p.number === number);\r\n if (!pr) throw new Error(`Unknown PR #${number}`);\r\n return {\r\n number,\r\n title: pr.title,\r\n body: `Implements the change.\\n\\nCloses #${pr.closesIssues[0] ?? '?'}`,\r\n url: pr.url,\r\n headRefName: pr.headRefName,\r\n headSha: pr.headSha,\r\n isCrossRepository: false,\r\n closesIssues: pr.closesIssues,\r\n state: pr.state,\r\n mergeable: pr.mergeable,\r\n mergeState: pr.mergeState,\r\n };\r\n },\r\n issueDetails: async (fullName, number) => {\r\n const i = repos.get(fullName)?.issues.find((x) => x.number === number);\r\n return { title: i?.title ?? `Issue #${number}`, body: i?.body ?? '' };\r\n },\r\n commentPull: async (fullName, number) => `https://github.com/${fullName}/pull/${number}#issuecomment-${Date.now()}`,\r\n uploadEvidence: async (fullName, filePath) => `https://github.com/${fullName}/raw/swarm-qa-evidence/${filePath}`,\r\n ensureClone: async () => new Promise((r) => setTimeout(r, 400)),\r\n syncMain: async (fullName, _branch, { touch }) => {\r\n const behind = mergedSinceSync.get(fullName) ?? 0;\r\n if (behind === 0) return 'in sync';\r\n if (!touch) return `update ready (${behind} commit${behind === 1 ? '' : 's'})`;\r\n mergedSinceSync.set(fullName, 0);\r\n return `updated to ${fakeSha().slice(0, 7)}`;\r\n },\r\n mainDir: (fullName) => `/demo/${fullName}/main`,\r\n deskDir: (fullName, slug) => `/demo/${fullName}/desks/${slug}`,\r\n prepareDesk: async (fullName, _base, slug) => {\r\n await new Promise((r) => setTimeout(r, 900));\r\n const dir = `/demo/${fullName}/desks/${slug}`;\r\n deskRepo.set(dir, fullName);\r\n return dir;\r\n },\r\n removeDesk: async () => undefined,\r\n releaseDesk: async () => undefined,\r\n startSession: (opts, cb) => (opts.role === 'ceo' ? ceoSession(opts, cb) : fakeSession(opts, cb, deskRepo.get(opts.cwd) ?? [...repos.keys()][0])),\r\n previews: demoPreviews,\r\n };\r\n}\r\n\r\n// ---------- the demo preview ----------\r\n\r\nfunction placeholderPage(title: string, hue: number) {\r\n const safe = title.replace(/[<>&\"]/g, '');\r\n return `<!doctype html>\r\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:,\">\r\n<style>\r\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; }\r\n main { text-align: center; padding: 32px 40px; background: #fff; border-radius: 18px; box-shadow: 0 8px 30px hsla(${hue},50%,40%,.18); }\r\n h1 { margin: 0 0 6px; font-size: 26px; color: hsl(${hue},60%,38%); }\r\n p { margin: 0 0 22px; color: #666; }\r\n button { font: inherit; font-size: 18px; padding: 10px 26px; border: 0; border-radius: 999px; background: hsl(${hue},70%,55%); color: #fff; cursor: pointer; }\r\n button:active { transform: scale(.97); }\r\n #count { display: block; margin-top: 16px; font-size: 15px; color: #444; }\r\n</style></head>\r\n<body><main>\r\n <h1>${safe}</h1>\r\n <p>A placeholder app served by the demo office.</p>\r\n <button id=\"btn\" type=\"button\">Click me</button>\r\n <span id=\"count\">Clicked 0 times</span>\r\n</main>\r\n<script>\r\n let n = 0;\r\n document.getElementById('btn').addEventListener('click', () => {\r\n n++;\r\n document.getElementById('count').textContent = 'Clicked ' + n + (n === 1 ? ' time' : ' times');\r\n });\r\n</script>\r\n</body></html>`;\r\n}\r\n\r\n/** Programs the demo pretends to have, so a bogus preview command fails the way it would for real. */\r\nconst DEMO_PROGRAMS = ['npm', 'npx', 'node', 'pnpm', 'yarn', 'bun', 'deno', 'vite', 'next', 'python', 'python3', 'py', 'php', 'ruby', 'go', 'cargo', 'dotnet'];\r\n\r\n/**\r\n * No git, no npm: short fake delays through the real statuses, then a placeholder page on the floor's port.\r\n * Floors made in the demo have nothing to run until they get a command, and a command whose program isn't in\r\n * DEMO_PROGRAMS fails, so the viewer's unconfigured and error states can be tried out.\r\n */\r\nconst demoPreviews: PreviewBackend = {\r\n hasDefault: async (fullName) => !bareRepos.has(fullName),\r\n start(job, cb) {\r\n let stopped = false;\r\n let server: http.Server | null = null;\r\n const timers: NodeJS.Timeout[] = [];\r\n const later = (ms: number, fn: () => void) => timers.push(setTimeout(() => !stopped && fn(), ms));\r\n const hue = [...job.fullName].reduce((h, c) => (h * 31 + c.charCodeAt(0)) % 360, 7);\r\n const sha = (job.pr ? repos.get(job.fullName)?.pulls.find((p) => p.number === job.pr)?.headRefName ?? String(job.pr) : job.fullName + job.defaultBranch)\r\n .split('')\r\n .reduce((h, c) => (h * 33 + c.charCodeAt(0)) >>> 0, 5381)\r\n .toString(16)\r\n .padStart(7, '0')\r\n .slice(0, 7);\r\n\r\n cb.status('preparing');\r\n later(700, () => {\r\n cb.commit(sha);\r\n cb.log([`HEAD is now at ${sha} (${job.pr ? `PR #${job.pr}` : job.defaultBranch})`]);\r\n if (!job.command && bareRepos.has(job.fullName)) {\r\n stopped = true;\r\n cb.failed('Nothing to run: this floor has no preview command and no package.json.', true);\r\n return;\r\n }\r\n cb.status('installing');\r\n cb.log(['$ npm ci', 'added 214 packages in 1s (demo)']);\r\n });\r\n later(1600, () => {\r\n cb.status('starting');\r\n cb.log([`$ ${job.command ?? 'npm run dev'}`.replaceAll('{port}', String(job.port))]);\r\n const program = job.command?.trim().split(/\\s+/)[0] ?? 'npm';\r\n if (!DEMO_PROGRAMS.includes(program.toLowerCase())) {\r\n later(400, () => {\r\n cb.log([`'${program}' is not recognized as an internal or external command,`, 'operable program or batch file.']);\r\n stopped = true;\r\n cb.failed(`The app exited (code 1) before it listened on port ${job.port}.`);\r\n });\r\n return;\r\n }\r\n server = http.createServer((req, res) => {\r\n if (req.url !== '/' && !req.url?.startsWith('/?')) return void res.writeHead(404).end('Not found');\r\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });\r\n res.end(placeholderPage(job.title, hue));\r\n });\r\n server.once('error', (err) => {\r\n if (stopped) return;\r\n stopped = true;\r\n cb.failed(`Could not listen on port ${job.port}: ${err.message}`);\r\n });\r\n server.listen(job.port, '127.0.0.1', () => {\r\n if (stopped) return void server?.close();\r\n later(500, () => {\r\n cb.log([` \u279C Local: http://localhost:${job.port}/`]);\r\n cb.status('running');\r\n });\r\n });\r\n });\r\n\r\n return {\r\n async stop() {\r\n stopped = true;\r\n timers.forEach(clearTimeout);\r\n const s = server;\r\n server = null;\r\n if (!s?.listening) return;\r\n s.closeAllConnections();\r\n await new Promise<void>((resolve) => s.close(() => resolve()));\r\n },\r\n };\r\n },\r\n};\r\n\r\n// ---------- the demo CEO ----------\r\n\r\ninterface Profile {\r\n summary: string;\r\n qa: string;\r\n qaTitle: string;\r\n qaJob: string;\r\n devTitle: string;\r\n devSpecialty: string;\r\n devJob: string;\r\n hires: { title: string; specialty: string; job_description: string; reason: string }[];\r\n}\r\n\r\nconst PROFILES: Record<string, Profile> = {\r\n 'pixel-todo': {\r\n summary: 'Todo web app \u00B7 React + Vite + TypeScript',\r\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',\r\n qaTitle: 'UI QA tester',\r\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.',\r\n devTitle: 'React UI engineer',\r\n devSpecialty: 'frontend',\r\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.',\r\n hires: [\r\n {\r\n title: 'Accessibility engineer',\r\n specialty: 'a11y',\r\n job_description:\r\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.',\r\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.',\r\n },\r\n ],\r\n },\r\n 'weather-api': {\r\n summary: 'REST API \u00B7 Node + Express',\r\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',\r\n qaTitle: 'API QA tester',\r\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.',\r\n devTitle: 'Backend engineer',\r\n devSpecialty: 'backend',\r\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.',\r\n hires: [\r\n {\r\n title: 'API reliability engineer',\r\n specialty: 'reliability',\r\n job_description: 'You own rate limiting, caching and error handling. Measure before you optimise and document every limit in the OpenAPI spec.',\r\n reason: 'Rate limiting is in the backlog and the forecast endpoint will call an upstream service that needs caching and timeouts.',\r\n },\r\n ],\r\n },\r\n};\r\n\r\nconst GENERIC: Profile = {\r\n summary: 'Web project \u00B7 early stage',\r\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',\r\n qaTitle: 'QA tester',\r\n qaJob: 'You check every PR end to end in the browser, at desktop and phone widths.',\r\n devTitle: 'Full-stack engineer',\r\n devSpecialty: 'fullstack',\r\n devJob: 'You build features end to end, from the UI down to the data.',\r\n hires: [\r\n {\r\n title: 'Frontend engineer',\r\n specialty: 'frontend',\r\n job_description: 'You own the UI:\\n\\n1. Layout and components\\n2. Styling, checked at **desktop and phone** widths',\r\n reason: 'The project needs someone who owns the UI from the start.',\r\n },\r\n ],\r\n};\r\n\r\ninterface DemoFloor {\r\n floor: number;\r\n repo: string;\r\n brief: string | null;\r\n team: { id: string; name: string; role: string; specialty: string | null; status: string }[];\r\n backlog: unknown[];\r\n pullRequests: unknown[];\r\n}\r\n\r\n/** A scripted CEO that uses the real office tools, so proposals, profiles and issues behave exactly as in the real thing. */\r\nfunction ceoSession(opts: SessionOptions, cb: SessionCallbacks): SessionHandle {\r\n const office = opts.office!;\r\n const timers: NodeJS.Timeout[] = [];\r\n let stopped = false;\r\n let done = false;\r\n const wait = (ms: number) => new Promise<void>((resolve) => timers.push(setTimeout(resolve, ms)));\r\n const step = async (entries: LogEntry[], ms = 900 + Math.random() * 1500) => {\r\n if (stopped) throw new Error('Stopped by manager');\r\n cb.tool(entries.find((e) => e.tool)?.tool ?? null);\r\n cb.log(entries);\r\n await wait(ms);\r\n };\r\n const status = async () => {\r\n await step([{ kind: 'tool', tool: 'mcp__office__company_status', text: `\u23FA ${describeOfficeTool('company_status', {})}` }]);\r\n const s = JSON.parse(await office.call('company_status', {})) as { floors: DemoFloor[]; pendingProposals: unknown[] };\r\n const people = s.floors.reduce((n, f) => n + f.team.length, 0);\r\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\r\n cb.log([{ kind: 'result', text: ` \u23BF ${s.floors.length} floors \u00B7 ${people} people \u00B7 ${issues} open issues \u00B7 ${s.pendingProposals.length} proposals pending` }]);\r\n return s;\r\n };\r\n const use = async (name: string, args: Record<string, unknown>) => {\r\n await step([{ kind: 'tool', tool: `mcp__office__${name}`, text: `\u23FA ${describeOfficeTool(name, args)}` }]);\r\n const out = await office.call(name, args);\r\n cb.log([{ kind: out.startsWith('Refused') ? 'error' : 'result', text: ` \u23BF ${out.split('\\n')[0].slice(0, 170)}` }]);\r\n return out;\r\n };\r\n const read = (file: string, lines: number) => step([{ kind: 'tool', tool: 'Read', text: `\u23FA Read ${file}` }, { kind: 'result', text: ` \u23BF Read ${lines} lines` }]);\r\n const think = (text: string) => step([{ kind: 'thinking', text: '\u273B Thinking\u2026' }, { kind: 'text', text: `\u25CF ${text}` }], 1800);\r\n const short = (s: string, n = 48) => (s.length > n ? `${s.slice(0, n - 1).trim()}\u2026` : s);\r\n\r\n const planIssues = async (floor: number, mission: string, team: DemoFloor['team']) => {\r\n const first = await use('file_issue', {\r\n floor,\r\n title: 'Set up the project skeleton',\r\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`,\r\n specialty: 'frontend',\r\n });\r\n const n = Number(first.match(/#(\\d+)/)?.[1] ?? 0);\r\n await use('file_issue', {\r\n floor,\r\n title: `Build the core: ${short(mission, 60)}`,\r\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`,\r\n specialty: 'frontend',\r\n });\r\n await use('file_issue', {\r\n floor,\r\n title: 'Polish: phone layout and empty states',\r\n body: `${n ? `Depends on #${n}\\n\\n` : ''}Make every screen work at 375px and add friendly empty states.`,\r\n specialty: 'frontend',\r\n });\r\n if (!team.some((a) => a.specialty === 'frontend')) {\r\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.' });\r\n }\r\n return n;\r\n };\r\n\r\n const scripts = {\r\n async onboard(floor: number, fullName: string) {\r\n const s = await status();\r\n const f = s.floors.find((x) => x.floor === floor);\r\n if (!f) return 'That floor has gone, so there was nothing to onboard.';\r\n const p = PROFILES[fullName.split('/')[1] ?? ''] ?? GENERIC;\r\n await read(`${f.repo}/README.md`, 48);\r\n await step([{ kind: 'tool', tool: 'Glob', text: '\u23FA Glob src/**/*' }, { kind: 'result', text: ' \u23BF Found 23 files' }]);\r\n await read('package.json', 36);\r\n await think(`${p.summary}. Let me shape the team around that.`);\r\n await use('set_floor_profile', { floor, summary: p.summary, qa_brief: p.qa });\r\n const qa = f.team.find((a) => a.role === 'qa');\r\n if (qa) {\r\n await step([{ kind: 'tool', tool: 'mcp__office__agent_detail', text: `\u23FA ${describeOfficeTool('agent_detail', { agent_id: qa.id })}` }]);\r\n const d = JSON.parse(await office.call('agent_detail', { agent_id: qa.id })) as { title: string; jobDescription: string | null };\r\n cb.log([{ kind: 'result', text: ` \u23BF ${d.title} \u00B7 job description ${d.jobDescription?.length ?? 0} chars` }]);\r\n await use('update_job', { agent_id: qa.id, title: p.qaTitle, job_description: p.qaJob });\r\n }\r\n const dev = f.team.find((a) => a.role === 'dev' && !a.specialty);\r\n if (dev) await use('update_job', { agent_id: dev.id, title: p.devTitle, specialty: p.devSpecialty, job_description: p.devJob });\r\n const proposed: string[] = [];\r\n for (const h of p.hires) if (!(await use('propose_hire', { floor, role: 'dev', ...h })).startsWith('Refused')) proposed.push(h.title);\r\n let planned = '';\r\n if (f.brief && f.backlog.length === 0) {\r\n const n = await planIssues(floor, f.brief, f.team);\r\n planned = ` I also turned your brief into three issues; #${n} sets up the skeleton and the other two wait for it.`;\r\n }\r\n return [\r\n `Floor ${floor}: ${p.summary}.`,\r\n `I wrote a QA brief for it${qa ? `, made ${qa.name} our ${p.qaTitle}` : ''}${dev ? ` and ${dev.name} our ${p.devTitle}` : ''}.`,\r\n proposed.length ? `I've proposed hiring: ${proposed.join(', ')}. The resume${proposed.length === 1 ? ' is' : 's are'} waiting on your phone.` : '',\r\n planned,\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n },\r\n async plan(floor: number, mission: string) {\r\n const s = await status();\r\n const f = s.floors.find((x) => x.floor === floor);\r\n if (!f) return 'That floor has gone, so there was nothing to plan.';\r\n await read(`${f.repo}/README.md`, 12);\r\n await think(\"Foundation first, so the parallel work doesn't collide.\");\r\n const n = await planIssues(floor, mission, f.team);\r\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.`;\r\n },\r\n async review() {\r\n const s = await status();\r\n await think('Checking each floor for idle people and stuck work.');\r\n for (const f of s.floors) {\r\n const idle = f.team.filter((a) => a.role === 'dev' && !a.specialty && (a.status === 'idle' || a.status === 'done'));\r\n const devs = f.team.filter((a) => a.role === 'dev').length;\r\n if (devs >= 6 && idle.length >= 2 && f.backlog.length < devs) {\r\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.` });\r\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.`;\r\n }\r\n }\r\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\r\n const prs = s.floors.reduce((n, f) => n + f.pullRequests.length, 0);\r\n return `All ${s.floors.length} floors look healthy: ${issues} open issues and ${prs} pull requests in flight. No changes needed.`;\r\n },\r\n async chat(text: string) {\r\n const s = await status();\r\n await think('Reading your message.');\r\n const people = s.floors.reduce((n, f) => n + f.team.length, 0);\r\n const issues = s.floors.reduce((n, f) => n + f.backlog.length, 0);\r\n const pending = s.pendingProposals.length;\r\n // Real CEOs answer in Markdown, so the demo one does too: every element the phone renders.\r\n const rows = s.floors.map((f) => `| ${f.floor} | \\`${f.repo.split('/').pop()}\\` | ${f.team.length} | ${f.backlog.length} | ${f.pullRequests.length} |`);\r\n return [\r\n `**Quick status:** ${s.floors.length} floor${s.floors.length === 1 ? '' : 's'}, ${people} people and ${issues} open issues.`,\r\n '',\r\n '- The team is *heads down* on the backlog',\r\n `- ${pending ? `**${pending}** proposal${pending === 1 ? ' is' : 's are'} waiting for you in Hires` : 'No hiring decisions waiting on you'}`,\r\n ' - QA re-tests every PR after a fix',\r\n '',\r\n '| Floor | Repo | People | Issues | PRs |',\r\n '| ---: | --- | ---: | ---: | ---: |',\r\n ...(rows.length ? rows : ['| \u2013 | no projects yet | 0 | 0 | 0 |']),\r\n '',\r\n 'What I would do next:',\r\n '',\r\n '1. Merge anything that passed QA',\r\n '2. Run `npm run build` on each floor before the next milestone',\r\n '3. Hire only where the backlog is piling up',\r\n '',\r\n '```bash',\r\n 'SWARM_HOME=/tmp/cubefarm-demo SWARM_PORT=5260 node --import tsx server/index.ts --demo',\r\n '```',\r\n '',\r\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).`,\r\n ].join('\\n');\r\n },\r\n };\r\n\r\n const prompt = opts.prompt;\r\n const where = prompt.match(/[Ff]loor (\\d+) \\(([^,)]+)/);\r\n const run = /just joined the company/.test(prompt)\r\n ? () => scripts.onboard(Number(where?.[1]), where?.[2] ?? '')\r\n : /has a brief for floor/.test(prompt)\r\n ? () => scripts.plan(Number(where?.[1]), prompt.match(/\"\"\"([\\s\\S]*?)\"\"\"/)?.[1]?.trim() ?? '')\r\n : /Periodic review/.test(prompt)\r\n ? () => scripts.review()\r\n : () => scripts.chat(prompt.split('\\n').slice(1).join(' ').trim() || prompt);\r\n\r\n const finish = (ok: boolean, text: string, error?: string) => {\r\n if (done) return;\r\n done = true;\r\n cb.tool(null);\r\n cb.finished({ ok, text, costUsd: ok ? 0.4 + Math.random() : 0.05, turns: 6 + Math.floor(Math.random() * 10), errors: error ? [error] : [] });\r\n };\r\n\r\n timers.push(\r\n setTimeout(async () => {\r\n try {\r\n cb.log([{ kind: 'system', text: `\u273B Claude Code (demo) \u00B7 ${opts.model} \u00B7 ${opts.effort} effort \u00B7 CEO` }]);\r\n const reply = await run();\r\n cb.log([{ kind: 'text', text: `\u25CF ${reply}` }]);\r\n cb.turn?.(reply);\r\n finish(true, reply);\r\n } catch (err) {\r\n finish(false, '', stopped ? 'Stopped by manager' : (err as Error).message);\r\n }\r\n }, 500),\r\n );\r\n\r\n return {\r\n send(text) {\r\n timers.push(\r\n setTimeout(() => {\r\n if (stopped || done) return;\r\n const said = text.split('\\n').slice(1).join(' ').trim() || text;\r\n cb.log([{ kind: 'text', text: `\u25CF Noted: \"${short(said, 70)}\"` }]);\r\n cb.turn?.(`Noted, I'll factor that in: \"${short(said, 90)}\"`);\r\n }, 1500),\r\n );\r\n },\r\n stop() {\r\n stopped = true;\r\n timers.forEach(clearTimeout);\r\n finish(false, '', 'Stopped by manager');\r\n },\r\n };\r\n}\r\n", "import fs from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport crypto from 'node:crypto';\r\nimport type { WebSocket } from 'ws';\r\nimport type { Backend } from './backend.ts';\r\nimport type { LogEntry, SessionHandle, SessionResult } from './agentRunner.ts';\r\nimport type { PrDetails } from './github.ts';\r\nimport { defaultProjectsDir, HOME_DIR, LOG_BUFFER, SCHEDULER_INTERVAL_MS, STATE_FILE, SYNC_INTERVAL_MS, WORKSPACE_ROOT } from './config.ts';\r\nimport { ceoJobPrompt, ceoSystemPrompt, createOfficeTools, jobLabel, specialtyLabel, specialtySlug, type CeoJob, type OfficeTools } from './ceo.ts';\r\nimport { HttpError } from './httpError.ts';\r\nimport { DEFAULT_PREVIEW, Previews, parsePreviewPatch } from './previews.ts';\r\nimport { blockers, holdUps, issueSpecialty } from '../shared/issues.ts';\r\nimport { CEO_ID } from '../shared/types.ts';\r\nimport type {\r\n AgentLook,\r\n AgentRole,\r\n AgentStatus,\r\n AgentTask,\r\n AgentView,\r\n CeoInfo,\r\n EffortLevel,\r\n HireRequestView,\r\n IssueInfo,\r\n LogLine,\r\n PhoneMessage,\r\n PreviewConfig,\r\n PreviewView,\r\n ProjectFolderView,\r\n PullInfo,\r\n QaCheck,\r\n QaView,\r\n RepoView,\r\n ServerEvent,\r\n SwarmSettings,\r\n WorldSnapshot,\r\n} from '../shared/types.ts';\r\n\r\n// ---------- persisted shape ----------\r\n\r\ninterface PersistedRepo {\r\n id: string;\r\n fullName: string;\r\n description: string;\r\n url: string;\r\n defaultBranch: string;\r\n floor: number;\r\n color: string;\r\n autoAssign: boolean;\r\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\r\n browserTesting: boolean;\r\n links: string[]; // other connected repos this floor's agents may read\r\n localPath: string | null; // the manager's own project folder (null: a clone under WORKSPACE_ROOT)\r\n mission: string;\r\n summary: string;\r\n qaBrief: string;\r\n preview: PreviewConfig; // how the floor's app runs for the preview monitor\r\n addedAt: number;\r\n}\r\n\r\ninterface PersistedAgent {\r\n id: string;\r\n name: string;\r\n repoId: string; // '' for the CEO, who works in the lobby\r\n role: AgentRole;\r\n title: string;\r\n specialty: string;\r\n brief: string;\r\n hiredBy: 'manager' | 'ceo';\r\n look: AgentLook;\r\n task: AgentTask | null;\r\n desk: number;\r\n color: string;\r\n hair: string;\r\n skin: string;\r\n model: string;\r\n effort: EffortLevel | '';\r\n status: AgentStatus;\r\n issueNumber: number | null;\r\n issueTitle: string | null;\r\n branch: string | null;\r\n prNumber: number | null;\r\n prUrl: string | null;\r\n startedAt: number | null;\r\n endedAt: number | null;\r\n costUsd: number;\r\n turns: number;\r\n sessionId: string | null;\r\n lastError: string | null;\r\n logTail: LogLine[];\r\n}\r\n\r\n/** A pull request's trip through QA. */\r\ninterface QaRecord extends QaView {\r\n issueNumber: number | null;\r\n devSessionId: string | null; // the dev's Claude Code session, resumed to fix QA findings\r\n fixInstructions: string | null;\r\n sessionFailures: number;\r\n testedSha: string | null; // the head commit QA is testing\r\n passedSha: string | null; // the head commit QA signed off on: auto-merge merges exactly that\r\n fixReason: 'qa' | 'checks' | 'conflict' | null; // why it was last sent back to a developer\r\n mergeFixes: number; // times it went back for failing checks or conflicts\r\n retests: number; // QA rounds caused by merge fixes or new commits rather than by QA failing it\r\n pendingSince: number | null; // when auto-merge started waiting on its checks\r\n mergeRetryAt: number | null; // GitHub refused the merge: try again after this\r\n alerted: boolean; // the manager has been told it's stuck\r\n}\r\n\r\n/** Choices made when a project moves into the office. */\r\ninterface FloorOptions {\r\n mission?: string; // brief for the CEO to plan from\r\n autoAssign?: boolean; // free developers pick up backlog issues as soon as they're filed\r\n}\r\n\r\ninterface CeoState {\r\n queue: CeoJob[];\r\n job: CeoJob | null; // the job the CEO is on right now\r\n lastReviewAt: number | null;\r\n lastFingerprint: string | null; // company state at the last review; unchanged means the next review is skipped\r\n}\r\n\r\ninterface Persisted {\r\n settings: SwarmSettings;\r\n repos: PersistedRepo[];\r\n agents: PersistedAgent[];\r\n qa: QaRecord[];\r\n requests: HireRequestView[];\r\n ceo: CeoState;\r\n messages: PhoneMessage[];\r\n phoneReadAt: number;\r\n}\r\n\r\ninterface Shot {\r\n data: Buffer;\r\n mime: string;\r\n url: string | null;\r\n at: number;\r\n}\r\n\r\ninterface AgentRuntime {\r\n log: LogLine[];\r\n pending: LogLine[];\r\n session: SessionHandle | null;\r\n currentTool: string | null;\r\n browserUrl: string | null;\r\n screenshot: { data: Buffer; mime: string; at: number } | null;\r\n shots: Shot[]; // every screenshot of the current session (QA evidence)\r\n}\r\n\r\ninterface RepoRuntime {\r\n issues: IssueInfo[];\r\n pulls: PullInfo[];\r\n lastSync: number | null;\r\n syncError?: string;\r\n syncing: boolean;\r\n cloneStatus: RepoView['cloneStatus'];\r\n cloneError?: string;\r\n fetchedAt?: number; // when the latest issues/PRs fetch started\r\n lastMergedAt: string | null; // newest merge seen: a newer one means the folder needs a sync\r\n folderSync: string | null;\r\n merging: boolean;\r\n}\r\n\r\ninterface QaReport {\r\n verdict: 'pass' | 'fail';\r\n summary: string;\r\n checks: QaCheck[];\r\n commands: { command: string; result: string }[];\r\n screenshots: string[];\r\n fixInstructions?: string;\r\n}\r\n\r\n// ---------- flavour ----------\r\n\r\nconst FLOOR_COLORS = ['#ff8a5b', '#4fb3e8', '#8fd14f', '#c77dff', '#ffc93c', '#ff6fb5', '#2ec4b6', '#f25f5c'];\r\nconst SHIRTS = ['#e63946', '#457b9d', '#2a9d8f', '#f4a261', '#9b5de5', '#f15bb5', '#00bbf9', '#06d6a0', '#ffbe0b', '#8338ec', '#fb5607', '#3a86ff'];\r\nconst HAIR = ['#2b2118', '#6b4226', '#c68642', '#f2d16b', '#d94f30', '#1c1c1c', '#8e8e8e', '#5b3cc4', '#e76f51'];\r\nconst SKIN = ['#ffdbac', '#f1c27d', '#e0ac69', '#c68642', '#8d5524', '#ffe0bd'];\r\nconst DEV_NAMES = [\r\n 'Ada', 'Linus', 'Grace', 'Alan', 'Margaret', 'Dennis', 'Barbara', 'Ken', 'Radia', 'Guido', 'Hedy', 'Tim', 'Katherine',\r\n 'Bjarne', 'Frances', 'Edsger', 'Anita', 'Donald', 'Sophie', 'Yukihiro', 'Jean', 'Niklaus', 'Karen', 'Brendan',\r\n];\r\nconst QA_NAMES = ['Sherlock', 'Marple', 'Poirot', 'Nancy', 'Columbo', 'Fletcher', 'Watson', 'Morse', 'Holmes', 'Maigret'];\r\n\r\n// Names that get the feminine character look: everyone in the name pools above, plus common first names\r\n// for agents the manager names themselves. The manager can always change an agent's look in the console.\r\nconst FEMININE_NAMES = new Set(\r\n (\r\n 'ada grace margaret barbara radia hedy katherine frances anita sophie jean karen marple nancy fletcher ' +\r\n 'alice amanda amelia amy ana anna anne aisha astrid ava bella beth carla caroline charlotte chloe claire clara ' +\r\n 'diana elena elizabeth ella ellie emily emma eva fatima fiona freya georgia hannah harper helen holly ingrid iris ' +\r\n 'isabella ivy jane jasmine jessica julia kate laura leah leila lena lily linda lisa lucy maria marie mary maya mei ' +\r\n 'mia mila monica naomi natalie nina nora olivia paula priya rachel rose ruby sandra sara sarah scarlett sofia ' +\r\n 'stella susan tess tessa tina vera victoria yuki zara zoe'\r\n ).split(' '),\r\n);\r\nconst lookFor = (name: string): AgentLook => (FEMININE_NAMES.has(name.trim().split(/\\s+/)[0].toLowerCase()) ? 'feminine' : 'masculine');\r\nconst LOOKS: AgentLook[] = ['feminine', 'masculine'];\r\nconst MAX_DESKS: Record<AgentRole, number> = { dev: 12, qa: 3, ceo: 1 };\r\nconst MAX_QA_ROUNDS = 3;\r\n// Every agent runs Claude Opus 5.5 at medium effort unless the manager overrides it.\r\nconst DEFAULT_MODEL = 'claude-opus-5-5';\r\nconst EFFORTS: EffortLevel[] = ['low', 'medium', 'high', 'xhigh', 'max'];\r\n// The CEO thinks harder than the staff: Opus 5.5 at xhigh effort unless the manager changes it.\r\nconst CEO_MODEL = 'claude-opus-5-5';\r\nconst CEO_EFFORT: EffortLevel = 'xhigh';\r\nconst CEO_NAME = 'Morgan';\r\n// The CEO's own folder: its notes about the company live here. Repos are read through their clones.\r\nconst CEO_DIR = path.join(HOME_DIR, 'ceo');\r\nconst DEFAULT_PROJECTS_DIR = defaultProjectsDir(path.resolve(import.meta.dirname, '..'));\r\nconst MAX_PENDING_REQUESTS = 8;\r\nconst MAX_ISSUES_PER_JOB = 12;\r\nconst KEEP_MESSAGES = 200;\r\nconst KEEP_DECIDED_REQUESTS = 40;\r\n\r\nconst pick = <T>(arr: T[]) => arr[Math.floor(Math.random() * arr.length)];\r\nconst slugify = (s: string) =>\r\n s\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, '-')\r\n .replace(/^-|-$/g, '')\r\n .slice(0, 40) || 'agent';\r\n\r\nconst BUSY: AgentStatus[] = ['preparing', 'working'];\r\nconst FREE: AgentStatus[] = ['idle', 'done'];\r\n// An agent whose session failed sits out this long before taking new work, so a broken setup can't burn through the queue.\r\nconst ERROR_COOLDOWN_MS = 2 * 60_000;\r\n// Auto-assign stops retrying an issue after this many failed sessions; the manager can still assign it by hand.\r\nconst MAX_ISSUE_FAILURES = 2;\r\n// How long the office waits after Claude's usage limit is hit when Claude doesn't say when it resets.\r\nconst LIMIT_PAUSE_MS = 15 * 60_000;\r\n// Auto-merge: fixes for failing checks or conflicts before a PR needs the manager, how long checks may run before\r\n// the manager hears about it, and how long to wait before retrying a merge GitHub refused.\r\nconst MAX_MERGE_FIXES = 3;\r\nconst CHECKS_ALERT_MS = 30 * 60_000;\r\nconst MERGE_RETRY_MS = 10 * 60_000;\r\n// The running office's own folder: syncing it would restart the server mid-work, so it's only reported.\r\nconst OFFICE_DIR = path.resolve(import.meta.dirname, '..');\r\nconst isSamePath = (a: string, b: string) => (process.platform === 'win32' ? path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase() : path.resolve(a) === path.resolve(b));\r\nconst oneLine = (err: unknown) => (err instanceof Error ? err.message : String(err)).split(/\\r?\\n/)[0].slice(0, 200);\r\n\r\n// The latest browser screenshot per agent is kept on disk so monitors survive a server restart.\r\nconst SCREENS_DIR = path.join(HOME_DIR, 'screens');\r\nconst MIME_EXT: Record<string, string> = { 'image/png': 'png', 'image/jpeg': 'jpg', 'image/webp': 'webp', 'image/svg+xml': 'svg' };\r\nconst screenFile = (agentId: string, mime: string) => path.join(SCREENS_DIR, `${agentId}.${MIME_EXT[mime] ?? 'img'}`);\r\n\r\nasync function loadScreen(agentId: string): Promise<{ data: Buffer; mime: string; at: number } | null> {\r\n for (const [mime, ext] of Object.entries(MIME_EXT)) {\r\n const file = path.join(SCREENS_DIR, `${agentId}.${ext}`);\r\n try {\r\n const [data, stat] = await Promise.all([fs.readFile(file), fs.stat(file)]);\r\n return { data, mime, at: stat.mtimeMs };\r\n } catch {\r\n // try the next extension\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nasync function removeScreens(agentId: string) {\r\n await Promise.all(Object.values(MIME_EXT).map((ext) => fs.rm(path.join(SCREENS_DIR, `${agentId}.${ext}`), { force: true })));\r\n}\r\n\r\n// ---------- QA report ----------\r\n\r\nconst QA_SCHEMA: Record<string, unknown> = {\r\n type: 'object',\r\n additionalProperties: false,\r\n required: ['verdict', 'summary', 'checks', 'commands', 'screenshots'],\r\n properties: {\r\n verdict: { type: 'string', enum: ['pass', 'fail'], description: 'pass only if the change works and meets the issue requirements' },\r\n summary: { type: 'string', description: 'Two to four sentences for the pull request comment.' },\r\n checks: {\r\n type: 'array',\r\n description: 'Each acceptance criterion, test run or scenario you verified.',\r\n items: {\r\n type: 'object',\r\n additionalProperties: false,\r\n required: ['name', 'result', 'details'],\r\n properties: {\r\n name: { type: 'string' },\r\n result: { type: 'string', enum: ['pass', 'fail', 'skip'] },\r\n details: { type: 'string', description: 'What you did and what you observed.' },\r\n },\r\n },\r\n },\r\n commands: {\r\n type: 'array',\r\n description: 'Test suites, linters, builds and other commands you ran.',\r\n items: {\r\n type: 'object',\r\n additionalProperties: false,\r\n required: ['command', 'result'],\r\n properties: { command: { type: 'string' }, result: { type: 'string', description: 'e.g. \"42 passed, 0 failed\"' } },\r\n },\r\n },\r\n screenshots: {\r\n type: 'array',\r\n description: 'One short caption per screenshot you took with browser_take_screenshot, in the order you took them.',\r\n items: { type: 'string' },\r\n },\r\n fixInstructions: { type: 'string', description: 'When the verdict is fail: precise, actionable instructions for the developer.' },\r\n },\r\n};\r\n\r\nfunction parseReport(result: SessionResult): QaReport | null {\r\n let raw: unknown = result.structured;\r\n if (!raw && result.text) {\r\n const json = result.text.match(/\\{[\\s\\S]*\\}/);\r\n if (json) {\r\n try {\r\n raw = JSON.parse(json[0]);\r\n } catch {\r\n raw = null;\r\n }\r\n }\r\n }\r\n if (!raw || typeof raw !== 'object') return null;\r\n const r = raw as Partial<QaReport>;\r\n if (r.verdict !== 'pass' && r.verdict !== 'fail') return null;\r\n return {\r\n verdict: r.verdict,\r\n summary: String(r.summary ?? ''),\r\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 ?? '') })) : [],\r\n commands: Array.isArray(r.commands) ? r.commands.map((c) => ({ command: String(c.command ?? ''), result: String(c.result ?? '') })) : [],\r\n screenshots: Array.isArray(r.screenshots) ? r.screenshots.map(String) : [],\r\n fixInstructions: r.fixInstructions ? String(r.fixInstructions) : undefined,\r\n };\r\n}\r\n\r\nconst cell = (s: string) => s.replace(/\\|/g, '\\\\|').replace(/\\r?\\n/g, '<br>');\r\nconst ICON = { pass: '\u2705', fail: '\u274C', skip: '\u23ED\uFE0F' } as const;\r\n\r\nexport { HttpError };\r\n\r\nexport class Swarm {\r\n private state: Persisted = {\r\n settings: {\r\n sessionLimit: 0,\r\n defaultModel: DEFAULT_MODEL,\r\n defaultEffort: 'medium',\r\n permissionMode: 'guarded',\r\n hiring: 'approve',\r\n teamCap: 6,\r\n ceoHeartbeatMin: 60,\r\n managerName: '',\r\n companyName: '',\r\n projectsDir: DEFAULT_PROJECTS_DIR,\r\n setupDone: false,\r\n tutorialStep: 0,\r\n },\r\n repos: [],\r\n agents: [],\r\n qa: [],\r\n requests: [],\r\n ceo: { queue: [], job: null, lastReviewAt: null, lastFingerprint: null },\r\n messages: [],\r\n phoneReadAt: 0,\r\n };\r\n /**\r\n * The CEO's office tools. Every session gets its own server: one can only be connected to one session at a time, so\r\n * a shared one left the next session connected but without any tools while an earlier session still held it.\r\n */\r\n private officeTools(): OfficeTools {\r\n return createOfficeTools({\r\n companyStatus: () => this.companyStatus(),\r\n agentDetail: (a) => this.agentDetail(a),\r\n setFloorProfile: (a) => this.setFloorProfile(a),\r\n updateJob: (a) => this.updateJob(a),\r\n proposeHire: (a) => this.proposeHire(a),\r\n proposeLetGo: (a) => this.proposeLetGo(a),\r\n fileIssue: (a) => this.fileIssue(a),\r\n });\r\n }\r\n private ceoIssues = { filed: 0, repos: new Set<string>() }; // issues filed during the current CEO job\r\n private messageSeq = 1;\r\n private agentRt = new Map<string, AgentRuntime>();\r\n private repoRt = new Map<string, RepoRuntime>();\r\n private clients = new Set<WebSocket>();\r\n private user: string | null = null;\r\n private ghError: string | undefined;\r\n private saveTimer: NodeJS.Timeout | null = null;\r\n private flushTimer: NodeJS.Timeout | null = null;\r\n private logSeq = 1;\r\n private previews: Previews;\r\n\r\n constructor(private backend: Backend) {\r\n this.previews = new Previews(backend, {\r\n emit: (id) => {\r\n const r = this.state.repos.find((x) => x.id === id);\r\n if (r && this.repoRt.has(id)) this.emitRepo(r);\r\n },\r\n pulls: (id) => this.repoRt.get(id)?.pulls ?? [],\r\n });\r\n }\r\n\r\n // ---------- lifecycle ----------\r\n\r\n async init() {\r\n try {\r\n const raw = await fs.readFile(STATE_FILE, 'utf8');\r\n const loaded = JSON.parse(raw) as Partial<Persisted>;\r\n this.state = {\r\n settings: { ...this.state.settings, ...loaded.settings },\r\n repos: (loaded.repos ?? []).map((r) => ({\r\n ...r,\r\n autoMerge: r.autoMerge ?? true,\r\n links: r.links ?? [],\r\n mission: r.mission ?? '',\r\n summary: r.summary ?? '',\r\n qaBrief: r.qaBrief ?? '',\r\n localPath: r.localPath ?? null,\r\n preview: { command: r.preview?.command ?? null, env: { ...r.preview?.env } },\r\n })),\r\n agents: (loaded.agents ?? []).map((a) => ({\r\n ...a,\r\n effort: a.effort ?? '',\r\n role: a.role ?? 'dev',\r\n title: a.title ?? '',\r\n specialty: a.specialty ?? '',\r\n brief: a.brief ?? '',\r\n hiredBy: a.hiredBy ?? 'manager',\r\n look: a.look ?? lookFor(a.name),\r\n task: a.task ?? (a.issueNumber ? 'issue' : null),\r\n })),\r\n qa: (loaded.qa ?? []).map((q) => ({\r\n ...q,\r\n testedSha: q.testedSha ?? null,\r\n passedSha: q.passedSha ?? null,\r\n fixReason: q.fixReason ?? null,\r\n mergeFixes: q.mergeFixes ?? 0,\r\n retests: q.retests ?? 0,\r\n pendingSince: q.pendingSince ?? null,\r\n mergeRetryAt: q.mergeRetryAt ?? null,\r\n alerted: q.alerted ?? false,\r\n mergeNote: null,\r\n })),\r\n requests: loaded.requests ?? [],\r\n ceo: { ...this.state.ceo, ...loaded.ceo },\r\n messages: loaded.messages ?? [],\r\n phoneReadAt: loaded.phoneReadAt ?? 0,\r\n };\r\n for (const m of this.state.messages) this.messageSeq = Math.max(this.messageSeq, m.id + 1);\r\n if (!this.state.settings.defaultModel) this.state.settings.defaultModel = DEFAULT_MODEL;\r\n if (!EFFORTS.includes(this.state.settings.defaultEffort)) this.state.settings.defaultEffort = 'medium';\r\n // \"Max concurrent sessions\" (default 4) became an optional session limit. The old default goes; a limit the manager chose stays.\r\n const old = this.state.settings as SwarmSettings & { maxConcurrent?: number };\r\n if (old.maxConcurrent !== undefined) {\r\n if (loaded.settings?.sessionLimit === undefined) old.sessionLimit = old.maxConcurrent === 4 ? 0 : old.maxConcurrent;\r\n delete old.maxConcurrent;\r\n }\r\n // Offices that were set up before the setup wizard existed skip it.\r\n if (loaded.settings && loaded.settings.setupDone === undefined && this.state.repos.length > 0) {\r\n Object.assign(this.state.settings, { setupDone: true, tutorialStep: -1 });\r\n }\r\n } catch {\r\n // first run\r\n }\r\n for (const r of this.state.repos) if (r.localPath) this.backend.setLocalPath(r.fullName, r.localPath);\r\n const interrupted: PersistedAgent[] = [];\r\n for (const a of this.state.agents) {\r\n const tail = a.logTail ?? [];\r\n for (const l of tail) this.logSeq = Math.max(this.logSeq, l.id + 1);\r\n this.agentRt.set(a.id, { log: tail, pending: [], session: null, currentTool: null, browserUrl: null, screenshot: await loadScreen(a.id), shots: [] });\r\n if (BUSY.includes(a.status)) {\r\n a.status = 'stopped';\r\n a.lastError = 'The swarm server restarted while this agent was working.';\r\n interrupted.push(a);\r\n }\r\n }\r\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 });\r\n\r\n try {\r\n this.user = await this.backend.user();\r\n } catch (err) {\r\n this.ghError = `GitHub CLI is not ready: ${(err as Error).message}. Run \"gh auth login\".`;\r\n console.warn(this.ghError);\r\n }\r\n\r\n if (this.backend.demo && this.state.repos.length === 0) {\r\n // The demo opens on a busy office; the tutorial still runs so it can be tried.\r\n Object.assign(this.state.settings, { setupDone: true, managerName: 'Demo Manager', companyName: 'Demo Co.' });\r\n for (const r of await this.backend.listMyRepos()) {\r\n const repo = await this.connectRepo(r.nameWithOwner);\r\n for (let i = 0; i < (repo.floor === 1 ? 5 : 3); i++) this.hireAgent(repo.id, {});\r\n this.updateRepo(repo.id, { autoAssign: true });\r\n }\r\n }\r\n for (const r of this.state.repos) this.ensureQaTester(r);\r\n this.ensureCeo(interrupted);\r\n\r\n for (const r of this.state.repos) void this.cloneRepo(r.id);\r\n await Promise.all(this.state.repos.map((r) => this.syncRepo(r.id)));\r\n // Nothing is running yet, so anything still alive in a desk (or a preview) is left over from before the restart.\r\n await Promise.all([\r\n ...this.state.agents.map((a) => {\r\n const repo = this.state.repos.find((r) => r.id === a.repoId);\r\n return repo ? this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined) : undefined;\r\n }),\r\n this.previews.clearOrphans(this.state.repos),\r\n ]);\r\n for (const r of this.state.repos) void this.previews.refreshDefault(r);\r\n this.recover(interrupted);\r\n setInterval(() => this.state.repos.forEach((r, i) => setTimeout(() => void this.syncRepo(r.id), i * 1500)), SYNC_INTERVAL_MS);\r\n setInterval(() => this.schedule(), SCHEDULER_INTERVAL_MS);\r\n this.save();\r\n setTimeout(() => this.schedule(), 1000);\r\n }\r\n\r\n /** Agents cut off by a server restart pick their Claude Code session back up (QA and demo agents start over). */\r\n private recover(agents: PersistedAgent[]) {\r\n for (const a of agents) {\r\n if (a.task === 'qa' || this.backend.demo || !a.sessionId || !a.branch) {\r\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Starting over from the queue.' }]);\r\n const rec = a.task === 'qa' ? this.state.qa.find((q) => q.qaAgentId === a.id && q.status === 'testing') : undefined;\r\n if (rec) this.setQa(rec, { status: 'queued' });\r\n const fix = a.task === 'fix' ? this.state.qa.find((q) => q.devAgentId === a.id && q.status === 'fixing') : undefined;\r\n if (fix) this.setQa(fix, { status: 'failed' });\r\n this.clearTask(a);\r\n continue;\r\n }\r\n if (this.slotsFull()) continue; // stays 'stopped'; the manager can resume it later\r\n void this.message(a.id, 'The office server restarted while you were working. Check the state of your worktree and continue where you left off.').catch((err) =>\r\n console.warn(`could not resume ${a.name}`, err),\r\n );\r\n }\r\n }\r\n\r\n // ---------- views ----------\r\n\r\n private repoView(r: PersistedRepo): RepoView {\r\n const rt = this.repoRt.get(r.id)!;\r\n return {\r\n id: r.id,\r\n fullName: r.fullName,\r\n description: r.description,\r\n url: r.url,\r\n defaultBranch: r.defaultBranch,\r\n floor: r.floor,\r\n color: r.color,\r\n autoAssign: r.autoAssign,\r\n autoMerge: r.autoMerge,\r\n folderSync: rt.folderSync,\r\n browserTesting: r.browserTesting,\r\n links: r.links,\r\n mission: r.mission,\r\n summary: r.summary,\r\n qaBrief: r.qaBrief,\r\n localPath: r.localPath,\r\n checkoutPath: this.backend.mainDir(r.fullName),\r\n cloneStatus: rt.cloneStatus,\r\n cloneError: rt.cloneError,\r\n issues: rt.issues,\r\n pulls: rt.pulls,\r\n lastSync: rt.lastSync,\r\n syncError: rt.syncError,\r\n previewConfig: r.preview,\r\n preview: this.previews.view(r),\r\n };\r\n }\r\n\r\n private agentView(a: PersistedAgent, withLog: boolean): AgentView {\r\n const rt = this.agentRt.get(a.id)!;\r\n return {\r\n id: a.id,\r\n name: a.name,\r\n repoId: a.repoId,\r\n role: a.role,\r\n title: a.title,\r\n specialty: a.specialty,\r\n brief: a.brief,\r\n hiredBy: a.hiredBy,\r\n look: a.look,\r\n task: a.task,\r\n desk: a.desk,\r\n color: a.color,\r\n hair: a.hair,\r\n skin: a.skin,\r\n model: a.model,\r\n effort: a.effort,\r\n status: a.status,\r\n issueNumber: a.issueNumber,\r\n issueTitle: a.issueTitle,\r\n branch: a.branch,\r\n prNumber: a.prNumber,\r\n prUrl: a.prUrl,\r\n currentTool: rt.currentTool,\r\n startedAt: a.startedAt,\r\n endedAt: a.endedAt,\r\n costUsd: a.costUsd,\r\n turns: a.turns,\r\n browserUrl: rt.browserUrl,\r\n hasScreenshot: !!rt.screenshot,\r\n screenshotAt: rt.screenshot?.at ?? null,\r\n lastError: a.lastError,\r\n log: withLog ? rt.log : [],\r\n };\r\n }\r\n\r\n private qaView(q: QaRecord): QaView {\r\n return {\r\n repoId: q.repoId,\r\n prNumber: q.prNumber,\r\n status: q.status,\r\n round: q.round,\r\n devAgentId: q.devAgentId,\r\n qaAgentId: q.qaAgentId,\r\n summary: q.summary,\r\n checks: q.checks,\r\n commentUrl: q.commentUrl,\r\n mergeNote: q.mergeNote,\r\n updatedAt: q.updatedAt,\r\n };\r\n }\r\n\r\n snapshot(): WorldSnapshot {\r\n return {\r\n user: this.user,\r\n ghReady: !this.ghError,\r\n ghError: this.ghError,\r\n demo: this.backend.demo,\r\n workspaceRoot: WORKSPACE_ROOT,\r\n settings: this.state.settings,\r\n repos: this.state.repos.map((r) => this.repoView(r)),\r\n agents: this.state.agents.map((a) => this.agentView(a, true)),\r\n qa: this.state.qa.map((q) => this.qaView(q)),\r\n requests: this.state.requests,\r\n ceo: this.ceoInfo(),\r\n messages: this.state.messages.slice(-100),\r\n phoneReadAt: this.state.phoneReadAt,\r\n };\r\n }\r\n\r\n screenshot(agentId: string) {\r\n return this.agentRt.get(agentId)?.screenshot ?? null;\r\n }\r\n\r\n // ---------- clients ----------\r\n\r\n addClient(ws: WebSocket) {\r\n this.clients.add(ws);\r\n ws.on('close', () => this.clients.delete(ws));\r\n this.send(ws, { type: 'snapshot', data: this.snapshot() });\r\n }\r\n\r\n private send(ws: WebSocket, ev: ServerEvent) {\r\n if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(ev));\r\n }\r\n\r\n private broadcast(ev: ServerEvent) {\r\n const msg = JSON.stringify(ev);\r\n for (const ws of this.clients) if (ws.readyState === ws.OPEN) ws.send(msg);\r\n }\r\n\r\n private toast(level: 'info' | 'success' | 'error', text: string) {\r\n this.broadcast({ type: 'toast', level, text });\r\n }\r\n\r\n private emitRepo(r: PersistedRepo) {\r\n this.broadcast({ type: 'repo', repo: this.repoView(r) });\r\n }\r\n\r\n private emitAgent(a: PersistedAgent) {\r\n // A session can finish after its agent was let go (their floor disconnected mid-task); they're gone, so say nothing.\r\n if (!this.agentRt.has(a.id)) return;\r\n const { log: _log, ...rest } = this.agentView(a, false);\r\n this.broadcast({ type: 'agent', agent: rest });\r\n }\r\n\r\n private setQa(rec: QaRecord, patch: Partial<QaRecord>) {\r\n Object.assign(rec, patch, { updatedAt: Date.now() });\r\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\r\n this.save();\r\n }\r\n\r\n private appendLog(a: PersistedAgent, entries: LogEntry[]) {\r\n const rt = this.agentRt.get(a.id);\r\n if (!rt) return;\r\n const t = Date.now();\r\n for (const e of entries) {\r\n const line: LogLine = { id: this.logSeq++, t, kind: e.kind, text: e.text, tool: e.tool };\r\n rt.log.push(line);\r\n rt.pending.push(line);\r\n }\r\n if (rt.log.length > LOG_BUFFER) rt.log.splice(0, rt.log.length - LOG_BUFFER);\r\n if (!this.flushTimer) this.flushTimer = setTimeout(() => this.flushLogs(), 120);\r\n }\r\n\r\n private flushLogs() {\r\n this.flushTimer = null;\r\n for (const [agentId, rt] of this.agentRt) {\r\n if (rt.pending.length === 0) continue;\r\n this.broadcast({ type: 'log', agentId, lines: rt.pending });\r\n rt.pending = [];\r\n }\r\n this.save();\r\n }\r\n\r\n // ---------- persistence ----------\r\n\r\n private save() {\r\n if (this.saveTimer) return;\r\n this.saveTimer = setTimeout(async () => {\r\n this.saveTimer = null;\r\n for (const a of this.state.agents) a.logTail = (this.agentRt.get(a.id)?.log ?? []).slice(-200);\r\n await fs.mkdir(path.dirname(STATE_FILE), { recursive: true });\r\n const tmp = `${STATE_FILE}.tmp`;\r\n await fs.writeFile(tmp, JSON.stringify(this.state, null, 2));\r\n await fs.rename(tmp, STATE_FILE);\r\n }, 1500);\r\n }\r\n\r\n // ---------- lookups ----------\r\n\r\n private repo(id: string) {\r\n const r = this.state.repos.find((x) => x.id === id);\r\n if (!r) throw new HttpError(404, `Repo ${id} is not connected`);\r\n return r;\r\n }\r\n\r\n private agent(id: string) {\r\n const a = this.state.agents.find((x) => x.id === id);\r\n if (!a) throw new HttpError(404, `No agent ${id}`);\r\n return a;\r\n }\r\n\r\n private running() {\r\n return this.state.agents.filter((a) => BUSY.includes(a.status)).length;\r\n }\r\n\r\n /** True when the manager has set a session limit and every slot is taken. */\r\n private slotsFull() {\r\n const limit = this.state.settings.sessionLimit;\r\n return limit > 0 && this.running() >= limit;\r\n }\r\n\r\n private agentSlug(a: PersistedAgent) {\r\n return `${slugify(a.name)}-${a.id.slice(0, 4)}`;\r\n }\r\n\r\n private clearTask(a: PersistedAgent) {\r\n Object.assign(a, { status: 'idle', task: null, issueNumber: null, issueTitle: null, branch: null, prNumber: null, prUrl: null, lastError: null });\r\n this.emitAgent(a);\r\n }\r\n\r\n // ---------- GitHub / repos ----------\r\n\r\n listGithubRepos(owner?: string) {\r\n return this.backend.listMyRepos(owner);\r\n }\r\n\r\n /**\r\n * Give a GitHub repo a floor. Its main checkout is one of your own folders: the one you picked, else the folder in\r\n * your projects folder that already has it as origin, else a fresh clone into your projects folder.\r\n */\r\n async connectRepo(fullName: string, opts: FloorOptions & { localPath?: string } = {}): Promise<RepoView> {\r\n const existing = this.state.repos.find((r) => r.id.toLowerCase() === fullName.toLowerCase());\r\n if (existing) throw new HttpError(409, `${fullName} is already floor ${existing.floor}`);\r\n const meta = await this.backend.repoMeta(fullName);\r\n const folder = opts.localPath ?? (await this.projectFolderFor(meta.nameWithOwner));\r\n const floor = this.state.repos.reduce((m, r) => Math.max(m, r.floor), 0) + 1;\r\n const repo: PersistedRepo = {\r\n id: meta.nameWithOwner,\r\n fullName: meta.nameWithOwner,\r\n description: meta.description,\r\n url: meta.url,\r\n defaultBranch: meta.defaultBranch,\r\n floor,\r\n color: FLOOR_COLORS[(floor - 1) % FLOOR_COLORS.length],\r\n autoAssign: !!opts.autoAssign,\r\n autoMerge: true,\r\n browserTesting: true,\r\n links: [],\r\n localPath: folder,\r\n mission: (opts.mission ?? '').trim().slice(0, 4000),\r\n summary: '',\r\n qaBrief: '',\r\n preview: { ...DEFAULT_PREVIEW, env: {} },\r\n addedAt: Date.now(),\r\n };\r\n this.backend.setLocalPath(repo.fullName, folder);\r\n this.state.repos.push(repo);\r\n this.repoRt.set(repo.id, { issues: [], pulls: [], lastSync: null, syncing: false, cloneStatus: 'pending', lastMergedAt: null, folderSync: null, merging: false });\r\n this.save();\r\n this.emitRepo(repo);\r\n this.toast('success', `${repo.fullName} moved into floor ${floor}`);\r\n this.ensureQaTester(repo);\r\n void this.cloneRepo(repo.id);\r\n void this.syncRepo(repo.id);\r\n // The CEO studies every new floor and proposes the team it needs.\r\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\r\n return this.repoView(repo);\r\n }\r\n\r\n /** Where a GitHub repo's checkout goes when you connect it without picking a folder. */\r\n private async projectFolderFor(fullName: string): Promise<string> {\r\n const root = this.state.settings.projectsDir;\r\n const folders = await this.backend.scanProjects(root).catch(() => []);\r\n const match = folders.find((f) => f.github?.toLowerCase() === fullName.toLowerCase());\r\n if (match) return match.path;\r\n const name = fullName.split('/')[1];\r\n const taken = folders.find((f) => f.name.toLowerCase() === name.toLowerCase());\r\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.`);\r\n return path.join(root, name); // cloned there when the floor opens\r\n }\r\n\r\n /** A brand-new project: a folder in your projects folder, pushed to a new GitHub repo. */\r\n async createRepo(name: string, opts: FloorOptions & { description?: string; visibility: 'private' | 'public'; owner?: string }) {\r\n if (!/^[A-Za-z0-9._-]+$/.test(name)) throw new HttpError(400, 'Project names may only contain letters, numbers, \".\", \"-\" and \"_\"');\r\n const created = await this.backend.createProject(this.state.settings.projectsDir, name, opts).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n return this.connectRepo(created.fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: created.path });\r\n }\r\n\r\n /** The folders in your projects folder (or another folder you point at), and which are floors already. */\r\n async listProjectFolders(dir?: string): Promise<{ root: string; folders: ProjectFolderView[] }> {\r\n const root = dir?.trim() ? path.resolve(dir.trim()) : this.state.settings.projectsDir;\r\n const folders = await this.backend.scanProjects(root).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n const same = (a: string, b: string) => path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase();\r\n const floorOf = (f: { path: string; github: string | null }) =>\r\n this.state.repos.find((r) => (r.localPath && same(r.localPath, f.path)) || (f.github && r.id.toLowerCase() === f.github.toLowerCase()))?.floor ?? null;\r\n return { root, folders: folders.map((f) => ({ name: f.name, path: f.path, git: f.git, github: f.github, floor: floorOf(f) })) };\r\n }\r\n\r\n /** Give one of your folders a floor. It must already be on GitHub; otherwise publish it first. */\r\n async connectFolder(dir: string, opts: FloorOptions = {}) {\r\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\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.`);\r\n return this.connectRepo(f.github, { ...opts, localPath: f.path });\r\n }\r\n\r\n /** Put one of your folders on GitHub (only what's committed goes up), then give it a floor. */\r\n async publishFolder(dir: string, opts: FloorOptions & { name?: string; visibility: 'private' | 'public'; description?: string }) {\r\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n const name = (opts.name?.trim() || f.name).replace(/[^A-Za-z0-9._-]+/g, '-');\r\n const fullName = await this.backend.publishFolder(f.path, { name, visibility: opts.visibility, description: opts.description }).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n return this.connectRepo(fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: f.path });\r\n }\r\n\r\n disconnectRepo(id: string) {\r\n const repo = this.repo(id);\r\n this.state.ceo.queue = this.state.ceo.queue.filter((j) => j.repoId !== id);\r\n for (const r of this.state.requests.filter((x) => x.repoId === id && x.status === 'pending')) {\r\n this.decide(r, { status: 'rejected', note: 'The floor was disconnected.', decidedBy: null });\r\n }\r\n for (const a of this.state.agents.filter((x) => x.repoId === id)) this.fireAgent(a.id, true);\r\n void this.previews.remove({ ...repo });\r\n this.state.repos = this.state.repos.filter((r) => r.id !== id);\r\n for (const q of this.state.qa.filter((x) => x.repoId === id)) this.broadcast({ type: 'qaRemoved', repoId: id, prNumber: q.prNumber });\r\n this.state.qa = this.state.qa.filter((q) => q.repoId !== id);\r\n for (const r of this.state.repos) r.links = r.links.filter((l) => l !== id);\r\n this.repoRt.delete(id);\r\n // Keep floors contiguous.\r\n this.state.repos.sort((a, b) => a.floor - b.floor).forEach((r, i) => (r.floor = i + 1));\r\n this.backend.setLocalPath(repo.fullName, null);\r\n this.save();\r\n this.broadcast({ type: 'repoRemoved', repoId: id });\r\n for (const r of this.state.repos) this.emitRepo(r);\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)`);\r\n }\r\n\r\n updateRepo(\r\n id: string,\r\n patch: Partial<Pick<PersistedRepo, 'autoAssign' | 'autoMerge' | 'browserTesting' | 'color' | 'links' | 'mission' | 'summary' | 'qaBrief'>> & { previewCommand?: unknown; previewEnv?: unknown },\r\n ) {\r\n const repo = this.repo(id);\r\n const preview = parsePreviewPatch(patch.previewCommand, patch.previewEnv);\r\n repo.preview = { ...repo.preview, ...preview };\r\n if (preview.command === null) void this.previews.refreshDefault(repo);\r\n if (patch.autoAssign !== undefined) repo.autoAssign = !!patch.autoAssign;\r\n if (patch.autoMerge !== undefined) {\r\n repo.autoMerge = !!patch.autoMerge;\r\n if (repo.autoMerge) void this.syncRepo(repo.id);\r\n }\r\n if (patch.browserTesting !== undefined) repo.browserTesting = !!patch.browserTesting;\r\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) repo.color = patch.color;\r\n if (Array.isArray(patch.links)) repo.links = patch.links.filter((l) => l !== id && this.state.repos.some((r) => r.id === l));\r\n if (typeof patch.mission === 'string') repo.mission = patch.mission.trim().slice(0, 4000);\r\n if (typeof patch.summary === 'string') repo.summary = patch.summary.trim().slice(0, 140);\r\n if (typeof patch.qaBrief === 'string') repo.qaBrief = patch.qaBrief.trim().slice(0, 2500);\r\n this.save();\r\n this.emitRepo(repo);\r\n setTimeout(() => this.schedule(), 200);\r\n return this.repoView(repo);\r\n }\r\n\r\n // ---------- auto-merge ----------\r\n\r\n /**\r\n * Auto-merge (floors with it on): a swarm PR merges itself once QA has signed off on its latest commit and GitHub's\r\n * checks are green. Failing checks and merge conflicts go back to a developer; new commits after QA's sign-off send\r\n * it back to QA. Merging deletes the remote branch, and the floor's folder then fast-forwards (syncRepo sees the merge).\r\n */\r\n private async advanceMerges(repo: PersistedRepo) {\r\n const rt = this.repoRt.get(repo.id);\r\n if (!rt || !repo.autoMerge || rt.merging) return;\r\n rt.merging = true;\r\n let merged = false;\r\n try {\r\n for (const rec of this.state.qa.filter((q) => q.repoId === repo.id && q.status === 'passed')) {\r\n const pr = rt.pulls.find((p) => p.number === rec.prNumber && p.state === 'OPEN');\r\n if (!pr || !pr.headRefName.startsWith('swarm/')) continue; // people's own PRs are theirs to merge\r\n // Only act on PR data fetched after the record last changed (a fix may have just pushed).\r\n if ((rt.fetchedAt ?? 0) < rec.updatedAt) continue;\r\n try {\r\n if (await this.advanceMerge(repo, rec, pr)) merged = true;\r\n } catch (err) {\r\n console.warn(`auto-merge of ${repo.fullName}#${pr.number} failed`, err);\r\n this.mergeNote(rec, `auto-merge hit a problem: ${oneLine(err)}`);\r\n }\r\n }\r\n } finally {\r\n rt.merging = false;\r\n }\r\n if (merged) {\r\n await this.syncRepo(repo.id);\r\n setTimeout(() => this.schedule(), 200);\r\n }\r\n }\r\n\r\n /** One step toward merging a QA-passed PR. Returns true when it merged. */\r\n private async advanceMerge(repo: PersistedRepo, rec: QaRecord, pr: PullInfo): Promise<boolean> {\r\n if (pr.isDraft) return this.mergeNote(rec, 'a draft: waiting');\r\n if (pr.mergeable === 'UNKNOWN' || pr.mergeState === 'UNKNOWN') {\r\n // GitHub works mergeability out lazily and lists often say UNKNOWN; asking about the PR itself gets an answer.\r\n const d = await this.backend.prDetails(repo.fullName, pr.number);\r\n pr = { ...pr, headSha: d.headSha, mergeable: d.mergeable, mergeState: d.mergeState };\r\n }\r\n rec.passedSha ??= pr.headSha; // signed off before the office tracked commits\r\n if (pr.headSha !== rec.passedSha) {\r\n // Commits arrived after QA's sign-off: they get tested too.\r\n this.setQa(rec, { status: 'queued', round: rec.round + 1, retests: rec.retests + 1, mergeNote: null, pendingSince: null });\r\n setTimeout(() => this.schedule(), 200);\r\n return false;\r\n }\r\n if (pr.mergeable === 'CONFLICTING' || pr.mergeState === 'DIRTY') {\r\n return this.sendBack(repo, rec, 'conflict', `It conflicts with ${repo.defaultBranch}.`);\r\n }\r\n if (pr.checks === 'failing') {\r\n return this.sendBack(repo, rec, 'checks', pr.failedChecks.map((c) => `- ${c.name}${c.url ? `: ${c.url}` : ''}`).join('\\n'));\r\n }\r\n if (pr.checks === 'pending') {\r\n rec.pendingSince ??= Date.now();\r\n if (Date.now() - rec.pendingSince > CHECKS_ALERT_MS && !rec.alerted) {\r\n rec.alerted = true;\r\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.`);\r\n }\r\n return this.mergeNote(rec, `waiting for checks: ${pr.pendingChecks.join(', ') || 'running'}`);\r\n }\r\n rec.pendingSince = null;\r\n if (pr.mergeable === 'UNKNOWN') return this.mergeNote(rec, 'GitHub is checking it can merge');\r\n if (pr.mergeState === 'BEHIND') {\r\n // The repo only merges up-to-date branches. GitHub merges the base in cleanly (or refuses); CI checks the result.\r\n this.mergeNote(rec, `updating the branch with ${repo.defaultBranch}`);\r\n await this.backend.updateBranch(repo.fullName, pr.number);\r\n const details = await this.backend.prDetails(repo.fullName, pr.number);\r\n this.setQa(rec, { passedSha: details.headSha });\r\n return false;\r\n }\r\n if (rec.mergeRetryAt && Date.now() < rec.mergeRetryAt) return false;\r\n this.mergeNote(rec, 'merging\u2026');\r\n let error = '';\r\n for (const method of ['squash', 'merge', 'rebase'] as const) {\r\n try {\r\n await this.backend.mergePull(repo.fullName, pr.number, method, rec.passedSha);\r\n error = '';\r\n break;\r\n } catch (err) {\r\n error = oneLine(err).replace(/^gh .*? failed: /, '');\r\n if (!/not allowed/i.test(error)) break; // only a merge method the repo turned off is worth another try\r\n }\r\n }\r\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\r\n if (error) {\r\n rec.mergeRetryAt = Date.now() + MERGE_RETRY_MS;\r\n if (!rec.alerted) {\r\n rec.alerted = true;\r\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.`);\r\n }\r\n return this.mergeNote(rec, `merge blocked: ${error}`);\r\n }\r\n this.toast('success', `\uD83D\uDD00 Merged PR #${pr.number} into ${repo.defaultBranch}: ${pr.title}`);\r\n return true;\r\n }\r\n\r\n /** Show where auto-merge stands on a PR's card. Doesn't count as a change to the record. */\r\n private mergeNote(rec: QaRecord, text: string | null) {\r\n if (rec.mergeNote !== text) {\r\n rec.mergeNote = text;\r\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\r\n }\r\n return false;\r\n }\r\n\r\n /** QA passed, but the PR can't merge as it is: a developer fixes it, and QA re-tests if the code changed. */\r\n private sendBack(repo: PersistedRepo, rec: QaRecord, reason: 'checks' | 'conflict', fixInstructions: string) {\r\n if (rec.mergeFixes >= MAX_MERGE_FIXES) {\r\n this.setQa(rec, { status: 'needs-human', mergeNote: null });\r\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.`);\r\n return false;\r\n }\r\n this.setQa(rec, { status: 'failed', fixReason: reason, fixInstructions, mergeFixes: rec.mergeFixes + 1, mergeNote: null, pendingSince: null });\r\n setTimeout(() => this.schedule(), 200);\r\n return false;\r\n }\r\n\r\n /** Fast-forward the floor's main checkout (usually your own project folder) and report how it stands. */\r\n private async syncFolder(repo: PersistedRepo) {\r\n const rt = this.repoRt.get(repo.id);\r\n if (!rt || rt.cloneStatus !== 'ready') return rt?.folderSync ?? null;\r\n const own = isSamePath(this.backend.mainDir(repo.fullName), OFFICE_DIR); // updating the running office restarts it mid-work\r\n const status = await this.backend.syncMain(repo.fullName, repo.defaultBranch, { touch: !own }).catch((err) => `sync failed: ${oneLine(err)}`);\r\n if (!this.repoRt.has(repo.id)) return null;\r\n const before = rt.folderSync;\r\n rt.folderSync = status;\r\n this.emitRepo(repo);\r\n if (status && status !== before) {\r\n const name = repo.localPath ? path.basename(repo.localPath) : repo.fullName;\r\n if (status.startsWith('updated')) this.toast('success', `\uD83D\uDCC1 ${name}: ${status}`);\r\n else if (/behind|diverged|failed/.test(status)) this.toast('info', `\uD83D\uDCC1 ${name} wasn't updated: ${status}`);\r\n }\r\n return status;\r\n }\r\n\r\n /** The manager's \"Sync now\". */\r\n async syncFolderNow(repoId: string) {\r\n return { folderSync: await this.syncFolder(this.repo(repoId)) };\r\n }\r\n\r\n // ---------- the floor's app (preview monitor) ----------\r\n\r\n /** Run the floor's app from its preview worktree: the default branch, or an open PR. Replaces what it is running now. */\r\n async startPreview(id: string, pr?: number | null): Promise<PreviewView> {\r\n const repo = this.repo(id);\r\n return this.previews.start(repo, `${repo.fullName.split('/')[1]} app`, pr);\r\n }\r\n\r\n stopPreview(id: string): Promise<PreviewView> {\r\n return this.previews.stop(this.repo(id));\r\n }\r\n\r\n /** Server shutdown: stop every floor's app so nothing is left holding a preview port. */\r\n shutdown(): Promise<void> {\r\n return this.previews.stopAll(this.state.repos);\r\n }\r\n\r\n private async cloneRepo(id: string) {\r\n const repo = this.state.repos.find((r) => r.id === id);\r\n const rt = this.repoRt.get(id);\r\n if (!repo || !rt || rt.cloneStatus === 'cloning') return;\r\n rt.cloneStatus = 'cloning';\r\n rt.cloneError = undefined;\r\n this.emitRepo(repo);\r\n try {\r\n await this.backend.ensureClone(repo.fullName);\r\n rt.cloneStatus = 'ready';\r\n void this.previews.refreshDefault(repo);\r\n } catch (err) {\r\n rt.cloneStatus = 'error';\r\n rt.cloneError = (err as Error).message;\r\n this.toast('error', `Could not clone ${repo.fullName}: ${rt.cloneError}`);\r\n }\r\n if (this.repoRt.has(id)) this.emitRepo(repo);\r\n }\r\n\r\n async syncRepo(id: string) {\r\n const repo = this.state.repos.find((r) => r.id === id);\r\n const rt = this.repoRt.get(id);\r\n if (!repo || !rt || rt.syncing) return;\r\n rt.syncing = true;\r\n try {\r\n const started = Date.now();\r\n const [issues, pulls] = await Promise.all([this.backend.listIssues(repo.fullName), this.backend.listPulls(repo.fullName)]);\r\n rt.issues = issues;\r\n rt.pulls = pulls;\r\n rt.lastSync = Date.now();\r\n rt.fetchedAt = started;\r\n rt.syncError = undefined;\r\n this.reconcilePulls(repo, pulls);\r\n // Something was merged since the last look (by the office or anyone else): bring the folder up to date.\r\n const newest = pulls.reduce<string | null>((m, p) => (p.mergedAt && (!m || p.mergedAt > m) ? p.mergedAt : m), null);\r\n if (newest !== rt.lastMergedAt) {\r\n rt.lastMergedAt = newest;\r\n void this.syncFolder(repo);\r\n }\r\n void this.advanceMerges(repo);\r\n } catch (err) {\r\n rt.syncError = (err as Error).message;\r\n } finally {\r\n rt.syncing = false;\r\n }\r\n if (this.repoRt.has(id)) this.emitRepo(repo);\r\n }\r\n\r\n /** Keep agents and QA records in step with what happened to PRs on GitHub. */\r\n private reconcilePulls(repo: PersistedRepo, pulls: PullInfo[]) {\r\n for (const a of this.state.agents) {\r\n if (a.repoId !== repo.id || a.role !== 'dev' || a.prNumber == null || BUSY.includes(a.status) || a.status === 'idle') continue;\r\n const pr = pulls.find((p) => p.number === a.prNumber);\r\n if (!pr || pr.state === 'OPEN') continue;\r\n if (a.task === 'qa') {\r\n this.clearTask(a); // they only tested it\r\n continue;\r\n }\r\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.` }]);\r\n this.clearTask(a);\r\n }\r\n\r\n // Finished PRs leave QA.\r\n for (const q of this.state.qa.filter((x) => x.repoId === repo.id)) {\r\n const pr = pulls.find((p) => p.number === q.prNumber);\r\n if (pr && pr.state !== 'OPEN' && q.status !== 'testing' && q.status !== 'fixing') {\r\n this.state.qa = this.state.qa.filter((x) => x !== q);\r\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: q.prNumber });\r\n }\r\n }\r\n\r\n // Every swarm PR goes through QA, including ones opened before QA existed or while the server was down.\r\n for (const pr of pulls) {\r\n if (pr.state !== 'OPEN' || pr.isDraft || !pr.headRefName.startsWith('swarm/')) continue;\r\n if (this.state.qa.some((q) => q.repoId === repo.id && q.prNumber === pr.number)) continue;\r\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));\r\n this.queueQa(repo, pr.number, dev ?? null, pr.closesIssues[0] ?? null);\r\n }\r\n this.save();\r\n }\r\n\r\n async createIssue(repoId: string, title: string, body: string, assignTo?: string, specialty?: string) {\r\n const repo = this.repo(repoId);\r\n if (!title.trim()) throw new HttpError(400, 'An issue needs a title');\r\n const slug = specialtySlug(specialty);\r\n const number = await this.backend.createIssue(repo.fullName, title.trim(), body, slug ? [specialtyLabel(slug)] : []);\r\n await this.syncRepo(repo.id);\r\n this.toast('success', `Issue #${number} filed on ${repo.fullName}`);\r\n if (assignTo) await this.assign(assignTo, number);\r\n else setTimeout(() => this.schedule(), 200);\r\n return number;\r\n }\r\n\r\n async mergePull(repoId: string, number: number, method: 'squash' | 'merge' | 'rebase' = 'squash') {\r\n const repo = this.repo(repoId);\r\n await this.backend.mergePull(repo.fullName, number, method);\r\n this.toast('success', `Merged PR #${number} into ${repo.defaultBranch}`);\r\n await this.syncRepo(repo.id);\r\n setTimeout(() => this.schedule(), 200);\r\n }\r\n\r\n async closePull(repoId: string, number: number) {\r\n const repo = this.repo(repoId);\r\n await this.backend.closePull(repo.fullName, number);\r\n await this.syncRepo(repo.id);\r\n }\r\n\r\n // ---------- agents ----------\r\n\r\n hireAgent(\r\n repoId: string,\r\n opts: {\r\n name?: string;\r\n model?: string;\r\n effort?: string;\r\n role?: string;\r\n look?: string;\r\n title?: string;\r\n specialty?: string;\r\n brief?: string;\r\n hiredBy?: 'manager' | 'ceo';\r\n appearance?: { color: string; hair: string; skin: string };\r\n },\r\n ) {\r\n const repo = this.repo(repoId);\r\n const role: AgentRole = opts.role === 'qa' ? 'qa' : 'dev';\r\n const used = new Set(this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).map((a) => a.desk));\r\n let desk = 0;\r\n while (used.has(desk)) desk++;\r\n if (desk >= MAX_DESKS[role]) {\r\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)`);\r\n }\r\n const name = opts.name?.trim() || this.freeName(role);\r\n const agent: PersistedAgent = {\r\n id: crypto.randomUUID(),\r\n name,\r\n repoId: repo.id,\r\n role,\r\n title: String(opts.title ?? '').trim().slice(0, 60),\r\n specialty: specialtySlug(opts.specialty),\r\n brief: String(opts.brief ?? '').trim().slice(0, 2500),\r\n hiredBy: opts.hiredBy ?? 'manager',\r\n look: LOOKS.includes(opts.look as AgentLook) ? (opts.look as AgentLook) : lookFor(name),\r\n task: null,\r\n desk,\r\n color: opts.appearance?.color ?? pick(SHIRTS),\r\n hair: opts.appearance?.hair ?? pick(HAIR),\r\n skin: opts.appearance?.skin ?? pick(SKIN),\r\n model: opts.model ?? '',\r\n effort: EFFORTS.includes(opts.effort as EffortLevel) ? (opts.effort as EffortLevel) : '',\r\n status: 'idle',\r\n issueNumber: null,\r\n issueTitle: null,\r\n branch: null,\r\n prNumber: null,\r\n prUrl: null,\r\n startedAt: null,\r\n endedAt: null,\r\n costUsd: 0,\r\n turns: 0,\r\n sessionId: null,\r\n lastError: null,\r\n logTail: [],\r\n };\r\n this.state.agents.push(agent);\r\n this.agentRt.set(agent.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [] });\r\n this.appendLog(agent, [\r\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}).` },\r\n ...(agent.title ? [{ kind: 'system' as const, text: `\uD83E\uDEAA ${agent.title}${agent.specialty ? ` \u00B7 takes swarm:${agent.specialty} issues first` : ''}` }] : []),\r\n ]);\r\n this.save();\r\n this.broadcast({ type: 'agent', agent: this.agentView(agent, false) });\r\n setTimeout(() => this.schedule(), 200);\r\n return this.agentView(agent, true);\r\n }\r\n\r\n /** Every floor has at least one QA tester. */\r\n private ensureQaTester(repo: PersistedRepo) {\r\n if (this.state.agents.some((a) => a.repoId === repo.id && a.role === 'qa')) return;\r\n this.hireAgent(repo.id, { role: 'qa' });\r\n }\r\n\r\n /** A name from the role's pool that no agent or pending candidate has. */\r\n private freeName(role: 'dev' | 'qa') {\r\n const taken = new Set([...this.state.agents.map((a) => a.name), ...this.state.requests.filter((r) => r.status === 'pending').map((r) => r.name)]);\r\n const pool = role === 'qa' ? QA_NAMES : DEV_NAMES;\r\n return pool.find((n) => !taken.has(n)) || `${role === 'qa' ? 'Tester' : 'Agent'} ${this.state.agents.length + 1}`;\r\n }\r\n\r\n updateAgent(\r\n id: string,\r\n patch: { name?: string; model?: string; effort?: string; look?: string; title?: string; specialty?: string; brief?: string; color?: string; hair?: string },\r\n ) {\r\n const a = this.agent(id);\r\n if (patch.name?.trim() && patch.name.trim() !== a.name) {\r\n a.name = patch.name.trim().slice(0, 24);\r\n a.look = lookFor(a.name);\r\n }\r\n if (LOOKS.includes(patch.look as AgentLook)) a.look = patch.look as AgentLook;\r\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) a.color = patch.color;\r\n if (patch.hair && /^#[0-9a-f]{6}$/i.test(patch.hair)) a.hair = patch.hair;\r\n if (patch.model !== undefined) a.model = String(patch.model).trim();\r\n if (patch.effort !== undefined) a.effort = EFFORTS.includes(patch.effort as EffortLevel) ? (patch.effort as EffortLevel) : '';\r\n if (a.role !== 'ceo') {\r\n if (patch.title !== undefined) a.title = String(patch.title).trim().slice(0, 60);\r\n if (patch.specialty !== undefined) a.specialty = specialtySlug(patch.specialty);\r\n if (patch.brief !== undefined) a.brief = String(patch.brief).trim().slice(0, 2500);\r\n }\r\n this.save();\r\n this.emitAgent(a);\r\n }\r\n\r\n fireAgent(id: string, force = false) {\r\n const a = this.agent(id);\r\n if (a.role === 'ceo') throw new HttpError(409, `${a.name} runs the company and can't be let go.`);\r\n if (!force && a.role === 'qa' && this.state.agents.filter((x) => x.repoId === a.repoId && x.role === 'qa').length <= 1) {\r\n throw new HttpError(409, `${a.name} is the only QA tester on this floor, and every floor needs at least one.`);\r\n }\r\n for (const r of this.state.requests.filter((x) => x.kind === 'let-go' && x.agentId === id && x.status === 'pending')) {\r\n this.decide(r, { status: 'approved', note: 'They were let go directly.', decidedBy: 'manager' });\r\n }\r\n\r\n this.agentRt.get(id)?.session?.stop();\r\n void removeScreens(id);\r\n for (const q of this.state.qa) {\r\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\r\n if (q.devAgentId === id) q.devAgentId = null;\r\n if (q.devAgentId === null && q.status === 'fixing') this.setQa(q, { status: 'failed' });\r\n }\r\n const repo = this.state.repos.find((r) => r.id === a.repoId);\r\n if (repo) {\r\n const slug = this.agentSlug(a);\r\n void this.backend\r\n .releaseDesk(repo.fullName, slug, this.port(a))\r\n .then(() => this.backend.removeDesk(repo.fullName, slug))\r\n .catch(() => undefined);\r\n }\r\n this.state.agents = this.state.agents.filter((x) => x.id !== id);\r\n this.agentRt.delete(id);\r\n this.save();\r\n this.broadcast({ type: 'agentRemoved', agentId: id });\r\n }\r\n\r\n stopAgent(id: string) {\r\n const a = this.agent(id);\r\n if (!BUSY.includes(a.status)) return;\r\n a.status = 'stopped';\r\n a.lastError = 'Stopped by manager';\r\n this.appendLog(a, [{ kind: 'manager', text: '\u25A0 Manager stopped this session.' }]);\r\n this.agentRt.get(id)?.session?.stop();\r\n this.emitAgent(a);\r\n this.save();\r\n }\r\n\r\n resetAgent(id: string) {\r\n const a = this.agent(id);\r\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is busy; stop them first`);\r\n for (const q of this.state.qa) {\r\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\r\n if (q.devAgentId === id && q.status === 'fixing') this.setQa(q, { status: 'failed' });\r\n }\r\n this.clearTask(a);\r\n this.appendLog(a, [{ kind: 'system', text: '\u21BA Cleared desk. Ready for new work.' }]);\r\n this.save();\r\n }\r\n\r\n private issueTaken(repo: PersistedRepo, n: number) {\r\n if (this.state.agents.some((a) => a.repoId === repo.id && a.role === 'dev' && a.task !== 'qa' && a.issueNumber === n && a.status !== 'idle' && a.status !== 'error')) return true;\r\n const pulls = this.repoRt.get(repo.id)?.pulls ?? [];\r\n return pulls.some((p) => p.state === 'OPEN' && (p.closesIssues.includes(n) || p.headRefName.startsWith(`swarm/issue-${n}-`)));\r\n }\r\n\r\n private ensureSlot() {\r\n if (this.slotsFull()) {\r\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.`);\r\n }\r\n }\r\n\r\n async assign(agentId: string, issueNumber: number, note?: string) {\r\n const a = this.agent(agentId);\r\n const repo = this.repo(a.repoId);\r\n if (a.role === 'qa') throw new HttpError(400, `${a.name} is a QA tester; they test pull requests rather than issues.`);\r\n if (a.role === 'ceo') throw new HttpError(400, `${a.name} runs the company; give issues to the developers.`);\r\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is already working on #${a.issueNumber}`);\r\n this.ensureSlot();\r\n const issue = this.repoRt.get(repo.id)?.issues.find((i) => i.number === issueNumber);\r\n if (!issue) throw new HttpError(404, `Issue #${issueNumber} is not open on ${repo.fullName}`);\r\n const holder = this.state.agents.find((x) => x.id !== a.id && x.repoId === repo.id && x.issueNumber === issueNumber && BUSY.includes(x.status));\r\n if (holder) throw new HttpError(409, `${holder.name} is already working on #${issueNumber}`);\r\n void this.runTask(a, repo, issue, note);\r\n return this.agentView(a, false);\r\n }\r\n\r\n private port(a: PersistedAgent) {\r\n return 5200 + (parseInt(a.id.slice(0, 4), 16) % 700);\r\n }\r\n\r\n private linkedRepos(repo: PersistedRepo) {\r\n return repo.links.map((id) => this.state.repos.find((r) => r.id === id)).filter((r): r is PersistedRepo => !!r);\r\n }\r\n\r\n private buildSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, fixing?: { pr: number; headRef: string }) {\r\n const linked = this.linkedRepos(repo).map((r) => `- ${r.fullName}: read-only reference clone at ${this.backend.mainDir(r.fullName)}`);\r\n const push = fixing ? `git push origin HEAD:${fixing.headRef}` : `git push -u origin ${branch}`;\r\n return [\r\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.`,\r\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.`,\r\n a.brief ? `\\nYour job description:\\n${a.brief}` : '',\r\n '',\r\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\r\n repo.summary ? `Project: ${repo.summary}` : '',\r\n repo.mission ? `What the team is building (the manager's brief): ${repo.mission}` : '',\r\n `Your worktree: ${cwd}`,\r\n fixing\r\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.`\r\n : `Your branch: ${branch} (already checked out, created from origin/${repo.defaultBranch})`,\r\n linked.length ? `Related repositories you may read for context (do not modify them):\\n${linked.join('\\n')}` : '',\r\n '',\r\n 'Workflow:',\r\n '1. Read the issue and explore the relevant code before changing anything.',\r\n '2. Implement the change with focused commits and clear messages.',\r\n \"3. Run the project's existing tests, linters and build (if any) and fix what you broke. Install dependencies first if needed.\",\r\n repo.browserTesting\r\n ? `4. If the project has a web UI, start its dev server in the background on port ${this.port(a)} (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.`\r\n : '4. Verify the behaviour you changed as directly as you can.',\r\n `5. Push: ${push}`,\r\n fixing\r\n ? '6. Reply with a short summary of what you fixed.'\r\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>\".`,\r\n fixing ? '' : '7. End your final message with the pull request URL on its own line.',\r\n '',\r\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.',\r\n ]\r\n .filter((l) => l !== '')\r\n .join('\\n');\r\n }\r\n\r\n private beginTask(a: PersistedAgent, patch: Partial<PersistedAgent>, banner: string, preparing: string) {\r\n const rt = this.agentRt.get(a.id)!;\r\n Object.assign(a, {\r\n status: 'preparing' as AgentStatus,\r\n startedAt: Date.now(),\r\n endedAt: null,\r\n costUsd: 0,\r\n turns: 0,\r\n lastError: null,\r\n ...patch,\r\n });\r\n rt.screenshot = null;\r\n rt.browserUrl = null;\r\n rt.shots = [];\r\n void removeScreens(a.id);\r\n this.appendLog(a, [\r\n { kind: 'system', text: '' },\r\n { kind: 'system', text: `\u2501\u2501\u2501 ${banner} \u2501\u2501\u2501` },\r\n { kind: 'system', text: preparing },\r\n ]);\r\n this.emitAgent(a);\r\n this.save();\r\n }\r\n\r\n private async prepare(a: PersistedAgent, repo: PersistedRepo, base: { pr?: number }, branch: string): Promise<string | null> {\r\n try {\r\n if (this.repoRt.get(repo.id)?.cloneStatus !== 'ready') await this.cloneRepo(repo.id);\r\n await this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a));\r\n const cwd = await this.backend.prepareDesk(repo.fullName, { defaultBranch: repo.defaultBranch, pr: base.pr }, this.agentSlug(a), branch);\r\n return a.status === 'preparing' ? cwd : null; // null: stopped or fired while preparing\r\n } catch (err) {\r\n if (a.status !== 'preparing') return null;\r\n a.status = 'error';\r\n a.endedAt = Date.now();\r\n a.lastError = (err as Error).message;\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n this.emitAgent(a);\r\n this.save();\r\n return null;\r\n }\r\n }\r\n\r\n private async runTask(a: PersistedAgent, repo: PersistedRepo, issue: IssueInfo, note?: string) {\r\n const branch = `swarm/issue-${issue.number}-${slugify(a.name)}`;\r\n this.beginTask(\r\n a,\r\n { task: 'issue', issueNumber: issue.number, issueTitle: issue.title, branch, prNumber: null, prUrl: null, sessionId: null },\r\n `Issue #${issue.number}: ${issue.title}`,\r\n `Preparing worktree on ${branch}\u2026`,\r\n );\r\n const cwd = await this.prepare(a, repo, {}, branch);\r\n if (!cwd) return;\r\n\r\n const prompt = [\r\n `Please resolve GitHub issue #${issue.number}: ${issue.title}`,\r\n `URL: ${issue.url}`,\r\n issue.labels.length ? `Labels: ${issue.labels.join(', ')}` : '',\r\n '',\r\n issue.body?.trim() || '(The issue has no description.)',\r\n note ? `\\nNote from the manager: ${note}` : '',\r\n ]\r\n .filter(Boolean)\r\n .join('\\n');\r\n\r\n this.startAgentSession(a, repo, cwd, prompt, this.buildSystemAppend(a, repo, cwd, branch));\r\n }\r\n\r\n private startAgentSession(\r\n a: PersistedAgent,\r\n repo: PersistedRepo,\r\n cwd: string,\r\n prompt: string,\r\n systemAppend: string,\r\n resumeSessionId?: string,\r\n outputSchema?: Record<string, unknown>,\r\n ) {\r\n const rt = this.agentRt.get(a.id)!;\r\n a.status = 'working';\r\n this.emitAgent(a);\r\n rt.session = this.backend.startSession(\r\n {\r\n cwd,\r\n prompt,\r\n systemAppend,\r\n model: a.model || this.state.settings.defaultModel,\r\n effort: a.effort || this.state.settings.defaultEffort,\r\n browserTesting: repo.browserTesting,\r\n permissionMode: this.state.settings.permissionMode,\r\n additionalDirectories: this.linkedRepos(repo).map((r) => this.backend.mainDir(r.fullName)),\r\n role: a.task === 'qa' ? 'qa' : a.role, // a developer covering QA works under QA's rules\r\n outputSchema,\r\n resumeSessionId,\r\n },\r\n {\r\n log: (entries) => this.appendLog(a, entries),\r\n tool: (name) => {\r\n if (rt.currentTool === name) return;\r\n rt.currentTool = name;\r\n this.emitAgent(a);\r\n },\r\n sessionId: (id) => {\r\n a.sessionId = id;\r\n },\r\n browserUrl: (url) => {\r\n rt.browserUrl = url;\r\n this.emitAgent(a);\r\n },\r\n screenshot: (data, mime) => {\r\n const at = Date.now();\r\n rt.screenshot = { data, mime, at };\r\n rt.shots.push({ data, mime, url: rt.browserUrl, at });\r\n if (rt.shots.length > 12) rt.shots.shift();\r\n this.broadcast({ type: 'screen', agentId: a.id, url: rt.browserUrl, at });\r\n void removeScreens(a.id)\r\n .then(() => fs.mkdir(SCREENS_DIR, { recursive: true }))\r\n .then(() => fs.writeFile(screenFile(a.id, mime), data))\r\n .catch((err) => console.warn('could not save screenshot', err));\r\n },\r\n limited: (at) => this.pauseForLimit(at),\r\n finished: (result) => void this.onFinished(a, repo, result),\r\n },\r\n repo.defaultBranch,\r\n );\r\n }\r\n\r\n private async onFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const rt = this.agentRt.get(a.id);\r\n if (!rt || !this.state.agents.includes(a)) return; // fired\r\n rt.session = null;\r\n rt.currentTool = null;\r\n a.endedAt = Date.now();\r\n a.costUsd += result.costUsd;\r\n a.turns += result.turns;\r\n // Dev servers the agent forgot to stop would otherwise keep its port and lock its desk folder.\r\n void this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined);\r\n\r\n if (a.task === 'qa') await this.onQaFinished(a, repo, result);\r\n else if (a.task === 'fix') this.onFixFinished(a, repo, result);\r\n else await this.onIssueFinished(a, repo, result);\r\n\r\n this.emitAgent(a);\r\n this.save();\r\n void this.syncRepo(repo.id);\r\n setTimeout(() => this.schedule(), 500);\r\n }\r\n\r\n private minutes(a: PersistedAgent) {\r\n return a.startedAt && a.endedAt ? Math.max(1, Math.round((a.endedAt - a.startedAt) / 60000)) : 0;\r\n }\r\n\r\n private fail(a: PersistedAgent, result: SessionResult, what: string) {\r\n a.status = 'error';\r\n a.lastError = result.errors.join('; ') || 'Session failed';\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n this.toast('error', `${a.name} hit a problem on ${what}: ${a.lastError.slice(0, 120)}`);\r\n }\r\n\r\n private async onIssueFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const escaped = repo.fullName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n const m = result.text.match(new RegExp(`https://github\\\\.com/${escaped}/pull/(\\\\d+)`, 'i'));\r\n if (m) {\r\n a.prNumber = Number(m[1]);\r\n a.prUrl = m[0];\r\n } else if (a.branch) {\r\n const pr = await this.backend.prForBranch(repo.fullName, a.branch).catch(() => null);\r\n if (pr) {\r\n a.prNumber = pr.number;\r\n a.prUrl = pr.url;\r\n }\r\n }\r\n\r\n if (a.status === 'stopped') return; // the manager already logged the stop\r\n if (!result.ok) {\r\n this.issueFailed(repo, a.issueNumber);\r\n return this.fail(a, result, `#${a.issueNumber}`);\r\n }\r\n this.issueFailures.delete(`${repo.id}#${a.issueNumber}`);\r\n a.status = 'done';\r\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'}` }]);\r\n if (a.prNumber) {\r\n this.queueQa(repo, a.prNumber, a, a.issueNumber);\r\n this.appendLog(a, [{ kind: 'system', text: `\uD83D\uDCE8 Handed PR #${a.prNumber} to QA.` }]);\r\n this.toast('success', `${a.name} opened PR #${a.prNumber} for #${a.issueNumber}; it's off to QA`);\r\n } else {\r\n this.noPullRequest(a, repo);\r\n }\r\n }\r\n\r\n /**\r\n * An issue session ended without a PR, which would leave the issue \"taken\" with nobody on it. The same developer,\r\n * who has the context and the worktree, is asked once to finish; after that the issue goes back on the board.\r\n */\r\n private noPullRequest(a: PersistedAgent, repo: PersistedRepo) {\r\n const key = `${repo.id}#${a.issueNumber}`;\r\n if (this.nudged.has(key)) return this.releaseIssue(a, repo);\r\n this.nudged.add(key);\r\n // message() starts the session before its first await, so the scheduler can't hand this developer other work first.\r\n void this.message(\r\n a.id,\r\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.`,\r\n ).catch(() => this.releaseIssue(a, repo));\r\n }\r\n\r\n private releaseIssue(a: PersistedAgent, repo: PersistedRepo) {\r\n const n = a.issueNumber;\r\n this.clearTask(a);\r\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.`);\r\n }\r\n\r\n // ---------- QA ----------\r\n\r\n private queueQa(repo: PersistedRepo, prNumber: number, dev: PersistedAgent | null, issueNumber: number | null) {\r\n let rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\r\n if (rec) {\r\n if (rec.status === 'testing') return;\r\n this.setQa(rec, { status: 'queued', devAgentId: dev?.id ?? rec.devAgentId, devSessionId: dev?.sessionId ?? rec.devSessionId });\r\n } else {\r\n rec = {\r\n repoId: repo.id,\r\n prNumber,\r\n status: 'queued',\r\n round: 1,\r\n devAgentId: dev?.id ?? null,\r\n qaAgentId: null,\r\n summary: null,\r\n checks: [],\r\n commentUrl: null,\r\n updatedAt: Date.now(),\r\n issueNumber,\r\n devSessionId: dev && dev.prNumber === prNumber ? dev.sessionId : null,\r\n fixInstructions: null,\r\n sessionFailures: 0,\r\n mergeNote: null,\r\n testedSha: null,\r\n passedSha: null,\r\n fixReason: null,\r\n mergeFixes: 0,\r\n retests: 0,\r\n pendingSince: null,\r\n mergeRetryAt: null,\r\n alerted: false,\r\n };\r\n this.state.qa.push(rec);\r\n this.setQa(rec, {});\r\n }\r\n setTimeout(() => this.schedule(), 200);\r\n }\r\n\r\n /** Manager's \"send to QA\" for any open PR (including ones opened by people). */\r\n async sendToQa(repoId: string, prNumber: number) {\r\n const repo = this.repo(repoId);\r\n const pr = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === prNumber && p.state === 'OPEN');\r\n if (!pr) throw new HttpError(404, `PR #${prNumber} is not open on ${repo.fullName}`);\r\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\r\n if (rec?.status === 'testing' || rec?.status === 'fixing') throw new HttpError(409, `PR #${prNumber} is already ${rec.status}`);\r\n if (rec && (rec.status === 'needs-human' || rec.status === 'passed' || rec.status === 'failed')) {\r\n // a fresh start: the manager decided it deserves another round\r\n rec.round += 1;\r\n rec.sessionFailures = 0;\r\n }\r\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));\r\n this.queueQa(repo, prNumber, dev ?? null, pr.closesIssues[0] ?? null);\r\n this.toast('info', `PR #${prNumber} is queued for QA`);\r\n }\r\n\r\n private buildQaSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, pr: PrDetails) {\r\n return [\r\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.`,\r\n ...(a.brief ? ['', `Your job description:\\n${a.brief}`] : []),\r\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.\"] : []),\r\n '',\r\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\r\n ...(repo.summary ? [`Project: ${repo.summary}`] : []),\r\n ...(repo.mission ? [`What the team is building (the manager's brief): ${repo.mission}`] : []),\r\n ...(repo.qaBrief ? [`What to check on this project (from the CEO):\\n${repo.qaBrief}`] : []),\r\n `Pull request #${pr.number} \"${pr.title}\" from branch ${pr.headRefName}: ${pr.url}`,\r\n `Your worktree: ${cwd}. It has the pull request's code checked out on local branch ${branch}.`,\r\n '',\r\n 'How to test:',\r\n '1. Read the PR description and the linked issue, and work out the acceptance criteria.',\r\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.`,\r\n \"3. Install dependencies if needed, then run the project's test suite, linters, type checks and build (whichever exist).\",\r\n repo.browserTesting\r\n ? `4. If the project has a UI, start it in the background on port ${this.port(a)} (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 of every important state: the screenshots are attached to the PR as evidence. Stop the server afterwards.`\r\n : '4. Exercise the changed behaviour directly (run the program, call the API, write a quick script).',\r\n '5. You may write throwaway scripts to probe behaviour, but do not commit them.',\r\n '',\r\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.',\r\n ].join('\\n');\r\n }\r\n\r\n private async runQa(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\r\n const branch = `qa/pr-${rec.prNumber}-${slugify(a.name)}`;\r\n this.setQa(rec, { status: 'testing', qaAgentId: a.id });\r\n this.beginTask(\r\n a,\r\n { task: 'qa', issueNumber: rec.issueNumber, issueTitle: `PR #${rec.prNumber}`, branch, prNumber: rec.prNumber, prUrl: null, sessionId: null },\r\n `QA \u00B7 PR #${rec.prNumber} \u00B7 round ${rec.round}`,\r\n `Checking out PR #${rec.prNumber}\u2026`,\r\n );\r\n\r\n let pr: PrDetails;\r\n let issue: { title: string; body: string } | null = null;\r\n try {\r\n pr = await this.backend.prDetails(repo.fullName, rec.prNumber);\r\n const issueNumber = rec.issueNumber ?? pr.closesIssues[0] ?? null;\r\n if (issueNumber) issue = await this.backend.issueDetails(repo.fullName, issueNumber).catch(() => null);\r\n Object.assign(a, { issueTitle: pr.title, prUrl: pr.url });\r\n rec.testedSha = pr.headSha;\r\n this.emitAgent(a);\r\n } catch (err) {\r\n a.status = 'error';\r\n a.endedAt = Date.now();\r\n a.lastError = (err as Error).message;\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n this.setQa(rec, { status: 'queued', qaAgentId: null });\r\n this.emitAgent(a);\r\n return;\r\n }\r\n if (pr.state !== 'OPEN') {\r\n this.appendLog(a, [{ kind: 'system', text: `PR #${pr.number} is ${pr.state.toLowerCase()}; nothing to test.` }]);\r\n this.state.qa = this.state.qa.filter((q) => q !== rec);\r\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: rec.prNumber });\r\n this.clearTask(a);\r\n return;\r\n }\r\n\r\n const cwd = await this.prepare(a, repo, { pr: rec.prNumber }, branch);\r\n if (!cwd) {\r\n if (this.state.qa.includes(rec) && rec.status === 'testing') this.setQa(rec, { status: 'queued', qaAgentId: null });\r\n return;\r\n }\r\n\r\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\r\n const prompt = [\r\n `Please QA pull request #${pr.number}: ${pr.title}`,\r\n `URL: ${pr.url}`,\r\n `Author: ${dev ? `${dev.name} (developer agent)` : 'a teammate'} \u00B7 QA round ${rec.round}`,\r\n rec.fixReason === 'conflict'\r\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.`\r\n : rec.fixReason === 'checks'\r\n ? '\\nQA passed it before, but since then the developer changed the code to fix failing GitHub checks. Re-check everything.'\r\n : rec.round > 1 && rec.summary\r\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.`\r\n : '',\r\n '',\r\n 'PR description:',\r\n pr.body.trim() || '(empty)',\r\n issue ? `\\nLinked issue: ${issue.title}\\n${issue.body.trim() || '(no description)'}` : '',\r\n ]\r\n .filter((l) => l !== '')\r\n .join('\\n');\r\n\r\n this.startAgentSession(a, repo, cwd, prompt, this.buildQaSystemAppend(a, repo, cwd, branch, pr), undefined, QA_SCHEMA);\r\n }\r\n\r\n private async onQaFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\r\n const rt = this.agentRt.get(a.id)!;\r\n const report = result.ok ? parseReport(result) : null;\r\n\r\n if (a.status === 'stopped' || !report) {\r\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}`);\r\n if (rec) {\r\n const failures = rec.sessionFailures + (this.limited() ? 0 : 1); // the usage limit isn't the PR's fault\r\n this.setQa(rec, {\r\n status: a.status === 'stopped' || failures >= 2 ? 'needs-human' : 'queued',\r\n qaAgentId: null,\r\n sessionFailures: failures,\r\n summary: a.status === 'stopped' ? 'QA was stopped by the manager.' : rec.summary,\r\n });\r\n }\r\n return;\r\n }\r\n\r\n a.status = 'done';\r\n const pass = report.verdict === 'pass';\r\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` }]);\r\n\r\n // Evidence + comment on the PR\r\n let commentUrl: string | null = null;\r\n if (rec) {\r\n try {\r\n this.appendLog(a, [{ kind: 'system', text: '\uD83D\uDCCE Uploading evidence and posting the QA report on the PR\u2026' }]);\r\n const body = await this.renderQaComment(a, repo, rec, report, rt.shots);\r\n commentUrl = (await this.backend.commentPull(repo.fullName, rec.prNumber, body)) || null;\r\n this.appendLog(a, [{ kind: 'system', text: ` \u23BF ${commentUrl ?? 'comment posted'}` }]);\r\n } catch (err) {\r\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF Could not post the QA report: ${(err as Error).message}` }]);\r\n }\r\n const qaRounds = rec.round - rec.retests; // rounds QA itself asked for\r\n const nextStatus = pass ? 'passed' : qaRounds >= MAX_QA_ROUNDS ? 'needs-human' : 'failed';\r\n this.setQa(rec, {\r\n status: nextStatus,\r\n summary: report.summary,\r\n checks: report.checks,\r\n commentUrl: commentUrl ?? rec.commentUrl,\r\n fixInstructions: report.fixInstructions ?? report.checks.filter((c) => c.result === 'fail').map((c) => `${c.name}: ${c.details}`).join('\\n'),\r\n sessionFailures: 0,\r\n fixReason: pass ? null : 'qa',\r\n passedSha: pass ? rec.testedSha : null,\r\n mergeNote: null,\r\n pendingSince: null,\r\n mergeRetryAt: null,\r\n alerted: false,\r\n });\r\n this.toast(\r\n pass ? 'success' : 'error',\r\n pass\r\n ? `\u2705 ${a.name} passed PR #${rec.prNumber}${repo.autoMerge ? \"; it merges once GitHub's checks are green\" : ': ready to merge'}`\r\n : nextStatus === 'needs-human'\r\n ? `\u274C PR #${rec.prNumber} failed QA ${qaRounds} times and needs a human`\r\n : `\u274C ${a.name} failed PR #${rec.prNumber}; sending it back to the developer`,\r\n );\r\n }\r\n }\r\n\r\n private async renderQaComment(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord, report: QaReport, shots: Shot[]) {\r\n const pass = report.verdict === 'pass';\r\n const images: string[] = [];\r\n const evidence = shots.slice(-8);\r\n const offset = shots.length - evidence.length;\r\n const folder = `pr-${rec.prNumber}/round-${rec.round}-${Date.now().toString(36)}`;\r\n for (const [i, shot] of evidence.entries()) {\r\n const n = offset + i + 1;\r\n const ext = MIME_EXT[shot.mime] ?? 'png';\r\n const file = `${folder}/${String(n).padStart(2, '0')}.${ext}`;\r\n try {\r\n const url = await this.backend.uploadEvidence(repo.fullName, file, shot.data);\r\n const caption = report.screenshots[n - 1] ?? `Screenshot ${n}`;\r\n images.push(`**${n}. ${caption}**${shot.url ? ` \u00B7 \\`${shot.url}\\`` : ''}\\n\\n<img src=\"${url}\" alt=\"${caption.replace(/\"/g, \"'\")}\" width=\"760\">`);\r\n } catch (err) {\r\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF screenshot ${n} upload failed: ${(err as Error).message.slice(0, 120)}` }]);\r\n }\r\n }\r\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\r\n const lines = [\r\n `## \uD83D\uDD0D QA report: ${pass ? '\u2705 Passed' : '\u274C Failed'}`,\r\n `**Tester:** ${a.name} (cubefarm QA agent) \u00B7 **Round:** ${rec.round}${dev ? ` \u00B7 **Author:** ${dev.name}` : ''}`,\r\n '',\r\n report.summary,\r\n '',\r\n '| | Check | Details |',\r\n '|---|---|---|',\r\n ...report.checks.map((c) => `| ${ICON[c.result]} | ${cell(c.name)} | ${cell(c.details)} |`),\r\n ];\r\n if (report.commands.length) {\r\n lines.push('', '<details><summary>\uD83E\uDDEA Commands run</summary>', '', '| Command | Result |', '|---|---|', ...report.commands.map((c) => `| \\`${cell(c.command)}\\` | ${cell(c.result)} |`), '', '</details>');\r\n }\r\n if (!pass && report.fixInstructions) lines.push('', '### \uD83D\uDD27 What needs fixing', '', report.fixInstructions);\r\n if (images.length) lines.push('', '### \uD83D\uDCF8 Evidence', '', ...images.flatMap((img) => [img, '']));\r\n else lines.push('', '_No browser screenshots were taken in this round._');\r\n const merge = repo.autoMerge ? \"merges automatically once GitHub's checks pass\" : 'ready for the manager to merge';\r\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>`);\r\n return lines.join('\\n');\r\n }\r\n\r\n /** Send a failed PR back to the developer who wrote it (or any free developer on the floor). */\r\n private async runFix(dev: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\r\n const original = rec.devAgentId === dev.id;\r\n const pull = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === rec.prNumber);\r\n const headRef = pull?.headRefName ?? dev.branch ?? `pr-${rec.prNumber}`;\r\n const qaAgent = rec.qaAgentId ? this.state.agents.find((x) => x.id === rec.qaAgentId) : null;\r\n this.setQa(rec, { status: 'fixing', devAgentId: dev.id });\r\n this.beginTask(\r\n dev,\r\n { task: 'fix', issueNumber: rec.issueNumber, issueTitle: pull?.title ?? `PR #${rec.prNumber}`, branch: headRef, prNumber: rec.prNumber, prUrl: pull?.url ?? null },\r\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}`,\r\n `Checking out PR #${rec.prNumber}\u2026`,\r\n );\r\n const cwd = await this.prepare(dev, repo, { pr: rec.prNumber }, headRef);\r\n if (!cwd) {\r\n if (rec.status === 'fixing') this.setQa(rec, { status: 'failed' });\r\n return;\r\n }\r\n const failed = rec.checks.filter((c) => c.result === 'fail');\r\n const takeover = original ? '' : ' A teammate wrote it, so read the PR and the linked issue first.';\r\n const push = `push to the same branch: git push origin HEAD:${headRef}`;\r\n const mergeFix =\r\n rec.fixReason === 'conflict'\r\n ? [\r\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but it now conflicts with ${repo.defaultBranch} because other work was merged first.${takeover}`,\r\n '',\r\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}`,\r\n ]\r\n : rec.fixReason === 'checks'\r\n ? [\r\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but GitHub checks failed on it.${takeover}`,\r\n '',\r\n `Failed checks:\\n${rec.fixInstructions ?? ''}`,\r\n '',\r\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}`,\r\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.`,\r\n ]\r\n : null;\r\n const qaFix = [\r\n original\r\n ? `QA tester ${qaAgent?.name ?? 'QA'} tested your pull request #${rec.prNumber} and it FAILED (round ${rec.round}).`\r\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.`,\r\n '',\r\n `QA summary: ${rec.summary ?? ''}`,\r\n failed.length ? `Failed checks:\\n${failed.map((c) => `- ${c.name}: ${c.details}`).join('\\n')}` : '',\r\n rec.fixInstructions ? `\\nWhat needs fixing:\\n${rec.fixInstructions}` : '',\r\n rec.commentUrl ? `\\nFull report with screenshots: ${rec.commentUrl}` : '',\r\n '',\r\n `Fix these problems, re-run the relevant checks, and push to the same branch: git push origin HEAD:${headRef}`,\r\n 'Then reply with a short summary of what you changed. Do not open a new pull request; QA will re-test automatically.',\r\n ];\r\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.';\r\n const prompt = (mergeFix ? [...mergeFix, '', mergeEnd] : qaFix).filter((l) => l !== '').join('\\n');\r\n const resume = original && rec.devSessionId ? rec.devSessionId : undefined;\r\n this.startAgentSession(dev, repo, cwd, prompt, this.buildSystemAppend(dev, repo, cwd, headRef, { pr: rec.prNumber, headRef }), resume);\r\n }\r\n\r\n private onFixFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\r\n if (a.status === 'stopped') {\r\n if (rec?.status === 'fixing') this.setQa(rec, { status: 'failed' });\r\n return;\r\n }\r\n if (!result.ok) {\r\n this.fail(a, result, `the fix for PR #${a.prNumber}`);\r\n // Someone else gets a go before it lands on the manager.\r\n const failures = rec ? rec.sessionFailures + (this.limited() ? 0 : 1) : 0;\r\n if (rec) this.setQa(rec, { status: failures >= 2 ? 'needs-human' : 'failed', sessionFailures: failures });\r\n return;\r\n }\r\n a.status = 'done';\r\n if (rec && (rec.fixReason === 'checks' || rec.fixReason === 'conflict')) {\r\n // Back in line to merge: new commits go through QA again first, a re-run of flaky checks doesn't.\r\n this.appendLog(a, [{ kind: 'done', text: `\u2714 PR #${a.prNumber} fixed in ${this.minutes(a)}m. Back in line to merge.` }]);\r\n this.setQa(rec, { status: 'passed', devSessionId: a.sessionId ?? rec.devSessionId, mergeNote: 'waiting for fresh checks' });\r\n this.toast('info', `${a.name} fixed PR #${rec.prNumber}; it merges once it passes again`);\r\n return;\r\n }\r\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Fix pushed for PR #${a.prNumber} in ${this.minutes(a)}m. Back to QA.` }]);\r\n if (rec) {\r\n this.setQa(rec, { status: 'queued', round: rec.round + 1, devSessionId: a.sessionId ?? rec.devSessionId });\r\n this.toast('info', `${a.name} pushed fixes for PR #${rec.prNumber}; QA round ${rec.round} is queued`);\r\n }\r\n }\r\n\r\n async message(id: string, text: string) {\r\n const a = this.agent(id);\r\n if (a.role === 'ceo') return this.messageCeo(text);\r\n const repo = this.repo(a.repoId);\r\n if (!text.trim()) throw new HttpError(400, 'Empty message');\r\n const rt = this.agentRt.get(id)!;\r\n if (rt.session) {\r\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\r\n rt.session.send(text);\r\n return;\r\n }\r\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.`);\r\n if (a.status === 'preparing') throw new HttpError(409, `${a.name} is still setting up; try again in a moment`);\r\n if (!a.sessionId || !a.branch || a.task === 'qa') throw new HttpError(409, `${a.name} has no session to continue. Assign an issue instead.`);\r\n this.ensureSlot();\r\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\r\n const cwd = this.backend.deskDir(repo.fullName, this.agentSlug(a));\r\n a.lastError = null;\r\n a.startedAt = Date.now();\r\n if (a.task === null) a.task = 'issue';\r\n const fixing = a.task === 'fix' && a.prNumber ? { pr: a.prNumber, headRef: a.branch } : undefined;\r\n this.startAgentSession(a, repo, cwd, text, this.buildSystemAppend(a, repo, cwd, a.branch, fixing), a.sessionId);\r\n }\r\n\r\n updateSettings(patch: Partial<SwarmSettings>) {\r\n const s = this.state.settings;\r\n if (patch.sessionLimit !== undefined) s.sessionLimit = Math.max(0, Math.round(Number(patch.sessionLimit)) || 0);\r\n if (patch.defaultModel !== undefined) s.defaultModel = String(patch.defaultModel).trim() || DEFAULT_MODEL;\r\n if (patch.defaultEffort !== undefined && EFFORTS.includes(patch.defaultEffort)) s.defaultEffort = patch.defaultEffort;\r\n if (patch.permissionMode === 'guarded' || patch.permissionMode === 'bypass') s.permissionMode = patch.permissionMode;\r\n if (patch.hiring === 'approve' || patch.hiring === 'auto') s.hiring = patch.hiring;\r\n if (patch.teamCap !== undefined) s.teamCap = Math.max(1, Math.min(15, Math.round(Number(patch.teamCap)) || 1));\r\n if (patch.ceoHeartbeatMin !== undefined) s.ceoHeartbeatMin = Math.max(0, Math.min(1440, Math.round(Number(patch.ceoHeartbeatMin)) || 0));\r\n if (typeof patch.managerName === 'string') s.managerName = patch.managerName.trim().slice(0, 40);\r\n if (typeof patch.companyName === 'string') s.companyName = patch.companyName.trim().slice(0, 60);\r\n if (typeof patch.projectsDir === 'string' && patch.projectsDir.trim()) s.projectsDir = path.resolve(patch.projectsDir.trim());\r\n if (typeof patch.setupDone === 'boolean') s.setupDone = patch.setupDone;\r\n if (patch.tutorialStep !== undefined) s.tutorialStep = Math.max(-1, Math.round(Number(patch.tutorialStep)) || 0);\r\n this.save();\r\n this.broadcast({ type: 'settings', settings: s });\r\n this.emitCeo();\r\n setTimeout(() => this.schedule(), 200);\r\n return s;\r\n }\r\n\r\n /** The setup wizard: who you are, the company, and your CEO. */\r\n setup(x: { managerName?: string; companyName?: string; hiring?: string; ceoName?: string; ceoLook?: string; ceoColor?: string }) {\r\n this.updateSettings({\r\n managerName: x.managerName,\r\n companyName: x.companyName,\r\n ...(x.hiring === 'auto' || x.hiring === 'approve' ? { hiring: x.hiring } : {}),\r\n });\r\n const ceo = this.ceo();\r\n this.updateAgent(ceo.id, { name: x.ceoName, color: x.ceoColor });\r\n if (LOOKS.includes(x.ceoLook as AgentLook)) this.updateAgent(ceo.id, { look: x.ceoLook });\r\n return this.state.settings;\r\n }\r\n\r\n // ---------- scheduling ----------\r\n\r\n /**\r\n * Agents on a floor who can take work now. One whose last session failed sits out a short cooldown, then gets work\r\n * like everyone else instead of waiting for the manager to reset them.\r\n */\r\n private available(repo: PersistedRepo, role: AgentRole) {\r\n const now = Date.now();\r\n return this.state.agents\r\n .filter((a) => a.repoId === repo.id && a.role === role && (FREE.includes(a.status) || (a.status === 'error' && now - (a.endedAt ?? 0) >= ERROR_COOLDOWN_MS)))\r\n .sort((x, y) => x.desk - y.desk);\r\n }\r\n\r\n private scheduleOffset = 0;\r\n private issueFailures = new Map<string, number>(); // `${repoId}#${issue}` \u2192 failed sessions on it\r\n private nudged = new Set<string>(); // `${repoId}#${issue}`: its developer was asked once to finish the missing PR\r\n private pausedUntil = 0; // Claude's usage limit was hit: nothing new starts before this\r\n\r\n /** Backlog issues that can start now, most urgent first: the ones holding up the longest chain of other issues, then the oldest. */\r\n private readyIssues(repo: PersistedRepo) {\r\n const issues = this.repoRt.get(repo.id)!.issues;\r\n const open = new Set(issues.map((i) => i.number));\r\n const weight = holdUps(issues);\r\n return issues\r\n .filter(\r\n (i) =>\r\n !i.labels.some((l) => /^(swarm:skip|wontfix|question)$/i.test(l)) &&\r\n !this.issueTaken(repo, i.number) &&\r\n blockers(i.body, open).length === 0 &&\r\n (this.issueFailures.get(`${repo.id}#${i.number}`) ?? 0) < MAX_ISSUE_FAILURES,\r\n )\r\n .map((issue) => ({ issue, want: issueSpecialty(issue.labels), ...weight.get(issue.number)! }))\r\n .sort((x, y) => y.chain - x.chain || y.waiting - x.waiting || x.issue.number - y.issue.number);\r\n }\r\n\r\n /**\r\n * The free developer to put on a job: one it `suits` first, then whoever is least needed elsewhere (fewest ready\r\n * issues in their specialty, then the least open work in it), so specialists stay free for their own lane.\r\n */\r\n private pickDev(repo: PersistedRepo, devs: PersistedAgent[], suits: (a: PersistedAgent) => boolean) {\r\n if (devs.length <= 1) return devs[0];\r\n const ready = this.readyIssues(repo).map((r) => r.want);\r\n const open = this.repoRt.get(repo.id)!.issues.map((i) => issueSpecialty(i.labels));\r\n const rank = (a: PersistedAgent) => {\r\n const s = a.specialty.toLowerCase();\r\n return [suits(a) ? 0 : 1, ready.filter((w) => w === s).length, open.filter((w) => w === s).length, a.desk];\r\n };\r\n return devs\r\n .map((a) => ({ a, r: rank(a) }))\r\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;\r\n }\r\n\r\n /**\r\n * Finish work in flight: test queued PRs (oldest first) and get failed ones fixed. Returns true if work started.\r\n * QA testers test; when they're all busy, a free developer who didn't write the PR covers for them, so QA never\r\n * holds up the floor. A failed PR goes back to its author when they're free, and otherwise to any free developer.\r\n */\r\n private startPipelineWork(repo: PersistedRepo): boolean {\r\n const devs = this.available(repo, 'dev');\r\n const testers = this.available(repo, 'qa');\r\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);\r\n for (const rec of waiting('queued')) {\r\n const tester =\r\n testers[0] ??\r\n this.pickDev(\r\n repo,\r\n devs.filter((a) => a.id !== rec.devAgentId),\r\n (a) => /test|qa/i.test(a.specialty),\r\n );\r\n if (!tester) continue;\r\n void this.runQa(tester, repo, rec);\r\n return true;\r\n }\r\n for (const rec of waiting('failed')) {\r\n const issue = this.repoRt.get(repo.id)!.issues.find((i) => i.number === rec.issueNumber);\r\n const want = issue ? issueSpecialty(issue.labels) : null;\r\n const dev = devs.find((a) => a.id === rec.devAgentId) ?? this.pickDev(repo, devs, (a) => a.specialty.toLowerCase() === want);\r\n if (!dev) break;\r\n void this.runFix(dev, repo, rec);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Give a free developer the next backlog issue (auto-assign floors only). Returns true if work started.\r\n * Issues that say \"Depends on #N\" wait until #N is closed; the rest go in readyIssues() order. A swarm:<specialty>\r\n * label is a preference, not a lock: a free specialist gets first pick, and otherwise the issue goes to whichever\r\n * free developer is least needed elsewhere, so nobody sits idle while there is work that can start.\r\n */\r\n private startIssueWork(repo: PersistedRepo): boolean {\r\n if (!repo.autoAssign) return false;\r\n const free = this.available(repo, 'dev');\r\n const ready = free.length ? this.readyIssues(repo) : [];\r\n if (ready.length === 0) return false;\r\n const fits = (a: PersistedAgent, want: string) => a.specialty.toLowerCase() === want;\r\n // Of the issues holding up the most, take one a free specialist fits.\r\n const pick = ready.find((r) => r.chain === ready[0].chain && free.some((a) => fits(a, r.want))) ?? ready[0];\r\n const agent = this.pickDev(repo, free, (a) => fits(a, pick.want))!;\r\n // assign() flips the agent to 'preparing' synchronously, so the next pass sees it as busy.\r\n void this.assign(agent.id, pick.issue.number).catch((err) => console.warn('auto-assign failed', err));\r\n return agent.status === 'preparing';\r\n }\r\n\r\n private limited() {\r\n return Date.now() < this.pausedUntil;\r\n }\r\n\r\n /** Claude turned a session away for the usage limit: start nothing new until it resets, rather than failing agent after agent. */\r\n private pauseForLimit(resetsAt: number | null) {\r\n const until = (resetsAt ?? Date.now() + LIMIT_PAUSE_MS) + 30_000;\r\n if (until <= this.pausedUntil) return;\r\n const fresh = Date.now() >= this.pausedUntil;\r\n this.pausedUntil = until;\r\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.`);\r\n }\r\n\r\n /** A failed session releases its issue for someone else; an issue that keeps failing waits for the manager. */\r\n private issueFailed(repo: PersistedRepo, n: number | null) {\r\n if (n == null || this.limited()) return; // the usage limit isn't the issue's fault\r\n const key = `${repo.id}#${n}`;\r\n const failures = (this.issueFailures.get(key) ?? 0) + 1;\r\n this.issueFailures.set(key, failures);\r\n if (failures === MAX_ISSUE_FAILURES) {\r\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.`);\r\n }\r\n }\r\n\r\n /**\r\n * Hand out work for free session slots. Finishing beats starting: QA and QA fixes on every floor go before any new issue.\r\n * Within each phase floors take turns (one job per floor per pass), and the starting floor rotates between calls,\r\n * so no repo can hog the slots.\r\n */\r\n private schedule() {\r\n if (this.limited()) return;\r\n // Management first: the CEO's jobs are short and shape everyone else's work.\r\n this.maybeHeartbeat();\r\n this.startCeoWork();\r\n const repos = this.state.repos.filter((r) => {\r\n const rt = this.repoRt.get(r.id);\r\n return rt && rt.lastSync != null && rt.cloneStatus !== 'error';\r\n });\r\n if (repos.length === 0) return;\r\n this.scheduleOffset = (this.scheduleOffset + 1) % repos.length;\r\n const order = [...repos.slice(this.scheduleOffset), ...repos.slice(0, this.scheduleOffset)];\r\n for (const start of [(r: PersistedRepo) => this.startPipelineWork(r), (r: PersistedRepo) => this.startIssueWork(r)]) {\r\n let progress = true;\r\n while (progress) {\r\n progress = false;\r\n for (const repo of order) {\r\n if (this.slotsFull()) return;\r\n if (start(repo)) progress = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // ---------- the CEO ----------\r\n\r\n private ceo() {\r\n return this.state.agents.find((a) => a.id === CEO_ID)!;\r\n }\r\n\r\n /** The company always has a CEO. One cut off by a server restart picks its job back up. */\r\n private ensureCeo(interrupted: PersistedAgent[]) {\r\n let a = this.state.agents.find((x) => x.id === CEO_ID);\r\n if (!a) {\r\n a = {\r\n id: CEO_ID,\r\n name: CEO_NAME,\r\n repoId: '',\r\n role: 'ceo',\r\n title: 'Chief Executive Officer',\r\n specialty: '',\r\n brief: '',\r\n hiredBy: 'manager',\r\n look: lookFor(CEO_NAME),\r\n task: null,\r\n desk: 0,\r\n color: '#e63946',\r\n hair: '#2b2118',\r\n skin: pick(SKIN),\r\n model: CEO_MODEL,\r\n effort: CEO_EFFORT,\r\n status: 'idle',\r\n issueNumber: null,\r\n issueTitle: null,\r\n branch: null,\r\n prNumber: null,\r\n prUrl: null,\r\n startedAt: null,\r\n endedAt: null,\r\n costUsd: 0,\r\n turns: 0,\r\n sessionId: null,\r\n lastError: null,\r\n logTail: [],\r\n };\r\n this.state.agents.push(a);\r\n this.agentRt.set(a.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [] });\r\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.` }]);\r\n }\r\n const i = interrupted.indexOf(a);\r\n if (i >= 0) {\r\n interrupted.splice(i, 1);\r\n a.status = 'idle';\r\n a.lastError = null;\r\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Picking the job back up.' }]);\r\n }\r\n if (this.state.ceo.job) {\r\n this.state.ceo.queue.unshift(this.state.ceo.job);\r\n this.state.ceo.job = null;\r\n }\r\n this.state.ceo.lastReviewAt ??= Date.now(); // the first review comes one heartbeat after the office opens\r\n }\r\n\r\n private ceoFloor(repoId?: string) {\r\n const repo = repoId ? this.state.repos.find((r) => r.id === repoId) : undefined;\r\n if (!repo) return null;\r\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 };\r\n }\r\n\r\n private ceoInfo(): CeoInfo {\r\n const c = this.state.ceo;\r\n const view = (j: CeoJob) => ({ kind: j.kind, label: jobLabel(j, this.ceoFloor(j.repoId)) });\r\n const min = this.state.settings.ceoHeartbeatMin;\r\n return {\r\n queue: c.queue.map(view),\r\n job: c.job ? view(c.job) : null,\r\n lastReviewAt: c.lastReviewAt,\r\n nextReviewAt: min > 0 && c.lastReviewAt ? c.lastReviewAt + min * 60_000 : null,\r\n };\r\n }\r\n\r\n private emitCeo() {\r\n this.broadcast({ type: 'ceo', ceo: this.ceoInfo() });\r\n }\r\n\r\n /** Queue a job for the CEO: one onboarding or plan per floor, one review, and chat messages merge into one reply. */\r\n private enqueueCeo(job: CeoJob) {\r\n const q = this.state.ceo.queue;\r\n if (job.kind === 'plan' && q.some((j) => j.kind === 'onboard' && j.repoId === job.repoId)) return; // onboarding plans from the brief too\r\n const same = q.findIndex((j) => j.kind === job.kind && (job.kind === 'review' || job.kind === 'chat' || j.repoId === job.repoId));\r\n if (same >= 0) q[same] = job.kind === 'chat' ? { ...q[same], text: `${q[same].text}\\n${job.text}` } : job;\r\n else q.push(job);\r\n this.emitCeo();\r\n this.save();\r\n setTimeout(() => this.schedule(), 150);\r\n }\r\n\r\n /** Start the CEO's next job when they're free and a session slot is open. Replies to the manager go first. */\r\n private startCeoWork(): void {\r\n const a = this.state.agents.find((x) => x.id === CEO_ID);\r\n const c = this.state.ceo;\r\n if (!a || BUSY.includes(a.status) || c.job || c.queue.length === 0) return;\r\n if (this.slotsFull()) return;\r\n const rank: Record<CeoJob['kind'], number> = { chat: 0, onboard: 1, plan: 1, review: 2 };\r\n // A floor's jobs wait for its clone and first sync, so the CEO has something to read.\r\n const ready = (j: CeoJob) => {\r\n const rt = j.repoId ? this.repoRt.get(j.repoId) : undefined;\r\n return !rt || rt.cloneStatus === 'error' || (rt.cloneStatus === 'ready' && rt.lastSync != null);\r\n };\r\n const job = [...c.queue].sort((x, y) => rank[x.kind] - rank[y.kind]).find(ready);\r\n if (!job) return;\r\n c.queue.splice(c.queue.indexOf(job), 1);\r\n const rt = job.repoId ? this.repoRt.get(job.repoId) : undefined;\r\n if (job.repoId && (!rt || rt.cloneStatus === 'error')) {\r\n const repo = this.state.repos.find((r) => r.id === job.repoId);\r\n if (repo) this.postMessage('office', `\u26A0\uFE0F ${a.name} couldn't study floor ${repo.floor}: the repository clone failed (${rt?.cloneError ?? 'unknown error'}).`);\r\n this.emitCeo();\r\n this.save();\r\n return this.startCeoWork();\r\n }\r\n void this.runCeoJob(a, job);\r\n }\r\n\r\n private async runCeoJob(a: PersistedAgent, job: CeoJob) {\r\n const rt = this.agentRt.get(a.id)!;\r\n const floor = this.ceoFloor(job.repoId);\r\n const label = jobLabel(job, floor);\r\n this.state.ceo.job = job;\r\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 });\r\n this.appendLog(a, [\r\n { kind: 'system', text: '' },\r\n { kind: 'system', text: `\u2501\u2501\u2501 ${label} \u2501\u2501\u2501` },\r\n ]);\r\n if (job.kind === 'chat') this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${job.text}` }]);\r\n if (job.kind === 'review') {\r\n this.state.ceo.lastReviewAt = Date.now();\r\n this.state.ceo.lastFingerprint = this.fingerprint();\r\n }\r\n this.ceoIssues = { filed: 0, repos: new Set() };\r\n this.emitAgent(a);\r\n this.emitCeo();\r\n this.save();\r\n await fs.mkdir(CEO_DIR, { recursive: true }).catch(() => undefined);\r\n if (a.status !== 'working') {\r\n // stopped before the session started\r\n this.state.ceo.job = null;\r\n this.emitCeo();\r\n return;\r\n }\r\n const s = this.state.settings;\r\n rt.session = this.backend.startSession(\r\n {\r\n cwd: CEO_DIR,\r\n prompt: ceoJobPrompt(job, floor),\r\n systemAppend: ceoSystemPrompt({\r\n name: a.name,\r\n company: s.companyName,\r\n manager: s.managerName,\r\n notesFile: path.join(CEO_DIR, 'NOTES.md'),\r\n sessionLimit: s.sessionLimit,\r\n teamCap: s.teamCap,\r\n hiring: s.hiring,\r\n }),\r\n model: a.model || CEO_MODEL,\r\n effort: a.effort || CEO_EFFORT,\r\n browserTesting: false,\r\n permissionMode: s.permissionMode,\r\n additionalDirectories: this.state.repos.filter((r) => this.repoRt.get(r.id)?.cloneStatus === 'ready').map((r) => this.backend.mainDir(r.fullName)),\r\n role: 'ceo',\r\n office: this.officeTools(),\r\n // A chat carries on from the CEO's last session, so \"why did you propose that?\" has an answer.\r\n resumeSessionId: job.kind === 'chat' ? (a.sessionId ?? undefined) : undefined,\r\n },\r\n {\r\n log: (entries) => this.appendLog(a, entries),\r\n tool: (name) => {\r\n if (rt.currentTool === name) return;\r\n rt.currentTool = name;\r\n this.emitAgent(a);\r\n },\r\n sessionId: (id) => {\r\n a.sessionId = id;\r\n },\r\n browserUrl: () => undefined,\r\n screenshot: () => undefined,\r\n turn: (text) => this.postMessage('ceo', text),\r\n limited: (at) => this.pauseForLimit(at),\r\n finished: (result) => this.onCeoFinished(a, result),\r\n },\r\n '',\r\n );\r\n }\r\n\r\n private onCeoFinished(a: PersistedAgent, result: SessionResult) {\r\n const rt = this.agentRt.get(a.id);\r\n if (!rt) return;\r\n rt.session = null;\r\n rt.currentTool = null;\r\n a.endedAt = Date.now();\r\n a.costUsd += result.costUsd;\r\n a.turns += result.turns;\r\n const job = this.state.ceo.job;\r\n this.state.ceo.job = null;\r\n if (a.status === 'stopped') {\r\n // the manager already logged the stop\r\n } else if (!result.ok) {\r\n a.status = 'error';\r\n a.lastError = result.errors.join('; ') || 'Session failed';\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n const what = job ? jobLabel(job, this.ceoFloor(job.repoId)).toLowerCase() : 'working';\r\n this.postMessage('office', `\u26A0\uFE0F ${a.name} hit a problem while ${what}: ${a.lastError.slice(0, 240)}`);\r\n } else {\r\n a.status = 'done';\r\n const filed = this.ceoIssues.filed ? ` \u00B7 ${this.ceoIssues.filed} issue${this.ceoIssues.filed === 1 ? '' : 's'} filed` : '';\r\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Done in ${this.minutes(a)}m \u00B7 ${a.turns} turns${filed}` }]);\r\n }\r\n for (const id of this.ceoIssues.repos) void this.syncRepo(id);\r\n this.emitAgent(a);\r\n this.emitCeo();\r\n this.save();\r\n setTimeout(() => this.schedule(), 300);\r\n }\r\n\r\n /** The manager's phone \u2192 the CEO. Injected into a running session, otherwise the CEO picks it up next. */\r\n async messageCeo(text: string) {\r\n const t = text.trim().slice(0, 4000);\r\n if (!t) throw new HttpError(400, 'Empty message');\r\n const a = this.ceo();\r\n this.postMessage('manager', t);\r\n const rt = this.agentRt.get(a.id)!;\r\n if (rt.session) {\r\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${t}` }]);\r\n rt.session.send(`Message from the manager (they read your reply on their phone, so keep it short):\\n${t}`);\r\n return;\r\n }\r\n this.enqueueCeo({ kind: 'chat', text: t, at: Date.now() });\r\n }\r\n\r\n requestReview() {\r\n if (this.state.repos.length === 0) throw new HttpError(400, 'Connect a repo first: the CEO needs a floor to review.');\r\n this.enqueueCeo({ kind: 'review', at: Date.now() });\r\n }\r\n\r\n onboardFloor(repoId: string) {\r\n const repo = this.repo(repoId);\r\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\r\n }\r\n\r\n /** The manager hands the CEO a brief for a floor; the CEO turns it into issues and a team. */\r\n planFloor(repoId: string, mission?: string) {\r\n const repo = this.repo(repoId);\r\n if (typeof mission === 'string') {\r\n repo.mission = mission.trim().slice(0, 4000);\r\n this.emitRepo(repo);\r\n }\r\n if (!repo.mission) throw new HttpError(400, 'Write a brief first: what should this floor build?');\r\n this.enqueueCeo({ kind: 'plan', repoId: repo.id, at: Date.now() });\r\n }\r\n\r\n /** Everything the heartbeat cares about. When it hasn't changed since the last review, the review is skipped. */\r\n private fingerprint() {\r\n const data = {\r\n repos: this.state.repos.map((r) => {\r\n const rt = this.repoRt.get(r.id);\r\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)];\r\n }),\r\n agents: this.state.agents.filter((a) => a.role !== 'ceo').map((a) => [a.id, FREE.includes(a.status) ? 'free' : a.status]),\r\n qa: this.state.qa.map((q) => [q.repoId, q.prNumber, q.status]),\r\n requests: this.state.requests.filter((r) => r.status === 'pending').map((r) => r.id),\r\n };\r\n return crypto.createHash('sha1').update(JSON.stringify(data)).digest('hex');\r\n }\r\n\r\n private maybeHeartbeat() {\r\n const min = this.state.settings.ceoHeartbeatMin;\r\n const c = this.state.ceo;\r\n if (!min || this.state.repos.length === 0 || c.job?.kind === 'review' || c.queue.some((j) => j.kind === 'review')) return;\r\n if (Date.now() < (c.lastReviewAt ?? 0) + min * 60_000) return;\r\n if (this.fingerprint() === c.lastFingerprint) {\r\n c.lastReviewAt = Date.now(); // nothing changed since the last review\r\n this.emitCeo();\r\n this.save();\r\n return;\r\n }\r\n this.enqueueCeo({ kind: 'review', at: Date.now() });\r\n }\r\n\r\n // ---------- the phone ----------\r\n\r\n private postMessage(from: PhoneMessage['from'], text: string, requestId?: string) {\r\n const m: PhoneMessage = { id: this.messageSeq++, from, text: text.trim().slice(0, 6000), at: Date.now(), ...(requestId ? { requestId } : {}) };\r\n this.state.messages.push(m);\r\n if (this.state.messages.length > KEEP_MESSAGES) this.state.messages.splice(0, this.state.messages.length - KEEP_MESSAGES);\r\n this.broadcast({ type: 'message', message: m });\r\n this.save();\r\n return m;\r\n }\r\n\r\n markPhoneRead(at: number) {\r\n const t = Math.min(Number(at) || Date.now(), Date.now());\r\n if (t <= this.state.phoneReadAt) return;\r\n this.state.phoneReadAt = t;\r\n this.broadcast({ type: 'phoneRead', at: t });\r\n this.save();\r\n }\r\n\r\n // ---------- hire and let-go proposals ----------\r\n\r\n private addRequest(req: HireRequestView) {\r\n this.state.requests.push(req);\r\n const decided = this.state.requests.filter((r) => r.status !== 'pending');\r\n if (decided.length > KEEP_DECIDED_REQUESTS) {\r\n const drop = new Set(decided.slice(0, decided.length - KEEP_DECIDED_REQUESTS));\r\n this.state.requests = this.state.requests.filter((r) => !drop.has(r));\r\n }\r\n this.broadcast({ type: 'request', request: req });\r\n this.save();\r\n }\r\n\r\n private decide(req: HireRequestView, patch: Pick<HireRequestView, 'status' | 'note' | 'decidedBy'>) {\r\n Object.assign(req, patch, { decidedAt: Date.now() });\r\n this.broadcast({ type: 'request', request: req });\r\n this.save();\r\n }\r\n\r\n approveRequest(id: string, overrides: { name?: string; model?: string; effort?: string } = {}, by: 'manager' | 'auto' = 'manager') {\r\n const req = this.state.requests.find((r) => r.id === id);\r\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\r\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\r\n const repo = this.repo(req.repoId);\r\n if (req.kind === 'hire') {\r\n const name = overrides.name?.trim() || req.name;\r\n const agent = this.hireAgent(repo.id, {\r\n name,\r\n role: req.role,\r\n model: overrides.model ?? req.model,\r\n effort: overrides.effort ?? req.effort,\r\n look: name === req.name ? req.look : undefined,\r\n title: req.title,\r\n specialty: req.specialty,\r\n brief: req.brief,\r\n hiredBy: 'ceo',\r\n appearance: { color: req.color, hair: req.hair, skin: req.skin },\r\n });\r\n req.agentId = agent.id;\r\n req.name = agent.name;\r\n this.decide(req, { status: 'approved', note: '', decidedBy: by });\r\n this.postMessage(\r\n 'office',\r\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}.`,\r\n req.id,\r\n );\r\n this.toast('success', `${agent.name} (${req.title}) joined floor ${repo.floor}`);\r\n return;\r\n }\r\n const a = req.agentId ? this.state.agents.find((x) => x.id === req.agentId) : undefined;\r\n this.decide(req, { status: 'approved', note: a ? '' : 'They had already left.', decidedBy: by });\r\n if (a) {\r\n try {\r\n this.fireAgent(a.id);\r\n } catch (err) {\r\n this.decide(req, { status: 'pending', note: '', decidedBy: null });\r\n throw err;\r\n }\r\n }\r\n this.postMessage('office', `\uD83D\uDC4B ${req.name} left floor ${repo.floor}${by === 'auto' ? ' (auto-approved)' : ''}.`, req.id);\r\n }\r\n\r\n rejectRequest(id: string, note = '') {\r\n const req = this.state.requests.find((r) => r.id === id);\r\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\r\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\r\n this.decide(req, { status: 'rejected', note: note.trim().slice(0, 400), decidedBy: 'manager' });\r\n const what = req.kind === 'hire' ? `${req.name} (${req.title})` : `letting ${req.name} go`;\r\n this.postMessage('office', `\u270B You declined ${what}${req.note ? `: \"${req.note}\"` : '.'}`, req.id);\r\n }\r\n\r\n // ---------- the CEO's office tools ----------\r\n\r\n private floorRepo(floor: number) {\r\n const r = this.state.repos.find((x) => x.floor === Number(floor));\r\n if (!r) throw new Error(`There is no floor ${floor}. Floors: ${this.state.repos.map((x) => `${x.floor} (${x.fullName})`).join(', ') || 'none'}.`);\r\n return r;\r\n }\r\n\r\n private agentByRef(ref: string) {\r\n const r = String(ref ?? '').trim().toLowerCase();\r\n const a = this.state.agents.find((x) => x.id === ref || x.name.toLowerCase() === r);\r\n if (!a) throw new Error(`No agent \"${ref}\". Use the ids from company_status.`);\r\n return a;\r\n }\r\n\r\n private agentDoing(a: PersistedAgent) {\r\n return !BUSY.includes(a.status) ? null : a.task === 'qa' ? `testing PR #${a.prNumber}` : a.task === 'fix' ? `fixing PR #${a.prNumber}` : `issue #${a.issueNumber}`;\r\n }\r\n\r\n private companyStatus() {\r\n const s = this.state.settings;\r\n const doing = (a: PersistedAgent) => this.agentDoing(a);\r\n // Keep the status compact, but make the cut visible so the CEO knows to read agent_detail before rewriting.\r\n const jobDescription = (brief: string) => {\r\n if (brief.length <= 400) return brief;\r\n const mark = `\u2026 (truncated, ${brief.length} chars; see agent_detail)`;\r\n return brief.slice(0, 400 - mark.length).trimEnd() + mark;\r\n };\r\n const floors = [...this.state.repos]\r\n .sort((x, y) => x.floor - y.floor)\r\n .map((r) => {\r\n const rt = this.repoRt.get(r.id)!;\r\n const open = new Set(rt.issues.map((i) => i.number));\r\n return {\r\n floor: r.floor,\r\n repo: r.fullName,\r\n description: r.description,\r\n clone: rt.cloneStatus === 'ready' ? this.backend.mainDir(r.fullName) : `(not available: clone ${rt.cloneStatus})`,\r\n brief: r.mission || null,\r\n profile: r.summary || null,\r\n qaBrief: r.qaBrief || null,\r\n preview: { command: r.preview.command, env: r.preview.env, status: this.previews.view(r).status },\r\n autoAssign: r.autoAssign,\r\n autoMerge: r.autoMerge,\r\n folderSync: rt.folderSync,\r\n capacity: {\r\n developers: this.state.agents.filter((a) => a.repoId === r.id && a.role === 'dev').length,\r\n developersFree: this.available(r, 'dev').length,\r\n issuesReadyToStart: this.readyIssues(r).length,\r\n issuesWaitingOnOthers: rt.issues.filter((i) => blockers(i.body, open).length > 0).length,\r\n longestDependencyChain: Math.max(0, ...[...holdUps(rt.issues).values()].map((w) => w.chain)),\r\n },\r\n team: this.state.agents\r\n .filter((a) => a.repoId === r.id)\r\n .map((a) => ({\r\n id: a.id,\r\n name: a.name,\r\n role: a.role,\r\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\r\n specialty: a.specialty || null,\r\n status: a.status,\r\n doing: doing(a),\r\n hiredBy: a.hiredBy,\r\n jobDescription: a.brief ? jobDescription(a.brief) : null,\r\n })),\r\n backlog: rt.issues.map((i) => ({\r\n number: i.number,\r\n title: i.title,\r\n specialty: issueSpecialty(i.labels) || null,\r\n waitsFor: blockers(i.body, open),\r\n inProgress: this.issueTaken(r, i.number),\r\n })),\r\n pullRequests: rt.pulls\r\n .filter((p) => p.state === 'OPEN')\r\n .map((p) => {\r\n const q = this.state.qa.find((x) => x.repoId === r.id && x.prNumber === p.number);\r\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 };\r\n }),\r\n mergedRecently: rt.pulls.filter((p) => p.state === 'MERGED').map((p) => `#${p.number} ${p.title}`),\r\n };\r\n });\r\n const req = (r: HireRequestView) => ({\r\n id: r.id,\r\n kind: r.kind,\r\n floor: this.state.repos.find((x) => x.id === r.repoId)?.floor ?? null,\r\n role: r.role,\r\n name: r.name,\r\n title: r.title,\r\n specialty: r.specialty || null,\r\n reason: r.reason,\r\n status: r.status,\r\n managerNote: r.note || null,\r\n });\r\n return JSON.stringify(\r\n {\r\n company: {\r\n ceo: this.ceo().name,\r\n hiring: s.hiring === 'auto' ? `auto-approved while a floor has fewer than ${s.teamCap} people` : 'the manager approves every proposal',\r\n teamCap: s.teamCap,\r\n sessionLimit: s.sessionLimit || 'none',\r\n sessionsRunning: this.running(),\r\n deskLimits: { dev: MAX_DESKS.dev, qa: MAX_DESKS.qa },\r\n },\r\n floors,\r\n pendingProposals: this.state.requests.filter((r) => r.status === 'pending').map(req),\r\n recentDecisions: this.state.requests.filter((r) => r.status !== 'pending').slice(-10).map(req),\r\n },\r\n null,\r\n 1,\r\n );\r\n }\r\n\r\n private agentDetail(x: { agent_id: string }) {\r\n const a = this.agentByRef(x.agent_id);\r\n const repo = this.state.repos.find((r) => r.id === a.repoId);\r\n const ceo = a.role === 'ceo';\r\n return JSON.stringify(\r\n {\r\n id: a.id,\r\n name: a.name,\r\n floor: repo?.floor ?? null,\r\n role: a.role,\r\n title: a.title || (a.role === 'qa' ? 'QA tester' : a.role === 'dev' ? 'Developer' : 'CEO'),\r\n specialty: a.specialty || null,\r\n status: a.status,\r\n doing: this.agentDoing(a),\r\n issue: a.issueNumber ? { number: a.issueNumber, title: a.issueTitle } : null,\r\n pullRequest: a.prNumber ? { number: a.prNumber, url: a.prUrl } : null,\r\n model: a.model || (ceo ? CEO_MODEL : this.state.settings.defaultModel),\r\n effort: a.effort || (ceo ? CEO_EFFORT : this.state.settings.defaultEffort),\r\n hiredBy: a.hiredBy,\r\n jobDescription: a.brief || null,\r\n },\r\n null,\r\n 1,\r\n );\r\n }\r\n\r\n private setFloorProfile(x: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }) {\r\n const r = this.floorRepo(x.floor);\r\n const preview = parsePreviewPatch(x.preview_command, x.preview_env);\r\n if (x.summary !== undefined) r.summary = String(x.summary).trim().slice(0, 140);\r\n if (x.qa_brief !== undefined) r.qaBrief = String(x.qa_brief).trim().slice(0, 2500);\r\n r.preview = { ...r.preview, ...preview };\r\n if (preview.command === null) void this.previews.refreshDefault(r);\r\n this.emitRepo(r);\r\n this.save();\r\n return `Saved floor ${r.floor}'s profile.`;\r\n }\r\n\r\n private updateJob(x: { agent_id: string; title?: string; specialty?: string; job_description?: string }) {\r\n const a = this.agentByRef(x.agent_id);\r\n if (a.role === 'ceo') throw new Error(\"That's you.\");\r\n this.updateAgent(a.id, { title: x.title, specialty: x.specialty, brief: x.job_description });\r\n const title = a.title || (a.role === 'qa' ? 'QA tester' : 'Developer');\r\n this.appendLog(a, [{ kind: 'system', text: `\uD83E\uDEAA ${this.ceo().name} updated ${a.name}'s job: ${title}${a.specialty ? ` \u00B7 swarm:${a.specialty}` : ''}` }]);\r\n return `Updated ${a.name}: ${title}${a.specialty ? ` (specialty ${a.specialty})` : ''}.`;\r\n }\r\n\r\n private proposeHire(x: { floor: number; role: 'dev' | 'qa'; title: string; specialty: string; job_description: string; reason: string; model?: string; effort?: string }) {\r\n const repo = this.floorRepo(x.floor);\r\n const role = x.role === 'qa' ? 'qa' : 'dev';\r\n const title = String(x.title ?? '').trim().slice(0, 60);\r\n if (!title) throw new Error('A hire needs a job title.');\r\n const specialty = specialtySlug(x.specialty);\r\n const pending = this.state.requests.filter((r) => r.status === 'pending');\r\n if (pending.length >= MAX_PENDING_REQUESTS) throw new Error(`${pending.length} proposals are already waiting for the manager. Wait for their decisions first.`);\r\n const dup = pending.find((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role && r.specialty === specialty);\r\n if (dup) throw new Error(`${dup.name} (${dup.title}) is already proposed for floor ${repo.floor} with that specialty.`);\r\n const seated = this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).length;\r\n const waiting = pending.filter((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role).length;\r\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.`);\r\n const name = this.freeName(role);\r\n const req: HireRequestView = {\r\n id: crypto.randomUUID(),\r\n kind: 'hire',\r\n repoId: repo.id,\r\n role,\r\n agentId: null,\r\n name,\r\n title,\r\n specialty,\r\n brief: String(x.job_description ?? '').trim().slice(0, 2500),\r\n reason: String(x.reason ?? '').trim().slice(0, 600),\r\n model: String(x.model ?? '').trim(),\r\n effort: EFFORTS.includes(x.effort as EffortLevel) ? (x.effort as EffortLevel) : '',\r\n look: lookFor(name),\r\n color: pick(SHIRTS),\r\n hair: pick(HAIR),\r\n skin: pick(SKIN),\r\n status: 'pending',\r\n note: '',\r\n createdAt: Date.now(),\r\n decidedAt: null,\r\n decidedBy: null,\r\n };\r\n this.addRequest(req);\r\n const s = this.state.settings;\r\n if (s.hiring === 'auto' && this.state.agents.filter((a) => a.repoId === repo.id).length < s.teamCap) {\r\n this.approveRequest(req.id, {}, 'auto');\r\n return `Hired ${req.name} as ${title} on floor ${repo.floor} (auto-approved; agent id ${req.agentId}).`;\r\n }\r\n this.postMessage('ceo', `\uD83D\uDCC4 New candidate for floor ${repo.floor}: ${name}, ${title}. ${req.reason}`, req.id);\r\n return `Proposed ${name} as ${title} on floor ${repo.floor}. The manager will approve or decline (request ${req.id}).`;\r\n }\r\n\r\n private proposeLetGo(x: { agent_id: string; reason: string }) {\r\n const a = this.agentByRef(x.agent_id);\r\n if (a.role === 'ceo') throw new Error(\"You can't let yourself go.\");\r\n const repo = this.repo(a.repoId);\r\n if (a.role === 'qa' && this.state.agents.filter((y) => y.repoId === repo.id && y.role === 'qa').length <= 1) {\r\n throw new Error(`${a.name} is floor ${repo.floor}'s only QA tester, and every floor keeps one.`);\r\n }\r\n const pending = this.state.requests.filter((r) => r.status === 'pending');\r\n if (pending.some((r) => r.kind === 'let-go' && r.agentId === a.id)) throw new Error(`Letting ${a.name} go is already proposed.`);\r\n if (pending.length >= MAX_PENDING_REQUESTS) throw new Error(`${pending.length} proposals are already waiting for the manager. Wait for their decisions first.`);\r\n const req: HireRequestView = {\r\n id: crypto.randomUUID(),\r\n kind: 'let-go',\r\n repoId: repo.id,\r\n role: a.role,\r\n agentId: a.id,\r\n name: a.name,\r\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\r\n specialty: a.specialty,\r\n brief: a.brief,\r\n reason: String(x.reason ?? '').trim().slice(0, 600),\r\n model: a.model,\r\n effort: a.effort,\r\n look: a.look,\r\n color: a.color,\r\n hair: a.hair,\r\n skin: a.skin,\r\n status: 'pending',\r\n note: '',\r\n createdAt: Date.now(),\r\n decidedAt: null,\r\n decidedBy: null,\r\n };\r\n this.addRequest(req);\r\n if (this.state.settings.hiring === 'auto' && FREE.includes(a.status)) {\r\n this.approveRequest(req.id, {}, 'auto');\r\n return `Let ${a.name} go (auto-approved).`;\r\n }\r\n this.postMessage('ceo', `\uD83D\uDC4B I suggest letting ${a.name} (${req.title}, floor ${repo.floor}) go. ${req.reason}`, req.id);\r\n return `Proposed letting ${a.name} go. The manager will decide (request ${req.id}).`;\r\n }\r\n\r\n private async fileIssue(x: { floor: number; title: string; body: string; specialty?: string }) {\r\n const repo = this.floorRepo(x.floor);\r\n if (this.ceoIssues.filed >= MAX_ISSUES_PER_JOB) throw new Error(`You already filed ${MAX_ISSUES_PER_JOB} issues in this job. That's plenty for one milestone.`);\r\n const title = String(x.title ?? '').trim().slice(0, 120);\r\n if (!title) throw new Error('An issue needs a title.');\r\n const slug = specialtySlug(x.specialty);\r\n const body = `${String(x.body ?? '').trim()}\\n\\n---\\n_Filed by ${this.ceo().name}, the cubefarm CEO._`;\r\n const n = await this.backend.createIssue(repo.fullName, title, body, slug ? [specialtyLabel(slug)] : []);\r\n this.ceoIssues.filed++;\r\n this.ceoIssues.repos.add(repo.id);\r\n return `Filed #${n} on floor ${repo.floor}: ${title}${slug ? ` (routed to ${slug})` : ''}.`;\r\n }\r\n}\r\n", "import { createSdkMcpServer, tool, type McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';\r\nimport { z } from 'zod';\r\nimport type { CeoJobKind } from '../shared/types.ts';\r\n\r\n// The CEO: a Claude Code session in the lobby that runs the company instead of writing code.\r\n// It studies each floor's repo, shapes the team (hire / let-go proposals the manager approves),\r\n// plans work as GitHub issues, and writes each floor's QA brief. Everything it changes goes\r\n// through the office tools below, so the swarm stays the single source of truth.\r\n\r\nexport interface CeoJob {\r\n kind: CeoJobKind;\r\n repoId?: string; // onboard / plan\r\n text?: string; // chat: the manager's message(s)\r\n at: number;\r\n}\r\n\r\n/** What the CEO's tools do. Implemented by the swarm; errors are returned to the CEO as tool errors. */\r\nexport interface OfficeHandlers {\r\n companyStatus(): string;\r\n agentDetail(a: { agent_id: string }): string;\r\n setFloorProfile(a: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }): string;\r\n updateJob(a: { agent_id: string; title?: string; specialty?: string; job_description?: string }): string;\r\n proposeHire(a: {\r\n floor: number;\r\n role: 'dev' | 'qa';\r\n title: string;\r\n specialty: string;\r\n job_description: string;\r\n reason: string;\r\n model?: string;\r\n effort?: string;\r\n }): string;\r\n proposeLetGo(a: { agent_id: string; reason: string }): string;\r\n fileIssue(a: { floor: number; title: string; body: string; specialty?: string }): Promise<string>;\r\n}\r\n\r\nexport interface OfficeTools {\r\n server: McpSdkServerConfigWithInstance;\r\n /** Run a tool without a model in the loop (the demo CEO). */\r\n call(name: string, args: Record<string, unknown>): Promise<string>;\r\n}\r\n\r\nconst EFFORT = z.enum(['low', 'medium', 'high', 'xhigh', 'max']);\r\n\r\nexport function createOfficeTools(h: OfficeHandlers): OfficeTools {\r\n const run = async (fn: () => string | Promise<string>) => {\r\n try {\r\n return { content: [{ type: 'text' as const, text: await fn() }] };\r\n } catch (err) {\r\n return { content: [{ type: 'text' as const, text: `Refused: ${(err as Error).message}` }], isError: true };\r\n }\r\n };\r\n const defs = [\r\n tool(\r\n 'company_status',\r\n 'Everything about the company right now: settings, every floor (repo, clone path, brief, profile, QA brief), its team, backlog, pull requests and QA, pending proposals and recent decisions by the manager. Call this first.',\r\n {},\r\n () => run(() => h.companyStatus()),\r\n ),\r\n tool(\r\n 'agent_detail',\r\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.\",\r\n { agent_id: z.string().describe('An id (or name) from company_status') },\r\n (a) => run(() => h.agentDetail(a)),\r\n ),\r\n tool(\r\n 'set_floor_profile',\r\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.\",\r\n {\r\n floor: z.number().int().describe('Floor number'),\r\n summary: z.string().max(140).optional().describe('e.g. \"3D browser game \u00B7 Three.js + Vite + TypeScript\"'),\r\n qa_brief: z.string().max(2500).optional().describe('What QA must check on every PR for this project, as short bullet points'),\r\n preview_command: z\r\n .string()\r\n .max(2000)\r\n .optional()\r\n .describe(\r\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.',\r\n ),\r\n // Not z.record(): the SDK can't turn it into JSON Schema, and one bad tool empties the whole tools/list.\r\n preview_env: z\r\n .object({})\r\n .catchall(z.string())\r\n .optional()\r\n .describe('Extra environment variables for the preview; {port} and {tmp} are replaced in the values. Replaces the whole set.'),\r\n },\r\n (a) => run(() => h.setFloorProfile(a)),\r\n ),\r\n tool(\r\n 'update_job',\r\n \"Change an existing agent's job title, specialty or job description so it fits the project. Takes effect from their next task.\",\r\n {\r\n agent_id: z.string(),\r\n title: z.string().max(60).optional(),\r\n specialty: z.string().max(24).optional().describe('Short lowercase slug, e.g. \"graphics\"; \"\" for a generalist'),\r\n job_description: z.string().max(2500).optional(),\r\n },\r\n (a) => run(() => h.updateJob(a)),\r\n ),\r\n tool(\r\n 'propose_hire',\r\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).',\r\n {\r\n floor: z.number().int(),\r\n role: z.enum(['dev', 'qa']).describe('dev = builds issues into pull requests; qa = tests pull requests'),\r\n title: z.string().max(60).describe('Specific job title, e.g. \"Three.js graphics engineer\"'),\r\n specialty: z.string().max(24).describe('Short lowercase slug used to label issues swarm:<specialty>, e.g. \"graphics\"'),\r\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.'),\r\n reason: z.string().max(600).describe('Why the floor needs them now. The manager reads this.'),\r\n model: z.string().optional().describe('Leave out to use the default model'),\r\n effort: EFFORT.optional().describe('Leave out to use the default effort'),\r\n },\r\n (a) => run(() => h.proposeHire(a)),\r\n ),\r\n tool(\r\n 'propose_let_go',\r\n 'Propose letting an agent go (overstaffed floor, specialty no longer needed). The manager decides.',\r\n { agent_id: z.string(), reason: z.string().max(600) },\r\n (a) => run(() => h.proposeLetGo(a)),\r\n ),\r\n tool(\r\n 'file_issue',\r\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.',\r\n {\r\n floor: z.number().int(),\r\n title: z.string().max(120),\r\n body: z.string().max(6000).describe('Context, what to build, acceptance criteria'),\r\n specialty: z.string().max(24).optional(),\r\n },\r\n (a) => run(() => h.fileIssue(a)),\r\n ),\r\n ];\r\n const server = createSdkMcpServer({ name: 'office', version: '1.0.0', tools: defs });\r\n return {\r\n server,\r\n async call(name, args) {\r\n const def = defs.find((d) => d.name === name);\r\n if (!def) throw new Error(`No office tool ${name}`);\r\n const res = (await def.handler(args as never, undefined)) as { content: { text?: string }[] };\r\n return res.content.map((c) => c.text ?? '').join('\\n');\r\n },\r\n };\r\n}\r\n\r\n// ---------- prompts ----------\r\n\r\nexport function ceoSystemPrompt(o: {\r\n name: string;\r\n company: string;\r\n manager: string;\r\n notesFile: string;\r\n sessionLimit: number;\r\n teamCap: number;\r\n hiring: 'approve' | 'auto';\r\n}) {\r\n const manager = o.manager ? `the manager, ${o.manager}` : 'the human manager';\r\n return [\r\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.`,\r\n `Every floor of the building is one GitHub repository with its own team of Claude Code 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.`,\r\n '',\r\n 'Your job is to run the company, not to write code:',\r\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.',\r\n `- Shape each floor's team. Propose specialists with a specific title and a job description written for this project. Keep teams lean: every agent shares one Claude 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. Propose letting people go when a floor is clearly overstaffed or a specialty is no longer needed.`,\r\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.\",\r\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).\",\r\n '',\r\n 'How you work:',\r\n '- Call mcp__office__company_status first. It lists every floor, its clone path, team, backlog, pull requests and your pending proposals.',\r\n '- Read the repositories through their clone paths with Read, Glob and Grep. They are read-only to you. You cannot run shell commands.',\r\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.`,\r\n '- Change things only through the mcp__office__ tools.',\r\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.\",\r\n '',\r\n 'Rules:',\r\n '- Every floor keeps at least one QA tester.',\r\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.',\r\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.',\r\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.'}`,\r\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. File at most 12 issues per job.',\r\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.',\r\n ].join('\\n');\r\n}\r\n\r\nexport function ceoJobPrompt(job: CeoJob, floor: { floor: number; fullName: string; clone: string; mission: string; backlog: number } | null): string {\r\n switch (job.kind) {\r\n case 'onboard':\r\n if (!floor) return 'A floor was added but has since been removed. Reply \"Nothing to do.\"';\r\n return [\r\n `Floor ${floor.floor} (${floor.fullName}) just joined the company. Its read-only clone is at ${floor.clone}.`,\r\n 'Study it: README, package manifest, source layout, tests, and how far along it is. Then:',\r\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.\",\r\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).',\r\n '3. Propose the hires this project needs. Usually two to four developers with distinct specialties is plenty.',\r\n floor.mission\r\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.`}`\r\n : floor.backlog === 0\r\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.'\r\n : `4. There are ${floor.backlog} open issues. Label nothing retroactively; just make sure the team can cover them.`,\r\n ].join('\\n');\r\n case 'plan':\r\n if (!floor) return 'A floor you were asked to plan has been removed. Reply \"Nothing to do.\"';\r\n return [\r\n `The manager has a brief for floor ${floor.floor} (${floor.fullName}, clone at ${floor.clone}):`,\r\n `\"\"\"${floor.mission}\"\"\"`,\r\n '',\r\n 'Plan the next milestone toward it:',\r\n `- Read the current code and the ${floor.backlog} open issues first, so you build on what exists and do not duplicate anything.`,\r\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.',\r\n '- File the issues, each routed to a specialty.',\r\n '- Make sure the floor has the specialists those issues need; propose hires if not.',\r\n '- Update the floor profile and QA brief if the brief changes what the project is.',\r\n ].join('\\n');\r\n case 'review':\r\n return [\r\n 'Periodic review of the company. For every floor, look at:',\r\n '- floors without a profile or QA brief: study them and write one',\r\n '- backlog against the team (capacity): fewer issues ready to start than free developers, long dependency chains, a specialty with a long queue',\r\n '- pull requests stuck in QA or marked as needing a human',\r\n '- floors with a brief and an empty backlog: plan the next milestone',\r\n 'Propose hires or let-gos only when clearly justified. If nothing needs doing, reply with one short sentence saying so.',\r\n ].join('\\n');\r\n case 'chat':\r\n return `Message from the manager (they're reading your reply on their phone):\\n${job.text ?? ''}`;\r\n }\r\n}\r\n\r\nexport function jobLabel(job: CeoJob, floor: { floor: number; fullName: string } | null) {\r\n const where = floor ? `floor ${floor.floor} \u00B7 ${floor.fullName.split('/')[1] ?? floor.fullName}` : 'a removed floor';\r\n switch (job.kind) {\r\n case 'onboard':\r\n return `Onboarding ${where}`;\r\n case 'plan':\r\n return `Planning ${where}`;\r\n case 'review':\r\n return 'Reviewing the company';\r\n case 'chat':\r\n return 'Replying to you';\r\n }\r\n}\r\n\r\n/** Short lowercase slug for a specialty (\"Three.js graphics\" -> \"three-js-graphics\"). */\r\nexport function specialtySlug(s: string | undefined) {\r\n const slug = String(s ?? '')\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, '-')\r\n .replace(/^-|-$/g, '')\r\n .slice(0, 24);\r\n return slug === 'skip' ? '' : slug;\r\n}\r\n\r\nexport const specialtyLabel = (slug: string) => `swarm:${slug}`;\r\n", "/** An error the REST layer turns into this status with a JSON { error } body. */\r\nexport class HttpError extends Error {\r\n constructor(\r\n public status: number,\r\n message: string,\r\n ) {\r\n super(message);\r\n }\r\n}\r\n", "import type { Backend } from './backend.ts';\r\nimport { PORT } from './config.ts';\r\nimport { HttpError } from './httpError.ts';\r\nimport { PREVIEW_SLUG, portOpen, type PreviewHandle } from './previewRunner.ts';\r\nimport type { PreviewConfig, PreviewStatus, PreviewView, PullInfo } from '../shared/types.ts';\r\n\r\n// One preview per floor: the floor's app, run from its own worktree on a port reserved for the floor.\r\n// Only the config is persisted; after a restart every preview reads 'stopped'.\r\n\r\n/** What the previews need to know about a floor. */\r\nexport interface PreviewFloor {\r\n id: string;\r\n fullName: string;\r\n defaultBranch: string;\r\n floor: number;\r\n preview: PreviewConfig;\r\n}\r\n\r\ninterface Run {\r\n status: PreviewStatus;\r\n port: number | null; // the port of the current or last run\r\n ref: string | null;\r\n pr: number | null;\r\n commit: string | null;\r\n startedAt: number | null;\r\n error: string | null;\r\n log: string[];\r\n handle: PreviewHandle | null;\r\n gen: number; // bumped by every start / stop; callbacks from older runs are ignored\r\n}\r\n\r\nconst PREVIEW_BASE_PORT = 6300;\r\nconst LOG_KEEP = 200;\r\nconst LOG_VIEW = 40;\r\nconst ACTIVE: PreviewStatus[] = ['preparing', 'installing', 'starting', 'running'];\r\n\r\n/** Never the office itself, the other office port, or the agents' range. */\r\nconst forbidden = (p: number) => p === PORT || p === 4317 || p === 5317 || (p >= 5200 && p <= 5899);\r\n\r\nexport const DEFAULT_PREVIEW: PreviewConfig = { command: null, env: {} };\r\n\r\n/** Check a previewCommand / previewEnv patch; throws 400 on bad input. undefined: not in the patch. */\r\nexport function parsePreviewPatch(command: unknown, env: unknown): Partial<PreviewConfig> {\r\n const out: Partial<PreviewConfig> = {};\r\n if (command !== undefined) {\r\n if (command !== null && typeof command !== 'string') throw new HttpError(400, 'previewCommand must be a string or null');\r\n const c = (command ?? '').trim();\r\n if (c.length > 2000) throw new HttpError(400, 'previewCommand is too long');\r\n out.command = c || null;\r\n }\r\n if (env !== undefined) {\r\n if (env === null) out.env = {};\r\n else {\r\n if (typeof env !== 'object' || Array.isArray(env)) throw new HttpError(400, 'previewEnv must be an object of string values');\r\n const entries = Object.entries(env as Record<string, unknown>);\r\n if (entries.length > 50) throw new HttpError(400, 'previewEnv has too many variables');\r\n for (const [k, v] of entries) {\r\n if (typeof v !== 'string') throw new HttpError(400, `previewEnv.${k} must be a string`);\r\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) throw new HttpError(400, `\"${k}\" is not a valid environment variable name`);\r\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`);\r\n if (v.length > 4000) throw new HttpError(400, `previewEnv.${k} is too long`);\r\n }\r\n out.env = Object.fromEntries(entries) as Record<string, string>;\r\n }\r\n }\r\n return out;\r\n}\r\n\r\nexport class Previews {\r\n private runs = new Map<string, Run>();\r\n private hasDefault = new Map<string, boolean>(); // floor id -> package.json in its checkout\r\n private emitTimers = new Map<string, NodeJS.Timeout>();\r\n\r\n constructor(\r\n private backend: Backend,\r\n private hooks: { emit(repoId: string): void; pulls(repoId: string): PullInfo[] },\r\n ) {}\r\n\r\n private run(id: string): Run {\r\n let r = this.runs.get(id);\r\n if (!r) {\r\n r = { status: 'stopped', port: null, ref: null, pr: null, commit: null, startedAt: null, error: null, log: [], handle: null, gen: 0 };\r\n this.runs.set(id, r);\r\n }\r\n return r;\r\n }\r\n\r\n /** The floor's reserved port: 6300 + floor, moved up by 100 while it clashes with the office or another preview. */\r\n portFor(f: PreviewFloor): number {\r\n const active = this.runs.get(f.id);\r\n if (active?.port && ACTIVE.includes(active.status)) return active.port;\r\n const taken = new Set([...this.runs.entries()].filter(([id, r]) => id !== f.id && r.port && ACTIVE.includes(r.status)).map(([, r]) => r.port!));\r\n let p = PREVIEW_BASE_PORT + f.floor;\r\n while (forbidden(p) || taken.has(p)) p += 100;\r\n return p;\r\n }\r\n\r\n view(f: PreviewFloor): PreviewView {\r\n const r = this.runs.get(f.id);\r\n let status: PreviewStatus = r?.status ?? 'stopped';\r\n if (status === 'stopped' && !f.preview.command && this.hasDefault.get(f.id) === false) status = 'unconfigured';\r\n const port = r?.port ?? this.portFor(f);\r\n return {\r\n status,\r\n port,\r\n url: status === 'running' ? `http://localhost:${port}/` : null,\r\n ref: r?.ref ?? null,\r\n pr: r?.pr ?? null,\r\n commit: r?.commit ?? null,\r\n startedAt: r?.startedAt ?? null,\r\n error: r?.error ?? null,\r\n logTail: (r?.log ?? []).slice(-LOG_VIEW),\r\n };\r\n }\r\n\r\n /** Re-check whether a floor without a command has a package.json to fall back on. */\r\n async refreshDefault(f: PreviewFloor) {\r\n const has = await this.backend.previews.hasDefault(f.fullName).catch(() => true);\r\n if (this.hasDefault.get(f.id) === has) return;\r\n this.hasDefault.set(f.id, has);\r\n this.hooks.emit(f.id);\r\n }\r\n\r\n /** Start the floor's preview on the default branch or an open PR, replacing whatever it is running now. */\r\n async start(f: PreviewFloor, title: string, pr?: number | null): Promise<PreviewView> {\r\n if (pr !== undefined && pr !== null && (!Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, `Invalid pull request number: ${pr}`);\r\n if (pr) await this.checkOpen(f, pr);\r\n const r = this.run(f.id);\r\n const gen = ++r.gen;\r\n await this.halt(f, r);\r\n if (gen !== r.gen) return this.view(f); // another start or a stop came in meanwhile\r\n\r\n const port = this.portFor(f);\r\n const ref = pr ? `PR #${pr}` : f.defaultBranch;\r\n Object.assign(r, { port, ref, pr: pr ?? null, commit: null, startedAt: Date.now(), error: null, log: [] });\r\n if (await portOpen(port)) {\r\n if (gen !== r.gen) return this.view(f);\r\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.` });\r\n this.hooks.emit(f.id);\r\n throw new HttpError(409, r.error!);\r\n }\r\n if (gen !== r.gen) return this.view(f);\r\n r.status = 'preparing';\r\n this.hooks.emit(f.id);\r\n\r\n const live = () => gen === r.gen;\r\n r.handle = this.backend.previews.start(\r\n { fullName: f.fullName, defaultBranch: f.defaultBranch, pr: pr ?? null, port, command: f.preview.command, env: { ...f.preview.env }, title: `${title} \u00B7 ${ref}` },\r\n {\r\n status: (s) => {\r\n if (!live()) return;\r\n r.status = s;\r\n this.hooks.emit(f.id);\r\n },\r\n commit: (sha) => {\r\n if (!live()) return;\r\n r.commit = sha || null;\r\n this.hooks.emit(f.id);\r\n },\r\n log: (lines) => {\r\n if (!live()) return;\r\n r.log.push(...lines.map((l) => l.slice(0, 500)));\r\n if (r.log.length > LOG_KEEP) r.log.splice(0, r.log.length - LOG_KEEP);\r\n this.emitSoon(f.id);\r\n },\r\n failed: (message, unconfigured) => {\r\n if (!live()) return;\r\n r.handle = null;\r\n Object.assign(r, { status: unconfigured ? 'unconfigured' : 'error', error: message });\r\n if (unconfigured) this.hasDefault.set(f.id, false);\r\n this.hooks.emit(f.id);\r\n // Anything the app left behind in its worktree or on its port goes too.\r\n void this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, port).catch(() => undefined);\r\n },\r\n },\r\n );\r\n return this.view(f);\r\n }\r\n\r\n /** Stop the floor's preview and free its port. */\r\n async stop(f: PreviewFloor): Promise<PreviewView> {\r\n const r = this.run(f.id);\r\n r.gen++;\r\n await this.halt(f, r);\r\n Object.assign(r, { status: 'stopped', error: null, startedAt: null });\r\n this.hooks.emit(f.id);\r\n return this.view(f);\r\n }\r\n\r\n /** The floor is leaving the building: stop its preview and remove the preview worktree. */\r\n async remove(f: PreviewFloor) {\r\n const r = this.runs.get(f.id);\r\n if (r) {\r\n r.gen++;\r\n await this.halt(f, r);\r\n }\r\n this.runs.delete(f.id);\r\n this.hasDefault.delete(f.id);\r\n clearTimeout(this.emitTimers.get(f.id));\r\n await this.backend.removeDesk(f.fullName, PREVIEW_SLUG).catch(() => undefined);\r\n }\r\n\r\n /** Server shutdown: stop every running preview. */\r\n async stopAll(floors: PreviewFloor[]) {\r\n await Promise.all(\r\n floors.map((f) => {\r\n const r = this.runs.get(f.id);\r\n if (!r) return;\r\n r.gen++;\r\n return this.halt(f, r);\r\n }),\r\n );\r\n }\r\n\r\n /** Server start: nothing is running yet, so anything alive in a preview worktree or on a preview port is an orphan. */\r\n async clearOrphans(floors: PreviewFloor[]) {\r\n await Promise.all(floors.map((f) => this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, this.portFor(f)).catch(() => undefined)));\r\n }\r\n\r\n private async halt(f: PreviewFloor, r: Run) {\r\n const handle = r.handle;\r\n r.handle = null;\r\n if (!handle) return;\r\n await handle.stop().catch(() => undefined);\r\n if (!r.port) return;\r\n await this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, r.port).catch(() => undefined);\r\n // Windows can take a moment to let go of a killed process's socket.\r\n for (let i = 0; i < 20 && (await portOpen(r.port)); i++) await new Promise((res) => setTimeout(res, 250));\r\n }\r\n\r\n private async checkOpen(f: PreviewFloor, pr: number) {\r\n const known = this.hooks.pulls(f.id).find((p) => p.number === pr);\r\n const state = known?.state ?? (await this.backend.prDetails(f.fullName, pr).then((d) => d.state).catch(() => null));\r\n if (!state) throw new HttpError(404, `${f.fullName} has no pull request #${pr}`);\r\n if (state !== 'OPEN') throw new HttpError(400, `Pull request #${pr} is ${state.toLowerCase()}, not open`);\r\n }\r\n\r\n /** Log lines arrive in bursts (npm install); send them at most once a second. */\r\n private emitSoon(id: string) {\r\n if (this.emitTimers.has(id)) return;\r\n this.emitTimers.set(\r\n id,\r\n setTimeout(() => {\r\n this.emitTimers.delete(id);\r\n if (this.runs.has(id)) this.hooks.emit(id);\r\n }, 1000),\r\n );\r\n }\r\n}\r\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\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", "// Types shared between the swarm server and the 3D client.\r\n\r\nexport type AgentStatus =\r\n | 'idle' // at desk, nothing assigned\r\n | 'preparing' // setting up the git worktree\r\n | 'working' // Claude Code session running\r\n | 'done' // finished, PR opened (or finished without one)\r\n | 'error' // session failed\r\n | 'stopped'; // manager stopped it\r\n\r\nexport type LogKind = 'text' | 'tool' | 'result' | 'system' | 'error' | 'manager' | 'done' | 'thinking';\r\n\r\nexport interface LogLine {\r\n id: number;\r\n t: number; // epoch ms\r\n kind: LogKind;\r\n text: string;\r\n tool?: string; // tool name for kind === 'tool'\r\n}\r\n\r\nexport interface IssueInfo {\r\n number: number;\r\n title: string;\r\n body: string;\r\n url: string;\r\n labels: string[];\r\n createdAt: string;\r\n}\r\n\r\nexport interface PullInfo {\r\n number: number;\r\n title: string;\r\n url: string;\r\n headRefName: string;\r\n state: 'OPEN' | 'CLOSED' | 'MERGED';\r\n isDraft: boolean;\r\n mergeable: string; // MERGEABLE | CONFLICTING | UNKNOWN\r\n reviewDecision: string | null;\r\n closesIssues: number[];\r\n createdAt: string;\r\n mergedAt: string | null;\r\n additions: number;\r\n deletions: number;\r\n checks: 'pending' | 'passing' | 'failing' | 'none';\r\n headSha: string;\r\n mergeState: string; // GitHub's mergeStateStatus: CLEAN | BEHIND | BLOCKED | DIRTY | UNSTABLE | DRAFT | UNKNOWN \u2026\r\n failedChecks: { name: string; url: string | null }[];\r\n pendingChecks: string[];\r\n}\r\n\r\nexport interface RepoView {\r\n id: string; // \"owner/name\"\r\n fullName: string;\r\n description: string;\r\n url: string;\r\n defaultBranch: string;\r\n floor: number; // 1-based floor number in the building\r\n color: string; // accent color for the floor\r\n autoAssign: boolean;\r\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\r\n folderSync: string | null; // how the floor's main checkout stands against GitHub: \"in sync\", \"updated to abc1234\", \"2 behind: local changes\" \u2026\r\n browserTesting: boolean;\r\n links: string[]; // ids of related repos this floor's agents can read for context\r\n mission: string; // the manager's brief: what this floor is building\r\n summary: string; // the CEO's one-line read of the project, e.g. \"3D browser game \u00B7 Three.js + Vite\"\r\n qaBrief: string; // how QA should test this kind of project (written by the CEO, editable)\r\n localPath: string | null; // the manager's own project folder, when the floor lives in one\r\n checkoutPath: string; // where the floor's main checkout is on disk (localPath, or a clone the office manages)\r\n cloneStatus: 'pending' | 'cloning' | 'ready' | 'error';\r\n cloneError?: string;\r\n issues: IssueInfo[]; // open issues\r\n pulls: PullInfo[]; // open + recently merged PRs\r\n lastSync: number | null;\r\n syncError?: string;\r\n previewConfig: PreviewConfig;\r\n preview: PreviewView;\r\n}\r\n\r\n/**\r\n * How a floor's app is run for the preview monitor. {port} and {tmp} are replaced in the command and env values;\r\n * PORT={port} is always set. command null: npm run dev, else start, else preview from package.json.\r\n */\r\nexport interface PreviewConfig {\r\n command: string | null;\r\n env: Record<string, string>;\r\n}\r\n\r\nexport type PreviewStatus =\r\n | 'unconfigured' // no command and no package.json\r\n | 'stopped'\r\n | 'preparing' // checking out the ref in the preview worktree\r\n | 'installing' // npm ci / npm install\r\n | 'starting' // command started, waiting for the port\r\n | 'running'\r\n | 'error';\r\n\r\n/** The floor's running app, served from its own worktree on a port reserved for the floor. */\r\nexport interface PreviewView {\r\n status: PreviewStatus;\r\n port: number;\r\n url: string | null; // set while running\r\n ref: string | null; // the default branch's name, or \"PR #n\"\r\n pr: number | null;\r\n commit: string | null; // short sha\r\n startedAt: number | null;\r\n error: string | null;\r\n logTail: string[]; // the last 40 lines of install / app output\r\n}\r\n\r\n/** A folder in the manager's projects folder, as offered when adding a floor. */\r\nexport interface ProjectFolderView {\r\n name: string;\r\n path: string;\r\n git: boolean;\r\n github: string | null; // owner/name of its GitHub origin\r\n floor: number | null; // already a floor in the office\r\n}\r\n\r\n/** dev and qa are the two pipeline lanes on every floor; the one CEO works in the lobby and runs the company. */\r\nexport type AgentRole = 'dev' | 'qa' | 'ceo';\r\n\r\n/** Fixed id of the CEO agent. */\r\nexport const CEO_ID = 'ceo';\r\n\r\n/** How the cartoon character is drawn. Picked from the agent's name when hired; the manager can change it. */\r\nexport type AgentLook = 'feminine' | 'masculine';\r\n\r\n/** What an agent is currently doing: implementing an issue, testing a PR, or fixing a PR after QA. */\r\nexport type AgentTask = 'issue' | 'qa' | 'fix';\r\n\r\nexport interface AgentView {\r\n id: string;\r\n name: string;\r\n repoId: string;\r\n role: AgentRole;\r\n title: string; // job title, e.g. \"Three.js graphics engineer\" ('' = plain developer / QA tester)\r\n specialty: string; // routes issues labelled swarm:<specialty> to this agent first ('' = generalist)\r\n brief: string; // job description for this project, added to the agent's instructions\r\n hiredBy: 'manager' | 'ceo';\r\n look: AgentLook;\r\n task: AgentTask | null;\r\n desk: number; // desk slot on the floor (dev desks and QA lab stations are numbered separately)\r\n color: string; // shirt color\r\n hair: string; // hair color\r\n skin: string;\r\n model: string; // '' = use the swarm default model, or a model id / alias\r\n effort: EffortLevel | ''; // '' = use the swarm default effort\r\n status: AgentStatus;\r\n issueNumber: number | null; // devs: the issue being worked on\r\n issueTitle: string | null; // devs: issue title; QA: title of the PR under test\r\n branch: string | null;\r\n prNumber: number | null; // devs: the PR they opened; QA: the PR under test\r\n prUrl: string | null;\r\n currentTool: string | null;\r\n startedAt: number | null;\r\n endedAt: number | null;\r\n costUsd: number;\r\n turns: number;\r\n browserUrl: string | null;\r\n hasScreenshot: boolean;\r\n screenshotAt: number | null;\r\n lastError: string | null;\r\n log: LogLine[]; // tail of the terminal log (full buffer on snapshot)\r\n}\r\n\r\nexport type EffortLevel = 'low' | 'medium' | 'high' | 'xhigh' | 'max';\r\n\r\nexport type QaStatus =\r\n | 'queued' // waiting for a free QA tester\r\n | 'testing' // a QA tester is on it\r\n | 'passed' // ready to merge\r\n | 'failed' // failed; waiting for the dev who wrote it to be free\r\n | 'fixing' // the dev is fixing what QA found\r\n | 'needs-human'; // failed too many rounds, or nobody can fix it automatically\r\n\r\nexport interface QaCheck {\r\n name: string;\r\n result: 'pass' | 'fail' | 'skip';\r\n details: string;\r\n}\r\n\r\nexport interface QaView {\r\n repoId: string;\r\n prNumber: number;\r\n status: QaStatus;\r\n round: number; // 1-based QA round\r\n devAgentId: string | null; // who wrote it (null for PRs opened outside the swarm)\r\n qaAgentId: string | null; // who is testing / last tested it\r\n summary: string | null; // latest QA summary\r\n checks: QaCheck[];\r\n commentUrl: string | null; // the PR comment with the latest QA report\r\n mergeNote: string | null; // where auto-merge stands once QA passed, e.g. \"waiting for checks: Vercel\"\r\n updatedAt: number;\r\n}\r\n\r\nexport interface SwarmSettings {\r\n sessionLimit: number; // most Claude Code sessions running at once; 0 = no limit\r\n defaultModel: string;\r\n defaultEffort: EffortLevel;\r\n permissionMode: 'guarded' | 'bypass';\r\n hiring: 'approve' | 'auto'; // CEO proposals wait for the manager, or go through while the floor is under teamCap\r\n teamCap: number; // most agents per floor the CEO may reach without the manager's approval (auto mode)\r\n ceoHeartbeatMin: number; // minutes between the CEO's periodic reviews; 0 = off\r\n managerName: string; // what the office calls you\r\n companyName: string;\r\n projectsDir: string; // where your project folders live; new projects are created here\r\n setupDone: boolean; // the first-run setup wizard has been completed or skipped\r\n tutorialStep: number; // index of the current tutorial step; -1 when finished or skipped\r\n}\r\n\r\n/** A CEO proposal to hire someone or let someone go. The manager (the board) decides. */\r\nexport interface HireRequestView {\r\n id: string;\r\n kind: 'hire' | 'let-go';\r\n repoId: string;\r\n role: 'dev' | 'qa';\r\n agentId: string | null; // let-go: who; hire: who was hired once approved\r\n name: string; // the candidate's name (let-go: the agent's name)\r\n title: string;\r\n specialty: string;\r\n brief: string;\r\n reason: string;\r\n model: string;\r\n effort: EffortLevel | '';\r\n look: AgentLook;\r\n color: string;\r\n hair: string;\r\n skin: string;\r\n status: 'pending' | 'approved' | 'rejected';\r\n note: string; // the manager's reason when rejecting\r\n createdAt: number;\r\n decidedAt: number | null;\r\n decidedBy: 'manager' | 'auto' | null;\r\n}\r\n\r\n/** One message in the phone thread between the manager and the CEO. */\r\nexport interface PhoneMessage {\r\n id: number;\r\n from: 'ceo' | 'manager' | 'office'; // office = notes from the building itself (decisions, errors)\r\n text: string;\r\n at: number;\r\n requestId?: string; // a hire / let-go proposal this message is about\r\n}\r\n\r\nexport type CeoJobKind = 'onboard' | 'plan' | 'review' | 'chat';\r\n\r\nexport interface CeoInfo {\r\n queue: { kind: CeoJobKind; label: string }[]; // jobs waiting for the CEO\r\n job: { kind: CeoJobKind; label: string } | null; // what the CEO is doing now\r\n lastReviewAt: number | null;\r\n nextReviewAt: number | null; // null when the heartbeat is off\r\n}\r\n\r\nexport interface WorldSnapshot {\r\n user: string | null; // gh login\r\n ghReady: boolean;\r\n ghError?: string;\r\n demo: boolean;\r\n workspaceRoot: string;\r\n settings: SwarmSettings;\r\n repos: RepoView[];\r\n agents: AgentView[];\r\n qa: QaView[];\r\n requests: HireRequestView[];\r\n ceo: CeoInfo;\r\n messages: PhoneMessage[];\r\n phoneReadAt: number; // CEO messages newer than this are unread\r\n}\r\n\r\nexport type ServerEvent =\r\n | { type: 'snapshot'; data: WorldSnapshot }\r\n | { type: 'repo'; repo: RepoView }\r\n | { type: 'repoRemoved'; repoId: string }\r\n | { type: 'agent'; agent: Omit<AgentView, 'log'> }\r\n | { type: 'agentRemoved'; agentId: string }\r\n | { type: 'log'; agentId: string; lines: LogLine[] }\r\n | { type: 'screen'; agentId: string; url: string | null; at: number }\r\n | { type: 'qa'; qa: QaView }\r\n | { type: 'qaRemoved'; repoId: string; prNumber: number }\r\n | { type: 'settings'; settings: SwarmSettings }\r\n | { type: 'request'; request: HireRequestView }\r\n | { type: 'ceo'; ceo: CeoInfo }\r\n | { type: 'message'; message: PhoneMessage }\r\n | { type: 'phoneRead'; at: number }\r\n | { type: 'toast'; level: 'info' | 'success' | 'error'; text: string };\r\n\r\nexport interface GhRepoSummary {\r\n nameWithOwner: string;\r\n description: string;\r\n visibility: string;\r\n updatedAt: string;\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": ["http", "path", "fs", "repos", "fs", "path", "path", "fs", "path", "rel", "path", "tool", "fs", "path", "fs", "path", "code", "crypto", "path", "crypto", "path", "tool", "git", "server", "pending", "run", "fs", "path", "crypto", "run", "server", "path", "fs", "fs", "path", "repoId", "crypto", "issue", "failed", "now", "pick", "repos", "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/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/httpError.ts", "../server/mergeGate.ts", "../server/previews.ts", "../server/pacing.ts", "../server/terminal.ts", "../shared/models.ts", "../shared/types.ts"],
4
+ "sourcesContent": ["import http from 'node:http';\r\nimport path from 'node:path';\r\nimport fs from 'node:fs';\r\nimport express, { type NextFunction, type Request, type Response } from 'express';\r\nimport type { AddressInfo } from 'node:net';\r\nimport { WebSocketServer } from 'ws';\r\nimport { DEMO, PORT, STATE_FILE, WORKSPACE_ROOT } from './config.ts';\r\nimport { realBackend } from './backend.ts';\r\nimport { handleHook, handleMcp, setOfficeUrl } from './cliRunner.ts';\r\nimport { createDemoBackend } from './demo.ts';\r\nimport { underLauncher } from './officeUpdate.ts';\r\nimport { HttpError, Swarm } from './swarm.ts';\r\n\r\nconst swarm = new Swarm(DEMO ? createDemoBackend() : realBackend);\r\n// Sessions the office picks back up while it starts need the address their CLIs call back on before it listens.\r\nif (PORT) setOfficeUrl(`http://127.0.0.1:${PORT}`);\r\nawait swarm.init();\r\n\r\nconst app = express();\r\n// Agent CLIs calling back: hooks (a tool result can be a large screenshot, hence the limit) and the CEO's office tools.\r\n// The token in the path is the session's; unknown tokens get an empty answer.\r\napp.post('/api/hooks/:token', express.json({ limit: '64mb' }), (req, res) => void res.json(handleHook(String(req.params.token), req.body)));\r\napp.post('/api/mcp/:token', express.json({ limit: '4mb' }), (req, res, next) => void handleMcp(String(req.params.token), req, res).catch(next));\r\napp.all('/api/mcp/:token', (_req, res) => void res.status(405).set('Allow', 'POST').end());\r\napp.use(express.json({ limit: '1mb' }));\r\n\r\ntype Handler = (req: Request, res: Response) => Promise<unknown> | unknown;\r\nconst route = (fn: Handler) => async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n const out = await fn(req, res);\r\n if (!res.headersSent) res.json(out ?? { ok: true });\r\n } catch (err) {\r\n next(err);\r\n }\r\n};\r\nconst num = (v: unknown) => {\r\n const n = Number(v);\r\n if (!Number.isInteger(n) || n <= 0) throw new HttpError(400, `Invalid number: ${v}`);\r\n return n;\r\n};\r\nconst str = (v: unknown) => (typeof v === 'string' ? v : '');\r\n// Repo ids contain a slash (\"owner/name\"), so they travel URL-encoded as a single segment.\r\nconst repoId = (req: Request) => decodeURIComponent(String(req.params.repo));\r\n\r\napp.get('/api/state', route(() => swarm.snapshot()));\r\n\r\napp.get('/api/github/repos', route((req) => swarm.listGithubRepos(str(req.query.owner) || undefined)));\r\n\r\n// What happens once a project moves in: the CEO's brief, and whether work starts on its own.\r\nconst floorOptions = (req: Request) => ({ mission: str(req.body.mission), autoAssign: req.body.autoAssign === true });\r\n\r\napp.post('/api/repos', route((req) => swarm.connectRepo(str(req.body.fullName).trim(), floorOptions(req))));\r\n\r\n// Your projects folder\r\napp.get('/api/folders', route((req) => swarm.listProjectFolders(str(req.query.dir) || undefined)));\r\napp.post('/api/folders/connect', route((req) => swarm.connectFolder(str(req.body.path), floorOptions(req))));\r\napp.post(\r\n '/api/folders/publish',\r\n route((req) =>\r\n swarm.publishFolder(str(req.body.path), {\r\n ...floorOptions(req),\r\n name: str(req.body.name) || undefined,\r\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\r\n description: str(req.body.description),\r\n }),\r\n ),\r\n);\r\napp.post(\r\n '/api/setup',\r\n route((req) =>\r\n swarm.setup({\r\n managerName: str(req.body.managerName),\r\n companyName: str(req.body.companyName),\r\n hiring: str(req.body.hiring),\r\n ceoName: str(req.body.ceoName),\r\n ceoLook: str(req.body.ceoLook),\r\n ceoColor: str(req.body.ceoColor),\r\n }),\r\n ),\r\n);\r\napp.post(\r\n '/api/repos/new',\r\n route((req) =>\r\n swarm.createRepo(str(req.body.name).trim(), {\r\n ...floorOptions(req),\r\n description: str(req.body.description),\r\n visibility: req.body.visibility === 'public' ? 'public' : 'private',\r\n owner: str(req.body.owner).trim() || undefined,\r\n }),\r\n ),\r\n);\r\napp.patch('/api/repos/:repo', route((req) => swarm.updateRepo(repoId(req), req.body ?? {})));\r\napp.delete('/api/repos/:repo', route((req) => swarm.disconnectRepo(repoId(req))));\r\napp.post('/api/repos/:repo/sync', route((req) => swarm.syncRepo(repoId(req))));\r\napp.post('/api/repos/:repo/sync-folder', route((req) => swarm.syncFolderNow(repoId(req))));\r\napp.post(\r\n '/api/repos/:repo/issues',\r\n route(async (req) => ({\r\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),\r\n })),\r\n);\r\napp.post('/api/repos/:repo/plan', route((req) => swarm.planFloor(repoId(req), typeof req.body?.mission === 'string' ? req.body.mission : undefined)));\r\napp.post('/api/repos/:repo/onboard', route((req) => swarm.onboardFloor(repoId(req))));\r\n// The floor's app, for the preview monitor\r\napp.post(\r\n '/api/repos/:repo/preview',\r\n route((req) => {\r\n const pr = req.body?.pr;\r\n if (pr !== undefined && pr !== null && (typeof pr !== 'number' || !Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, 'pr must be a positive integer');\r\n return swarm.startPreview(repoId(req), pr ?? null);\r\n }),\r\n);\r\napp.delete('/api/repos/:repo/preview', route((req) => swarm.stopPreview(repoId(req))));\r\napp.post('/api/repos/:repo/pulls/:n/merge', route((req) => swarm.mergePull(repoId(req), num(req.params.n), req.body?.method ?? 'squash')));\r\napp.post('/api/repos/:repo/pulls/:n/close', route((req) => swarm.closePull(repoId(req), num(req.params.n))));\r\napp.post('/api/repos/:repo/pulls/:n/qa', route((req) => swarm.sendToQa(repoId(req), num(req.params.n))));\r\napp.post(\r\n '/api/repos/:repo/agents',\r\n route((req) =>\r\n swarm.hireAgent(repoId(req), {\r\n name: str(req.body.name),\r\n model: str(req.body.model),\r\n effort: str(req.body.effort),\r\n role: str(req.body.role),\r\n look: str(req.body.look),\r\n title: str(req.body.title),\r\n specialty: str(req.body.specialty),\r\n brief: str(req.body.brief),\r\n }),\r\n ),\r\n);\r\n\r\napp.patch('/api/agents/:id', route((req) => swarm.updateAgent(String(req.params.id), req.body ?? {})));\r\napp.delete('/api/agents/:id', route((req) => swarm.fireAgent(String(req.params.id))));\r\napp.post('/api/agents/:id/assign', route((req) => swarm.assign(String(req.params.id), num(req.body.issueNumber), str(req.body.note) || undefined)));\r\napp.post('/api/agents/:id/stop', route((req) => swarm.stopAgent(String(req.params.id))));\r\napp.post('/api/agents/:id/reset', route((req) => swarm.resetAgent(String(req.params.id))));\r\napp.post('/api/agents/:id/message', route((req) => swarm.message(String(req.params.id), str(req.body.text))));\r\napp.get('/api/agents/:id/screen', (req, res) => {\r\n const shot = swarm.screenshot(String(req.params.id));\r\n if (!shot) return void res.status(404).end();\r\n res.setHeader('Content-Type', shot.mime);\r\n res.setHeader('Cache-Control', 'no-store');\r\n res.end(shot.data);\r\n});\r\n\r\napp.patch('/api/settings', route((req) => swarm.updateSettings(req.body ?? {})));\r\n// The office's own update: Update now / Later\r\napp.post('/api/office/update', route((req) => swarm.updateOffice(req.body?.action)));\r\n\r\n// The CEO and the manager's phone\r\napp.post('/api/ceo/message', route((req) => swarm.messageCeo(str(req.body.text))));\r\napp.post('/api/ceo/review', route(() => swarm.requestReview()));\r\napp.post('/api/phone/read', route((req) => swarm.markPhoneRead(Number(req.body?.at) || Date.now())));\r\napp.post(\r\n '/api/requests/:id/approve',\r\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 })),\r\n);\r\napp.post('/api/requests/:id/reject', route((req) => swarm.rejectRequest(String(req.params.id), str(req.body?.note))));\r\n\r\n// Serve the built client: the published package, or `npm start` after `npm run build`.\r\nconst dist = path.resolve(import.meta.dirname, '../dist');\r\nif (fs.existsSync(dist)) {\r\n app.use(express.static(dist));\r\n app.get(/^(?!\\/api).*/, (_req, res) => res.sendFile(path.join(dist, 'index.html')));\r\n}\r\n\r\napp.use((err: unknown, _req: Request, res: Response, _next: NextFunction) => {\r\n // express.json() flags malformed bodies with a 4xx status of its own.\r\n const parserStatus = (err as { status?: unknown })?.status;\r\n const status = err instanceof HttpError ? err.status : typeof parserStatus === 'number' && parserStatus >= 400 && parserStatus < 500 ? parserStatus : 500;\r\n const message = err instanceof Error ? err.message : String(err);\r\n if (status >= 500) console.error(err);\r\n res.status(status).json({ error: message });\r\n});\r\n\r\nconst server = http.createServer(app);\r\n// Two sockets: /ws carries the office's state to every tab, /ws/term?agent=<id> one agent's terminal to whoever opened it.\r\nconst wss = new WebSocketServer({ noServer: true });\r\nconst terms = new WebSocketServer({ noServer: true });\r\nwss.on('connection', (ws) => swarm.addClient(ws));\r\nterms.on('connection', (ws, req) => swarm.attachTerminal(new URL(req.url ?? '', 'http://localhost').searchParams.get('agent') ?? '', ws));\r\nserver.on('upgrade', (req, socket, head) => {\r\n const { pathname } = new URL(req.url ?? '', 'http://localhost');\r\n const target = pathname === '/ws' ? wss : pathname === '/ws/term' ? terms : null;\r\n if (!target) return void socket.destroy();\r\n target.handleUpgrade(req, socket, head, (ws) => target.emit('connection', ws, req));\r\n});\r\n\r\nserver.listen(PORT, '127.0.0.1', () => {\r\n setOfficeUrl(`http://127.0.0.1:${(server.address() as AddressInfo).port}`);\r\n console.log(`\\n \uD83C\uDFE2 cubefarm on http://localhost:${PORT}${DEMO ? ' (DEMO MODE: fake GitHub + fake agents)' : ''}`);\r\n console.log(` state: ${STATE_FILE}`);\r\n console.log(` workspaces: ${WORKSPACE_ROOT}\\n`);\r\n});\r\n\r\n// Floors' apps don't outlive the office. (A hard kill skips this; the next start clears the orphans.) Agents' CLIs\r\n// carry on through a restart and stop when the office quits.\r\nlet closing = false;\r\nconst shutdown = (signal: string) => {\r\n if (closing) return;\r\n closing = true;\r\n console.log(`\\n ${signal}: stopping floor previews\u2026`);\r\n const force = setTimeout(() => process.exit(0), 15_000);\r\n void swarm\r\n .shutdown(signal === 'restart')\r\n .catch((err) => console.error(err))\r\n .finally(() => {\r\n clearTimeout(force);\r\n process.exit(0);\r\n });\r\n};\r\nprocess.once('SIGINT', () => shutdown('SIGINT'));\r\nprocess.once('SIGTERM', () => shutdown('SIGTERM'));\r\nprocess.once('SIGHUP', () => shutdown('SIGHUP')); // its terminal window closed (macOS, Linux; Windows' console too)\r\n// The launcher asks the office to stop: to restart it (an update, a code change) unless it says it's quitting.\r\nif (underLauncher()) {\r\n process.on('message', (msg) => {\r\n const m = msg as { type?: unknown; restart?: unknown } | null;\r\n if (m?.type === 'office:shutdown') shutdown(m.restart === false ? 'stop' : 'restart');\r\n });\r\n}\r\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// 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';\r\nimport type { GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\r\n\r\n// All GitHub access goes through the gh CLI so it reuses the user's existing `gh auth login`.\r\n\r\nexport async function currentUser(): Promise<string> {\r\n return gh(['api', 'user', '--jq', '.login']);\r\n}\r\n\r\nexport async function listMyRepos(owner?: string): Promise<GhRepoSummary[]> {\r\n const args = ['repo', 'list'];\r\n if (owner) args.push(owner);\r\n args.push('--limit', '200', '--json', 'nameWithOwner,description,visibility,updatedAt');\r\n const repos = await ghJson<GhRepoSummary[]>(args);\r\n return repos.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\r\n}\r\n\r\nexport interface RepoMeta {\r\n nameWithOwner: string;\r\n description: string;\r\n url: string;\r\n defaultBranch: string;\r\n}\r\n\r\nexport async function repoMeta(fullName: string): Promise<RepoMeta> {\r\n const raw = await ghJson<{ nameWithOwner: string; description: string | null; url: string; defaultBranchRef: { name: string } | null }>([\r\n 'repo',\r\n 'view',\r\n fullName,\r\n '--json',\r\n 'nameWithOwner,description,url,defaultBranchRef',\r\n ]);\r\n return {\r\n nameWithOwner: raw.nameWithOwner,\r\n description: raw.description ?? '',\r\n url: raw.url,\r\n defaultBranch: raw.defaultBranchRef?.name || 'main',\r\n };\r\n}\r\n\r\nexport async function listIssues(fullName: string): Promise<IssueInfo[]> {\r\n const raw = await ghJson<\r\n { number: number; title: string; body: string; url: string; labels: { name: string }[]; createdAt: string }[]\r\n >(['issue', 'list', '-R', fullName, '--state', 'open', '--limit', '100', '--json', 'number,title,body,url,labels,createdAt']);\r\n return raw\r\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 }))\r\n .sort((a, b) => a.number - b.number);\r\n}\r\n\r\ninterface RawPull {\r\n number: number;\r\n title: string;\r\n url: string;\r\n headRefName: string;\r\n state: 'OPEN' | 'CLOSED' | 'MERGED';\r\n isDraft: boolean;\r\n mergeable: string;\r\n reviewDecision: string | null;\r\n closingIssuesReferences: { number: number }[] | null;\r\n createdAt: string;\r\n mergedAt: string | null;\r\n additions: number;\r\n deletions: number;\r\n headRefOid: string;\r\n mergeStateStatus: string;\r\n // check runs (GitHub Actions\u2026) carry name/status/conclusion/detailsUrl; commit statuses (Vercel\u2026) carry context/state/targetUrl\r\n statusCheckRollup: { name?: string; context?: string; status?: string; conclusion?: string; state?: string; detailsUrl?: string; targetUrl?: string }[] | null;\r\n}\r\n\r\nconst PR_FIELDS =\r\n 'number,title,url,headRefName,headRefOid,state,isDraft,mergeable,mergeStateStatus,reviewDecision,closingIssuesReferences,createdAt,mergedAt,additions,deletions,statusCheckRollup';\r\n\r\ntype Check = NonNullable<RawPull['statusCheckRollup']>[number];\r\nconst BAD = ['FAILURE', 'ERROR', 'CANCELLED', 'TIMED_OUT', 'ACTION_REQUIRED', 'STARTUP_FAILURE'];\r\nconst failed = (c: Check) => BAD.includes(c.conclusion ?? '') || BAD.includes(c.state ?? '');\r\nconst pending = (c: Check) => (!!c.status && c.status !== 'COMPLETED') || c.state === 'PENDING' || c.state === 'EXPECTED';\r\nconst checkName = (c: Check) => c.name || c.context || 'check';\r\n\r\nfunction checksOf(rollup: RawPull['statusCheckRollup']): PullInfo['checks'] {\r\n if (!rollup || rollup.length === 0) return 'none';\r\n if (rollup.some(failed)) return 'failing';\r\n if (rollup.some(pending)) return 'pending';\r\n return 'passing';\r\n}\r\n\r\nfunction toPull(p: RawPull): PullInfo {\r\n return {\r\n number: p.number,\r\n title: p.title,\r\n url: p.url,\r\n headRefName: p.headRefName,\r\n state: p.state,\r\n isDraft: p.isDraft,\r\n mergeable: p.mergeable,\r\n reviewDecision: p.reviewDecision || null,\r\n closesIssues: (p.closingIssuesReferences ?? []).map((r) => r.number),\r\n createdAt: p.createdAt,\r\n mergedAt: p.mergedAt,\r\n additions: p.additions,\r\n deletions: p.deletions,\r\n checks: checksOf(p.statusCheckRollup),\r\n headSha: p.headRefOid,\r\n mergeState: p.mergeStateStatus || 'UNKNOWN',\r\n failedChecks: (p.statusCheckRollup ?? []).filter(failed).map((c) => ({ name: checkName(c), url: c.detailsUrl || c.targetUrl || null })),\r\n pendingChecks: (p.statusCheckRollup ?? []).filter(pending).map(checkName),\r\n };\r\n}\r\n\r\nexport async function listPulls(fullName: string): Promise<PullInfo[]> {\r\n const [open, merged] = await Promise.all([\r\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'open', '--limit', '50', '--json', PR_FIELDS]),\r\n ghJson<RawPull[]>(['pr', 'list', '-R', fullName, '--state', 'merged', '--limit', '8', '--json', PR_FIELDS]),\r\n ]);\r\n return [...open, ...merged].map(toPull);\r\n}\r\n\r\n// swarm:<specialty> labels route issues to specialists. gh refuses unknown labels, so they're created on first use.\r\nconst labelsMade = new Set<string>();\r\n\r\nasync function ensureLabel(fullName: string, name: string) {\r\n const key = `${fullName}#${name}`;\r\n if (labelsMade.has(key)) return;\r\n await gh(['label', 'create', name, '-R', fullName, '--color', 'c77dff', '--description', 'cubefarm: routed to this specialty', '--force']);\r\n labelsMade.add(key);\r\n}\r\n\r\nexport async function createIssue(fullName: string, title: string, body: string, labels: string[] = []): Promise<number> {\r\n for (const l of labels) await ensureLabel(fullName, l);\r\n const args = ['issue', 'create', '-R', fullName, '--title', title, '--body-file', '-'];\r\n for (const l of labels) args.push('--label', l);\r\n const out = await gh(args, { input: body || ' ' });\r\n const match = out.match(/\\/issues\\/(\\d+)/);\r\n if (!match) throw new Error(`Could not read the new issue number from gh output: ${out}`);\r\n return Number(match[1]);\r\n}\r\n\r\n/** OPEN or CLOSED; null when the repo has no such issue. */\r\nexport async function issueState(fullName: string, number: number): Promise<'OPEN' | 'CLOSED' | null> {\r\n try {\r\n const raw = await ghJson<{ state: string }>(['issue', 'view', String(number), '-R', fullName, '--json', 'state']);\r\n return raw.state === 'OPEN' ? 'OPEN' : 'CLOSED';\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Replace an issue's body and/or add and remove labels. */\r\nexport async function editIssue(fullName: string, number: number, edit: { body?: string; addLabels?: string[]; removeLabels?: string[] }): Promise<void> {\r\n const args = ['issue', 'edit', String(number), '-R', fullName];\r\n if (edit.body !== undefined) args.push('--body-file', '-');\r\n for (const l of edit.addLabels ?? []) {\r\n await ensureLabel(fullName, l);\r\n args.push('--add-label', l);\r\n }\r\n for (const l of edit.removeLabels ?? []) args.push('--remove-label', l);\r\n if (args.length === 5) return;\r\n await gh(args, edit.body !== undefined ? { input: edit.body || ' ' } : undefined);\r\n}\r\n\r\n/** Merge a PR. With headSha, GitHub refuses if anything was pushed after that commit (e.g. after QA signed it off). */\r\nexport async function mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void> {\r\n const pr = await ghJson<{ headRefName: string; isCrossRepository: boolean }>(['pr', 'view', String(number), '-R', fullName, '--json', 'headRefName,isCrossRepository']);\r\n await gh(['pr', 'merge', String(number), '-R', fullName, `--${method}`, ...(headSha ? ['--match-head-commit', headSha] : [])], { timeoutMs: 60_000 });\r\n // Tidy up the swarm branch on the remote; the local worktree is cleaned when the agent takes its next issue.\r\n if (!pr.isCrossRepository && pr.headRefName.startsWith('swarm/')) {\r\n await gh(['api', '-X', 'DELETE', `repos/${fullName}/git/refs/heads/${pr.headRefName}`]).catch(() => undefined);\r\n }\r\n}\r\n\r\n/** Merge the base branch into a PR's branch on GitHub, for repos that only merge up-to-date branches. */\r\nexport async function updateBranch(fullName: string, number: number): Promise<void> {\r\n await gh(['pr', 'update-branch', String(number), '-R', fullName], { timeoutMs: 60_000 });\r\n}\r\n\r\nexport async function closePull(fullName: string, number: number): Promise<void> {\r\n await gh(['pr', 'close', String(number), '-R', fullName]);\r\n}\r\n\r\nexport async function prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null> {\r\n const list = await ghJson<{ number: number; url: string }[]>(['pr', 'list', '-R', fullName, '--head', branch, '--state', 'all', '--json', 'number,url', '--limit', '1']);\r\n return list[0] ?? null;\r\n}\r\n\r\n// ---------- QA support ----------\r\n\r\nexport interface PrDetails {\r\n number: number;\r\n title: string;\r\n body: string;\r\n url: string;\r\n headRefName: string;\r\n headSha: string;\r\n isCrossRepository: boolean;\r\n closesIssues: number[];\r\n state: 'OPEN' | 'CLOSED' | 'MERGED';\r\n mergeable: string;\r\n mergeState: string;\r\n}\r\n\r\nexport async function prDetails(fullName: string, number: number): Promise<PrDetails> {\r\n const raw = await ghJson<{\r\n number: number;\r\n title: string;\r\n body: string;\r\n url: string;\r\n headRefName: string;\r\n headRefOid: string;\r\n isCrossRepository: boolean;\r\n closingIssuesReferences: { number: number }[] | null;\r\n state: PrDetails['state'];\r\n mergeable: string;\r\n mergeStateStatus: string;\r\n }>(['pr', 'view', String(number), '-R', fullName, '--json', 'number,title,body,url,headRefName,headRefOid,isCrossRepository,closingIssuesReferences,state,mergeable,mergeStateStatus']);\r\n return {\r\n number: raw.number,\r\n title: raw.title,\r\n body: raw.body ?? '',\r\n url: raw.url,\r\n headRefName: raw.headRefName,\r\n headSha: raw.headRefOid,\r\n isCrossRepository: raw.isCrossRepository,\r\n closesIssues: (raw.closingIssuesReferences ?? []).map((r) => r.number),\r\n state: raw.state,\r\n mergeable: raw.mergeable,\r\n mergeState: raw.mergeStateStatus || 'UNKNOWN',\r\n };\r\n}\r\n\r\nexport async function issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }> {\r\n const raw = await ghJson<{ title: string; body: string }>(['issue', 'view', String(number), '-R', fullName, '--json', 'title,body']);\r\n return { title: raw.title, body: raw.body ?? '' };\r\n}\r\n\r\nexport async function commentPull(fullName: string, number: number, body: string): Promise<string> {\r\n const out = await gh(['pr', 'comment', String(number), '-R', fullName, '--body-file', '-'], { input: body });\r\n return out.match(/https:\\/\\/github\\.com\\/\\S+/)?.[0] ?? '';\r\n}\r\n\r\n// QA screenshots live on an orphan branch so evidence never lands in the default branch when a PR is merged.\r\nexport const EVIDENCE_BRANCH = 'swarm-qa-evidence';\r\nconst evidenceReady = new Set<string>();\r\n\r\nconst ghApiJson = <T>(method: string, endpoint: string, body: unknown) =>\r\n gh(['api', '-X', method, endpoint, '-H', 'Content-Type: application/json', '--input', '-'], { input: JSON.stringify(body), timeoutMs: 120_000 }).then(\r\n (out) => (out ? JSON.parse(out) : null) as T,\r\n );\r\n\r\nasync function ensureEvidenceBranch(fullName: string) {\r\n if (evidenceReady.has(fullName)) return;\r\n try {\r\n await gh(['api', `repos/${fullName}/git/ref/heads/${EVIDENCE_BRANCH}`]);\r\n } catch {\r\n const readme =\r\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';\r\n const newTree = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/trees`, {\r\n tree: [{ path: 'README.md', mode: '100644', type: 'blob', content: readme }],\r\n });\r\n const commit = await ghApiJson<{ sha: string }>('POST', `repos/${fullName}/git/commits`, { message: 'QA evidence branch (cubefarm)', tree: newTree.sha, parents: [] });\r\n await ghApiJson('POST', `repos/${fullName}/git/refs`, { ref: `refs/heads/${EVIDENCE_BRANCH}`, sha: commit.sha });\r\n }\r\n evidenceReady.add(fullName);\r\n}\r\n\r\n/** Upload one evidence file and return a URL that renders inside PR comments (also for private repos). */\r\nexport async function uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string> {\r\n await ensureEvidenceBranch(fullName);\r\n await ghApiJson('PUT', `repos/${fullName}/contents/${filePath}`, {\r\n message: `QA evidence: ${filePath}`,\r\n content: data.toString('base64'),\r\n branch: EVIDENCE_BRANCH,\r\n });\r\n return `https://github.com/${fullName}/raw/${EVIDENCE_BRANCH}/${filePath}`;\r\n}\r\n", "import fs from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { WORKSPACE_ROOT } from './config.ts';\r\nimport { gh, git, run } from './exec.ts';\r\n\r\n// Layout on disk:\r\n// <your projects folder>/<repo> the floor's main checkout: your own folder, only fetched and fast-forwarded (syncMain)\r\n// <WORKSPACE_ROOT>/<owner>__<repo>/desks/<agent> one git worktree per agent, reused from task to task\r\n// Desks stay outside your project so its dev server, tsc and linters never see them.\r\n// Floors connected before project folders existed keep their clone at <WORKSPACE_ROOT>/<owner>__<repo>/main.\r\n\r\nconst locks = new Map<string, Promise<unknown>>();\r\nconst localRoots = new Map<string, string>(); // lowercased owner/name -> the user's project folder\r\n\r\n/** Serialise git operations per repo so concurrent worktree adds don't fight over index locks. */\r\nfunction withRepoLock<T>(fullName: string, fn: () => Promise<T>): Promise<T> {\r\n const prev = locks.get(fullName) ?? Promise.resolve();\r\n const next = prev.catch(() => undefined).then(fn);\r\n locks.set(fullName, next);\r\n return next;\r\n}\r\n\r\nexport const repoDir = (fullName: string) => path.join(WORKSPACE_ROOT, fullName.replace('/', '__'));\r\nexport const mainDir = (fullName: string) => localRoots.get(fullName.toLowerCase()) ?? path.join(repoDir(fullName), 'main');\r\nexport const deskDir = (fullName: string, agentSlug: string) => path.join(repoDir(fullName), 'desks', agentSlug);\r\n\r\n/** Use the user's own folder as a floor's main checkout (null: back to a clone the office manages). */\r\nexport function setLocalPath(fullName: string, dir: string | null) {\r\n if (dir) localRoots.set(fullName.toLowerCase(), path.resolve(dir));\r\n else localRoots.delete(fullName.toLowerCase());\r\n}\r\n\r\nasync function exists(p: string) {\r\n return fs\r\n .access(p)\r\n .then(() => true)\r\n .catch(() => false);\r\n}\r\n\r\n// Tool droppings that should never be committed from a desk (shared by all worktrees of the clone).\r\n// .preview-tmp/ is the preview worktree's {tmp} scratch folder.\r\nconst LOCAL_EXCLUDES = ['.playwright-mcp/', '.preview-tmp/'];\r\n\r\nasync function addLocalExcludes(main: string) {\r\n const file = path.join(main, '.git', 'info', 'exclude');\r\n const current = await fs.readFile(file, 'utf8').catch(() => '');\r\n const missing = LOCAL_EXCLUDES.filter((l) => !current.split(/\\r?\\n/).includes(l));\r\n if (missing.length === 0) return;\r\n await fs.mkdir(path.dirname(file), { recursive: true });\r\n await fs.appendFile(file, `${current && !current.endsWith('\\n') ? '\\n' : ''}# added by cubefarm\\n${missing.join('\\n')}\\n`);\r\n}\r\n\r\n/** Make sure the floor's worktrees keep LOCAL_EXCLUDES out of git status. */\r\nexport const ensureLocalExcludes = (fullName: string) => addLocalExcludes(mainDir(fullName));\r\n\r\nexport function ensureClone(fullName: string): Promise<void> {\r\n return withRepoLock(fullName, async () => {\r\n const dir = mainDir(fullName);\r\n if (await exists(path.join(dir, '.git'))) {\r\n // Only remote-tracking refs change: your checkout, branch and uncommitted work are left alone.\r\n await git(['fetch', 'origin', '--prune'], { cwd: dir, timeoutMs: 180_000 });\r\n } else {\r\n await fs.mkdir(path.dirname(dir), { recursive: true });\r\n await gh(['repo', 'clone', fullName, dir], { timeoutMs: 600_000 });\r\n }\r\n await addLocalExcludes(dir);\r\n });\r\n}\r\n\r\nconst installs = new Map<string, Promise<unknown>>();\r\n\r\n/** npm install in a folder, one at a time per folder. */\r\nfunction npmInstall(dir: string) {\r\n const prev = installs.get(dir) ?? Promise.resolve();\r\n const opts = { cwd: dir, timeoutMs: 600_000 };\r\n const next = prev\r\n .catch(() => undefined)\r\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)));\r\n installs.set(dir, next);\r\n return next;\r\n}\r\n\r\n/** How a floor's main checkout stands after syncMain. */\r\nexport interface MainSync {\r\n status: string; // e.g. \"in sync\", \"updated to abc1234\", \"update ready (3 commits)\" or \"2 behind: local changes\"\r\n behind: number; // commits it is still behind GitHub's default branch\r\n updatable: boolean; // on the default branch without local commits, so a fast-forward would bring it up to date\r\n}\r\n\r\n/**\r\n * Bring a floor's main checkout up to date with GitHub. It only ever fast-forwards, and only when the checkout is on\r\n * the default branch with no local changes: nothing is stashed, reset or discarded, and anything else leaves the\r\n * folder as it is. Installs dependencies when package.json or the lockfile changed. With `touch: false` it only\r\n * reports (the office's own folder). Returns how the checkout stands; null when there is no checkout yet.\r\n */\r\nexport async function syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<MainSync | null> {\r\n const dir = mainDir(fullName);\r\n const result = await withRepoLock(fullName, async (): Promise<(MainSync & { install?: boolean }) | null> => {\r\n if (!(await exists(path.join(dir, '.git')))) return null;\r\n const g = (args: string[], timeoutMs?: number) => git(args, { cwd: dir, timeoutMs });\r\n let behind = 0;\r\n try {\r\n await g(['fetch', 'origin', '--prune'], 180_000);\r\n const target = `origin/${defaultBranch}`;\r\n behind = Number(await g(['rev-list', '--count', `HEAD..${target}`]));\r\n const commits = `${behind} commit${behind === 1 ? '' : 's'}`;\r\n const branch = await g(['symbolic-ref', '--short', '-q', 'HEAD']).catch(() => '');\r\n const stays = (status: string) => ({ status, behind, updatable: false });\r\n if (branch !== defaultBranch) return stays(`on ${branch ? `branch ${branch}` : 'a detached HEAD'}${behind ? ` (${defaultBranch} is ${commits} ahead)` : ''}`);\r\n if (behind === 0) return stays('in sync');\r\n if (Number(await g(['rev-list', '--count', `${target}..HEAD`])) > 0) return stays(`diverged: local commits, and ${commits} to pull`);\r\n if (!opts.touch) return { status: `update ready (${commits})`, behind, updatable: true };\r\n if (await g(['status', '--porcelain', '--untracked-files=no'])) return { status: `${behind} behind: local changes`, behind, updatable: true };\r\n const before = await g(['rev-parse', 'HEAD']);\r\n try {\r\n await g(['merge', '--ff-only', target], 120_000);\r\n } catch {\r\n return { status: `${behind} behind: local files are in the way`, behind, updatable: true };\r\n }\r\n const changed = (await g(['diff', '--name-only', before, 'HEAD'])).split(/\\r?\\n/);\r\n const install = changed.some((f) => f === 'package.json' || f === 'package-lock.json') && (await exists(path.join(dir, 'package.json')));\r\n return { status: `updated to ${await g(['rev-parse', '--short', 'HEAD'])}`, behind: 0, updatable: false, install };\r\n } catch (err) {\r\n return { status: `sync failed: ${(err as Error).message.split(/\\r?\\n/)[0].slice(0, 160)}`, behind, updatable: false };\r\n }\r\n });\r\n if (!result?.install) return result;\r\n const { install: _install, ...sync } = result;\r\n // Outside the repo lock: agents' worktrees don't wait for npm.\r\n try {\r\n await npmInstall(dir);\r\n return { ...sync, status: `${sync.status} \u00B7 dependencies installed` };\r\n } catch (err) {\r\n console.warn(`npm install in ${dir} failed:`, (err as Error).message);\r\n return { ...sync, status: `${sync.status} \u00B7 npm install failed` };\r\n }\r\n}\r\n\r\n// ---------- your projects folder ----------\r\n\r\nexport interface LocalFolder {\r\n name: string;\r\n path: string;\r\n git: boolean;\r\n github: string | null; // owner/name of its GitHub origin\r\n modified: number;\r\n}\r\n\r\n/** owner/name from a git config's origin URL, if it points at GitHub. */\r\nfunction githubFromConfig(config: string): string | null {\r\n const url = config.match(/\\[remote \"origin\"\\][^[]*?url\\s*=\\s*(\\S+)/)?.[1];\r\n const m = url?.match(/github\\.com[:/]([^/\\s]+)\\/([^/\\s]+?)(?:\\.git)?\\/?$/i);\r\n return m ? `${m[1]}/${m[2]}` : null;\r\n}\r\n\r\n/** What a folder is: a git repo? with a GitHub origin? Reads .git/config directly, so scanning is quick. */\r\nexport async function inspectFolder(dir: string): Promise<LocalFolder> {\r\n const full = path.resolve(dir);\r\n const stat = await fs.stat(full).catch(() => null);\r\n if (!stat?.isDirectory()) throw new Error(`${full} is not a folder`);\r\n const dotGit = path.join(full, '.git');\r\n const gitStat = await fs.stat(dotGit).catch(() => null);\r\n let config = '';\r\n if (gitStat?.isDirectory()) config = await fs.readFile(path.join(dotGit, 'config'), 'utf8').catch(() => '');\r\n else if (gitStat) {\r\n // a worktree or submodule: .git is a file pointing at the real git dir\r\n const ref = (await fs.readFile(dotGit, 'utf8').catch(() => '')).match(/gitdir:\\s*(.+)/)?.[1]?.trim();\r\n if (ref) {\r\n const gitDir = path.resolve(full, ref);\r\n config = await fs.readFile(path.join(gitDir, 'config'), 'utf8').catch(() => fs.readFile(path.join(gitDir, '..', '..', 'config'), 'utf8').catch(() => ''));\r\n }\r\n }\r\n return { name: path.basename(full), path: full, git: !!gitStat, github: githubFromConfig(config), modified: stat.mtimeMs };\r\n}\r\n\r\n/** The folders directly inside the projects folder, most recently changed first. */\r\nexport async function scanProjects(root: string): Promise<LocalFolder[]> {\r\n const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => {\r\n throw new Error(`Can't read the projects folder ${root}`);\r\n });\r\n const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules');\r\n const folders = await Promise.all(dirs.map((e) => inspectFolder(path.join(root, e.name)).catch(() => null)));\r\n return folders.filter((f): f is LocalFolder => !!f).sort((a, b) => b.modified - a.modified);\r\n}\r\n\r\nasync function commitReadme(dir: string, title: string, description: string) {\r\n const readme = path.join(dir, 'README.md');\r\n if (!(await exists(readme))) await fs.writeFile(readme, `# ${title}\\n\\n${description.trim()}\\n`);\r\n await git(['add', 'README.md'], { cwd: dir });\r\n try {\r\n await git(['commit', '-m', 'Initial commit'], { cwd: dir });\r\n } catch (err) {\r\n if (!/tell me who you are|user\\.(name|email)/i.test((err as Error).message)) throw err;\r\n // No git identity on this machine: commit as the GitHub account gh is signed in to.\r\n const login = await gh(['api', 'user', '--jq', '.login']);\r\n await git(['-c', `user.name=${login}`, '-c', `user.email=${login}@users.noreply.github.com`, 'commit', '-m', 'Initial commit'], { cwd: dir });\r\n }\r\n}\r\n\r\n/**\r\n * Put a folder on GitHub (gh repo create --source --push). Only what's already committed is pushed. A folder with\r\n * no commits yet gets a README commit, but only when it's empty: the office never decides which of your files go public.\r\n */\r\nexport async function publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string> {\r\n const full = path.resolve(dir);\r\n const info = await inspectFolder(full);\r\n if (info.github) return info.github;\r\n if (!info.git) await git(['init', '-b', 'main'], { cwd: full });\r\n const hasCommit = await git(['rev-parse', '--verify', 'HEAD'], { cwd: full }).then(\r\n () => true,\r\n () => false,\r\n );\r\n if (!hasCommit) {\r\n const files = (await fs.readdir(full)).filter((f) => f !== '.git' && f !== 'README.md');\r\n if (files.length) {\r\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.`);\r\n }\r\n await commitReadme(full, opts.name, opts.description ?? '');\r\n }\r\n const origin = await git(['remote', 'get-url', 'origin'], { cwd: full }).catch(() => '');\r\n if (origin) throw new Error(`${info.name}'s origin (${origin}) isn't on GitHub. cubefarm needs GitHub for issues and pull requests.`);\r\n const target = opts.owner ? `${opts.owner}/${opts.name}` : opts.name;\r\n const args = ['repo', 'create', target, `--${opts.visibility}`, '--source', full, '--remote', 'origin', '--push'];\r\n if (opts.description) args.push('--description', opts.description);\r\n const out = await gh(args, { cwd: full, timeoutMs: 120_000 });\r\n return out.match(/github\\.com\\/([^/\\s]+\\/[^/\\s]+?)(?:\\.git)?(?:\\s|$)/)?.[1] ?? (await inspectFolder(full)).github ?? target;\r\n}\r\n\r\n/** A brand-new project: <root>/<name> with a README, pushed to a new GitHub repo. */\r\nexport async function createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }) {\r\n const dir = path.join(root, name);\r\n if (await exists(dir)) {\r\n const inside = await fs.readdir(dir).catch(() => ['?']);\r\n if (inside.length) throw new Error(`${dir} already exists. Pick another name, or connect that folder instead.`);\r\n }\r\n await fs.mkdir(dir, { recursive: true });\r\n await git(['init', '-b', 'main'], { cwd: dir });\r\n await commitReadme(dir, name, opts.description ?? '');\r\n const fullName = await publishFolder(dir, { name, ...opts });\r\n return { fullName, path: dir };\r\n}\r\n\r\nexport interface DeskBase {\r\n defaultBranch: string;\r\n /** Start from a pull request's head instead of the default branch (QA testing, fixes after QA). */\r\n pr?: number;\r\n}\r\n\r\n/** Remove a directory, retrying while Windows still has handles open in it. */\r\nasync function removeDir(dir: string) {\r\n await fs.rm(dir, { recursive: true, force: true, maxRetries: 8, retryDelay: 250 });\r\n}\r\n\r\nexport function prepareDesk(fullName: string, base: DeskBase, agentSlug: string, branch: string): Promise<string> {\r\n return withRepoLock(fullName, async () => {\r\n const main = mainDir(fullName);\r\n await git(['fetch', 'origin', '--prune'], { cwd: main, timeoutMs: 180_000 });\r\n let ref = `origin/${base.defaultBranch}`;\r\n if (base.pr) {\r\n // refs/pull/N/head works for branches in this repo and for forks alike\r\n ref = `origin/pr/${base.pr}`;\r\n await git(['fetch', 'origin', `+refs/pull/${base.pr}/head:refs/remotes/${ref}`], { cwd: main, timeoutMs: 180_000 });\r\n }\r\n try {\r\n await git(['rev-parse', '--verify', ref], { cwd: main });\r\n } catch {\r\n throw new Error(\r\n base.pr\r\n ? `Could not fetch pull request #${base.pr} of ${fullName}.`\r\n : `${fullName} has no ${base.defaultBranch} branch yet. Push an initial commit (or create the repo with a README) before assigning work.`,\r\n );\r\n }\r\n\r\n const wt = deskDir(fullName, agentSlug);\r\n\r\n // Reuse the desk's worktree in place. Deleting it fails on Windows while any process (a dev server\r\n // the agent left running, a browser) still has its working directory inside, and reuse keeps\r\n // node_modules warm between tasks.\r\n if (await exists(path.join(wt, '.git'))) {\r\n try {\r\n await git(['checkout', '--force', '-B', branch, ref], { cwd: wt });\r\n await git(['reset', '--hard', ref], { cwd: wt });\r\n // Untracked leftovers from the last task go; ignored files (node_modules, build caches) stay.\r\n await git(['clean', '-fd'], { cwd: wt }).catch(() => undefined);\r\n return wt;\r\n } catch {\r\n // fall through and rebuild the worktree from scratch\r\n }\r\n }\r\n\r\n if (await exists(wt)) {\r\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\r\n try {\r\n await removeDir(wt);\r\n } catch (err) {\r\n throw new Error(\r\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.`,\r\n );\r\n }\r\n }\r\n await git(['worktree', 'prune'], { cwd: main });\r\n await fs.mkdir(path.dirname(wt), { recursive: true });\r\n await git(['worktree', 'add', '-B', branch, wt, ref], { cwd: main });\r\n return wt;\r\n });\r\n}\r\n\r\nexport function removeDesk(fullName: string, agentSlug: string): Promise<void> {\r\n return withRepoLock(fullName, async () => {\r\n const main = mainDir(fullName);\r\n const wt = deskDir(fullName, agentSlug);\r\n if (!(await exists(wt))) return;\r\n await git(['worktree', 'remove', '--force', wt], { cwd: main }).catch(() => undefined);\r\n await removeDir(wt).catch(() => undefined);\r\n await git(['worktree', 'prune'], { cwd: main }).catch(() => undefined);\r\n });\r\n}\r\n\r\n// ---------- leftover processes ----------\r\n\r\n// Only these kinds of processes are stopped when walking up from a leftover to its (orphaned) launcher.\r\nconst LAUNCHERS = ['node.exe', 'cmd.exe', 'bash.exe', 'sh.exe', 'conhost.exe', 'python.exe', 'npm.exe', 'npx.exe', 'bun.exe', 'deno.exe'];\r\n\r\n/** What a desk clean-up leaves alone: the office's own processes, and command lines that carry these paths. */\r\nexport interface OfficeProcesses {\r\n /** The office, its terminal keeper and every CLI running in an agent's terminal. */\r\n pids: number[];\r\n /** Paths only the CLIs' own command lines carry (the office's session files): those are agents, not leftovers. */\r\n markers: string[];\r\n}\r\n\r\n/** A path as it can appear in a command line: as is, with forward slashes, and JSON-escaped (Codex's -c values). */\r\nexport const pathForms = (p: string) => [...new Set([p, p.replaceAll('\\\\', '/'), p.replaceAll('\\\\', '\\\\\\\\')])];\r\n\r\n/** The processes of a `ps -A -ww -o pid=,args=` listing whose command line points into a desk, except the office's. */\r\nexport function leftoversInDesk(listing: string, desk: string, keep: OfficeProcesses): number[] {\r\n const out: number[] = [];\r\n for (const line of listing.split('\\n')) {\r\n const m = line.trim().match(/^(\\d+)\\s+(.*)$/);\r\n if (!m) continue;\r\n const [pid, args] = [Number(m[1]), m[2]];\r\n if (keep.pids.includes(pid) || keep.markers.some((mark) => pathForms(mark).some((f) => args.includes(f)))) continue;\r\n if (pathForms(desk).some((f) => args.includes(f))) out.push(pid);\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Stop what an agent left running: anything listening on its reserved port or whose command line points into its\r\n * desk, plus the shell/node chain that launched it. Never the office's own processes (the keeper, the CLIs in agents'\r\n * terminals): the walk up from a leftover stops at them.\r\n */\r\nexport async function releaseDesk(fullName: string, agentSlug: string, port: number, keep: OfficeProcesses = { pids: [], markers: [] }): Promise<void> {\r\n const desk = deskDir(fullName, agentSlug);\r\n const spare = [process.pid, ...keep.pids];\r\n if (process.platform === 'win32') {\r\n const psList = (paths: string[]) => paths.flatMap(pathForms).map((d) => `'${d.toLowerCase().replaceAll(\"'\", \"''\")}'`).join(', ');\r\n const script = `\r\n$ErrorActionPreference = 'SilentlyContinue'\r\n$spare = @(${spare.join(', ')})\r\n$seed = @()\r\nGet-NetTCPConnection -LocalPort ${port} -State Listen | ForEach-Object { $seed += [int]$_.OwningProcess }\r\n$desks = @(${psList([desk])})\r\n$marks = @(${psList(keep.markers)})\r\n$all = Get-CimInstance Win32_Process\r\n$byId = @{}; foreach ($p in $all) { $byId[[int]$p.ProcessId] = $p }\r\nforeach ($p in $all) {\r\n if (-not $p.CommandLine) { continue }\r\n $cmd = $p.CommandLine.ToLower()\r\n $ours = $false\r\n foreach ($m in $marks) { if ($cmd.Contains($m)) { $ours = $true } }\r\n if ($ours) { continue }\r\n foreach ($d in $desks) { if ($cmd.Contains($d)) { $seed += [int]$p.ProcessId } }\r\n}\r\n$launchers = @(${LAUNCHERS.map((n) => `'${n}'`).join(', ')})\r\n$kill = New-Object 'System.Collections.Generic.HashSet[int]'\r\nforeach ($id in $seed) {\r\n $cur = $byId[$id]\r\n $first = $true\r\n while ($cur -and -not ($spare -contains [int]$cur.ProcessId) -and ($first -or $launchers -contains $cur.Name.ToLower())) {\r\n [void]$kill.Add([int]$cur.ProcessId)\r\n $first = $false\r\n $cur = $byId[[int]$cur.ParentProcessId]\r\n }\r\n}\r\nforeach ($id in $kill) { taskkill /PID $id /T /F 2>&1 | Out-Null }\r\nWrite-Output $kill.Count`;\r\n await run('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], { timeoutMs: 30_000 }).catch(() => undefined);\r\n return;\r\n }\r\n const listening = await run('sh', ['-c', `lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null || true`]).catch(() => '');\r\n const listing = await run('ps', ['-A', '-ww', '-o', 'pid=,args=']).catch(() => '');\r\n const pids = new Set([...listening.split(/\\s+/).map(Number), ...leftoversInDesk(listing, desk, keep)]);\r\n for (const pid of pids) {\r\n if (!pid || spare.includes(pid)) continue;\r\n try {\r\n process.kill(pid, 'SIGKILL');\r\n } catch {\r\n // already gone\r\n }\r\n }\r\n}\r\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 { 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 sessionId(id: string): 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, s);\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 // browser-init.js keeps pages from taking the real mouse with pointer lock (headless Chrome does on Windows).\n const args = ['-y', '@playwright/mcp@latest', '--headless', '--isolated', '--init-script', path.join(import.meta.dirname, 'browser-init.js')];\n mcpServers.playwright = process.platform === 'win32' ? { command: 'cmd', args: ['/c', 'npx', ...args] } : { command: 'npx', args };\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 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 { HOME_DIR } from './config.ts';\nimport { cliLabel, CODEX_HOOK_SOURCE, 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/** The browser for a session. Its snapshots and unnamed screenshots go to the session's folder, not the worktree. */\nfunction playwrightServer(outputDir: string) {\n const args = ['-y', '@playwright/mcp@latest', '--headless', '--isolated', '--output-dir', outputDir, '--init-script', path.join(import.meta.dirname, 'browser-init.js')];\n return process.platform === 'win32' ? { command: 'cmd', args: ['/c', 'npx', ...args] } : { command: 'npx', args };\n}\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/** Close a CLI for good. */\nfunction endLive(live: LiveCli) {\n if (lives.get(live.term) !== live) return;\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 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}\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 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.\n */\nexport function releaseClis(restart: boolean) {\n if (!restart) for (const l of [...lives.values()]) endLive(l);\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\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 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 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 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 const browser = opts.browserTesting ? playwrightServer(path.join(dir, 'browser')) : null;\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') 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 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 handle;\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 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// ---------- 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 const p = nodePty.spawn(file, args, { name: 'xterm-256color', cols: o.cols, rows: o.rows, cwd: o.cwd, env: o.env });\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';\r\nimport path from 'node:path';\r\nimport { HOME_DIR } from './config.ts';\r\nimport { git } from './exec.ts';\r\nimport type { OfficeUpdateState } from '../shared/types.ts';\r\n\r\n// The office updating itself (#37). The server only decides when: it drains (starts nothing new, lets running\r\n// sessions finish) and then hands the update to the launcher (scripts/office.mjs), which pulls, installs, builds and\r\n// restarts it. Contract with the launcher:\r\n// server \u2192 launcher { type: 'office:update', from: '<full HEAD sha>' } once drained\r\n// launcher \u2192 server { type: 'office:shutdown', restart } run shutdown(), then exit 0\r\n// (restart: false when the office quits; agents' CLIs stop instead of waiting in the keeper)\r\n// <SWARM_HOME>/last-update.json = { from, to, ok, error?, installed, built, at }, read and deleted on startup\r\n\r\n/** Sessions still running this long after draining started are stopped, and the update goes ahead. */\r\nexport const DRAIN_TIMEOUT_MS = 20 * 60_000;\r\n/** Later: ask again after this long, or sooner when a newer commit lands. */\r\nexport const POSTPONE_MS = 2 * 60 * 60_000;\r\n\r\n/** Started by the launcher: an IPC channel and SWARM_LAUNCHER=1. Anything else (tsx, the demo, QA) only reports. */\r\nexport function underLauncher(proc: { send?: unknown; env: Record<string, string | undefined> } = process): boolean {\r\n return typeof proc.send === 'function' && proc.env.SWARM_LAUNCHER === '1';\r\n}\r\n\r\nexport interface DrainInput {\r\n now: number;\r\n behind: number; // commits the office's folder can fast-forward by (0: nothing to update)\r\n launcher: boolean;\r\n autoUpdate: boolean;\r\n requested: boolean; // the manager pressed Update now\r\n postponedUntil: number | null; // the manager pressed Later\r\n postponedBehind: number; // how far behind it was then: a newer commit ends the postponement\r\n failed: string | null; // the last update's error\r\n failedBehind: number | null; // how far behind it was after that failure: only a newer commit retries on its own\r\n drainingSince: number | null;\r\n sent: boolean; // handed to the launcher\r\n running: number; // sessions still running\r\n}\r\n\r\nexport interface DrainDecision {\r\n state: OfficeUpdateState;\r\n drainingSince: number | null;\r\n /** Hand the update to the launcher now: nothing is running, or the drain timed out (`timedOut`). */\r\n send: boolean;\r\n timedOut: boolean;\r\n}\r\n\r\n/**\r\n * Where the office's own update stands and what to do about it. Draining (start nothing new, let running sessions\r\n * finish) happens when there is an update, a launcher, and either autoUpdate is on or the manager pressed Update now.\r\n * Later holds an automatic update back for POSTPONE_MS or until a newer commit lands ('waiting'); a failed update is\r\n * only retried automatically for a newer commit.\r\n */\r\nexport function drainDecision(s: DrainInput): DrainDecision {\r\n const idle = (state: OfficeUpdateState): DrainDecision => ({ state, drainingSince: null, send: false, timedOut: false });\r\n if (s.sent) return { state: 'updating', drainingSince: s.drainingSince, send: false, timedOut: false };\r\n if (s.behind <= 0) return idle('none');\r\n if (!s.launcher) return idle(s.failed ? 'failed' : 'available');\r\n const postponed = s.postponedUntil !== null && s.now < s.postponedUntil && s.behind <= s.postponedBehind;\r\n const failedHold = s.failed !== null && s.behind <= (s.failedBehind ?? Infinity);\r\n const due = s.requested || (s.autoUpdate && !postponed && !failedHold);\r\n if (!due) return idle(s.failed ? 'failed' : s.autoUpdate && postponed ? 'waiting' : 'available');\r\n const since = s.drainingSince ?? s.now;\r\n const timedOut = s.running > 0 && s.now - since >= DRAIN_TIMEOUT_MS;\r\n return { state: 'draining', drainingSince: since, send: s.running === 0 || timedOut, timedOut };\r\n}\r\n\r\n/** What the launcher leaves behind after an update. */\r\nexport interface LastUpdate {\r\n from: string;\r\n to: string;\r\n ok: boolean;\r\n error?: string;\r\n installed: boolean;\r\n built: boolean;\r\n at: number;\r\n}\r\n\r\n/** Parse last-update.json; null when it isn't one. */\r\nexport function parseLastUpdate(raw: string): LastUpdate | null {\r\n try {\r\n const u = JSON.parse(raw) as Partial<LastUpdate>;\r\n if (!u || typeof u.from !== 'string' || typeof u.ok !== 'boolean') return null;\r\n return {\r\n from: u.from,\r\n to: typeof u.to === 'string' ? u.to : '',\r\n ok: u.ok,\r\n error: typeof u.error === 'string' ? u.error : undefined,\r\n installed: !!u.installed,\r\n built: !!u.built,\r\n at: Number(u.at) || Date.now(),\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Read and delete <home>/last-update.json, so its phone message is posted once. */\r\nexport async function takeLastUpdate(home: string): Promise<LastUpdate | null> {\r\n const file = path.join(home, 'last-update.json');\r\n const raw = await fs.readFile(file, 'utf8').catch(() => null);\r\n if (raw === null) return null;\r\n await fs.rm(file, { force: true, maxRetries: 3 }).catch(() => undefined);\r\n return parseLastUpdate(raw);\r\n}\r\n\r\n/** The phone message for an update: \"Updated the office from abc1234 to def5678 (3 commits)\" or why it failed. */\r\nexport function lastUpdateMessage(u: LastUpdate, commits: number | null): string {\r\n if (!u.ok) return `\u26A0\uFE0F Update failed and was rolled back: ${u.error || 'unknown error'}`;\r\n const n = commits === null ? '' : ` (${commits} commit${commits === 1 ? '' : 's'})`;\r\n return `\u2B06\uFE0F Updated the office from ${u.from.slice(0, 7)} to ${u.to.slice(0, 7)}${n}`;\r\n}\r\n\r\n// ---------- the running office ----------\r\n\r\n/** The running office's own checkout and its launcher. The demo fakes it. */\r\nexport interface OfficeHost {\r\n launcher: boolean;\r\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). */\r\n head(): Promise<string | null>;\r\n /** Is this floor checkout the office's own folder? Syncing it would restart the office mid-work, so it's only reported. */\r\n isOwnFolder(dir: string): boolean;\r\n /** Commits between two shas of the office's folder, or null when git can't tell. */\r\n commitsBetween(from: string, to: string): Promise<number | null>;\r\n /** Read and delete the result the launcher left from the last update. */\r\n takeLastUpdate(): Promise<LastUpdate | null>;\r\n /** Hand the drained office to the launcher, which restarts it (resolves null). The demo resolves with a fake result. */\r\n update(from: string): Promise<LastUpdate | null>;\r\n}\r\n\r\nconst OFFICE_DIR = path.resolve(import.meta.dirname, '..');\r\nconst isSamePath = (a: string, b: string) => (process.platform === 'win32' ? path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase() : path.resolve(a) === path.resolve(b));\r\n\r\nexport const realOffice: OfficeHost = {\r\n launcher: underLauncher(),\r\n head: () => git(['rev-parse', 'HEAD'], { cwd: OFFICE_DIR }).catch(() => null),\r\n isOwnFolder: (dir) => isSamePath(dir, OFFICE_DIR),\r\n commitsBetween: (from, to) =>\r\n git(['rev-list', '--count', `${from}..${to}`], { cwd: OFFICE_DIR })\r\n .then(Number)\r\n .catch(() => null),\r\n takeLastUpdate: () => takeLastUpdate(HOME_DIR),\r\n async update(from) {\r\n if (!underLauncher()) throw new Error('The office was not started by the launcher');\r\n await new Promise<void>((resolve, reject) => process.send!({ type: 'office:update', from }, undefined, {}, (err) => (err ? reject(err) : resolve())));\r\n return null;\r\n },\r\n};\r\n", "import * as github from './github.ts';\r\nimport * as workspace from './workspace.ts';\r\nimport { startSession, type SessionCallbacks, type SessionHandle, type SessionOptions } from './agentRunner.ts';\r\nimport { hooksReady, officeProcesses, reconnectClis, releaseClis, startCliSession, terminalsAvailable, type ReconnectedCli } from './cliRunner.ts';\r\nimport { detectClis } from './clis.ts';\r\nimport { realPreviews, type PreviewBackend } from './previewRunner.ts';\r\nimport { realOffice, type OfficeHost } from './officeUpdate.ts';\r\nimport type { AgentTerminal } from './terminal.ts';\r\nimport type { CliView, GhRepoSummary, IssueInfo, PullInfo } from '../shared/types.ts';\r\n\r\n/** Everything the swarm needs from the outside world. The demo backend fakes all of it. */\r\nexport interface Backend {\r\n demo: boolean;\r\n user(): Promise<string>;\r\n listMyRepos(owner?: string): Promise<GhRepoSummary[]>;\r\n repoMeta(fullName: string): Promise<github.RepoMeta>;\r\n listIssues(fullName: string): Promise<IssueInfo[]>;\r\n listPulls(fullName: string): Promise<PullInfo[]>;\r\n createIssue(fullName: string, title: string, body: string, labels?: string[]): Promise<number>;\r\n /** OPEN or CLOSED; null when there is no such issue. */\r\n issueState(fullName: string, number: number): Promise<'OPEN' | 'CLOSED' | null>;\r\n editIssue(fullName: string, number: number, edit: { body?: string; addLabels?: string[]; removeLabels?: string[] }): Promise<void>;\r\n mergePull(fullName: string, number: number, method: 'squash' | 'merge' | 'rebase', headSha?: string): Promise<void>;\r\n updateBranch(fullName: string, number: number): Promise<void>;\r\n closePull(fullName: string, number: number): Promise<void>;\r\n prForBranch(fullName: string, branch: string): Promise<{ number: number; url: string } | null>;\r\n prDetails(fullName: string, number: number): Promise<github.PrDetails>;\r\n issueDetails(fullName: string, number: number): Promise<{ title: string; body: string }>;\r\n commentPull(fullName: string, number: number, body: string): Promise<string>;\r\n uploadEvidence(fullName: string, filePath: string, data: Buffer): Promise<string>;\r\n ensureClone(fullName: string): Promise<void>;\r\n /** Fast-forward the floor's main checkout to GitHub when that is safe; returns how it stands. */\r\n syncMain(fullName: string, defaultBranch: string, opts: { touch: boolean }): Promise<workspace.MainSync | null>;\r\n /** Point a floor at the user's own project folder (null: a clone the office manages). */\r\n setLocalPath(fullName: string, dir: string | null): void;\r\n scanProjects(root: string): Promise<workspace.LocalFolder[]>;\r\n inspectFolder(dir: string): Promise<workspace.LocalFolder>;\r\n publishFolder(dir: string, opts: { name: string; visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<string>;\r\n createProject(root: string, name: string, opts: { visibility: 'private' | 'public'; owner?: string; description?: string }): Promise<{ fullName: string; path: string }>;\r\n mainDir(fullName: string): string;\r\n deskDir(fullName: string, agentSlug: string): string;\r\n prepareDesk(fullName: string, base: workspace.DeskBase, agentSlug: string, branch: string): Promise<string>;\r\n removeDesk(fullName: string, agentSlug: string): Promise<void>;\r\n /** Stop processes an agent left running (dev servers on its port, anything started in its desk). */\r\n releaseDesk(fullName: string, agentSlug: string, port: number): Promise<void>;\r\n /** An agent session: the real CLI in the agent's terminal when opts.terminal is set, else an Agent SDK session. */\r\n startSession(opts: SessionOptions, cb: SessionCallbacks): SessionHandle;\r\n /** Terminals can run here (the native pseudo-terminal module loaded). */\r\n terminals: boolean;\r\n /** The office started: the CLIs its terminal keeper kept running through a restart, back in their agents' terminals. */\r\n reconnectClis(terminalFor: (agentId: string) => AgentTerminal | null): Promise<ReconnectedCli[]>;\r\n /** The office follows those CLIs' sessions again: hooks that waited for it can come in. */\r\n hooksReady(): void;\r\n /** The office is stopping: its CLIs carry on in the keeper through a restart (true), or stop with it. */\r\n releaseClis(restart: boolean): void;\r\n /** The coding-agent CLIs installed on this machine. */\r\n detectClis(): Promise<CliView[]>;\r\n /** Run a floor's app for the preview monitor (its own worktree, its own port). */\r\n previews: PreviewBackend;\r\n /** The running office's own folder and its launcher, for the office's self-update. */\r\n office: OfficeHost;\r\n}\r\n\r\nexport const realBackend: Backend = {\r\n demo: false,\r\n user: github.currentUser,\r\n listMyRepos: github.listMyRepos,\r\n repoMeta: github.repoMeta,\r\n listIssues: github.listIssues,\r\n listPulls: github.listPulls,\r\n createIssue: github.createIssue,\r\n issueState: github.issueState,\r\n editIssue: github.editIssue,\r\n mergePull: github.mergePull,\r\n updateBranch: github.updateBranch,\r\n closePull: github.closePull,\r\n prForBranch: github.prForBranch,\r\n prDetails: github.prDetails,\r\n issueDetails: github.issueDetails,\r\n commentPull: github.commentPull,\r\n uploadEvidence: github.uploadEvidence,\r\n ensureClone: workspace.ensureClone,\r\n syncMain: workspace.syncMain,\r\n setLocalPath: workspace.setLocalPath,\r\n scanProjects: workspace.scanProjects,\r\n inspectFolder: workspace.inspectFolder,\r\n publishFolder: workspace.publishFolder,\r\n createProject: workspace.createProject,\r\n mainDir: workspace.mainDir,\r\n deskDir: workspace.deskDir,\r\n prepareDesk: workspace.prepareDesk,\r\n removeDesk: workspace.removeDesk,\r\n releaseDesk: (fullName, agentSlug, port) => workspace.releaseDesk(fullName, agentSlug, port, officeProcesses()),\r\n startSession: (opts, cb) => (opts.terminal ? startCliSession(opts, cb) : startSession(opts, cb)),\r\n terminals: terminalsAvailable,\r\n reconnectClis: (terminalFor) => (terminalsAvailable ? reconnectClis(terminalFor) : Promise.resolve([])),\r\n hooksReady,\r\n releaseClis,\r\n detectClis,\r\n previews: realPreviews,\r\n office: realOffice,\r\n};\r\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): 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 [{ 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 ];\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\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) : 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) {\n pr.headSha = fakeSha();\n pr.mergeState = 'CLEAN';\n pr.mergeable = 'MERGEABLE';\n runChecks(pr, false);\n }\n cb.log([{ kind: 'text', text: `\u25CF Fixed PR #${number} and pushed. 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 for (const n of pr.closesIssues) closedIssues.add(`${fullName}#${n}`);\n r.issues = r.issues.filter((i) => !pr.closesIssues.includes(i.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 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: () => 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}\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 cb.log([{ kind: 'result', text: ` \u23BF ${s.floors.length} floors \u00B7 ${people} people \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';\r\nimport path from 'node:path';\r\nimport crypto from 'node:crypto';\r\nimport type { WebSocket } from 'ws';\r\nimport type { Backend } from './backend.ts';\r\nimport type { LogEntry, SessionHandle, SessionResult } from './agentRunner.ts';\r\nimport type { PrDetails } from './github.ts';\r\nimport { defaultProjectsDir, HOME_DIR, LOG_BUFFER, SCHEDULER_INTERVAL_MS, STATE_FILE, SYNC_INTERVAL_MS, WORKSPACE_ROOT } from './config.ts';\r\nimport { ceoJobPrompt, ceoSystemPrompt, createOfficeTools, IssueCap, jobLabel, planRoute, specialtyLabel, specialtySlug, type CeoJob, type OfficeTools } from './ceo.ts';\r\nimport { HttpError } from './httpError.ts';\r\nimport { CHECKS_ALERT_MS, MAX_MERGE_FIXES, MERGE_RETRY_MS, mergeStep } from './mergeGate.ts';\r\nimport { DEFAULT_PREVIEW, Previews, parsePreviewPatch } from './previews.ts';\r\nimport { drainDecision, lastUpdateMessage, POSTPONE_MS, type DrainInput, type LastUpdate } from './officeUpdate.ts';\r\nimport { clampPacingSessions, DEFAULT_PACING_SESSIONS, mayStart, PACING_MS, pacingMessage, usageLabel, usageView, type UsageWarning, type WorkKind } from './pacing.ts';\r\nimport { isCli } from './clis.ts';\r\nimport { AgentTerminal } from './terminal.ts';\r\nimport { blockers, holdUps, issueSpecialty } from '../shared/issues.ts';\r\nimport { effectiveModel } from '../shared/models.ts';\r\nimport { CEO_ID } from '../shared/types.ts';\r\nimport type {\r\n AgentCli,\r\n AgentLook,\r\n AgentRole,\r\n AgentStatus,\r\n AgentTask,\r\n AgentView,\r\n CeoInfo,\r\n CliView,\r\n EffortLevel,\r\n HireRequestView,\r\n IssueInfo,\r\n LogLine,\r\n OfficeUpdateView,\r\n PhoneMessage,\r\n PreviewConfig,\r\n PreviewView,\r\n ProjectFolderView,\r\n PullInfo,\r\n QaCheck,\r\n QaView,\r\n RepoView,\r\n ServerEvent,\r\n SwarmSettings,\r\n WorldSnapshot,\r\n} from '../shared/types.ts';\r\n\r\n// ---------- persisted shape ----------\r\n\r\ninterface PersistedRepo {\r\n id: string;\r\n fullName: string;\r\n description: string;\r\n url: string;\r\n defaultBranch: string;\r\n floor: number;\r\n color: string;\r\n autoAssign: boolean;\r\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\r\n browserTesting: boolean;\r\n links: string[]; // other connected repos this floor's agents may read\r\n localPath: string | null; // the manager's own project folder (null: a clone under WORKSPACE_ROOT)\r\n mission: string;\r\n summary: string;\r\n qaBrief: string;\r\n preview: PreviewConfig; // how the floor's app runs for the preview monitor\r\n addedAt: number;\r\n}\r\n\r\ninterface PersistedAgent {\r\n id: string;\r\n name: string;\r\n repoId: string; // '' for the CEO, who works in the lobby\r\n role: AgentRole;\r\n title: string;\r\n specialty: string;\r\n brief: string;\r\n hiredBy: 'manager' | 'ceo';\r\n look: AgentLook;\r\n task: AgentTask | null;\r\n desk: number;\r\n color: string;\r\n hair: string;\r\n skin: string;\r\n model: string;\r\n effort: EffortLevel | '';\r\n cli: AgentCli | ''; // '' = the office's default CLI\r\n status: AgentStatus;\r\n issueNumber: number | null;\r\n issueTitle: string | null;\r\n branch: string | null;\r\n prNumber: number | null;\r\n prUrl: string | null;\r\n startedAt: number | null;\r\n endedAt: number | null;\r\n costUsd: number;\r\n turns: number;\r\n sessionId: string | null;\r\n sessionCli: AgentCli | null; // the CLI whose session sessionId is: only it can resume it\r\n lastError: string | null;\r\n logTail: LogLine[];\r\n}\r\n\r\n/** A pull request's trip through QA. */\r\ninterface QaRecord extends QaView {\r\n issueNumber: number | null;\r\n devSessionId: string | null; // the dev's Claude Code session, resumed to fix QA findings\r\n fixInstructions: string | null;\r\n sessionFailures: number;\r\n testedSha: string | null; // the head commit QA is testing\r\n passedSha: string | null; // the head commit QA signed off on: auto-merge merges exactly that\r\n fixReason: 'qa' | 'checks' | 'conflict' | null; // why it was last sent back to a developer\r\n mergeFixes: number; // times it went back for failing checks or conflicts\r\n retests: number; // QA rounds caused by merge fixes or new commits rather than by QA failing it\r\n pendingSince: number | null; // when auto-merge started waiting on its checks\r\n mergeRetryAt: number | null; // GitHub refused the merge: try again after this\r\n alerted: boolean; // the manager has been told it's stuck\r\n}\r\n\r\n/** Choices made when a project moves into the office. */\r\ninterface FloorOptions {\r\n mission?: string; // brief for the CEO to plan from\r\n autoAssign?: boolean; // free developers pick up backlog issues as soon as they're filed\r\n}\r\n\r\ninterface CeoState {\r\n queue: CeoJob[];\r\n job: CeoJob | null; // the job the CEO is on right now\r\n lastReviewAt: number | null;\r\n lastFingerprint: string | null; // company state at the last review; unchanged means the next review is skipped\r\n}\r\n\r\ninterface Persisted {\r\n settings: SwarmSettings;\r\n repos: PersistedRepo[];\r\n agents: PersistedAgent[];\r\n qa: QaRecord[];\r\n requests: HireRequestView[];\r\n ceo: CeoState;\r\n messages: PhoneMessage[];\r\n phoneReadAt: number;\r\n}\r\n\r\ninterface Shot {\r\n data: Buffer;\r\n mime: string;\r\n url: string | null;\r\n at: number;\r\n}\r\n\r\ninterface AgentRuntime {\r\n log: LogLine[];\r\n pending: LogLine[];\r\n session: SessionHandle | null;\r\n currentTool: string | null;\r\n browserUrl: string | null;\r\n screenshot: { data: Buffer; mime: string; at: number } | null;\r\n shots: Shot[]; // every screenshot of the current session (QA evidence)\r\n terminal: AgentTerminal | null; // their terminal, once they've run in the terminal runtime\r\n}\r\n\r\ninterface RepoRuntime {\r\n issues: IssueInfo[];\r\n pulls: PullInfo[];\r\n lastSync: number | null;\r\n syncError?: string;\r\n syncing: boolean;\r\n cloneStatus: RepoView['cloneStatus'];\r\n cloneError?: string;\r\n fetchedAt?: number; // when the latest issues/PRs fetch started\r\n lastMergedAt: string | null; // newest merge seen: a newer one means the folder needs a sync\r\n folderSync: string | null;\r\n merging: boolean;\r\n}\r\n\r\ninterface QaReport {\r\n verdict: 'pass' | 'fail';\r\n summary: string;\r\n checks: QaCheck[];\r\n commands: { command: string; result: string }[];\r\n screenshots: string[];\r\n fixInstructions?: string;\r\n}\r\n\r\n// ---------- flavour ----------\r\n\r\nconst FLOOR_COLORS = ['#ff8a5b', '#4fb3e8', '#8fd14f', '#c77dff', '#ffc93c', '#ff6fb5', '#2ec4b6', '#f25f5c'];\r\nconst SHIRTS = ['#e63946', '#457b9d', '#2a9d8f', '#f4a261', '#9b5de5', '#f15bb5', '#00bbf9', '#06d6a0', '#ffbe0b', '#8338ec', '#fb5607', '#3a86ff'];\r\nconst HAIR = ['#2b2118', '#6b4226', '#c68642', '#f2d16b', '#d94f30', '#1c1c1c', '#8e8e8e', '#5b3cc4', '#e76f51'];\r\nconst SKIN = ['#ffdbac', '#f1c27d', '#e0ac69', '#c68642', '#8d5524', '#ffe0bd'];\r\nconst DEV_NAMES = [\r\n 'Ada', 'Linus', 'Grace', 'Alan', 'Margaret', 'Dennis', 'Barbara', 'Ken', 'Radia', 'Guido', 'Hedy', 'Tim', 'Katherine',\r\n 'Bjarne', 'Frances', 'Edsger', 'Anita', 'Donald', 'Sophie', 'Yukihiro', 'Jean', 'Niklaus', 'Karen', 'Brendan',\r\n];\r\nconst QA_NAMES = ['Sherlock', 'Marple', 'Poirot', 'Nancy', 'Columbo', 'Fletcher', 'Watson', 'Morse', 'Holmes', 'Maigret'];\r\n\r\n// Names that get the feminine character look: everyone in the name pools above, plus common first names\r\n// for agents the manager names themselves. The manager can always change an agent's look in the console.\r\nconst FEMININE_NAMES = new Set(\r\n (\r\n 'ada grace margaret barbara radia hedy katherine frances anita sophie jean karen marple nancy fletcher ' +\r\n 'alice amanda amelia amy ana anna anne aisha astrid ava bella beth carla caroline charlotte chloe claire clara ' +\r\n 'diana elena elizabeth ella ellie emily emma eva fatima fiona freya georgia hannah harper helen holly ingrid iris ' +\r\n 'isabella ivy jane jasmine jessica julia kate laura leah leila lena lily linda lisa lucy maria marie mary maya mei ' +\r\n 'mia mila monica naomi natalie nina nora olivia paula priya rachel rose ruby sandra sara sarah scarlett sofia ' +\r\n 'stella susan tess tessa tina vera victoria yuki zara zoe'\r\n ).split(' '),\r\n);\r\nconst lookFor = (name: string): AgentLook => (FEMININE_NAMES.has(name.trim().split(/\\s+/)[0].toLowerCase()) ? 'feminine' : 'masculine');\r\nconst LOOKS: AgentLook[] = ['feminine', 'masculine'];\r\nconst MAX_DESKS: Record<AgentRole, number> = { dev: 12, qa: 3, ceo: 1 };\r\nconst MAX_QA_ROUNDS = 3;\r\n// Every agent runs Claude Opus 5.5 at medium effort unless the manager overrides it.\r\nconst DEFAULT_MODEL = 'claude-opus-5-5';\r\nconst EFFORTS: EffortLevel[] = ['low', 'medium', 'high', 'xhigh', 'max'];\r\n// The CEO thinks harder than the staff: Opus 5.5 at xhigh effort unless the manager changes it.\r\nconst CEO_MODEL = 'claude-opus-5-5';\r\nconst CEO_EFFORT: EffortLevel = 'xhigh';\r\nconst CEO_NAME = 'Morgan';\r\n// The CEO's own folder: its notes about the company live here. Repos are read through their clones.\r\nconst CEO_DIR = path.join(HOME_DIR, 'ceo');\r\nconst DEFAULT_PROJECTS_DIR = defaultProjectsDir(path.resolve(import.meta.dirname, '..'));\r\nconst MAX_PENDING_REQUESTS = 8;\r\nconst MAX_ISSUES_PER_JOB = 12;\r\nconst KEEP_MESSAGES = 200;\r\nconst KEEP_DECIDED_REQUESTS = 40;\r\n\r\nconst pick = <T>(arr: T[]) => arr[Math.floor(Math.random() * arr.length)];\r\nconst slugify = (s: string) =>\r\n s\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, '-')\r\n .replace(/^-|-$/g, '')\r\n .slice(0, 40) || 'agent';\r\n\r\nconst BUSY: AgentStatus[] = ['preparing', 'working'];\r\nconst FREE: AgentStatus[] = ['idle', 'done'];\r\n// An agent whose session failed sits out this long before taking new work, so a broken setup can't burn through the queue.\r\nconst ERROR_COOLDOWN_MS = 2 * 60_000;\r\n// Auto-assign stops retrying an issue after this many failed sessions; the manager can still assign it by hand.\r\nconst MAX_ISSUE_FAILURES = 2;\r\n// How long the office waits after Claude's usage limit is hit when Claude doesn't say when it resets.\r\nconst LIMIT_PAUSE_MS = 15 * 60_000;\r\nconst oneLine = (err: unknown) => (err instanceof Error ? err.message : String(err)).split(/\\r?\\n/)[0].slice(0, 200);\r\n\r\n// The latest browser screenshot per agent is kept on disk so monitors survive a server restart.\r\nconst SCREENS_DIR = path.join(HOME_DIR, 'screens');\r\nconst MIME_EXT: Record<string, string> = { 'image/png': 'png', 'image/jpeg': 'jpg', 'image/webp': 'webp', 'image/svg+xml': 'svg' };\r\nconst screenFile = (agentId: string, mime: string) => path.join(SCREENS_DIR, `${agentId}.${MIME_EXT[mime] ?? 'img'}`);\r\n\r\nasync function loadScreen(agentId: string): Promise<{ data: Buffer; mime: string; at: number } | null> {\r\n for (const [mime, ext] of Object.entries(MIME_EXT)) {\r\n const file = path.join(SCREENS_DIR, `${agentId}.${ext}`);\r\n try {\r\n const [data, stat] = await Promise.all([fs.readFile(file), fs.stat(file)]);\r\n return { data, mime, at: stat.mtimeMs };\r\n } catch {\r\n // try the next extension\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nasync function removeScreens(agentId: string) {\r\n await Promise.all(Object.values(MIME_EXT).map((ext) => fs.rm(path.join(SCREENS_DIR, `${agentId}.${ext}`), { force: true })));\r\n}\r\n\r\n// Each agent's terminal (screen and scrollback) is saved too, so the office shows what they did after a restart.\r\nconst TERMINALS_DIR = path.join(HOME_DIR, 'terminals');\r\nconst terminalFile = (agentId: string) => path.join(TERMINALS_DIR, `${agentId}.ansi`);\r\nconst TERMINAL_SAVE_MS = 20_000;\r\n\r\n// ---------- QA report ----------\r\n\r\nconst QA_SCHEMA: Record<string, unknown> = {\r\n type: 'object',\r\n additionalProperties: false,\r\n required: ['verdict', 'summary', 'checks', 'commands', 'screenshots'],\r\n properties: {\r\n verdict: { type: 'string', enum: ['pass', 'fail'], description: 'pass only if the change works and meets the issue requirements' },\r\n summary: { type: 'string', description: 'Two to four sentences for the pull request comment.' },\r\n checks: {\r\n type: 'array',\r\n description: 'Each acceptance criterion, test run or scenario you verified.',\r\n items: {\r\n type: 'object',\r\n additionalProperties: false,\r\n required: ['name', 'result', 'details'],\r\n properties: {\r\n name: { type: 'string' },\r\n result: { type: 'string', enum: ['pass', 'fail', 'skip'] },\r\n details: { type: 'string', description: 'What you did and what you observed.' },\r\n },\r\n },\r\n },\r\n commands: {\r\n type: 'array',\r\n description: 'Test suites, linters, builds and other commands you ran.',\r\n items: {\r\n type: 'object',\r\n additionalProperties: false,\r\n required: ['command', 'result'],\r\n properties: { command: { type: 'string' }, result: { type: 'string', description: 'e.g. \"42 passed, 0 failed\"' } },\r\n },\r\n },\r\n screenshots: {\r\n type: 'array',\r\n description: 'One short caption per screenshot you took with browser_take_screenshot, in the order you took them.',\r\n items: { type: 'string' },\r\n },\r\n fixInstructions: { type: 'string', description: 'When the verdict is fail: precise, actionable instructions for the developer.' },\r\n },\r\n};\r\n\r\nfunction parseReport(result: SessionResult): QaReport | null {\r\n let raw: unknown = result.structured;\r\n if (!raw && result.text) {\r\n // Terminal agents end their last message with the report, usually in a ```json block.\r\n const fenced = [...result.text.matchAll(/```(?:json)?\\s*(\\{[\\s\\S]*?\\})\\s*```/g)].map((m) => m[1]).reverse();\r\n for (const json of [...fenced, result.text.match(/\\{[\\s\\S]*\\}/)?.[0]].filter((j): j is string => !!j)) {\r\n try {\r\n raw = JSON.parse(json);\r\n break;\r\n } catch {\r\n raw = null;\r\n }\r\n }\r\n }\r\n if (!raw || typeof raw !== 'object') return null;\r\n const r = raw as Partial<QaReport>;\r\n if (r.verdict !== 'pass' && r.verdict !== 'fail') return null;\r\n return {\r\n verdict: r.verdict,\r\n summary: String(r.summary ?? ''),\r\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 ?? '') })) : [],\r\n commands: Array.isArray(r.commands) ? r.commands.map((c) => ({ command: String(c.command ?? ''), result: String(c.result ?? '') })) : [],\r\n screenshots: Array.isArray(r.screenshots) ? r.screenshots.map(String) : [],\r\n fixInstructions: r.fixInstructions ? String(r.fixInstructions) : undefined,\r\n };\r\n}\r\n\r\nconst cell = (s: string) => s.replace(/\\|/g, '\\\\|').replace(/\\r?\\n/g, '<br>');\r\nconst ICON = { pass: '\u2705', fail: '\u274C', skip: '\u23ED\uFE0F' } as const;\r\n\r\nexport { HttpError };\r\n\r\nexport class Swarm {\r\n private state: Persisted = {\r\n settings: {\r\n sessionLimit: 0,\r\n defaultModel: DEFAULT_MODEL,\r\n defaultEffort: 'medium',\r\n runtime: 'terminal',\r\n defaultCli: 'claude',\r\n hiring: 'approve',\r\n teamCap: 6,\r\n ceoHeartbeatMin: 60,\r\n managerName: '',\r\n companyName: '',\r\n projectsDir: DEFAULT_PROJECTS_DIR,\r\n setupDone: false,\r\n tutorialStep: 0,\r\n autoUpdate: true,\r\n pacingSessions: DEFAULT_PACING_SESSIONS,\r\n },\r\n repos: [],\r\n agents: [],\r\n qa: [],\r\n requests: [],\r\n ceo: { queue: [], job: null, lastReviewAt: null, lastFingerprint: null },\r\n messages: [],\r\n phoneReadAt: 0,\r\n };\r\n /**\r\n * The CEO's office tools. Every session gets its own server: one can only be connected to one session at a time, so\r\n * a shared one left the next session connected but without any tools while an earlier session still held it.\r\n */\r\n private officeTools(): OfficeTools {\r\n return createOfficeTools({\r\n companyStatus: () => this.companyStatus(),\r\n agentDetail: (a) => this.agentDetail(a),\r\n setFloorProfile: (a) => this.setFloorProfile(a),\r\n updateJob: (a) => this.updateJob(a),\r\n proposeHire: (a) => this.proposeHire(a),\r\n proposeLetGo: (a) => this.proposeLetGo(a),\r\n fileIssue: (a) => this.fileIssue(a),\r\n routeIssue: (a) => this.routeIssue(a),\r\n });\r\n }\r\n private ceoIssues = new IssueCap(MAX_ISSUES_PER_JOB); // issues filed during the current CEO job\r\n private messageSeq = 1;\r\n private agentRt = new Map<string, AgentRuntime>();\r\n private repoRt = new Map<string, RepoRuntime>();\r\n private clients = new Set<WebSocket>();\r\n private user: string | null = null;\r\n private ghError: string | undefined;\r\n private saveTimer: NodeJS.Timeout | null = null;\r\n private flushTimer: NodeJS.Timeout | null = null;\r\n private logSeq = 1;\r\n private previews: Previews;\r\n private officeHead: string | null = null; // the commit the office runs (null: not a git checkout, so no self-update)\r\n private officeUpdate = {\r\n behind: 0,\r\n requested: false,\r\n postponedUntil: null as number | null,\r\n postponedBehind: 0,\r\n failed: null as string | null,\r\n failedBehind: null as number | null,\r\n drainingSince: null as number | null,\r\n sent: false,\r\n handedOver: false, // sessions cut off by the hand-over are the restarted office's to recover\r\n };\r\n private lastOfficeView = '';\r\n private clis: CliView[] = []; // coding-agent CLIs found on this machine (detected at startup)\r\n\r\n constructor(private backend: Backend) {\r\n this.previews = new Previews(backend, {\r\n emit: (id) => {\r\n const r = this.state.repos.find((x) => x.id === id);\r\n if (r && this.repoRt.has(id)) this.emitRepo(r);\r\n },\r\n pulls: (id) => this.repoRt.get(id)?.pulls ?? [],\r\n });\r\n }\r\n\r\n // ---------- lifecycle ----------\r\n\r\n async init() {\r\n try {\r\n const raw = await fs.readFile(STATE_FILE, 'utf8');\r\n const loaded = JSON.parse(raw) as Partial<Persisted>;\r\n this.state = {\r\n settings: { ...this.state.settings, ...loaded.settings },\r\n repos: (loaded.repos ?? []).map((r) => ({\r\n ...r,\r\n autoMerge: r.autoMerge ?? true,\r\n links: r.links ?? [],\r\n mission: r.mission ?? '',\r\n summary: r.summary ?? '',\r\n qaBrief: r.qaBrief ?? '',\r\n localPath: r.localPath ?? null,\r\n preview: { command: r.preview?.command ?? null, env: { ...r.preview?.env } },\r\n })),\r\n agents: (loaded.agents ?? []).map((a) => ({\r\n ...a,\r\n effort: a.effort ?? '',\r\n role: a.role ?? 'dev',\r\n title: a.title ?? '',\r\n specialty: a.specialty ?? '',\r\n brief: a.brief ?? '',\r\n hiredBy: a.hiredBy ?? 'manager',\r\n look: a.look ?? lookFor(a.name),\r\n task: a.task ?? (a.issueNumber ? 'issue' : null),\r\n cli: isCli(a.cli) ? a.cli : '',\r\n sessionCli: a.sessionCli ?? (a.sessionId ? 'claude' : null),\r\n })),\r\n qa: (loaded.qa ?? []).map((q) => ({\r\n ...q,\r\n testedSha: q.testedSha ?? null,\r\n passedSha: q.passedSha ?? null,\r\n fixReason: q.fixReason ?? null,\r\n mergeFixes: q.mergeFixes ?? 0,\r\n retests: q.retests ?? 0,\r\n pendingSince: q.pendingSince ?? null,\r\n mergeRetryAt: q.mergeRetryAt ?? null,\r\n alerted: q.alerted ?? false,\r\n mergeNote: null,\r\n })),\r\n requests: loaded.requests ?? [],\r\n ceo: { ...this.state.ceo, ...loaded.ceo },\r\n messages: loaded.messages ?? [],\r\n phoneReadAt: loaded.phoneReadAt ?? 0,\r\n };\r\n for (const m of this.state.messages) this.messageSeq = Math.max(this.messageSeq, m.id + 1);\r\n if (!EFFORTS.includes(this.state.settings.defaultEffort)) this.state.settings.defaultEffort = 'medium';\r\n if (this.state.settings.runtime !== 'sdk') this.state.settings.runtime = 'terminal';\r\n if (!isCli(this.state.settings.defaultCli)) this.state.settings.defaultCli = 'claude';\r\n if (!this.state.settings.defaultModel && this.state.settings.defaultCli === 'claude') this.state.settings.defaultModel = DEFAULT_MODEL;\r\n // \"Max concurrent sessions\" (default 4) became an optional session limit. The old default goes; a limit the manager chose stays.\r\n const old = this.state.settings as SwarmSettings & { maxConcurrent?: number; permissionMode?: string };\r\n if (old.maxConcurrent !== undefined) {\r\n if (loaded.settings?.sessionLimit === undefined) old.sessionLimit = old.maxConcurrent === 4 ? 0 : old.maxConcurrent;\r\n delete old.maxConcurrent;\r\n }\r\n delete old.permissionMode; // the office's rules are instructions now, not a permission mode\r\n // Offices that were set up before the setup wizard existed skip it.\r\n if (loaded.settings && loaded.settings.setupDone === undefined && this.state.repos.length > 0) {\r\n Object.assign(this.state.settings, { setupDone: true, tutorialStep: -1 });\r\n }\r\n } catch {\r\n // first run\r\n }\r\n for (const r of this.state.repos) if (r.localPath) this.backend.setLocalPath(r.fullName, r.localPath);\r\n const interrupted: PersistedAgent[] = [];\r\n for (const a of this.state.agents) {\r\n const tail = a.logTail ?? [];\r\n for (const l of tail) this.logSeq = Math.max(this.logSeq, l.id + 1);\r\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) });\r\n }\r\n // CLIs the terminal keeper kept running through the restart go back into their terminals, and busy ones carry on.\r\n // (The CEO's session is resumed instead: its office tools live in this process.)\r\n const back = await this.backend\r\n .reconnectClis((id) => {\r\n const a = this.state.agents.find((x) => x.id === id);\r\n return a && a.role !== 'ceo' ? this.terminalFor(a) : null;\r\n })\r\n .catch((err) => {\r\n console.warn('could not reconnect to the terminal keeper', err);\r\n return [];\r\n });\r\n const carryOn: PersistedAgent[] = [];\r\n for (const a of this.state.agents) {\r\n if (!BUSY.includes(a.status)) continue;\r\n if (back.some((c) => c.agentId === a.id && c.busy)) {\r\n carryOn.push(a);\r\n continue;\r\n }\r\n a.status = 'stopped';\r\n a.lastError = 'The swarm server restarted while this agent was working.';\r\n interrupted.push(a);\r\n }\r\n for (const c of back) if (c.busy && !carryOn.some((a) => a.id === c.agentId)) this.agentRt.get(c.agentId)?.terminal?.releaseIdle?.();\r\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 });\r\n for (const a of carryOn) this.reattachSession(a);\r\n this.backend.hooksReady();\r\n\r\n try {\r\n this.user = await this.backend.user();\r\n } catch (err) {\r\n this.ghError = `GitHub CLI is not ready: ${(err as Error).message}. Run \"gh auth login\".`;\r\n console.warn(this.ghError);\r\n }\r\n\r\n if (this.backend.demo && this.state.repos.length === 0) {\r\n // The demo opens on a busy office; the tutorial still runs so it can be tried.\r\n Object.assign(this.state.settings, { setupDone: true, managerName: 'Demo Manager', companyName: 'Demo Co.' });\r\n for (const r of await this.backend.listMyRepos()) {\r\n const repo = await this.connectRepo(r.nameWithOwner);\r\n for (let i = 0; i < (repo.floor === 1 ? 5 : 3); i++) this.hireAgent(repo.id, {});\r\n this.updateRepo(repo.id, { autoAssign: true });\r\n }\r\n }\r\n for (const r of this.state.repos) this.ensureQaTester(r);\r\n this.ensureCeo(interrupted);\r\n\r\n for (const r of this.state.repos) void this.cloneRepo(r.id);\r\n await Promise.all(this.state.repos.map((r) => this.syncRepo(r.id)));\r\n // Anything still alive in a desk (or a preview) is left over from before the restart, except around the CLIs that\r\n // kept running through it: their dev servers and commands are theirs.\r\n await Promise.all([\r\n ...this.state.agents.map((a) => {\r\n const repo = this.state.repos.find((r) => r.id === a.repoId);\r\n if (!repo || back.some((c) => c.agentId === a.id)) return undefined;\r\n return this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined);\r\n }),\r\n this.previews.clearOrphans(this.state.repos),\r\n ]);\r\n for (const r of this.state.repos) void this.previews.refreshDefault(r);\r\n this.recover(interrupted);\r\n this.officeHead = await this.backend.office.head();\r\n const updated = await this.backend.office.takeLastUpdate().catch(() => null);\r\n if (updated) await this.reportUpdate(updated);\r\n setInterval(() => this.state.repos.forEach((r, i) => setTimeout(() => void this.syncRepo(r.id), i * 1500)), SYNC_INTERVAL_MS);\r\n setInterval(() => this.schedule(), SCHEDULER_INTERVAL_MS);\r\n setInterval(() => void this.saveTerminals(), TERMINAL_SAVE_MS);\r\n void this.backend\r\n .detectClis()\r\n .then((clis) => {\r\n this.clis = clis;\r\n this.broadcast({ type: 'clis', clis });\r\n })\r\n .catch((err) => console.warn('could not look for agent CLIs', err));\r\n this.save();\r\n setTimeout(() => this.schedule(), 1000);\r\n }\r\n\r\n /** Agents cut off by a server restart pick their Claude Code session back up (QA and demo agents start over). */\r\n private recover(agents: PersistedAgent[]) {\r\n for (const a of agents) {\r\n if (a.task === 'qa' || this.backend.demo || !a.sessionId || !a.branch) {\r\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Starting over from the queue.' }]);\r\n const rec = a.task === 'qa' ? this.state.qa.find((q) => q.qaAgentId === a.id && q.status === 'testing') : undefined;\r\n if (rec) this.setQa(rec, { status: 'queued' });\r\n const fix = a.task === 'fix' ? this.state.qa.find((q) => q.devAgentId === a.id && q.status === 'fixing') : undefined;\r\n if (fix) this.setQa(fix, { status: 'failed' });\r\n this.clearTask(a);\r\n continue;\r\n }\r\n if (this.slotsFull()) continue; // stays 'stopped'; the manager can resume it later\r\n void this.message(a.id, 'The office server restarted while you were working. Check the state of your worktree and continue where you left off.').catch((err) =>\r\n console.warn(`could not resume ${a.name}`, err),\r\n );\r\n }\r\n }\r\n\r\n // ---------- views ----------\r\n\r\n private repoView(r: PersistedRepo): RepoView {\r\n const rt = this.repoRt.get(r.id)!;\r\n return {\r\n id: r.id,\r\n fullName: r.fullName,\r\n description: r.description,\r\n url: r.url,\r\n defaultBranch: r.defaultBranch,\r\n floor: r.floor,\r\n color: r.color,\r\n autoAssign: r.autoAssign,\r\n autoMerge: r.autoMerge,\r\n folderSync: rt.folderSync,\r\n browserTesting: r.browserTesting,\r\n links: r.links,\r\n mission: r.mission,\r\n summary: r.summary,\r\n qaBrief: r.qaBrief,\r\n localPath: r.localPath,\r\n checkoutPath: this.backend.mainDir(r.fullName),\r\n cloneStatus: rt.cloneStatus,\r\n cloneError: rt.cloneError,\r\n issues: rt.issues,\r\n pulls: rt.pulls,\r\n lastSync: rt.lastSync,\r\n syncError: rt.syncError,\r\n previewConfig: r.preview,\r\n preview: this.previews.view(r),\r\n };\r\n }\r\n\r\n private agentView(a: PersistedAgent, withLog: boolean): AgentView {\r\n const rt = this.agentRt.get(a.id)!;\r\n return {\r\n id: a.id,\r\n name: a.name,\r\n repoId: a.repoId,\r\n role: a.role,\r\n title: a.title,\r\n specialty: a.specialty,\r\n brief: a.brief,\r\n hiredBy: a.hiredBy,\r\n look: a.look,\r\n task: a.task,\r\n desk: a.desk,\r\n color: a.color,\r\n hair: a.hair,\r\n skin: a.skin,\r\n model: a.model,\r\n effort: a.effort,\r\n cli: a.cli,\r\n terminal: !!rt.terminal,\r\n status: a.status,\r\n issueNumber: a.issueNumber,\r\n issueTitle: a.issueTitle,\r\n branch: a.branch,\r\n prNumber: a.prNumber,\r\n prUrl: a.prUrl,\r\n currentTool: rt.currentTool,\r\n startedAt: a.startedAt,\r\n endedAt: a.endedAt,\r\n costUsd: a.costUsd,\r\n turns: a.turns,\r\n browserUrl: rt.browserUrl,\r\n hasScreenshot: !!rt.screenshot,\r\n screenshotAt: rt.screenshot?.at ?? null,\r\n lastError: a.lastError,\r\n log: withLog ? rt.log : [],\r\n };\r\n }\r\n\r\n private qaView(q: QaRecord): QaView {\r\n return {\r\n repoId: q.repoId,\r\n prNumber: q.prNumber,\r\n status: q.status,\r\n round: q.round,\r\n devAgentId: q.devAgentId,\r\n qaAgentId: q.qaAgentId,\r\n summary: q.summary,\r\n checks: q.checks,\r\n commentUrl: q.commentUrl,\r\n mergeNote: q.mergeNote,\r\n updatedAt: q.updatedAt,\r\n };\r\n }\r\n\r\n snapshot(): WorldSnapshot {\r\n return {\r\n user: this.user,\r\n ghReady: !this.ghError,\r\n ghError: this.ghError,\r\n demo: this.backend.demo,\r\n workspaceRoot: WORKSPACE_ROOT,\r\n settings: this.state.settings,\r\n repos: this.state.repos.map((r) => this.repoView(r)),\r\n agents: this.state.agents.map((a) => this.agentView(a, true)),\r\n qa: this.state.qa.map((q) => this.qaView(q)),\r\n requests: this.state.requests,\r\n ceo: this.ceoInfo(),\r\n messages: this.state.messages.slice(-100),\r\n phoneReadAt: this.state.phoneReadAt,\r\n usage: this.usageNow(),\r\n clis: this.clis,\r\n officeCommit: this.officeHead?.slice(0, 7) ?? null,\r\n officeUpdate: this.officeHead ? this.officeUpdateView() : undefined,\r\n };\r\n }\r\n\r\n screenshot(agentId: string) {\r\n return this.agentRt.get(agentId)?.screenshot ?? null;\r\n }\r\n\r\n // ---------- clients ----------\r\n\r\n addClient(ws: WebSocket) {\r\n this.clients.add(ws);\r\n ws.on('close', () => this.clients.delete(ws));\r\n this.send(ws, { type: 'snapshot', data: this.snapshot() });\r\n }\r\n\r\n private send(ws: WebSocket, ev: ServerEvent) {\r\n if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(ev));\r\n }\r\n\r\n private broadcast(ev: ServerEvent) {\r\n const msg = JSON.stringify(ev);\r\n for (const ws of this.clients) if (ws.readyState === ws.OPEN) ws.send(msg);\r\n }\r\n\r\n private toast(level: 'info' | 'success' | 'error', text: string) {\r\n this.broadcast({ type: 'toast', level, text });\r\n }\r\n\r\n private emitRepo(r: PersistedRepo) {\r\n this.broadcast({ type: 'repo', repo: this.repoView(r) });\r\n }\r\n\r\n private emitAgent(a: PersistedAgent) {\r\n // A session can finish after its agent was let go (their floor disconnected mid-task); they're gone, so say nothing.\r\n if (!this.agentRt.has(a.id)) return;\r\n const { log: _log, ...rest } = this.agentView(a, false);\r\n this.broadcast({ type: 'agent', agent: rest });\r\n }\r\n\r\n private setQa(rec: QaRecord, patch: Partial<QaRecord>) {\r\n Object.assign(rec, patch, { updatedAt: Date.now() });\r\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\r\n this.save();\r\n }\r\n\r\n private appendLog(a: PersistedAgent, entries: LogEntry[]) {\r\n const rt = this.agentRt.get(a.id);\r\n if (!rt) return;\r\n const t = Date.now();\r\n for (const e of entries) {\r\n const line: LogLine = { id: this.logSeq++, t, kind: e.kind, text: e.text, tool: e.tool };\r\n rt.log.push(line);\r\n rt.pending.push(line);\r\n }\r\n if (rt.log.length > LOG_BUFFER) rt.log.splice(0, rt.log.length - LOG_BUFFER);\r\n if (!this.flushTimer) this.flushTimer = setTimeout(() => this.flushLogs(), 120);\r\n }\r\n\r\n private flushLogs() {\r\n this.flushTimer = null;\r\n for (const [agentId, rt] of this.agentRt) {\r\n if (rt.pending.length === 0) continue;\r\n this.broadcast({ type: 'log', agentId, lines: rt.pending });\r\n rt.pending = [];\r\n }\r\n this.save();\r\n }\r\n\r\n // ---------- persistence ----------\r\n\r\n private save() {\r\n if (this.saveTimer) return;\r\n this.saveTimer = setTimeout(() => void this.writeState().catch((err) => console.warn('could not save the state', err)), 1500);\r\n }\r\n\r\n /** Write the state file now, e.g. before the office stops or hands itself to the launcher. */\r\n private async writeState() {\r\n if (this.saveTimer) clearTimeout(this.saveTimer);\r\n this.saveTimer = null;\r\n for (const a of this.state.agents) a.logTail = (this.agentRt.get(a.id)?.log ?? []).slice(-200);\r\n await fs.mkdir(path.dirname(STATE_FILE), { recursive: true });\r\n const tmp = `${STATE_FILE}.tmp`;\r\n await fs.writeFile(tmp, JSON.stringify(this.state, null, 2));\r\n await fs.rename(tmp, STATE_FILE);\r\n }\r\n\r\n // ---------- lookups ----------\r\n\r\n private repo(id: string) {\r\n const r = this.state.repos.find((x) => x.id === id);\r\n if (!r) throw new HttpError(404, `Repo ${id} is not connected`);\r\n return r;\r\n }\r\n\r\n private agent(id: string) {\r\n const a = this.state.agents.find((x) => x.id === id);\r\n if (!a) throw new HttpError(404, `No agent ${id}`);\r\n return a;\r\n }\r\n\r\n private running() {\r\n return this.state.agents.filter((a) => BUSY.includes(a.status)).length;\r\n }\r\n\r\n /** True when the manager has set a session limit and every slot is taken. */\r\n private slotsFull() {\r\n const limit = this.state.settings.sessionLimit;\r\n return limit > 0 && this.running() >= limit;\r\n }\r\n\r\n private agentSlug(a: PersistedAgent) {\r\n return `${slugify(a.name)}-${a.id.slice(0, 4)}`;\r\n }\r\n\r\n private clearTask(a: PersistedAgent) {\r\n Object.assign(a, { status: 'idle', task: null, issueNumber: null, issueTitle: null, branch: null, prNumber: null, prUrl: null, lastError: null });\r\n this.emitAgent(a);\r\n }\r\n\r\n // ---------- GitHub / repos ----------\r\n\r\n listGithubRepos(owner?: string) {\r\n return this.backend.listMyRepos(owner);\r\n }\r\n\r\n /**\r\n * Give a GitHub repo a floor. Its main checkout is one of your own folders: the one you picked, else the folder in\r\n * your projects folder that already has it as origin, else a fresh clone into your projects folder.\r\n */\r\n async connectRepo(fullName: string, opts: FloorOptions & { localPath?: string } = {}): Promise<RepoView> {\r\n const existing = this.state.repos.find((r) => r.id.toLowerCase() === fullName.toLowerCase());\r\n if (existing) throw new HttpError(409, `${fullName} is already floor ${existing.floor}`);\r\n const meta = await this.backend.repoMeta(fullName);\r\n const folder = opts.localPath ?? (await this.projectFolderFor(meta.nameWithOwner));\r\n const floor = this.state.repos.reduce((m, r) => Math.max(m, r.floor), 0) + 1;\r\n const repo: PersistedRepo = {\r\n id: meta.nameWithOwner,\r\n fullName: meta.nameWithOwner,\r\n description: meta.description,\r\n url: meta.url,\r\n defaultBranch: meta.defaultBranch,\r\n floor,\r\n color: FLOOR_COLORS[(floor - 1) % FLOOR_COLORS.length],\r\n autoAssign: !!opts.autoAssign,\r\n autoMerge: true,\r\n browserTesting: true,\r\n links: [],\r\n localPath: folder,\r\n mission: (opts.mission ?? '').trim().slice(0, 4000),\r\n summary: '',\r\n qaBrief: '',\r\n preview: { ...DEFAULT_PREVIEW, env: {} },\r\n addedAt: Date.now(),\r\n };\r\n this.backend.setLocalPath(repo.fullName, folder);\r\n this.state.repos.push(repo);\r\n this.repoRt.set(repo.id, { issues: [], pulls: [], lastSync: null, syncing: false, cloneStatus: 'pending', lastMergedAt: null, folderSync: null, merging: false });\r\n this.save();\r\n this.emitRepo(repo);\r\n this.toast('success', `${repo.fullName} moved into floor ${floor}`);\r\n this.ensureQaTester(repo);\r\n void this.cloneRepo(repo.id);\r\n void this.syncRepo(repo.id);\r\n // The CEO studies every new floor and proposes the team it needs.\r\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\r\n return this.repoView(repo);\r\n }\r\n\r\n /** Where a GitHub repo's checkout goes when you connect it without picking a folder. */\r\n private async projectFolderFor(fullName: string): Promise<string> {\r\n const root = this.state.settings.projectsDir;\r\n const folders = await this.backend.scanProjects(root).catch(() => []);\r\n const match = folders.find((f) => f.github?.toLowerCase() === fullName.toLowerCase());\r\n if (match) return match.path;\r\n const name = fullName.split('/')[1];\r\n const taken = folders.find((f) => f.name.toLowerCase() === name.toLowerCase());\r\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.`);\r\n return path.join(root, name); // cloned there when the floor opens\r\n }\r\n\r\n /** A brand-new project: a folder in your projects folder, pushed to a new GitHub repo. */\r\n async createRepo(name: string, opts: FloorOptions & { description?: string; visibility: 'private' | 'public'; owner?: string }) {\r\n if (!/^[A-Za-z0-9._-]+$/.test(name)) throw new HttpError(400, 'Project names may only contain letters, numbers, \".\", \"-\" and \"_\"');\r\n const created = await this.backend.createProject(this.state.settings.projectsDir, name, opts).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n return this.connectRepo(created.fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: created.path });\r\n }\r\n\r\n /** The folders in your projects folder (or another folder you point at), and which are floors already. */\r\n async listProjectFolders(dir?: string): Promise<{ root: string; folders: ProjectFolderView[] }> {\r\n const root = dir?.trim() ? path.resolve(dir.trim()) : this.state.settings.projectsDir;\r\n const folders = await this.backend.scanProjects(root).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n const same = (a: string, b: string) => path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase();\r\n const floorOf = (f: { path: string; github: string | null }) =>\r\n this.state.repos.find((r) => (r.localPath && same(r.localPath, f.path)) || (f.github && r.id.toLowerCase() === f.github.toLowerCase()))?.floor ?? null;\r\n return { root, folders: folders.map((f) => ({ name: f.name, path: f.path, git: f.git, github: f.github, floor: floorOf(f) })) };\r\n }\r\n\r\n /** Give one of your folders a floor. It must already be on GitHub; otherwise publish it first. */\r\n async connectFolder(dir: string, opts: FloorOptions = {}) {\r\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\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.`);\r\n return this.connectRepo(f.github, { ...opts, localPath: f.path });\r\n }\r\n\r\n /** Put one of your folders on GitHub (only what's committed goes up), then give it a floor. */\r\n async publishFolder(dir: string, opts: FloorOptions & { name?: string; visibility: 'private' | 'public'; description?: string }) {\r\n const f = await this.backend.inspectFolder(dir).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n const name = (opts.name?.trim() || f.name).replace(/[^A-Za-z0-9._-]+/g, '-');\r\n const fullName = await this.backend.publishFolder(f.path, { name, visibility: opts.visibility, description: opts.description }).catch((err: Error) => {\r\n throw new HttpError(400, err.message);\r\n });\r\n return this.connectRepo(fullName, { mission: opts.mission, autoAssign: opts.autoAssign, localPath: f.path });\r\n }\r\n\r\n disconnectRepo(id: string) {\r\n const repo = this.repo(id);\r\n this.state.ceo.queue = this.state.ceo.queue.filter((j) => j.repoId !== id);\r\n for (const r of this.state.requests.filter((x) => x.repoId === id && x.status === 'pending')) {\r\n this.decide(r, { status: 'rejected', note: 'The floor was disconnected.', decidedBy: null });\r\n }\r\n for (const a of this.state.agents.filter((x) => x.repoId === id)) this.fireAgent(a.id, true);\r\n void this.previews.remove({ ...repo });\r\n this.state.repos = this.state.repos.filter((r) => r.id !== id);\r\n for (const q of this.state.qa.filter((x) => x.repoId === id)) this.broadcast({ type: 'qaRemoved', repoId: id, prNumber: q.prNumber });\r\n this.state.qa = this.state.qa.filter((q) => q.repoId !== id);\r\n for (const r of this.state.repos) r.links = r.links.filter((l) => l !== id);\r\n this.repoRt.delete(id);\r\n // Keep floors contiguous.\r\n this.state.repos.sort((a, b) => a.floor - b.floor).forEach((r, i) => (r.floor = i + 1));\r\n this.backend.setLocalPath(repo.fullName, null);\r\n this.save();\r\n this.broadcast({ type: 'repoRemoved', repoId: id });\r\n for (const r of this.state.repos) this.emitRepo(r);\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)`);\r\n }\r\n\r\n updateRepo(\r\n id: string,\r\n patch: Partial<Pick<PersistedRepo, 'autoAssign' | 'autoMerge' | 'browserTesting' | 'color' | 'links' | 'mission' | 'summary' | 'qaBrief'>> & { previewCommand?: unknown; previewEnv?: unknown },\r\n ) {\r\n const repo = this.repo(id);\r\n const preview = parsePreviewPatch(patch.previewCommand, patch.previewEnv);\r\n repo.preview = { ...repo.preview, ...preview };\r\n if (preview.command === null) void this.previews.refreshDefault(repo);\r\n if (patch.autoAssign !== undefined) repo.autoAssign = !!patch.autoAssign;\r\n if (patch.autoMerge !== undefined) {\r\n repo.autoMerge = !!patch.autoMerge;\r\n if (repo.autoMerge) void this.syncRepo(repo.id);\r\n }\r\n if (patch.browserTesting !== undefined) repo.browserTesting = !!patch.browserTesting;\r\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) repo.color = patch.color;\r\n if (Array.isArray(patch.links)) repo.links = patch.links.filter((l) => l !== id && this.state.repos.some((r) => r.id === l));\r\n if (typeof patch.mission === 'string') repo.mission = patch.mission.trim().slice(0, 4000);\r\n if (typeof patch.summary === 'string') repo.summary = patch.summary.trim().slice(0, 140);\r\n if (typeof patch.qaBrief === 'string') repo.qaBrief = patch.qaBrief.trim().slice(0, 2500);\r\n this.save();\r\n this.emitRepo(repo);\r\n setTimeout(() => this.schedule(), 200);\r\n return this.repoView(repo);\r\n }\r\n\r\n // ---------- auto-merge ----------\r\n\r\n /**\r\n * Auto-merge (floors with it on): a swarm PR merges itself once QA has signed off on its latest commit and GitHub's\r\n * checks are green. Failing checks and merge conflicts go back to a developer; new commits after QA's sign-off send\r\n * it back to QA. Merging deletes the remote branch, and the floor's folder then fast-forwards (syncRepo sees the merge).\r\n */\r\n private async advanceMerges(repo: PersistedRepo) {\r\n const rt = this.repoRt.get(repo.id);\r\n if (!rt || !repo.autoMerge || rt.merging) return;\r\n rt.merging = true;\r\n let merged = false;\r\n try {\r\n for (const rec of this.state.qa.filter((q) => q.repoId === repo.id && q.status === 'passed')) {\r\n const pr = rt.pulls.find((p) => p.number === rec.prNumber && p.state === 'OPEN');\r\n if (!pr || !pr.headRefName.startsWith('swarm/')) continue; // people's own PRs are theirs to merge\r\n // Only act on PR data fetched after the record last changed (a fix may have just pushed).\r\n if ((rt.fetchedAt ?? 0) < rec.updatedAt) continue;\r\n try {\r\n if (await this.advanceMerge(repo, rec, pr)) merged = true;\r\n } catch (err) {\r\n console.warn(`auto-merge of ${repo.fullName}#${pr.number} failed`, err);\r\n this.mergeNote(rec, `auto-merge hit a problem: ${oneLine(err)}`);\r\n }\r\n }\r\n } finally {\r\n rt.merging = false;\r\n }\r\n if (merged) {\r\n await this.syncRepo(repo.id);\r\n setTimeout(() => this.schedule(), 200);\r\n }\r\n }\r\n\r\n /** One step toward merging a QA-passed PR. Returns true when it merged. */\r\n private async advanceMerge(repo: PersistedRepo, rec: QaRecord, pr: PullInfo): Promise<boolean> {\r\n let step = mergeStep(pr, rec, Date.now(), { base: repo.defaultBranch });\r\n if (step.do === 'details') {\r\n // GitHub works mergeability out lazily and lists often say UNKNOWN; asking about the PR itself gets an answer.\r\n const d = await this.backend.prDetails(repo.fullName, pr.number);\r\n pr = { ...pr, headSha: d.headSha, mergeable: d.mergeable, mergeState: d.mergeState };\r\n step = mergeStep(pr, rec, Date.now(), { base: repo.defaultBranch, detailed: true });\r\n }\r\n Object.assign(rec, step.set);\r\n if (step.do === 'requeue') {\r\n // Commits arrived after QA's sign-off: they get tested too.\r\n this.setQa(rec, { status: 'queued', round: rec.round + 1, retests: rec.retests + 1, mergeNote: null, pendingSince: null });\r\n setTimeout(() => this.schedule(), 200);\r\n return false;\r\n }\r\n if (step.do === 'send-back') return this.sendBack(repo, rec, step.reason, step.instructions, step.needsHuman);\r\n if (step.do === 'wait') {\r\n if (step.alert) {\r\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.`);\r\n }\r\n return step.note === undefined ? false : this.mergeNote(rec, step.note);\r\n }\r\n if (step.do === 'update-branch') {\r\n // The repo only merges up-to-date branches. GitHub merges the base in cleanly (or refuses); CI checks the result.\r\n this.mergeNote(rec, `updating the branch with ${repo.defaultBranch}`);\r\n await this.backend.updateBranch(repo.fullName, pr.number);\r\n const details = await this.backend.prDetails(repo.fullName, pr.number);\r\n this.setQa(rec, { passedSha: details.headSha });\r\n return false;\r\n }\r\n if (step.do !== 'merge') return false;\r\n this.mergeNote(rec, 'merging\u2026');\r\n let error = '';\r\n for (const method of ['squash', 'merge', 'rebase'] as const) {\r\n try {\r\n await this.backend.mergePull(repo.fullName, pr.number, method, rec.passedSha ?? pr.headSha);\r\n error = '';\r\n break;\r\n } catch (err) {\r\n error = oneLine(err).replace(/^gh .*? failed: /, '');\r\n if (!/not allowed/i.test(error)) break; // only a merge method the repo turned off is worth another try\r\n }\r\n }\r\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\r\n if (error) {\r\n rec.mergeRetryAt = Date.now() + MERGE_RETRY_MS;\r\n if (!rec.alerted) {\r\n rec.alerted = true;\r\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.`);\r\n }\r\n return this.mergeNote(rec, `merge blocked: ${error}`);\r\n }\r\n this.toast('success', `\uD83D\uDD00 Merged PR #${pr.number} into ${repo.defaultBranch}: ${pr.title}`);\r\n return true;\r\n }\r\n\r\n /** Show where auto-merge stands on a PR's card. Doesn't count as a change to the record. */\r\n private mergeNote(rec: QaRecord, text: string | null) {\r\n if (rec.mergeNote !== text) {\r\n rec.mergeNote = text;\r\n this.broadcast({ type: 'qa', qa: this.qaView(rec) });\r\n }\r\n return false;\r\n }\r\n\r\n /** QA passed, but the PR can't merge as it is: a developer fixes it, and QA re-tests if the code changed. */\r\n private sendBack(repo: PersistedRepo, rec: QaRecord, reason: 'checks' | 'conflict', fixInstructions: string, needsHuman: boolean) {\r\n if (needsHuman) {\r\n this.setQa(rec, { status: 'needs-human', mergeNote: null });\r\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.`);\r\n return false;\r\n }\r\n this.setQa(rec, { status: 'failed', fixReason: reason, fixInstructions, mergeFixes: rec.mergeFixes + 1, mergeNote: null, pendingSince: null });\r\n setTimeout(() => this.schedule(), 200);\r\n return false;\r\n }\r\n\r\n /** Fast-forward the floor's main checkout (usually your own project folder) and report how it stands. */\r\n private async syncFolder(repo: PersistedRepo) {\r\n const rt = this.repoRt.get(repo.id);\r\n if (!rt || rt.cloneStatus !== 'ready') return rt?.folderSync ?? null;\r\n const own = this.backend.office.isOwnFolder(this.backend.mainDir(repo.fullName)); // updating the running office restarts it mid-work\r\n const sync = await this.backend.syncMain(repo.fullName, repo.defaultBranch, { touch: !own }).catch((err) => ({ status: `sync failed: ${oneLine(err)}`, behind: 0, updatable: false }));\r\n const status = sync?.status ?? null;\r\n if (own && sync) this.setOfficeBehind(sync.updatable ? sync.behind : 0);\r\n if (!this.repoRt.has(repo.id)) return null;\r\n const before = rt.folderSync;\r\n rt.folderSync = status;\r\n this.emitRepo(repo);\r\n if (status && status !== before) {\r\n const name = repo.localPath ? path.basename(repo.localPath) : repo.fullName;\r\n if (status.startsWith('updated')) this.toast('success', `\uD83D\uDCC1 ${name}: ${status}`);\r\n else if (/behind|diverged|failed/.test(status)) this.toast('info', `\uD83D\uDCC1 ${name} wasn't updated: ${status}`);\r\n }\r\n return status;\r\n }\r\n\r\n /** The manager's \"Sync now\". */\r\n async syncFolderNow(repoId: string) {\r\n return { folderSync: await this.syncFolder(this.repo(repoId)) };\r\n }\r\n\r\n // ---------- the floor's app (preview monitor) ----------\r\n\r\n /** Run the floor's app from its preview worktree: the default branch, or an open PR. Replaces what it is running now. */\r\n async startPreview(id: string, pr?: number | null): Promise<PreviewView> {\r\n const repo = this.repo(id);\r\n return this.previews.start(repo, `${repo.fullName.split('/')[1]} app`, pr);\r\n }\r\n\r\n stopPreview(id: string): Promise<PreviewView> {\r\n return this.previews.stop(this.repo(id));\r\n }\r\n\r\n /**\r\n * Server shutdown: stop every floor's app so nothing is left holding a preview port. Agents' CLIs keep working\r\n * through a restart (the terminal keeper holds them for the next start) and stop when the office quits.\r\n */\r\n async shutdown(restart = false): Promise<void> {\r\n await this.writeState().catch((err) => console.warn('could not save the state', err));\r\n this.backend.releaseClis(restart); // before the terminals are saved: whatever they print next waits in the keeper\r\n await this.saveTerminals(true);\r\n await this.previews.stopAll(this.state.repos);\r\n }\r\n\r\n private async cloneRepo(id: string) {\r\n const repo = this.state.repos.find((r) => r.id === id);\r\n const rt = this.repoRt.get(id);\r\n if (!repo || !rt || rt.cloneStatus === 'cloning') return;\r\n rt.cloneStatus = 'cloning';\r\n rt.cloneError = undefined;\r\n this.emitRepo(repo);\r\n try {\r\n await this.backend.ensureClone(repo.fullName);\r\n rt.cloneStatus = 'ready';\r\n void this.previews.refreshDefault(repo);\r\n } catch (err) {\r\n rt.cloneStatus = 'error';\r\n rt.cloneError = (err as Error).message;\r\n this.toast('error', `Could not clone ${repo.fullName}: ${rt.cloneError}`);\r\n }\r\n if (this.repoRt.has(id)) this.emitRepo(repo);\r\n }\r\n\r\n async syncRepo(id: string) {\r\n const repo = this.state.repos.find((r) => r.id === id);\r\n const rt = this.repoRt.get(id);\r\n if (!repo || !rt || rt.syncing) return;\r\n rt.syncing = true;\r\n try {\r\n const started = Date.now();\r\n const [issues, pulls] = await Promise.all([this.backend.listIssues(repo.fullName), this.backend.listPulls(repo.fullName)]);\r\n rt.issues = issues;\r\n rt.pulls = pulls;\r\n rt.lastSync = Date.now();\r\n rt.fetchedAt = started;\r\n rt.syncError = undefined;\r\n this.reconcilePulls(repo, pulls);\r\n // Something was merged since the last look (by the office or anyone else): bring the folder up to date.\r\n const newest = pulls.reduce<string | null>((m, p) => (p.mergedAt && (!m || p.mergedAt > m) ? p.mergedAt : m), null);\r\n if (newest !== rt.lastMergedAt) {\r\n rt.lastMergedAt = newest;\r\n void this.syncFolder(repo);\r\n }\r\n void this.advanceMerges(repo);\r\n } catch (err) {\r\n rt.syncError = (err as Error).message;\r\n } finally {\r\n rt.syncing = false;\r\n }\r\n if (this.repoRt.has(id)) this.emitRepo(repo);\r\n }\r\n\r\n /** Keep agents and QA records in step with what happened to PRs on GitHub. */\r\n private reconcilePulls(repo: PersistedRepo, pulls: PullInfo[]) {\r\n for (const a of this.state.agents) {\r\n if (a.repoId !== repo.id || a.role !== 'dev' || a.prNumber == null || BUSY.includes(a.status) || a.status === 'idle') continue;\r\n const pr = pulls.find((p) => p.number === a.prNumber);\r\n if (!pr || pr.state === 'OPEN') continue;\r\n if (a.task === 'qa') {\r\n this.clearTask(a); // they only tested it\r\n continue;\r\n }\r\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.` }]);\r\n this.clearTask(a);\r\n }\r\n\r\n // Finished PRs leave QA.\r\n for (const q of this.state.qa.filter((x) => x.repoId === repo.id)) {\r\n const pr = pulls.find((p) => p.number === q.prNumber);\r\n if (pr && pr.state !== 'OPEN' && q.status !== 'testing' && q.status !== 'fixing') {\r\n this.state.qa = this.state.qa.filter((x) => x !== q);\r\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: q.prNumber });\r\n }\r\n }\r\n\r\n // Every swarm PR goes through QA, including ones opened before QA existed or while the server was down.\r\n for (const pr of pulls) {\r\n if (pr.state !== 'OPEN' || pr.isDraft || !pr.headRefName.startsWith('swarm/')) continue;\r\n if (this.state.qa.some((q) => q.repoId === repo.id && q.prNumber === pr.number)) continue;\r\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));\r\n this.queueQa(repo, pr.number, dev ?? null, pr.closesIssues[0] ?? null);\r\n }\r\n this.save();\r\n }\r\n\r\n async createIssue(repoId: string, title: string, body: string, assignTo?: string, specialty?: string) {\r\n const repo = this.repo(repoId);\r\n if (!title.trim()) throw new HttpError(400, 'An issue needs a title');\r\n const slug = specialtySlug(specialty);\r\n const number = await this.backend.createIssue(repo.fullName, title.trim(), body, slug ? [specialtyLabel(slug)] : []);\r\n await this.syncRepo(repo.id);\r\n this.toast('success', `Issue #${number} filed on ${repo.fullName}`);\r\n if (assignTo) await this.assign(assignTo, number);\r\n else setTimeout(() => this.schedule(), 200);\r\n return number;\r\n }\r\n\r\n async mergePull(repoId: string, number: number, method: 'squash' | 'merge' | 'rebase' = 'squash') {\r\n const repo = this.repo(repoId);\r\n await this.backend.mergePull(repo.fullName, number, method);\r\n this.toast('success', `Merged PR #${number} into ${repo.defaultBranch}`);\r\n await this.syncRepo(repo.id);\r\n setTimeout(() => this.schedule(), 200);\r\n }\r\n\r\n async closePull(repoId: string, number: number) {\r\n const repo = this.repo(repoId);\r\n await this.backend.closePull(repo.fullName, number);\r\n await this.syncRepo(repo.id);\r\n }\r\n\r\n // ---------- agents ----------\r\n\r\n hireAgent(\r\n repoId: string,\r\n opts: {\r\n name?: string;\r\n model?: string;\r\n effort?: string;\r\n role?: string;\r\n look?: string;\r\n title?: string;\r\n specialty?: string;\r\n brief?: string;\r\n cli?: string;\r\n hiredBy?: 'manager' | 'ceo';\r\n appearance?: { color: string; hair: string; skin: string };\r\n },\r\n ) {\r\n const repo = this.repo(repoId);\r\n const role: AgentRole = opts.role === 'qa' ? 'qa' : 'dev';\r\n const used = new Set(this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).map((a) => a.desk));\r\n let desk = 0;\r\n while (used.has(desk)) desk++;\r\n if (desk >= MAX_DESKS[role]) {\r\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)`);\r\n }\r\n const name = opts.name?.trim() || this.freeName(role);\r\n const agent: PersistedAgent = {\r\n id: crypto.randomUUID(),\r\n name,\r\n repoId: repo.id,\r\n role,\r\n title: String(opts.title ?? '').trim().slice(0, 60),\r\n specialty: specialtySlug(opts.specialty),\r\n brief: String(opts.brief ?? '').trim().slice(0, 2500),\r\n hiredBy: opts.hiredBy ?? 'manager',\r\n look: LOOKS.includes(opts.look as AgentLook) ? (opts.look as AgentLook) : lookFor(name),\r\n task: null,\r\n desk,\r\n color: opts.appearance?.color ?? pick(SHIRTS),\r\n hair: opts.appearance?.hair ?? pick(HAIR),\r\n skin: opts.appearance?.skin ?? pick(SKIN),\r\n model: opts.model ?? '',\r\n effort: EFFORTS.includes(opts.effort as EffortLevel) ? (opts.effort as EffortLevel) : '',\r\n cli: isCli(opts.cli) ? opts.cli : '',\r\n status: 'idle',\r\n issueNumber: null,\r\n issueTitle: null,\r\n branch: null,\r\n prNumber: null,\r\n prUrl: null,\r\n startedAt: null,\r\n endedAt: null,\r\n costUsd: 0,\r\n turns: 0,\r\n sessionId: null,\r\n sessionCli: null,\r\n lastError: null,\r\n logTail: [],\r\n };\r\n this.state.agents.push(agent);\r\n this.agentRt.set(agent.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [], terminal: null });\r\n this.appendLog(agent, [\r\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}).` },\r\n ...(agent.title ? [{ kind: 'system' as const, text: `\uD83E\uDEAA ${agent.title}${agent.specialty ? ` \u00B7 takes swarm:${agent.specialty} issues first` : ''}` }] : []),\r\n ]);\r\n this.save();\r\n this.broadcast({ type: 'agent', agent: this.agentView(agent, false) });\r\n setTimeout(() => this.schedule(), 200);\r\n return this.agentView(agent, true);\r\n }\r\n\r\n /** Every floor has at least one QA tester. */\r\n private ensureQaTester(repo: PersistedRepo) {\r\n if (this.state.agents.some((a) => a.repoId === repo.id && a.role === 'qa')) return;\r\n this.hireAgent(repo.id, { role: 'qa' });\r\n }\r\n\r\n /** A name from the role's pool that no agent or pending candidate has. */\r\n private freeName(role: 'dev' | 'qa') {\r\n const taken = new Set([...this.state.agents.map((a) => a.name), ...this.state.requests.filter((r) => r.status === 'pending').map((r) => r.name)]);\r\n const pool = role === 'qa' ? QA_NAMES : DEV_NAMES;\r\n return pool.find((n) => !taken.has(n)) || `${role === 'qa' ? 'Tester' : 'Agent'} ${this.state.agents.length + 1}`;\r\n }\r\n\r\n updateAgent(\r\n id: string,\r\n patch: { name?: string; model?: string; effort?: string; cli?: string; look?: string; title?: string; specialty?: string; brief?: string; color?: string; hair?: string },\r\n ) {\r\n const a = this.agent(id);\r\n if (patch.cli !== undefined && a.role !== 'ceo') a.cli = isCli(patch.cli) ? patch.cli : '';\r\n if (patch.name?.trim() && patch.name.trim() !== a.name) {\r\n a.name = patch.name.trim().slice(0, 24);\r\n a.look = lookFor(a.name);\r\n }\r\n if (LOOKS.includes(patch.look as AgentLook)) a.look = patch.look as AgentLook;\r\n if (patch.color && /^#[0-9a-f]{6}$/i.test(patch.color)) a.color = patch.color;\r\n if (patch.hair && /^#[0-9a-f]{6}$/i.test(patch.hair)) a.hair = patch.hair;\r\n if (patch.model !== undefined) a.model = String(patch.model).trim();\r\n if (patch.effort !== undefined) a.effort = EFFORTS.includes(patch.effort as EffortLevel) ? (patch.effort as EffortLevel) : '';\r\n if (a.role !== 'ceo') {\r\n if (patch.title !== undefined) a.title = String(patch.title).trim().slice(0, 60);\r\n if (patch.specialty !== undefined) a.specialty = specialtySlug(patch.specialty);\r\n if (patch.brief !== undefined) a.brief = String(patch.brief).trim().slice(0, 2500);\r\n }\r\n this.save();\r\n this.emitAgent(a);\r\n }\r\n\r\n fireAgent(id: string, force = false) {\r\n const a = this.agent(id);\r\n if (a.role === 'ceo') throw new HttpError(409, `${a.name} runs the company and can't be let go.`);\r\n if (!force && a.role === 'qa' && this.state.agents.filter((x) => x.repoId === a.repoId && x.role === 'qa').length <= 1) {\r\n throw new HttpError(409, `${a.name} is the only QA tester on this floor, and every floor needs at least one.`);\r\n }\r\n for (const r of this.state.requests.filter((x) => x.kind === 'let-go' && x.agentId === id && x.status === 'pending')) {\r\n this.decide(r, { status: 'approved', note: 'They were let go directly.', decidedBy: 'manager' });\r\n }\r\n\r\n this.agentRt.get(id)?.session?.stop();\r\n this.agentRt.get(id)?.terminal?.releaseIdle?.();\r\n this.agentRt.get(id)?.terminal?.dispose();\r\n void removeScreens(id);\r\n void fs.rm(terminalFile(id), { force: true }).catch(() => undefined);\r\n for (const q of this.state.qa) {\r\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\r\n if (q.devAgentId === id) q.devAgentId = null;\r\n if (q.devAgentId === null && q.status === 'fixing') this.setQa(q, { status: 'failed' });\r\n }\r\n const repo = this.state.repos.find((r) => r.id === a.repoId);\r\n if (repo) {\r\n const slug = this.agentSlug(a);\r\n void this.backend\r\n .releaseDesk(repo.fullName, slug, this.port(a))\r\n .then(() => this.backend.removeDesk(repo.fullName, slug))\r\n .catch(() => undefined);\r\n }\r\n this.state.agents = this.state.agents.filter((x) => x.id !== id);\r\n this.agentRt.delete(id);\r\n this.save();\r\n this.broadcast({ type: 'agentRemoved', agentId: id });\r\n }\r\n\r\n stopAgent(id: string) {\r\n const a = this.agent(id);\r\n if (!BUSY.includes(a.status)) return;\r\n a.status = 'stopped';\r\n a.lastError = 'Stopped by manager';\r\n this.appendLog(a, [{ kind: 'manager', text: '\u25A0 Manager stopped this session.' }]);\r\n this.agentRt.get(id)?.session?.stop();\r\n this.emitAgent(a);\r\n this.save();\r\n }\r\n\r\n /** An agent whose CLI kept working through the office's restart: the office follows its session again. */\r\n private reattachSession(a: PersistedAgent) {\r\n const repo = this.state.repos.find((r) => r.id === a.repoId);\r\n if (!repo) return;\r\n this.appendLog(a, [{ kind: 'system', text: '\u21BB The office restarted; their CLI kept working and the office is following it again.' }]);\r\n this.startAgentSession(a, repo, this.backend.deskDir(repo.fullName, this.agentSlug(a)), '', '', a.sessionId ?? undefined, undefined, 'reattach');\r\n }\r\n\r\n /** The manager pressed Esc in the agent's terminal and the CLI stopped its turn: a Stop that leaves the CLI to them. */\r\n private interrupted(a: PersistedAgent) {\r\n if (!BUSY.includes(a.status)) return;\r\n a.status = 'stopped';\r\n a.lastError = 'Interrupted in the terminal';\r\n this.appendLog(a, [{ kind: 'manager', text: '\u25A0 Interrupted in the terminal. Type there to carry on.' }]);\r\n }\r\n\r\n resetAgent(id: string) {\r\n const a = this.agent(id);\r\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is busy; stop them first`);\r\n for (const q of this.state.qa) {\r\n if (q.qaAgentId === id && q.status === 'testing') this.setQa(q, { status: 'queued', qaAgentId: null });\r\n if (q.devAgentId === id && q.status === 'fixing') this.setQa(q, { status: 'failed' });\r\n }\r\n this.agentRt.get(id)?.terminal?.releaseIdle?.();\r\n this.clearTask(a);\r\n this.appendLog(a, [{ kind: 'system', text: '\u21BA Cleared desk. Ready for new work.' }]);\r\n this.save();\r\n }\r\n\r\n private issueTaken(repo: PersistedRepo, n: number) {\r\n if (this.state.agents.some((a) => a.repoId === repo.id && a.role === 'dev' && a.task !== 'qa' && a.issueNumber === n && a.status !== 'idle' && a.status !== 'error')) return true;\r\n const pulls = this.repoRt.get(repo.id)?.pulls ?? [];\r\n return pulls.some((p) => p.state === 'OPEN' && (p.closesIssues.includes(n) || p.headRefName.startsWith(`swarm/issue-${n}-`)));\r\n }\r\n\r\n private ensureSlot() {\r\n if (this.slotsFull()) {\r\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.`);\r\n }\r\n }\r\n\r\n async assign(agentId: string, issueNumber: number, note?: string) {\r\n const a = this.agent(agentId);\r\n const repo = this.repo(a.repoId);\r\n if (a.role === 'qa') throw new HttpError(400, `${a.name} is a QA tester; they test pull requests rather than issues.`);\r\n if (a.role === 'ceo') throw new HttpError(400, `${a.name} runs the company; give issues to the developers.`);\r\n if (BUSY.includes(a.status)) throw new HttpError(409, `${a.name} is already working on #${a.issueNumber}`);\r\n this.ensureSlot();\r\n const issue = this.repoRt.get(repo.id)?.issues.find((i) => i.number === issueNumber);\r\n if (!issue) throw new HttpError(404, `Issue #${issueNumber} is not open on ${repo.fullName}`);\r\n const holder = this.state.agents.find((x) => x.id !== a.id && x.repoId === repo.id && x.issueNumber === issueNumber && BUSY.includes(x.status));\r\n if (holder) throw new HttpError(409, `${holder.name} is already working on #${issueNumber}`);\r\n void this.runTask(a, repo, issue, note);\r\n return this.agentView(a, false);\r\n }\r\n\r\n private port(a: PersistedAgent) {\r\n return 5200 + (parseInt(a.id.slice(0, 4), 16) % 700);\r\n }\r\n\r\n private linkedRepos(repo: PersistedRepo) {\r\n return repo.links.map((id) => this.state.repos.find((r) => r.id === id)).filter((r): r is PersistedRepo => !!r);\r\n }\r\n\r\n /**\r\n * How an agent's next session runs: the CLI in their terminal (the terminal runtime), or Claude Code through the\r\n * SDK. A session can only be resumed by the CLI that made it, so a follow-up stays with that CLI.\r\n */\r\n private sessionRuntime(a: PersistedAgent, resume?: string): { terminal?: AgentTerminal; cli?: AgentCli; label?: string; resumeSessionId?: string } {\r\n const inTerminal = this.state.settings.runtime === 'terminal' && this.backend.terminals;\r\n let cli: AgentCli = a.role === 'ceo' ? 'claude' : a.cli || this.state.settings.defaultCli;\r\n if (resume && a.sessionCli && a.sessionCli !== cli) {\r\n if (inTerminal) cli = a.sessionCli;\r\n else if (a.sessionCli !== 'claude') resume = undefined;\r\n }\r\n if (!inTerminal) return { resumeSessionId: resume };\r\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;\r\n return { terminal: this.terminalFor(a), cli, label: `${a.name}${what ? ` \u00B7 ${what}` : ''}`.slice(0, 80).trim(), resumeSessionId: resume };\r\n }\r\n\r\n /** The model to ask for (the Agent SDK runs Claude Code). '' lets another coding agent use its own default. */\r\n private modelFor(a: PersistedAgent, cli: AgentCli | undefined) {\r\n return effectiveModel(a.model, cli ?? 'claude', this.state.settings, DEFAULT_MODEL);\r\n }\r\n\r\n // ---------- terminals ----------\r\n\r\n private async loadTerminal(agentId: string): Promise<AgentTerminal | null> {\r\n if (!(await fs.stat(terminalFile(agentId)).catch(() => null))) return null;\r\n const t = this.newTerminal(agentId);\r\n await t.load(terminalFile(agentId));\r\n return t;\r\n }\r\n\r\n /** The agent's terminal, made the first time they run in the terminal runtime. */\r\n private terminalFor(a: PersistedAgent): AgentTerminal {\r\n const rt = this.agentRt.get(a.id)!;\r\n rt.terminal ??= this.newTerminal(a.id);\r\n return rt.terminal;\r\n }\r\n\r\n private newTerminal(agentId: string) {\r\n const t = new AgentTerminal();\r\n // Typed at a CLI waiting at its prompt after its task: a follow-up, which starts synchronously when it can.\r\n t.onIdlePrompt = (text) => {\r\n void this.message(agentId, text, true).catch(() => undefined);\r\n return !!this.agentRt.get(agentId)?.session;\r\n };\r\n return t;\r\n }\r\n\r\n private async saveTerminals(all = false) {\r\n for (const [id, rt] of this.agentRt) {\r\n if (rt.terminal && (all || rt.terminal.dirty)) await rt.terminal.save(terminalFile(id)).catch((err) => console.warn('could not save a terminal', err));\r\n }\r\n }\r\n\r\n /** A browser opened an agent's terminal (/ws/term?agent=<id>). */\r\n attachTerminal(agentId: string, ws: WebSocket) {\r\n const t = this.agentRt.get(agentId)?.terminal;\r\n if (!t) return ws.close(4404, 'That agent has no terminal');\r\n t.attach(ws);\r\n }\r\n\r\n private buildSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, fixing?: { pr: number; headRef: string }) {\r\n const linked = this.linkedRepos(repo).map((r) => `- ${r.fullName}: read-only reference clone at ${this.backend.mainDir(r.fullName)}`);\r\n const push = fixing ? `git push origin HEAD:${fixing.headRef}` : `git push -u origin ${branch}`;\r\n return [\r\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.`,\r\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.`,\r\n a.brief ? `\\nYour job description:\\n${a.brief}` : '',\r\n '',\r\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\r\n repo.summary ? `Project: ${repo.summary}` : '',\r\n repo.mission ? `What the team is building (the manager's brief): ${repo.mission}` : '',\r\n `Your worktree: ${cwd}`,\r\n fixing\r\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.`\r\n : `Your branch: ${branch} (already checked out, created from origin/${repo.defaultBranch})`,\r\n linked.length ? `Related repositories you may read for context (do not modify them):\\n${linked.join('\\n')}` : '',\r\n '',\r\n 'Workflow:',\r\n '1. Read the issue and explore the relevant code before changing anything.',\r\n '2. Implement the change with focused commits and clear messages.',\r\n \"3. Run the project's existing tests, linters and build (if any) and fix what you broke. Install dependencies first if needed.\",\r\n repo.browserTesting\r\n ? `4. If the project has a web UI, start its dev server in the background on port ${this.port(a)} (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.`\r\n : '4. Verify the behaviour you changed as directly as you can.',\r\n `5. Push: ${push}`,\r\n fixing\r\n ? '6. Reply with a short summary of what you fixed.'\r\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>\".`,\r\n fixing ? '' : '7. End your final message with the pull request URL on its own line.',\r\n '',\r\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.',\r\n ]\r\n .filter((l) => l !== '')\r\n .join('\\n');\r\n }\r\n\r\n private beginTask(a: PersistedAgent, patch: Partial<PersistedAgent>, banner: string, preparing: string) {\r\n const rt = this.agentRt.get(a.id)!;\r\n Object.assign(a, {\r\n status: 'preparing' as AgentStatus,\r\n startedAt: Date.now(),\r\n endedAt: null,\r\n costUsd: 0,\r\n turns: 0,\r\n lastError: null,\r\n ...patch,\r\n });\r\n rt.screenshot = null;\r\n rt.browserUrl = null;\r\n rt.shots = [];\r\n void removeScreens(a.id);\r\n this.appendLog(a, [\r\n { kind: 'system', text: '' },\r\n { kind: 'system', text: `\u2501\u2501\u2501 ${banner} \u2501\u2501\u2501` },\r\n { kind: 'system', text: preparing },\r\n ]);\r\n this.emitAgent(a);\r\n this.save();\r\n }\r\n\r\n private async prepare(a: PersistedAgent, repo: PersistedRepo, base: { pr?: number }, branch: string): Promise<string | null> {\r\n try {\r\n if (this.repoRt.get(repo.id)?.cloneStatus !== 'ready') await this.cloneRepo(repo.id);\r\n await this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a));\r\n const cwd = await this.backend.prepareDesk(repo.fullName, { defaultBranch: repo.defaultBranch, pr: base.pr }, this.agentSlug(a), branch);\r\n return a.status === 'preparing' ? cwd : null; // null: stopped or fired while preparing\r\n } catch (err) {\r\n if (a.status !== 'preparing') return null;\r\n a.status = 'error';\r\n a.endedAt = Date.now();\r\n a.lastError = (err as Error).message;\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n this.emitAgent(a);\r\n this.save();\r\n return null;\r\n }\r\n }\r\n\r\n private async runTask(a: PersistedAgent, repo: PersistedRepo, issue: IssueInfo, note?: string) {\r\n const branch = `swarm/issue-${issue.number}-${slugify(a.name)}`;\r\n this.beginTask(\r\n a,\r\n { task: 'issue', issueNumber: issue.number, issueTitle: issue.title, branch, prNumber: null, prUrl: null, sessionId: null },\r\n `Issue #${issue.number}: ${issue.title}`,\r\n `Preparing worktree on ${branch}\u2026`,\r\n );\r\n const cwd = await this.prepare(a, repo, {}, branch);\r\n if (!cwd) return;\r\n\r\n const prompt = [\r\n `Please resolve GitHub issue #${issue.number}: ${issue.title}`,\r\n `URL: ${issue.url}`,\r\n issue.labels.length ? `Labels: ${issue.labels.join(', ')}` : '',\r\n '',\r\n issue.body?.trim() || '(The issue has no description.)',\r\n note ? `\\nNote from the manager: ${note}` : '',\r\n ]\r\n .filter(Boolean)\r\n .join('\\n');\r\n\r\n this.startAgentSession(a, repo, cwd, prompt, this.buildSystemAppend(a, repo, cwd, branch));\r\n }\r\n\r\n private startAgentSession(\r\n a: PersistedAgent,\r\n repo: PersistedRepo,\r\n cwd: string,\r\n prompt: string,\r\n systemAppend: string,\r\n resumeSessionId?: string,\r\n outputSchema?: Record<string, unknown>,\r\n /** typed: the manager typed the prompt at the CLI; reattach: follow the CLI that kept working through a restart. */\r\n mode: 'typed' | 'reattach' | null = null,\r\n ) {\r\n const rt = this.agentRt.get(a.id)!;\r\n a.status = 'working';\r\n const how = this.sessionRuntime(a, resumeSessionId);\r\n this.emitAgent(a);\r\n rt.session = this.backend.startSession(\r\n {\r\n cwd,\r\n prompt,\r\n systemAppend,\r\n model: this.modelFor(a, how.cli),\r\n effort: a.effort || this.state.settings.defaultEffort,\r\n browserTesting: repo.browserTesting,\r\n additionalDirectories: this.linkedRepos(repo).map((r) => this.backend.mainDir(r.fullName)),\r\n role: a.task === 'qa' ? 'qa' : a.role, // a developer covering QA works under QA's rules\r\n outputSchema,\r\n // A developer's CLI stays at its prompt afterwards, for the manager and for follow-ups; QA's closes.\r\n keepAlive: a.task !== 'qa',\r\n typed: mode === 'typed',\r\n reattach: mode === 'reattach',\r\n agentId: a.id,\r\n ...how,\r\n },\r\n {\r\n log: (entries) => this.appendLog(a, entries),\r\n tool: (name) => {\r\n if (rt.currentTool === name) return;\r\n rt.currentTool = name;\r\n this.emitAgent(a);\r\n },\r\n sessionId: (id) => {\r\n a.sessionId = id;\r\n a.sessionCli = how.cli ?? 'claude';\r\n },\r\n browserUrl: (url) => {\r\n rt.browserUrl = url;\r\n this.emitAgent(a);\r\n },\r\n screenshot: (data, mime) => {\r\n const at = Date.now();\r\n rt.screenshot = { data, mime, at };\r\n rt.shots.push({ data, mime, url: rt.browserUrl, at });\r\n if (rt.shots.length > 12) rt.shots.shift();\r\n this.broadcast({ type: 'screen', agentId: a.id, url: rt.browserUrl, at });\r\n void removeScreens(a.id)\r\n .then(() => fs.mkdir(SCREENS_DIR, { recursive: true }))\r\n .then(() => fs.writeFile(screenFile(a.id, mime), data))\r\n .catch((err) => console.warn('could not save screenshot', err));\r\n },\r\n limited: (at) => this.pauseForLimit(at),\r\n usageWarning: (info) => this.paceForWarning(info),\r\n finished: (result) => void this.onFinished(a, repo, result),\r\n },\r\n );\r\n }\r\n\r\n private async onFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const rt = this.agentRt.get(a.id);\r\n if (!rt || !this.state.agents.includes(a)) return; // fired\r\n if (this.officeUpdate.handedOver) return; // stopped for the office's update: recovered like after a restart\r\n rt.session = null;\r\n rt.currentTool = null;\r\n a.endedAt = Date.now();\r\n a.costUsd += result.costUsd;\r\n a.turns += result.turns;\r\n // Dev servers the agent forgot to stop would otherwise keep its port and lock its desk folder.\r\n void this.backend.releaseDesk(repo.fullName, this.agentSlug(a), this.port(a)).catch(() => undefined);\r\n if (result.interrupted) this.interrupted(a);\r\n\r\n if (a.task === 'qa') await this.onQaFinished(a, repo, result);\r\n else if (a.task === 'fix') this.onFixFinished(a, repo, result);\r\n else await this.onIssueFinished(a, repo, result);\r\n\r\n this.emitAgent(a);\r\n this.save();\r\n void this.syncRepo(repo.id);\r\n setTimeout(() => this.schedule(), 500);\r\n }\r\n\r\n private minutes(a: PersistedAgent) {\r\n return a.startedAt && a.endedAt ? Math.max(1, Math.round((a.endedAt - a.startedAt) / 60000)) : 0;\r\n }\r\n\r\n private fail(a: PersistedAgent, result: SessionResult, what: string) {\r\n a.status = 'error';\r\n a.lastError = result.errors.join('; ') || 'Session failed';\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n this.toast('error', `${a.name} hit a problem on ${what}: ${a.lastError.slice(0, 120)}`);\r\n }\r\n\r\n private async onIssueFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const escaped = repo.fullName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n const m = result.text.match(new RegExp(`https://github\\\\.com/${escaped}/pull/(\\\\d+)`, 'i'));\r\n if (m) {\r\n a.prNumber = Number(m[1]);\r\n a.prUrl = m[0];\r\n } else if (a.branch) {\r\n const pr = await this.backend.prForBranch(repo.fullName, a.branch).catch(() => null);\r\n if (pr) {\r\n a.prNumber = pr.number;\r\n a.prUrl = pr.url;\r\n }\r\n }\r\n\r\n if (a.status === 'stopped') return; // the manager already logged the stop\r\n if (!result.ok) {\r\n this.issueFailed(repo, a.issueNumber);\r\n return this.fail(a, result, `#${a.issueNumber}`);\r\n }\r\n this.issueFailures.delete(`${repo.id}#${a.issueNumber}`);\r\n a.status = 'done';\r\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'}` }]);\r\n if (a.prNumber) {\r\n this.queueQa(repo, a.prNumber, a, a.issueNumber);\r\n this.appendLog(a, [{ kind: 'system', text: `\uD83D\uDCE8 Handed PR #${a.prNumber} to QA.` }]);\r\n this.toast('success', `${a.name} opened PR #${a.prNumber} for #${a.issueNumber}; it's off to QA`);\r\n } else {\r\n this.noPullRequest(a, repo);\r\n }\r\n }\r\n\r\n /**\r\n * An issue session ended without a PR, which would leave the issue \"taken\" with nobody on it. The same developer,\r\n * who has the context and the worktree, is asked once to finish; after that the issue goes back on the board.\r\n */\r\n private noPullRequest(a: PersistedAgent, repo: PersistedRepo) {\r\n const key = `${repo.id}#${a.issueNumber}`;\r\n if (this.nudged.has(key)) return this.releaseIssue(a, repo);\r\n this.nudged.add(key);\r\n // message() starts the session before its first await, so the scheduler can't hand this developer other work first.\r\n void this.message(\r\n a.id,\r\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.`,\r\n ).catch(() => this.releaseIssue(a, repo));\r\n }\r\n\r\n private releaseIssue(a: PersistedAgent, repo: PersistedRepo) {\r\n const n = a.issueNumber;\r\n this.clearTask(a);\r\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.`);\r\n }\r\n\r\n // ---------- QA ----------\r\n\r\n private queueQa(repo: PersistedRepo, prNumber: number, dev: PersistedAgent | null, issueNumber: number | null) {\r\n let rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\r\n if (rec) {\r\n if (rec.status === 'testing') return;\r\n this.setQa(rec, { status: 'queued', devAgentId: dev?.id ?? rec.devAgentId, devSessionId: dev?.sessionId ?? rec.devSessionId });\r\n } else {\r\n rec = {\r\n repoId: repo.id,\r\n prNumber,\r\n status: 'queued',\r\n round: 1,\r\n devAgentId: dev?.id ?? null,\r\n qaAgentId: null,\r\n summary: null,\r\n checks: [],\r\n commentUrl: null,\r\n updatedAt: Date.now(),\r\n issueNumber,\r\n devSessionId: dev && dev.prNumber === prNumber ? dev.sessionId : null,\r\n fixInstructions: null,\r\n sessionFailures: 0,\r\n mergeNote: null,\r\n testedSha: null,\r\n passedSha: null,\r\n fixReason: null,\r\n mergeFixes: 0,\r\n retests: 0,\r\n pendingSince: null,\r\n mergeRetryAt: null,\r\n alerted: false,\r\n };\r\n this.state.qa.push(rec);\r\n this.setQa(rec, {});\r\n }\r\n setTimeout(() => this.schedule(), 200);\r\n }\r\n\r\n /** Manager's \"send to QA\" for any open PR (including ones opened by people). */\r\n async sendToQa(repoId: string, prNumber: number) {\r\n const repo = this.repo(repoId);\r\n const pr = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === prNumber && p.state === 'OPEN');\r\n if (!pr) throw new HttpError(404, `PR #${prNumber} is not open on ${repo.fullName}`);\r\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === prNumber);\r\n if (rec?.status === 'testing' || rec?.status === 'fixing') throw new HttpError(409, `PR #${prNumber} is already ${rec.status}`);\r\n if (rec && (rec.status === 'needs-human' || rec.status === 'passed' || rec.status === 'failed')) {\r\n // a fresh start: the manager decided it deserves another round\r\n rec.round += 1;\r\n rec.sessionFailures = 0;\r\n }\r\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));\r\n this.queueQa(repo, prNumber, dev ?? null, pr.closesIssues[0] ?? null);\r\n this.toast('info', `PR #${prNumber} is queued for QA`);\r\n }\r\n\r\n private buildQaSystemAppend(a: PersistedAgent, repo: PersistedRepo, cwd: string, branch: string, pr: PrDetails) {\r\n return [\r\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.`,\r\n ...(a.brief ? ['', `Your job description:\\n${a.brief}`] : []),\r\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.\"] : []),\r\n '',\r\n `Repository: ${repo.fullName} (default branch: ${repo.defaultBranch})`,\r\n ...(repo.summary ? [`Project: ${repo.summary}`] : []),\r\n ...(repo.mission ? [`What the team is building (the manager's brief): ${repo.mission}`] : []),\r\n ...(repo.qaBrief ? [`What to check on this project (from the CEO):\\n${repo.qaBrief}`] : []),\r\n `Pull request #${pr.number} \"${pr.title}\" from branch ${pr.headRefName}: ${pr.url}`,\r\n `Your worktree: ${cwd}. It has the pull request's code checked out on local branch ${branch}.`,\r\n '',\r\n 'How to test:',\r\n '1. Read the PR description and the linked issue, and work out the acceptance criteria.',\r\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.`,\r\n \"3. Install dependencies if needed, then run the project's test suite, linters, type checks and build (whichever exist).\",\r\n repo.browserTesting\r\n ? `4. If the project has a UI, start it in the background on port ${this.port(a)} (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.`\r\n : '4. Exercise the changed behaviour directly (run the program, call the API, write a quick script).',\r\n '5. You may write throwaway scripts to probe behaviour, but do not commit them.',\r\n '',\r\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.',\r\n ].join('\\n');\r\n }\r\n\r\n private async runQa(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\r\n const branch = `qa/pr-${rec.prNumber}-${slugify(a.name)}`;\r\n this.setQa(rec, { status: 'testing', qaAgentId: a.id });\r\n this.beginTask(\r\n a,\r\n { task: 'qa', issueNumber: rec.issueNumber, issueTitle: `PR #${rec.prNumber}`, branch, prNumber: rec.prNumber, prUrl: null, sessionId: null },\r\n `QA \u00B7 PR #${rec.prNumber} \u00B7 round ${rec.round}`,\r\n `Checking out PR #${rec.prNumber}\u2026`,\r\n );\r\n\r\n let pr: PrDetails;\r\n let issue: { title: string; body: string } | null = null;\r\n try {\r\n pr = await this.backend.prDetails(repo.fullName, rec.prNumber);\r\n const issueNumber = rec.issueNumber ?? pr.closesIssues[0] ?? null;\r\n if (issueNumber) issue = await this.backend.issueDetails(repo.fullName, issueNumber).catch(() => null);\r\n Object.assign(a, { issueTitle: pr.title, prUrl: pr.url });\r\n rec.testedSha = pr.headSha;\r\n this.emitAgent(a);\r\n } catch (err) {\r\n a.status = 'error';\r\n a.endedAt = Date.now();\r\n a.lastError = (err as Error).message;\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n this.setQa(rec, { status: 'queued', qaAgentId: null });\r\n this.emitAgent(a);\r\n return;\r\n }\r\n if (pr.state !== 'OPEN') {\r\n this.appendLog(a, [{ kind: 'system', text: `PR #${pr.number} is ${pr.state.toLowerCase()}; nothing to test.` }]);\r\n this.state.qa = this.state.qa.filter((q) => q !== rec);\r\n this.broadcast({ type: 'qaRemoved', repoId: repo.id, prNumber: rec.prNumber });\r\n this.clearTask(a);\r\n return;\r\n }\r\n\r\n const cwd = await this.prepare(a, repo, { pr: rec.prNumber }, branch);\r\n if (!cwd) {\r\n if (this.state.qa.includes(rec) && rec.status === 'testing') this.setQa(rec, { status: 'queued', qaAgentId: null });\r\n return;\r\n }\r\n\r\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\r\n const prompt = [\r\n `Please QA pull request #${pr.number}: ${pr.title}`,\r\n `URL: ${pr.url}`,\r\n `Author: ${dev ? `${dev.name} (developer agent)` : 'a teammate'} \u00B7 QA round ${rec.round}`,\r\n rec.fixReason === 'conflict'\r\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.`\r\n : rec.fixReason === 'checks'\r\n ? '\\nQA passed it before, but since then the developer changed the code to fix failing GitHub checks. Re-check everything.'\r\n : rec.round > 1 && rec.summary\r\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.`\r\n : '',\r\n '',\r\n 'PR description:',\r\n pr.body.trim() || '(empty)',\r\n issue ? `\\nLinked issue: ${issue.title}\\n${issue.body.trim() || '(no description)'}` : '',\r\n ]\r\n .filter((l) => l !== '')\r\n .join('\\n');\r\n\r\n this.startAgentSession(a, repo, cwd, prompt, this.buildQaSystemAppend(a, repo, cwd, branch, pr), undefined, QA_SCHEMA);\r\n }\r\n\r\n private async onQaFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\r\n const rt = this.agentRt.get(a.id)!;\r\n const report = result.ok ? parseReport(result) : null;\r\n\r\n if (a.status === 'stopped' || !report) {\r\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}`);\r\n if (rec) {\r\n const failures = rec.sessionFailures + (this.limited() ? 0 : 1); // the usage limit isn't the PR's fault\r\n this.setQa(rec, {\r\n status: a.status === 'stopped' || failures >= 2 ? 'needs-human' : 'queued',\r\n qaAgentId: null,\r\n sessionFailures: failures,\r\n summary: a.status === 'stopped' ? 'QA was stopped by the manager.' : rec.summary,\r\n });\r\n }\r\n return;\r\n }\r\n\r\n a.status = 'done';\r\n const pass = report.verdict === 'pass';\r\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` }]);\r\n\r\n // Evidence + comment on the PR\r\n let commentUrl: string | null = null;\r\n if (rec) {\r\n try {\r\n this.appendLog(a, [{ kind: 'system', text: '\uD83D\uDCCE Uploading evidence and posting the QA report on the PR\u2026' }]);\r\n const body = await this.renderQaComment(a, repo, rec, report, rt.shots);\r\n commentUrl = (await this.backend.commentPull(repo.fullName, rec.prNumber, body)) || null;\r\n this.appendLog(a, [{ kind: 'system', text: ` \u23BF ${commentUrl ?? 'comment posted'}` }]);\r\n } catch (err) {\r\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF Could not post the QA report: ${(err as Error).message}` }]);\r\n }\r\n const qaRounds = rec.round - rec.retests; // rounds QA itself asked for\r\n const nextStatus = pass ? 'passed' : qaRounds >= MAX_QA_ROUNDS ? 'needs-human' : 'failed';\r\n this.setQa(rec, {\r\n status: nextStatus,\r\n summary: report.summary,\r\n checks: report.checks,\r\n commentUrl: commentUrl ?? rec.commentUrl,\r\n fixInstructions: report.fixInstructions ?? report.checks.filter((c) => c.result === 'fail').map((c) => `${c.name}: ${c.details}`).join('\\n'),\r\n sessionFailures: 0,\r\n fixReason: pass ? null : 'qa',\r\n passedSha: pass ? rec.testedSha : null,\r\n mergeNote: null,\r\n pendingSince: null,\r\n mergeRetryAt: null,\r\n alerted: false,\r\n });\r\n this.toast(\r\n pass ? 'success' : 'error',\r\n pass\r\n ? `\u2705 ${a.name} passed PR #${rec.prNumber}${repo.autoMerge ? \"; it merges once GitHub's checks are green\" : ': ready to merge'}`\r\n : nextStatus === 'needs-human'\r\n ? `\u274C PR #${rec.prNumber} failed QA ${qaRounds} times and needs a human`\r\n : `\u274C ${a.name} failed PR #${rec.prNumber}; sending it back to the developer`,\r\n );\r\n }\r\n }\r\n\r\n private async renderQaComment(a: PersistedAgent, repo: PersistedRepo, rec: QaRecord, report: QaReport, shots: Shot[]) {\r\n const pass = report.verdict === 'pass';\r\n const images: string[] = [];\r\n const evidence = shots.slice(-8);\r\n const offset = shots.length - evidence.length;\r\n const folder = `pr-${rec.prNumber}/round-${rec.round}-${Date.now().toString(36)}`;\r\n for (const [i, shot] of evidence.entries()) {\r\n const n = offset + i + 1;\r\n const ext = MIME_EXT[shot.mime] ?? 'png';\r\n const file = `${folder}/${String(n).padStart(2, '0')}.${ext}`;\r\n try {\r\n const url = await this.backend.uploadEvidence(repo.fullName, file, shot.data);\r\n const caption = report.screenshots[n - 1] ?? `Screenshot ${n}`;\r\n images.push(`**${n}. ${caption}**${shot.url ? ` \u00B7 \\`${shot.url}\\`` : ''}\\n\\n<img src=\"${url}\" alt=\"${caption.replace(/\"/g, \"'\")}\" width=\"760\">`);\r\n } catch (err) {\r\n this.appendLog(a, [{ kind: 'error', text: ` \u23BF screenshot ${n} upload failed: ${(err as Error).message.slice(0, 120)}` }]);\r\n }\r\n }\r\n const dev = rec.devAgentId ? this.state.agents.find((x) => x.id === rec.devAgentId) : null;\r\n const lines = [\r\n `## \uD83D\uDD0D QA report: ${pass ? '\u2705 Passed' : '\u274C Failed'}`,\r\n `**Tester:** ${a.name} (cubefarm QA agent) \u00B7 **Round:** ${rec.round}${dev ? ` \u00B7 **Author:** ${dev.name}` : ''}`,\r\n '',\r\n report.summary,\r\n '',\r\n '| | Check | Details |',\r\n '|---|---|---|',\r\n ...report.checks.map((c) => `| ${ICON[c.result]} | ${cell(c.name)} | ${cell(c.details)} |`),\r\n ];\r\n if (report.commands.length) {\r\n lines.push('', '<details><summary>\uD83E\uDDEA Commands run</summary>', '', '| Command | Result |', '|---|---|', ...report.commands.map((c) => `| \\`${cell(c.command)}\\` | ${cell(c.result)} |`), '', '</details>');\r\n }\r\n if (!pass && report.fixInstructions) lines.push('', '### \uD83D\uDD27 What needs fixing', '', report.fixInstructions);\r\n if (images.length) lines.push('', '### \uD83D\uDCF8 Evidence', '', ...images.flatMap((img) => [img, '']));\r\n else lines.push('', '_No browser screenshots were taken in this round._');\r\n const merge = repo.autoMerge ? \"merges automatically once GitHub's checks pass\" : 'ready for the manager to merge';\r\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>`);\r\n return lines.join('\\n');\r\n }\r\n\r\n /** Send a failed PR back to the developer who wrote it (or any free developer on the floor). */\r\n private async runFix(dev: PersistedAgent, repo: PersistedRepo, rec: QaRecord) {\r\n const original = rec.devAgentId === dev.id;\r\n const pull = this.repoRt.get(repo.id)?.pulls.find((p) => p.number === rec.prNumber);\r\n const headRef = pull?.headRefName ?? dev.branch ?? `pr-${rec.prNumber}`;\r\n const qaAgent = rec.qaAgentId ? this.state.agents.find((x) => x.id === rec.qaAgentId) : null;\r\n this.setQa(rec, { status: 'fixing', devAgentId: dev.id });\r\n this.beginTask(\r\n dev,\r\n { task: 'fix', issueNumber: rec.issueNumber, issueTitle: pull?.title ?? `PR #${rec.prNumber}`, branch: headRef, prNumber: rec.prNumber, prUrl: pull?.url ?? null },\r\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}`,\r\n `Checking out PR #${rec.prNumber}\u2026`,\r\n );\r\n const cwd = await this.prepare(dev, repo, { pr: rec.prNumber }, headRef);\r\n if (!cwd) {\r\n if (rec.status === 'fixing') this.setQa(rec, { status: 'failed' });\r\n return;\r\n }\r\n const failed = rec.checks.filter((c) => c.result === 'fail');\r\n const takeover = original ? '' : ' A teammate wrote it, so read the PR and the linked issue first.';\r\n const push = `push to the same branch: git push origin HEAD:${headRef}`;\r\n const mergeFix =\r\n rec.fixReason === 'conflict'\r\n ? [\r\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but it now conflicts with ${repo.defaultBranch} because other work was merged first.${takeover}`,\r\n '',\r\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}`,\r\n ]\r\n : rec.fixReason === 'checks'\r\n ? [\r\n `QA passed pull request #${rec.prNumber} (${pull?.url ?? ''}), but GitHub checks failed on it.${takeover}`,\r\n '',\r\n `Failed checks:\\n${rec.fixInstructions ?? ''}`,\r\n '',\r\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}`,\r\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.`,\r\n ]\r\n : null;\r\n const qaFix = [\r\n original\r\n ? `QA tester ${qaAgent?.name ?? 'QA'} tested your pull request #${rec.prNumber} and it FAILED (round ${rec.round}).`\r\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.`,\r\n '',\r\n `QA summary: ${rec.summary ?? ''}`,\r\n failed.length ? `Failed checks:\\n${failed.map((c) => `- ${c.name}: ${c.details}`).join('\\n')}` : '',\r\n rec.fixInstructions ? `\\nWhat needs fixing:\\n${rec.fixInstructions}` : '',\r\n rec.commentUrl ? `\\nFull report with screenshots: ${rec.commentUrl}` : '',\r\n '',\r\n `Fix these problems, re-run the relevant checks, and push to the same branch: git push origin HEAD:${headRef}`,\r\n 'Then reply with a short summary of what you changed. Do not open a new pull request; QA will re-test automatically.',\r\n ];\r\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.';\r\n const prompt = (mergeFix ? [...mergeFix, '', mergeEnd] : qaFix).filter((l) => l !== '').join('\\n');\r\n const resume = original && rec.devSessionId ? rec.devSessionId : undefined;\r\n this.startAgentSession(dev, repo, cwd, prompt, this.buildSystemAppend(dev, repo, cwd, headRef, { pr: rec.prNumber, headRef }), resume);\r\n }\r\n\r\n private onFixFinished(a: PersistedAgent, repo: PersistedRepo, result: SessionResult) {\r\n const rec = this.state.qa.find((q) => q.repoId === repo.id && q.prNumber === a.prNumber);\r\n if (a.status === 'stopped') {\r\n if (rec?.status === 'fixing') this.setQa(rec, { status: 'failed' });\r\n return;\r\n }\r\n if (!result.ok) {\r\n this.fail(a, result, `the fix for PR #${a.prNumber}`);\r\n // Someone else gets a go before it lands on the manager.\r\n const failures = rec ? rec.sessionFailures + (this.limited() ? 0 : 1) : 0;\r\n if (rec) this.setQa(rec, { status: failures >= 2 ? 'needs-human' : 'failed', sessionFailures: failures });\r\n return;\r\n }\r\n a.status = 'done';\r\n if (rec && (rec.fixReason === 'checks' || rec.fixReason === 'conflict')) {\r\n // Back in line to merge: new commits go through QA again first, a re-run of flaky checks doesn't.\r\n this.appendLog(a, [{ kind: 'done', text: `\u2714 PR #${a.prNumber} fixed in ${this.minutes(a)}m. Back in line to merge.` }]);\r\n this.setQa(rec, { status: 'passed', devSessionId: a.sessionId ?? rec.devSessionId, mergeNote: 'waiting for fresh checks' });\r\n this.toast('info', `${a.name} fixed PR #${rec.prNumber}; it merges once it passes again`);\r\n return;\r\n }\r\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Fix pushed for PR #${a.prNumber} in ${this.minutes(a)}m. Back to QA.` }]);\r\n if (rec) {\r\n this.setQa(rec, { status: 'queued', round: rec.round + 1, devSessionId: a.sessionId ?? rec.devSessionId });\r\n this.toast('info', `${a.name} pushed fixes for PR #${rec.prNumber}; QA round ${rec.round} is queued`);\r\n }\r\n }\r\n\r\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. */\r\n async message(id: string, text: string, typed = false) {\r\n const a = this.agent(id);\r\n if (a.role === 'ceo') return this.messageCeo(text);\r\n const repo = this.repo(a.repoId);\r\n if (!text.trim()) throw new HttpError(400, 'Empty message');\r\n const rt = this.agentRt.get(id)!;\r\n if (rt.session) {\r\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\r\n if (!typed) rt.session.send(text);\r\n return;\r\n }\r\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.`);\r\n if (a.status === 'preparing') throw new HttpError(409, `${a.name} is still setting up; try again in a moment`);\r\n if (!a.sessionId || !a.branch || a.task === 'qa') throw new HttpError(409, `${a.name} has no session to continue. Assign an issue instead.`);\r\n this.ensureSlot();\r\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${text}` }]);\r\n const cwd = this.backend.deskDir(repo.fullName, this.agentSlug(a));\r\n a.lastError = null;\r\n a.startedAt = Date.now();\r\n if (a.task === null) a.task = 'issue';\r\n const fixing = a.task === 'fix' && a.prNumber ? { pr: a.prNumber, headRef: a.branch } : undefined;\r\n this.startAgentSession(a, repo, cwd, text, this.buildSystemAppend(a, repo, cwd, a.branch, fixing), a.sessionId, undefined, typed ? 'typed' : null);\r\n }\r\n\r\n updateSettings(patch: Partial<SwarmSettings>) {\r\n const s = this.state.settings;\r\n if (patch.sessionLimit !== undefined) s.sessionLimit = Math.max(0, Math.round(Number(patch.sessionLimit)) || 0);\r\n // The default model belongs to the default coding agent: a new agent starts on its own default.\r\n if (isCli(patch.defaultCli) && patch.defaultCli !== s.defaultCli) {\r\n s.defaultCli = patch.defaultCli;\r\n if (patch.defaultModel === undefined) s.defaultModel = s.defaultCli === 'claude' ? DEFAULT_MODEL : '';\r\n }\r\n if (patch.defaultModel !== undefined) s.defaultModel = String(patch.defaultModel).trim() || (s.defaultCli === 'claude' ? DEFAULT_MODEL : '');\r\n if (patch.defaultEffort !== undefined && EFFORTS.includes(patch.defaultEffort)) s.defaultEffort = patch.defaultEffort;\r\n if (patch.runtime === 'terminal' || patch.runtime === 'sdk') s.runtime = patch.runtime;\r\n if (patch.hiring === 'approve' || patch.hiring === 'auto') s.hiring = patch.hiring;\r\n if (patch.teamCap !== undefined) s.teamCap = Math.max(1, Math.min(15, Math.round(Number(patch.teamCap)) || 1));\r\n if (patch.ceoHeartbeatMin !== undefined) s.ceoHeartbeatMin = Math.max(0, Math.min(1440, Math.round(Number(patch.ceoHeartbeatMin)) || 0));\r\n if (typeof patch.managerName === 'string') s.managerName = patch.managerName.trim().slice(0, 40);\r\n if (typeof patch.companyName === 'string') s.companyName = patch.companyName.trim().slice(0, 60);\r\n if (typeof patch.projectsDir === 'string' && patch.projectsDir.trim()) s.projectsDir = path.resolve(patch.projectsDir.trim());\r\n if (typeof patch.setupDone === 'boolean') s.setupDone = patch.setupDone;\r\n if (patch.tutorialStep !== undefined) s.tutorialStep = Math.max(-1, Math.round(Number(patch.tutorialStep)) || 0);\r\n if (typeof patch.autoUpdate === 'boolean') s.autoUpdate = patch.autoUpdate;\r\n if (patch.pacingSessions !== undefined) s.pacingSessions = clampPacingSessions(patch.pacingSessions);\r\n this.save();\r\n this.broadcast({ type: 'settings', settings: s });\r\n this.emitCeo();\r\n setTimeout(() => this.schedule(), 200);\r\n return s;\r\n }\r\n\r\n /** The setup wizard: who you are, the company, and your CEO. */\r\n setup(x: { managerName?: string; companyName?: string; hiring?: string; ceoName?: string; ceoLook?: string; ceoColor?: string }) {\r\n this.updateSettings({\r\n managerName: x.managerName,\r\n companyName: x.companyName,\r\n ...(x.hiring === 'auto' || x.hiring === 'approve' ? { hiring: x.hiring } : {}),\r\n });\r\n const ceo = this.ceo();\r\n this.updateAgent(ceo.id, { name: x.ceoName, color: x.ceoColor });\r\n if (LOOKS.includes(x.ceoLook as AgentLook)) this.updateAgent(ceo.id, { look: x.ceoLook });\r\n return this.state.settings;\r\n }\r\n\r\n // ---------- scheduling ----------\r\n\r\n /**\r\n * Agents on a floor who can take work now. One whose last session failed sits out a short cooldown, then gets work\r\n * like everyone else instead of waiting for the manager to reset them.\r\n */\r\n private available(repo: PersistedRepo, role: AgentRole) {\r\n const now = Date.now();\r\n return this.state.agents\r\n .filter((a) => a.repoId === repo.id && a.role === role && (FREE.includes(a.status) || (a.status === 'error' && now - (a.endedAt ?? 0) >= ERROR_COOLDOWN_MS)))\r\n .sort((x, y) => x.desk - y.desk);\r\n }\r\n\r\n private scheduleOffset = 0;\r\n private issueFailures = new Map<string, number>(); // `${repoId}#${issue}` \u2192 failed sessions on it\r\n private nudged = new Set<string>(); // `${repoId}#${issue}`: its developer was asked once to finish the missing PR\r\n private pausedUntil = 0; // Claude's usage limit was hit: nothing new starts before this\r\n private pacingUntil = 0; // Claude warned about usage: new issues are paced until this\r\n private lastUsage = '';\r\n\r\n /** Backlog issues that can start now, most urgent first: the ones holding up the longest chain of other issues, then the oldest. */\r\n private readyIssues(repo: PersistedRepo) {\r\n const issues = this.repoRt.get(repo.id)!.issues;\r\n const open = new Set(issues.map((i) => i.number));\r\n const weight = holdUps(issues);\r\n return issues\r\n .filter(\r\n (i) =>\r\n !i.labels.some((l) => /^(swarm:skip|wontfix|question)$/i.test(l)) &&\r\n !this.issueTaken(repo, i.number) &&\r\n blockers(i.body, open).length === 0 &&\r\n (this.issueFailures.get(`${repo.id}#${i.number}`) ?? 0) < MAX_ISSUE_FAILURES,\r\n )\r\n .map((issue) => ({ issue, want: issueSpecialty(issue.labels), ...weight.get(issue.number)! }))\r\n .sort((x, y) => y.chain - x.chain || y.waiting - x.waiting || x.issue.number - y.issue.number);\r\n }\r\n\r\n /**\r\n * The free developer to put on a job: one it `suits` first, then whoever is least needed elsewhere (fewest ready\r\n * issues in their specialty, then the least open work in it), so specialists stay free for their own lane.\r\n */\r\n private pickDev(repo: PersistedRepo, devs: PersistedAgent[], suits: (a: PersistedAgent) => boolean) {\r\n if (devs.length <= 1) return devs[0];\r\n const ready = this.readyIssues(repo).map((r) => r.want);\r\n const open = this.repoRt.get(repo.id)!.issues.map((i) => issueSpecialty(i.labels));\r\n const rank = (a: PersistedAgent) => {\r\n const s = a.specialty.toLowerCase();\r\n return [suits(a) ? 0 : 1, ready.filter((w) => w === s).length, open.filter((w) => w === s).length, a.desk];\r\n };\r\n return devs\r\n .map((a) => ({ a, r: rank(a) }))\r\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;\r\n }\r\n\r\n /**\r\n * Finish work in flight: test queued PRs (oldest first) and get failed ones fixed. Returns true if work started.\r\n * QA testers test; when they're all busy, a free developer who didn't write the PR covers for them, so QA never\r\n * holds up the floor. A failed PR goes back to its author when they're free, and otherwise to any free developer.\r\n */\r\n private startPipelineWork(repo: PersistedRepo): boolean {\r\n const devs = this.available(repo, 'dev');\r\n const testers = this.available(repo, 'qa');\r\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);\r\n for (const rec of waiting('queued')) {\r\n const tester =\r\n testers[0] ??\r\n this.pickDev(\r\n repo,\r\n devs.filter((a) => a.id !== rec.devAgentId),\r\n (a) => /test|qa/i.test(a.specialty),\r\n );\r\n if (!tester) continue;\r\n void this.runQa(tester, repo, rec);\r\n return true;\r\n }\r\n for (const rec of waiting('failed')) {\r\n const issue = this.repoRt.get(repo.id)!.issues.find((i) => i.number === rec.issueNumber);\r\n const want = issue ? issueSpecialty(issue.labels) : null;\r\n const dev = devs.find((a) => a.id === rec.devAgentId) ?? this.pickDev(repo, devs, (a) => a.specialty.toLowerCase() === want);\r\n if (!dev) break;\r\n void this.runFix(dev, repo, rec);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Give a free developer the next backlog issue (auto-assign floors only). Returns true if work started.\r\n * Issues that say \"Depends on #N\" wait until #N is closed; the rest go in readyIssues() order. A swarm:<specialty>\r\n * label is a preference, not a lock: a free specialist gets first pick, and otherwise the issue goes to whichever\r\n * free developer is least needed elsewhere, so nobody sits idle while there is work that can start.\r\n */\r\n private startIssueWork(repo: PersistedRepo): boolean {\r\n if (!repo.autoAssign || !this.mayStart('issue')) return false;\r\n const free = this.available(repo, 'dev');\r\n const ready = free.length ? this.readyIssues(repo) : [];\r\n if (ready.length === 0) return false;\r\n const fits = (a: PersistedAgent, want: string) => a.specialty.toLowerCase() === want;\r\n // Of the issues holding up the most, take one a free specialist fits.\r\n const pick = ready.find((r) => r.chain === ready[0].chain && free.some((a) => fits(a, r.want))) ?? ready[0];\r\n const agent = this.pickDev(repo, free, (a) => fits(a, pick.want))!;\r\n // assign() flips the agent to 'preparing' synchronously, so the next pass sees it as busy.\r\n void this.assign(agent.id, pick.issue.number).catch((err) => console.warn('auto-assign failed', err));\r\n return agent.status === 'preparing';\r\n }\r\n\r\n private limited() {\r\n return Date.now() < this.pausedUntil;\r\n }\r\n\r\n /** Claude turned a session away for the usage limit: start nothing new until it resets, rather than failing agent after agent. */\r\n private pauseForLimit(resetsAt: number | null) {\r\n const until = (resetsAt ?? Date.now() + LIMIT_PAUSE_MS) + 30_000;\r\n if (until <= this.pausedUntil) return;\r\n const fresh = Date.now() >= this.pausedUntil;\r\n this.pausedUntil = until;\r\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.`);\r\n this.emitUsage();\r\n }\r\n\r\n /** Claude warned that usage is getting high: pace new issues until the window resets, rather than run into the limit. */\r\n private paceForWarning(info: UsageWarning) {\r\n const now = Date.now();\r\n const until = info.resetsAt && info.resetsAt > now ? info.resetsAt : now + PACING_MS;\r\n if (until <= this.pacingUntil) return;\r\n const fresh = now >= this.pacingUntil;\r\n this.pacingUntil = until;\r\n if (fresh) this.postMessage('office', pacingMessage(info, until, this.state.settings.pacingSessions, now));\r\n this.emitUsage();\r\n }\r\n\r\n /** May work of this kind start now, as far as Claude's usage goes? */\r\n private mayStart(kind: WorkKind) {\r\n return mayStart(kind, { now: Date.now(), pausedUntil: this.pausedUntil, pacingUntil: this.pacingUntil, running: this.running(), pacingSessions: this.state.settings.pacingSessions });\r\n }\r\n\r\n private usageNow() {\r\n return usageView({ now: Date.now(), pausedUntil: this.pausedUntil, pacingUntil: this.pacingUntil });\r\n }\r\n\r\n private emitUsage() {\r\n const usage = this.usageNow();\r\n const key = JSON.stringify(usage);\r\n if (key === this.lastUsage) return;\r\n this.lastUsage = key;\r\n this.broadcast({ type: 'usage', usage });\r\n }\r\n\r\n /** Pacing and pauses run out on their own: say so when pacing ends. */\r\n private tickUsage() {\r\n if (this.pacingUntil && Date.now() >= this.pacingUntil) {\r\n this.pacingUntil = 0;\r\n this.postMessage('office', \"\u2705 Claude's usage is back to normal. The office starts new work at full speed again.\");\r\n }\r\n this.emitUsage();\r\n }\r\n\r\n /** A failed session releases its issue for someone else; an issue that keeps failing waits for the manager. */\r\n private issueFailed(repo: PersistedRepo, n: number | null) {\r\n if (n == null || this.limited()) return; // the usage limit isn't the issue's fault\r\n const key = `${repo.id}#${n}`;\r\n const failures = (this.issueFailures.get(key) ?? 0) + 1;\r\n this.issueFailures.set(key, failures);\r\n if (failures === MAX_ISSUE_FAILURES) {\r\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.`);\r\n }\r\n }\r\n\r\n /**\r\n * Hand out work for free session slots. Finishing beats starting: QA and QA fixes on every floor go before any new issue.\r\n * Within each phase floors take turns (one job per floor per pass), and the starting floor rotates between calls,\r\n * so no repo can hog the slots.\r\n */\r\n private schedule() {\r\n this.tickUsage();\r\n if (this.officeUpdateTick()) return; // draining for the office's own update\r\n if (this.limited()) return;\r\n // Management first: the CEO's jobs are short and shape everyone else's work.\r\n this.maybeHeartbeat();\r\n this.startCeoWork();\r\n const repos = this.state.repos.filter((r) => {\r\n const rt = this.repoRt.get(r.id);\r\n return rt && rt.lastSync != null && rt.cloneStatus !== 'error';\r\n });\r\n if (repos.length === 0) return;\r\n this.scheduleOffset = (this.scheduleOffset + 1) % repos.length;\r\n const order = [...repos.slice(this.scheduleOffset), ...repos.slice(0, this.scheduleOffset)];\r\n for (const start of [(r: PersistedRepo) => this.startPipelineWork(r), (r: PersistedRepo) => this.startIssueWork(r)]) {\r\n let progress = true;\r\n while (progress) {\r\n progress = false;\r\n for (const repo of order) {\r\n if (this.slotsFull()) return;\r\n if (start(repo)) progress = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // ---------- the office's own update ----------\r\n\r\n private drainInput(): DrainInput {\r\n const u = this.officeUpdate;\r\n return {\r\n now: Date.now(),\r\n behind: this.officeHead ? u.behind : 0,\r\n launcher: this.backend.office.launcher,\r\n autoUpdate: this.state.settings.autoUpdate !== false,\r\n requested: u.requested,\r\n postponedUntil: u.postponedUntil,\r\n postponedBehind: u.postponedBehind,\r\n failed: u.failed,\r\n failedBehind: u.failedBehind,\r\n drainingSince: u.drainingSince,\r\n sent: u.sent,\r\n running: this.running(),\r\n };\r\n }\r\n\r\n private officeUpdateView(): OfficeUpdateView {\r\n const u = this.officeUpdate;\r\n const input = this.drainInput();\r\n const d = drainDecision(input);\r\n const until = u.postponedUntil ? new Date(u.postponedUntil).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : '';\r\n const detail = d.state === 'failed' ? u.failed : d.state === 'waiting' ? `Postponed until ${until}, or until a newer commit lands.` : null;\r\n return { state: d.state, behind: input.behind, launcher: input.launcher, drainingSince: u.drainingSince ?? d.drainingSince, running: input.running, detail };\r\n }\r\n\r\n private emitOfficeUpdate() {\r\n if (!this.officeHead) return;\r\n const view = this.officeUpdateView();\r\n const key = JSON.stringify(view);\r\n if (key === this.lastOfficeView) return;\r\n this.lastOfficeView = key;\r\n this.broadcast({ type: 'officeUpdate', officeUpdate: view });\r\n }\r\n\r\n /** The own-folder check found the office this many commits behind GitHub. */\r\n private setOfficeBehind(behind: number) {\r\n const u = this.officeUpdate;\r\n if (u.failed && u.failedBehind === null) u.failedBehind = behind; // only a newer commit retries a failed update by itself\r\n u.behind = behind;\r\n if (behind === 0) Object.assign(u, { requested: false, failed: null, failedBehind: null });\r\n this.officeUpdateTick();\r\n }\r\n\r\n /**\r\n * Take the office's own update one step (see drainDecision): drain, and once nothing is running, or the drain timed\r\n * out, hand it to the launcher. True while nothing new may start.\r\n */\r\n private officeUpdateTick(): boolean {\r\n if (!this.officeHead) return false;\r\n const u = this.officeUpdate;\r\n const d = drainDecision(this.drainInput());\r\n if (d.state === 'draining' && u.drainingSince === null) {\r\n const running = this.running();\r\n this.postMessage(\r\n 'office',\r\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.`,\r\n );\r\n }\r\n u.drainingSince = d.drainingSince;\r\n if (d.send) void this.handOver(d.timedOut);\r\n this.emitOfficeUpdate();\r\n return d.state === 'draining' || d.state === 'updating';\r\n }\r\n\r\n /** Drained: hand the update to the launcher. Sessions still running after the timeout stop the way a restart stops them. */\r\n private async handOver(timedOut: boolean) {\r\n const u = this.officeUpdate;\r\n const from = this.officeHead!;\r\n u.sent = true;\r\n const busy = this.state.agents.filter((a) => BUSY.includes(a.status));\r\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.`);\r\n this.emitOfficeUpdate();\r\n u.handedOver = true;\r\n await this.writeState().catch((err) => console.warn('could not save the state', err)); // still \"working\": the restarted office recovers them\r\n for (const a of busy) this.agentRt.get(a.id)?.session?.stop();\r\n try {\r\n const result = await this.backend.office.update(from);\r\n if (result) await this.afterUpdate(result); // the demo: nothing restarts\r\n } catch (err) {\r\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() });\r\n }\r\n }\r\n\r\n /** An update that didn't restart the office (the demo, or a failed hand-over): recover like a restart would, then report it. */\r\n private async afterUpdate(result: LastUpdate) {\r\n const u = this.officeUpdate;\r\n Object.assign(u, { sent: false, handedOver: false, requested: false, drainingSince: null });\r\n const interrupted = this.state.agents.filter((a) => BUSY.includes(a.status));\r\n for (const a of interrupted) {\r\n Object.assign(a, { status: 'stopped', lastError: 'The office updated itself while this agent was working.' });\r\n const rt = this.agentRt.get(a.id);\r\n if (rt) Object.assign(rt, { session: null, currentTool: null });\r\n }\r\n this.ensureCeo(interrupted);\r\n this.recover(interrupted);\r\n interrupted.forEach((a) => this.emitAgent(a));\r\n await this.reportUpdate(result);\r\n if (!result.ok) u.failedBehind = u.behind;\r\n const own = this.state.repos.find((r) => this.backend.office.isOwnFolder(this.backend.mainDir(r.fullName)));\r\n if (own) await this.syncFolder(own);\r\n this.emitCeo();\r\n this.save();\r\n setTimeout(() => this.schedule(), 300);\r\n }\r\n\r\n /** One phone message about the last update (the launcher's last-update.json, or the demo's fake). */\r\n private async reportUpdate(result: LastUpdate) {\r\n const commits = result.ok && result.to ? await this.backend.office.commitsBetween(result.from, result.to) : null;\r\n this.postMessage('office', lastUpdateMessage(result, commits));\r\n Object.assign(this.officeUpdate, { failed: result.ok ? null : result.error || 'unknown error', failedBehind: null });\r\n }\r\n\r\n /** The manager's Update now (drain now, even with automatic updates off) or Later (not for 2 hours, or until a newer commit). */\r\n updateOffice(action: unknown): OfficeUpdateView {\r\n if (action !== 'now' && action !== 'later') throw new HttpError(400, 'action must be \"now\" or \"later\"');\r\n const u = this.officeUpdate;\r\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).');\r\n if (u.sent) throw new HttpError(409, 'The update is already under way.');\r\n if (u.behind <= 0) throw new HttpError(409, 'The office is up to date: there is nothing to update.');\r\n if (action === 'now') Object.assign(u, { requested: true, postponedUntil: null });\r\n else Object.assign(u, { requested: false, postponedUntil: Date.now() + POSTPONE_MS, postponedBehind: u.behind });\r\n this.officeUpdateTick();\r\n setTimeout(() => this.schedule(), 200);\r\n return this.officeUpdateView();\r\n }\r\n\r\n // ---------- the CEO ----------\r\n\r\n private ceo() {\r\n return this.state.agents.find((a) => a.id === CEO_ID)!;\r\n }\r\n\r\n /** The company always has a CEO. One cut off by a server restart picks its job back up. */\r\n private ensureCeo(interrupted: PersistedAgent[]) {\r\n let a = this.state.agents.find((x) => x.id === CEO_ID);\r\n if (!a) {\r\n a = {\r\n id: CEO_ID,\r\n name: CEO_NAME,\r\n repoId: '',\r\n role: 'ceo',\r\n title: 'Chief Executive Officer',\r\n specialty: '',\r\n brief: '',\r\n hiredBy: 'manager',\r\n look: lookFor(CEO_NAME),\r\n task: null,\r\n desk: 0,\r\n color: '#e63946',\r\n hair: '#2b2118',\r\n skin: pick(SKIN),\r\n model: CEO_MODEL,\r\n effort: CEO_EFFORT,\r\n cli: 'claude',\r\n status: 'idle',\r\n issueNumber: null,\r\n issueTitle: null,\r\n branch: null,\r\n prNumber: null,\r\n prUrl: null,\r\n startedAt: null,\r\n endedAt: null,\r\n costUsd: 0,\r\n turns: 0,\r\n sessionId: null,\r\n sessionCli: null,\r\n lastError: null,\r\n logTail: [],\r\n };\r\n this.state.agents.push(a);\r\n this.agentRt.set(a.id, { log: [], pending: [], session: null, currentTool: null, browserUrl: null, screenshot: null, shots: [], terminal: null });\r\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.` }]);\r\n }\r\n const i = interrupted.indexOf(a);\r\n if (i >= 0) {\r\n interrupted.splice(i, 1);\r\n a.status = 'idle';\r\n a.lastError = null;\r\n this.appendLog(a, [{ kind: 'system', text: '\u21BA The office server restarted. Picking the job back up.' }]);\r\n }\r\n if (this.state.ceo.job) {\r\n this.state.ceo.queue.unshift(this.state.ceo.job);\r\n this.state.ceo.job = null;\r\n }\r\n this.state.ceo.lastReviewAt ??= Date.now(); // the first review comes one heartbeat after the office opens\r\n }\r\n\r\n private ceoFloor(repoId?: string) {\r\n const repo = repoId ? this.state.repos.find((r) => r.id === repoId) : undefined;\r\n if (!repo) return null;\r\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 };\r\n }\r\n\r\n private ceoInfo(): CeoInfo {\r\n const c = this.state.ceo;\r\n const view = (j: CeoJob) => ({ kind: j.kind, label: jobLabel(j, this.ceoFloor(j.repoId)) });\r\n const min = this.state.settings.ceoHeartbeatMin;\r\n return {\r\n queue: c.queue.map(view),\r\n job: c.job ? view(c.job) : null,\r\n lastReviewAt: c.lastReviewAt,\r\n nextReviewAt: min > 0 && c.lastReviewAt ? c.lastReviewAt + min * 60_000 : null,\r\n };\r\n }\r\n\r\n private emitCeo() {\r\n this.broadcast({ type: 'ceo', ceo: this.ceoInfo() });\r\n }\r\n\r\n /** Queue a job for the CEO: one onboarding or plan per floor, one review, and chat messages merge into one reply. */\r\n private enqueueCeo(job: CeoJob) {\r\n const q = this.state.ceo.queue;\r\n if (job.kind === 'plan' && q.some((j) => j.kind === 'onboard' && j.repoId === job.repoId)) return; // onboarding plans from the brief too\r\n const same = q.findIndex((j) => j.kind === job.kind && (job.kind === 'review' || job.kind === 'chat' || j.repoId === job.repoId));\r\n if (same >= 0) q[same] = job.kind === 'chat' ? { ...q[same], text: `${q[same].text}\\n${job.text}` } : job;\r\n else q.push(job);\r\n this.emitCeo();\r\n this.save();\r\n setTimeout(() => this.schedule(), 150);\r\n }\r\n\r\n /** Start the CEO's next job when they're free and a session slot is open. Replies to the manager go first. */\r\n private startCeoWork(): void {\r\n const a = this.state.agents.find((x) => x.id === CEO_ID);\r\n const c = this.state.ceo;\r\n if (!a || BUSY.includes(a.status) || c.job || c.queue.length === 0) return;\r\n if (this.slotsFull()) return;\r\n const rank: Record<CeoJob['kind'], number> = { chat: 0, onboard: 1, plan: 1, review: 2 };\r\n // A floor's jobs wait for its clone and first sync, so the CEO has something to read.\r\n const ready = (j: CeoJob) => {\r\n const rt = j.repoId ? this.repoRt.get(j.repoId) : undefined;\r\n return !rt || rt.cloneStatus === 'error' || (rt.cloneStatus === 'ready' && rt.lastSync != null);\r\n };\r\n const job = [...c.queue].sort((x, y) => rank[x.kind] - rank[y.kind]).find(ready);\r\n if (!job) return;\r\n c.queue.splice(c.queue.indexOf(job), 1);\r\n const rt = job.repoId ? this.repoRt.get(job.repoId) : undefined;\r\n if (job.repoId && (!rt || rt.cloneStatus === 'error')) {\r\n const repo = this.state.repos.find((r) => r.id === job.repoId);\r\n if (repo) this.postMessage('office', `\u26A0\uFE0F ${a.name} couldn't study floor ${repo.floor}: the repository clone failed (${rt?.cloneError ?? 'unknown error'}).`);\r\n this.emitCeo();\r\n this.save();\r\n return this.startCeoWork();\r\n }\r\n void this.runCeoJob(a, job);\r\n }\r\n\r\n private async runCeoJob(a: PersistedAgent, job: CeoJob) {\r\n const rt = this.agentRt.get(a.id)!;\r\n const floor = this.ceoFloor(job.repoId);\r\n const label = jobLabel(job, floor);\r\n this.state.ceo.job = job;\r\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 });\r\n this.appendLog(a, [\r\n { kind: 'system', text: '' },\r\n { kind: 'system', text: `\u2501\u2501\u2501 ${label} \u2501\u2501\u2501` },\r\n ]);\r\n if (job.kind === 'chat') this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${job.text}` }]);\r\n if (job.kind === 'review') {\r\n this.state.ceo.lastReviewAt = Date.now();\r\n this.state.ceo.lastFingerprint = this.fingerprint();\r\n }\r\n this.ceoIssues = new IssueCap(MAX_ISSUES_PER_JOB);\r\n this.emitAgent(a);\r\n this.emitCeo();\r\n this.save();\r\n await fs.mkdir(CEO_DIR, { recursive: true }).catch(() => undefined);\r\n if (a.status !== 'working') {\r\n // stopped before the session started\r\n this.state.ceo.job = null;\r\n this.emitCeo();\r\n return;\r\n }\r\n const s = this.state.settings;\r\n // A chat carries on from the CEO's last session, so \"why did you propose that?\" has an answer.\r\n const how = this.sessionRuntime(a, job.kind === 'chat' ? (a.sessionId ?? undefined) : undefined);\r\n rt.session = this.backend.startSession(\r\n {\r\n cwd: CEO_DIR,\r\n prompt: ceoJobPrompt(job, floor),\r\n systemAppend: ceoSystemPrompt({\r\n name: a.name,\r\n company: s.companyName,\r\n manager: s.managerName,\r\n notesFile: path.join(CEO_DIR, 'NOTES.md'),\r\n sessionLimit: s.sessionLimit,\r\n teamCap: s.teamCap,\r\n hiring: s.hiring,\r\n }),\r\n model: a.model || CEO_MODEL,\r\n effort: a.effort || CEO_EFFORT,\r\n browserTesting: false,\r\n additionalDirectories: this.state.repos.filter((r) => this.repoRt.get(r.id)?.cloneStatus === 'ready').map((r) => this.backend.mainDir(r.fullName)),\r\n role: 'ceo',\r\n office: this.officeTools(),\r\n ...how,\r\n },\r\n {\r\n log: (entries) => this.appendLog(a, entries),\r\n tool: (name) => {\r\n if (rt.currentTool === name) return;\r\n rt.currentTool = name;\r\n this.emitAgent(a);\r\n },\r\n sessionId: (id) => {\r\n a.sessionId = id;\r\n a.sessionCli = 'claude';\r\n },\r\n browserUrl: () => undefined,\r\n screenshot: () => undefined,\r\n turn: (text) => this.postMessage('ceo', text),\r\n limited: (at) => this.pauseForLimit(at),\r\n usageWarning: (info) => this.paceForWarning(info),\r\n finished: (result) => this.onCeoFinished(a, result),\r\n },\r\n );\r\n }\r\n\r\n private onCeoFinished(a: PersistedAgent, result: SessionResult) {\r\n const rt = this.agentRt.get(a.id);\r\n if (!rt || this.officeUpdate.handedOver) return;\r\n rt.session = null;\r\n rt.currentTool = null;\r\n a.endedAt = Date.now();\r\n a.costUsd += result.costUsd;\r\n a.turns += result.turns;\r\n const job = this.state.ceo.job;\r\n this.state.ceo.job = null;\r\n if (result.interrupted) this.interrupted(a);\r\n if (a.status === 'stopped') {\r\n // the manager already logged the stop\r\n } else if (!result.ok) {\r\n a.status = 'error';\r\n a.lastError = result.errors.join('; ') || 'Session failed';\r\n this.appendLog(a, [{ kind: 'error', text: `\u2717 ${a.lastError}` }]);\r\n const what = job ? jobLabel(job, this.ceoFloor(job.repoId)).toLowerCase() : 'working';\r\n this.postMessage('office', `\u26A0\uFE0F ${a.name} hit a problem while ${what}: ${a.lastError.slice(0, 240)}`);\r\n } else {\r\n a.status = 'done';\r\n const filed = this.ceoIssues.total ? ` \u00B7 ${this.ceoIssues.total} issue${this.ceoIssues.total === 1 ? '' : 's'} filed` : '';\r\n this.appendLog(a, [{ kind: 'done', text: `\u2714 Done in ${this.minutes(a)}m \u00B7 ${a.turns} turns${filed}` }]);\r\n }\r\n for (const id of this.ceoIssues.repos) void this.syncRepo(id);\r\n this.emitAgent(a);\r\n this.emitCeo();\r\n this.save();\r\n setTimeout(() => this.schedule(), 300);\r\n }\r\n\r\n /** The manager's phone \u2192 the CEO. Injected into a running session, otherwise the CEO picks it up next. */\r\n async messageCeo(text: string) {\r\n const t = text.trim().slice(0, 4000);\r\n if (!t) throw new HttpError(400, 'Empty message');\r\n const a = this.ceo();\r\n this.postMessage('manager', t);\r\n const rt = this.agentRt.get(a.id)!;\r\n if (rt.session) {\r\n this.appendLog(a, [{ kind: 'manager', text: `\u25B6 Manager: ${t}` }]);\r\n this.ceoIssues.managerMessage(); // a new request: the issue cap counts from here\r\n rt.session.send(`Message from the manager (they read your reply on their phone, so keep it short):\\n${t}`);\r\n return;\r\n }\r\n this.enqueueCeo({ kind: 'chat', text: t, at: Date.now() });\r\n }\r\n\r\n requestReview() {\r\n if (this.state.repos.length === 0) throw new HttpError(400, 'Connect a repo first: the CEO needs a floor to review.');\r\n this.enqueueCeo({ kind: 'review', at: Date.now() });\r\n }\r\n\r\n onboardFloor(repoId: string) {\r\n const repo = this.repo(repoId);\r\n this.enqueueCeo({ kind: 'onboard', repoId: repo.id, at: Date.now() });\r\n }\r\n\r\n /** The manager hands the CEO a brief for a floor; the CEO turns it into issues and a team. */\r\n planFloor(repoId: string, mission?: string) {\r\n const repo = this.repo(repoId);\r\n if (typeof mission === 'string') {\r\n repo.mission = mission.trim().slice(0, 4000);\r\n this.emitRepo(repo);\r\n }\r\n if (!repo.mission) throw new HttpError(400, 'Write a brief first: what should this floor build?');\r\n this.enqueueCeo({ kind: 'plan', repoId: repo.id, at: Date.now() });\r\n }\r\n\r\n /** Everything the heartbeat cares about. When it hasn't changed since the last review, the review is skipped. */\r\n private fingerprint() {\r\n const data = {\r\n repos: this.state.repos.map((r) => {\r\n const rt = this.repoRt.get(r.id);\r\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)];\r\n }),\r\n agents: this.state.agents.filter((a) => a.role !== 'ceo').map((a) => [a.id, FREE.includes(a.status) ? 'free' : a.status]),\r\n qa: this.state.qa.map((q) => [q.repoId, q.prNumber, q.status]),\r\n requests: this.state.requests.filter((r) => r.status === 'pending').map((r) => r.id),\r\n };\r\n return crypto.createHash('sha1').update(JSON.stringify(data)).digest('hex');\r\n }\r\n\r\n private maybeHeartbeat() {\r\n const min = this.state.settings.ceoHeartbeatMin;\r\n const c = this.state.ceo;\r\n if (!min || this.state.repos.length === 0 || c.job?.kind === 'review' || c.queue.some((j) => j.kind === 'review')) return;\r\n if (Date.now() < (c.lastReviewAt ?? 0) + min * 60_000) return;\r\n if (this.fingerprint() === c.lastFingerprint) {\r\n c.lastReviewAt = Date.now(); // nothing changed since the last review\r\n this.emitCeo();\r\n this.save();\r\n return;\r\n }\r\n this.enqueueCeo({ kind: 'review', at: Date.now() });\r\n }\r\n\r\n // ---------- the phone ----------\r\n\r\n private postMessage(from: PhoneMessage['from'], text: string, requestId?: string) {\r\n const m: PhoneMessage = { id: this.messageSeq++, from, text: text.trim().slice(0, 6000), at: Date.now(), ...(requestId ? { requestId } : {}) };\r\n this.state.messages.push(m);\r\n if (this.state.messages.length > KEEP_MESSAGES) this.state.messages.splice(0, this.state.messages.length - KEEP_MESSAGES);\r\n this.broadcast({ type: 'message', message: m });\r\n this.save();\r\n return m;\r\n }\r\n\r\n markPhoneRead(at: number) {\r\n const t = Math.min(Number(at) || Date.now(), Date.now());\r\n if (t <= this.state.phoneReadAt) return;\r\n this.state.phoneReadAt = t;\r\n this.broadcast({ type: 'phoneRead', at: t });\r\n this.save();\r\n }\r\n\r\n // ---------- hire and let-go proposals ----------\r\n\r\n private addRequest(req: HireRequestView) {\r\n this.state.requests.push(req);\r\n const decided = this.state.requests.filter((r) => r.status !== 'pending');\r\n if (decided.length > KEEP_DECIDED_REQUESTS) {\r\n const drop = new Set(decided.slice(0, decided.length - KEEP_DECIDED_REQUESTS));\r\n this.state.requests = this.state.requests.filter((r) => !drop.has(r));\r\n }\r\n this.broadcast({ type: 'request', request: req });\r\n this.save();\r\n }\r\n\r\n private decide(req: HireRequestView, patch: Pick<HireRequestView, 'status' | 'note' | 'decidedBy'>) {\r\n Object.assign(req, patch, { decidedAt: Date.now() });\r\n this.broadcast({ type: 'request', request: req });\r\n this.save();\r\n }\r\n\r\n approveRequest(id: string, overrides: { name?: string; model?: string; effort?: string } = {}, by: 'manager' | 'auto' = 'manager') {\r\n const req = this.state.requests.find((r) => r.id === id);\r\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\r\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\r\n const repo = this.repo(req.repoId);\r\n if (req.kind === 'hire') {\r\n const name = overrides.name?.trim() || req.name;\r\n const agent = this.hireAgent(repo.id, {\r\n name,\r\n role: req.role,\r\n model: overrides.model ?? req.model,\r\n effort: overrides.effort ?? req.effort,\r\n look: name === req.name ? req.look : undefined,\r\n title: req.title,\r\n specialty: req.specialty,\r\n brief: req.brief,\r\n hiredBy: 'ceo',\r\n appearance: { color: req.color, hair: req.hair, skin: req.skin },\r\n });\r\n req.agentId = agent.id;\r\n req.name = agent.name;\r\n this.decide(req, { status: 'approved', note: '', decidedBy: by });\r\n this.postMessage(\r\n 'office',\r\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}.`,\r\n req.id,\r\n );\r\n this.toast('success', `${agent.name} (${req.title}) joined floor ${repo.floor}`);\r\n return;\r\n }\r\n const a = req.agentId ? this.state.agents.find((x) => x.id === req.agentId) : undefined;\r\n this.decide(req, { status: 'approved', note: a ? '' : 'They had already left.', decidedBy: by });\r\n if (a) {\r\n try {\r\n this.fireAgent(a.id);\r\n } catch (err) {\r\n this.decide(req, { status: 'pending', note: '', decidedBy: null });\r\n throw err;\r\n }\r\n }\r\n this.postMessage('office', `\uD83D\uDC4B ${req.name} left floor ${repo.floor}${by === 'auto' ? ' (auto-approved)' : ''}.`, req.id);\r\n }\r\n\r\n rejectRequest(id: string, note = '') {\r\n const req = this.state.requests.find((r) => r.id === id);\r\n if (!req) throw new HttpError(404, 'That proposal no longer exists');\r\n if (req.status !== 'pending') throw new HttpError(409, `That proposal was already ${req.status}`);\r\n this.decide(req, { status: 'rejected', note: note.trim().slice(0, 400), decidedBy: 'manager' });\r\n const what = req.kind === 'hire' ? `${req.name} (${req.title})` : `letting ${req.name} go`;\r\n this.postMessage('office', `\u270B You declined ${what}${req.note ? `: \"${req.note}\"` : '.'}`, req.id);\r\n }\r\n\r\n // ---------- the CEO's office tools ----------\r\n\r\n private floorRepo(floor: number) {\r\n const r = this.state.repos.find((x) => x.floor === Number(floor));\r\n if (!r) throw new Error(`There is no floor ${floor}. Floors: ${this.state.repos.map((x) => `${x.floor} (${x.fullName})`).join(', ') || 'none'}.`);\r\n return r;\r\n }\r\n\r\n private agentByRef(ref: string) {\r\n const r = String(ref ?? '').trim().toLowerCase();\r\n const a = this.state.agents.find((x) => x.id === ref || x.name.toLowerCase() === r);\r\n if (!a) throw new Error(`No agent \"${ref}\". Use the ids from company_status.`);\r\n return a;\r\n }\r\n\r\n private agentDoing(a: PersistedAgent) {\r\n return !BUSY.includes(a.status) ? null : a.task === 'qa' ? `testing PR #${a.prNumber}` : a.task === 'fix' ? `fixing PR #${a.prNumber}` : `issue #${a.issueNumber}`;\r\n }\r\n\r\n private companyStatus() {\r\n const s = this.state.settings;\r\n const doing = (a: PersistedAgent) => this.agentDoing(a);\r\n // Keep the status compact, but make the cut visible so the CEO knows to read agent_detail before rewriting.\r\n const jobDescription = (brief: string) => {\r\n if (brief.length <= 400) return brief;\r\n const mark = `\u2026 (truncated, ${brief.length} chars; see agent_detail)`;\r\n return brief.slice(0, 400 - mark.length).trimEnd() + mark;\r\n };\r\n const floors = [...this.state.repos]\r\n .sort((x, y) => x.floor - y.floor)\r\n .map((r) => {\r\n const rt = this.repoRt.get(r.id)!;\r\n const open = new Set(rt.issues.map((i) => i.number));\r\n return {\r\n floor: r.floor,\r\n repo: r.fullName,\r\n description: r.description,\r\n clone: rt.cloneStatus === 'ready' ? this.backend.mainDir(r.fullName) : `(not available: clone ${rt.cloneStatus})`,\r\n brief: r.mission || null,\r\n profile: r.summary || null,\r\n qaBrief: r.qaBrief || null,\r\n preview: { command: r.preview.command, env: r.preview.env, status: this.previews.view(r).status },\r\n autoAssign: r.autoAssign,\r\n autoMerge: r.autoMerge,\r\n folderSync: rt.folderSync,\r\n capacity: {\r\n developers: this.state.agents.filter((a) => a.repoId === r.id && a.role === 'dev').length,\r\n developersFree: this.available(r, 'dev').length,\r\n issuesReadyToStart: this.readyIssues(r).length,\r\n issuesWaitingOnOthers: rt.issues.filter((i) => blockers(i.body, open).length > 0).length,\r\n longestDependencyChain: Math.max(0, ...[...holdUps(rt.issues).values()].map((w) => w.chain)),\r\n },\r\n team: this.state.agents\r\n .filter((a) => a.repoId === r.id)\r\n .map((a) => ({\r\n id: a.id,\r\n name: a.name,\r\n role: a.role,\r\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\r\n specialty: a.specialty || null,\r\n status: a.status,\r\n doing: doing(a),\r\n hiredBy: a.hiredBy,\r\n jobDescription: a.brief ? jobDescription(a.brief) : null,\r\n })),\r\n backlog: rt.issues.map((i) => ({\r\n number: i.number,\r\n title: i.title,\r\n specialty: issueSpecialty(i.labels) || null,\r\n waitsFor: blockers(i.body, open),\r\n inProgress: this.issueTaken(r, i.number),\r\n })),\r\n pullRequests: rt.pulls\r\n .filter((p) => p.state === 'OPEN')\r\n .map((p) => {\r\n const q = this.state.qa.find((x) => x.repoId === r.id && x.prNumber === p.number);\r\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 };\r\n }),\r\n mergedRecently: rt.pulls.filter((p) => p.state === 'MERGED').map((p) => `#${p.number} ${p.title}`),\r\n };\r\n });\r\n const req = (r: HireRequestView) => ({\r\n id: r.id,\r\n kind: r.kind,\r\n floor: this.state.repos.find((x) => x.id === r.repoId)?.floor ?? null,\r\n role: r.role,\r\n name: r.name,\r\n title: r.title,\r\n specialty: r.specialty || null,\r\n reason: r.reason,\r\n status: r.status,\r\n managerNote: r.note || null,\r\n });\r\n return JSON.stringify(\r\n {\r\n company: {\r\n ceo: this.ceo().name,\r\n hiring: s.hiring === 'auto' ? `auto-approved while a floor has fewer than ${s.teamCap} people` : 'the manager approves every proposal',\r\n teamCap: s.teamCap,\r\n sessionLimit: s.sessionLimit || 'none',\r\n sessionsRunning: this.running(),\r\n usage: usageLabel(this.usageNow(), Date.now()),\r\n deskLimits: { dev: MAX_DESKS.dev, qa: MAX_DESKS.qa },\r\n },\r\n floors,\r\n pendingProposals: this.state.requests.filter((r) => r.status === 'pending').map(req),\r\n recentDecisions: this.state.requests.filter((r) => r.status !== 'pending').slice(-10).map(req),\r\n },\r\n null,\r\n 1,\r\n );\r\n }\r\n\r\n private agentDetail(x: { agent_id: string }) {\r\n const a = this.agentByRef(x.agent_id);\r\n const repo = this.state.repos.find((r) => r.id === a.repoId);\r\n const ceo = a.role === 'ceo';\r\n return JSON.stringify(\r\n {\r\n id: a.id,\r\n name: a.name,\r\n floor: repo?.floor ?? null,\r\n role: a.role,\r\n title: a.title || (a.role === 'qa' ? 'QA tester' : a.role === 'dev' ? 'Developer' : 'CEO'),\r\n specialty: a.specialty || null,\r\n status: a.status,\r\n doing: this.agentDoing(a),\r\n issue: a.issueNumber ? { number: a.issueNumber, title: a.issueTitle } : null,\r\n pullRequest: a.prNumber ? { number: a.prNumber, url: a.prUrl } : null,\r\n codingAgent: ceo ? 'claude' : a.cli || this.state.settings.defaultCli,\r\n model: ceo ? a.model || CEO_MODEL : this.modelFor(a, a.cli || this.state.settings.defaultCli) || 'the coding agent default',\r\n effort: a.effort || (ceo ? CEO_EFFORT : this.state.settings.defaultEffort),\r\n hiredBy: a.hiredBy,\r\n jobDescription: a.brief || null,\r\n },\r\n null,\r\n 1,\r\n );\r\n }\r\n\r\n private setFloorProfile(x: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }) {\r\n const r = this.floorRepo(x.floor);\r\n const preview = parsePreviewPatch(x.preview_command, x.preview_env);\r\n if (x.summary !== undefined) r.summary = String(x.summary).trim().slice(0, 140);\r\n if (x.qa_brief !== undefined) r.qaBrief = String(x.qa_brief).trim().slice(0, 2500);\r\n r.preview = { ...r.preview, ...preview };\r\n if (preview.command === null) void this.previews.refreshDefault(r);\r\n this.emitRepo(r);\r\n this.save();\r\n return `Saved floor ${r.floor}'s profile.`;\r\n }\r\n\r\n private updateJob(x: { agent_id: string; title?: string; specialty?: string; job_description?: string }) {\r\n const a = this.agentByRef(x.agent_id);\r\n if (a.role === 'ceo') throw new Error(\"That's you.\");\r\n this.updateAgent(a.id, { title: x.title, specialty: x.specialty, brief: x.job_description });\r\n const title = a.title || (a.role === 'qa' ? 'QA tester' : 'Developer');\r\n this.appendLog(a, [{ kind: 'system', text: `\uD83E\uDEAA ${this.ceo().name} updated ${a.name}'s job: ${title}${a.specialty ? ` \u00B7 swarm:${a.specialty}` : ''}` }]);\r\n return `Updated ${a.name}: ${title}${a.specialty ? ` (specialty ${a.specialty})` : ''}.`;\r\n }\r\n\r\n private proposeHire(x: { floor: number; role: 'dev' | 'qa'; title: string; specialty: string; job_description: string; reason: string; model?: string; effort?: string }) {\r\n const repo = this.floorRepo(x.floor);\r\n const role = x.role === 'qa' ? 'qa' : 'dev';\r\n const title = String(x.title ?? '').trim().slice(0, 60);\r\n if (!title) throw new Error('A hire needs a job title.');\r\n const specialty = specialtySlug(x.specialty);\r\n const pending = this.state.requests.filter((r) => r.status === 'pending');\r\n if (pending.length >= MAX_PENDING_REQUESTS) throw new Error(`${pending.length} proposals are already waiting for the manager. Wait for their decisions first.`);\r\n const dup = pending.find((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role && r.specialty === specialty);\r\n if (dup) throw new Error(`${dup.name} (${dup.title}) is already proposed for floor ${repo.floor} with that specialty.`);\r\n const seated = this.state.agents.filter((a) => a.repoId === repo.id && a.role === role).length;\r\n const waiting = pending.filter((r) => r.kind === 'hire' && r.repoId === repo.id && r.role === role).length;\r\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.`);\r\n const name = this.freeName(role);\r\n const req: HireRequestView = {\r\n id: crypto.randomUUID(),\r\n kind: 'hire',\r\n repoId: repo.id,\r\n role,\r\n agentId: null,\r\n name,\r\n title,\r\n specialty,\r\n brief: String(x.job_description ?? '').trim().slice(0, 2500),\r\n reason: String(x.reason ?? '').trim().slice(0, 600),\r\n model: String(x.model ?? '').trim(),\r\n effort: EFFORTS.includes(x.effort as EffortLevel) ? (x.effort as EffortLevel) : '',\r\n look: lookFor(name),\r\n color: pick(SHIRTS),\r\n hair: pick(HAIR),\r\n skin: pick(SKIN),\r\n status: 'pending',\r\n note: '',\r\n createdAt: Date.now(),\r\n decidedAt: null,\r\n decidedBy: null,\r\n };\r\n this.addRequest(req);\r\n const s = this.state.settings;\r\n if (s.hiring === 'auto' && this.state.agents.filter((a) => a.repoId === repo.id).length < s.teamCap) {\r\n this.approveRequest(req.id, {}, 'auto');\r\n return `Hired ${req.name} as ${title} on floor ${repo.floor} (auto-approved; agent id ${req.agentId}).`;\r\n }\r\n this.postMessage('ceo', `\uD83D\uDCC4 New candidate for floor ${repo.floor}: ${name}, ${title}. ${req.reason}`, req.id);\r\n return `Proposed ${name} as ${title} on floor ${repo.floor}. The manager will approve or decline (request ${req.id}).`;\r\n }\r\n\r\n private proposeLetGo(x: { agent_id: string; reason: string }) {\r\n const a = this.agentByRef(x.agent_id);\r\n if (a.role === 'ceo') throw new Error(\"You can't let yourself go.\");\r\n const repo = this.repo(a.repoId);\r\n if (a.role === 'qa' && this.state.agents.filter((y) => y.repoId === repo.id && y.role === 'qa').length <= 1) {\r\n throw new Error(`${a.name} is floor ${repo.floor}'s only QA tester, and every floor keeps one.`);\r\n }\r\n const pending = this.state.requests.filter((r) => r.status === 'pending');\r\n if (pending.some((r) => r.kind === 'let-go' && r.agentId === a.id)) throw new Error(`Letting ${a.name} go is already proposed.`);\r\n if (pending.length >= MAX_PENDING_REQUESTS) throw new Error(`${pending.length} proposals are already waiting for the manager. Wait for their decisions first.`);\r\n const req: HireRequestView = {\r\n id: crypto.randomUUID(),\r\n kind: 'let-go',\r\n repoId: repo.id,\r\n role: a.role,\r\n agentId: a.id,\r\n name: a.name,\r\n title: a.title || (a.role === 'qa' ? 'QA tester' : 'Developer'),\r\n specialty: a.specialty,\r\n brief: a.brief,\r\n reason: String(x.reason ?? '').trim().slice(0, 600),\r\n model: a.model,\r\n effort: a.effort,\r\n look: a.look,\r\n color: a.color,\r\n hair: a.hair,\r\n skin: a.skin,\r\n status: 'pending',\r\n note: '',\r\n createdAt: Date.now(),\r\n decidedAt: null,\r\n decidedBy: null,\r\n };\r\n this.addRequest(req);\r\n if (this.state.settings.hiring === 'auto' && FREE.includes(a.status)) {\r\n this.approveRequest(req.id, {}, 'auto');\r\n return `Let ${a.name} go (auto-approved).`;\r\n }\r\n this.postMessage('ceo', `\uD83D\uDC4B I suggest letting ${a.name} (${req.title}, floor ${repo.floor}) go. ${req.reason}`, req.id);\r\n return `Proposed letting ${a.name} go. The manager will decide (request ${req.id}).`;\r\n }\r\n\r\n private async fileIssue(x: { floor: number; title: string; body: string; specialty?: string }) {\r\n const repo = this.floorRepo(x.floor);\r\n this.ceoIssues.check();\r\n const title = String(x.title ?? '').trim().slice(0, 120);\r\n if (!title) throw new Error('An issue needs a title.');\r\n const slug = specialtySlug(x.specialty);\r\n const body = `${String(x.body ?? '').trim()}\\n\\n---\\n_Filed by ${this.ceo().name}, the cubefarm CEO._`;\r\n const n = await this.backend.createIssue(repo.fullName, title, body, slug ? [specialtyLabel(slug)] : []);\r\n this.ceoIssues.record(repo.id);\r\n return `Filed #${n} on floor ${repo.floor}: ${title}${slug ? ` (routed to ${slug})` : ''}.`;\r\n }\r\n\r\n /** Change an open issue's specialty and/or dependencies (see planRoute for what is refused). */\r\n private async routeIssue(x: { floor: number; number: number; specialty?: string; depends_on?: number[] }) {\r\n const repo = this.floorRepo(x.floor);\r\n const issues = this.repoRt.get(repo.id)?.issues ?? [];\r\n const asked = [Number(x.number), ...(x.depends_on ?? []).map(Number)].filter((n) => !issues.some((i) => i.number === n));\r\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)));\r\n const specialties = [\r\n ...this.state.agents.filter((a) => a.repoId === repo.id && a.specialty).map((a) => a.specialty.toLowerCase()),\r\n ...this.state.requests.filter((r) => r.status === 'pending' && r.kind === 'hire' && r.repoId === repo.id && r.specialty).map((r) => r.specialty),\r\n ];\r\n const plan = planRoute({\r\n floor: repo.floor,\r\n number: Number(x.number),\r\n specialty: x.specialty,\r\n dependsOn: x.depends_on,\r\n issues,\r\n closed: (n) => states.get(n) === 'CLOSED',\r\n inProgress: this.issueTaken(repo, Number(x.number)),\r\n specialties,\r\n });\r\n if (plan.body !== null || plan.addLabels.length || plan.removeLabels.length) {\r\n await this.backend.editIssue(repo.fullName, Number(x.number), { body: plan.body ?? undefined, addLabels: plan.addLabels, removeLabels: plan.removeLabels });\r\n await this.syncRepo(repo.id); // the scheduler sees the new routing right away\r\n }\r\n return plan.summary;\r\n }\r\n}\r\n", "import { createSdkMcpServer, tool, type McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';\r\nimport { z } from 'zod';\r\nimport { blockers, holdUps, setDependsOn } from '../shared/issues.ts';\r\nimport type { CeoJobKind } from '../shared/types.ts';\r\n\r\n// The CEO: a Claude Code session in the lobby that runs the company instead of writing code.\r\n// It studies each floor's repo, shapes the team (hire / let-go proposals the manager approves),\r\n// plans work as GitHub issues, and writes each floor's QA brief. Everything it changes goes\r\n// through the office tools below, so the swarm stays the single source of truth.\r\n\r\nexport interface CeoJob {\r\n kind: CeoJobKind;\r\n repoId?: string; // onboard / plan\r\n text?: string; // chat: the manager's message(s)\r\n at: number;\r\n}\r\n\r\n/** What the CEO's tools do. Implemented by the swarm; errors are returned to the CEO as tool errors. */\r\nexport interface OfficeHandlers {\r\n companyStatus(): string;\r\n agentDetail(a: { agent_id: string }): string;\r\n setFloorProfile(a: { floor: number; summary?: string; qa_brief?: string; preview_command?: string; preview_env?: Record<string, string> }): string;\r\n updateJob(a: { agent_id: string; title?: string; specialty?: string; job_description?: string }): string;\r\n proposeHire(a: {\r\n floor: number;\r\n role: 'dev' | 'qa';\r\n title: string;\r\n specialty: string;\r\n job_description: string;\r\n reason: string;\r\n model?: string;\r\n effort?: string;\r\n }): string;\r\n proposeLetGo(a: { agent_id: string; reason: string }): string;\r\n fileIssue(a: { floor: number; title: string; body: string; specialty?: string }): Promise<string>;\r\n routeIssue(a: { floor: number; number: number; specialty?: string; depends_on?: number[] }): Promise<string>;\r\n}\r\n\r\nexport interface OfficeTools {\r\n server: McpSdkServerConfigWithInstance;\r\n /** A fresh MCP server with the same tools, for one request from a CEO running in a terminal (served over HTTP). */\r\n serve(): McpSdkServerConfigWithInstance['instance'];\r\n /** Run a tool without a model in the loop (the demo CEO). */\r\n call(name: string, args: Record<string, unknown>): Promise<string>;\r\n}\r\n\r\nconst EFFORT = z.enum(['low', 'medium', 'high', 'xhigh', 'max']);\r\n\r\nexport function createOfficeTools(h: OfficeHandlers): OfficeTools {\r\n const run = async (fn: () => string | Promise<string>) => {\r\n try {\r\n return { content: [{ type: 'text' as const, text: await fn() }] };\r\n } catch (err) {\r\n return { content: [{ type: 'text' as const, text: `Refused: ${(err as Error).message}` }], isError: true };\r\n }\r\n };\r\n const defs = [\r\n tool(\r\n 'company_status',\r\n 'Everything about the company right now: settings, every floor (repo, clone path, brief, profile, QA brief), its team, backlog, pull requests and QA, pending proposals and recent decisions by the manager. Call this first.',\r\n {},\r\n () => run(() => h.companyStatus()),\r\n ),\r\n tool(\r\n 'agent_detail',\r\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.\",\r\n { agent_id: z.string().describe('An id (or name) from company_status') },\r\n (a) => run(() => h.agentDetail(a)),\r\n ),\r\n tool(\r\n 'set_floor_profile',\r\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.\",\r\n {\r\n floor: z.number().int().describe('Floor number'),\r\n summary: z.string().max(140).optional().describe('e.g. \"3D browser game \u00B7 Three.js + Vite + TypeScript\"'),\r\n qa_brief: z.string().max(2500).optional().describe('What QA must check on every PR for this project, as short bullet points'),\r\n preview_command: z\r\n .string()\r\n .max(2000)\r\n .optional()\r\n .describe(\r\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.',\r\n ),\r\n // Not z.record(): the SDK can't turn it into JSON Schema, and one bad tool empties the whole tools/list.\r\n preview_env: z\r\n .object({})\r\n .catchall(z.string())\r\n .optional()\r\n .describe('Extra environment variables for the preview; {port} and {tmp} are replaced in the values. Replaces the whole set.'),\r\n },\r\n (a) => run(() => h.setFloorProfile(a)),\r\n ),\r\n tool(\r\n 'update_job',\r\n \"Change an existing agent's job title, specialty or job description so it fits the project. Takes effect from their next task.\",\r\n {\r\n agent_id: z.string(),\r\n title: z.string().max(60).optional(),\r\n specialty: z.string().max(24).optional().describe('Short lowercase slug, e.g. \"graphics\"; \"\" for a generalist'),\r\n job_description: z.string().max(2500).optional(),\r\n },\r\n (a) => run(() => h.updateJob(a)),\r\n ),\r\n tool(\r\n 'propose_hire',\r\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).',\r\n {\r\n floor: z.number().int(),\r\n role: z.enum(['dev', 'qa']).describe('dev = builds issues into pull requests; qa = tests pull requests'),\r\n title: z.string().max(60).describe('Specific job title, e.g. \"Three.js graphics engineer\"'),\r\n specialty: z.string().max(24).describe('Short lowercase slug used to label issues swarm:<specialty>, e.g. \"graphics\"'),\r\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.'),\r\n reason: z.string().max(600).describe('Why the floor needs them now. The manager reads this.'),\r\n model: z.string().optional().describe('Leave out to use the default model'),\r\n effort: EFFORT.optional().describe('Leave out to use the default effort'),\r\n },\r\n (a) => run(() => h.proposeHire(a)),\r\n ),\r\n tool(\r\n 'propose_let_go',\r\n 'Propose letting an agent go (overstaffed floor, specialty no longer needed). The manager decides.',\r\n { agent_id: z.string(), reason: z.string().max(600) },\r\n (a) => run(() => h.proposeLetGo(a)),\r\n ),\r\n tool(\r\n 'file_issue',\r\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.',\r\n {\r\n floor: z.number().int(),\r\n title: z.string().max(120),\r\n body: z.string().max(6000).describe('Context, what to build, acceptance criteria'),\r\n specialty: z.string().max(24).optional(),\r\n },\r\n (a) => run(() => h.fileIssue(a)),\r\n ),\r\n tool(\r\n 'route_issue',\r\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.',\r\n {\r\n floor: z.number().int(),\r\n number: z.number().int().positive().describe('The issue number'),\r\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.'),\r\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.'),\r\n },\r\n (a) => run(() => h.routeIssue(a)),\r\n ),\r\n ];\r\n const server = createSdkMcpServer({ name: 'office', version: '1.0.0', tools: defs });\r\n return {\r\n server,\r\n serve: () => createSdkMcpServer({ name: 'office', version: '1.0.0', tools: defs }).instance,\r\n async call(name, args) {\r\n const def = defs.find((d) => d.name === name);\r\n if (!def) throw new Error(`No office tool ${name}`);\r\n const res = (await def.handler(args as never, undefined)) as { content: { text?: string }[] };\r\n return res.content.map((c) => c.text ?? '').join('\\n');\r\n },\r\n };\r\n}\r\n\r\n// ---------- prompts ----------\r\n\r\nexport function ceoSystemPrompt(o: {\r\n name: string;\r\n company: string;\r\n manager: string;\r\n notesFile: string;\r\n sessionLimit: number;\r\n teamCap: number;\r\n hiring: 'approve' | 'auto';\r\n}) {\r\n const manager = o.manager ? `the manager, ${o.manager}` : 'the human manager';\r\n return [\r\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.`,\r\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.`,\r\n '',\r\n 'Your job is to run the company, not to write code:',\r\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.',\r\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. Propose letting people go when a floor is clearly overstaffed or a specialty is no longer needed.`,\r\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.\",\r\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).\",\r\n '',\r\n 'How you work:',\r\n '- Call mcp__office__company_status first. It lists every floor, its clone path, team, backlog, pull requests and your pending proposals.',\r\n '- Read the repositories through their clone paths with Read, Glob and Grep. They are read-only to you. You cannot run shell commands.',\r\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.`,\r\n '- Change things only through the mcp__office__ tools.',\r\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.\",\r\n '',\r\n 'Rules:',\r\n '- Every floor keeps at least one QA tester.',\r\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.',\r\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.',\r\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.'}`,\r\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.',\r\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.\",\r\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.',\r\n ].join('\\n');\r\n}\r\n\r\nexport function ceoJobPrompt(job: CeoJob, floor: { floor: number; fullName: string; clone: string; mission: string; backlog: number } | null): string {\r\n switch (job.kind) {\r\n case 'onboard':\r\n if (!floor) return 'A floor was added but has since been removed. Reply \"Nothing to do.\"';\r\n return [\r\n `Floor ${floor.floor} (${floor.fullName}) just joined the company. Its read-only clone is at ${floor.clone}.`,\r\n 'Study it: README, package manifest, source layout, tests, and how far along it is. Then:',\r\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.\",\r\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).',\r\n '3. Propose the hires this project needs. Usually two to four developers with distinct specialties is plenty.',\r\n floor.mission\r\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.`}`\r\n : floor.backlog === 0\r\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.'\r\n : `4. There are ${floor.backlog} open issues. Label nothing retroactively; just make sure the team can cover them.`,\r\n ].join('\\n');\r\n case 'plan':\r\n if (!floor) return 'A floor you were asked to plan has been removed. Reply \"Nothing to do.\"';\r\n return [\r\n `The manager has a brief for floor ${floor.floor} (${floor.fullName}, clone at ${floor.clone}):`,\r\n `\"\"\"${floor.mission}\"\"\"`,\r\n '',\r\n 'Plan the next milestone toward it:',\r\n `- Read the current code and the ${floor.backlog} open issues first, so you build on what exists and do not duplicate anything.`,\r\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.',\r\n '- File the issues, each routed to a specialty.',\r\n '- Make sure the floor has the specialists those issues need; propose hires if not.',\r\n '- Update the floor profile and QA brief if the brief changes what the project is.',\r\n ].join('\\n');\r\n case 'review':\r\n return [\r\n 'Periodic review of the company. For every floor, look at:',\r\n '- floors without a profile or QA brief: study them and write one',\r\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)',\r\n '- pull requests stuck in QA or marked as needing a human',\r\n '- floors with a brief and an empty backlog: plan the next milestone',\r\n 'Propose hires or let-gos only when clearly justified. If nothing needs doing, reply with one short sentence saying so.',\r\n ].join('\\n');\r\n case 'chat':\r\n return `Message from the manager (they're reading your reply on their phone):\\n${job.text ?? ''}`;\r\n }\r\n}\r\n\r\nexport function jobLabel(job: CeoJob, floor: { floor: number; fullName: string } | null) {\r\n const where = floor ? `floor ${floor.floor} \u00B7 ${floor.fullName.split('/')[1] ?? floor.fullName}` : 'a removed floor';\r\n switch (job.kind) {\r\n case 'onboard':\r\n return `Onboarding ${where}`;\r\n case 'plan':\r\n return `Planning ${where}`;\r\n case 'review':\r\n return 'Reviewing the company';\r\n case 'chat':\r\n return 'Replying to you';\r\n }\r\n}\r\n\r\n// ---------- issues ----------\r\n\r\n/**\r\n * The CEO's issue cap: at most `max` issues per request from the manager. A manager message that arrives while the\r\n * job runs is a new request, so it resets the count.\r\n */\r\nexport class IssueCap {\r\n filed = 0; // since the job started or the manager's last message\r\n total = 0; // in the whole job\r\n readonly repos = new Set<string>(); // floors that got issues, to refresh when the job ends\r\n constructor(readonly max: number) {}\r\n\r\n check() {\r\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.`);\r\n }\r\n\r\n record(repoId: string) {\r\n this.filed++;\r\n this.total++;\r\n this.repos.add(repoId);\r\n }\r\n\r\n managerMessage() {\r\n this.filed = 0;\r\n }\r\n}\r\n\r\nexport interface RouteRequest {\r\n floor: number;\r\n number: number;\r\n specialty?: string; // '' = no specialty\r\n dependsOn?: number[]; // [] = no dependencies\r\n issues: { number: number; body: string; labels: string[] }[]; // the floor's open issues\r\n closed: (n: number) => boolean; // for numbers that aren't open: closed, rather than unknown\r\n inProgress: boolean;\r\n specialties: string[]; // held by someone on the floor or by a pending hire proposal for it\r\n}\r\n\r\nexport interface RoutePlan {\r\n addLabels: string[];\r\n removeLabels: string[];\r\n body: string | null; // null: leave the body alone\r\n summary: string;\r\n}\r\n\r\n/** Longest chain of open issues this one waits for, one step per \"Depends on\". */\r\nfunction waitsDepth(n: number, deps: Map<number, number[]>, seen = new Set<number>()): number {\r\n if (seen.has(n)) return 0;\r\n seen.add(n);\r\n const depth = Math.max(0, ...(deps.get(n) ?? []).map((d) => waitsDepth(d, deps, seen) + 1));\r\n seen.delete(n);\r\n return depth;\r\n}\r\n\r\n/**\r\n * What route_issue changes, or why it refuses: a closed or unknown issue, a specialty nobody on the floor has,\r\n * dependencies on an issue in progress, a dependency on itself, on a closed or unknown issue, a cycle, or a chain\r\n * deeper than two steps.\r\n */\r\nexport function planRoute(r: RouteRequest): RoutePlan {\r\n const issue = r.issues.find((i) => i.number === r.number);\r\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}.`);\r\n if (r.specialty === undefined && r.dependsOn === undefined) throw new Error('Nothing to change: pass specialty, depends_on or both.');\r\n const plan: RoutePlan = { addLabels: [], removeLabels: [], body: null, summary: '' };\r\n const done: string[] = [];\r\n\r\n if (r.specialty !== undefined) {\r\n const slug = specialtySlug(r.specialty);\r\n if (r.specialty.trim() && !slug) throw new Error(`\"${r.specialty}\" is not a specialty. Use a short lowercase slug, or \"\" for none.`);\r\n if (slug && !r.specialties.includes(slug)) {\r\n const have = [...new Set(r.specialties)].join(', ') || 'none';\r\n throw new Error(`Nobody on floor ${r.floor} has the specialty \"${slug}\", and no pending proposal does. Specialties there: ${have}.`);\r\n }\r\n const label = slug ? specialtyLabel(slug) : null;\r\n plan.removeLabels = issue.labels.filter((l) => /^swarm:/i.test(l) && !/^swarm:skip$/i.test(l) && l !== label);\r\n if (label && !issue.labels.includes(label)) plan.addLabels = [label];\r\n done.push(slug ? `routed to ${slug}` : 'no specialty');\r\n }\r\n\r\n if (r.dependsOn !== undefined) {\r\n if (r.inProgress) throw new Error(`#${r.number} is already in progress, so its dependencies can't change. Changing its specialty is fine.`);\r\n const deps = [...new Set(r.dependsOn.map(Number))];\r\n const open = new Set(r.issues.map((i) => i.number));\r\n for (const d of deps) {\r\n if (d === r.number) throw new Error(`#${r.number} can't depend on itself.`);\r\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}.`);\r\n }\r\n const body = setDependsOn(issue.body, deps);\r\n const after = r.issues.map((i) => (i.number === r.number ? { ...i, body } : i));\r\n const waits = new Map(after.map((i) => [i.number, blockers(i.body, open)]));\r\n const loop = deps.find((d) => reaches(d, r.number, waits));\r\n if (loop !== undefined) throw new Error(`#${loop} already waits for #${r.number}, directly or through other issues, so that would be a cycle.`);\r\n const depth = waitsDepth(r.number, waits) + (holdUps(after).get(r.number)?.chain ?? 0);\r\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.`);\r\n if (body !== issue.body) plan.body = body;\r\n done.push(deps.length ? `depends on ${deps.map((d) => `#${d}`).join(', ')}` : 'no dependencies');\r\n }\r\n\r\n plan.summary = `#${r.number} on floor ${r.floor}: ${done.join(', ')}.`;\r\n return plan;\r\n}\r\n\r\n/** Does `from` wait for `to`, directly or through other issues? */\r\nfunction reaches(from: number, to: number, waits: Map<number, number[]>, seen = new Set<number>()): boolean {\r\n if (from === to) return true;\r\n if (seen.has(from)) return false;\r\n seen.add(from);\r\n return (waits.get(from) ?? []).some((n) => reaches(n, to, waits, seen));\r\n}\r\n\r\n/** Short lowercase slug for a specialty (\"Three.js graphics\" -> \"three-js-graphics\"). */\r\nexport function specialtySlug(s: string | undefined) {\r\n const slug = String(s ?? '')\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, '-')\r\n .replace(/^-|-$/g, '')\r\n .slice(0, 24);\r\n return slug === 'skip' ? '' : slug;\r\n}\r\n\r\nexport const specialtyLabel = (slug: string) => `swarm:${slug}`;\r\n", "// Issue conventions shared by the server's scheduler and the client's whiteboard.\r\n\r\n/** The specialty an issue is routed to, from its swarm:<specialty> label ('' = anyone). */\r\nexport function issueSpecialty(labels: string[]) {\r\n const l = labels.find((x) => /^swarm:/i.test(x) && !/^swarm:skip$/i.test(x));\r\n return l ? l.slice(6).toLowerCase() : '';\r\n}\r\n\r\n/** Open issues this issue waits for, from \"Depends on #3\" / \"Blocked by #4, #5\" in its body. */\r\nexport function blockers(body: string, open: Set<number>) {\r\n const out = new Set<number>();\r\n for (const m of (body ?? '').matchAll(/\\b(?:depends\\s+on|blocked\\s+by)\\s*:?\\s*((?:#\\d+(?:\\s*(?:,|and|&)\\s*)?)+)/gi)) {\r\n for (const n of m[1].matchAll(/#(\\d+)/g)) if (open.has(Number(n[1]))) out.add(Number(n[1]));\r\n }\r\n return [...out];\r\n}\r\n\r\nconst DEPENDENCY = /\\b(?:depends\\s+on|blocked\\s+by)\\s*:?\\s*(?:#\\d+(?:\\s*(?:,|and|&)\\s*)?)+/gi;\r\nconst STATEMENT = new RegExp(`\\\\s*${DEPENDENCY.source}[.;,]?`, 'gi'); // with the space before it and a full stop after\r\n\r\n/**\r\n * An issue body with its \"Depends on #N\" / \"Blocked by #N\" statements replaced by one \"Depends on #a, #b\" line at the\r\n * top ([] removes them). A line that only said that goes; the rest of the body is left alone.\r\n */\r\nexport function setDependsOn(body: string, deps: number[]) {\r\n const lines: string[] = [];\r\n let dropped = false;\r\n for (const line of (body ?? '').split(/\\r?\\n/)) {\r\n const rest = line.match(DEPENDENCY) ? line.replace(STATEMENT, '').trimEnd() : line;\r\n if (rest !== line && !/[\\p{L}\\p{N}]/u.test(rest)) {\r\n dropped = true;\r\n continue;\r\n }\r\n // A dropped line between two paragraphs doesn't leave a double gap.\r\n if (dropped && !rest.trim() && !lines[lines.length - 1]?.trim()) continue;\r\n dropped = false;\r\n lines.push(rest);\r\n }\r\n while (lines.length && !lines[0].trim()) lines.shift();\r\n const rest = lines.join('\\n');\r\n if (deps.length === 0) return rest;\r\n return `Depends on ${deps.map((n) => `#${n}`).join(', ')}${rest ? `\\n\\n${rest}` : ''}`;\r\n}\r\n\r\n/**\r\n * How much of the backlog each open issue holds up: the longest chain of open issues waiting on it (`chain`) and how\r\n * many wait on it directly or indirectly (`waiting`). Starting the issues with the most behind them first lets the\r\n * most work run in parallel later.\r\n */\r\nexport function holdUps(issues: { number: number; body: string }[]) {\r\n const open = new Set(issues.map((i) => i.number));\r\n const waiters = new Map<number, number[]>();\r\n for (const i of issues) for (const b of blockers(i.body, open)) waiters.set(b, [...(waiters.get(b) ?? []), i.number]);\r\n const chains = new Map<number, number>();\r\n const visiting = new Set<number>();\r\n const chain = (n: number): number => {\r\n const known = chains.get(n);\r\n if (known !== undefined) return known;\r\n if (visiting.has(n)) return 0; // a dependency cycle\r\n visiting.add(n);\r\n const longest = Math.max(0, ...(waiters.get(n) ?? []).map((w) => chain(w) + 1));\r\n visiting.delete(n);\r\n chains.set(n, longest);\r\n return longest;\r\n };\r\n const out = new Map<number, { chain: number; waiting: number }>();\r\n for (const i of issues) {\r\n const seen = new Set<number>();\r\n const stack = [...(waiters.get(i.number) ?? [])];\r\n while (stack.length) {\r\n const n = stack.pop()!;\r\n if (n === i.number || seen.has(n)) continue;\r\n seen.add(n);\r\n stack.push(...(waiters.get(n) ?? []));\r\n }\r\n out.set(i.number, { chain: chain(i.number), waiting: seen.size });\r\n }\r\n return out;\r\n}\r\n", "/** An error the REST layer turns into this status with a JSON { error } body. */\r\nexport class HttpError extends Error {\r\n constructor(\r\n public status: number,\r\n message: string,\r\n ) {\r\n super(message);\r\n }\r\n}\r\n", "import type { PullInfo } from '../shared/types.ts';\r\n\r\n// Auto-merge: fixes for failing checks or conflicts before a PR needs the manager, how long checks may run before\r\n// the manager hears about it, and how long to wait before retrying a merge GitHub refused.\r\nexport const MAX_MERGE_FIXES = 3;\r\nexport const CHECKS_ALERT_MS = 30 * 60_000;\r\nexport const MERGE_RETRY_MS = 10 * 60_000;\r\n\r\n/** The parts of a QA record the merge gate reads. */\r\nexport interface MergeRecord {\r\n passedSha: string | null;\r\n mergeFixes: number;\r\n pendingSince: number | null;\r\n mergeRetryAt: number | null;\r\n alerted: boolean;\r\n}\r\n\r\n/** Bookkeeping the caller writes onto the record as it is (it doesn't count as a change to the record). */\r\nexport type MergeBookkeeping = Partial<Pick<MergeRecord, 'passedSha' | 'pendingSince' | 'alerted'>>;\r\n\r\nexport type MergePull = Pick<PullInfo, 'isDraft' | 'mergeable' | 'mergeState' | 'headSha' | 'checks' | 'failedChecks' | 'pendingChecks'>;\r\n\r\n/** What auto-merge does next with a QA-passed PR. */\r\nexport type MergeStep = { set: MergeBookkeeping } & (\r\n | { do: 'wait'; note?: string; alert?: boolean } // no note: leave the card as it is; alert: tell the manager checks are slow\r\n | { do: 'details' } // GitHub hasn't worked out mergeability: ask about the PR itself, then decide again with `detailed`\r\n | { do: 'requeue' } // commits arrived after QA's sign-off: QA tests them too\r\n | { do: 'send-back'; reason: 'checks' | 'conflict'; instructions: string; needsHuman: boolean } // needsHuman: the fix budget ran out\r\n | { do: 'update-branch' } // the repo only merges up-to-date branches\r\n | { do: 'merge' }\r\n);\r\n\r\n/**\r\n * Decide the next step toward merging a PR QA has passed. Pure: advanceMerge (swarm.ts) does the talking to GitHub\r\n * and the office. `detailed` means the PR's mergeability has already been asked for, so UNKNOWN is waited out.\r\n */\r\nexport function mergeStep(pr: MergePull, rec: MergeRecord, now: number, opts: { base: string; detailed?: boolean }): MergeStep {\r\n if (pr.isDraft) return { do: 'wait', note: 'a draft: waiting', set: {} };\r\n if (!opts.detailed && (pr.mergeable === 'UNKNOWN' || pr.mergeState === 'UNKNOWN')) return { do: 'details', set: {} };\r\n const set: MergeBookkeeping = {};\r\n if (rec.passedSha == null) set.passedSha = pr.headSha; // signed off before the office tracked commits\r\n if (pr.headSha !== (set.passedSha ?? rec.passedSha)) return { do: 'requeue', set };\r\n const needsHuman = rec.mergeFixes >= MAX_MERGE_FIXES;\r\n if (pr.mergeable === 'CONFLICTING' || pr.mergeState === 'DIRTY') {\r\n return { do: 'send-back', reason: 'conflict', instructions: `It conflicts with ${opts.base}.`, needsHuman, set };\r\n }\r\n if (pr.checks === 'failing') {\r\n const instructions = pr.failedChecks.map((c) => `- ${c.name}${c.url ? `: ${c.url}` : ''}`).join('\\n');\r\n return { do: 'send-back', reason: 'checks', instructions, needsHuman, set };\r\n }\r\n if (pr.checks === 'pending') {\r\n const since = rec.pendingSince ?? now;\r\n if (rec.pendingSince == null) set.pendingSince = since;\r\n const alert = now - since > CHECKS_ALERT_MS && !rec.alerted;\r\n if (alert) set.alerted = true;\r\n return { do: 'wait', note: `waiting for checks: ${pr.pendingChecks.join(', ') || 'running'}`, alert, set };\r\n }\r\n set.pendingSince = null;\r\n if (pr.mergeable === 'UNKNOWN') return { do: 'wait', note: 'GitHub is checking it can merge', set };\r\n if (pr.mergeState === 'BEHIND') return { do: 'update-branch', set };\r\n if (rec.mergeRetryAt && now < rec.mergeRetryAt) return { do: 'wait', set };\r\n return { do: 'merge', set };\r\n}\r\n", "import type { Backend } from './backend.ts';\r\nimport { PORT } from './config.ts';\r\nimport { HttpError } from './httpError.ts';\r\nimport { PREVIEW_SLUG, portOpen, type PreviewHandle } from './previewRunner.ts';\r\nimport type { PreviewConfig, PreviewStatus, PreviewView, PullInfo } from '../shared/types.ts';\r\n\r\n// One preview per floor: the floor's app, run from its own worktree on a port reserved for the floor.\r\n// Only the config is persisted; after a restart every preview reads 'stopped'.\r\n\r\n/** What the previews need to know about a floor. */\r\nexport interface PreviewFloor {\r\n id: string;\r\n fullName: string;\r\n defaultBranch: string;\r\n floor: number;\r\n preview: PreviewConfig;\r\n}\r\n\r\ninterface Run {\r\n status: PreviewStatus;\r\n port: number | null; // the port of the current or last run\r\n ref: string | null;\r\n pr: number | null;\r\n commit: string | null;\r\n startedAt: number | null;\r\n error: string | null;\r\n log: string[];\r\n handle: PreviewHandle | null;\r\n gen: number; // bumped by every start / stop; callbacks from older runs are ignored\r\n}\r\n\r\nconst PREVIEW_BASE_PORT = 6300;\r\nconst LOG_KEEP = 200;\r\nconst LOG_VIEW = 40;\r\nconst ACTIVE: PreviewStatus[] = ['preparing', 'installing', 'starting', 'running'];\r\n\r\n/** Never the office itself, the other office port, or the agents' range. */\r\nconst forbidden = (p: number) => p === PORT || p === 4317 || p === 5317 || (p >= 5200 && p <= 5899);\r\n\r\nexport const DEFAULT_PREVIEW: PreviewConfig = { command: null, env: {} };\r\n\r\n/** Check a previewCommand / previewEnv patch; throws 400 on bad input. undefined: not in the patch. */\r\nexport function parsePreviewPatch(command: unknown, env: unknown): Partial<PreviewConfig> {\r\n const out: Partial<PreviewConfig> = {};\r\n if (command !== undefined) {\r\n if (command !== null && typeof command !== 'string') throw new HttpError(400, 'previewCommand must be a string or null');\r\n const c = (command ?? '').trim();\r\n if (c.length > 2000) throw new HttpError(400, 'previewCommand is too long');\r\n out.command = c || null;\r\n }\r\n if (env !== undefined) {\r\n if (env === null) out.env = {};\r\n else {\r\n if (typeof env !== 'object' || Array.isArray(env)) throw new HttpError(400, 'previewEnv must be an object of string values');\r\n const entries = Object.entries(env as Record<string, unknown>);\r\n if (entries.length > 50) throw new HttpError(400, 'previewEnv has too many variables');\r\n for (const [k, v] of entries) {\r\n if (typeof v !== 'string') throw new HttpError(400, `previewEnv.${k} must be a string`);\r\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) throw new HttpError(400, `\"${k}\" is not a valid environment variable name`);\r\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`);\r\n if (v.length > 4000) throw new HttpError(400, `previewEnv.${k} is too long`);\r\n }\r\n out.env = Object.fromEntries(entries) as Record<string, string>;\r\n }\r\n }\r\n return out;\r\n}\r\n\r\nexport class Previews {\r\n private runs = new Map<string, Run>();\r\n private hasDefault = new Map<string, boolean>(); // floor id -> package.json in its checkout\r\n private emitTimers = new Map<string, NodeJS.Timeout>();\r\n\r\n constructor(\r\n private backend: Backend,\r\n private hooks: { emit(repoId: string): void; pulls(repoId: string): PullInfo[] },\r\n ) {}\r\n\r\n private run(id: string): Run {\r\n let r = this.runs.get(id);\r\n if (!r) {\r\n r = { status: 'stopped', port: null, ref: null, pr: null, commit: null, startedAt: null, error: null, log: [], handle: null, gen: 0 };\r\n this.runs.set(id, r);\r\n }\r\n return r;\r\n }\r\n\r\n /** The floor's reserved port: 6300 + floor, moved up by 100 while it clashes with the office or another preview. */\r\n portFor(f: PreviewFloor): number {\r\n const active = this.runs.get(f.id);\r\n if (active?.port && ACTIVE.includes(active.status)) return active.port;\r\n const taken = new Set([...this.runs.entries()].filter(([id, r]) => id !== f.id && r.port && ACTIVE.includes(r.status)).map(([, r]) => r.port!));\r\n let p = PREVIEW_BASE_PORT + f.floor;\r\n while (forbidden(p) || taken.has(p)) p += 100;\r\n return p;\r\n }\r\n\r\n view(f: PreviewFloor): PreviewView {\r\n const r = this.runs.get(f.id);\r\n let status: PreviewStatus = r?.status ?? 'stopped';\r\n if (status === 'stopped' && !f.preview.command && this.hasDefault.get(f.id) === false) status = 'unconfigured';\r\n const port = r?.port ?? this.portFor(f);\r\n return {\r\n status,\r\n port,\r\n url: status === 'running' ? `http://localhost:${port}/` : null,\r\n ref: r?.ref ?? null,\r\n pr: r?.pr ?? null,\r\n commit: r?.commit ?? null,\r\n startedAt: r?.startedAt ?? null,\r\n error: r?.error ?? null,\r\n logTail: (r?.log ?? []).slice(-LOG_VIEW),\r\n };\r\n }\r\n\r\n /** Re-check whether a floor without a command has a package.json to fall back on. */\r\n async refreshDefault(f: PreviewFloor) {\r\n const has = await this.backend.previews.hasDefault(f.fullName).catch(() => true);\r\n if (this.hasDefault.get(f.id) === has) return;\r\n this.hasDefault.set(f.id, has);\r\n this.hooks.emit(f.id);\r\n }\r\n\r\n /** Start the floor's preview on the default branch or an open PR, replacing whatever it is running now. */\r\n async start(f: PreviewFloor, title: string, pr?: number | null): Promise<PreviewView> {\r\n if (pr !== undefined && pr !== null && (!Number.isInteger(pr) || pr <= 0)) throw new HttpError(400, `Invalid pull request number: ${pr}`);\r\n if (pr) await this.checkOpen(f, pr);\r\n const r = this.run(f.id);\r\n const gen = ++r.gen;\r\n await this.halt(f, r);\r\n if (gen !== r.gen) return this.view(f); // another start or a stop came in meanwhile\r\n\r\n const port = this.portFor(f);\r\n const ref = pr ? `PR #${pr}` : f.defaultBranch;\r\n Object.assign(r, { port, ref, pr: pr ?? null, commit: null, startedAt: Date.now(), error: null, log: [] });\r\n if (await portOpen(port)) {\r\n if (gen !== r.gen) return this.view(f);\r\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.` });\r\n this.hooks.emit(f.id);\r\n throw new HttpError(409, r.error!);\r\n }\r\n if (gen !== r.gen) return this.view(f);\r\n r.status = 'preparing';\r\n this.hooks.emit(f.id);\r\n\r\n const live = () => gen === r.gen;\r\n r.handle = this.backend.previews.start(\r\n { fullName: f.fullName, defaultBranch: f.defaultBranch, pr: pr ?? null, port, command: f.preview.command, env: { ...f.preview.env }, title: `${title} \u00B7 ${ref}` },\r\n {\r\n status: (s) => {\r\n if (!live()) return;\r\n r.status = s;\r\n this.hooks.emit(f.id);\r\n },\r\n commit: (sha) => {\r\n if (!live()) return;\r\n r.commit = sha || null;\r\n this.hooks.emit(f.id);\r\n },\r\n log: (lines) => {\r\n if (!live()) return;\r\n r.log.push(...lines.map((l) => l.slice(0, 500)));\r\n if (r.log.length > LOG_KEEP) r.log.splice(0, r.log.length - LOG_KEEP);\r\n this.emitSoon(f.id);\r\n },\r\n failed: (message, unconfigured) => {\r\n if (!live()) return;\r\n r.handle = null;\r\n Object.assign(r, { status: unconfigured ? 'unconfigured' : 'error', error: message });\r\n if (unconfigured) this.hasDefault.set(f.id, false);\r\n this.hooks.emit(f.id);\r\n // Anything the app left behind in its worktree or on its port goes too.\r\n void this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, port).catch(() => undefined);\r\n },\r\n },\r\n );\r\n return this.view(f);\r\n }\r\n\r\n /** Stop the floor's preview and free its port. */\r\n async stop(f: PreviewFloor): Promise<PreviewView> {\r\n const r = this.run(f.id);\r\n r.gen++;\r\n await this.halt(f, r);\r\n Object.assign(r, { status: 'stopped', error: null, startedAt: null });\r\n this.hooks.emit(f.id);\r\n return this.view(f);\r\n }\r\n\r\n /** The floor is leaving the building: stop its preview and remove the preview worktree. */\r\n async remove(f: PreviewFloor) {\r\n const r = this.runs.get(f.id);\r\n if (r) {\r\n r.gen++;\r\n await this.halt(f, r);\r\n }\r\n this.runs.delete(f.id);\r\n this.hasDefault.delete(f.id);\r\n clearTimeout(this.emitTimers.get(f.id));\r\n await this.backend.removeDesk(f.fullName, PREVIEW_SLUG).catch(() => undefined);\r\n }\r\n\r\n /** Server shutdown: stop every running preview. */\r\n async stopAll(floors: PreviewFloor[]) {\r\n await Promise.all(\r\n floors.map((f) => {\r\n const r = this.runs.get(f.id);\r\n if (!r) return;\r\n r.gen++;\r\n return this.halt(f, r);\r\n }),\r\n );\r\n }\r\n\r\n /** Server start: nothing is running yet, so anything alive in a preview worktree or on a preview port is an orphan. */\r\n async clearOrphans(floors: PreviewFloor[]) {\r\n await Promise.all(floors.map((f) => this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, this.portFor(f)).catch(() => undefined)));\r\n }\r\n\r\n private async halt(f: PreviewFloor, r: Run) {\r\n const handle = r.handle;\r\n r.handle = null;\r\n if (!handle) return;\r\n await handle.stop().catch(() => undefined);\r\n if (!r.port) return;\r\n await this.backend.releaseDesk(f.fullName, PREVIEW_SLUG, r.port).catch(() => undefined);\r\n // Windows can take a moment to let go of a killed process's socket.\r\n for (let i = 0; i < 20 && (await portOpen(r.port)); i++) await new Promise((res) => setTimeout(res, 250));\r\n }\r\n\r\n private async checkOpen(f: PreviewFloor, pr: number) {\r\n const known = this.hooks.pulls(f.id).find((p) => p.number === pr);\r\n const state = known?.state ?? (await this.backend.prDetails(f.fullName, pr).then((d) => d.state).catch(() => null));\r\n if (!state) throw new HttpError(404, `${f.fullName} has no pull request #${pr}`);\r\n if (state !== 'OPEN') throw new HttpError(400, `Pull request #${pr} is ${state.toLowerCase()}, not open`);\r\n }\r\n\r\n /** Log lines arrive in bursts (npm install); send them at most once a second. */\r\n private emitSoon(id: string) {\r\n if (this.emitTimers.has(id)) return;\r\n this.emitTimers.set(\r\n id,\r\n setTimeout(() => {\r\n this.emitTimers.delete(id);\r\n if (this.runs.has(id)) this.hooks.emit(id);\r\n }, 1000),\r\n );\r\n }\r\n}\r\n", "import type { UsageView } from '../shared/types.ts';\r\n\r\n// Pacing new work on Claude's usage warnings (#40). Every agent shares one subscription. When Claude warns that\r\n// usage is getting high, the office slows down instead of running into the hard limit: finishing beats starting.\r\n// QA, QA fixes and CEO jobs start as normal; new issues only while fewer than settings.pacingSessions sessions run.\r\n\r\n/** How long pacing lasts when Claude doesn't say when the window resets. */\r\nexport const PACING_MS = 60 * 60_000;\r\nexport const DEFAULT_PACING_SESSIONS = 3;\r\n\r\n/** What a session is started for. Only new issues are held back while pacing. */\r\nexport type WorkKind = 'issue' | 'qa' | 'fix' | 'ceo';\r\n\r\nexport interface UsageClock {\r\n now: number;\r\n pausedUntil: number; // Claude rejected a session for the usage limit: nothing new starts before this\r\n pacingUntil: number; // Claude warned about usage: new issues are paced until this\r\n}\r\n\r\n/** May work of this kind start now? A rejection pauses everything; pacing caps new issues at `pacingSessions` running. */\r\nexport function mayStart(kind: WorkKind, c: UsageClock & { running: number; pacingSessions: number }): boolean {\r\n if (c.now < c.pausedUntil) return false;\r\n if (kind === 'issue' && c.now < c.pacingUntil) return c.running < c.pacingSessions;\r\n return true;\r\n}\r\n\r\n/** The usage state for the snapshot. */\r\nexport function usageView(c: UsageClock): UsageView {\r\n if (c.now < c.pausedUntil) return { state: 'paused', until: c.pausedUntil };\r\n if (c.now < c.pacingUntil) return { state: 'pacing', until: c.pacingUntil };\r\n return { state: 'normal', until: null };\r\n}\r\n\r\n/** \"14:30\", with the weekday when it isn't today. */\r\nexport function clock(at: number, now: number): string {\r\n const d = new Date(at);\r\n const hm = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;\r\n return d.toDateString() === new Date(now).toDateString() ? hm : `${d.toLocaleDateString('en-US', { weekday: 'short' })} ${hm}`;\r\n}\r\n\r\n/** company.usage for the CEO: \"normal\", \"pacing until 14:30\" or \"paused until 14:30\". */\r\nexport function usageLabel(u: UsageView, now: number): string {\r\n return u.state === 'normal' || u.until === null ? 'normal' : `${u.state} until ${clock(u.until, now)}`;\r\n}\r\n\r\n/** Clamp the pacing cap from the settings (1-32, default 3). */\r\nexport function clampPacingSessions(v: unknown): number {\r\n const n = Math.round(Number(v));\r\n return Number.isFinite(n) && n > 0 ? Math.min(32, n) : DEFAULT_PACING_SESSIONS;\r\n}\r\n\r\nconst LIMIT_NAMES: Record<string, string> = {\r\n five_hour: '5-hour limit',\r\n seven_day: 'weekly limit',\r\n seven_day_opus: 'weekly Opus limit',\r\n seven_day_sonnet: 'weekly Sonnet limit',\r\n};\r\n\r\n/** A usage warning as the SDK reports it. utilization may be a fraction (0.82) or a percentage (82). */\r\nexport interface UsageWarning {\r\n resetsAt: number | null; // epoch ms\r\n rateLimitType: string | null;\r\n utilization: number | null;\r\n}\r\n\r\n/** The phone message when pacing starts. */\r\nexport function pacingMessage(w: UsageWarning, until: number, sessions: number, now: number): string {\r\n const pct = w.utilization === null ? null : Math.round(w.utilization <= 1 ? w.utilization * 100 : w.utilization);\r\n const what = [w.rateLimitType ? (LIMIT_NAMES[w.rateLimitType] ?? w.rateLimitType.replace(/_/g, ' ')) : null, pct === null ? null : `${pct}%`].filter(Boolean).join(', ');\r\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.`;\r\n}\r\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", "// Types shared between the swarm server and the 3D client.\r\n\r\nexport type AgentStatus =\r\n | 'idle' // at desk, nothing assigned\r\n | 'preparing' // setting up the git worktree\r\n | 'working' // Claude Code session running\r\n | 'done' // finished, PR opened (or finished without one)\r\n | 'error' // session failed\r\n | 'stopped'; // manager stopped it\r\n\r\nexport type LogKind = 'text' | 'tool' | 'result' | 'system' | 'error' | 'manager' | 'done' | 'thinking';\r\n\r\nexport interface LogLine {\r\n id: number;\r\n t: number; // epoch ms\r\n kind: LogKind;\r\n text: string;\r\n tool?: string; // tool name for kind === 'tool'\r\n}\r\n\r\nexport interface IssueInfo {\r\n number: number;\r\n title: string;\r\n body: string;\r\n url: string;\r\n labels: string[];\r\n createdAt: string;\r\n}\r\n\r\nexport interface PullInfo {\r\n number: number;\r\n title: string;\r\n url: string;\r\n headRefName: string;\r\n state: 'OPEN' | 'CLOSED' | 'MERGED';\r\n isDraft: boolean;\r\n mergeable: string; // MERGEABLE | CONFLICTING | UNKNOWN\r\n reviewDecision: string | null;\r\n closesIssues: number[];\r\n createdAt: string;\r\n mergedAt: string | null;\r\n additions: number;\r\n deletions: number;\r\n checks: 'pending' | 'passing' | 'failing' | 'none';\r\n headSha: string;\r\n mergeState: string; // GitHub's mergeStateStatus: CLEAN | BEHIND | BLOCKED | DIRTY | UNSTABLE | DRAFT | UNKNOWN \u2026\r\n failedChecks: { name: string; url: string | null }[];\r\n pendingChecks: string[];\r\n}\r\n\r\nexport interface RepoView {\r\n id: string; // \"owner/name\"\r\n fullName: string;\r\n description: string;\r\n url: string;\r\n defaultBranch: string;\r\n floor: number; // 1-based floor number in the building\r\n color: string; // accent color for the floor\r\n autoAssign: boolean;\r\n autoMerge: boolean; // PRs merge themselves once QA passes and GitHub's checks are green\r\n folderSync: string | null; // how the floor's main checkout stands against GitHub: \"in sync\", \"updated to abc1234\", \"2 behind: local changes\" \u2026\r\n browserTesting: boolean;\r\n links: string[]; // ids of related repos this floor's agents can read for context\r\n mission: string; // the manager's brief: what this floor is building\r\n summary: string; // the CEO's one-line read of the project, e.g. \"3D browser game \u00B7 Three.js + Vite\"\r\n qaBrief: string; // how QA should test this kind of project (written by the CEO, editable)\r\n localPath: string | null; // the manager's own project folder, when the floor lives in one\r\n checkoutPath: string; // where the floor's main checkout is on disk (localPath, or a clone the office manages)\r\n cloneStatus: 'pending' | 'cloning' | 'ready' | 'error';\r\n cloneError?: string;\r\n issues: IssueInfo[]; // open issues\r\n pulls: PullInfo[]; // open + recently merged PRs\r\n lastSync: number | null;\r\n syncError?: string;\r\n previewConfig: PreviewConfig;\r\n preview: PreviewView;\r\n}\r\n\r\n/**\r\n * How a floor's app is run for the preview monitor. {port} and {tmp} are replaced in the command and env values;\r\n * PORT={port} is always set. command null: npm run dev, else start, else preview from package.json.\r\n */\r\nexport interface PreviewConfig {\r\n command: string | null;\r\n env: Record<string, string>;\r\n}\r\n\r\nexport type PreviewStatus =\r\n | 'unconfigured' // no command and no package.json\r\n | 'stopped'\r\n | 'preparing' // checking out the ref in the preview worktree\r\n | 'installing' // npm ci / npm install\r\n | 'starting' // command started, waiting for the port\r\n | 'running'\r\n | 'error';\r\n\r\n/** The floor's running app, served from its own worktree on a port reserved for the floor. */\r\nexport interface PreviewView {\r\n status: PreviewStatus;\r\n port: number;\r\n url: string | null; // set while running\r\n ref: string | null; // the default branch's name, or \"PR #n\"\r\n pr: number | null;\r\n commit: string | null; // short sha\r\n startedAt: number | null;\r\n error: string | null;\r\n logTail: string[]; // the last 40 lines of install / app output\r\n}\r\n\r\n/** A folder in the manager's projects folder, as offered when adding a floor. */\r\nexport interface ProjectFolderView {\r\n name: string;\r\n path: string;\r\n git: boolean;\r\n github: string | null; // owner/name of its GitHub origin\r\n floor: number | null; // already a floor in the office\r\n}\r\n\r\n/** dev and qa are the two pipeline lanes on every floor; the one CEO works in the lobby and runs the company. */\r\nexport type AgentRole = 'dev' | 'qa' | 'ceo';\r\n\r\n/** Fixed id of the CEO agent. */\r\nexport const CEO_ID = 'ceo';\r\n\r\n/** How the cartoon character is drawn. Picked from the agent's name when hired; the manager can change it. */\r\nexport type AgentLook = 'feminine' | 'masculine';\r\n\r\n/** What an agent is currently doing: implementing an issue, testing a PR, or fixing a PR after QA. */\r\nexport type AgentTask = 'issue' | 'qa' | 'fix';\r\n\r\n/**\r\n * How agents run. terminal: each agent is the real coding-agent CLI in its own terminal, shown live in the office.\r\n * sdk: Claude Code through the Agent SDK, its stream turned into log lines.\r\n */\r\nexport type AgentRuntime = 'terminal' | 'sdk';\r\n\r\n/** The coding-agent CLI an agent runs in its terminal. The CEO is always Claude Code. */\r\nexport type AgentCli = 'claude' | 'codex' | 'opencode';\r\n\r\n/** A coding-agent CLI the office knows how to run, and whether it's installed on this machine. */\r\nexport interface CliView {\r\n id: AgentCli;\r\n label: string;\r\n installed: boolean;\r\n version: string | null;\r\n /** Hooks report every tool call and enforce the guard rails; the others report only when a turn ends. */\r\n integrated: boolean;\r\n}\r\n\r\n/** Messages on an agent's terminal socket (/ws/term?agent=<id>), server to browser. */\r\nexport type TermServerMessage =\r\n | { t: 'snapshot'; data: string; cols: number; rows: number; live: boolean } // the screen and scrollback so far\r\n | { t: 'data'; data: string }\r\n | { t: 'size'; cols: number; rows: number } // another viewer resized the terminal\r\n | { t: 'live'; live: boolean }; // a CLI is (or is no longer) running in it\r\n\r\n/** Browser to server: keystrokes go to the running CLI; the size is the viewer's fitted terminal. */\r\nexport type TermClientMessage = { t: 'input'; data: string } | { t: 'resize'; cols: number; rows: number };\r\n\r\nexport interface AgentView {\r\n id: string;\r\n name: string;\r\n repoId: string;\r\n role: AgentRole;\r\n title: string; // job title, e.g. \"Three.js graphics engineer\" ('' = plain developer / QA tester)\r\n specialty: string; // routes issues labelled swarm:<specialty> to this agent first ('' = generalist)\r\n brief: string; // job description for this project, added to the agent's instructions\r\n hiredBy: 'manager' | 'ceo';\r\n look: AgentLook;\r\n task: AgentTask | null;\r\n desk: number; // desk slot on the floor (dev desks and QA lab stations are numbered separately)\r\n color: string; // shirt color\r\n hair: string; // hair color\r\n skin: string;\r\n model: string; // '' = use the swarm default model, or a model id / alias\r\n effort: EffortLevel | ''; // '' = use the swarm default effort\r\n cli: AgentCli | ''; // the CLI they run in the terminal runtime ('' = the office default)\r\n terminal: boolean; // they have a terminal to watch (the terminal runtime); otherwise their log lines are the screen\r\n status: AgentStatus;\r\n issueNumber: number | null; // devs: the issue being worked on\r\n issueTitle: string | null; // devs: issue title; QA: title of the PR under test\r\n branch: string | null;\r\n prNumber: number | null; // devs: the PR they opened; QA: the PR under test\r\n prUrl: string | null;\r\n currentTool: string | null;\r\n startedAt: number | null;\r\n endedAt: number | null;\r\n costUsd: number;\r\n turns: number;\r\n browserUrl: string | null;\r\n hasScreenshot: boolean;\r\n screenshotAt: number | null;\r\n lastError: string | null;\r\n log: LogLine[]; // tail of the terminal log (full buffer on snapshot)\r\n}\r\n\r\nexport type EffortLevel = 'low' | 'medium' | 'high' | 'xhigh' | 'max';\r\n\r\nexport type QaStatus =\r\n | 'queued' // waiting for a free QA tester\r\n | 'testing' // a QA tester is on it\r\n | 'passed' // ready to merge\r\n | 'failed' // failed; waiting for the dev who wrote it to be free\r\n | 'fixing' // the dev is fixing what QA found\r\n | 'needs-human'; // failed too many rounds, or nobody can fix it automatically\r\n\r\nexport interface QaCheck {\r\n name: string;\r\n result: 'pass' | 'fail' | 'skip';\r\n details: string;\r\n}\r\n\r\nexport interface QaView {\r\n repoId: string;\r\n prNumber: number;\r\n status: QaStatus;\r\n round: number; // 1-based QA round\r\n devAgentId: string | null; // who wrote it (null for PRs opened outside the swarm)\r\n qaAgentId: string | null; // who is testing / last tested it\r\n summary: string | null; // latest QA summary\r\n checks: QaCheck[];\r\n commentUrl: string | null; // the PR comment with the latest QA report\r\n mergeNote: string | null; // where auto-merge stands once QA passed, e.g. \"waiting for checks: Vercel\"\r\n updatedAt: number;\r\n}\r\n\r\nexport interface SwarmSettings {\r\n sessionLimit: number; // most Claude Code sessions running at once; 0 = no limit\r\n defaultModel: string;\r\n defaultEffort: EffortLevel;\r\n runtime: AgentRuntime;\r\n defaultCli: AgentCli; // what developers and QA testers run in their terminals unless they have their own\r\n hiring: 'approve' | 'auto'; // CEO proposals wait for the manager, or go through while the floor is under teamCap\r\n teamCap: number; // most agents per floor the CEO may reach without the manager's approval (auto mode)\r\n ceoHeartbeatMin: number; // minutes between the CEO's periodic reviews; 0 = off\r\n managerName: string; // what the office calls you\r\n companyName: string;\r\n projectsDir: string; // where your project folders live; new projects are created here\r\n setupDone: boolean; // the first-run setup wizard has been completed or skipped\r\n tutorialStep: number; // index of the current tutorial step; -1 when finished or skipped\r\n autoUpdate?: boolean; // update the office itself once it's quiet (absent on servers without self-update)\r\n pacingSessions: number; // after Claude warns about usage, new issues start only while fewer sessions than this run\r\n}\r\n\r\n/** Claude's subscription usage: normal, pacing new work after a usage warning, or paused at the limit until `until`. */\r\nexport interface UsageView {\r\n state: 'normal' | 'pacing' | 'paused';\r\n until: number | null;\r\n}\r\n\r\n/**\r\n * Where the office's own update stands. none: up to date \u00B7 available: new commits on GitHub \u00B7 waiting / draining:\r\n * starting nothing new while running sessions finish \u00B7 updating: handed to the launcher \u00B7 failed: see detail.\r\n */\r\nexport type OfficeUpdateState = 'none' | 'available' | 'waiting' | 'draining' | 'updating' | 'failed';\r\n\r\nexport interface OfficeUpdateView {\r\n state: OfficeUpdateState;\r\n behind: number; // commits the office's folder is behind GitHub\r\n launcher: boolean; // started by npm run dev / npm start, which can install the update and restart the office\r\n drainingSince: number | null;\r\n running: number; // sessions still running\r\n detail: string | null;\r\n}\r\n\r\n/** A CEO proposal to hire someone or let someone go. The manager (the board) decides. */\r\nexport interface HireRequestView {\r\n id: string;\r\n kind: 'hire' | 'let-go';\r\n repoId: string;\r\n role: 'dev' | 'qa';\r\n agentId: string | null; // let-go: who; hire: who was hired once approved\r\n name: string; // the candidate's name (let-go: the agent's name)\r\n title: string;\r\n specialty: string;\r\n brief: string;\r\n reason: string;\r\n model: string;\r\n effort: EffortLevel | '';\r\n look: AgentLook;\r\n color: string;\r\n hair: string;\r\n skin: string;\r\n status: 'pending' | 'approved' | 'rejected';\r\n note: string; // the manager's reason when rejecting\r\n createdAt: number;\r\n decidedAt: number | null;\r\n decidedBy: 'manager' | 'auto' | null;\r\n}\r\n\r\n/** One message in the phone thread between the manager and the CEO. */\r\nexport interface PhoneMessage {\r\n id: number;\r\n from: 'ceo' | 'manager' | 'office'; // office = notes from the building itself (decisions, errors)\r\n text: string;\r\n at: number;\r\n requestId?: string; // a hire / let-go proposal this message is about\r\n}\r\n\r\nexport type CeoJobKind = 'onboard' | 'plan' | 'review' | 'chat';\r\n\r\nexport interface CeoInfo {\r\n queue: { kind: CeoJobKind; label: string }[]; // jobs waiting for the CEO\r\n job: { kind: CeoJobKind; label: string } | null; // what the CEO is doing now\r\n lastReviewAt: number | null;\r\n nextReviewAt: number | null; // null when the heartbeat is off\r\n}\r\n\r\nexport interface WorldSnapshot {\r\n user: string | null; // gh login\r\n ghReady: boolean;\r\n ghError?: string;\r\n demo: boolean;\r\n workspaceRoot: string;\r\n settings: SwarmSettings;\r\n repos: RepoView[];\r\n agents: AgentView[];\r\n qa: QaView[];\r\n requests: HireRequestView[];\r\n ceo: CeoInfo;\r\n messages: PhoneMessage[];\r\n phoneReadAt: number; // CEO messages newer than this are unread\r\n officeCommit?: string | null; // short sha the server started on (absent on servers without self-update)\r\n officeUpdate?: OfficeUpdateView;\r\n usage: UsageView;\r\n clis: CliView[];\r\n}\r\n\r\nexport type ServerEvent =\r\n | { type: 'snapshot'; data: WorldSnapshot }\r\n | { type: 'repo'; repo: RepoView }\r\n | { type: 'repoRemoved'; repoId: string }\r\n | { type: 'agent'; agent: Omit<AgentView, 'log'> }\r\n | { type: 'agentRemoved'; agentId: string }\r\n | { type: 'log'; agentId: string; lines: LogLine[] }\r\n | { type: 'screen'; agentId: string; url: string | null; at: number }\r\n | { type: 'qa'; qa: QaView }\r\n | { type: 'qaRemoved'; repoId: string; prNumber: number }\r\n | { type: 'settings'; settings: SwarmSettings }\r\n | { type: 'request'; request: HireRequestView }\r\n | { type: 'ceo'; ceo: CeoInfo }\r\n | { type: 'message'; message: PhoneMessage }\r\n | { type: 'phoneRead'; at: number }\r\n | { type: 'officeUpdate'; officeUpdate: OfficeUpdateView }\r\n | { type: 'usage'; usage: UsageView }\r\n | { type: 'clis'; clis: CliView[] }\r\n | { type: 'toast'; level: 'info' | 'success' | 'error'; text: string };\r\n\r\nexport interface GhRepoSummary {\r\n nameWithOwner: string;\r\n description: string;\r\n visibility: string;\r\n updatedAt: string;\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["http", "path", "fs", "repos", "fs", "path", "path", "fs", "fs", "path", "fs", "path", "now", "found", "tool", "toolInput", "crypto", "fs", "path", "fs", "path", "path", "fs", "bundled", "found", "crypto", "fs", "path", "path", "onMessage", "path", "fs", "crypto", "p", "path", "route", "server", "fs", "crypto", "path", "l", "fs", "prompt", "p", "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", "repoId", "issue", "now", "now", "fs", "path", "path", "fs", "fs", "path", "repoId", "crypto", "issue", "inTerminal", "failed", "now", "pick", "repos", "rt", "pending", "path", "fs", "http"]
7
7
  }