cubefarm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/bin/cubefarm.js +257 -0
- package/dist/assets/ToyWorld-Bj5kLnpv.js +2 -0
- package/dist/assets/index-8tdBZH9c.css +1 -0
- package/dist/assets/index-uo74me0U.js +4316 -0
- package/dist/assets/rapier-DO_XuNdK.js +1 -0
- package/dist/index.html +17 -0
- package/dist-server/browser-init.js +24 -0
- package/dist-server/index.js +4753 -0
- package/dist-server/index.js.map +7 -0
- package/package.json +79 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
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"]
|
|
7
|
+
}
|