thinkpool-pair 0.7.376 → 0.7.378

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/bridge.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import e from"node:os";import t from"node:fs";import r from"node:path";import o from"node:readline";import{spawn as n,execFileSync as s}from"node:child_process";import{fileURLToPath as i}from"node:url";import{createRequire as a}from"node:module";import{randomUUID as c}from"node:crypto";import{createClient as l}from"@supabase/supabase-js";import{serveDecision as d,fetchServeRow as u,refusalMessage as m,gateFailAction as p}from"./serve-consent.mjs";import{reapTerminalRow as h}from"./reap-terminal.mjs";import{reconcileTerminalRows as f}from"./terminal-row-reconcile.mjs";import{cancelDurableDispatchPermissions as w,cancelDurablePermissions as g}from"./dispatch-permission-cleanup.mjs";import{createPermNotifier as v,shouldNotifyTurnDone as y,shouldRecordTurnDone as k,permissionSummary as b,clipSummary as $,isUserFacingLane as T,DEFAULT_MIN_TURN_MS as I}from"./agent-notify.mjs";import{resolveProviderEnv as R,resolveProviderRef as S,resolveProviderResiliencePolicy as C,providerNameMap as x,publicKeyB64 as _,bridgeHostId as A,announceProviders as P,listProviders as N,effectiveLaneModel as O,sameProviderEnv as E,providerModel as D}from"./providers.mjs";import{createMemoryCircuit as j,providerResilienceCapAdmission as q}from"./provider-resilience.mjs";import{validateProviderSwitch as K,providerSwitchPlan as M,BUILTIN_PROVIDER as U}from"./switch-provider.mjs";import{createSdkMcpServer as F,tool as B}from"@anthropic-ai/claude-agent-sdk";import{z as L}from"zod";import{readCodexDefaultModel as W,readCodexModels as H,codexConfigForMode as z,codexThreadCanResume as J}from"./codex-session.mjs";import{codexAccountUsageLine as G,codexCreditsReportLine as Y,codexLimitReportLine as V}from"./codex-commands.mjs";import{withMcpSessionFactory as Q}from"./codex-mcp-http.mjs";import{startStructuredSession as X}from"./runtime-session.mjs";import{admitRuntimeCapability as Z}from"./runtime-contract.mjs";import{cleanTerminalName as ee,modelTerminalNameInput as te}from"./terminal-name.mjs";import{defaultStructuredMode as re,normalizeStructuredEffort as oe,shouldDeferStructuredRuntime as ne,structuredModeForSlice as se,structuredModeLocked as ie,structuredModesForLane as ae,structuredRuntimeForCommand as ce,structuredRuntimeMetadata as le,structuredRuntimeSupportsMode as de}from"./runtime-registry.mjs";import{commandCatalogForRuntime as ue,commandHelpLine as me,reconcileCommandCatalog as pe}from"./command-catalog.mjs";import{gitDiffReport as he}from"./git-diff-report.mjs";import{repoSearch as fe}from"./repo-search.mjs";import{formatProjectIntelligence as we,ProjectIntelligence as ge,PROJECT_INTELLIGENCE_OPERATIONS as ve,PROJECT_INTELLIGENCE_TOOL_ANNOTATIONS as ye}from"./project-intelligence.mjs";import{probeHermesRuntime as ke}from"./hermes-probe.mjs";import{hermesRequiredMcpTools as be,hermesRoleFor as $e}from"./hermes-policy.mjs";import{canonicalRoomFilePath as Te,waitForNativeImages as Ie}from"./codex-images.mjs";import{createManagedLaneWorktree as Re,removeManagedLaneWorktree as Se}from"./lane-worktree.mjs";import{commandOnPath as Ce}from"./agent-detect.mjs";import{agentVisibilityStates as xe}from"./agent-visibility.mjs";import{requiresSdkAdmission as _e,sdkSmokePassed as Ae}from"./sdk-admission.mjs";import{hermesUserInputResponse as Pe}from"./question-response.mjs";import{hostMemoryAdmission as Ne}from"./host-memory.mjs";import{HostCapacityAuthority as Oe}from"./host-capacity.mjs";import{admitAbortRequest as Ee,queueAbortBarrier as De,takePendingAbortRequest as je,waitForAbortBarrier as qe}from"./abort-turn-barrier.mjs";import{PAIR_CLI as Ke,pairCli as Me}from"./command-guidance.mjs";import{explicitKeepAwakeChoice as Ue,keepAwakeEnabled as Fe,saveKeepAwakePreference as Be,startKeepAwake as Le}from"./keep-awake.mjs";const We=new Set(["default","acceptEdits","plan","review","bypassPermissions"]);import{FLOW_CONDUCTOR_PROMPT as He,FLOW_LANE_PROMPT as ze,FLOW_CODEX_CONDUCTOR_PROMPT as Je,FLOW_CODEX_LANE_PROMPT as Ge,buildConductorEnv as Ye,assembleCrossWaveContext as Ve,buildLanePrompt as Qe}from"./flow-conductor.mjs";import{legacyBuilderCompletionAllowed as Xe,normalizeBaselineEvidence as Ze,normalizePlanOutput as et,validatePlanForRuntime as tt,validateTaskContractSeal as rt,validReviewTargetShape as ot}from"./flow-task-graph.mjs";import{normalizeFlowRuntime as nt,flowLaneModelFor as st,flowConductorModelFor as it,spawnedLaneModelFor as at,modelCatalogValues as ct,resolveCodexModel as lt,resolveHermesOpenModel as dt,assertRuntimeModelCompatible as ut}from"./flow-models.mjs";import{writeLaneArtifact as mt,digestSlice as pt,appendDigest as ht,resumeLane as ft}from"./flow-context-store.mjs";import{createFlowWorktree as wt,worktreeSpec as gt}from"./flow-worktree.mjs";import{startPreview as vt,stopAllPreviews as yt,previews as kt}from"./flow-preview.mjs";import{ViewportManager as bt,createViewportTools as $t,sharedViewportBrowser as Tt}from"./viewport.mjs";import{deleteDesignAssetDraft as It,designPrompt as Rt,designTranscript as St,materializeDesignAsset as Ct,refreshDesignSource as xt,resolveManifestDesignSource as _t,resolveManifestDisplaySource as At,restoreDesignSources as Pt,syncRealtimeAuth as Nt,validateDesignBatchRequest as Ot}from"./design-edit.mjs";function Et(e,t=null){for(const[r,o]of kt)if("string"==typeof r&&(t?r===`lane:${e}:${t}`:r.startsWith(`lane:${e}:`)))try{o.stop()}catch{}}import{FLOW_REVIEWER_PROMPT as Dt,FLOW_CODEX_REVIEWER_PROMPT as jt,revertLane as qt,parseReviewVerdict as Kt,reviewVerdictToReflection as Mt}from"./flow-review.mjs";import{createFlowReviewReceipt as Ut,createFlowReviewSingleFlight as Ft,isFlowReviewReceipt as Bt}from"./flow-receipt.mjs";import{collectFlowScopeEvidence as Lt,normalizeFlowScopeEvidence as Wt}from"./flow-scope-evidence.mjs";import{formatPastWorkSearch as Ht,searchPastWork as zt}from"./past-work-search.mjs";import{reviewGateDecision as Jt}from"./flow-review-gate.mjs";import{IMMUTABLE_REVIEW_READ_TOOL_EXTRAS as Gt,UNSANDBOXED_REVIEW_CHECK_TOOL_EXTRAS as Yt,readReviewFile as Vt,runReviewCheck as Qt}from"./review-check.mjs";import{pairAdjudicationPrompt as Xt,reviewReflectionDecision as Zt,REVIEW_DEFAULTS as er}from"./flow-review-reflect.mjs";import{mergeWorktrees as tr,inlineSingleHtml as rr,initRepo as or}from"./flow-assembly.mjs";import{canDispatch as nr,makeBudget as sr,recordSpend as ir,killSwitchEnv as ar}from"./flow-budget.mjs";import{prepareRedispatch as cr,redispatchKey as lr}from"./flow-redispatch.mjs";import{sanitizeSession as dr}from"./transcript-sanitize.mjs";import{boundStructuredLog as ur,STRUCTURED_LOG_BYTE_CAP as mr}from"./event-bounds.mjs";import{executeFlowRevert as pr}from"./flow-host-revert.mjs";const hr=new Map,fr=new Set,wr=new Map,gr=(e,t,r)=>{if(!e||!t||!r)return null;try{return s("git",["-C",e,"diff","--name-only","--diff-filter=ACMRD",`${t}..${r}`],{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).split("\n").map(e=>e.trim()).filter(Boolean)}catch{return null}};import{formatPeek as vr,PEEK as yr,readTerminalTurnBudgetDecision as kr,siblingsOf as br,resolveSibling as $r,crossPostDecision as Tr,CROSSPOST as Ir,spawnDecision as Rr,SPAWN as Sr,CROSSROOM as Cr,CROSSROOM_BUS as xr,formatPairRoster as _r,crossRoomPostDecision as Ar,formatRoomNow as Pr,formatClosableHint as Nr,closeLaneDecision as Or,laneBusyOf as Er,laneStatusOf as Dr,settleLaneBusy as jr,settleLaneControl as qr,nativeClaudeFallbackHint as Kr,buildDispatchPreview as Mr,authorizeDirectDispatch as Ur,activeWorkerCapacityDecision as Fr,machineCapacityDecision as Br,countActiveDispatchedWorkers as Lr,maxSpawnedFor as Wr}from"./cross-terminal.mjs";import{createStandalonePairResponder as Hr,standalonePairIdentity as zr}from"./direct-pair-room.mjs";import{dispatchPendingRecap as Jr,recoverInterruptedTurn as Gr,recoverMissingResumeOnce as Yr,sendInterruptedContinue as Vr,shouldAttemptNativeResume as Qr,supersedeInterruptedResume as Xr}from"./interrupted-resume.mjs";import{supersedeDispatchLease as Zr}from"./dispatch-lease.mjs";import{realtimeRecoveryDecision as eo,turnInFlight as to}from"./update-gate.mjs";import{saveSession as ro,flushSession as oo,deleteSession as no,loadAll as so,loadArchived as io,canResume as ao,loadPtyId as co,savePtyId as lo,loadNames as uo,saveNames as mo,appendDurableEvents as po,seedDurableEvents as ho,readDurablePage as fo,readDurableOldestSeq as wo,searchDurableSessionEvents as go,hasDurableArchive as vo,servesHistoryPage as yo,acknowledgePendingScheduledOutcome as ko,commitRecordedScheduledOutcome as bo,deletePendingScheduledOutcome as $o,loadPendingScheduledOutcome as To,loadPendingScheduledOutcomes as Io,savePendingScheduledOutcome as Ro}from"./session-store.mjs";import{stampEvent as So,makeSeqCounter as Co,maxSeq as xo,seqable as _o,capReplayEvents as Ao,chunkReplayEvents as Po,boundEventForBroadcast as No,inlineImageBlocks as Oo,ImageEventQueue as Eo,imageQueueConfig as Do,uploadCodeImage as jo,usageReportLine as qo,codexUsageReportLine as Ko,appendCurrentPersonRequest as Mo,buildCheckpointFromLog as Uo,buildRecapFromLog as Fo,resolveCheckpointCarry as Bo,RECAP_CAP as Lo,trimmedBeforeSeq as Wo,firstSeq as Ho}from"./event-id.mjs";import{createLatestReplayPump as zo,requestedReplayIds as Jo}from"./replay-transport.mjs";import{createEventDeliveryQueue as Go}from"./event-delivery-queue.mjs";import{formatMcpFlight as Yo,normalizeMcpFlight as Vo,recordMcpFlightEvent as Qo}from"./mcp-flight-recorder.mjs";import{classifyCodeEvent as Xo,unknownCodeEventNotice as Zo}from"./code-event-contract.mjs";import{fetchPairControlDeliveryAuthority as en}from"./pair-control-authority.mjs";import{finishScheduledRunWithRetry as tn,pollDueScheduledRuns as rn,sanitizeScheduledOutcomeIntent as on,scheduledOutcomeReconciliationComplete as nn,scheduledRunDeadlineRequired as sn,scheduledRunSpawnAdmission as an,scheduledRunsCapability as cn,scheduledRunsEnabled as ln}from"./scheduled-runs.mjs";import{acquireScheduledRunAdmission as dn,releaseScheduledRunAdmission as un}from"./scheduled-run-admission.mjs";import{SIDE_HANDOFF_PROMPT as mn,SIDE_ROLE_PROMPT as pn,appendSideContext as hn,assistantTextSince as fn,dispatchSideContexts as wn,sideContextBlock as gn,sideSnapshot as vn}from"./side-lane.mjs";import{acknowledgeWorkerCompletions as yn,enqueueWorkerCompletion as kn,workerCompletionPrompt as bn,workerCompletionRecord as $n}from"./worker-completion.mjs";import{planMeterLine as Tn}from"./plan-meters.mjs";import{priceForModel as In}from"./model-prices.mjs";import{loadHermesModelCache as Rn,saveHermesModelCache as Sn}from"./hermes-model-cache.mjs";import{makeThrottledTrack as Cn,recoveryBackoffMs as xn}from"./presence.mjs";import{MockupDeliveryQueue as _n,completeMockupManifest as An,isMockupDeliveryBoundary as Pn}from"./mockup-delivery.mjs";import{resolveAnonKey as Nn,DEFAULT_SUPABASE_URL as On}from"./supabase-key.mjs";import{buildTerminalRolePrompt as En,HERMES_VISIBLE_WORKER_FALLBACK_RULE as Dn,THINKPOOL_PROMPT_BUNDLE as jn}from"./thinkpool-room-prompt.mjs";const qn=process.env.TP_SUPABASE_URL||On,Kn=process.env.TP_WEB_BASE||"https://thinkpool.io",Mn=Do();let Un=Rn();const{key:Fn,source:Bn}=await Nn({supabaseUrl:qn,webBase:Kn,log:e=>{process.env.TP_DEBUG&&console.error(` ◇ ${e}`)}});process.env.TP_DEBUG&&console.error(` ◇ supabase anon key source: ${Bn}`);let Ln=process.env.TP_ACCESS_TOKEN||null,Wn=null;try{Wn=(await import("node-pty")).default??await import("node-pty")}catch{console.error("\n ⚠ node-pty not built — raw terminal sharing is off (structured Claude still works).\n For PTY mode (bash / aider / codex / TP_PTY=1): install a C toolchain, then `npm i` in the bridge.\n (Xcode CLT on mac · build-essential on linux · VS Build Tools on Windows.)\n")}const Hn=[{label:"Claude Code",cmd:"claude",resume:{args:["--continue"],probe:function(){try{const o=r.resolve(process.cwd()).replace(/[/\\.:]/g,"-");return t.readdirSync(r.join(e.homedir(),".claude","projects",o)).length>0}catch{return!1}}}},{label:"Codex CLI",cmd:"codex"},{label:"Hermes Agent",cmd:"thinkpool",availability:()=>ke().available},{label:"Gemini CLI",cmd:"gemini"},{label:"Aider",cmd:"aider"},{label:"Cursor CLI",cmd:"cursor-agent"},{label:"opencode",cmd:"opencode"},{label:"Copilot CLI",cmd:"copilot"},{label:"Goose",cmd:"goose"},{label:"Crush",cmd:"crush"},{label:"Qwen Code",cmd:"qwen"}],zn=process.argv.slice(2);if("install-service"===zn[0]||"restart-service"===zn[0]){const e=Ue(zn);null===e||Be(e)||(process.stderr.write(" ⚠ could not save the keep-awake setting; service left unchanged.\n"),process.exit(1))}if("privacy-report"===zn[0]){const{runPrivacyReport:e}=await import("./privacy-report.mjs");e(),process.exit(0)}if("install-service"===zn[0]||"uninstall-service"===zn[0]){const e=zn[1]||"",t=!e||e.startsWith("-")?null:e.toUpperCase().trim(),r=zn.indexOf("--"),o=r>=0?zn.slice(r+1):[],n=zn.includes("--auto-update"),s=await import("./service.mjs");if("install-service"===zn[0]){const e=n?s.installService(t,o,{autoUpdate:n}):await s.installAndConfirmService(t,o);process.exit(!1===e?1:0)}else s.uninstallService(t);process.exit(0)}if("restart-service"===zn[0]){const e=zn[1]||"",t=!e||e.startsWith("-")?null:e.toUpperCase().trim(),r=await import("./service.mjs"),o=zn.includes("--current")?r.restartService(t):await r.updateAndConfirmService(t);process.exit(o?0:1)}const{applyProviderEnv:Jn}=await import("./provider.mjs"),Gn=Jn();if("login"===zn[0]){const{runLogin:e}=await import("./account.mjs");await e(qn,Fn,Kn)}if("bind"===zn[0]){const{runBind:e}=await import("./account.mjs");e(zn[1],zn[2])}if("set-default-dir"===zn[0]){const{saveDefaultDir:t}=await import("./auth-store.mjs");let r=(zn[1]||"").trim();r.startsWith("~")&&(r=r.replace(/^~/,e.homedir())),r||(console.error(` usage: ${Me("set-default-dir","<dir>")}`),process.exit(1)),t(r),console.log(` ◆ default project dir set → ${r}\n New/unbound sessions auto-serve from here — no per-session bind. Takes effect next serve tick.`),process.exit(0)}if("provider"===zn[0]){const{runProvider:e}=await import("./provider.mjs");await e(zn.slice(1)),process.exit(0)}if("setup-hermes"===zn[0]){const e=zn.includes("--clone"),t=zn.includes("--clean");e&&t&&(console.error(" choose one Hermes setup mode: --clone or --clean"),process.exit(1));let r=e?"clone":t?"clean":void 0;if(!r&&process.stdin.isTTY){const e=await new Promise(e=>{const t=o.createInterface({input:process.stdin,output:process.stderr});t.question("\n Clone your active Hermes provider/config into an isolated thinkpool profile? [Y/n] ",r=>{t.close(),e(String(r).trim())})});r=/^n/i.test(e)?"clean":"clone"}try{const{setupHermesRuntime:e}=await import("./hermes-setup.mjs"),t=e({mode:r});process.stderr.write(`\n ◆ Hermes ${t.version||""} is ready for thinkpool ordinary lanes.\n profile: ${t.profile} (${t.created?`${t.mode} created`:"existing"})\n hidden delegation: blocked\n${t.created&&"clean"===t.mode?" provider: run `thinkpool setup` before the first model turn\n":""}\n`),process.exit(0)}catch(e){console.error(`\n ◇ Hermes setup failed: ${e?.message||e}\n New profile: npx thinkpool-pair@latest setup-hermes --clone\n Clean profile: npx thinkpool-pair@latest setup-hermes --clean\n`),process.exit(1)}}if("verify-hermes-isolation"===zn[0])try{const{verifyHermesMcpIsolation:e}=await import("./hermes-isolation.mjs"),t=await e({rounds:2});process.stderr.write(`\n ◆ Hermes MCP isolation HELD for ${t.length} consecutive two-lane rounds.\n Each ACP session advertised only its lane-bound marker endpoint.\n No model inference was used.\n\n`),process.exit(0)}catch(e){console.error(`\n ◇ Hermes MCP isolation VIOLATED or unproven: ${e?.message||e}\n`),process.exit(1)}if((!zn[0]||"setup"===zn[0])&&process.stdin.isTTY){const{runLauncher:e,detectState:t}=await import("./launcher.mjs"),r=await import("./service.mjs"),s=i(import.meta.url),a={print:e=>process.stderr.write(e+"\n"),ask:e=>new Promise(t=>{const r=o.createInterface({input:process.stdin,output:process.stderr});r.question(e,e=>{r.close(),t(String(e).trim())})})},c={pairRoom:({room:e,agentCmd:t,resumeArgs:r=[],headless:o})=>new Promise(()=>{const i=[s,e,...o?["--headless"]:[],"--",t,...r];n(process.execPath,i,{stdio:"inherit"}).on("exit",e=>process.exit(null==e?0:e))}),serveAccountForeground:async()=>{Le({enabled:Fe([])});const{runAccount:e}=await import("./account.mjs");await e(qn,Fn)},installService:({room:e=null,agentCmd:t}={})=>r.installAndConfirmService(e,t?[t]:[]),uninstallService:({room:e=null}={})=>{r.uninstallService(e)},restartService:({room:e=null}={})=>{r.restartService(e)},restartUpdateService:async({room:e=null}={})=>"win32"===process.platform?r.updateService(e):r.updateAndConfirmService(e),relaunchLauncher:async()=>{const e=r.serviceRuntimeVersion(null);if(!e)return a.print("\n ⚠ the managed runtime was confirmed earlier but could not be resolved for launcher handoff; staying in this launcher."),!1;let t="";try{t=r.provisionRuntime(e)}catch(t){return a.print(`\n ⚠ could not open the verified v${e} launcher: ${t?.message||t}`),!1}return new Promise(e=>{const r=n(process.execPath,[t],{stdio:"inherit",cwd:process.cwd(),env:process.env});r.once("error",t=>{a.print(`\n ⚠ launcher handoff failed: ${t?.message||t}`),e(!1)}),r.once("exit",()=>e(!0))})},login:async()=>{const{runLogin:e}=await import("./account.mjs");await e(qn,Fn,Kn)},setProvider:async({kind:e,base:t,token:r,model:o})=>{const{runProvider:n}=await import("./provider.mjs"),s="custom"===e?["custom","--base",t,"--token",r,...o?["--model",o]:[]]:["anthropic"];await n(s)},setKeepAwake:async({enabled:e})=>Be(e)?(r.isServiceInstalled(null)&&r.restartService(null),!0):(a.print("\n ⚠ could not save the keep-awake setting; nothing was changed."),!1),setupHermes:async({mode:e})=>{const{setupHermesRuntime:t}=await import("./hermes-setup.mjs"),r=t({mode:e});a.print(`\n ✓ Hermes ${r.version||""} ready — isolated profile, ACP healthy, hidden delegation blocked.`),r.created&&"clean"===r.mode&&a.print(" Run `thinkpool setup` once to choose a provider before the first model turn.")}};await e({actions:c,io:a,refresh:t}),process.exit(0)}const Yn=process.env.TP_SDK_SMOKE_PATH||r.join(r.dirname(i(import.meta.url)),"sdk-smoke.mjs");let Vn={ok:null,version:"unknown",reason:""};function Qn(){try{const e=a(import.meta.url);let o=r.dirname(e.resolve("@anthropic-ai/claude-agent-sdk"));for(let e=0;e<8;e++){try{const e=JSON.parse(t.readFileSync(r.join(o,"package.json"),"utf8"));if("@anthropic-ai/claude-agent-sdk"===e.name)return e.version}catch{}const e=r.dirname(o);if(e===o)break;o=e}}catch{}return"unknown"}function Xn(){try{return s(process.execPath,[Yn],{encoding:"utf8",timeout:22e3,stdio:["ignore","pipe","ignore"]}).trim()}catch(e){return(e.stdout||"").toString().trim()||`SMOKE:FAIL:${Qn()}:${"ETIMEDOUT"===e.code?"timeout":(e.message||"run error").slice(0,80)}`}}if("verify-sdk"===zn[0]){const e=Xn();console.log(e),process.exit(Ae(e)?0:1)}if(!zn[0]||zn[0].startsWith("-")){Le({enabled:Fe(zn)});const{runAccount:e}=await import("./account.mjs");await e(qn,Fn)}const Zn=(zn[0]||"").toUpperCase().trim();Zn||(console.error(`usage: ${Me("<ROOM>","[--headless]","[--continue|--fresh]","[-- <command…>]")} | ${Ke} (account mode)`),process.exit(1)),/^[A-Z0-9_-]{2,32}$/.test(Zn)||(console.error(`refused: invalid room code ${JSON.stringify(Zn)} (expected 2–32 alphanumerics, dash, or underscore)`),process.exit(1)),_e(zn)&&(function(){const o=r.join(e.homedir(),".thinkpool-pair"),n=r.join(o,"sdk-ok"),s=Qn();Vn.version=s;let i="";try{i=t.readFileSync(n,"utf8").trim()}catch{}if(i&&i===s)return void(Vn.ok=!0);const a=Xn().match(/^SMOKE:(PASS|FAIL):([^:\n]*)(?::(.*))?$/m);if(a&&"PASS"===a[1]){Vn={ok:!0,version:a[2]||s,reason:""};try{t.mkdirSync(o,{recursive:!0}),t.writeFileSync(n,Vn.version)}catch{}process.stderr.write(`\n ◆ agent SDK v${Vn.version} passed the compatibility smoke test.\n`)}else{Vn={ok:!1,version:a&&a[2]||s,reason:a&&a[3]||"unknown"};try{t.mkdirSync(o,{recursive:!0}),t.writeFileSync(r.join(o,"sdk-bad"),`${Vn.version}: ${Vn.reason}`)}catch{}process.stderr.write(`\n ⛔ agent SDK v${Vn.version} FAILED the compatibility smoke test — ${Vn.reason}.\n ⛔ refusing to serve agent turns. Repair or pin a known-good SDK, then restart.\n`)}}(),Vn.ok||process.exit(1));const es=zn.indexOf("--"),ts=es>=0?zn.slice(0,es):zn;if(ts.includes("--supervise")||ts.includes("--keep-alive")){const e=process.argv.slice(1).filter(e=>"--supervise"!==e&&"--keep-alive"!==e);let t=1e3,r=!1,o=null;const s=()=>{const i=Date.now();o=n(process.execPath,e,{stdio:"inherit"}),o.on("exit",(e,o)=>{(r||0===e)&&process.exit(e||0);const n=Date.now()-i>6e4,a=n?1e3:t;t=n?1e3:Math.min(2*t,3e4),process.stderr.write(`\n ⚠ bridge exited (${o||`code ${e}`}); restarting in ${Math.round(a/1e3)}s…\n`),setTimeout(s,a)}),o.on("error",()=>{})};for(const e of["SIGINT","SIGTERM"])process.on(e,()=>{r=!0;try{o?.kill(e)}catch{}setTimeout(()=>process.exit(0),400)});process.stderr.write(`\n [b:${gs} r:${Zn}] ◆ supervisor up — keeping the bridge for room ${Zn} alive (auto-restart on crash).\n`),s(),await new Promise(()=>{})}{const{acquireMachineLock:e,releaseMachineLock:t,shouldHoldMachineLock:r}=await import("./account.mjs");r(process.env)&&!e()&&(console.error("\n ◇ A thinkpool-pair bridge is already running on this machine\n (~/.thinkpool-pair/account.lock). Only one can be active, and the running\n one already serves every room you are in — use it, or stop it first.\n (If you are certain none is running, delete that stale lock file.)\n"),process.exit(0)),r(process.env)&&process.on("exit",()=>{try{t()}catch{}})}Le({enabled:Fe(zn)});const rs=zn.includes("--headless"),os=(zn.find(e=>e.startsWith("--auto="))||"").slice(7)||null,ns=("1"===process.env.TP_STRUCTURED||zn.includes("--structured"),ce),ss=e=>!!ns(e)&&"1"!==process.env.TP_PTY,is=Hn.filter(e=>{return t=e.cmd,Ce(t)&&(!e.availability||e.availability());var t}),as=zn.indexOf("--"),cs=as>=0?zn.slice(0,as):zn,ls=cs.includes("--continue"),ds=cs.includes("--fresh"),us=(e,t=!0)=>new Promise(r=>{const n=o.createInterface({input:process.stdin,output:process.stderr});n.question(e,e=>{n.close();const o=String(e).trim();r(t?!/^n/i.test(o):/^y/i.test(o))})});let ms=null,ps=[],hs=!1;if(as>=0)[ms,...ps]=zn.slice(as+1),ms&&ms.startsWith("-")&&(process.stderr.write(`\n ◇ ignoring "${ms}" after \`--\` — that's a flag, not a command to share.\n`),ms=null,ps=[]);else if(!rs){0===is.length&&(console.error(`\n No known coding-agent CLI found on your PATH.\n Install one (claude / codex / gemini / aider / cursor-agent / opencode …)\n or share a specific command: ${Me(Zn,"--","<your-command>")}\n`),process.exit(1)),ms=await(fs=is,new Promise(e=>{if(1===fs.length||!process.stdin.isTTY)return void e(fs[0].cmd);const t=o.createInterface({input:process.stdin,output:process.stderr});process.stderr.write("\n Which coding agent do you want to share?\n\n"),fs.forEach((e,t)=>process.stderr.write(` ${t+1}) ${e.label}\n`)),process.stderr.write("\n"),t.question(" Pick a number [1]: ",r=>{t.close();const o=parseInt(String(r).trim(),10),n=Number.isInteger(o)&&o>=1&&o<=fs.length?o-1:0;e(fs[n].cmd)})}));const e=Hn.find(e=>e.cmd===ms);e?.resume&&!ds&&(ls?hs=!0:process.stdin.isTTY&&e.resume.probe()&&(hs=await us(`\n Continue your latest ${e.label} session in this directory? [Y/n] `)),hs&&(ps=[...e.resume.args]))}var fs;if(process.stdin.isTTY&&!rs&&"1"!==process.env.THINKPOOL_PAIR_AUTOUPDATE){const o=await import("./service.mjs");o.isServiceInstalled(Zn)&&(process.stderr.write(`\n ◆ a background service is already running room ${Zn} (auto-updating).\n ◆ remove it with: npx thinkpool-pair@latest uninstall-service ${Zn}\n\n`),process.exit(0));const n=r.join(e.homedir(),".thinkpool-pair",`${Zn}.svc-declined`);let s=!1;try{s=t.existsSync(n)}catch{}if(!s){await us("\n Run as a background service instead? It survives reboot + auto-updates,\n but runs detached — you'd stop it with 'uninstall-service', not Ctrl-C.\n Install background service? [y/N] ",!1)&&(o.installService(Zn,ms?[ms,...ps]:[]),process.stderr.write(`\n [b:${gs} r:${Zn}] ◆ the background service is handling room ${Zn} now — you can close this terminal.\n ◆ STOP IT with: npx thinkpool-pair@latest uninstall-service ${Zn}\n (closing the terminal does NOT stop it — it's detached under launchd/systemd.)\n\n`),process.exit(0));try{t.mkdirSync(r.dirname(n),{recursive:!0}),t.writeFileSync(n,(new Date).toISOString())}catch{}process.stderr.write(` [b:${gs} r:${Zn}] ◆ running in this terminal. (Auto-update service anytime: npx thinkpool-pair@latest install-service ${Zn})\n`)}}const ws=process.env.TP_NAME||e.userInfo().username||"host",gs=c?.().slice(0,8)||"bridgexx",vs=process.env.TP_ACCOUNT_BRIDGE_ID||null,ys=Number.parseInt(process.env.TP_ACCOUNT_BRIDGE_FENCING||"",10),ks=Date.now(),bs=(e.hostname()||"host").split(".")[0].slice(0,24),$s=A(),Ts=j(),Is=process.cwd(),Rs=r.basename(Is);let Ss=null;try{Ss=JSON.parse(t.readFileSync(new URL("./package.json",import.meta.url),"utf8")).version}catch{}try{const o=r.join(e.homedir(),".npm","_npx"),n=t.readdirSync(o,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).filter(e=>"cache"!==e),s=e=>e?e.split(".").map(e=>parseInt(e,10)||0):[0,0,0],i=(e,t)=>{const r=s(e),o=s(t);for(let e=0;e<3;e++){if(r[e]<o[e])return!0;if(r[e]>o[e])return!1}return!1};let a=null;for(const e of n){const n=r.join(o,e,"node_modules","thinkpool-pair","package.json");try{const e=JSON.parse(t.readFileSync(n,"utf8"));e.version&&(a&&!i(a,e.version)||(a=e.version))}catch{}}a&&Ss&&i(Ss,a)&&process.stderr.write(` ⚠ stale-cache: running ${Ss}, newest ${a}\n`)}catch{}function Cs(){try{let e=r.join(Is,".git");t.statSync(e).isFile()&&(e=t.readFileSync(e,"utf8").replace(/^gitdir:\s*/i,"").trim());const o=t.readFileSync(r.join(e,"HEAD"),"utf8").trim();return o.startsWith("ref:")?o.split("/").pop():o.slice(0,7)}catch{return null}}const xs=r.join(e.tmpdir(),"thinkpool-pair",Zn),_s=l(qn,Fn,{realtime:{params:{eventsPerSecond:60}}});let As="free";async function Ps(){const e=Ln;if(e)try{const{data:t,error:r}=await _s.auth.getUser(e),o=t?.user?.id;if(r||!o)return;const n=await fetch(`${qn}/rest/v1/profiles?select=plan&id=eq.${o}`,{headers:{apikey:Fn,Authorization:`Bearer ${e}`}});if(!n.ok)return;const s=await n.json();s?.[0]?.plan&&(As="plus"===s[0].plan?"plus":"free")}catch{}}let Ns=null;{let e=!1;if(!Ln)try{const{loadAuth:t}=await import("./auth-store.mjs");Ln=t()?.access_token||null,Ln&&(e=!0)}catch{}if(e)try{const{authedClient:e}=await import("./account.mjs"),t=await e(qn,Fn);t?.session?.access_token&&(Ln=t.session.access_token)}catch{}try{if(Ln){const{data:e}=await _s.auth.getUser(Ln);Ns=e?.user?.id||null}const{ownerId:e,name:t}=await u({supabaseUrl:qn,anonKey:Fn,token:Ln,room:Zn}),r=d({ownerId:e,myUid:Ns});r.serve||(process.stderr.write(m({room:Zn,name:t,reason:r.reason})),process.exit(0))}catch(e){"refuse"===p(e)&&(process.stderr.write(m({room:Zn,name:null,reason:"no-identity"})),process.stderr.write(`\n ◇ (serve-consent: auth rejected at the gate — ${e.message}; the stored login is expired or revoked. Re-run: ${Me("login")})\n`),process.exit(0)),process.stderr.write(`\n ◇ serve-consent check degraded (${e.message}); proceeding without it.\n`)}}!await Nt(_s,Ln,Fn)&&Ln&&process.stderr.write("\n ⚠ realtime auth could not be initialized; private bridge features are unavailable.\n"),Ps();const Os="1"===process.env.TP_BUDGET_OFF;async function Es(e,t){const r=await fetch(`${qn}/rest/v1/rpc/${e}`,{method:"POST",headers:{apikey:Fn,Authorization:`Bearer ${Ln}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!r.ok)throw new Error(`${e} ${r.status}`);const o=await r.text();return o?JSON.parse(o):null}const Ds="1"===process.env.TP_AGENT_NOTIFY_OFF,js=Number(process.env.TP_NOTIFY_MIN_TURN_MS)>0?Number(process.env.TP_NOTIFY_MIN_TURN_MS):I;function qs(e){if(Ds||!Ln||!Ns||!Zn)return;const{eventId:t,...r}=e||{},o={id:`ae:${"string"==typeof t&&/^[A-Za-z0-9_-]{1,120}$/.test(t)?t:c()}`,session_code:Zn,author_id:Ns,payload:{__agent:!0,ts:Date.now(),...r}};fetch(`${qn}/rest/v1/code_messages`,{method:"POST",headers:{apikey:Fn,Authorization:`Bearer ${Ln}`,"Content-Type":"application/json",Prefer:"return=minimal"},body:JSON.stringify(o)}).then(e=>{!e.ok&&process.env.TP_DEBUG&&process.stderr.write(`\n ◆ agent-event insert ${e.status}\n`)}).catch(()=>{})}let Ks=null;const Ms=_s.channel(`tpcode:${Zn}`,{config:{private:!0,broadcast:{self:!1},presence:{key:`bridge:${ws}`}}}),Us=_s.channel(`tpflow:${Zn}`,{config:{broadcast:{self:!1}}}),Fs=_s.channel(`tpdesign:${Zn}`,{config:{private:!0,broadcast:{self:!1}}}),Bs=_s.channel(`tpcontrol:${Zn}`,{config:{private:!0,broadcast:{self:!1}}}),Ls=new Map,Ws=new Map;let Hs=0;function zs(e,t=Date.now()){const r=e?.session?.turnActive??!1;return r!==e?._busyAnn&&(r&&(e._turnRev=(Number(e._turnRev)||0)+1,e._turnStart=t,e._settledTurnRev=null,e._turnSettledAt=null),e._busyAnn=r,!0)}function Js(e,t=Date.now()){return!0!==e?._busyAnn&&(e._turnRev=(Number(e._turnRev)||0)+1,e._turnStart=t,e._busyAnn=!0,e._settledTurnRev=null,e._turnSettledAt=null,!0)}function Gs(e,t,{options:r,visibleEvent:o,rejectionMessage:n="The agent did not accept this turn; retry after the lane is available."}={}){if(!e?.session)return{accepted:!1,error:new Error("session unavailable")};zs(e);let s=!1,i=null;try{s=!1!==e.session.sendTurn(t,r)}catch(e){i=e}if(s?Js(e):zs(e),o&&(Sa(e,o),pi("code-event",{term:e.id,evt:o})),!s){const t={kind:"error",message:n,recoverable:!0};Sa(e,t),pi("code-event",{term:e.id,evt:t})}return bi(),{accepted:s,error:i}}function Ys(e){e?.pendingSideContexts?.length&&!e._sideContextTimer&&(e._sideContextTimer=setTimeout(()=>{e._sideContextTimer=null,function(e){if(!e?.pendingSideContexts?.length||"function"!=typeof e.session?.sendTurn)return!1;const t=wn({contexts:e.pendingSideContexts,busy:!0===e.session?.turnActive,sendTurn:t=>e.session?.sendTurn(t)});return e.pendingSideContexts=t.pending,!!t.dispatched&&(Js(e),e.flush?.(),bi(),!0)}(e)&&process.stderr.write("\n ◆ started main turn from side-lane handoff.\n")},0),e._sideContextTimer.unref?.())}function Vs(e){e?.pendingWorkerCompletions?.length&&!e._workerCompletionTimer&&(e._workerCompletionTimer=setTimeout(()=>{e._workerCompletionTimer=null,function(e){if(!e?.pendingWorkerCompletions?.length||"function"!=typeof e.session?.sendTurn)return!1;if(e.workerCompletionsInFlight?.length)return!1;if(Er(e)||(e.pending?.size||0)>0)return!1;const t=e.pendingWorkerCompletions.slice(),r=bn(t);return r?(e.workerCompletionsInFlight=t,e.flush?.(),!!Gs(e,r,{rejectionMessage:"The worker-completion continuation was not accepted; it remains queued."}).accepted||(e.workerCompletionsInFlight=[],e.flush?.(),!1)):(e.pendingWorkerCompletions=[],!1)}(e)&&process.stderr.write("\n ◆ worker finished — continued its owning terminal.\n")},0),e._workerCompletionTimer.unref?.())}function Qs(e,t){return t&&null==t.turnRev&&Number(e?._turnRev)>0&&(t.turnRev=e._turnRev),t}let Xs=null,Zs=!1;const ei=[];let ti=0;const ri="1"===process.env.TP_BACKGROUND_WARM;async function oi(){for(;ti<3&&ei.length;){const e=ei.shift();if(!e||e.warmed||e.warming||!e.session||e.session.started)continue;const t=await ji(e);if(!t.ok){process.stderr.write(`\n ◇ background warm held for ${String(e.id).slice(0,8)} — ${t.reason||"host runtime capacity is full"}\n`);break}e.warming=!0,ti++;try{e.session.warm?.()}catch{e.warming=!1,ti--,qi(e,t);continue}e.warmTimer=setTimeout(()=>{e.warming&&(e.warming=!1,ti=Math.max(0,ti-1),oi())},1e5)}}let ni=Date.now();const si=()=>{if(ni=Date.now(),process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD)try{process.send({t:"busy"})}catch{}};let ii=null,ai=!1,ci=!1;const li=()=>{try{const e=Ms.presenceState()||{};for(const t of Object.values(e))for(const e of t||[])if(e&&"bridge"!==e.role)return!0}catch{}return!1},di=2e5,ui=async(e,t,r=Ms)=>{"pty-out"!==e&&"code-event"!==e||(ni=Date.now()),t=((e,t)=>{let r,o;try{r=JSON.stringify(t)}catch{return t}if(!r||r.length<=di)return t;process.stderr.write(`\n ⚠ oversized ${e} frame: ${r.length}B (term ${String(t?.term||"?").slice(0,8)}) — defanging so Realtime doesn't drop it\n`);try{o=JSON.parse(r)}catch{return t}if(o.evt&&"object"==typeof o.evt&&(o.evt=No(o.evt,1e5)),Array.isArray(o.events)){o.events=o.events.map(e=>No(e,1e5));let e=0,t=0;for(;o.events.length>1&&JSON.stringify(o).length>di&&e++<1e4;)o.events.shift(),t++;if(t){const e=Ho(o.events);"number"==typeof e&&(o.trimmedBefore=Math.max(o.trimmedBefore??0,e))}}return o})(e,t);try{return r.channelAdapter?.canPush?.()??1?await r.send({type:"broadcast",event:e,payload:t}):await r.httpSend(e,t)}catch{return null}},mi=Go({send:({event:e,payload:t,ch:r})=>ui(e,t,r)}),pi=(e,t,r=Ms)=>{"code-event"!==e||r!==Ms?ui(e,t,r):mi.enqueue({event:e,payload:t,ch:r})},hi=zo({send:({event:e,payload:t})=>ui(e,t)}),fi=uo(Zn),wi=new Set,gi=(e,t,r=null)=>{pi("term-opened",{id:e,kind:t,sideParent:r?.sideParent||void 0,sideTask:r?.sideTask||void 0,name:fi[e]||void 0})},vi=new Set,yi=new Map;let ki=null;const bi=()=>{const e=x(),t=new Map(xe(is.map(e=>e.cmd)).map(e=>[e.cmd,e.enabled])),o=++Hs;return ui("bridge",{v:2,name:ws,bridge_id:gs,started_at:ks,rev:o,repo:Rs,branch:Cs(),...!1===Vn.ok?{sdkWarn:`${Vn.version}: ${Vn.reason}`}:{},models:ki||void 0,cwd:Is,version:Ss,promptBundle:jn,host:bs,hostId:$s,uid:Ns||void 0,provider:Gn.provider,providerBaseUrl:Gn.baseUrl||void 0,ctxCarry:!0,providerPubKey:_(),providers:P(),pendingUpdate:ii,updir:xs.split(r.sep).join("/"),scheduledRuns:cn(),capacity:{workerActive:Lr(Ws.values()),workerLimit:Wr(As),hostStatus:Ai},agents:is.map(e=>{let r=!1;if(e.resume)try{r=e.resume.probe()}catch{}return{label:e.label,cmd:e.cmd,canResume:r,enabled:!1!==t.get(e.cmd)}}),terms:[...[...Ls.entries()].map(([e,t])=>({id:e,cmd:t.cmd,alive:!0,cols:t.term.cols,rows:t.term.rows,name:fi[e]||void 0,...Dr(t)})),...[...Ws.entries()].map(([t,r])=>({id:t,cmd:r.cmd,kind:"structured",runtime:r.runtime||"claude",alive:!0,...Dr(r),turnRev:Number(r._turnRev)||0,...Er(r)&&r._turnStart?{turnStartedAt:r._turnStart}:{},...!Er(r)&&Number(r._settledTurnRev)>0&&Number(r._settledTurnRev)===Number(r._turnRev)?{settledTurnRev:Number(r._settledTurnRev),turnSettledAt:Number(r._turnSettledAt)||void 0}:{},hasTranscript:r.log.length>0,commands:r.commands,mode:r.mode||void 0,effort:r.effort||void 0,name:fi[t]||void 0,model:r.model||void 0,capabilities:{...le(r.runtime||"claude"),modes:ae(r.runtime||"claude",r)},..."codex"===r.runtime?{approvalPolicy:z(r.mode).approvalPolicy,models:r.models||[],canSteer:r.session?.canSteer??!1}:"hermes"===r.runtime?{models:r.models||[],canSteer:r.session?.canSteer??!1}:{},...null!=r.archiveOldestSeq?{oldestSeq:r.archiveOldestSeq}:{},...r.spawnedBy?{spawned:!0,spawnedBy:r.spawnedBy}:{},...r.sideParent?{sideParent:r.sideParent,sideTask:r.sideTask||void 0,sideHandback:!!r.sideHandback}:{},...r.flowSessionId?{flowId:r.flowSessionId,flowRole:r.flowTaskKey?"lane":"conductor"}:{},...r.scheduleRunId?{scheduleRunId:r.scheduleRunId}:{},...r.provider&&"anthropic"!==r.provider?{provider:{id:r.provider,name:e[r.provider]||r.provider}}:{}}))]})},$i=async(e,t,r,o=!0)=>{if(Ln&&e&&t)try{const n=r?`&name=eq.${encodeURIComponent(r)}`:`&or=${encodeURIComponent("(name.is.null,name.eq.Terminal)")}`,s=await fetch(`${qn}/rest/v1/code_terminals?id=eq.${encodeURIComponent(e)}${n}&select=id`,{method:"PATCH",headers:{apikey:Fn,Authorization:`Bearer ${Ln}`,"Content-Type":"application/json",Prefer:"return=representation"},body:JSON.stringify({name:t})}),i=s.ok?await s.json().catch(()=>[]):[];if(o&&(!s.ok||!Array.isArray(i)||0===i.length)){const o=setTimeout(()=>{$i(e,t,r,!1)},1500);o.unref?.()}}catch{if(o){const o=setTimeout(()=>{$i(e,t,r,!1)},1500);o.unref?.()}}},Ti=async(e,t,r=!0)=>{if(!Ln||!e||!t)return;const o=new AbortController,n=setTimeout(()=>o.abort(),4500);try{const s=await fetch(`${Kn}/api/code-terminal-name`,{method:"POST",headers:{Authorization:`Bearer ${Ln}`,"Content-Type":"application/json"},body:JSON.stringify({code:Zn,terminalId:e,task:t}),signal:o.signal});clearTimeout(n);const i=await s.json().catch(()=>({}));if(r&&404===s.status&&"terminal_pending"===i?.code){const r=setTimeout(()=>{Ti(e,t,!1)},1500);return void r.unref?.()}if(!s.ok)return;const a=ee(i?.name);a&&((e,t)=>{if(!t||wi.has(e))return!1;const r=yi.get(e);if(fi[e]&&fi[e]!==r)return!1;const o=fi[e]||null,n=((e,t)=>{const r=new Set(Object.entries(fi).filter(([t])=>t!==e).map(([,e])=>String(e).toLowerCase()));if(!r.has(t.toLowerCase()))return t;for(let e=2;e<100;e++){const o=` ${e}`,n=`${t.slice(0,48-o.length).trim()}${o}`;if(!r.has(n.toLowerCase()))return n}return t})(e,t);fi[e]===n||(fi[e]=n,yi.set(e,n),mo(Zn,fi),$i(e,n,o),bi())})(e,a)}catch{clearTimeout(n)}},Ii=(e,t)=>{const r=Ws.get(e);if(!r||fi[e]||wi.has(e)||vi.has(e))return;if(r.log?.some(e=>"you"===e?.kind))return;const o=te(t);o&&(vi.add(e),Ti(e,o))},Ri=!(!process.send||"1"!==process.env.THINKPOOL_PAIR_ACCOUNT_CHILD),Si=new Oe,Ci=new Map,xi=new Set,_i=new Map;let Ai="available",Pi=null;const Ni=()=>{if(!Ne("resume queued Dispatch work").ok)return Ai="held",void Oi();Ai="available",bi(),pi("capacity-changed",{},Us)},Oi=()=>{Ai="held",Pi||(Pi=setInterval(()=>{Ne("resume queued Dispatch work").ok&&(clearInterval(Pi),Pi=null,Ni())},5e3),Pi.unref?.(),bi())},Ei=async e=>{if(!e)return{ok:!1,code:"invalid_capacity_request"};if(!Ri){const t=Si.acquire({room:Zn,terminalId:e});return t.ok&&xi.add(e),t.ok||(Ai="held"),t}const t=c();return new Promise(r=>{const o=setTimeout(()=>{Ci.delete(t),Ai="held";try{process.send({t:"capacity-release",terminalId:e})}catch{}r({ok:!1,code:"capacity_authority_unavailable",reason:"The bridge capacity authority did not answer. No lane was opened; retry when the bridge reconnects."})},2500);o.unref?.(),Ci.set(t,{resolve:r,timer:o,terminalId:e});try{process.send({t:"capacity-acquire",reqId:t,terminalId:e})}catch{clearTimeout(o),Ci.delete(t),Ai="held",r({ok:!1,code:"capacity_authority_unavailable",reason:"The bridge capacity authority is unavailable. No lane was opened."})}})},Di=e=>{if(e)if(xi.delete(e),Ri)try{process.send({t:"capacity-release",terminalId:e})}catch{}else Si.release({room:Zn,terminalId:e})&&Ni()};Ri&&process.on("message",e=>{if("capacity-acquire-result"===e?.t){const t=Ci.get(e.reqId);if(!t)return;clearTimeout(t.timer),Ci.delete(e.reqId),e.ok&&xi.add(t.terminalId),e.ok||(Ai="held"),t.resolve({ok:!0===e.ok,code:e.code,reason:e.reason,active:e.active,limit:e.limit})}else"capacity-changed"===e?.t&&Ni()});const ji=async e=>{const t=e?.id;if(!t)return{ok:!1,code:"invalid_capacity_request",newlyAcquired:!1};if(xi.has(t))return{ok:!0,code:"already_admitted",newlyAcquired:!1};const r=_i.get(t);if(r)return{...await r,newlyAcquired:!1};const o=Ei(t);_i.set(t,o);try{const e=await o;return{...e,newlyAcquired:!0===e.ok}}finally{_i.get(t)===o&&_i.delete(t)}},qi=(e,t)=>{t?.newlyAcquired&&queueMicrotask(()=>{e?.session?.started||e?.session?.turnActive||Di(e?.id)})},Ki=new Map;let Mi=null;function Ui(e,t={},r=4e3){if("1"===process.env.TP_CROSSROOM_OFF)return Promise.resolve({error:"Cross-session reach is turned off in this room."});if(!Ri)return Promise.resolve({error:`Cross-session reach needs the thinkpool account bridge running your sessions (${Ke}). This room is running standalone, so it can only see its own terminals — use read_terminal.`});const o=c();return new Promise(n=>{const s=setTimeout(()=>{Ki.delete(o),n({error:"The other session did not respond in time."})},r);s.unref?.(),Ki.set(o,{resolve:n,timer:s});try{process.send({t:e,reqId:o,...t})}catch{clearTimeout(s),Ki.delete(o),n({error:"Could not reach the account bridge."})}})}function Fi(e,t){const r={kind:"needs-input",subtype:"pair-control",summary:"A protected action requires a durable decision.",permissionId:String(t?.id||"").slice(0,160)};return Sa(e,r),pi("code-event",{term:e.id,evt:r}),{...t,...e.scheduleRunId?{runId:e.scheduleRunId}:{},source:{epoch:0,cid:r.cid,seq:r.seq}}}async function Bi({fromRoom:e,fromHost:t,fromTerminalName:r,text:o,terminal:n}){if("1"===process.env.TP_PAIRBUS_OFF)return{error:"Cross-room posting is turned off in this room."};const s=String(o||"").trim();if(!s)return{error:"Empty cross-room post ignored."};const i=br({selfId:null,sessions:Ws,terms:Ls,names:fi});let a=null;if(n){const e=$r(i,n);if(e&&"agent"!==e.kind)return{error:`Terminal ${e.ref} in room ${Zn} is a shell, not an agent — cross-room posts go to agents only.`};a=e?.id||null}else{const e=[...Ws.keys()];1===e.length&&(a=e[0])}if(!a){const e=i.filter(e=>"agent"===e.kind);return{error:e.length?`Name which agent lane in room ${Zn} to deliver to (${e.map(e=>e.ref).join(", ")}).`:`No agent terminal is open in room ${Zn} to receive this.`}}const l=Ws.get(a);if(!l?.session)return{error:`That terminal in room ${Zn} is no longer live.`};const d=`${e}${t?` on ${t}`:""}`;let u="deny";try{u=await(m=l,p={id:c(),toolName:"mcp__thinkpool__post_to_session",input:{session:e,host:t,terminalName:r,text:s,incoming:!0},risk:"high"},new Promise(e=>{if(!m?.pending)return e("deny");const t=Fi(m,{term:m.id,id:p.id,toolName:p.toolName,input:p.input,risk:p.risk});m.pending.set(p.id,{resolve:e,payload:t}),bi(),pi("code-perm-req",t),process.stderr.write(`\n ● incoming cross-room task for ${String(m.id).slice(0,8)} — approve in the room.\n`)}))}catch{u="deny"}var m,p;if("allow"!==u)return{error:`The people in room ${Zn} declined the incoming task from ${d}.`};const h=await ji(l);if(!h.ok)return{error:h.reason||`The host cannot start terminal ${String(a).slice(0,8)} yet.`};l.roomHop=1,l.hop=(l.hop||0)+1,l.peekCount=0,l.peekRosterCount=0,l.postCount=0,l.pairPeekCount=0,l.crossRoomPostCount=0;const f=`[From: room ${d} — relayed via the thinkpool cross-room Ensemble, approved by a person in this room]\n${s}`,w={kind:"you",text:f,by:`room ${e}`,crosspost:!0,relaySourceName:String(r||"").trim().slice(0,80)||void 0};Ii(a,s);const g=Gs(l,f,{visibleEvent:w,rejectionMessage:"The incoming cross-room task was not accepted; retry after the lane is available."});return g.accepted?{ok:!0,ref:String(a).slice(0,8)}:(qi(l,h),{error:g.error?`Could not deliver to room ${Zn} — the lane may have just closed.`:`Could not deliver to room ${Zn} — the lane refused the turn (check its visible host-memory/runtime error).`})}!async function(){if(Ri||"1"===process.env.TP_PAIRBUS_OFF||"1"===process.env.TP_CROSSROOM_OFF)return;if(!Ln||!Ns)return;let t=null;try{const e=`${qn}/rest/v1/code_sessions?code=eq.${encodeURIComponent(Zn)}&select=code,name,owner_id,participants`,r=await fetch(e,{headers:{apikey:Fn,Authorization:`Bearer ${Ln}`}});if(!r.ok)return;const o=await r.json().catch(()=>[]);t=Array.isArray(o)?o[0]:null}catch{return}const r=zr({row:t,myUid:Ns});if(!r?.topic)return;const o=Hr({room:Zn,roomName:t?.name||null,host:e.hostname().replace(/\.local$/,""),formatPeek:e=>vr({selfId:null,sessions:Ws,terms:Ls,names:fi,terminal:e.terminal,lines:e.lines}),receivePost:e=>Bi(e)}),n=_s.channel(r.topic,{config:{private:!0,broadcast:{self:!1}}}),s=async(e,t)=>{if(t)try{await n.send({type:"broadcast",event:e,payload:t})}catch{}};n.on("broadcast",{event:"peer-list-req"},({payload:e})=>{s("peer-list-res",o.list(e))}).on("broadcast",{event:"peer-peek-req"},({payload:e})=>{const t=o.peek(e);t&&s("peer-peek-res",t)}).on("broadcast",{event:"peer-post-req"},({payload:e})=>{o.post(e).then(e=>{if(e)return s("peer-post-res",e)})}).subscribe(e=>{"SUBSCRIBED"===e?process.stderr.write("\n ◆ standalone pair bus subscribed — this live room can receive approval-gated cross-session tasks.\n"):"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e||process.stderr.write(`\n ◇ standalone pair bus ${e.toLowerCase().replace("_"," ")} — cross-session reach will retry with realtime.\n`)}),Mi=n}(),Ri&&process.on("message",e=>{if(e&&e.t){if("pair-list-res"===e.t||"pair-peek-res"===e.t||"pair-post-res"===e.t){const t=Ki.get(e.reqId);if(!t)return;return clearTimeout(t.timer),Ki.delete(e.reqId),void t.resolve(e)}if("pair-peek-local"===e.t){let t,r;try{t=vr({selfId:null,sessions:Ws,terms:Ls,names:fi,terminal:e.terminal,lines:e.lines})}catch{r="Could not read that session."}try{process.send({t:"pair-peek-res",reqId:e.reqId,text:t,error:r})}catch{}return}"pair-post-local"!==e.t||Bi(e).then(t=>{try{process.send({t:"pair-post-res",reqId:e.reqId,...t})}catch{}})}});const Li=()=>{const e=li();for(const[t,r]of Ls){if(!r.buf)continue;if(!e){r.buf="",ni=Date.now();continue}const o=Buffer.from(r.buf,"utf8").toString("base64");r.buf="",pi("pty-out",{term:t,b64:o})}},Wi=setInterval(Li,35);Wi.unref?.();const Hi=r.join(e.tmpdir(),"thinkpool-mockups",Zn);try{t.mkdirSync(Hi,{recursive:!0}),process.env.TP_MOCKUP_OUTBOX=Hi}catch{}const zi=new Map,Ji=new Map,Gi=new Map,Yi=new Map,Vi=new Map;function Qi(e){e?.scheduleDeadlineTimer&&clearTimeout(e.scheduleDeadlineTimer),e&&(e.scheduleDeadlineTimer=null)}const Xi=new Set;async function Zi(e){const t=e?.scheduleAdmissionLease;return!t||!!(await un(t)).ok&&(e.scheduleAdmissionLease=null,!0)}async function ea(e){const t=on(e?.scheduleOutcomePending);if(!e?.id||!t||e.scheduleOutcomeRecorded)return!1;const r=`${e.id}:${t.runId}`;if(Xi.has(r))return!1;Xi.add(r);try{if(!(await tn({supabaseUrl:qn,anonKey:Fn,token:Ln,roomCode:Zn,runId:t.runId,bridgeId:vs,bridgeFencing:ys,result:t.result,canceled:t.canceled,evidenceRefs:t.evidenceRefs})).ok)return!1;if(await Zi(e),Ws.get(e.id)!==e)return!!ko(Zn,e.id,t.runId)&&$o(Zn,e.id);const r=e.scheduleOutcomePending;e.scheduleOutcomeRecorded=!0,e.scheduleOutcomePending=null;const o=bo(Zn,e.id,()=>e.flush?.());return o.snapshotRecorded?o.ok:(e.scheduleOutcomeRecorded=!1,e.scheduleOutcomePending=r,!1)}finally{Xi.delete(r)}}function ta(e,t,{canceled:r=!1}={}){if(!e?.scheduleRunId||e.scheduleOutcomeRecorded||e.scheduleOutcomePending)return!1;const o=on({runId:e.scheduleRunId,result:t,canceled:r,evidenceRefs:(n=e.id,[...Ji.values()].filter(e=>e?.term===n&&"string"==typeof e.previewId).slice(0,16).map(e=>({type:"preview",id:e.previewId})))});var n;return!!o&&!!Ro(Zn,e.id,o)&&(e.scheduleOutcomePending=o,Qi(e),e.flush?.(),ea(e),!0)}function ra(e){if(Qi(e),!sn({runId:e?.scheduleRunId,deadlineAt:e?.scheduleDeadlineAt,outcomeRecorded:e?.scheduleOutcomeRecorded,outcomePending:e?.scheduleOutcomePending}))return;const t=Math.max(0,e.scheduleDeadlineAt-Date.now());e.scheduleDeadlineTimer=setTimeout(async()=>{if(e.scheduleDeadlineTimer=null,e.scheduleOutcomeRecorded)return;e.scheduleTimedOut=!0,Ka(e),await De(e);const t={kind:"error",subtype:"runtime_limit",message:"Scheduled run reached its configured runtime ceiling."};Sa(e,t),pi("code-event",{term:e.id,evt:t}),ta(e,t),e.flush?.(),bi()},t),e.scheduleDeadlineTimer.unref?.()}const oa=e=>Fs.send({type:"broadcast",event:"design-status",payload:{ts:Date.now(),...e}}),na=(e,t,r={})=>{const o=Yi.get(e);if(o){if(o.timer&&clearTimeout(o.timer),Yi.delete(e),oa({previewId:o.record.previewId,requestId:o.request.cid,state:t,...r}),"verified-live"===t){const t=Gi.get(e)||[];for(const e of t.splice(0))oa({previewId:e.record.previewId,requestId:e.request.cid,state:"stale",message:"The artifact changed. Reselect the element on the new revision."})}queueMicrotask(()=>ia(e))}},sa=e=>{const t=Yi.get(e);t?.resultOk&&t.proof&&na(e,"verified-live",{message:"Verified at desktop and mobile.",artifact:t.proof.artifact,...t.proof.artifactHtml?{artifactHtml:t.proof.artifactHtml}:{},canRestore:"preview"!==t.record.sourceKind})};async function ia(e){if(Yi.has(e))return;const t=Gi.get(e)||[],r=t[0];if(!r)return;const o=Ws.get(e);if(!o)return t.shift(),oa({previewId:r.record.previewId,requestId:r.request.cid,state:"needs-lane",message:"The producing lane is no longer available."}),ia(e);if(o.session?.turnActive)return;t.shift();const n=Ji.get(r.record.previewId),s=n&&xt(n);if(!n||!s||s.revision!==r.record.revision)return oa({previewId:r.record.previewId,requestId:r.request.cid,state:"stale",message:"The artifact changed. Reselect the element."}),ia(e);const i=await ji(o);if(!i.ok)return oa({previewId:r.record.previewId,requestId:r.request.cid,state:"failed",message:i.reason||"The host cannot start the producing lane yet."}),ia(e);const a={...r,resultOk:!1,proof:null,timer:null};Yi.set(e,a);const c={kind:"you",text:St(r.request,{restore:!!r.restoreRecord}),cid:r.request.cid,by:r.by,design:!0};zs(o);let l=!1;try{l=!1!==o.session.sendTurn(Rt({record:r.record,request:r.request,by:r.by,restore:!!r.restoreRecord,priorRecord:r.restoreRecord}))}catch{l=!1}if(l&&Js(o),So(c),Sa(o,c),pi("code-event",{term:e,evt:c}),l&&oa({previewId:r.record.previewId,requestId:r.request.cid,state:"applying"}),!l){qi(o,i),zs(o);const t={kind:"error",message:"The producing lane could not start the edit.",recoverable:!0};Sa(o,t),pi("code-event",{term:e,evt:t}),na(e,"failed",{message:"The producing lane could not start the edit."})}bi()}const aa=(e,o,n,s)=>{try{const i=r.join(e,`${o}.receipt.json`),a=`${i}.tmp`;t.writeFileSync(a,JSON.stringify({ok:n,status:s,ts:Date.now()})),t.renameSync(a,i)}catch{}},ca=new _n({deliver:async({box:e,term:o,trustedDesignSource:n=!1,slug:s,m:i})=>{const a=n?Ws.get(o):null,l=a?_t(i,a.cwd||process.cwd(),{box:e}):null,d=l?At(i,l,{box:e}):null,u=l?Yi.get(o):null,m=!(!u||i.designRequestId!==u.request.cid||i.parentRevision!==u.record.revision),p=u?.restoreRecord?.revision,h=p?l?.revision===p:l?.revision!==u?.record?.revision,f="preview"===u?.record?.sourceKind?"preview"===l?.sourceKind&&l?.captureKey===u.record.captureKey:l?.sourcePath===u?.record?.sourcePath,w=m&&f&&h?u.record.revision:null,g=e=>{try{return e&&t.readFileSync(e).toString("base64")}catch(t){return e&&process.stderr.write(`\n ◇ mockup asset unreadable: ${e} (${t?.code||t?.message||t})\n`),null}},v=e=>{try{return e&&t.readFileSync(e,"utf8")}catch(t){return e&&process.stderr.write(`\n ◇ mockup asset unreadable: ${e} (${t?.code||t?.message||t})\n`),null}},y=c(),k=Date.now();if(l&&!d)return aa(e,s,!1,"invalid-snapshot"),void process.stderr.write(`\n ◇ mockup "${i.slug}" rendered snapshot was not trusted.\n`);try{const n={"Content-Type":"application/json"};Ln&&(n.Authorization=`Bearer ${Ln}`);const a=await fetch(`${Kn}/api/code-mockup`,{method:"POST",headers:n,body:JSON.stringify({code:Zn,slug:i.slug,title:i.title,cid:y,ts:k,term:o,desktopPng:g(i.desktop),mobilePng:g(i.mobile),html:l?d:v(i.html),...l?{previewId:l.previewId,revision:l.revision,sourceKnown:!0}:{},...w?{verified:!0,parentRevision:w}:{}})});if(!a.ok)return aa(e,s,!1,a.status),void process.stderr.write(`\n ◇ mockup "${i.slug}" upload failed (${a.status}).\n`);const c=await a.json(),{paths:m}=c,p=!(!l||!c?.payload?.sourceKnown),h=!(!p||!w||!0!==c?.payload?.verified||c.payload.parentRevision!==w),f="string"==typeof c?.payload?.artifactHtml?c.payload.artifactHtml:null,b={kind:"mockup",__struct:!0,cid:y,term:o,slug:i.slug,title:i.title||i.slug,ts:k,paths:m,...p?{previewId:l.previewId,revision:l.revision,sourceKnown:!0,...h?{verified:!0,parentRevision:w}:{}}:{},...f?{artifactHtml:f}:{}};if(p){Object.assign(l,{term:o,slug:i.slug,title:i.title||i.slug,desktop:i.desktop,mobile:i.mobile});try{const o=r.join(e,".design-revisions");t.mkdirSync(o,{recursive:!0}),l.backupPath=r.join(o,`${l.revision}.html`),t.existsSync(l.backupPath)||t.writeFileSync(l.backupPath,l.source)}catch{}Ji.set(l.previewId,l);const n=u,s=h,a=!!(m?.html&&m?.desktop&&m?.mobile&&i.desktop&&i.mobile);if(s&&a){"preview"!==n.record.sourceKind&&Vi.set(l.previewId,{priorRecord:n.record,request:n.request});const e=f||(Buffer.byteLength(d,"utf8")<=131072?d:null);n.proof={artifact:b,artifactHtml:e},sa(o)}}pi("code-event",{term:o,evt:b}),aa(e,s,!0,200),process.stderr.write(`\n ◆ mockup "${i.title||i.slug}" pushed to the room.\n`)}catch(t){aa(e,s,!1,"error"),process.stderr.write(`\n ◇ mockup "${i.slug}" send failed: ${t?.message||t}\n`)}}});function la(e,o,n=!1){try{t.mkdirSync(e,{recursive:!0})}catch{return null}try{return t.watch(e,(s,i)=>function(e,o,n,s=!1){const i=((e,o,n,s=!1)=>{if(!o||o.endsWith(".receipt.json")||!o.endsWith(".json"))return null;const i=r.join(e,o);let a;try{a=t.statSync(i)}catch{return null}const c=o.replace(/\.json$/,""),l=`${n}/${c}`;if(zi.get(l)===a.mtimeMs)return null;if(zi.set(l,a.mtimeMs),!n)return null;let d;try{d=JSON.parse(t.readFileSync(i,"utf8"))}catch{return null}return d?.slug?An(d,{isReadyFile:e=>{try{const r=t.statSync(e);return r.isFile()&&r.size>0}catch{return!1}}})?{box:e,file:o,term:n,trustedDesignSource:s,slug:c,m:d}:(aa(e,c,!1,"incomplete"),process.stderr.write(`\n ◇ mockup "${d.title||d.slug}" is incomplete — desktop, mobile, and source are all required.\n`),null):null})(e,o,n,s);if(!i)return;const a=Ws.get(n),c=!!a&&(!0===a._busyAnn||!0===a.session?.turnActive),l="preview"===i.m.sourceKind?`preview:${i.m.captureKey||i.m.route||i.m.slug}:${i.m.title||""}`:`authored:${i.m.slug}`,d=ca.enqueue(n,i,{active:c,key:l});d.queued?(aa(e,i.slug,!0,"queued"),process.stderr.write(`\n ◆ mockup "${i.m.title||i.m.slug}" ready — ${d.replaced?"replaced an earlier queued render":"queued after the final response"}.\n`)):d.delivery.catch(()=>{})}(e,i,o(),n))}catch{return null}}const da=(e,t)=>r.join(Hi,e,t);la(Hi,()=>[...Ws.keys()][0]||Xs||[...Ls.keys()][0]);const ua="1"===process.env.TP_FOLLOW,ma=parseInt(process.env.TP_COLS,10)||null,pa=parseInt(process.env.TP_ROWS,10)||null,ha=()=>({cols:ma||(ua?process.stdout.columns||100:Math.min(process.stdout.columns||100,120)),rows:pa||(ua?process.stdout.rows||28:Math.min(process.stdout.rows||28,32))});function fa({id:e,cmd:t,args:r=[],attached:o=!1,cols:n,rows:s}){if(Ls.has(e))return;if(Ls.size>=8)return process.stderr.write(`\n ⚠ can't open "${t}" — terminal cap (8) reached; close one first.\n`),void pi("term-exit",{id:e});if(!Wn)return process.stderr.write(`\n ⚠ can't open "${t}" — node-pty isn't built (PTY mode disabled).\n`),void pi("term-exit",{id:e});const i=Ne(`start the ${t} terminal`);if(!i.ok)return Oi(),process.stderr.write(`\n ⚠ ${i.reason}\n`),void pi("term-exit",{id:e,reason:i.reason});const a=o?ha():null,c=da("terms",e),l=Wn.spawn(t,r,{name:"xterm-256color",cols:n||(o?a.cols:ma||120),rows:s||(o?a.rows:pa||32),cwd:process.cwd(),env:{...process.env,TP_MOCKUP_OUTBOX:c}}),d={term:l,cmd:t,attached:o,scrollback:"",buf:"",lastActionAt:null,mockupWatcher:la(c,()=>e)};return Ls.set(e,d),o&&(Xs=e),l.onData(e=>{o&&process.stdout.write(e),d.buf+=e,d.lastActionAt=Date.now(),d.scrollback=(d.scrollback+e).slice(-12e4)}),l.onExit(()=>{try{d.mockupWatcher?.close()}catch{}Ls.delete(e),Di(e),e===Xs&&(Xs=null,Ja()),Zs||(pi("term-exit",{id:e}),bi(),0!==Ls.size||rs?process.stderr.write(`\n ◇ terminal "${t}" ended — still relaying ${Ls.size} terminal(s). Ctrl-C to stop.\n`):nc())}),bi(),d}const wa=2e3,ga="",va="",ya="",ka="",ba="",$a="",Ta=e=>{const t=e&&(e.command||e.file_path||e.path||e.pattern||e.url||e.query||e.description);return t?" "+String(t).replace(/\s+/g," ").slice(0,100):""};function Ia(e){const t=e=>process.stderr.write(e+"\n");switch(e.kind){case"you":return t(`${ya}❯ ${e.text}${va}${e.by?` ${ga}(${e.by})${va}`:""}`);case"chat":return t(`${ga}${e.by}: ${e.text}${va}`);case"whisper":return t(`${ga}// ${e.by}: ${e.text}${va}`);case"pool":return t(e.pending?`${ya}◌ pool dispatching…${va}`:`${ya}◆ pool → ${e.text}${va}`);case"note":return t(`${ga}— ${e.text} —${va}`);case"clear":return t(`${ga}— context cleared —${va}`);case"usage":{const r=e.ctx;return r?t(`${ga} ctx ${r.pct}% · ${Math.round(r.used/1e3)}k/${Math.round(r.max/1e3)}k${null!=e.costUsd?` · $${e.costUsd.toFixed(3)}`:""}${va}`):void 0}case"error":return t(`${$a}✗ ${e.message}${va}`);case"tool_result":{const r=e.content,o=("string"==typeof r?r:Array.isArray(r)?r.map(e=>e?.text||"").join(" "):"").replace(/\s+/g," ").slice(0,120);return t(` ${e.isError?$a:ga}⎿ ${o||(e.isError?"error":"ok")}${va}`)}case"assistant":for(const r of e.blocks||[])"text"===r.type&&r.text?.trim()?t(`⏺${va} ${r.text.trim()}`):"thinking"===r.type&&r.text?.trim()?t(`${ga}✶ ${r.text.trim().slice(0,160)}${va}`):"tool_use"===r.type&&t(` ${ya}${r.name}${va}${Ta(r.input)}`);return;default:return}}function Ra(e,t){const r=Zo(t);return process.stderr.write(`\n ◇ ${r.message}\n`),e?.id&&(Sa(e,r),pi("code-event",{term:e.id,evt:r})),r}function Sa(e,t){if(!Xo(t).known)return Ra(e,t),null;Qs(e,t),So(t),e.mcpFlight=Qo(e.mcpFlight,t,{now:t.ts}),e.lastActionAt=t.ts,e.lastEvent=t,e.seq&&_o(t)&&(t.seq=e.seq.next()),e.id&&_o(t)&&(po(e.room,e.id,[t]),null==e.archiveOldestSeq&&(e.archiveOldestSeq=t.seq));const r=No(t);for(e.log.push(r),e.logBytes=(e.logBytes||0)+JSON.stringify(r).length+1;e.log.length>wa||e.log.length>1&&e.logBytes>mr;){const t=e.log.shift();e.logBytes-=JSON.stringify(t).length+1}return t}function Ca(e){for(let t=e.length-1;t>=0;t--){const r=e[t]?.kind;if("result"===r||"error"===r||"propose"===r||"pool"===r)return!1;if("assistant"===r||"you"===r||"tool_result"===r)return!0}return!1}function xa(e,t,r=null){const o={kind:"control",text:t,by:r};Sa(e,o),pi("code-event",{term:e.id,evt:o})}function _a(e){const t=Uo(e?.log);return!!t&&(e.pendingCheckpoint=t,!0)}function Aa(e,t={}){if(!e||"codex"!==e.runtime||e.codexCompactionPromise)return!1;const r=async function(e,t={}){const r=Fo(e.log,Lo,{reason:"compact"});if(!r)return void xa(e,"nothing to compact — context unchanged",t.by);const o=e.lastUsage?.ctx?.used||null;pi("code-event",{term:e.id,evt:{kind:"compact",status:"start",ts:Date.now()}});let n=!1;try{n=await(e.session.compactContext?.())}catch{n=null}finally{!e.session.turnActive&&qr(e)&&bi()}if(!0===n){_a(e);const r={kind:"compaction",trigger:"manual",preTokens:o,by:t.by,native:!0};return Sa(e,r),pi("code-event",{term:e.id,evt:r}),pi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),void e.flush?.()}if(null==n)return pi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),xa(e,"Native compaction is still settling; existing context was preserved.",t.by),void e.flush?.();if(!1===e.session.clearContext?.())return pi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),void xa(e,"Codex context compaction unavailable right now",t.by);const s=Bo(r,e.pendingCheckpoint);e.pendingRecap=s.pendingRecap,e.pendingCheckpoint=s.pendingCheckpoint;const i={kind:"compaction",trigger:"manual",preTokens:o,by:t.by};if(Sa(e,i),pi("code-event",{term:e.id,evt:i}),e.lastUsage?.ctx?.max){const t=Math.ceil(r.length/4),o=e.lastUsage.ctx.max,n={kind:"usage",ctx:{...e.lastUsage.ctx,used:t,max:o,pct:Math.min(100,Math.round(t/o*100)),over:t>o}};e.lastUsage=n,pi("code-event",{term:e.id,evt:n})}pi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),e.flush?.()}(e,t);return e.codexCompactionPromise=r,r.finally(()=>{e.codexCompactionPromise===r&&(e.codexCompactionPromise=null)}).catch(()=>{}),!0}const Pa=new Map;function Na(e,t="parent"){const o=r.resolve(e||process.cwd()),n=s("git",["-C",o,"rev-parse","--verify","HEAD^{commit}"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).trim();if(!/^[0-9a-f]{40}$/i.test(n))throw new Error("parent review source has no immutable HEAD");return{taskKey:t,cwd:o,sha:n}}function Oa({id:e,runtime:t="claude",model:o,models:n,effort:i,resume:a,log:l,commands:d,mode:u,spawnedBy:m,spawnDepth:p,cascadeRole:h,hop:f,sideParent:w,sideTask:g,pendingSideContexts:I,pendingWorkerCompletions:_,workerCompletionsInFlight:A,rolePrompt:E,sliceType:D,flowSessionId:j,flowTaskKey:K,flowTaskContract:M,flowRole:U,flowReviewTarget:z,flowReviewTargets:J,flowReviewSnapshots:G,flowReviewRound:Y,flowReviewConclusion:V,dispatchBaseSha:ee,revertTarget:te,cwd:ie,managedWorktree:ae,reviewSliceRoots:ce,openedAt:me,defer:he,provider:fe,carryRecap:ke,carryCheckpoint:Te,lastUsage:Ie,receivedTurnCids:Se,mcpFlight:Ce,scheduleRunId:xe,scheduleDeadlineAt:_e,scheduleOutcomeRecorded:Ae,scheduleAdmissionLease:Oe}){if(Ws.has(e))return;t=le(t)?t:"claude";const Ee=Z({runtime:t,capabilityId:"terminal_interrupt",input:{}});if(!Ee.ok)throw new TypeError(`Structured runtime contract rejected: ${Ee.code}`);u=se(t,{mode:u,sliceType:D,flowRole:U}),u=We.has(u)&&de(t,u)?u:re(t),ut({runtime:t,provider:fe,model:o});const De="codex"===t?H():[],je="codex"===t&&(o||W())||void 0,qe="codex"===t?je?lt(je,De):st({sliceType:"feature",runtime:"codex",catalog:De}):"hermes"===t?o||void 0:O({provider:fe,model:o,configuredModel:R(fe)?.ANTHROPIC_MODEL});i=oe(t,i);const Ke=Number.isInteger(p)&&p>=0?p:w||m&&!String(m).startsWith("flow:")?1:0,Me=Number.isInteger(f)&&f>=0?f:Ke,Ue=Array.isArray(l)?l.slice(-wa):[],Fe=ur(Ue),Be=Ue.length-Fe.length,Le=xe&&!0!==Ae?on(To(Zn,e)):null,He=Le?.runId===xe?Le:null,ze={cmd:t,runtime:t,kind:"structured",log:Fe,pending:new Map,receivedTurnCids:new Set(Array.isArray(Se)?Se.filter(Boolean).slice(-1e3):[]),mcpFlight:Vo(Ce),session:null,recovered:!1,commands:ue(t,d),mode:u,effort:i,models:"codex"===t?De:"hermes"===t?Array.isArray(n)&&n.length?n:Un:void 0,model:"codex"===t||"hermes"===t?qe||null:fe&&"anthropic"!==fe?qe||x()[fe]||fe:qe||null,provider:fe||null,spawnedBy:m||void 0,spawnDepth:Ke,cascadeRole:"conductor"===h||"worker"===h?h:null,hop:Me,sideParent:w||void 0,sideTask:g||void 0,scheduleRunId:xe||null,scheduleDeadlineAt:Number.isFinite(Number(_e))?Number(_e):null,scheduleOutcomeRecorded:!0===Ae,scheduleOutcomePending:He,scheduleAdmissionLease:Oe||null,pendingSideContexts:Array.isArray(I)?I.filter(Boolean).slice(-4):[],pendingWorkerCompletions:Array.isArray(_)?_.filter(e=>e?.workerId&&Number(e?.turnRev)>0).slice(-6):[],workerCompletionsInFlight:Array.isArray(A)?A.filter(e=>e?.workerId&&Number(e?.turnRev)>0).slice(-6):[],flowSessionId:j||null,flowTaskKey:K||null,cwd:ie||null,managedWorktree:ae||null,sliceType:"review"===D?"review":null,flowRole:U||(j?K?J?.length||ce?.length?"reviewer":"builder":"conductor":null),flowReviewTarget:z||null,flowReviewTargets:Array.isArray(J)&&J.length?J.filter(Boolean):z?[z]:[],flowReviewSnapshots:Array.isArray(G)?G.filter(e=>e?.taskKey&&e?.sha&&e?.cwd):[],flowReviewRound:Number.isInteger(Y)&&Y>=0?Y:0,flowReviewConclusion:V?.taskKey&&["pass","reject","surface"].includes(V?.action)&&Bt(V?.receipt)?{taskKey:V.taskKey,action:V.action,round:V.round,receipt:V.receipt}:null,dispatchBaseSha:ee||null,revertTarget:te||null,openedAt:me||Array.isArray(l)&&l.find(e=>e?.ts)?.ts||Date.now(),snapshotNeedsCompaction:Be>0||Fe.some((e,t)=>e!==Ue[t+Be]),logBytes:Fe.reduce((e,t)=>e+JSON.stringify(t).length+1,0)};ze._turnRev=ze.log.reduce((e,t)=>Math.max(e,Number(t?.turnRev)||0),0);const Je=[...ze.log].reverse().find(e=>"result"===e?.kind&&Number(e?.turnRev)>0);ze._settledTurnRev=Number(Je?.turnRev)||null,ze._turnSettledAt=Number(Je?.ts)||null,ze.interruptedRecap=Ca(ze.log)?Fo(ze.log,Lo):null,ze.workerCompletionsInFlight.length&&!ze.interruptedRecap&&(ze.workerCompletionsInFlight=[]),ze.permNotifier=v({onArm:(t,r)=>qs({kind:"needs-input",term:e,termName:fi[e]||null,model:ze.model||null,permissionId:t,summary:r,pushEligible:!1}),onFire:(t,r)=>qs({kind:"needs-input",term:e,termName:fi[e]||null,model:ze.model||null,permissionId:t,summary:r,pushEligible:!0}),onResolve:t=>qs({kind:"needs-resolved",term:e,termName:fi[e]||null,model:ze.model||null,permissionId:t})}),ze.seq=Co(xo(ze.log)),ze.rolePrompt=E||null,ze.flowTaskContract=M&&"object"==typeof M?M:null,ze.lastUsage=Ie||null,ze.reviewSliceRoots=Array.isArray(ce)?ce.filter(Boolean):[];const Ge=async({reviewPass:t=!1,baselineEvidence:r=""}={})=>{if(!ze.flowSessionId||!ze.flowTaskKey)return"Not a Dispatch lane — nothing to mark done.";if("builder"!==ze.flowRole&&(!t||"reviewer"!==ze.flowRole))return"This Dispatch role cannot mark a builder slice done.";if(ze.flowDone)return"This slice is already recorded as done.";let o="";const n=!t&&!!ze.flowTaskContract?.baseline?.gate;if(n)try{o=Ze(r)}catch(e){return`Slice "${ze.flowTaskKey}" is not done: submit the real bounded baselineEvidence receipt (${e?.message||e}). Observe the assigned pre-edit gate; do not fabricate a RED sentence.`}let i=null;try{i=s("git",["-C",ze.cwd||process.cwd(),"rev-parse","HEAD"],{encoding:"utf8"}).trim()}catch{}if(!t&&ze.dispatchBaseSha&&i===ze.dispatchBaseSha)return`Slice "${ze.flowTaskKey}" is not done: HEAD is still the dispatch base (${i.slice(0,8)}). Commit the verified implementation first.`;if(!t){const e=(e=>{try{return s("git",["-C",e,"status","--porcelain=v1","--untracked-files=all"],{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).split("\n").map(e=>e.trim()).filter(Boolean)}catch{return null}})(ze.cwd||process.cwd());if(null==e)return`Slice "${ze.flowTaskKey}" is not done: the bridge could not verify a clean worktree.`;if(e.length)return`Slice "${ze.flowTaskKey}" is not done: commit or remove every remaining worktree change before completion (${e.slice(0,4).join(", ")}).`}let a=null;if(!t&&ze.flowTaskContract?.scopePaths?.length){const e=gr(ze.cwd||process.cwd(),ze.dispatchBaseSha,i);if(!e)return`Slice "${ze.flowTaskKey}" is not done: the bridge could not derive its Git scope footprint.`;if(a=Lt({log:ze.log,repoRoot:ze.cwd||process.cwd(),declared:ze.flowTaskContract.scopePaths,changed:e}),!a.held)return`Slice "${ze.flowTaskKey}" is not done: scope drift detected in ${a.unexpected.join(", ")}. The approved scope must be amended before these files can ship.`}let c=null;try{c=(await vt({dir:ze.cwd||process.cwd(),id:`lane:${ze.flowSessionId}:${e}`})).url}catch{}try{const t=ze.cwd||process.cwd(),r=mt(ze.flowSessionId,ze.flowTaskKey,"_slice.done",JSON.stringify({taskKey:ze.flowTaskKey,commitSha:i||null,previewUrl:c||null}),{worktreeDir:t}),n=ft(ze.flowSessionId,{worktreeDir:t}),s=[{taskKey:ze.flowTaskKey,name:"_slice.done",path:r.path,sha:r.sha},...n.map(e=>({taskKey:e.taskKey,name:e.name,path:e.path,sha:e.sha}))],a=pt({key:ze.flowTaskKey,title:fi[e]||ze.flowTaskKey},{acceptanceProof:`${o?`baseline: ${o}; `:""}${i?`committed ${i.slice(0,8)}`:"slice done"}`,artifacts:s});ht(ze.flowSessionId,a,{baseDir:process.cwd()})}catch(e){process.stderr.write(`\n ${ga}◆ flow digest skip ${ze.flowTaskKey} — ${e?.message||e}${va}\n`)}const l=n?{...ze.flowTaskContract,baseline:{...ze.flowTaskContract.baseline,evidence:o},...a?{scopeEvidence:a}:{}}:ze.flowTaskContract?{...ze.flowTaskContract,...a?{scopeEvidence:a}:{}}:null;return pi("flow-task-done",{term:e,flowId:ze.flowSessionId,taskKey:ze.flowTaskKey,laneId:e,commitSha:i,previewUrl:c,contract:l,...t?{reviewAction:"pass"}:{}},Us),process.stderr.write(`\n ${ya}◆ flow slice done — ${ze.flowTaskKey} (${i?i.slice(0,8):"no commit"})${c?` · preview ${c}`:""}${va}\n`),ze.flowDone=!0,setTimeout(()=>{try{Ba(e)}catch{}},2500),`Slice "${ze.flowTaskKey}" recorded as DONE${i?` (commit ${i.slice(0,8)})`:""}${c?`. Live preview: ${c}`:""}. The room dispatches dependent slices + assembles when all are done. You are finished — stop here.`};ze.markFlowDone=Ge;const Ve=Ft(),Qe=async t=>ze.flowReviewConclusion?{ok:!0,message:`Review already concluded for ${ze.flowReviewConclusion.taskKey}; receipt ${ze.flowReviewConclusion.receipt.cid||"recorded"}.`}:Ve(()=>(async t=>{if(!ze.flowSessionId||!ze.flowTaskKey||"reviewer"!==ze.flowRole)return{ok:!1,message:"Not a Dispatch review lane."};let r,o=null;try{r=Kt(t);const e="string"==typeof t?JSON.parse(String(t).replace(/```(?:json)?|```/g,"").trim()):t,n=e&&(e.taskKey||e.target),s=ze.flowReviewTargets;if(!s.length)throw new Error("review lane has no authorized target");if("codex"===ze.runtime&&1!==s.length)throw new Error("Codex review lane must have exactly one authorized target");if(n&&!s.includes(n))throw new Error(`taskKey ${JSON.stringify(n)} is outside this review lane`);if(o=n||(1===s.length?s[0]:null),!o)throw new Error("taskKey is required when reviewing more than one slice")}catch(e){return{ok:!1,message:"codex"===ze.runtime?`Review verdict REJECTED: ${e?.message||e}. Re-call submit_flow_review with a valid authorized taskKey.`:`Review verdict REJECTED: ${e?.message||e}. Re-Write FLOW_REVIEW.json with {"pass":<boolean>,"reasons":["<specific finding>"],"taskKey":"<the slice you reviewed>"}.`}}if(ze.flowReviewConclusion)return{ok:!0,message:`Review already concluded for ${ze.flowReviewConclusion.taskKey}; receipt ${ze.flowReviewConclusion.receipt.cid||"recorded"}.`};const n=ze.flowReviewRound=(ze.flowReviewRound||0)+1;ze.flush?.();const s=wr.get(ze.flowSessionId)||null,i=Zt({round:n,maxRounds:er.maxRounds,spentTokens:s?s.spentTokens:0,budgetCap:s?s.capTokens:null,...Mt(r)});if(!i.stop){const e=n+1;return Gs(ze,"codex"===ze.runtime?`[Dispatch review — round ${e}/${er.maxRounds}] The happy path held, but you have NOT reported your checks exhausted. Dig one more round, then call submit_flow_review again — pass:false with specific evidence if you break it, or pass:true AND exhausted:true only when nothing remains to check.`:`[Dispatch review — round ${e}/${er.maxRounds}] The happy path held, but you have NOT reported your checks exhausted and you are under both the round and budget ceilings. Dig one more round: hunt the edge cases, the reload, the second click, concurrent use, the error path — the places the builder didn't. Then re-Write FLOW_REVIEW.json — pass:false with a specific reason if you break it, or pass:true AND exhausted:true if you genuinely have nothing left to check.`,{rejectionMessage:"The next Dispatch review round was not accepted; retry after the lane is available."}),process.stderr.write(`\n ${ga}◆ review round ${n} inconclusive — digging again (${e}/${er.maxRounds}) on ${o||ze.flowTaskKey}${va}\n`),{ok:!0,message:`Round ${n} recorded (pass, not yet exhausted). Keep hunting — asked you for round ${e}/${er.maxRounds}.`}}if("reject"===i.action&&o){const t=await Va({term:e,flowId:ze.flowSessionId,taskKey:o,reviewTaskKey:ze.flowTaskKey});t.ok||qs({kind:"needs-input",term:e,termName:fi[e]||null,summary:`Dispatch review could not revert ${o}: ${t.error||t.ignored||"unknown error"}`}),process.stderr.write(`\n ${ba}◆ review REJECT (round ${n}) — reverting ${o}: ${r.reasons.join("; ").slice(0,120)}${va}\n`)}else process.stderr.write(`\n ${ya}◆ review ${i.action.toUpperCase()} (round ${n}) — ${o||ze.flowTaskKey}${va}\n`);const a=o||ze.flowTaskKey,l=ze.flowReviewSnapshots.find(e=>e.taskKey===a)||null,d=ze.flowTaskContract?.digest||null;let u,m=i.action,p=r.reasons.length?r.reasons:[i.reason];try{u=Ut({taskKey:a,outcome:"surface"===m?"held":m,rounds:n,candidateSha:l?.sha,acceptanceDigest:d,scope:l?.scopeEvidence,reasons:p})}catch(e){if("pass"!==m)return{ok:!1,message:`Review verdict REJECTED: ${e?.message||e}.`};m="surface",p=[...p,"Exact candidate or sealed acceptance proof is missing; pass was held."],u=Ut({taskKey:a,outcome:"held",rounds:n,candidateSha:l?.sha,acceptanceDigest:d,scope:l?.scopeEvidence,reasons:p})}u.cid=c(),ze.flowReviewConclusion={taskKey:a,action:m,round:n,receipt:u},ze.flush?.(),Sa(ze,u),pi("code-event",{term:e,evt:u}),ze.flush?.(),pi("flow-review-verdict",{term:e,flowId:ze.flowSessionId,taskKey:a,pass:"pass"===m,reasons:p,action:m,rounds:n,surfaceToPair:"surface"===m||i.surfaceToPair,prompt:Xt({action:m,reason:m===i.action?i.reason:p.at(-1),taskKey:a,findings:p})},Us);let h="";return"pass"===m?h=await Ge({reviewPass:!0}):("surface"===m&&(pi("flow-review-held",{term:e,flowId:ze.flowSessionId,reviewTaskKey:ze.flowTaskKey,taskKey:o,reasons:p},Us),qs({eventId:u.cid,kind:"needs-input",term:e,termName:fi[e]||null,summary:`Dispatch review held ${a}: ${p.join("; ")||i.reason}`})),"reject"===m&&(ze.flowDone=!0,ze.flush?.(),setTimeout(()=>{try{Ba(e)}catch{}},2500))),{ok:!0,message:`Review verdict recorded: ${"reject"===m?`REJECT (round ${n}) — reverting ${o||"(no target)"} (${p.join("; ").slice(0,140)})`:"surface"===m?`SURFACED to the pair after ${n} round${1===n?"":"s"} — ${p.at(-1)||i.reason}`:`PASS (round ${n})`}.${h?` ${h}`:""}`}})(t));if(ze.id=e,ze.room=Zn,ho(Zn,e,ze.log.filter(e=>_o(e))),ze.archiveOldestSeq=wo(Zn,e),Ws.set(e,ze),ze.scheduleOutcomePending?ea(ze):ra(ze),ze.log.length&&Ca(ze.log)){const t={kind:"result",subtype:"aborted",recovered:!0};So(t),Sa(ze,t),process.stderr.write(`\n ◆ closed an interrupted turn on resume (${e.slice(0,8)}) — restored idle.\n`)}const rt=da("sessions",e);ze.mockupWatcher=la(rt,()=>e,!0);const ot=Pt(rt,ie||process.cwd(),e);for(const e of ot)Ji.set(e.previewId,e);ot.length&&process.stderr.write(`\n ◆ restored ${ot.length} thinkpool Design artifact${1===ot.length?"":"s"} (${e.slice(0,8)}).\n`),ze.viewport=new bt({workspaceRoot:ie||process.cwd(),ownerId:e,roomCode:Zn,outbox:rt,authContext:()=>({accessToken:Ln,supabaseUrl:qn}),designContext:()=>{const t=Yi.get(e);return t&&"preview"===t.record.sourceKind?{requestId:t.request.cid,parentRevision:t.record.revision,captureKey:t.record.captureKey}:null}}),ze.log.length&&process.stderr.write(`\n ◆ restored ${ze.log.length} prior events (${e.slice(0,8)})${a?" + resuming live context":""}.\n`);const nt=()=>({sessionId:ze.session?.sessionId||null,runtime:ze.runtime,log:ze.log,commands:ze.commands,mode:ze.mode,effort:ze.effort,model:ze.model||null,models:"hermes"===ze.runtime?ze.models||[]:void 0,provider:ze.provider||null,spawnedBy:ze.spawnedBy,spawnDepth:ze.spawnDepth||0,cascadeRole:ze.cascadeRole||null,hop:ze.hop||0,sideParent:ze.sideParent,sideTask:ze.sideTask,scheduleRunId:ze.scheduleRunId||null,scheduleDeadlineAt:ze.scheduleDeadlineAt||null,scheduleOutcomeRecorded:!0===ze.scheduleOutcomeRecorded,scheduleAdmissionLease:ze.scheduleAdmissionLease||null,pendingSideContexts:ze.pendingSideContexts,pendingWorkerCompletions:ze.pendingWorkerCompletions,workerCompletionsInFlight:ze.workerCompletionsInFlight,sliceType:ze.sliceType,flowSessionId:ze.flowSessionId,flowTaskKey:ze.flowTaskKey,flowTaskContract:ze.flowTaskContract,flowRole:ze.flowRole||null,flowReviewTargets:ze.flowReviewTargets||[],flowReviewSnapshots:ze.flowReviewSnapshots||[],flowReviewRound:ze.flowReviewRound||0,flowReviewConclusion:ze.flowReviewConclusion,dispatchBaseSha:ze.dispatchBaseSha||null,cwd:ze.cwd,managedWorktree:ze.managedWorktree,rolePrompt:ze.rolePrompt,flowReviewTarget:ze.flowReviewTarget||null,revertTarget:ze.revertTarget||null,reviewSliceRoots:ze.reviewSliceRoots||[],openedAt:ze.openedAt||null,lastUsage:ze.lastUsage||null,carryRecap:ze.pendingRecap||null,carryCheckpoint:ze.pendingCheckpoint||null,receivedTurnCids:[...ze.receivedTurnCids].slice(-1e3),mcpFlight:ze.mcpFlight}),it=()=>ro(Zn,e,nt());if(ze.flush=()=>oo(Zn,e,nt()),ze.flowReviewConclusion?.receipt&&!ze.log.some(e=>e?.cid===ze.flowReviewConclusion.receipt.cid)){const t={...ze.flowReviewConclusion.receipt};Sa(ze,t),pi("code-event",{term:e,evt:t}),ze.flush()}ze.scheduleOutcomeRecorded&&ze.scheduleAdmissionLease&&Zi(ze).then(e=>{e&&ze.flush?.()});const wt=!ze.spawnedBy&&!ze.sideParent&&!ze.flowRole&&0===(ze.spawnDepth||0),gt=wt&&"conductor"!==ze.cascadeRole,yt=wt,kt=()=>P().filter(e=>"anthropic"!==e.id).map(e=>`${e.name}${e.model?` (${e.model})`:""}`).join(", "),Tt=(e,{worker:t=!1}={})=>{const r=e?.runtime||ze.runtime||"claude";if("codex"===r&&e?.provider)return{error:"A Codex terminal uses its Codex/OpenAI login in v1; custom bridge providers are not wired to Codex yet. Omit provider or open a Claude terminal for that provider."};if("hermes"===r&&e?.provider)return{error:"A Hermes terminal uses its isolated Hermes profile and ACP model catalog; bridge provider IDs do not apply. Omit provider and choose an exact Hermes model ID."};const o="hermes"===ze.runtime&&ze.models?.length?ze.models:[...Ws.values()].flatMap(e=>"hermes"===e.runtime&&e.models||[]),n="codex"===r?H():"hermes"===r?o:[];if("codex"===r&&e?.model&&!ct(n).has(e.model))return{error:`Could not open a Codex terminal on ${JSON.stringify(e.model)} — that model is not in this host's visible Codex catalog.`};const s="hermes"===r?dt(e?.model,n,{strictCatalog:"hermes"===ze.runtime}):null;if(s&&!s.ok)return{error:s.error};const i="claude"===r&&e?.provider?S(e.provider):e?.provider;if("claude"===r&&e?.provider&&!i){const t=kt();return{error:`Unknown registered provider ${JSON.stringify(e.provider)}. No lane was opened and the built-in Claude login was not used.${t?` Available provider names: ${t}.`:" No custom providers are registered on this host."}`}}return"claude"===r&&!e?.provider&&e?.model&&/^gpt-/i.test(e.model)?{error:`Could not open a Claude terminal on Codex model ${JSON.stringify(e.model)}. Choose runtime="codex" or a Claude model.`}:{runtime:r,model:s?.model||e?.model||(t&&e?.sliceType?at({sliceType:e.sliceType,runtime:r,catalog:n}):void 0),mode:t?"bypassPermissions":e?.mode||("plan"===ze.mode?"default":ze.mode),provider:i}},It=(e=Date.now())=>({runtime:ze.runtime,mode:ze.mode,hop:ze.hop||0,spawnTimes:ze.spawnTimes||[],now:e,spawnedLive:Lr(Ws.values()),totalLive:Ws.size+Ls.size,plan:As,disabled:"1"===process.env.TP_SPAWN_OFF}),Rt=r=>new Promise(o=>{if(ze.flowSessionId&&"plan"===r.risk)return pi("flow-plan",{term:e,flowId:ze.flowSessionId,plan:r.plan||""},Us),process.stderr.write(`\n ${ka}◆ flow plan ready — flow ${String(ze.flowSessionId).slice(0,8)}.${va}\n`),void o("keep");const n=Fi(ze,{term:e,id:r.id,toolName:r.toolName,input:r.input,risk:r.risk,plan:r.plan,questions:r.questions,asker:r.asker,answerFormat:r.answerFormat,autoResolutionMs:r.autoResolutionMs}),s={resolve:o,payload:n,timer:null};ze.pending.set(r.id,s),bi(),pi("code-perm-req",n),T(ze)&&ze.permNotifier?.arm(r.id,b(n)),process.stderr.write("plan"===r.risk?`\n ${ka}◆ plan ready — approve in the room.${va}\n`:"ask"===r.risk?`\n ${ya}● ${r.asker||le(t)?.label||"Agent"} is asking: ${(r.questions||[]).map(e=>e.question).join(" / ").slice(0,100)} — answer in the room.${va}\n`:`\n ${ba}● permission: ${r.toolName}${Ta(r.input)} — approve in the room.${va}\n`);const i=Number(r.autoResolutionMs);"ask"===r.risk&&Number.isFinite(i)&&i>0&&(s.timer=setTimeout(()=>{if(ze.pending.get(r.id)===s){ze.pending.delete(r.id),ze.permNotifier?.resolve(r.id),pi("code-perm",{term:e,id:r.id,decision:"timeout",name:r.asker||"agent"});try{o(Ea(s,{decision:"timeout",answers:{}}))}catch{}bi()}},i),s.timer.unref?.())}),St=Q(()=>{const r=F({name:"thinkpool",version:"1.0.0",tools:[...ze.flowRole||"review"===ze.sliceType?[]:[B("read_mcp_flight_recorder","Read the privacy-filtered MCP flight recorder for THIS terminal. Use it to diagnose a tool path or audit recent MCP activity. It reports only tool identity, timing, outcome, byte counts, and coarse token estimates; it never records or returns arguments, result bodies, prompts, secrets, or host paths.",{limit:L.number().int().min(1).max(100).optional().describe("maximum recent calls to return (default 40)")},async e=>({content:[{type:"text",text:Yo(ze.mcpFlight,{limit:e?.limit})}]}))],..."hermes"===t&&"ordinary"===$e({flowRole:ze.flowRole,sliceType:ze.sliceType})?[B("request_user_input","Ask the people in this thinkpool room one to three multiple-choice questions and wait for their answer. Use this for choices that genuinely block useful progress. Each question needs two or three mutually exclusive options; a free-text answer remains available in the room card.",{questions:L.array(L.object({id:L.string().min(1).max(80),header:L.string().min(1).max(12),question:L.string().min(1).max(500),options:L.array(L.object({label:L.string().min(1).max(80),description:L.string().min(1).max(240)})).min(2).max(3),multiSelect:L.boolean().optional(),isSecret:L.boolean().optional()})).min(1).max(3),autoResolutionMs:L.number().int().min(6e4).max(24e4).optional()},async e=>{const t=e.questions.map(e=>({...e,options:e.options.map(e=>({...e}))})),r=await Rt({id:`hermes-question:${c()}`,toolName:"AskUserQuestion",input:{questions:t},risk:"ask",questions:t,asker:"Hermes",answerFormat:"hermes",autoResolutionMs:e.autoResolutionMs});return{content:[{type:"text",text:JSON.stringify(Pe(r,t))}]}})]:[],...$t({tool:B,z:L,manager:ze.viewport}),B("read_terminal","Read-only view of ANOTHER terminal in this thinkpool Code room (a sibling agent or a shell the people are using). The current ROOM NOW snapshot is the default roster. Call with no arguments only when that snapshot is missing or truncated; this optional full-roster lookup has its own one-call allowance. Call with `terminal` (a ref, id, name, or command) only when that lane’s detailed activity is needed. Targeted transcript reads have a separate bounded allowance: never poll, collect each finished owned worker once, then close it immediately.",{terminal:L.string().optional().describe("ref, id, or command of the terminal to read; omit to list the open terminals"),lines:L.number().int().positive().max(yr.maxLines).optional().describe(`how many recent lines to return (default ${yr.defaultLines})`)},async t=>{const r=br({selfId:e,sessions:Ws,terms:Ls,names:fi}),o=t?.terminal?$r(r,t.terminal):null;if(t?.terminal&&!o)return{content:[{type:"text",text:vr({selfId:e,sessions:Ws,terms:Ls,names:fi,terminal:t.terminal,lines:t?.lines})}]};const n=kr({targeted:!!t?.terminal,targetedCount:ze.peekCount,rosterCount:ze.peekRosterCount,budgetTurnRev:ze.peekBudgetTurnRev,currentTurnRev:ze._turnRev});if(ze.peekCount=n.targetedCount,ze.peekRosterCount=n.rosterCount,ze.peekBudgetTurnRev=n.budgetTurnRev,!n.ok)return{content:[{type:"text",text:n.reason}]};const s="agent"===o?.kind?Ws.get(o.id):null;return{content:[{type:"text",text:vr({selfId:e,sessions:Ws,terms:Ls,names:fi,terminal:t?.terminal,lines:t?.lines})+Kr({parentRuntime:ze.runtime,parentModels:ze.models,targetRuntime:s?.runtime,targetLog:s?.log})}]}}),...ze.flowRole?[]:[B("search_past_work","Search bounded saved terminal work from THIS thinkpool room. Returns privacy-filtered excerpts for prior decisions, failed attempts, commands, checks, and Dispatch receipts. Every hit cites the room, terminal, date, and event sequence. It never searches another room, exposes prompts or host paths, or changes state.",{query:L.string().min(2).max(160).describe("specific terms from the prior decision, failure, command, check, or feature"),limit:L.number().int().min(1).max(8).optional().describe("maximum cited hits; default 8")},async e=>{if(ze.pastWorkSearchTurnRev!==ze._turnRev&&(ze.pastWorkSearchTurnRev=ze._turnRev,ze.pastWorkSearchCount=0),(ze.pastWorkSearchCount||0)>=3)return{content:[{type:"text",text:"Past-work search limit reached for this turn (3). Use the cited results already returned or narrow the next room turn."}]};ze.pastWorkSearchCount=(ze.pastWorkSearchCount||0)+1;const t=new Map;for(const e of io(Zn,40))e?.id&&Array.isArray(e.log)&&t.set(e.id,{id:e.id,name:fi[e.id]||e.name||"Archived terminal",savedAt:e.savedAt||e._archivedAt,log:e.log});for(const[e,r]of Ws)t.set(e,{id:e,name:fi[e]||`Terminal ${String(e).slice(0,8)}`,savedAt:r.openedAt||Date.now(),log:r.log||[]});let r;try{r=zt([...t.values()],e?.query||"",{room:Zn,limit:e?.limit})}catch(e){return{content:[{type:"text",text:`Past-work search rejected: ${e?.message||e}`}]}}return{content:[{type:"text",text:Ht(r,e?.query||"")}]}})],B("list_sessions","List OTHER thinkpool Code sessions (rooms) reachable from this room: your own rooms on this machine plus your partner's shared rooms over the pair bus. Returns each room's code, name, and partner host when remote so you can read into one with read_session. This is thinkpool Ensemble across SESSIONS, not just terminals. Read-only.",{},async()=>{const e=e=>({content:[{type:"text",text:e}]});if(ze.pairPeekCount=(ze.pairPeekCount||0)+1,ze.pairPeekCount>Cr.peekPerTurnCap)return e(`Cross-session read limit reached for this turn (${Cr.peekPerTurnCap}). Continue with what you have.`);const t=await Ui("pair-list-req",{});return e(_r(t?.rooms,{thisRoom:Zn,error:t?.error}))}),B("read_session","Read-only view INTO another thinkpool Code session returned by list_sessions—either your own room on this machine or your partner's shared room over the pair bus. The authorized durable cloud transcript takes over when the partner bridge is offline. Pass `session` (the room code) and optionally `terminal` (a ref/name in that room) to read its recent activity; omit `terminal` to list that room's terminals. It never changes the other session.",{session:L.string().describe("the room code of the other session (from list_sessions)"),terminal:L.string().optional().describe("ref, id, or name of a terminal in that room; omit to list that room's terminals"),lines:L.number().int().positive().max(yr.maxLines).optional().describe(`how many recent lines to return (default ${yr.defaultLines})`)},async e=>{const t=e=>({content:[{type:"text",text:e}]}),r=String(e?.session||"").toUpperCase().trim();if(!r)return t("Name a room code to read (call list_sessions to see them).");if(r===Zn)return t("That is this room — use read_terminal for terminals in your own room.");if(ze.pairPeekCount=(ze.pairPeekCount||0)+1,ze.pairPeekCount>Cr.peekPerTurnCap)return t(`Cross-session read limit reached for this turn (${Cr.peekPerTurnCap}). Continue with what you have.`);const o=await Ui("pair-peek-req",{targetRoom:r,terminal:e?.terminal,lines:e?.lines},xr.busTimeoutMs+2e3);return t(o?.error?o.error:o?.text||`Room ${r} returned nothing.`)}),...ze.flowRole?[]:[B("post_to_session","Hand a task or message to an agent in ANOTHER of your thinkpool Code sessions — your own room on this machine, or your partner's room reachable through the pair (a room code from list_sessions). Pass `session` (the room code), `text` (what to send), and optionally `terminal` (which agent lane in that room). A person in YOUR room approves sending AND a person in the TARGET room approves receiving before it is delivered. An agent reached this way cannot post onward to a third room. Read the target with read_session first, and use this sparingly — only when the people clearly want the rooms to coordinate.",{session:L.string().describe("the room code of the other session (from list_sessions)"),text:L.string().describe("the message or task to deliver to that room's agent"),terminal:L.string().optional().describe("ref/name of the agent lane in that room; omit if it has a single agent")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=Ar({roomHop:ze.roomHop||0,postCount:ze.crossRoomPostCount||0,disabled:"1"===process.env.TP_PAIRBUS_OFF});if(!o.ok)return r(o.reason);const n=String(t?.session||"").toUpperCase().trim();if(!n)return r("Name a room code to post to (call list_sessions to see your rooms).");if(n===Zn)return r("That is this room — use post_to_terminal for an agent in your own room.");const s=String(t?.text||"").trim();if(!s)return r("Nothing to send — provide the task or message text.");ze.crossRoomPostCount=(ze.crossRoomPostCount||0)+1;const i=await Ui("pair-post-req",{targetRoom:n,terminal:t?.terminal,text:s,fromRoom:Zn,fromTerminalName:fi[e]||void 0},18e4);return r(i?.error?i.error:i?.ok?`Delivered to room ${n}${i.ref?` (lane ${i.ref})`:""} — it will respond in its own room; check back with read_session.`:`Room ${n} did not accept the message.`)})],...ze.flowRole?[]:[B("post_to_terminal","Send a message or task to ANOTHER AGENT terminal in this thinkpool Code room. Use `terminal` (a ref/id/command from read_terminal) and `text` (what to send). A person in the room must approve before it is delivered, and an agent reached via a cross-post cannot post onward. Targets agent terminals only, not plain shells. Use read_terminal first to understand the sibling.",{terminal:L.string().describe("ref, id, or command of the AGENT terminal to send to (from read_terminal)"),text:L.string().describe("the message or task to deliver to that terminal")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=Tr({hop:ze.hop||0,postCount:ze.postCount||0,disabled:"1"===process.env.TP_CROSSPOST_OFF});if(!o.ok)return r(o.reason);const n=br({selfId:e,sessions:Ws,terms:Ls,names:fi}),s=$r(n,t?.terminal);if(!s)return r(`No terminal matches "${t?.terminal}". Call read_terminal with no argument to list the open terminals.`);if("agent"!==s.kind)return r(`Terminal ${s.ref} is a shell, not an agent — cross-posting is only allowed to agent terminals.`);const i=Ws.get(s.id);if(!i?.session)return r(`Terminal ${s.ref} is no longer live.`);if(!t?.text||!String(t.text).trim())return r("Nothing to send — provide a non-empty `text` for the post.");const a=await ji(i);if(!a.ok)return r(a.reason||`The host cannot start terminal ${s.ref} yet.`);ze.postCount=(ze.postCount||0)+1;const c=String(e).slice(0,8),l=`[From: terminal ${c}'s agent — relayed via thinkpool cross-terminal, approved by a person in the room]\n${t.text}`;i.hop=(ze.hop||0)+1,i.peekCount=0,i.peekRosterCount=0,i.postCount=0;const d={kind:"you",text:l,by:`terminal ${c} (agent)`,crosspost:!0,relaySourceName:fi[e]||void 0};Ii(s.id,t.text);const u=Gs(i,l,{visibleEvent:d,rejectionMessage:"The cross-terminal task was not accepted; retry after the lane is available."});return u.accepted?r(`Delivered to terminal ${s.ref} (${s.cmd}). It will respond in its own lane; check back with read_terminal.`):(qi(i,a),r(u.error?`Could not deliver to terminal ${s.ref} — it may have just closed.`:`Could not deliver to terminal ${s.ref} — it refused the turn. Check its visible host-memory/runtime error.`))})],...gt?[B("open_main_terminal","Open a separate independent MAIN terminal on any supported runtime: Claude (including a connected Anthropic-compatible BYOK provider), Codex, or Hermes. Use this whenever a person asks to open, launch, start, spawn, or create a new, separate, independent, top-level, or main terminal—even for ordinary work or a handoff and even without the words Cascade or conductor. If the wording includes new or separate terminal, main-terminal routing wins. This is the top-level room lifecycle, NOT Ensemble dispatch: the new terminal has no spawnedBy owner and appears as a main terminal. Never substitute spawn_terminal, which creates worker sub-terminals only. Give the main terminal its full initial task; it can use spawn_terminal for bounded workers.",{name:L.string().max(80).optional().describe('short label for the main conductor, e.g. "Cascade · Multi-device chaos"'),task:L.string().min(1).describe("complete initial brief for the independent main terminal"),model:L.string().optional().describe("optional main-terminal model, e.g. opus / gpt-5.6-sol / nous:z-ai/glm-5.2"),runtime:L.enum(["claude","codex","hermes"]).optional().describe("agent runtime; every top-level terminal can open every supported runtime, defaulting to its own"),provider:L.string().optional().describe("optional registered Claude-compatible provider name or id; omit for built-in Anthropic"+(kt()?`. Available now: ${kt()}`:"")),mode:L.enum(["default","acceptEdits","bypassPermissions","plan"]).optional().describe("permission mode; defaults to inheriting this main terminal, except plan falls back to default")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=Tt(t);if(o.error)return r(o.error);const n=Ne("start another Cascade conductor");if(!n.ok)return Oi(),r(n.reason);const s=(()=>{const e=Date.now(),t=Rr({hop:0,spawnTimes:ze.spawnTimes||[],now:e,spawnedLive:0,totalLive:Ws.size+Ls.size,plan:As,disabled:"1"===process.env.TP_SPAWN_OFF});return t.ok?(ze.spawnTimes=[...(ze.spawnTimes||[]).filter(t=>Number.isFinite(t)&&t>e-Sr.windowMs),e],t):t})();if(!s.ok)return r(s.reason);const i=c(),a=await Ei(i);if(!a.ok)return r(a.reason||"The bridge machine cannot accept another live lane yet.");const l=String(i).slice(0,8),d=String(e).slice(0,8);t?.name&&(fi[i]=String(t.name).slice(0,80),mo(Zn,fi)),Oa({id:i,runtime:o.runtime,model:o.model,provider:o.provider,mode:o.mode,spawnDepth:0,cascadeRole:"conductor",hop:0});const u=Ws.get(i);if(!u)return Di(i),t?.name&&(delete fi[i],mo(Zn,fi)),r("Could not open the main conductor terminal — the machine terminal cap may have just been reached.");u.peekCount=0,u.peekRosterCount=0,u.postCount=0,u.spawnTimes=[],bi();const m=`[Task from main terminal ${d}'s agent — opened as an independent MAIN CASCADE CONDUCTOR terminal, not an Ensemble child]\n${String(t.task).trim()}`,p={kind:"you",text:m,by:`main terminal ${d} (agent)`,crosspost:!0,relaySourceName:fi[e]||void 0};Ii(i,t.task);const h=Gs(u,m,{visibleEvent:p,rejectionMessage:"The initial conductor task was not accepted; retry after the lane is available."});return h.accepted?r(`Opened independent main Cascade conductor ${l}${t?.name?` ("${t.name}")`:""} and handed it the task. It is a main terminal, not an Ensemble lane.`):r(h.error?`Opened main conductor ${l}${t?.name?` ("${t.name}")`:""}, but it may still be starting — the initial task could not be delivered.`:`Opened main conductor ${l}, but host pressure prevented its runtime from starting. Existing lanes remain connected; free memory and retry the task.`)})]:[],...yt?[B("spawn_terminal","Open a visible WORKER SUB-TERMINAL on any supported runtime—Claude (including a connected Anthropic-compatible BYOK provider), Codex, or Hermes—from any top-level terminal. spawn_terminal is worker-only: it can never create a Cascade conductor or main terminal. For ordinary workers use an appropriate non-Sol tier: gpt-5.6-luna or gpt-5.4-mini for scaffold/search, gpt-5.6-terra for feature/fix, and a balanced tier for adversarial review; never select Sol for routine workers. A Hermes sliceType=review lane is structurally reviewer-scoped before ACP startup: it can inspect files and use the bridge review-check tool, but has no terminal, write, patch, delegate, browser, skill, memory, or session-history schema. Pass sliceType=scaffold for mechanical work, feature/fix for builders, and review for adversarial verification. Give the worker a bounded initial task, collect its result with read_terminal, then ALWAYS close_terminal it.",{name:L.string().max(80).optional().describe('a short label for the new lane so the room (and you) can find it, e.g. "Research: topologies"'),task:L.string().optional().describe("an initial task to hand the new lane immediately; omit to open it idle"),model:L.string().optional().describe("model for the chosen runtime; Hermes accepts its profile default or an ACP ID such as nous:z-ai/glm-5.2"),sliceType:L.enum(["scaffold","feature","fix","review"]).optional().describe("optional cascade slice tier; omitted preserves normal inheritance/default, explicit model wins"),runtime:L.enum(["claude","codex","hermes"]).optional().describe("agent runtime for the new lane; every top-level terminal can open every supported runtime"),provider:L.string().optional().describe("optional registered Claude-compatible provider name or id; omit for built-in Anthropic"+(kt()?`. Available now: ${kt()}`:"")),mode:L.enum(["default","acceptEdits","bypassPermissions","plan"]).optional().describe("accepted for compatibility; spawned workers always run autonomously in bypassPermissions")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=Tt(t,{worker:!0});if(o.error)return r(o.error);const n=Date.now(),s=It(n),i=Rr(s);if(!i.ok)return r(i.reason+Nr(e,[...Ws.entries()].map(([e,t])=>({ref:String(e).slice(0,8),name:fi[e]||void 0,spawnedBy:t.spawnedBy,busy:(t.session?.turnActive??!1)||(t.pending?.size??0)>0}))));const a=Ne("start another worker lane");if(!a.ok)return Oi(),r(a.reason);const l={...t,runtime:o.runtime,model:o.model,provider:o.provider,mode:se(o.runtime,{mode:o.mode,sliceType:t?.sliceType})};let d;try{d=Mr({args:l,initiatorTerminalId:e,roomCode:Zn,bridgeAuthorityId:gs,localAuthorityId:e,context:{...s,providerName:o.provider?x()[o.provider]||o.provider:void 0,resolvedModel:o.model}})}catch(e){return process.stderr.write(`\n ${$a}✗ dispatch preview rejected — ${e?.message||e}${va}\n`),r("Dispatch preview could not be built safely. No lane was created.")}const u=Date.now(),m=It(u),p=Ur({preview:d,args:l,initiatorTerminalId:e,roomCode:Zn,bridgeAuthorityId:gs,localAuthorityId:e,context:{...m,providerName:o.provider?x()[o.provider]||o.provider:void 0,resolvedModel:o.model}});if(!p.ok)return r(p.reason||"Dispatch became stale or exceeded a cap. No lane was created.");ze.spawnTimes=[...(ze.spawnTimes||[]).filter(e=>Number.isFinite(e)&&e>u-Sr.windowMs),u];const h=c(),f=await Ei(h);if(!f.ok)return r(f.reason||"The bridge machine cannot accept another live lane yet.");const w=String(h).slice(0,8),g=String(e).slice(0,8);t?.name&&(fi[h]=String(t.name).slice(0,80),mo(Zn,fi));const v=(ze.spawnDepth||0)+1,y=(ze.hop||0)+1;let k=[];if("review"===t?.sliceType)try{k=[Na(ze.cwd||process.cwd())]}catch(e){return r(`Review lane was not opened: could not pin the spawning parent’s HEAD (${e?.message||e}).`)}Oa({id:h,runtime:o.runtime,model:o.model,provider:o.provider,mode:l.mode,sliceType:t?.sliceType,flowReviewTargets:k.map(e=>e.taskKey),flowReviewSnapshots:k,spawnedBy:e,spawnDepth:v,cascadeRole:"worker",hop:y});const b=Ws.get(h);if(!b)return Di(h),t?.name&&(delete fi[h],mo(Zn,fi)),r("Could not open a new lane. No host-capacity slot was kept; retry after checking the runtime.");if(b.peekCount=0,b.peekRosterCount=0,b.postCount=0,b.spawnTimes=[],bi(),t?.task){const o=k.length?`\n\n[Immutable review target: parent at spawn time — target key "parent", pinned HEAD ${k[0].sha}. Use read_review_file with target="parent" for source and run_review_check with target="parent" for fixed checks. Do not infer a target path/ref or mutate anything.]`:"",n=`[Task from terminal ${g}'s agent — relayed via thinkpool Ensemble; you are its WORKER SUB-TERMINAL, never a main terminal or Cascade conductor]\n${t.task}${o}`,s={kind:"you",text:n,by:`terminal ${g} (agent)`,crosspost:!0,relaySourceName:fi[e]||void 0};Ii(h,t.task);const i=Gs(b,n,{visibleEvent:s,rejectionMessage:"The initial worker task was not accepted; retry after the lane is available."});return i.accepted?r(`Opened agent lane ${w}${t?.name?` ("${t.name}")`:""} and handed it the task. It runs in its own lane — check back with read_terminal, then close_terminal when done.`):r(i.error?`Opened lane ${w}${t?.name?` ("${t.name}")`:""}, but it may still be starting — could not hand off the task. Try post_to_terminal shortly.`:`Opened lane ${w}${t?.name?` ("${t.name}")`:""}, but host pressure prevented its runtime from accepting the task. Existing lanes remain connected; free memory and retry.`)}return r(`Opened idle agent lane ${w}${t?.name?` ("${t.name}")`:""}. Hand it work with post_to_terminal, or a person can type into it.`)})]:[],...ze.flowRole?[]:[B("close_terminal","Close an IDLE agent lane that YOU opened with spawn_terminal (identified by ref/id/name). Active turns and permission waits are protected: collect the completed result with read_terminal before closing. You can only close lanes you spawned yourself — never a sibling someone else is working in, and never the main terminal.",{terminal:L.string().describe("ref, id, or name of the lane you spawned (from read_terminal)")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=br({selfId:e,sessions:Ws,terms:Ls,names:fi}),n=$r(o,t?.terminal);if(!n)return r(`No terminal matches "${t?.terminal}". Call read_terminal with no argument to list the open terminals.`);const s=Ws.get(n.id);if(!s)return r(`Terminal ${n.ref} is not an agent lane (or already closed) — only spawned agent lanes can be closed this way.`);const i=Or({callerId:e,spawnedBy:s.spawnedBy,busy:(s.session?.turnActive??!1)||(s.pending?.size??0)>0});return i.ok||"not-owner"!==i.reason?i.ok||"busy"!==i.reason?(Ba(n.id),r(`Closed agent lane ${n.ref}${n.name?` ("${n.name}")`:""}.`)):r(`Terminal ${n.ref} is still working or waiting for a permission decision. close_terminal will not kill an active turn. Wait until read_terminal reports it idle/completed, collect its result, then close it. If it is genuinely stuck, ask a person to press Stop.`):r(`Terminal ${n.ref} was not opened by you — you can only close lanes you spawned yourself. Leave it to the person running it.`)})],..."builder"===ze.flowRole?[B("mark_flow_done","thinkpool Dispatch ONLY — call this ONCE when your slice is built, RUNS, and meets its acceptance criteria. For a gate-first task, pass `baselineEvidence`: the real, bounded pre-edit command/behavior receipt proving the assigned failure/absence. Never fabricate a RED sentence. The bridge derives the edited-file footprint from Git, compares it with the sealed scopePaths, and refuses unexpected touches. Records your latest commit as the slice's atomic-revert target and signals the room that this slice is done (which unblocks slices that depended on you). Do not call before the slice actually runs + meets acceptance.",{baselineEvidence:L.string().max(1400).optional().describe("real single-line pre-edit baseline command/behavior receipt; required for new gate-first tasks")},async e=>({content:[{type:"text",text:await Ge({baselineEvidence:e?.baselineEvidence||""})}]}))]:[],..."conductor"===ze.flowRole?[B("submit_flow_plan",'thinkpool Dispatch CONDUCTOR ONLY — submit your decomposition for human approval. Call this ONCE when your task-graph is ready. Pass it as `plan`: a JSON string {"summary":"<one line; assumptions: …>","tasks":[{"key":"<kebab>","title":"…","scope":"human-readable ownership","scopePaths":["repo/file.js","repo/directory/**"],"acceptance":"observable proof","nonGoals":["bounded exclusion"],"baseline":{"gate":"what fails/is absent before edits","evidence":"optional observed receipt"},"deps":["<key>"],"sliceType":"feature|scaffold|review|fix"}]}. Each builder/fix/scaffold needs acceptance, machine-readable repo-relative scopePaths, nonGoals, and a safe bounded baseline gate; review tasks inherit one builder contract. When uncertain, choose and record a safe reversible default; ask only when a choice materially expands scope or authority. The room validates and persists the graph, then shows approval. Do NOT use ExitPlanMode or write a plan file.',{plan:L.string().describe("the task-graph as a JSON string (the {summary, tasks:[…]} object)")},async t=>{const r=e=>({content:[{type:"text",text:e}]});if(!ze.flowSessionId||"conductor"!==ze.flowRole)return r("Not a Dispatch conductor — there is no plan to submit.");let o;try{o=tt(et(t?.plan||""),ze.runtime)}catch(e){return r(`Plan REJECTED: ${e?.message||e}. Re-call submit_flow_plan with valid JSON: a non-empty acyclic tasks array; each builder/fix/scaffold has observable acceptance, repo-relative scopePaths, bounded nonGoals, and a safe baseline gate that says what fails/is absent; each review targets exactly one builder contract.`)}return pi("flow-plan",{term:e,flowId:ze.flowSessionId,plan:JSON.stringify(o)},Us),process.stderr.write(`\n ${ka}◆ flow plan submitted — flow ${String(ze.flowSessionId).slice(0,8)} (${o.tasks.length} slice${1===o.tasks.length?"":"s"}).${va}\n`),r(`Plan submitted (${o.tasks.length} slice${1===o.tasks.length?"":"s"}) with gate-first contracts. Safe reversible assumptions belong in the summary; user steering remains authoritative. The room is showing approval. You are DONE; stop here and wait for approval (lane dispatch is the room's job).`)})]:[],..."reviewer"===ze.flowRole?[B("submit_flow_review",'thinkpool Dispatch REVIEWER ONLY — submit one bounded adversarial review round. Pass `verdict` as JSON: {"pass":boolean,"reasons":["specific evidence"],"taskKey":"authorized reviewed task","exhausted":boolean}. This is the only review completion path; do not call mark_flow_done and do not write FLOW_REVIEW.json.',{verdict:L.string().describe("the structured review verdict as a JSON string")},async e=>({content:[{type:"text",text:(await Qe(e?.verdict||"")).message}]}))]:[],..."reviewer"===ze.flowRole||"review"===ze.sliceType?[B("read_review_file","Read one regular file from the declared immutable review target. This always reads the target’s pinned Git object, never a live worktree; target and path are validated and the response is byte-bounded.",{target:L.string(),path:L.string()},async e=>({content:[{type:"text",text:JSON.stringify(await Vt({target:e?.target,filePath:e?.path,snapshots:ze.flowReviewSnapshots}))}]}),Gt),B("run_review_check","Run one fixed verification check against an immutable git-archived review target. This accepts only the declared target and a fixed check id, but executes target-defined code in a scratch archive that is not an OS filesystem/network sandbox. It can require approval and must be refused by approvalPolicy=never reviewers.",{target:L.string(),checkId:L.string()},async e=>({content:[{type:"text",text:JSON.stringify(await Qt({target:e?.target,checkId:e?.checkId,snapshots:ze.flowReviewSnapshots}))}]}),Yt)]:[]]});return r.instance.registerTool("project_intelligence",{description:"Query a persistent local structural code graph for THIS terminal’s exact Git worktree. Use status to inspect freshness, search_code for definitions/types, trace_code for callers/callees, and read_symbol after an exact qualified-name hit. The first code query auto-indexes or refreshes the worktree in fast mode. Results are structured, bounded, cursor-aware, and redact the worktree plus common absolute host paths.",inputSchema:L.object({operation:L.enum(ve),query:L.string().min(1).max(240).optional().describe("search terms for search_code"),symbol:L.string().min(1).max(300).optional().describe("qualified symbol for trace_code or read_symbol"),direction:L.enum(["inbound","outbound","both"]).optional(),depth:L.number().int().min(1).max(5).optional(),includeTests:L.boolean().optional(),limit:L.number().int().min(1).max(12).optional(),cursor:L.string().regex(/^\d{1,8}$/).optional()}).strict(),outputSchema:L.object({version:L.number().int(),operation:L.string(),status:L.enum(["ok","ready","missing","stale","error"]),message:L.string().optional(),project:L.object({head:L.string(),indexedHead:L.string().nullable(),dirty:L.boolean()}).strict().optional(),items:L.array(L.record(L.string(),L.unknown())).optional(),text:L.string().optional(),total:L.number().int().optional(),hasMore:L.boolean().optional(),nextCursor:L.string().nullable().optional()}).strict(),annotations:ye},async e=>{const t=ze.cwd||process.cwd();if(!ze.projectIntelligence||ze.projectIntelligence.cwd!==t){try{await(ze.projectIntelligence?.close())}catch{}ze.projectIntelligence=new ge({cwd:t})}const r=await ze.projectIntelligence.query(e);return{content:[{type:"text",text:we(r)}],structuredContent:r}}),r}),Ct=r.join(ie||process.cwd(),"FLOW_REVIEW.json"),xt=ze.reviewSliceRoots.length?({toolName:e,input:t})=>{for(const r of ze.reviewSliceRoots){const o=Jt({toolName:e,input:t,sliceRoot:r,verdictFile:Ct});if(!o.allow)return o}return{allow:!0,reason:"no reviewed slice targeted"}}:null;ze.deferred=!!he;const _t=Bo(ke,Te);ze.pendingRecap=_t.pendingRecap,ze.pendingCheckpoint=_t.pendingCheckpoint;const At=[En({spawnedBy:ze.spawnedBy,spawnDepth:ze.spawnDepth,cascadeRole:ze.cascadeRole,flowRole:ze.flowRole,sideParent:ze.sideParent}),yt?Dn:""].filter(Boolean).join("\n\n"),Nt="claude"===t?C(fe):null;let Ot=!1;const Et=!0===Nt?.policy?.enabled?{policy:Nt.policy,providers:N(),providerId:Nt.target.providerId,model:Nt.target.actualConfiguredModel,requestedModel:qe||Nt.target.actualConfiguredModel,bridgeHostId:$s,circuit:Ts,turnRev:()=>(Number(ze._turnRev)||0)+1,capGate:()=>{const t=ze.flowSessionId?wr.get(ze.flowSessionId):null,r=q(t);return r.configured||Ot||(Ot=!0,process.stderr.write(`\n ${ga}◇ provider resilience cap_not_configured (${String(e).slice(0,8)})${va}\n`)),r}}:null;if(ze.session=X(t,{cwd:ie||process.cwd(),model:qe,effort:i,resume:a,mode:u,terminalRolePrompt:At,rolePrompt:E,prepareCwd:ie||j||K?null:()=>{try{ze.managedWorktree?.dir||(ze.managedWorktree=Re({terminalId:e,cwd:process.cwd()})),ze.cwd=ze.managedWorktree.dir,ze.viewport.setWorkspaceRoot(ze.cwd);try{ze.flush?.()}catch{}return ze.cwd}catch(t){return process.stderr.write(`\n ◇ terminal worktree unavailable (${String(e).slice(0,8)}): ${t?.message||t}; using bridge checkout.\n`),ie||process.cwd()}},suggest:!fe||"anthropic"===fe,roomContext:()=>{const t=function(e){const t=e||process.cwd(),r=Pa.get(t);if(r&&Date.now()-r.at<6e4)return r.list;let o=[];try{o=s("git",["-C",t,"worktree","list"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).split("\n").map(e=>e.trim()).filter(Boolean)}catch{o=[]}return Pa.set(t,{at:Date.now(),list:o}),o}(ie||process.cwd());return Pr({selfId:e,sessions:Ws,terms:Ls,names:fi,worktrees:t.length>1?t:[]})},lazy:ne({runtime:t,defer:he,cwd:ie,flowSessionId:j,flowTaskKey:K,models:ze.models}),admitStart:()=>{const e=Ne("start this agent runtime");return e.ok||Oi(),e},reviewGate:xt,blockSubagents:"conductor"===ze.flowRole,onSubmitPlan:t=>{if(!ze.flowSessionId||"conductor"!==ze.flowRole)return{ok:!1,message:"Not a Dispatch conductor — nothing to submit."};let r;try{r=tt(et(t||""),ze.runtime)}catch(e){return{ok:!1,message:`Plan REJECTED: ${e?.message||e}. Re-Write FLOW_PLAN.json with valid JSON: a non-empty acyclic tasks array; each builder/fix/scaffold has observable acceptance, bounded nonGoals, and a baseline gate that says what fails/is absent; each review targets exactly one builder contract.`}}return pi("flow-plan",{term:e,flowId:ze.flowSessionId,plan:JSON.stringify(r)},Us),process.stderr.write(`\n ${ka}◆ flow plan submitted — flow ${String(ze.flowSessionId).slice(0,8)} (${r.tasks.length} slice${1===r.tasks.length?"":"s"}).${va}\n`),{ok:!0,message:`Plan SUBMITTED (${r.tasks.length} slice${1===r.tasks.length?"":"s"}) with gate-first contracts. Record safe reversible assumptions in the summary; user steering remains authoritative. The room is showing approval. You are DONE: stop here and wait for approval.`}},onLaneDone:"builder"===ze.flowRole?async e=>{let t="";try{const r=JSON.parse(String(e||"").trim());t="string"==typeof r?.baselineEvidence?r.baselineEvidence:""}catch{}return{ok:!0,message:await Ge({baselineEvidence:t})}}:null,onReviewVerdict:"reviewer"===ze.flowRole?Qe:null,mcpServers:{thinkpool:St},requiredMcpTools:"hermes"===t?be($e({flowRole:ze.flowRole,sliceType:ze.sliceType}),{canSpawnWorkers:yt}):void 0,hermesRole:"hermes"===t?$e({flowRole:ze.flowRole,sliceType:ze.sliceType}):void 0,crossPostGate:()=>Tr({hop:ze.hop||0,postCount:ze.postCount||0,disabled:"1"===process.env.TP_CROSSPOST_OFF}),didSpawnTarget:t=>{try{const r=br({selfId:e,sessions:Ws,terms:Ls,names:fi}),o=$r(r,t);if(!o)return!1;const n=Ws.get(o.id);return!!n&&n.spawnedBy===e}catch{return!1}},crossRoomPostGate:()=>Ar({roomHop:ze.roomHop||0,postCount:ze.crossRoomPostCount||0,disabled:"1"===process.env.TP_PAIRBUS_OFF}),env:{...process.env,...Ye({flowSessionId:j,mode:u}),...R(fe)||{},TP_MOCKUP_OUTBOX:rt},resilience:Et,onTurnStart:(t={})=>{!0===ze._busyAnn?function(e,t=Date.now()){e._turnRev=(Number(e._turnRev)||0)+1,e._turnStart=t,e._busyAnn=!0,e._settledTurnRev=null,e._turnSettledAt=null}(ze):Js(ze);const r=t._thinkpoolQueuedEcho;if(r){const t={kind:"you",...r};Sa(ze,t),pi("code-event",{term:e,evt:t})}bi()},onEvent:r=>{if(!Xo(r).known)return Ia(Ra(ze,r)),void bi();const n="system"===r.kind&&pe({current:ze.commands,incoming:ue(t,r.commands),onChanged:e=>{ze.commands=e,bi(),it()}});if(a&&"error"===r.kind){const t=ze.interruptedRecap||Fo(ze.log,Lo),n=Yr(ze,{message:r.message,recap:t,reopen:t=>{ze.imageQueue?.close();try{ze.mockupWatcher?.close()}catch{}return Ws.delete(e),Oa({id:e,runtime:ze.runtime,model:ze.model||o,effort:ze.effort,provider:ze.provider,log:ze.log,commands:ze.commands,mode:ze.mode,spawnedBy:ze.spawnedBy,spawnDepth:ze.spawnDepth,cascadeRole:ze.cascadeRole,hop:ze.hop,sideParent:ze.sideParent,sideTask:ze.sideTask,pendingSideContexts:ze.pendingSideContexts,pendingWorkerCompletions:ze.pendingWorkerCompletions,workerCompletionsInFlight:ze.workerCompletionsInFlight,sliceType:ze.sliceType,flowSessionId:ze.flowSessionId,flowTaskKey:ze.flowTaskKey,flowTaskContract:ze.flowTaskContract,flowRole:ze.flowRole,flowReviewTarget:ze.flowReviewTarget,flowReviewTargets:ze.flowReviewTargets,flowReviewSnapshots:ze.flowReviewSnapshots,flowReviewRound:ze.flowReviewRound,flowReviewConclusion:ze.flowReviewConclusion,dispatchBaseSha:ze.dispatchBaseSha,revertTarget:ze.revertTarget,cwd:ze.cwd,managedWorktree:ze.managedWorktree,rolePrompt:ze.rolePrompt,reviewSliceRoots:ze.reviewSliceRoots,openedAt:ze.openedAt,lastUsage:ze.lastUsage,mcpFlight:ze.mcpFlight,carryRecap:t,carryCheckpoint:ze.pendingCheckpoint}),Ws.get(e)||null}});if(n.recovered)return void process.stderr.write(`\n ◆ saved session expired — started fresh with transcript recap (${n.delivery}).\n`)}const s="hermes"===t&&("result"===r.kind||"error"===r.kind)&&(ze.session?.queuedDepth||0)>0;s&&(r.continuesQueued=!0);const i=!s&&"result"===r.kind,c=i?jr(ze):zs(ze),l=Pn(r,{turnActive:!0===ze.session?.turnActive});Qs(ze,r),So(r),i&&(ze._settledTurnRev=Number(r.turnRev)||Number(ze._turnRev)||null,ze._turnSettledAt=Number(r.ts)||Date.now());const d="stalled"===r.kind?!ze.stalled:!!ze.stalled;ze.stalled="stalled"===r.kind,ze.lastEvent=r,"stalled"!==r.kind&&(ze.lastActionAt=r.ts),(c||d)&&bi();{const e=!0===le(ze.runtime)?.canSteer&&(ze.session?.canSteer??!1);e!==ze._canSteerAnn&&(ze._canSteerAnn=e,bi())}{const e="hermes"!==ze.runtime&&(!ze.provider||"anthropic"===ze.provider),t="hermes"===ze.runtime||e?r.model||r.ctx?.model:null;t&&t!==ze.model&&(ze.model=t,bi(),"model-switch"===r.kind&&it()),"hermes"===ze.runtime&&"models"===r.kind&&Array.isArray(r.models)&&r.models.length?(ze.models=Sn(r.models),Un=ze.models,bi()):e&&"models"===r.kind&&Array.isArray(r.models)&&r.models.length&&(ki=r.models,bi())}if("model-switch"===r.kind){const t=ze.pendingModelSwitch;ze.pendingModelSwitch=null;const o=r.requested||t?.model||"requested model",n={kind:"control",text:"success"===r.status?`switched model → ${r.model||o}`:`couldn’t switch to ${o} — still using ${ze.model||"the previous model"}`,by:t?.by||null,cid:t?.cid||void 0};Sa(ze,n),pi("code-event",{term:e,evt:n}),ze.flush?.(),bi()}if("usage"===r.kind&&(ze.lastUsage=r,it()),"effort"===r.kind&&(ze.effort=r.level??r.effort??null,it(),bi()),ze.flowSessionId&&ze.flowTaskKey&&"result"===r.kind&&r.usage){const e=wr.get(ze.flowSessionId);e&&wr.set(ze.flowSessionId,ir(e,r.usage.output_tokens||0))}var u;if("result"===r.kind&&r.usage&&(u=r.usage.output_tokens||0,!Os&&Ln&&Zn&&u&&Es("record_spend",{p_room:Zn,p_tokens:u}).catch(()=>{}),function(e,t,r){if(!Ln||!Zn||!e)return;const o=t||{},n=(o.input_tokens||0)+(o.cache_creation_input_tokens||0)+(o.cache_read_input_tokens||0),s=o.output_tokens||0,i=o.cache_read_input_tokens||0;(n||s)&&In(e).then(t=>Es("record_code_usage",{p_room:Zn,p_model:e,p_input:n,p_output:s,p_cached:i,p_provider:r||"unknown",p_input_usd_per_mtok:t?.input??null,p_output_usd_per_mtok:t?.output??null,p_cached_input_usd_per_mtok:t?.cached??null,p_rate_source:t?.source??null})).catch(()=>{})}(r.model,r.usage,ze.provider)),ze.flowSessionId&&ze.flowTaskKey&&!ze.flowDone&&Xe({runtime:ze.runtime,flowRole:ze.flowRole,eventKind:r.kind,eventSubtype:r.subtype})&&Promise.resolve().then(()=>Ge()).catch(()=>{}),"system"===r.kind&&ze.pendingAutoResume&&Vr(ze)&&process.stderr.write(`\n ◆ auto-resumed interrupted turn (${e.slice(0,8)}) — sent continue.\n`),"system"===r.kind&&ze.pendingRecap){const t=ze.pendingRecap.length;Jr(ze)&&process.stderr.write(`\n ◆ carried ${t}c context recap into fresh session (${e.slice(0,8)}) after provider/restore switch.\n`)}"system"===r.kind&&ze.warming&&(e=>{if(e&&e.warming){e.warming=!1,e.warmed=!0,ti=Math.max(0,ti-1);try{clearTimeout(e.warmTimer)}catch{}oi()}})(ze),"compaction"===r.kind&&(_a(ze),ze.compacting?(r.by=ze.compactBy||null,ze.compacting=!1,ze.compactBy=null,pi("code-event",{term:e,evt:{kind:"compact",status:"done",ts:Date.now()}})):"auto"===r.trigger&&(pi("code-event",{term:e,evt:{kind:"compact",status:"start",ts:Date.now()}}),setTimeout(()=>{pi("code-event",{term:e,evt:{kind:"compact",status:"done",ts:Date.now()}})},2500)));const m="mode"===r.kind||"usage"===r.kind||"effort"===r.kind||"clear"===r.kind||"compact"===r.kind||"stalled"===r.kind||"suggestion"===r.kind||"assistant_stream"===r.kind||"model-switch"===r.kind;if(("result"===r.kind||"error"===r.kind)&&ze.compacting){const t=ze.compactBy||null;ze.compacting=!1,ze.compactBy=null,pi("code-event",{term:e,evt:{kind:"compact",status:"done",ts:Date.now()}});const o={kind:"control",text:("error"===r.kind?"compaction failed":"aborted"===r.subtype?"compaction canceled":"nothing to compact")+" — context unchanged",by:t};Sa(ze,o),pi("code-event",{term:e,evt:o})}if(("result"===r.kind||"error"===r.kind)&&"codex"===ze.runtime&&ze.pendingCodexCompaction){const e=ze.pendingCodexCompaction;ze.pendingCodexCompaction=null,Aa(ze,e)}if("result"===r.kind||"error"===r.kind){i&&ze.workerCompletionsInFlight?.length&&(ze.pendingWorkerCompletions=yn(ze.pendingWorkerCompletions,ze.workerCompletionsInFlight),ze.workerCompletionsInFlight=[],ze.flush?.());const t=Yi.get(e);if(t?"result"!==r.kind||r.subtype&&"success"!==r.subtype?na(e,"failed",{message:"The producing lane did not complete the edit."}):(t.resultOk=!0,oa({previewId:t.record.previewId,requestId:t.request.cid,state:"verifying",message:"Waiting for correlated desktop and mobile renders…"}),t.timer=setTimeout(()=>na(e,"failed",{message:"The edit finished without a correlated desktop and mobile render."}),12e4),t.timer.unref?.(),sa(e)):(Gi.get(e)||[]).length&&queueMicrotask(()=>ia(e)),ze.sideHandback){const t=ze.sideHandback;ze.sideHandback=null;const o=Ws.get(t.parentId),n="result"!==r.kind||r.subtype&&"success"!==r.subtype?"":String(r.resultText||"").trim()||fn(ze.log,t.afterSeq);if(o&&n){const r=gn({sideId:e,sideName:fi[e],task:ze.sideTask,summary:n});o.pendingSideContexts=hn(o.pendingSideContexts,r);const s={kind:"side-handback",sideId:e,sideName:fi[e]||"Side lane",task:ze.sideTask||"",text:n,by:t.by};So(s),Sa(o,s),pi("code-event",{term:t.parentId,evt:s});const i={kind:"control",text:"Brought to main.",by:t.by};So(i),Sa(ze,i),pi("code-event",{term:e,evt:i}),o.flush?.(),Ys(o)}else{const r={kind:"control",text:o?"Couldn’t prepare a handoff — try again.":"The main terminal is no longer available.",by:t.by};So(r),Sa(ze,r),pi("code-event",{term:e,evt:r})}ze.flush?.(),bi()}const o=ze._turnStart;ze._turnStart=null;const n=[...ze.pending.keys()];Ka(ze);for(const t of n)pi("code-perm",{term:e,id:t,decision:"deny",name:"agent"});if(i&&ze.spawnedBy&&!String(ze.spawnedBy).startsWith("flow:")){const t=Ws.get(ze.spawnedBy),o=Number(r.turnRev)||Number(ze._turnRev)||0;if(t&&o>0&&ze._ownerNotifiedTurnRev!==o){const n=$n({workerId:e,workerName:fi[e],turnRev:o,subtype:r.subtype});n&&(ze._ownerNotifiedTurnRev=o,t.pendingWorkerCompletions=kn(t.pendingWorkerCompletions,n),t.flush?.(),Vs(t))}}Ys(ze),Vs(ze);const s=Date.now();k({entry:ze,subtype:r.subtype,startedAt:o,now:s})&&qs({kind:"turn-done",term:e,termName:fi[e]||null,model:ze.model||null,summary:$("result"===r.kind?r.resultText:r.message),subtype:r.subtype||("error"===r.kind?"error":null),pushEligible:y({entry:ze,subtype:r.subtype,startedAt:o,now:s,minTurnMs:js})})}const p=Oo(r);!function(e,t,r,o,n){e.imageQueue||=new Eo({maxPending:Mn.maxPending,maxBytes:Mn.maxBytes,upload:(e,r,o)=>async function(e,t,r,o){return jo({webBase:Kn,room:Zn,authToken:Ln,term:e,cid:t,image:r,timeoutMs:Mn.uploadTimeoutMs,activeUploads:o})}(t,e.cid,r,o),onUploadError:e=>process.stderr.write(`\n ◇ screenshot upload failed (${e?.message||e}).\n`),onOverload:({maxPending:e,maxBytes:t})=>process.stderr.write(`\n ◇ screenshot omitted (image queue cap: ${e} pending / ${t} encoded bytes).\n`)}),e.imageQueue.enqueue(r,o,n)}(ze,e,r,p,t=>{if(!n&&(m||Sa(ze,t),pi("code-event",{term:e,evt:t}),Ia(t),m||it(),l&&queueMicrotask(()=>{ca.flush(e).catch(()=>{})}),i&&ze.scheduleRunId&&("result"===t.kind||"error"===t.kind))){const e=ze.scheduleTimedOut?{...t,subtype:"runtime_limit"}:t;ta(ze,e,{canceled:!ze.scheduleTimedOut&&"aborted"===t.subtype})}})},requestPermission:Rt}),"codex"===t&&ze.session?.usageSnapshot?.context){const{used:e,max:t}=ze.session.usageSnapshot.context;ze.lastUsage={kind:"usage",ctx:{used:e,max:t,pct:Math.min(100,Math.max(0,Math.round(e/t*100))),over:e>t,model:ze.model}}}return ze.log.length||ze.flush(),Vs(ze),bi(),ze.log.length||process.stderr.write(`\n ◆ structured ${le(t)?.label||"agent"} session (${e.slice(0,8)}) — driven from the room.\n`),ze}function Ea(e,t={}){const r=t.decision||"deny";return"dispatch"===e?.payload?.answerFormat?{decision:r,dispatchFingerprint:t.dispatchFingerprint||null,controlItemId:t.controlItemId||null}:"ask"===e?.payload?.risk||"codex"===e?.payload?.answerFormat||"hermes"===e?.payload?.answerFormat?{decision:r,answers:t.answers||{},responder:t.responder||null}:r}function Da(e,t=null,r="permission_aborted",o=!1){const n=t||[...e?.pending?.entries?.()||[]].map(([e])=>e);n.length&&e?.id&&(o?w:g)({supabaseUrl:qn,anonKey:Fn,token:Ln,roomCode:Zn,bridgeId:gs,terminalId:e.id,permissionIds:n,reason:r}).then(e=>{!e.ok&&process.env.TP_DEBUG&&process.stderr.write(`\n ◇ durable permission cleanup incomplete (${e.code})\n`)})}let ja=!1;async function qa(){ja=!0;const e=await g({supabaseUrl:qn,anonKey:Fn,token:Ln,roomCode:Zn,currentBridgeId:gs,reason:"bridge_restarted"});return e.ok?ja=!1:process.env.TP_DEBUG&&process.stderr.write(`\n ◇ restored permission cleanup incomplete (${e.code})\n`),e}function Ka(e){if(e?.pending){Zr(e),Da(e,null,"permission_aborted");for(const[,t]of e.pending){t?.timer&&clearTimeout(t.timer);try{t.resolve(Ea(t,{decision:"deny"}))}catch{}}e.pending.clear(),e.permNotifier?.clearAll()}}function Ma(e){if(e?.pending)for(const[t,r]of e.pending)if("plan"!==r?.payload?.risk&&"ask"!==r?.payload?.risk&&"dispatch"!==r?.payload?.answerFormat){r?.timer&&clearTimeout(r.timer);try{r.resolve("allow")}catch{}e.pending.delete(t),e.permNotifier?.resolve(t)}}const Ua=new Set(["Write","Edit","MultiEdit","NotebookEdit"]);function Fa(e){if(e?.pending)for(const[t,r]of e.pending){const o=r?.payload?.toolName,n=r?.payload?.risk;if("plan"!==n&&"ask"!==n&&"high"!==n&&Ua.has(o)){r?.timer&&clearTimeout(r.timer);try{r.resolve("allow")}catch{}e.pending.delete(t),e.permNotifier?.resolve(t)}}}function Ba(e){if(!e)return;const r=Ws.get(e);if(r){ta(r,{subtype:"canceled"},{canceled:!0}),Qi(r),r.imageQueue?.close(),ca.clear(e),Ka(r);try{r.session?.end()}catch{}try{r.projectIntelligence?.close()}catch{}try{r.mockupWatcher?.close()}catch{}try{r.viewport?.stop()?.catch(()=>{})}catch{}const o=Yi.get(e);o?.timer&&clearTimeout(o.timer),Yi.delete(e),Gi.delete(e);for(const[t,r]of Ji)r.term===e&&Ji.delete(t);for(const[t,r]of Vi)r.priorRecord?.term===e&&Vi.delete(t);try{t.rmSync(da("sessions",e),{recursive:!0,force:!0})}catch{}Ws.delete(e),Di(e),pi("term-exit",{id:e}),function(e){h({id:e,token:Ln,supabaseUrl:qn,anonKey:Fn,shuttingDown:Zs,onFailure:({error:t,status:r})=>process.stderr.write(`\n ⚠ terminal row reap failed (${String(e).slice(0,8)}${r?`, HTTP ${r}`:""}): ${t||"unknown error"}\n`)})}(e),function(e){if(e)try{const t={"Content-Type":"application/json"};Ln&&(t.Authorization=`Bearer ${Ln}`),fetch(`${Kn}/api/code-image-cleanup`,{method:"POST",headers:t,body:JSON.stringify({code:Zn,term:e})}).catch(()=>{})}catch{}}(e);try{Se({terminalId:e,managedWorktree:r.managedWorktree})}catch{}for(const[t,r]of[...Ws])r.spawnedBy!==e&&r.sideParent!==e||Ba(t)}no(Zn,e),r&&bi()}function La(e,t=4e3){if(!e)return;const r=`flow:${e}`;wr.delete(e),setTimeout(()=>{for(const[t,o]of[...Ws])if(o.flowSessionId===e||o.spawnedBy===r)try{Ba(t)}catch{}},t)}function Wa(e){if(e&&ii!==e){ii=e;for(const t of Ws.keys())pi("code-event",{term:t,evt:{kind:"update-available",version:e}});bi()}}const Ha=()=>{if(to(Ws))return!1;for(const e of Ls.values())if(e.buf)return!1;return!0};async function za(){if(!ai||!ii||ci)return!1;if(process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD)return!1;if(!Ha())return!1;ci=!0;try{const e=await import("./service.mjs");if(!e.serviceActive(Zn))return!1;const t=!1!==e.updateService(Zn);return t||(ci=!1),t}catch(e){return ci=!1,process.stderr.write(`\n ⚠ bridge update failed: ${e?.message||e}\n`),!1}}setInterval(()=>{ai&&za()},5e3).unref();const Ja=()=>{try{process.stdin.isTTY&&process.stdin.setRawMode(!1)}catch{}};ms&&process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.on("data",e=>{const t=Xs&&Ls.get(Xs);if(t)try{t.term.write(e.toString("utf8"))}catch{}else e.includes(3)&&nc()}),process.stdout.on("resize",()=>{const e=Xs&&Ls.get(Xs);if(!e)return;const{cols:t,rows:r}=ha();if(e.term.cols!==t||e.term.rows!==r)try{e.term.resize(t,r),bi()}catch{}});let Ga=!1,Ya=Date.now();async function Va(e){try{return await pr({payload:e,bridgeName:ws,lanes:[...Ws.entries()],prepareLane:(e,t)=>cr({lane:{cwd:e.cwd,session:e.session,commitSha:e.commitSha,revertTarget:t.commitSha??e.commitSha??e.revertTarget??null},sanitize:dr}),rememberRedispatch:(e,t,r)=>{hr.set(lr(r.flowId,r.taskKey),{resumeSessionId:e.resumeSessionId,revertTarget:e.revertTarget}),e.healed&&process.stderr.write(`\n ${ga}◆ flow re-dispatch heal — ${r.taskKey}: ${e.healed} dangling tool block(s) healed before resume.${va}\n`)},endLane:e=>{try{Ba(e)}catch{}},stopPreview:Et,wait:()=>new Promise(e=>setTimeout(e,400)),revert:e=>qt({flowId:e.flowId,taskKey:e.taskKey}),broadcastReverted:e=>{pi("flow-reverted",{term:"flow",flowId:e.flowId,taskKey:e.taskKey,reviewTaskKey:e.reviewTaskKey,branch:e.branch},Us),process.stderr.write(`\n ${ba}◆ flow slice reverted — ${e.taskKey} (${e.branch}).${va}\n`)},onPrepError:(e,t,r)=>process.stderr.write(`\n ${ba}◆ flow re-dispatch prep failed (${r.taskKey}): ${e?.message||e} — will re-dispatch fresh.${va}\n`)})}catch(e){return process.stderr.write(`\n ${ba}◆ flow revert failed: ${e?.message||e}${va}\n`),{ok:!1,error:e?.message||String(e)}}}Bs.on("broadcast",{event:"apply-update"},()=>{if(ii&&(ai=!0,process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD))try{process.send({t:"apply-update"})}catch{}}).on("broadcast",{event:"bridge-update"},async({payload:e})=>{const t=e?.nonce,r=(e,r,o)=>Bs.send({type:"broadcast",event:"bridge-update-res",payload:{nonce:t,ok:e,...r?{error:r}:{},...o?{state:o}:{}}});if(!t)return r(!1,"invalid request");const o="string"==typeof e?.v&&/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(e.v)?e.v:null;if(!o)return r(!1,"invalid bridge version");if(Wa(o),ai=!0,process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD){try{process.send({t:"apply-update"})}catch{return r(!1,"account supervisor is unavailable")}return r(!0,null,"queued")}let n=!1;try{n=(await import("./service.mjs")).serviceActive(Zn)}catch{}return n?Ha()?(await r(!0,null,"applying"),void za()):r(!0,null,"queued"):(ai=!1,r(!1,"This bridge is running in a terminal. Restart it once with npx thinkpool-pair@latest, or install the background service to enable remote updates."))}).on("broadcast",{event:"providers-list-req"},({payload:e})=>{Bs.send({type:"broadcast",event:"providers-list-res",payload:{nonce:e?.nonce,ok:!0,providers:N()}})}).on("broadcast",{event:"provider-switch"},({payload:e})=>{const t=e?.nonce,r=(e,r,o)=>Bs.send({type:"broadcast",event:"provider-switch-res",payload:{nonce:t,ok:e,...r?{error:r}:{},...void 0===o?{}:{restarted:o}}}),o=e?.term,n=o?Ws.get(o):null;if(!n)return r(!1,"no such live lane");const s=K({provider:e?.provider,currentProvider:n.provider,registeredIds:N().map(e=>e.id)});if(!s.ok)return r(!1,s.error);const i=e?.provider===U?null:e?.provider,a=M({provider:e?.provider,currentProvider:n.provider,sameEnv:E(n.provider,i),targetModel:D(i)});if("noop"===a.action)return r(!0,void 0,!1);if("in-place"===a.action&&function(e,t){const r=Ws.get(e);if(!r?.session)return!1;const o=D(t);if(!o)return!1;r.provider=t||null,r.model=o;try{r.session.setModel(o)}catch{return!1}try{r.flush?.()}catch{}return!0}(o,i))return process.stderr.write(`\n ◆ lane ${String(o).slice(0,8)} switched model → ${D(i)} (same key, context kept).\n`),bi(),r(!0,void 0,!1);const c=function(e,t){const r=Ws.get(e);if(!r)return!1;r.imageQueue?.close();const{runtime:o,log:n,commands:s,mode:i,spawnedBy:a,spawnDepth:c,cascadeRole:l,hop:d,sideParent:u,sideTask:m,pendingSideContexts:p,pendingWorkerCompletions:h,workerCompletionsInFlight:f,sliceType:w,flowSessionId:g,flowTaskKey:v,flowTaskContract:y,flowRole:k,flowReviewTarget:b,flowReviewTargets:$,flowReviewSnapshots:T,flowReviewRound:I,flowReviewConclusion:R,dispatchBaseSha:S,revertTarget:C,cwd:x,managedWorktree:_,rolePrompt:A,reviewSliceRoots:P,openedAt:N,lastUsage:O,mcpFlight:E,pendingCheckpoint:D}=r,j=g?null:Fo(n,Lo);Ka(r);try{r.session?.end()}catch{}try{r.mockupWatcher?.close()}catch{}try{r.viewport?.stop()?.catch(()=>{})}catch{}return Ws.delete(e),Oa({id:e,runtime:o,provider:t,log:n,commands:s,mode:i,spawnedBy:a,spawnDepth:c,cascadeRole:l,hop:d,sideParent:u,sideTask:m,pendingSideContexts:p,pendingWorkerCompletions:h,workerCompletionsInFlight:f,sliceType:w,flowSessionId:g,flowTaskKey:v,flowTaskContract:y,flowRole:k,flowReviewTarget:b,flowReviewTargets:$,flowReviewSnapshots:T,flowReviewRound:I,flowReviewConclusion:R,dispatchBaseSha:S,revertTarget:C,cwd:x,managedWorktree:_,rolePrompt:A,reviewSliceRoots:P,openedAt:N,lastUsage:O,mcpFlight:E,carryRecap:j,carryCheckpoint:D}),!0}(o,i);if(!c)return r(!1,"no such live lane");process.stderr.write(`\n ◆ lane ${String(o).slice(0,8)} switched provider → ${i||"anthropic"} (memory reset, transcript kept).\n`),r(!0,void 0,!0)}).subscribe(e=>{"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||process.stderr.write(`\n ⚠ private bridge control ${e} (tpcontrol:${Zn}).\n`)}),Ms.on("broadcast",{event:"pty-in"},({payload:e})=>{if(!e?.data)return;si();const t=Ls.get(e.term)||(null==e.term&&Xs?Ls.get(Xs):null);if(t)try{t.term.write(e.data)}catch{}}).on("broadcast",{event:"resize"},({payload:e})=>{if(!e?.cols||!e?.rows)return;const t=Ls.get(e.term);if(t&&!t.attached)try{t.term.resize(Math.max(e.cols,80),Math.max(e.rows,20)),bi()}catch{}}).on("broadcast",{event:"session-deleted"},async()=>{if(process.stderr.write("\n ◆ this room was deleted — closing the bridge.\n"),"1"===process.env.THINKPOOL_PAIR_AUTOUPDATE)try{(await import("./service.mjs")).uninstallService(Zn)}catch{}nc()}).on("broadcast",{event:"term-open"},async({payload:e})=>{if(!e?.id||!e?.cmd)return;if(e.host&&e.host!==ws)return;if(Ls.has(e.id))return void gi(e.id,"pty",Ls.get(e.id));let t=[];if(e.resume){const r=Hn.find(t=>t.cmd===e.cmd);if(r?.resume)try{r.resume.probe()&&(t=[...r.resume.args])}catch{}}if(ss(e.cmd)){const t=Ws.get(e.id);if(t)return void gi(e.id,"structured",t);let r=ns(e.cmd),o=null,n=null;if(e.sideParent){const t=Ws.get(e.sideParent);if(o=t?.sideParent||e.sideParent,n=Ws.get(o),!n||!String(e.sideTask||"").trim())return void pi("side-open-failed",{id:e.id,parent:o,message:n?"Add a task after /side.":"The main terminal is not live."});r=n.runtime||r,e.name&&(fi[e.id]=String(e.name).slice(0,80),mo(Zn,fi))}if(Oa({id:e.id,runtime:r,mode:n?.mode||e.mode,model:n?.model||e.model||void 0,provider:"claude"===r&&(n?.provider||e.provider)||void 0,cwd:n?n.cwd||process.cwd():void 0,sideParent:o||void 0,sideTask:o?String(e.sideTask).trim():void 0,rolePrompt:o?pn:void 0,defer:!0}),o){const t=Ws.get(e.id),r=String(e.sideTask).trim(),s=Array.isArray(e.files)?e.files:[],i=String(e.by||"A room member"),a=fi[e.id]||"Side lane";if(!t)return void pi("side-open-failed",{id:e.id,parent:o,message:"The side lane could not start."});const c=await ji(t);if(!c.ok){const t=c.reason||"This bridge machine cannot start another agent runtime yet.";return pi("side-open-failed",{id:e.id,parent:o,message:t}),void Ba(e.id)}t.hop=0;const l={kind:"you",text:r,by:i,...s.length?{files:s}:{}},d={kind:"side-started",sideId:e.id,sideName:a,task:r,by:i};Sa(n,d),pi("code-event",{term:o,evt:d});const u=vn(n.log.filter(e=>e.cid!==d.cid)),m=s.map(e=>Te(e,{updir:xs})).filter(Boolean),p=m.length?`${r}\n\n${m.map(e=>`"${e}"`).join(" ")}`:r,h=u?`${u}\n\n--- side task ---\n${p}`:p,f="codex"===t.runtime||"hermes"===t.runtime?await Ie(s,{updir:xs}):[];return Gs(t,h,{options:f.length?{images:f}:void 0,visibleEvent:l,rejectionMessage:"The side-lane task was not accepted; retry after the lane is available."}).accepted?(t.flush?.(),n.flush?.(),bi(),gi(e.id,"structured",t),void process.stderr.write(`\n ◆ ${i} opened side lane ${String(e.id).slice(0,8)} under ${String(o).slice(0,8)}.\n`)):(qi(t,c),pi("side-open-failed",{id:e.id,parent:o,message:"The side agent could not start."}),void Ba(e.id))}const s=Ws.get(e.id);return s&&gi(e.id,"structured",s),void process.stderr.write(`\n ◆ web opened a structured "${e.cmd}" session (${e.mode||"default"}${e.model?`, model ${e.model}`:""}).\n`)}const r=await Ei(e.id);r.ok?(fa({id:e.id,cmd:e.cmd,args:t}),Ls.has(e.id)?gi(e.id,"pty",Ls.get(e.id)):Di(e.id),process.stderr.write(`\n ◆ web opened a "${e.cmd}"${t.length?" (continue)":""} terminal (headless).\n`)):pi("term-exit",{id:e.id,reason:r.reason||"This bridge machine cannot accept another live lane yet."})}).on("broadcast",{event:"term-close"},({payload:e})=>{const t=e?.id&&Ls.get(e.id);if(t&&!t.attached)try{t.term.kill()}catch{}else t||Ba(e?.id)}).on("broadcast",{event:"replay-request"},({payload:e})=>{Li();const t=e?.to??null,r=String(e?.requestId||c?.()||`${Date.now()}`),o=[];for(const[n,s]of Jo(Ls,e?.terms,e?.priority)){if(!s.scrollback)continue;const e=s.scrollback.length>1e5?s.scrollback.slice(-1e5):s.scrollback;o.push({event:"pty-replay",payload:{to:t,term:n,requestId:r,b64:Buffer.from(e,"utf8").toString("base64")}})}const n=Jo(Ws,e?.terms,e?.priority);for(const[s,i]of n){if(!i.log.length){o.push({event:"code-replay",payload:{to:t,term:s,requestId:r,chunkIndex:0,chunkCount:1,events:[],empty:!0}});continue}const n=Number(e?.cursors?.[s])||0,a=xo(i.log),c=n>a,l=(n>0&&!c?i.log.filter(e=>null==e.seq||e.seq>n):i.log).map(e=>No(e)),d=Po(l),u=c?0:n,m=Wo(Ho(d[0]||[]),u,i.archiveOldestSeq);for(let e=0;e<d.length;e++){const n=d[e];o.push({event:"code-replay",payload:{to:t,term:s,requestId:r,chunkIndex:e,chunkCount:d.length,events:n,...c?{reset:!0}:{},...0===e&&null!=m?{trimmedBefore:m}:{},...0===e&&i.lastUsage?.ctx?{lastUsage:i.lastUsage}:{}}})}}hi.enqueue(t||"*",o,async()=>{for(const[,e]of Ws)for(const[,t]of e.pending)await ui("code-perm-req",t.payload);bi()})}).on("broadcast",{event:"history-page-request"},({payload:e})=>{const t=e?.term;if(!t)return;if(!yo({payloadHost:e?.host,bridgeName:ws,hasSession:Ws.has(t),hasArchive:vo(Zn,t)}))return;const{events:r,hasMore:o}=fo(Zn,t,Number(e?.beforeSeq)||null,200),n=e?.to??null,s=String(e?.requestId||c?.()||`${Date.now()}`);if(!r.length)return void pi("history-page",{to:n,term:t,requestId:s,chunkIndex:0,chunkCount:1,events:[],hasMore:!1});const i=Po(r.map(e=>No(e)));i.forEach((e,r)=>pi("history-page",{to:n,term:t,requestId:s,chunkIndex:r,chunkCount:i.length,events:e,hasMore:0!==r||o}))}).on("broadcast",{event:"session-search-request"},({payload:e})=>{if(e?.host&&e.host!==ws)return;const t=String(e?.query||"").trim().slice(0,200),r=String(e?.requestId||""),o=e?.to??null;if(!t||!r)return;const n=[...Ws.keys()].map(e=>({term:e,termName:fi[e]||"terminal"})),{results:s,truncated:i}=go(Zn,n,t,{limit:200});pi("session-search",{to:o,requestId:r,host:ws,results:s,truncated:i})}).on("broadcast",{event:"file-put"},({payload:e})=>{e?.id&&e?.url&&(e.host&&e.host!==ws||(async()=>{try{const o=Te(e,{updir:xs});if(!o)throw new Error("invalid attachment metadata");const n=await(async e=>{const t=Ln&&(e=>{const t=String(e||""),r=`code/${Zn}/`;return!t.startsWith(r)||t.includes("..")||t.split("/").some(e=>!e)?null:`${qn}/storage/v1/object/authenticated/session-attachments/${t.split("/").map(encodeURIComponent).join("/")}`})(e?.path),r=[{url:e?.url,headers:void 0},...t?[{url:t,headers:{apikey:Fn,Authorization:`Bearer ${Ln}`}}]:[]].filter(e=>e.url);let o=new Error("no attachment source");for(let e=0;e<3;e++){for(const e of r)try{const t=await fetch(e.url,{headers:e.headers});if(!t.ok)throw new Error(`HTTP ${t.status}`);return Buffer.from(await t.arrayBuffer())}catch(e){o=e}e<2&&await new Promise(t=>setTimeout(t,250*(e+1)))}throw o})(e);if(n.length>26214400)throw new Error("file too large");t.mkdirSync(xs,{recursive:!0}),t.writeFileSync(o,n),process.stderr.write(`\n ◆ file from the room: ${o}\n`),pi("file-done",{id:e.id,path:o.split(r.sep).join("/"),host:ws})}catch(t){process.stderr.write(`\n ◇ room file download failed (${o=e.name,String(o||"file").replace(/[^a-zA-Z0-9._-]/g,"_").slice(-80)||e.id}): ${t.message}\n`)}var o})())}).on("broadcast",{event:"code-open"},async({payload:e})=>{if(e?.host&&e.host!==ws)return;const t=e?.id||c();Ws.has(t)||Oa({id:t,runtime:e?.runtime,model:e?.model,provider:"claude"===e?.runtime?e?.provider:void 0,resume:e?.resume,mode:e?.mode,defer:!0})}).on("broadcast",{event:"side-handback-request"},async({payload:e})=>{const t=e?.term&&Ws.get(e.term);if(!t?.sideParent||t.sideParent!==e?.parent)return;const r=String(e?.by||"A room member");if(t.sideHandback||t.session?.turnActive){const o={kind:"control",text:"Finish or stop the current side-lane turn before bringing it to main.",by:r};return So(o),Sa(t,o),void pi("code-event",{term:e.term,evt:o})}t.sideHandback={parentId:t.sideParent,by:r,afterSeq:xo(t.log)};const o={kind:"control",text:"Preparing a compact handoff for main…",by:r};So(o),Sa(t,o),pi("code-event",{term:e.term,evt:o}),t.flush?.(),bi();const n=await ji(t);if(!n.ok){t.sideHandback=null;const o={kind:"control",text:n.reason||"The host cannot start another agent runtime yet.",by:r,tone:"caution"};return So(o),Sa(t,o),pi("code-event",{term:e.term,evt:o}),t.flush?.(),void bi()}if(!Gs(t,mn,{rejectionMessage:"The side-lane handoff was not accepted; retry after the lane is available."}).accepted){qi(t,n),t.sideHandback=null;const o={kind:"control",text:"Couldn’t start the handoff — try again.",by:r};So(o),Sa(t,o),pi("code-event",{term:e.term,evt:o}),t.flush?.(),bi()}}).on("broadcast",{event:"code-turn"},async({payload:e})=>{const t=e?.term&&Ws.get(e.term);if(!t||null==e.text)return;if(await qe(t),Ws.get(e.term)!==t||!t.session)return;const r=e.cid&&String(e.cid);if(r){t.receivedTurnCids||(t.receivedTurnCids=new Set);const o=t.receivedTurnCids.has(r)||t.log?.some(e=>e?.cid===r&&("you"===e.kind||"control"===e.kind));if(!o){if(t.receivedTurnCids.add(r),t.receivedTurnCids.size>1e3){const e=t.receivedTurnCids.values().next().value;t.receivedTurnCids.delete(e)}t.flush?.()}if(pi("code-turn-ack",{term:e.term,cid:r,duplicate:o}),o)return}si(),t.peekCount=0,t.peekRosterCount=0,t.postCount=0,t.pairPeekCount=0,t.crossRoomPostCount=0,t.spawnTimes=[],t.hop=0,t.roomHop=0;const o=String(e.text),n=function(e){const t=Zr(e);if(!t)return null;const r=e.pending?.get(t.permissionId);Da(e,[t.permissionId],"dispatch_superseded",!0),r?.timer&&clearTimeout(r.timer),e.pending?.delete(t.permissionId),e.permNotifier?.resolve(t.permissionId);try{r?.resolve(Ea(r,{decision:"deny"}))}catch{}return t.permissionId}(t);n&&bi(),Xr(t);const s=()=>{if(e.silent)return;const r={kind:"you",text:null!=e.body?String(e.body):o,cid:e.cid,by:e.by,...e.authorId?{authorId:e.authorId}:{},...e.steered?{steered:!0}:{},...Array.isArray(e.files)&&e.files.length?{files:e.files}:{},...Array.isArray(e.pastes)&&e.pastes.length?{pastes:e.pastes}:{}};Sa(t,r),pi("code-event",{term:e.term,evt:r})},i=(r,o={})=>{const n={kind:"control",text:r,by:e.by,cid:e.cid,...o};Sa(t,n),pi("code-event",{term:e.term,evt:n})},a=async({echo:r=!1}={})=>{const o=await ji(t);if(o.ok)return o;r&&s();const n={kind:"error",message:o.reason||"This bridge machine cannot start another agent runtime yet. Close a running lane and retry.",recoverable:!0};return Sa(t,n),pi("code-event",{term:e.term,evt:n}),bi(),null};if(/^\/help\s*$/.test(o)&&"hermes"!==t.runtime)return void i(`Available commands · ${me(t.commands)}`);if(/^\/status\s*$/.test(o)&&"hermes"!==t.runtime){const e=le(t.runtime)?.label||t.runtime,r=t.session?.turnActive?"working":"idle";return void i(`${e} · ${r} · model ${t.model||"default"} · ${t.mode||"default"} permissions · effort ${t.effort||"default"}`)}if(/^\/context\s*$/.test(o)&&"hermes"!==t.runtime){const e=t.lastUsage?.ctx;return void i(e?.max?`Context · ${Number(e.used||0).toLocaleString("en-US")} / ${Number(e.max).toLocaleString("en-US")} tokens (${e.pct??Math.round(Number(e.used||0)/Number(e.max)*100)}%)`:"Context usage unavailable until the runtime reports a completed turn")}if(/^\/diff\s*$/.test(o)){try{const e=t.cwd||process.cwd();i(he({cwd:e}))}catch{i("Working-tree diff unavailable outside a readable Git checkout")}return}const c=o.match(/^\/find(?:\s+([\s\S]+))?$/i);if(c){const r={kind:"repo-search",...fe({cwd:t.cwd||process.cwd(),query:c[1]||""}),by:e.by,cid:e.cid};return Sa(t,r),void pi("code-event",{term:e.term,evt:r})}if(/^\/credits\s*$/.test(o)&&"hermes"!==t.runtime)return"codex"!==t.runtime||"function"!=typeof t.session?.accountUsage?void i("Credit balance is unavailable for this runtime; use /usage for provider limits"):void Promise.resolve(t.session.accountUsage()).then(e=>{i(Y(e?.limits))}).catch(()=>i("Codex credits unavailable for this account"));const l=o.match(/^\/model\b\s*(\S+)?/);if(l){if(l[1]){if("hermes"===t.runtime&&t.pendingModelSwitch)return void i("finish the current Hermes model switch before choosing another model");if(!1===t.session.setModel(l[1]))return void i(`finish or stop the current ${le(t.runtime)?.label||"agent"} turn before switching models`);if("hermes"===t.runtime)return t.pendingModelSwitch={model:l[1],by:e.by,cid:e.cid},void pi("code-event",{term:e.term,evt:{kind:"model-switch",status:"pending",requested:l[1],ts:Date.now()}});t.model=l[1],bi(),t.flush?.(),i(`switched model → ${l[1]}`)}else i("use /model <name> to switch — e.g. opus, sonnet, haiku");return}if(/^\/clear\s*$/.test(o)){if(t.pendingRecap=null,t.pendingCheckpoint=null,t.pendingCodexCompaction=null,"codex"===t.runtime||"hermes"===t.runtime)t.session.clearContext?.();else{const e=await a();if(!e)return;!1===t.session.sendTurn(o)&&qi(t,e)}return t.log=[],t.logBytes=0,t.seq=Co(0),t.archiveOldestSeq=null,pi("code-event",{term:e.term,evt:{kind:"clear"}}),oo(Zn,e.term,{sessionId:t.session?.sessionId||null,log:[]}),void i("context cleared. You can continue with these answers in mind.")}if(/^\/compact\s*$/.test(o)){if("codex"===t.runtime){if(t.codexCompactionPromise||t.pendingCodexCompaction)return;if(t.session.turnActive)return t.pendingCodexCompaction={by:e.by,cid:e.cid},void i("Compaction queued for after this turn.",{tone:"caution"});if(!await a())return;return void Aa(t,{by:e.by,cid:e.cid})}const r=await a();if(!r)return;return t.compacting=!0,t.compactBy=e.by,pi("code-event",{term:e.term,evt:{kind:"compact",status:"start",ts:Date.now()}}),void(!1===t.session.sendTurn(o)&&qi(t,r))}if(/^\/usage\s*$/.test(o))return i("codex"===t.runtime?Ko(t.model,t.session?.usageSnapshot):qo(t.model,t.log)),void("codex"===t.runtime?Promise.resolve(t.session?.accountUsage?.()).then(e=>{const t=G(e?.usage);t&&i(t),i(V(e?.limits))}).catch(()=>i("Codex provider limits unavailable")):Tn().then(e=>{e&&i(e)}).catch(()=>{}));if("codex"===t.runtime&&/^\/review(?:\s|$)/.test(o)&&(t.flowSessionId||t.flowRole||"review"===t.sliceType))return void i("Native /review is unavailable in Dispatch and reviewer lanes; their immutable review contract already owns scope and authority");const d=await a({echo:!0});if(!d)return;let u=o;const m=[];t.pendingRecap&&(m.push(t.pendingRecap),t.pendingRecap=null),t.pendingCheckpoint&&(m.push(t.pendingCheckpoint),t.pendingCheckpoint=null),t.pendingSideContexts?.length&&(m.push(...t.pendingSideContexts),t.pendingSideContexts=[]),m.length&&(u=Mo(m,o),t.flush?.());const p="codex"===t.runtime||"hermes"===t.runtime?await Ie(e.files,{updir:xs}):[],h="hermes"===t.runtime&&t.session.turnActive&&/^\s*\/queue\s+/i.test(o),f={...p.length?{images:p}:{},...h&&!e.silent?{_thinkpoolQueuedEcho:{text:null!=e.body?String(e.body):o,cid:e.cid,by:e.by,...Array.isArray(e.files)&&e.files.length?{files:e.files}:{},...Array.isArray(e.pastes)&&e.pastes.length?{pastes:e.pastes}:{}}}:{}};zs(t),Ii(e.term,null!=e.body?String(e.body):o);const w=t.session.sendTurn(u,Object.keys(f).length?f:void 0);if(!1===w?(zs(t),qi(t,d)):Js(t),h&&!1!==w||s(),!1===w){const r={kind:"error",message:`${le(t.runtime)?.label||"Agent"} did not accept this turn; retry after the lane is available.`,recoverable:!0};Sa(t,r),pi("code-event",{term:e.term,evt:r})}if(bi(),!1!==w&&je(t,{turnRev:t._turnRev,turnCid:r})&&(Ka(t),De(t).finally(()=>bi()),bi()),e.pooled&&!e.silent){const r={kind:"pool",text:"dispatched to agent"};Sa(t,r),pi("code-event",{term:e.term,evt:r})}}).on("broadcast",{event:"code-perm"},({payload:e})=>{const t=e?.term&&Ws.get(e.term),r=t&&e.id&&t.pending.get(e.id);r&&en({supabaseUrl:qn,anonKey:Fn,token:Ln,roomCode:Zn,bridgeId:gs,payload:e}).then(o=>{o.ok&&Ws.get(e.term)?.pending.get(e.id)===r?(r.timer&&clearTimeout(r.timer),t.pending.delete(e.id),t.permNotifier?.resolve(e.id),r.resolve(Ea(r,{...e,decision:o.decision,answers:o.answers,responder:o.responder})),bi()):!o.ok&&process.env.TP_DEBUG&&process.stderr.write(`\n ◇ ignored unverified permission delivery (${o.code})\n`)})}).on("broadcast",{event:"code-abort"},({payload:e})=>{const t=e?.term&&Ws.get(e.term);if(t){const r=Ee(t,e);pi("code-abort-ack",{term:e.term,cid:e.cid,turnRev:e.turnRev,action:r.action,code:r.code,currentTurnRev:r.currentTurnRev}),"abort"===r.action&&(Ka(t),De(t).finally(()=>bi()),bi())}}).on("broadcast",{event:"code-mode"},({payload:e})=>{const t=e?.term&&Ws.get(e.term);if(t&&We.has(e.mode)){if(ie(t)&&e.mode!==t.mode){const r={kind:"control",text:`This ${t.flowRole||"review"} lane is structurally locked to ${t.mode}; Dispatch and reviewer restrictions take precedence.`};return Sa(t,r),pi("code-event",{term:e.term,evt:r}),void bi()}if("codex"===t.runtime||"hermes"===t.runtime){if(!t.session.setMode(e.mode)){const r={kind:"control",text:`finish or stop the current ${le(t.runtime)?.label||"agent"} turn before switching permissions`};return Sa(t,r),pi("code-event",{term:e.term,evt:r}),void bi()}return t.mode=e.mode,"bypassPermissions"===e.mode?Ma(t):"acceptEdits"===e.mode?Fa(t):"plan"===e.mode&&Ka(t),t.flush?.(),void bi()}t.mode=e.mode,t.session.setMode(e.mode),"bypassPermissions"===e.mode?Ma(t):"acceptEdits"===e.mode&&Fa(t),bi()}}).on("broadcast",{event:"code-effort"},({payload:e})=>{const t=e?.term&&Ws.get(e.term),r=new Set(["low","medium","high","xhigh","max"]);if(t&&r.has(e.level)){if(t.session?.turnActive){const r={kind:"control",text:"finish or stop the current turn before switching thinking power"};return Sa(t,r),void pi("code-event",{term:e.term,evt:r})}Promise.resolve(t.session.setEffort?.(e.level)).then(r=>{!1!==r&&(t.effort=e.level,t.flush?.(),bi())}).catch(()=>{})}}).on("broadcast",{event:"code-close"},({payload:e})=>{Ba(e?.id)}).on("broadcast",{event:"term-rename"},({payload:e})=>{e?.id&&(wi.add(e.id),yi.delete(e.id),e.name?fi[e.id]=String(e.name).slice(0,80):delete fi[e.id],mo(Zn,fi),bi())}).on("broadcast",{event:"who"},bi).subscribe(async e=>{if("SUBSCRIBED"===e){Ga=!0,Ya=0,t={name:ws,role:"bridge",bridge_id:gs,started_at:ks},(Ks||=Cn(Ms,{minMs:5e3}))(t);const e=ms||os,r=[];if(e&&!Ls.size&&!Ws.size)if(ss(e)){const e=so(Zn),t=e=>e._bt||e.openedAt||e.savedAt||0;if(e.sort((e,r)=>t(e)-t(r)),await qa(),e.length)for(const t of e){const e=Ca(t.log||[]),o=t.runtime||"claude",n="hermes"===o?Array.isArray(t.models)&&t.models.length?t.models:Un:t.models,s=!t.flowSessionId&&!e,i=!ne({runtime:o,defer:s,cwd:t.cwd,flowSessionId:t.flowSessionId,flowTaskKey:t.flowTaskKey,models:n});if(i){const e=await Ei(t.id);if(!e.ok){process.stderr.write(`\n ◇ active restore held for ${String(t.id).slice(0,8)} — ${e.reason||"host runtime capacity is full"}\n`);continue}}const a=Qr(t,{canResume:ao,codexThreadCanResume:J}),c=e?Fo(t.log||[],Lo):"";Oa({id:t.id,runtime:o,model:t.model||void 0,models:t.models,effort:t.effort,provider:"claude"===t.runtime&&t.provider||void 0,resume:a?t.sessionId:void 0,log:t.log,commands:t.commands,mode:t.mode,spawnedBy:t.spawnedBy,spawnDepth:t.spawnDepth,cascadeRole:t.cascadeRole,hop:t.hop,sideParent:t.sideParent,sideTask:t.sideTask,scheduleRunId:t.scheduleRunId,scheduleDeadlineAt:t.scheduleDeadlineAt,scheduleOutcomeRecorded:t.scheduleOutcomeRecorded,scheduleAdmissionLease:t.scheduleAdmissionLease,pendingSideContexts:t.pendingSideContexts,pendingWorkerCompletions:t.pendingWorkerCompletions,workerCompletionsInFlight:t.workerCompletionsInFlight,sliceType:t.sliceType,flowSessionId:t.flowSessionId,flowTaskKey:t.flowTaskKey,flowTaskContract:t.flowTaskContract,flowRole:t.flowRole,flowReviewTarget:t.flowReviewTarget,flowReviewTargets:t.flowReviewTargets,flowReviewSnapshots:t.flowReviewSnapshots,flowReviewRound:t.flowReviewRound,flowReviewConclusion:t.flowReviewConclusion,dispatchBaseSha:t.dispatchBaseSha,revertTarget:t.revertTarget,cwd:t.cwd,managedWorktree:t.managedWorktree,rolePrompt:t.rolePrompt,reviewSliceRoots:t.reviewSliceRoots,openedAt:t.openedAt,lastUsage:t.lastUsage,receivedTurnCids:t.receivedTurnCids,mcpFlight:t.mcpFlight,carryRecap:e?c:t.carryRecap,carryCheckpoint:t.carryCheckpoint,defer:s});const l=Ws.get(t.id);!l&&i&&Di(t.id);const d=[...t.log||[]].reverse().find(e=>"result"===e?.kind||"error"===e?.kind);l&&t.flowTaskKey&&Xe({runtime:l.runtime,flowRole:l.flowRole,eventKind:d?.kind,eventSubtype:d?.subtype,interrupted:e})&&setTimeout(()=>{try{l.markFlowDone?.()}catch{}},2e3),l&&e&&(l.pendingInterruptedRecovery={resumable:a,recap:c},r.push(l))}else if(ms){const e=c();(await Ei(e)).ok&&(Oa({id:e,runtime:ns(ms)}),Ws.has(e)||Di(e))}ri&&setTimeout(()=>{for(const[,e]of Ws)!e.deferred||e.warmed||e.warming||e.session?.started||ei.push(e);ei.length&&(process.stderr.write(`\n ◆ background-warming ${ei.length} idle terminal(s) (≤3 at a time)…\n`),oi())},6e3)}else{const t=co(Zn)||c();lo(Zn,t),(await Ei(t)).ok&&(fa({id:t,cmd:e,args:ps,attached:!os}),Ls.has(t)||Di(t))}if(await bi(),f({room:Zn,hostId:$s,liveIds:[...Ls.keys(),...Ws.keys()],token:Ln,supabaseUrl:qn,anonKey:Fn,shuttingDown:Zs,onFailure:({error:e,status:t})=>process.stderr.write(`\n ⚠ terminal row reconcile failed${t?` (HTTP ${t})`:""}: ${e||"unknown error"}\n`)}).then(({reaped:e})=>{e.length&&process.stderr.write(`\n ◆ removed ${e.length} stale terminal row${1===e.length?"":"s"} after restore.\n`)}),process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD)try{process.send({t:"room-ready",room:Zn,bridgeId:gs})}catch{}r.forEach((e,t)=>{const r=setTimeout(()=>{const t=e.pendingInterruptedRecovery;if(e.pendingInterruptedRecovery=null,!t||Ws.get(e.id)!==e)return;const r=Gr(e,t);"sent"===r?process.stderr.write(`\n ◆ auto-resumed interrupted Codex turn (${e.id.slice(0,8)}) — sent continue.\n`):"recap-sent"===r&&process.stderr.write(`\n ◆ resumed interrupted Codex turn (${e.id.slice(0,8)}) with a fresh context recap.\n`)},1e3+5e3*t);r.unref?.()}),setImmediate(()=>{for(const e of Ws.values())if(e.snapshotNeedsCompaction){e.snapshotNeedsCompaction=!1;try{e.flush?.()}catch{}}}),process.stderr.write(rs?`\n ◆ thinkpool — relaying room ${Zn} (headless). Open terminals from the web UI.\n\n`:`\n ◆ thinkpool — sharing "${ms}"${hs?" (continuing your latest session)":""} into room ${Zn}. Open the web UI and you're both in.\n\n`)}else"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||(!Ga&&Ya||(Ya=Date.now()),Ga=!1,process.stderr.write(`\n ⚠ realtime ${e} — reconnecting…\n`));var t}),Us.on("broadcast",{event:"flow-start"},async({payload:e})=>{if(!e?.flowId)return;if(e.host&&e.host!==ws)return;for(const[,t]of Ws)if(t.flowSessionId===e.flowId)return;const t=e.originTerm?Ws.get(e.originTerm):null;if(e.originTerm&&!t)return;const r=t?nt(t.runtime,null):"claude";if(!r)return;const o="codex"===r?t?.models||H():"hermes"===r&&t?.models||[],n=it({runtime:r,originModel:t?.model,catalog:o}),s=Br({totalLive:Ws.size+Ls.size,disabled:"1"===process.env.TP_SPAWN_OFF});if(!s.ok)return process.stderr.write(`\n ${ba}◆ flow start held — ${s.reason}${va}\n`),void pi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:null,reason:s.reason},Us);const i=Ne("start the Dispatch conductor");if(!i.ok)return Oi(),process.stderr.write(`\n ${ba}◆ flow start held — ${i.reason}${va}\n`),void pi("flow-host-pressure",{term:"flow",flowId:e.flowId,reason:i.reason},Us);const a=c(),l=await Ei(a);if(!l.ok){const t=l.reason||"This bridge machine cannot accept another live lane yet.";return process.stderr.write(`\n ${ba}◆ dispatch start held — ${t}${va}\n`),void pi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:null,reason:t},Us)}fi[a]=`Dispatch · ${String(e.flowId).slice(0,6)}`,mo(Zn,fi),Oa({id:a,runtime:r,model:n,mode:"codex"===r?"plan":"default",rolePrompt:"claude"===r?He:Je,flowSessionId:e.flowId,flowRole:"conductor",spawnedBy:`flow:${e.flowId}`});const d=Ws.get(a);if(!d)return Di(a),delete fi[a],void mo(Zn,fi);d?.session&&Gs(d,e.prompt||"",{rejectionMessage:"The Dispatch conductor task was not accepted; retry after the lane is available."}),process.stderr.write(`\n ${ka}◆ flow conductor launched — flow ${String(e.flowId).slice(0,8)} (plan mode).${va}\n`),bi()}).on("broadcast",{event:"flow-dispatch"},async({payload:e})=>{if(!e?.flowId||!Array.isArray(e.tasks))return;if(e.host&&e.host!==ws)return;const t=[...Ws.values()].find(t=>t.flowSessionId===e.flowId&&"conductor"===t.flowRole);if(!t)return void process.stderr.write(`\n ${ba}◆ flow dispatch held — this bridge has no live/restored conductor for ${String(e.flowId).slice(0,8)}.${va}\n`);const r=nt(t.runtime,null);if(!r)return;const o="codex"===r?t.models||H():"hermes"===r&&t.models||[],n=[];let i=Lr(Ws.values());const a=ar();if(a.disabled)return void process.stderr.write(`\n ${ba}◆ flow dispatch refused — TP_FLOW_OFF kill-switch is on.${va}\n`);const l=e.mode||"guide",d=null!=a.capFromEnv?a.capFromEnv:null!=e.budgetCap?Number(e.budgetCap):null;let u=wr.get(e.flowId)||sr({capTokens:d});u.capTokens!==d&&(u={...u,capTokens:d}),wr.set(e.flowId,u);for(const t of e.tasks){if([...Ws.values()].some(r=>r.flowSessionId===e.flowId&&r.flowTaskKey===t.task_key&&!r.flowDone)){process.stderr.write(`\n ${ga}◆ flow dispatch skip ${t.task_key} — lane already live.${va}\n`);continue}const a=lr(e.flowId,t.task_key);if(fr.has(a))process.stderr.write(`\n ${ga}◆ flow dispatch skip ${t.task_key} — admission already in flight.${va}\n`);else{fr.add(a);try{const a=nr({mode:l,budget:u});if(!a.ok){process.stderr.write(`\n ${ba}◆ flow dispatch held (${a.reason}) — ${n.length} spawned this wave.${va}\n`);break}const d=Fr({spawnedLive:i,totalLive:Ws.size+Ls.size,plan:As,disabled:"1"===process.env.TP_SPAWN_OFF});if(!d.ok){process.stderr.write(`\n ${ba}◆ flow dispatch held — ${d.reason} ${n.length} spawned this wave; remaining slices stay queued.${va}\n`),pi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:t.task_key||null,reason:d.reason},Us);break}const m=Ne("start another Dispatch lane");if(!m.ok){Oi(),process.stderr.write(`\n ${ba}◆ flow dispatch held — ${m.reason}${va}\n`),pi("flow-host-pressure",{term:"flow",flowId:e.flowId,reason:m.reason},Us);break}const p=c(),h=await Ei(p);if(!h.ok){const r=h.reason||"This bridge machine cannot accept another live lane yet.";process.stderr.write(`\n ${ba}◆ dispatch held — ${r}${va}\n`),pi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:t.task_key||null,reason:r},Us);break}try{const a="review"===t.slice_type;try{rt(t,{legacy:null==t.contract})}catch(r){process.stderr.write(`\n ${ba}◆ flow dispatch held — ${t.task_key||"task"} failed its sealed acceptance contract: ${r?.message||r}${va}\n`),pi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:t.task_key||null,reason:"sealed acceptance contract mismatch"},Us),Di(p);continue}if(!ot(t,r)){process.stderr.write(`\n ${ba}◆ flow dispatch held — ${"hermes"===r?"Hermes":"Codex"} review ${t.task_key} must target exactly one dependency.${va}\n`),Di(p);continue}const{dir:c}=wt({flowId:e.flowId,taskKey:t.task_key});let l=null;try{l=s("git",["-C",c,"rev-parse","HEAD"],{encoding:"utf8"}).trim()}catch{}fi[p]=`Dispatch · ${t.task_key}`,mo(Zn,fi);const d=lr(e.flowId,t.task_key),u=hr.get(d)||null;u&&hr.delete(d);const m=a?(t.deps||[]).map(t=>gt({flowId:e.flowId,taskKey:t}).dir):[],h=a?(t.deps||[]).map(r=>{const o=gt({flowId:e.flowId,taskKey:r}).dir;let n=null;try{n=s("git",["-C",o,"rev-parse","HEAD"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).trim()}catch{}let i=null;if(n&&t.contract?.scopePaths?.length){let e=null;try{e=s("git",["-C",o,"merge-base",n,"origin/main"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).trim()}catch{}const r=gr(o,e,n);if(r){const e=Lt({log:[],repoRoot:o,declared:t.contract.scopePaths,changed:r}),n=Wt(t.contract.scopeEvidence);i=n?{...e,read:n.read,verified:n.verified}:e}}return{taskKey:r,cwd:o,sha:n,...i?{scopeEvidence:i}:{}}}).filter(e=>e.sha):[],f=Qe({base:"codex"===r||"hermes"===r?a?jt:Ge:a?Dt:ze}),w=t.contract?.acceptancePack?.task?.acceptance;Oa({id:p,runtime:r,cwd:c,model:st({sliceType:t.slice_type,runtime:r,catalog:o}),mode:se(r,{mode:"bypassPermissions",flowRole:a?"reviewer":"builder"}),rolePrompt:f,flowSessionId:e.flowId,flowTaskKey:t.task_key,flowTaskContract:t.contract||null,flowRole:a?"reviewer":"builder",flowReviewTargets:a&&t.deps||[],flowReviewSnapshots:h,dispatchBaseSha:l,revertTarget:u?.revertTarget||null,spawnedBy:`flow:${e.flowId}`,resume:u?.resumeSessionId||void 0,reviewSliceRoots:m});const g=Ws.get(p);g&&(u&&(g.revertTarget=u.revertTarget??null),a&&(g.flowReviewTarget=t.deps&&t.deps[0]||null),g.session&&!u)&&Gs(g,a?`[Dispatch REVIEW lane — slice "${t.task_key}" of run ${String(e.flowId).slice(0,8)}]\nYou are ADVERSARIALLY reviewing the slice(s): ${(t.deps||[]).join(", ")||t.title}\n`+(Array.isArray(t.deps)&&t.deps.length?"Reviewed slice worktree(s) — check out + RUN each yourself:\n"+t.deps.map(t=>{const r=gt({flowId:e.flowId,taskKey:t});return` - ${t}: dir ${r.dir} (branch ${r.branch})`}).join("\n")+"\n":"")+`ACCEPTANCE to INDEPENDENTLY verify: ${w||t.acceptance||t.title}\n`+`INHERITED NON-GOALS (must remain untouched): ${(t.contract?.nonGoals||[]).join(" | ")||"(legacy task: none recorded)"}\n`+`INHERITED BASELINE GATE: ${t.contract?.baseline?.gate||"(legacy task: none recorded)"}\n`+`BUILDER BASELINE EVIDENCE (verify; never invent another baseline): ${t.contract?.baseline?.evidence||"(missing — reject unless this is a legacy task)"}\n`+`\nProject (context): ${e.flowPrompt||""}\n\n`+("codex"===r||"hermes"===r?"Review it without mutating the builder worktree. For write-producing install/build/test commands, copy its source into scratch under your own current worktree first. Submit the structured verdict with the thinkpool submit_flow_review MCP tool; never write FLOW_REVIEW.json or call mark_flow_done.":'Review it — run it, hunt for failure. When done, use the Write tool to write FLOW_REVIEW.json with {"pass":<boolean>,"reasons":["<specific finding>"],"taskKey":"<the slice you reviewed>"}. That Write IS your verdict.'):`[Dispatch lane — slice "${t.task_key}" of run ${String(e.flowId).slice(0,8)}]\nTITLE: ${t.title}\nSCOPE (files you OWN — edit ONLY these): ${t.scope||"(none stated)"}\nACCEPTANCE (done = this runs + proves it): ${t.acceptance||"(meet the title)"}\nNON-GOALS (must remain untouched): ${(t.contract?.nonGoals||[]).join(" | ")||"(legacy task: none recorded)"}\nBASELINE GATE (before edits, observe this real failure/absence): ${t.contract?.baseline?.gate||"(legacy task: none recorded)"}\nBASELINE EVIDENCE: run/observe the pre-edit gate, then retain one real bounded command/behavior receipt for mark_flow_done; never fabricate a RED sentence.\n`+(t.deps&&t.deps.length?`DEPENDS ON (already built): ${t.deps.join(", ")}\n`:"")+(e=>e?`${e}\n`:"")(Ve(e.flowId,{baseDir:process.cwd(),deps:t.deps}).text)+`\nProject (context): ${e.flowPrompt||""}\n\nBuild your slice. Own only your files. Done = it runs + meets acceptance. Commit when done.`+("codex"===r||"hermes"===r?" Then call the thinkpool mark_flow_done MCP tool; do not write FLOW_DONE.":""),{rejectionMessage:`Dispatch slice ${t.task_key} was not accepted; retry after the lane is available.`}),g?(n.push({task_key:t.task_key,laneId:p}),i++):Di(p)}catch(e){Di(p),process.stderr.write(`\n ${ba}◆ flow dispatch failed for ${t.task_key}: ${e?.message||e}${va}\n`)}}finally{fr.delete(a)}}}n.length&&(pi("flow-dispatched",{term:"flow",flowId:e.flowId,assignments:n},Us),process.stderr.write(`\n ${ka}◆ flow dispatched ${n.length} lane(s) — flow ${String(e.flowId).slice(0,8)}.${va}\n`),bi())}).on("broadcast",{event:"flow-assemble"},async({payload:e})=>{if(e?.flowId&&Array.isArray(e.tasks)&&(!e.host||e.host===ws))try{const o=String(e.flowId).replace(/-/g,"").slice(0,8),n=e.tasks.map(t=>gt({flowId:e.flowId,taskKey:t.task_key}).dir).filter(e=>t.existsSync(e));if(!n.length)return void process.stderr.write(`\n ${ba}◆ flow assemble: no lane worktrees for ${o}.${va}\n`);const s=r.join(process.cwd(),".claude","worktrees",`flow-${o}-assembled`);t.rmSync(s,{recursive:!0,force:!0});const i=tr({dirs:n,outDir:s}),a=r.join(s,"index.html");if(t.existsSync(a))try{t.writeFileSync(a,rr({htmlPath:a,root:s}))}catch(e){process.stderr.write(`\n ${ba}◆ inline failed: ${e?.message||e}${va}\n`)}try{or({dir:s})}catch{}let c=null;try{c=(await vt({dir:s,id:`assembled:${e.flowId}`})).url}catch{}Et(e.flowId),pi("flow-assembled",{term:"flow",flowId:e.flowId,previewUrl:c,outDir:s,files:i.files,conflicts:i.conflicts},Us),process.stderr.write(`\n ${ka}◆ flow assembled — ${i.files.length} file(s)${i.conflicts.length?`, ${i.conflicts.length} conflict(s)`:""}${c?` · preview ${c}`:""} (flow ${o}).${va}\n`),bi(),La(e.flowId)}catch(e){process.stderr.write(`\n ${ba}◆ flow assemble failed: ${e?.message||e}${va}\n`)}}).on("broadcast",{event:"flow-revert"},async({payload:e})=>{await Va(e)}).on("broadcast",{event:"flow-cancel"},({payload:e})=>{e?.flowId&&(e.host&&e.host!==ws||(La(e.flowId,600),process.stderr.write(`\n ${ba}◆ flow cancelled — closing its lanes (${String(e.flowId).replace(/-/g,"").slice(0,8)}).${va}\n`)))}).subscribe(e=>{"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||process.stderr.write(`\n ⚠ flow realtime ${e} (tpflow:${Zn}).\n`)});const Qa=new Set;Fs.on("broadcast",{event:"design-capability"},({payload:e})=>{const t=e?.previewId&&Ji.get(String(e.previewId)),r=t&&xt(t),o=!!t&&!!r&&r.revision===t.revision&&t.revision===e?.revision&&Ws.has(t.term);Fs.send({type:"broadcast",event:"design-capability-res",payload:{previewId:String(e?.previewId||""),revision:String(e?.revision||""),ok:o}})}).on("broadcast",{event:"design-apply"},async({payload:e})=>{const t=Ot(e,Ji,Zn),r=String(e?.previewId||""),o=String(e?.cid||"").slice(0,80);if(!t.ok){const e=Number.isSafeInteger(t.editIndex)?`Edit ${t.editIndex+1}: `:"";return void oa({previewId:r,requestId:o,state:"stale-preview"===t.error?"stale":"failed",message:`${e}${t.error}`})}if(!o||Qa.has(o))return;Qa.add(o),Qa.size>500&&Qa.delete(Qa.values().next().value);const n=t.record.term,s=Gi.get(n)||[];if(Gi.set(n,s),s.length>=8)return void oa({previewId:r,requestId:o,state:"failed",message:"Too many Design batches are queued for this lane."});const i="batch"===t.request.mode?t.request.edits:[t.request],a=[];for(let e=0;e<i.length;e++){const t=i[e];if("image"!==t.mode)continue;const n=await Ct({webBase:Kn,token:Ln,room:Zn,asset:t.asset,requestId:`${o}-${e+1}`,cleanup:!1});if(!n)return void oa({previewId:r,requestId:o,state:"failed",message:`Edit ${e+1}: The private image draft could not be opened.`});t.asset.localPath=n,a.push(t.asset.path)}await Promise.all(a.map(e=>It({webBase:Kn,token:Ln,room:Zn,path:e})));const c=String(e?.by||"A room member").replace(/\0/g,"").trim().slice(0,120)||"A room member";s.push({...t,by:c});const l="batch"===t.request.mode?t.request.edits.length:1;oa({previewId:r,requestId:o,state:"queued",message:`${l} edit${1===l?"":"s"} pooled to the producing lane.`}),ia(n)}).on("broadcast",{event:"design-restore"},({payload:e})=>{const t=String(e?.previewId||""),r=String(e?.cid||"").slice(0,80),o=Ji.get(t),n=Vi.get(t),s=o&&xt(o);if(!(r&&o&&n?.priorRecord?.backupPath&&s&&s.revision===o.revision&&e?.revision===o.revision))return void oa({previewId:t,requestId:r,state:"stale",message:"That verified revision can no longer be restored safely."});if(Qa.has(r))return;Qa.add(r);const i=Gi.get(o.term)||[];if(Gi.set(o.term,i),i.length>=8)return void oa({previewId:t,requestId:r,state:"failed",message:"Too many Design edits are queued for this lane."});const a=String(e?.by||"A room member").replace(/\0/g,"").trim().slice(0,120)||"A room member";i.push({record:o,restoreRecord:n.priorRecord,request:{previewId:t,revision:o.revision,mode:"restore",intent:"restore previous verified revision",target:n.request.target||{selector:"html",tag:"artifact",name:`${n.request.edits?.length||1} pooled edits`},cid:r},by:a}),oa({previewId:t,requestId:r,state:"queued",message:"Restore queued in the producing lane."}),ia(o.term)}).subscribe(e=>{"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||process.stderr.write(`\n ⚠ design realtime ${e} (tpdesign:${Zn}).\n`)});let Xa=!1;const Za=e=>{const t=e?.runtime,r=e?.provider_id||"anthropic";return"claude"===t?!(!N().some(e=>e.id===r)||"anthropic"!==r&&e?.model&&D(r)!==e.model):!e?.provider_id&&("codex"===t?!e?.model||ct(H()).has(e.model):"hermes"===t&&(!e?.model||Un.some(t=>(t?.id||t?.model)===e.model)))},ec=async()=>{if(!Xa&&!Zs&&Ln&&Ns&&vs&&Number.isSafeInteger(ys)&&!(ys<1)){Xa=!0;try{if(!await async function(){if(!Ln||!vs||!Number.isSafeInteger(ys)||ys<1)return!1;const e=new Map(so(Zn).map(e=>[e?.id,e]).filter(([e])=>e));for(const{terminalId:t,intent:r,acknowledged:o}of Io(Zn)){if(o){$o(Zn,t);continue}const n=on(r);if(!n){$o(Zn,t);continue}let s=Ws.get(t);const i=e.get(t);(!0===s?.scheduleOutcomeRecorded?s.scheduleRunId:!0===i?.scheduleOutcomeRecorded?i.scheduleRunId:null)!==n.runId?!s&&i||s&&s.scheduleRunId&&s.scheduleRunId!==n.runId||(s||(s={id:t,scheduleRunId:n.runId,scheduleOutcomeRecorded:!1}),s.scheduleOutcomePending=n,await ea(s)):$o(Zn,t)}return nn(Io(Zn))}())return;if(!ln())return;const e=await rn({enabled:!0,supabaseUrl:qn,anonKey:Fn,token:Ln,roomCode:Zn,bridgeId:vs,bridgeFencing:ys,ownerId:Ns,providerAvailable:Za,admitRun:async({runId:e,terminalId:t,deadlineAt:r})=>{const o=an({spawnTimes:[],totalLive:Ws.size+Ls.size,disabled:"1"===process.env.TP_SPAWN_OFF});return o.ok?dn({runId:e,terminalId:t,deadlineAt:r}):o},releaseRun:e=>un(e),openTerminal:async({schedule:e,run:t,terminalId:r,admission:o})=>{const n=Date.parse(t.lease_expires_at),s=Number.isFinite(n)?n-6e4:NaN;if(!Number.isFinite(s)||s<=Date.now())return null;if(!(await Ei(r)).ok)return null;const i=Oa({id:r,runtime:e.runtime,provider:e.provider_id||void 0,model:e.model||void 0,mode:"default",scheduleRunId:t.id,scheduleDeadlineAt:s,scheduleAdmissionLease:o});if(!i)return Di(r),null;fi[r]=String(e.title||"Scheduled run").slice(0,80),mo(Zn,fi);const a=Gs(i,String(e.prompt||""),{visibleEvent:{kind:"you",text:String(e.prompt||""),by:"Scheduled run"},rejectionMessage:"The scheduled run could not start; no hidden fallback was used."});return a?.accepted?(ra(i),i.flush?.(),bi(),r):(i.scheduleRunId=null,Qi(i),Ba(r),null)}});!e.ok&&process.env.TP_DEBUG&&"runner_read_failed"!==e.code&&process.stderr.write(`\n ◇ scheduled-run poll: ${e.code}\n`)}finally{Xa=!1}}};ec(),setInterval(()=>{ec()},15e3).unref();let tc=!1,rc=0,oc=0;if(setInterval(async()=>{if(Ga||!Ya)return rc=0,void(oc=0);const e=Date.now();if(e-Ya<6e4||tc||e<oc)return;tc=!0;const t=await(async()=>{const e=new AbortController,t=setTimeout(()=>e.abort(),5e3);try{return(await fetch(`${qn}/auth/v1/health`,{headers:{apikey:Fn},signal:e.signal})).ok}catch{return!1}finally{clearTimeout(t)}})(),r=eo({brokenSince:Ya,now:Date.now(),httpHealthy:t,activeTurn:to(Ws)});if("restart"===r)return process.stderr.write("\n ⚠ realtime wedged while HTTP is healthy — exiting for a clean restart.\n"),void nc(1);const o=xn(rc);rc+=1,oc=Date.now()+o,process.stderr.write(`\n ◇ realtime unavailable (${r}) — preserving local agents; retrying in ${Math.round(o/1e3)}s.\n`);try{_s.realtime?.disconnect?.()}catch{}try{_s.realtime?.connect?.()}catch{}tc=!1},15e3).unref(),"1"===process.env.THINKPOOL_PAIR_AUTOUPDATE&&Ss){const e=1e3*Math.max(60,parseInt(process.env.THINKPOOL_PAIR_UPDATE_INTERVAL,10)||1800),t=1e3*Math.max(10,parseInt(process.env.THINKPOOL_PAIR_UPDATE_IDLE,10)||90),r=()=>{if(to(Ws))return!1;for(const e of Ls.values())if(e.buf)return!1;return!0},o=()=>r()&&Date.now()-ni>=t,n=(e,t)=>{const r=e=>String(e).split("-")[0].split(".").map(e=>parseInt(e,10)||0),o=r(e),n=r(t);for(let e=0;e<3;e++){if((o[e]||0)>(n[e]||0))return!0;if((o[e]||0)<(n[e]||0))return!1}return!1},s=async()=>{const e=new AbortController,t=setTimeout(()=>e.abort(),8e3);try{const t=await fetch("https://registry.npmjs.org/thinkpool-pair/latest",{signal:e.signal,headers:{accept:"application/json"}});if(!t.ok)return null;const r=await t.json();return"string"==typeof r?.version?r.version:null}catch{return null}finally{clearTimeout(t)}},i=()=>{if(ii){if(ai){if(!r())return}else if(!o()||li())return;process.stderr.write(`\n ◆ thinkpool-pair ${ii} ready (running ${Ss}) — restarting to update; the session resumes.\n`),nc(0,!1)}},a=async()=>{const e=await s();e&&n(e,Ss)&&(ii||process.stderr.write(`\n ◆ thinkpool-pair ${e} published — "update ready" in the room; applies between turns.\n`),Wa(e),i())};setInterval(a,e).unref(),setInterval(i,15e3).unref(),setTimeout(a,6e4).unref()}else if(process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD){const e=1e3*Math.max(10,parseInt(process.env.THINKPOOL_PAIR_UPDATE_IDLE,10)||90),t=()=>{if(to(Ws))return!1;for(const e of Ls.values())if(e.buf)return!1;return!0},r=()=>t()&&Date.now()-ni>=e;process.on("message",e=>{if(e)if("update-available"===e.t)Wa(e.version);else if("agent-visibility-changed"===e.t)bi();else if("restart-probe"===e.t)try{process.send({t:"restart-probe-result",nonce:e.nonce,between:t()})}catch{}else"token"===e.t&&(Ln=e.accessToken||null,Nt(_s,Ln,Fn).then(e=>{!e&&Ln&&process.stderr.write("\n ⚠ realtime auth refresh failed; private bridge features may need a reconnect.\n")}),Ps(),ja&&qa())}),setInterval(()=>{try{process.send({t:"idle",idle:r(),between:t(),webPeer:li()})}catch{}},5e3).unref()}else Ss&&setTimeout(async()=>{try{const e=new AbortController,t=setTimeout(()=>e.abort(),8e3),r=await fetch("https://registry.npmjs.org/thinkpool-pair/latest",{signal:e.signal,headers:{accept:"application/json"}}).finally(()=>clearTimeout(t));if(!r.ok)return;const o=await r.json(),n="string"==typeof o?.version?o.version:null;if(!n)return;const s=e=>String(e).split("-")[0].split(".").map(e=>parseInt(e,10)||0),i=s(n),a=s(Ss);let c=!1;for(let e=0;e<3;e++){if((i[e]||0)>(a[e]||0)){c=!0;break}if((i[e]||0)<(a[e]||0))break}c&&process.stderr.write(`\n ◆ thinkpool-pair ${n} is out (you're on ${Ss}).\n To update: stop this bridge (Ctrl-C), then rerun:\n npx thinkpool-pair@latest ${Zn}\n Your session resumes on restart (you'll be asked to continue it).\n For hands-off updates with no interruption, install the background\n service: npx thinkpool-pair@latest install-service ${Zn}\n`)}catch{}},6e4).unref();async function nc(e=0,t=!0){if(!Zs){Zs=!0,mi.close(),setTimeout(()=>process.exit(e),1500),clearInterval(Wi);try{yt()}catch{}try{Tt.close().catch(()=>{})}catch{}if(t)try{const e=Buffer.from("\r\n[ shared session ended ]\r\n","utf8").toString("base64");for(const t of Ls.keys())pi("pty-out",{term:t,b64:e})}catch{}for(const e of Ws.values())try{e.imageQueue?.close()}catch{}for(const e of Ws.values())try{e.flush?.()}catch{}for(const e of Ls.values())try{e.term.kill()}catch{}for(const e of Ws.values())try{e.session.end()}catch{}Ja();try{await Ms.untrack()}catch{}try{await _s.removeChannel(Ms)}catch{}try{Mi&&await _s.removeChannel(Mi)}catch{}try{await _s.removeChannel(Us)}catch{}try{await _s.removeChannel(Fs)}catch{}try{await _s.removeChannel(Bs)}catch{}setTimeout(()=>process.exit(e),250)}}process.on("SIGINT",()=>nc(0)),process.on("SIGTERM",()=>nc(0)),process.on("uncaughtException",e=>{if(!e||"EPIPE"!==e.code&&"ECONNRESET"!==e.code&&"ERR_STREAM_WRITE_AFTER_END"!==e.code&&"ERR_STREAM_DESTROYED"!==e.code){try{process.stderr.write(`\n ⚠ uncaughtException: ${e?.stack||e}\n ◆ shutting down cleanly for a fresh respawn.\n`)}catch{}nc(1)}else try{process.stderr.write(`\n ⚠ ignored benign ${e.code} (not fatal): ${e?.message||""}\n`)}catch{}}),process.on("unhandledRejection",e=>{try{process.stderr.write(`\n ⚠ unhandledRejection (non-fatal, continuing): ${e?.stack||e}\n`)}catch{}});
2
+ import e from"node:os";import t from"node:fs";import r from"node:path";import o from"node:readline";import{spawn as n,execFileSync as s}from"node:child_process";import{fileURLToPath as i}from"node:url";import{createRequire as a}from"node:module";import{randomUUID as c}from"node:crypto";import{createClient as l}from"@supabase/supabase-js";import{serveDecision as d,fetchServeRow as u,refusalMessage as m,gateFailAction as p}from"./serve-consent.mjs";import{reapTerminalRow as h}from"./reap-terminal.mjs";import{reconcileTerminalRows as f}from"./terminal-row-reconcile.mjs";import{cancelDurableDispatchPermissions as w,cancelDurablePermissions as g}from"./dispatch-permission-cleanup.mjs";import{createPermNotifier as v,shouldNotifyTurnDone as y,shouldRecordTurnDone as k,permissionSummary as b,clipSummary as $,isUserFacingLane as T,DEFAULT_MIN_TURN_MS as I}from"./agent-notify.mjs";import{resolveProviderEnv as R,resolveProviderRef as S,resolveProviderResiliencePolicy as C,providerNameMap as x,publicKeyB64 as _,bridgeHostId as A,announceProviders as P,listProviders as N,effectiveLaneModel as O,sameProviderEnv as E,providerModel as D}from"./providers.mjs";import{createMemoryCircuit as j,providerResilienceCapAdmission as q}from"./provider-resilience.mjs";import{validateProviderSwitch as K,providerSwitchPlan as M,BUILTIN_PROVIDER as U}from"./switch-provider.mjs";import{createSdkMcpServer as F,tool as B}from"@anthropic-ai/claude-agent-sdk";import{z as L}from"zod";import{readCodexDefaultModel as W,readCodexModels as H,codexConfigForMode as z,codexThreadCanResume as J}from"./codex-session.mjs";import{codexAccountUsageLine as G,codexCreditsReportLine as Y,codexLimitReportLine as V}from"./codex-commands.mjs";import{withMcpSessionFactory as Q}from"./codex-mcp-http.mjs";import{startStructuredSession as X}from"./runtime-session.mjs";import{admitRuntimeCapability as Z}from"./runtime-contract.mjs";import{cleanTerminalName as ee,modelTerminalNameInput as te}from"./terminal-name.mjs";import{defaultStructuredMode as re,normalizeStructuredEffort as oe,reasoningEffortsForLane as ne,shouldDeferStructuredRuntime as se,structuredModeForSlice as ie,structuredModeLocked as ae,structuredModesForLane as ce,structuredRuntimeForCommand as le,structuredRuntimeMetadata as de,structuredRuntimeSupportsMode as ue}from"./runtime-registry.mjs";import{codexUltraLaneEligible as me}from"./reasoning-effort.mjs";import{commandCatalogForRuntime as pe,commandHelpLine as he,reconcileCommandCatalog as fe}from"./command-catalog.mjs";import{gitDiffReport as we}from"./git-diff-report.mjs";import{repoSearch as ge}from"./repo-search.mjs";import{formatProjectIntelligence as ve,ProjectIntelligence as ye,PROJECT_INTELLIGENCE_OPERATIONS as ke,PROJECT_INTELLIGENCE_TOOL_ANNOTATIONS as be}from"./project-intelligence.mjs";import{probeHermesRuntime as $e}from"./hermes-probe.mjs";import{hermesRequiredMcpTools as Te,hermesRoleFor as Ie}from"./hermes-policy.mjs";import{canonicalRoomFilePath as Re,waitForNativeImages as Se}from"./codex-images.mjs";import{createManagedLaneWorktree as Ce,removeManagedLaneWorktree as xe}from"./lane-worktree.mjs";import{commandOnPath as _e}from"./agent-detect.mjs";import{agentVisibilityStates as Ae}from"./agent-visibility.mjs";import{requiresSdkAdmission as Pe,sdkSmokePassed as Ne}from"./sdk-admission.mjs";import{hermesUserInputResponse as Oe}from"./question-response.mjs";import{hostMemoryAdmission as Ee}from"./host-memory.mjs";import{HostCapacityAuthority as De}from"./host-capacity.mjs";import{admitAbortRequest as je,queueAbortBarrier as qe,takePendingAbortRequest as Ke,waitForAbortBarrier as Me}from"./abort-turn-barrier.mjs";import{PAIR_CLI as Ue,pairCli as Fe}from"./command-guidance.mjs";import{explicitKeepAwakeChoice as Be,keepAwakeEnabled as Le,saveKeepAwakePreference as We,startKeepAwake as He}from"./keep-awake.mjs";const ze=new Set(["default","acceptEdits","plan","review","bypassPermissions"]);import{FLOW_CONDUCTOR_PROMPT as Je,FLOW_LANE_PROMPT as Ge,FLOW_CODEX_CONDUCTOR_PROMPT as Ye,FLOW_CODEX_LANE_PROMPT as Ve,buildConductorEnv as Qe,assembleCrossWaveContext as Xe,buildLanePrompt as Ze}from"./flow-conductor.mjs";import{legacyBuilderCompletionAllowed as et,normalizeBaselineEvidence as tt,normalizePlanOutput as rt,validatePlanForRuntime as ot,validateTaskContractSeal as nt,validReviewTargetShape as st}from"./flow-task-graph.mjs";import{normalizeFlowRuntime as it,flowLaneModelFor as at,flowConductorModelFor as ct,spawnedLaneModelFor as lt,modelCatalogValues as dt,resolveCodexModel as ut,resolveHermesOpenModel as mt,assertRuntimeModelCompatible as pt}from"./flow-models.mjs";import{writeLaneArtifact as ht,digestSlice as ft,appendDigest as wt,resumeLane as gt}from"./flow-context-store.mjs";import{createFlowWorktree as vt,worktreeSpec as yt}from"./flow-worktree.mjs";import{startPreview as kt,stopAllPreviews as bt,previews as $t}from"./flow-preview.mjs";import{ViewportManager as Tt,createViewportTools as It,sharedViewportBrowser as Rt}from"./viewport.mjs";import{deleteDesignAssetDraft as St,designPrompt as Ct,designTranscript as xt,materializeDesignAsset as _t,refreshDesignSource as At,resolveManifestDesignSource as Pt,resolveManifestDisplaySource as Nt,restoreDesignSources as Ot,syncRealtimeAuth as Et,validateDesignBatchRequest as Dt}from"./design-edit.mjs";function jt(e,t=null){for(const[r,o]of $t)if("string"==typeof r&&(t?r===`lane:${e}:${t}`:r.startsWith(`lane:${e}:`)))try{o.stop()}catch{}}import{FLOW_REVIEWER_PROMPT as qt,FLOW_CODEX_REVIEWER_PROMPT as Kt,revertLane as Mt,parseReviewVerdict as Ut,reviewVerdictToReflection as Ft}from"./flow-review.mjs";import{createFlowReviewReceipt as Bt,createFlowReviewSingleFlight as Lt,isFlowReviewReceipt as Wt}from"./flow-receipt.mjs";import{collectFlowScopeEvidence as Ht,normalizeFlowScopeEvidence as zt}from"./flow-scope-evidence.mjs";import{formatPastWorkSearch as Jt,searchPastWork as Gt}from"./past-work-search.mjs";import{reviewGateDecision as Yt}from"./flow-review-gate.mjs";import{IMMUTABLE_REVIEW_READ_TOOL_EXTRAS as Vt,UNSANDBOXED_REVIEW_CHECK_TOOL_EXTRAS as Qt,readReviewFile as Xt,runReviewCheck as Zt}from"./review-check.mjs";import{pairAdjudicationPrompt as er,reviewReflectionDecision as tr,REVIEW_DEFAULTS as rr}from"./flow-review-reflect.mjs";import{mergeWorktrees as or,inlineSingleHtml as nr,initRepo as sr}from"./flow-assembly.mjs";import{canDispatch as ir,makeBudget as ar,recordSpend as cr,killSwitchEnv as lr}from"./flow-budget.mjs";import{prepareRedispatch as dr,redispatchKey as ur}from"./flow-redispatch.mjs";import{sanitizeSession as mr}from"./transcript-sanitize.mjs";import{boundStructuredLog as pr,STRUCTURED_LOG_BYTE_CAP as hr}from"./event-bounds.mjs";import{executeFlowRevert as fr}from"./flow-host-revert.mjs";const wr=new Map,gr=new Set,vr=new Map,yr=(e,t,r)=>{if(!e||!t||!r)return null;try{return s("git",["-C",e,"diff","--name-only","--diff-filter=ACMRD",`${t}..${r}`],{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).split("\n").map(e=>e.trim()).filter(Boolean)}catch{return null}};import{formatPeek as kr,PEEK as br,readTerminalTurnBudgetDecision as $r,siblingsOf as Tr,resolveSibling as Ir,crossPostDecision as Rr,CROSSPOST as Sr,spawnDecision as Cr,SPAWN as xr,CROSSROOM as _r,CROSSROOM_BUS as Ar,formatPairRoster as Pr,crossRoomPostDecision as Nr,formatRoomNow as Or,formatClosableHint as Er,closeLaneDecision as Dr,laneBusyOf as jr,laneStatusOf as qr,settleLaneBusy as Kr,settleLaneControl as Mr,nativeClaudeFallbackHint as Ur,buildDispatchPreview as Fr,authorizeDirectDispatch as Br,activeWorkerCapacityDecision as Lr,machineCapacityDecision as Wr,countActiveDispatchedWorkers as Hr,maxSpawnedFor as zr}from"./cross-terminal.mjs";import{createStandalonePairResponder as Jr,standalonePairIdentity as Gr}from"./direct-pair-room.mjs";import{dispatchPendingRecap as Yr,recoverInterruptedTurn as Vr,recoverMissingResumeOnce as Qr,sendInterruptedContinue as Xr,shouldAttemptNativeResume as Zr,supersedeInterruptedResume as eo}from"./interrupted-resume.mjs";import{supersedeDispatchLease as to}from"./dispatch-lease.mjs";import{realtimeRecoveryDecision as ro,turnInFlight as oo}from"./update-gate.mjs";import{saveSession as no,flushSession as so,deleteSession as io,loadAll as ao,loadArchived as co,canResume as lo,loadPtyId as uo,savePtyId as mo,loadNames as po,saveNames as ho,appendDurableEvents as fo,seedDurableEvents as wo,readDurablePage as go,readDurableOldestSeq as vo,searchDurableSessionEvents as yo,hasDurableArchive as ko,servesHistoryPage as bo,acknowledgePendingScheduledOutcome as $o,commitRecordedScheduledOutcome as To,deletePendingScheduledOutcome as Io,loadPendingScheduledOutcome as Ro,loadPendingScheduledOutcomes as So,savePendingScheduledOutcome as Co}from"./session-store.mjs";import{stampEvent as xo,makeSeqCounter as _o,maxSeq as Ao,seqable as Po,capReplayEvents as No,chunkReplayEvents as Oo,boundEventForBroadcast as Eo,inlineImageBlocks as Do,ImageEventQueue as jo,imageQueueConfig as qo,uploadCodeImage as Ko,usageReportLine as Mo,codexUsageReportLine as Uo,appendCurrentPersonRequest as Fo,buildCheckpointFromLog as Bo,buildRecapFromLog as Lo,resolveCheckpointCarry as Wo,RECAP_CAP as Ho,trimmedBeforeSeq as zo,firstSeq as Jo}from"./event-id.mjs";import{createLatestReplayPump as Go,requestedReplayIds as Yo}from"./replay-transport.mjs";import{createEventDeliveryQueue as Vo}from"./event-delivery-queue.mjs";import{buildLaneWorkSnapshot as Qo}from"./lane-work-snapshot.mjs";import{formatMcpFlight as Xo,normalizeMcpFlight as Zo,recordMcpFlightEvent as en}from"./mcp-flight-recorder.mjs";import{classifyCodeEvent as tn,unknownCodeEventNotice as rn}from"./code-event-contract.mjs";import{fetchPairControlDeliveryAuthority as on}from"./pair-control-authority.mjs";import{finishScheduledRunWithRetry as nn,pollDueScheduledRuns as sn,sanitizeScheduledOutcomeIntent as an,scheduledOutcomeReconciliationComplete as cn,scheduledRunDeadlineRequired as ln,scheduledRunSpawnAdmission as dn,scheduledRunsCapability as un,scheduledRunsEnabled as mn}from"./scheduled-runs.mjs";import{acquireScheduledRunAdmission as pn,releaseScheduledRunAdmission as hn}from"./scheduled-run-admission.mjs";import{SIDE_HANDOFF_PROMPT as fn,SIDE_ROLE_PROMPT as wn,appendSideContext as gn,assistantTextSince as vn,dispatchSideContexts as yn,sideContextBlock as kn,sideSnapshot as bn}from"./side-lane.mjs";import{acknowledgeWorkerCompletions as $n,enqueueWorkerCompletion as Tn,workerCompletionPrompt as In,workerCompletionRecord as Rn}from"./worker-completion.mjs";import{planMeterLine as Sn}from"./plan-meters.mjs";import{priceForModel as Cn}from"./model-prices.mjs";import{loadHermesModelCache as xn,saveHermesModelCache as _n}from"./hermes-model-cache.mjs";import{makeThrottledTrack as An,recoveryBackoffMs as Pn}from"./presence.mjs";import{MockupDeliveryQueue as Nn,completeMockupManifest as On,isMockupDeliveryBoundary as En}from"./mockup-delivery.mjs";import{resolveAnonKey as Dn,DEFAULT_SUPABASE_URL as jn}from"./supabase-key.mjs";import{buildTerminalRolePrompt as qn,HERMES_VISIBLE_WORKER_FALLBACK_RULE as Kn,THINKPOOL_PROMPT_BUNDLE as Mn}from"./thinkpool-room-prompt.mjs";const Un=process.env.TP_SUPABASE_URL||jn,Fn=process.env.TP_WEB_BASE||"https://thinkpool.io",Bn=qo();let Ln=xn();const{key:Wn,source:Hn}=await Dn({supabaseUrl:Un,webBase:Fn,log:e=>{process.env.TP_DEBUG&&console.error(` ◇ ${e}`)}});process.env.TP_DEBUG&&console.error(` ◇ supabase anon key source: ${Hn}`);let zn=process.env.TP_ACCESS_TOKEN||null,Jn=null;try{Jn=(await import("node-pty")).default??await import("node-pty")}catch{console.error("\n ⚠ node-pty not built — raw terminal sharing is off (structured Claude still works).\n For PTY mode (bash / aider / codex / TP_PTY=1): install a C toolchain, then `npm i` in the bridge.\n (Xcode CLT on mac · build-essential on linux · VS Build Tools on Windows.)\n")}const Gn=[{label:"Claude Code",cmd:"claude",resume:{args:["--continue"],probe:function(){try{const o=r.resolve(process.cwd()).replace(/[/\\.:]/g,"-");return t.readdirSync(r.join(e.homedir(),".claude","projects",o)).length>0}catch{return!1}}}},{label:"Codex CLI",cmd:"codex"},{label:"Hermes Agent",cmd:"thinkpool",availability:()=>$e().available},{label:"Gemini CLI",cmd:"gemini"},{label:"Aider",cmd:"aider"},{label:"Cursor CLI",cmd:"cursor-agent"},{label:"opencode",cmd:"opencode"},{label:"Copilot CLI",cmd:"copilot"},{label:"Goose",cmd:"goose"},{label:"Crush",cmd:"crush"},{label:"Qwen Code",cmd:"qwen"}],Yn=process.argv.slice(2);if("install-service"===Yn[0]||"restart-service"===Yn[0]){const e=Be(Yn);null===e||We(e)||(process.stderr.write(" ⚠ could not save the keep-awake setting; service left unchanged.\n"),process.exit(1))}if("privacy-report"===Yn[0]){const{runPrivacyReport:e}=await import("./privacy-report.mjs");e(),process.exit(0)}if("install-service"===Yn[0]||"uninstall-service"===Yn[0]){const e=Yn[1]||"",t=!e||e.startsWith("-")?null:e.toUpperCase().trim(),r=Yn.indexOf("--"),o=r>=0?Yn.slice(r+1):[],n=Yn.includes("--auto-update"),s=await import("./service.mjs");if("install-service"===Yn[0]){const e=n?s.installService(t,o,{autoUpdate:n}):await s.installAndConfirmService(t,o);process.exit(!1===e?1:0)}else s.uninstallService(t);process.exit(0)}if("restart-service"===Yn[0]){const e=Yn[1]||"",t=!e||e.startsWith("-")?null:e.toUpperCase().trim(),r=await import("./service.mjs"),o=Yn.includes("--current")?r.restartService(t):await r.updateAndConfirmService(t);process.exit(o?0:1)}const{applyProviderEnv:Vn}=await import("./provider.mjs"),Qn=Vn();if("login"===Yn[0]){const{runLogin:e}=await import("./account.mjs");await e(Un,Wn,Fn)}if("bind"===Yn[0]){const{runBind:e}=await import("./account.mjs");e(Yn[1],Yn[2])}if("set-default-dir"===Yn[0]){const{saveDefaultDir:t}=await import("./auth-store.mjs");let r=(Yn[1]||"").trim();r.startsWith("~")&&(r=r.replace(/^~/,e.homedir())),r||(console.error(` usage: ${Fe("set-default-dir","<dir>")}`),process.exit(1)),t(r),console.log(` ◆ default project dir set → ${r}\n New/unbound sessions auto-serve from here — no per-session bind. Takes effect next serve tick.`),process.exit(0)}if("provider"===Yn[0]){const{runProvider:e}=await import("./provider.mjs");await e(Yn.slice(1)),process.exit(0)}if("setup-hermes"===Yn[0]){const e=Yn.includes("--clone"),t=Yn.includes("--clean");e&&t&&(console.error(" choose one Hermes setup mode: --clone or --clean"),process.exit(1));let r=e?"clone":t?"clean":void 0;if(!r&&process.stdin.isTTY){const e=await new Promise(e=>{const t=o.createInterface({input:process.stdin,output:process.stderr});t.question("\n Clone your active Hermes provider/config into an isolated thinkpool profile? [Y/n] ",r=>{t.close(),e(String(r).trim())})});r=/^n/i.test(e)?"clean":"clone"}try{const{setupHermesRuntime:e}=await import("./hermes-setup.mjs"),t=e({mode:r});process.stderr.write(`\n ◆ Hermes ${t.version||""} is ready for thinkpool ordinary lanes.\n profile: ${t.profile} (${t.created?`${t.mode} created`:"existing"})\n hidden delegation: blocked\n${t.created&&"clean"===t.mode?" provider: run `thinkpool setup` before the first model turn\n":""}\n`),process.exit(0)}catch(e){console.error(`\n ◇ Hermes setup failed: ${e?.message||e}\n New profile: npx thinkpool-pair@latest setup-hermes --clone\n Clean profile: npx thinkpool-pair@latest setup-hermes --clean\n`),process.exit(1)}}if("verify-hermes-isolation"===Yn[0])try{const{verifyHermesMcpIsolation:e}=await import("./hermes-isolation.mjs"),t=await e({rounds:2});process.stderr.write(`\n ◆ Hermes MCP isolation HELD for ${t.length} consecutive two-lane rounds.\n Each ACP session advertised only its lane-bound marker endpoint.\n No model inference was used.\n\n`),process.exit(0)}catch(e){console.error(`\n ◇ Hermes MCP isolation VIOLATED or unproven: ${e?.message||e}\n`),process.exit(1)}if((!Yn[0]||"setup"===Yn[0])&&process.stdin.isTTY){const{runLauncher:e,detectState:t}=await import("./launcher.mjs"),r=await import("./service.mjs"),s=i(import.meta.url),a={print:e=>process.stderr.write(e+"\n"),ask:e=>new Promise(t=>{const r=o.createInterface({input:process.stdin,output:process.stderr});r.question(e,e=>{r.close(),t(String(e).trim())})})},c={pairRoom:({room:e,agentCmd:t,resumeArgs:r=[],headless:o})=>new Promise(()=>{const i=[s,e,...o?["--headless"]:[],"--",t,...r];n(process.execPath,i,{stdio:"inherit"}).on("exit",e=>process.exit(null==e?0:e))}),serveAccountForeground:async()=>{He({enabled:Le([])});const{runAccount:e}=await import("./account.mjs");await e(Un,Wn)},installService:({room:e=null,agentCmd:t}={})=>r.installAndConfirmService(e,t?[t]:[]),uninstallService:({room:e=null}={})=>{r.uninstallService(e)},restartService:({room:e=null}={})=>{r.restartService(e)},restartUpdateService:async({room:e=null}={})=>"win32"===process.platform?r.updateService(e):r.updateAndConfirmService(e),relaunchLauncher:async()=>{const e=r.serviceRuntimeVersion(null);if(!e)return a.print("\n ⚠ the managed runtime was confirmed earlier but could not be resolved for launcher handoff; staying in this launcher."),!1;let t="";try{t=r.provisionRuntime(e)}catch(t){return a.print(`\n ⚠ could not open the verified v${e} launcher: ${t?.message||t}`),!1}return new Promise(e=>{const r=n(process.execPath,[t],{stdio:"inherit",cwd:process.cwd(),env:process.env});r.once("error",t=>{a.print(`\n ⚠ launcher handoff failed: ${t?.message||t}`),e(!1)}),r.once("exit",()=>e(!0))})},login:async()=>{const{runLogin:e}=await import("./account.mjs");await e(Un,Wn,Fn)},setProvider:async({kind:e,base:t,token:r,model:o})=>{const{runProvider:n}=await import("./provider.mjs"),s="custom"===e?["custom","--base",t,"--token",r,...o?["--model",o]:[]]:["anthropic"];await n(s)},setKeepAwake:async({enabled:e})=>We(e)?(r.isServiceInstalled(null)&&r.restartService(null),!0):(a.print("\n ⚠ could not save the keep-awake setting; nothing was changed."),!1),setupHermes:async({mode:e})=>{const{setupHermesRuntime:t}=await import("./hermes-setup.mjs"),r=t({mode:e});a.print(`\n ✓ Hermes ${r.version||""} ready — isolated profile, ACP healthy, hidden delegation blocked.`),r.created&&"clean"===r.mode&&a.print(" Run `thinkpool setup` once to choose a provider before the first model turn.")}};await e({actions:c,io:a,refresh:t}),process.exit(0)}const Xn=process.env.TP_SDK_SMOKE_PATH||r.join(r.dirname(i(import.meta.url)),"sdk-smoke.mjs");let Zn={ok:null,version:"unknown",reason:""};function es(){try{const e=a(import.meta.url);let o=r.dirname(e.resolve("@anthropic-ai/claude-agent-sdk"));for(let e=0;e<8;e++){try{const e=JSON.parse(t.readFileSync(r.join(o,"package.json"),"utf8"));if("@anthropic-ai/claude-agent-sdk"===e.name)return e.version}catch{}const e=r.dirname(o);if(e===o)break;o=e}}catch{}return"unknown"}function ts(){try{return s(process.execPath,[Xn],{encoding:"utf8",timeout:22e3,stdio:["ignore","pipe","ignore"]}).trim()}catch(e){return(e.stdout||"").toString().trim()||`SMOKE:FAIL:${es()}:${"ETIMEDOUT"===e.code?"timeout":(e.message||"run error").slice(0,80)}`}}if("verify-sdk"===Yn[0]){const e=ts();console.log(e),process.exit(Ne(e)?0:1)}if(!Yn[0]||Yn[0].startsWith("-")){He({enabled:Le(Yn)});const{runAccount:e}=await import("./account.mjs");await e(Un,Wn)}const rs=(Yn[0]||"").toUpperCase().trim();rs||(console.error(`usage: ${Fe("<ROOM>","[--headless]","[--continue|--fresh]","[-- <command…>]")} | ${Ue} (account mode)`),process.exit(1)),/^[A-Z0-9_-]{2,32}$/.test(rs)||(console.error(`refused: invalid room code ${JSON.stringify(rs)} (expected 2–32 alphanumerics, dash, or underscore)`),process.exit(1)),Pe(Yn)&&(function(){const o=r.join(e.homedir(),".thinkpool-pair"),n=r.join(o,"sdk-ok"),s=es();Zn.version=s;let i="";try{i=t.readFileSync(n,"utf8").trim()}catch{}if(i&&i===s)return void(Zn.ok=!0);const a=ts().match(/^SMOKE:(PASS|FAIL):([^:\n]*)(?::(.*))?$/m);if(a&&"PASS"===a[1]){Zn={ok:!0,version:a[2]||s,reason:""};try{t.mkdirSync(o,{recursive:!0}),t.writeFileSync(n,Zn.version)}catch{}process.stderr.write(`\n ◆ agent SDK v${Zn.version} passed the compatibility smoke test.\n`)}else{Zn={ok:!1,version:a&&a[2]||s,reason:a&&a[3]||"unknown"};try{t.mkdirSync(o,{recursive:!0}),t.writeFileSync(r.join(o,"sdk-bad"),`${Zn.version}: ${Zn.reason}`)}catch{}process.stderr.write(`\n ⛔ agent SDK v${Zn.version} FAILED the compatibility smoke test — ${Zn.reason}.\n ⛔ refusing to serve agent turns. Repair or pin a known-good SDK, then restart.\n`)}}(),Zn.ok||process.exit(1));const os=Yn.indexOf("--"),ns=os>=0?Yn.slice(0,os):Yn;if(ns.includes("--supervise")||ns.includes("--keep-alive")){const e=process.argv.slice(1).filter(e=>"--supervise"!==e&&"--keep-alive"!==e);let t=1e3,r=!1,o=null;const s=()=>{const i=Date.now();o=n(process.execPath,e,{stdio:"inherit"}),o.on("exit",(e,o)=>{(r||0===e)&&process.exit(e||0);const n=Date.now()-i>6e4,a=n?1e3:t;t=n?1e3:Math.min(2*t,3e4),process.stderr.write(`\n ⚠ bridge exited (${o||`code ${e}`}); restarting in ${Math.round(a/1e3)}s…\n`),setTimeout(s,a)}),o.on("error",()=>{})};for(const e of["SIGINT","SIGTERM"])process.on(e,()=>{r=!0;try{o?.kill(e)}catch{}setTimeout(()=>process.exit(0),400)});process.stderr.write(`\n [b:${ks} r:${rs}] ◆ supervisor up — keeping the bridge for room ${rs} alive (auto-restart on crash).\n`),s(),await new Promise(()=>{})}{const{acquireMachineLock:e,releaseMachineLock:t,shouldHoldMachineLock:r}=await import("./account.mjs");r(process.env)&&!e()&&(console.error("\n ◇ A thinkpool-pair bridge is already running on this machine\n (~/.thinkpool-pair/account.lock). Only one can be active, and the running\n one already serves every room you are in — use it, or stop it first.\n (If you are certain none is running, delete that stale lock file.)\n"),process.exit(0)),r(process.env)&&process.on("exit",()=>{try{t()}catch{}})}He({enabled:Le(Yn)});const ss=Yn.includes("--headless"),is=(Yn.find(e=>e.startsWith("--auto="))||"").slice(7)||null,as=("1"===process.env.TP_STRUCTURED||Yn.includes("--structured"),le),cs=e=>!!as(e)&&"1"!==process.env.TP_PTY,ls=Gn.filter(e=>{return t=e.cmd,_e(t)&&(!e.availability||e.availability());var t}),ds=Yn.indexOf("--"),us=ds>=0?Yn.slice(0,ds):Yn,ms=us.includes("--continue"),ps=us.includes("--fresh"),hs=(e,t=!0)=>new Promise(r=>{const n=o.createInterface({input:process.stdin,output:process.stderr});n.question(e,e=>{n.close();const o=String(e).trim();r(t?!/^n/i.test(o):/^y/i.test(o))})});let fs=null,ws=[],gs=!1;if(ds>=0)[fs,...ws]=Yn.slice(ds+1),fs&&fs.startsWith("-")&&(process.stderr.write(`\n ◇ ignoring "${fs}" after \`--\` — that's a flag, not a command to share.\n`),fs=null,ws=[]);else if(!ss){0===ls.length&&(console.error(`\n No known coding-agent CLI found on your PATH.\n Install one (claude / codex / gemini / aider / cursor-agent / opencode …)\n or share a specific command: ${Fe(rs,"--","<your-command>")}\n`),process.exit(1)),fs=await(vs=ls,new Promise(e=>{if(1===vs.length||!process.stdin.isTTY)return void e(vs[0].cmd);const t=o.createInterface({input:process.stdin,output:process.stderr});process.stderr.write("\n Which coding agent do you want to share?\n\n"),vs.forEach((e,t)=>process.stderr.write(` ${t+1}) ${e.label}\n`)),process.stderr.write("\n"),t.question(" Pick a number [1]: ",r=>{t.close();const o=parseInt(String(r).trim(),10),n=Number.isInteger(o)&&o>=1&&o<=vs.length?o-1:0;e(vs[n].cmd)})}));const e=Gn.find(e=>e.cmd===fs);e?.resume&&!ps&&(ms?gs=!0:process.stdin.isTTY&&e.resume.probe()&&(gs=await hs(`\n Continue your latest ${e.label} session in this directory? [Y/n] `)),gs&&(ws=[...e.resume.args]))}var vs;if(process.stdin.isTTY&&!ss&&"1"!==process.env.THINKPOOL_PAIR_AUTOUPDATE){const o=await import("./service.mjs");o.isServiceInstalled(rs)&&(process.stderr.write(`\n ◆ a background service is already running room ${rs} (auto-updating).\n ◆ remove it with: npx thinkpool-pair@latest uninstall-service ${rs}\n\n`),process.exit(0));const n=r.join(e.homedir(),".thinkpool-pair",`${rs}.svc-declined`);let s=!1;try{s=t.existsSync(n)}catch{}if(!s){await hs("\n Run as a background service instead? It survives reboot + auto-updates,\n but runs detached — you'd stop it with 'uninstall-service', not Ctrl-C.\n Install background service? [y/N] ",!1)&&(o.installService(rs,fs?[fs,...ws]:[]),process.stderr.write(`\n [b:${ks} r:${rs}] ◆ the background service is handling room ${rs} now — you can close this terminal.\n ◆ STOP IT with: npx thinkpool-pair@latest uninstall-service ${rs}\n (closing the terminal does NOT stop it — it's detached under launchd/systemd.)\n\n`),process.exit(0));try{t.mkdirSync(r.dirname(n),{recursive:!0}),t.writeFileSync(n,(new Date).toISOString())}catch{}process.stderr.write(` [b:${ks} r:${rs}] ◆ running in this terminal. (Auto-update service anytime: npx thinkpool-pair@latest install-service ${rs})\n`)}}const ys=process.env.TP_NAME||e.userInfo().username||"host",ks=c?.().slice(0,8)||"bridgexx",bs=process.env.TP_ACCOUNT_BRIDGE_ID||null,$s=Number.parseInt(process.env.TP_ACCOUNT_BRIDGE_FENCING||"",10),Ts=Date.now(),Is=(e.hostname()||"host").split(".")[0].slice(0,24),Rs=A(),Ss=j(),Cs=process.cwd(),xs=r.basename(Cs);let _s=null;try{_s=JSON.parse(t.readFileSync(new URL("./package.json",import.meta.url),"utf8")).version}catch{}try{const o=r.join(e.homedir(),".npm","_npx"),n=t.readdirSync(o,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).filter(e=>"cache"!==e),s=e=>e?e.split(".").map(e=>parseInt(e,10)||0):[0,0,0],i=(e,t)=>{const r=s(e),o=s(t);for(let e=0;e<3;e++){if(r[e]<o[e])return!0;if(r[e]>o[e])return!1}return!1};let a=null;for(const e of n){const n=r.join(o,e,"node_modules","thinkpool-pair","package.json");try{const e=JSON.parse(t.readFileSync(n,"utf8"));e.version&&(a&&!i(a,e.version)||(a=e.version))}catch{}}a&&_s&&i(_s,a)&&process.stderr.write(` ⚠ stale-cache: running ${_s}, newest ${a}\n`)}catch{}function As(){try{let e=r.join(Cs,".git");t.statSync(e).isFile()&&(e=t.readFileSync(e,"utf8").replace(/^gitdir:\s*/i,"").trim());const o=t.readFileSync(r.join(e,"HEAD"),"utf8").trim();return o.startsWith("ref:")?o.split("/").pop():o.slice(0,7)}catch{return null}}const Ps=r.join(e.tmpdir(),"thinkpool-pair",rs),Ns=l(Un,Wn,{realtime:{params:{eventsPerSecond:60}}});let Os="free";async function Es(){const e=zn;if(e)try{const{data:t,error:r}=await Ns.auth.getUser(e),o=t?.user?.id;if(r||!o)return;const n=await fetch(`${Un}/rest/v1/profiles?select=plan&id=eq.${o}`,{headers:{apikey:Wn,Authorization:`Bearer ${e}`}});if(!n.ok)return;const s=await n.json();s?.[0]?.plan&&(Os="plus"===s[0].plan?"plus":"free")}catch{}}let Ds=null;{let e=!1;if(!zn)try{const{loadAuth:t}=await import("./auth-store.mjs");zn=t()?.access_token||null,zn&&(e=!0)}catch{}if(e)try{const{authedClient:e}=await import("./account.mjs"),t=await e(Un,Wn);t?.session?.access_token&&(zn=t.session.access_token)}catch{}try{if(zn){const{data:e}=await Ns.auth.getUser(zn);Ds=e?.user?.id||null}const{ownerId:e,name:t}=await u({supabaseUrl:Un,anonKey:Wn,token:zn,room:rs}),r=d({ownerId:e,myUid:Ds});r.serve||(process.stderr.write(m({room:rs,name:t,reason:r.reason})),process.exit(0))}catch(e){"refuse"===p(e)&&(process.stderr.write(m({room:rs,name:null,reason:"no-identity"})),process.stderr.write(`\n ◇ (serve-consent: auth rejected at the gate — ${e.message}; the stored login is expired or revoked. Re-run: ${Fe("login")})\n`),process.exit(0)),process.stderr.write(`\n ◇ serve-consent check degraded (${e.message}); proceeding without it.\n`)}}!await Et(Ns,zn,Wn)&&zn&&process.stderr.write("\n ⚠ realtime auth could not be initialized; private bridge features are unavailable.\n"),Es();const js="1"===process.env.TP_BUDGET_OFF;async function qs(e,t){const r=await fetch(`${Un}/rest/v1/rpc/${e}`,{method:"POST",headers:{apikey:Wn,Authorization:`Bearer ${zn}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!r.ok)throw new Error(`${e} ${r.status}`);const o=await r.text();return o?JSON.parse(o):null}const Ks="1"===process.env.TP_AGENT_NOTIFY_OFF,Ms=Number(process.env.TP_NOTIFY_MIN_TURN_MS)>0?Number(process.env.TP_NOTIFY_MIN_TURN_MS):I;function Us(e){if(Ks||!zn||!Ds||!rs)return;const{eventId:t,...r}=e||{},o={id:`ae:${"string"==typeof t&&/^[A-Za-z0-9_-]{1,120}$/.test(t)?t:c()}`,session_code:rs,author_id:Ds,payload:{__agent:!0,ts:Date.now(),...r}};fetch(`${Un}/rest/v1/code_messages`,{method:"POST",headers:{apikey:Wn,Authorization:`Bearer ${zn}`,"Content-Type":"application/json",Prefer:"return=minimal"},body:JSON.stringify(o)}).then(e=>{!e.ok&&process.env.TP_DEBUG&&process.stderr.write(`\n ◆ agent-event insert ${e.status}\n`)}).catch(()=>{})}let Fs=null;const Bs=Ns.channel(`tpcode:${rs}`,{config:{private:!0,broadcast:{self:!1},presence:{key:`bridge:${ys}`}}}),Ls=Ns.channel(`tpflow:${rs}`,{config:{broadcast:{self:!1}}}),Ws=Ns.channel(`tpdesign:${rs}`,{config:{private:!0,broadcast:{self:!1}}}),Hs=Ns.channel(`tpcontrol:${rs}`,{config:{private:!0,broadcast:{self:!1}}}),zs=new Map,Js=new Map;let Gs=0;function Ys(e,t=Date.now()){const r=e?.session?.turnActive??!1;return r!==e?._busyAnn&&(r&&(e._turnRev=(Number(e._turnRev)||0)+1,e._turnStart=t,e._settledTurnRev=null,e._turnSettledAt=null),e._busyAnn=r,!0)}function Vs(e,t=Date.now()){return!0!==e?._busyAnn&&(e._turnRev=(Number(e._turnRev)||0)+1,e._turnStart=t,e._busyAnn=!0,e._settledTurnRev=null,e._turnSettledAt=null,!0)}function Qs(e,t,{options:r,visibleEvent:o,rejectionMessage:n="The agent did not accept this turn; retry after the lane is available."}={}){if(!e?.session)return{accepted:!1,error:new Error("session unavailable")};Ys(e);let s=!1,i=null;try{s=!1!==e.session.sendTurn(t,r)}catch(e){i=e}if(s?Vs(e):Ys(e),o&&(_a(e,o),wi("code-event",{term:e.id,evt:o})),!s){const t={kind:"error",message:n,recoverable:!0};_a(e,t),wi("code-event",{term:e.id,evt:t})}return Ii(),{accepted:s,error:i}}function Xs(e){e?.pendingSideContexts?.length&&!e._sideContextTimer&&(e._sideContextTimer=setTimeout(()=>{e._sideContextTimer=null,function(e){if(!e?.pendingSideContexts?.length||"function"!=typeof e.session?.sendTurn)return!1;const t=yn({contexts:e.pendingSideContexts,busy:!0===e.session?.turnActive,sendTurn:t=>e.session?.sendTurn(t)});return e.pendingSideContexts=t.pending,!!t.dispatched&&(Vs(e),e.flush?.(),Ii(),!0)}(e)&&process.stderr.write("\n ◆ started main turn from side-lane handoff.\n")},0),e._sideContextTimer.unref?.())}function Zs(e){e?.pendingWorkerCompletions?.length&&!e._workerCompletionTimer&&(e._workerCompletionTimer=setTimeout(()=>{e._workerCompletionTimer=null,function(e){if(!e?.pendingWorkerCompletions?.length||"function"!=typeof e.session?.sendTurn)return!1;if(e.workerCompletionsInFlight?.length)return!1;if(jr(e)||(e.pending?.size||0)>0)return!1;const t=e.pendingWorkerCompletions.slice(),r=In(t);return r?(e.workerCompletionsInFlight=t,e.flush?.(),!!Qs(e,r,{rejectionMessage:"The worker-completion continuation was not accepted; it remains queued."}).accepted||(e.workerCompletionsInFlight=[],e.flush?.(),!1)):(e.pendingWorkerCompletions=[],!1)}(e)&&process.stderr.write("\n ◆ worker finished — continued its owning terminal.\n")},0),e._workerCompletionTimer.unref?.())}function ei(e,t){return t&&null==t.turnRev&&Number(e?._turnRev)>0&&(t.turnRev=e._turnRev),t}let ti=null,ri=!1;const oi=[];let ni=0;const si="1"===process.env.TP_BACKGROUND_WARM;async function ii(){for(;ni<3&&oi.length;){const e=oi.shift();if(!e||e.warmed||e.warming||!e.session||e.session.started)continue;const t=await Mi(e);if(!t.ok){process.stderr.write(`\n ◇ background warm held for ${String(e.id).slice(0,8)} — ${t.reason||"host runtime capacity is full"}\n`);break}e.warming=!0,ni++;try{e.session.warm?.()}catch{e.warming=!1,ni--,Ui(e,t);continue}e.warmTimer=setTimeout(()=>{e.warming&&(e.warming=!1,ni=Math.max(0,ni-1),ii())},1e5)}}let ai=Date.now();const ci=()=>{if(ai=Date.now(),process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD)try{process.send({t:"busy"})}catch{}};let li=null,di=!1,ui=!1;const mi=()=>{try{const e=Bs.presenceState()||{};for(const t of Object.values(e))for(const e of t||[])if(e&&"bridge"!==e.role)return!0}catch{}return!1},pi=2e5,hi=async(e,t,r=Bs)=>{"pty-out"!==e&&"code-event"!==e||(ai=Date.now()),t=((e,t)=>{let r,o;try{r=JSON.stringify(t)}catch{return t}if(!r||r.length<=pi)return t;process.stderr.write(`\n ⚠ oversized ${e} frame: ${r.length}B (term ${String(t?.term||"?").slice(0,8)}) — defanging so Realtime doesn't drop it\n`);try{o=JSON.parse(r)}catch{return t}if(o.evt&&"object"==typeof o.evt&&(o.evt=Eo(o.evt,1e5)),Array.isArray(o.events)){o.events=o.events.map(e=>Eo(e,1e5));let e=0,t=0;for(;o.events.length>1&&JSON.stringify(o).length>pi&&e++<1e4;)o.events.shift(),t++;if(t){const e=Jo(o.events);"number"==typeof e&&(o.trimmedBefore=Math.max(o.trimmedBefore??0,e))}}return o})(e,t);try{return r.channelAdapter?.canPush?.()??1?await r.send({type:"broadcast",event:e,payload:t}):await r.httpSend(e,t)}catch{return null}},fi=Vo({send:({event:e,payload:t,ch:r})=>hi(e,t,r)}),wi=(e,t,r=Bs)=>{"code-event"!==e||r!==Bs?hi(e,t,r):fi.enqueue({event:e,payload:t,ch:r})},gi=Go({send:({event:e,payload:t})=>hi(e,t)}),vi=po(rs),yi=new Set,ki=(e,t,r=null)=>{wi("term-opened",{id:e,kind:t,sideParent:r?.sideParent||void 0,sideTask:r?.sideTask||void 0,name:vi[e]||void 0})},bi=new Set,$i=new Map;let Ti=null;const Ii=()=>{const e=x(),t=new Map(Ae(ls.map(e=>e.cmd)).map(e=>[e.cmd,e.enabled])),o=++Gs;return hi("bridge",{v:2,name:ys,bridge_id:ks,started_at:Ts,rev:o,repo:xs,branch:As(),...!1===Zn.ok?{sdkWarn:`${Zn.version}: ${Zn.reason}`}:{},models:Ti||void 0,cwd:Cs,version:_s,promptBundle:Mn,host:Is,hostId:Rs,uid:Ds||void 0,provider:Qn.provider,providerBaseUrl:Qn.baseUrl||void 0,ctxCarry:!0,providerPubKey:_(),providers:P(),pendingUpdate:li,updir:Ps.split(r.sep).join("/"),scheduledRuns:un(),capacity:{workerActive:Hr(Js.values()),workerLimit:zr(Os),hostStatus:Oi},agents:ls.map(e=>{let r=!1;if(e.resume)try{r=e.resume.probe()}catch{}return{label:e.label,cmd:e.cmd,canResume:r,enabled:!1!==t.get(e.cmd)}}),terms:[...[...zs.entries()].map(([e,t])=>({id:e,cmd:t.cmd,alive:!0,cols:t.term.cols,rows:t.term.rows,name:vi[e]||void 0,...qr(t)})),...[...Js.entries()].map(([t,r])=>({id:t,cmd:r.cmd,kind:"structured",runtime:r.runtime||"claude",alive:!0,...qr(r),turnRev:Number(r._turnRev)||0,...jr(r)&&r._turnStart?{turnStartedAt:r._turnStart}:{},...!jr(r)&&Number(r._settledTurnRev)>0&&Number(r._settledTurnRev)===Number(r._turnRev)?{settledTurnRev:Number(r._settledTurnRev),turnSettledAt:Number(r._turnSettledAt)||void 0}:{},hasTranscript:r.log.length>0,commands:r.commands,mode:r.mode||void 0,effort:r.effort||void 0,name:vi[t]||void 0,model:r.model||void 0,capabilities:{...de(r.runtime||"claude"),modes:ce(r.runtime||"claude",r),efforts:ne(r.runtime||"claude",r)},..."codex"===r.runtime?{approvalPolicy:z(r.mode).approvalPolicy,models:r.models||[],canSteer:r.session?.canSteer??!1}:"hermes"===r.runtime?{models:r.models||[],canSteer:r.session?.canSteer??!1}:{},...null!=r.archiveOldestSeq?{oldestSeq:r.archiveOldestSeq}:{},...r.spawnedBy?{spawned:!0,spawnedBy:r.spawnedBy}:{},...r.sideParent?{sideParent:r.sideParent,sideTask:r.sideTask||void 0,sideHandback:!!r.sideHandback}:{},...r.flowSessionId?{flowId:r.flowSessionId,flowRole:r.flowTaskKey?"lane":"conductor"}:{},...r.scheduleRunId?{scheduleRunId:r.scheduleRunId}:{},...r.provider&&"anthropic"!==r.provider?{provider:{id:r.provider,name:e[r.provider]||r.provider}}:{}}))]})},Ri=async(e,t,r,o=!0)=>{if(zn&&e&&t)try{const n=r?`&name=eq.${encodeURIComponent(r)}`:`&or=${encodeURIComponent("(name.is.null,name.eq.Terminal)")}`,s=await fetch(`${Un}/rest/v1/code_terminals?id=eq.${encodeURIComponent(e)}${n}&select=id`,{method:"PATCH",headers:{apikey:Wn,Authorization:`Bearer ${zn}`,"Content-Type":"application/json",Prefer:"return=representation"},body:JSON.stringify({name:t})}),i=s.ok?await s.json().catch(()=>[]):[];if(o&&(!s.ok||!Array.isArray(i)||0===i.length)){const o=setTimeout(()=>{Ri(e,t,r,!1)},1500);o.unref?.()}}catch{if(o){const o=setTimeout(()=>{Ri(e,t,r,!1)},1500);o.unref?.()}}},Si=async(e,t,r=!0)=>{if(!zn||!e||!t)return;const o=new AbortController,n=setTimeout(()=>o.abort(),4500);try{const s=await fetch(`${Fn}/api/code-terminal-name`,{method:"POST",headers:{Authorization:`Bearer ${zn}`,"Content-Type":"application/json"},body:JSON.stringify({code:rs,terminalId:e,task:t}),signal:o.signal});clearTimeout(n);const i=await s.json().catch(()=>({}));if(r&&404===s.status&&"terminal_pending"===i?.code){const r=setTimeout(()=>{Si(e,t,!1)},1500);return void r.unref?.()}if(!s.ok)return;const a=ee(i?.name);a&&((e,t)=>{if(!t||yi.has(e))return!1;const r=$i.get(e);if(vi[e]&&vi[e]!==r)return!1;const o=vi[e]||null,n=((e,t)=>{const r=new Set(Object.entries(vi).filter(([t])=>t!==e).map(([,e])=>String(e).toLowerCase()));if(!r.has(t.toLowerCase()))return t;for(let e=2;e<100;e++){const o=` ${e}`,n=`${t.slice(0,48-o.length).trim()}${o}`;if(!r.has(n.toLowerCase()))return n}return t})(e,t);vi[e]===n||(vi[e]=n,$i.set(e,n),ho(rs,vi),Ri(e,n,o),Ii())})(e,a)}catch{clearTimeout(n)}},Ci=(e,t)=>{const r=Js.get(e);if(!r||vi[e]||yi.has(e)||bi.has(e))return;if(r.log?.some(e=>"you"===e?.kind))return;const o=te(t);o&&(bi.add(e),Si(e,o))},xi=!(!process.send||"1"!==process.env.THINKPOOL_PAIR_ACCOUNT_CHILD),_i=new De,Ai=new Map,Pi=new Set,Ni=new Map;let Oi="available",Ei=null;const Di=()=>{if(!Ee("resume queued Dispatch work").ok)return Oi="held",void ji();Oi="available",Ii(),wi("capacity-changed",{},Ls)},ji=()=>{Oi="held",Ei||(Ei=setInterval(()=>{Ee("resume queued Dispatch work").ok&&(clearInterval(Ei),Ei=null,Di())},5e3),Ei.unref?.(),Ii())},qi=async e=>{if(!e)return{ok:!1,code:"invalid_capacity_request"};if(!xi){const t=_i.acquire({room:rs,terminalId:e});return t.ok&&Pi.add(e),t.ok||(Oi="held"),t}const t=c();return new Promise(r=>{const o=setTimeout(()=>{Ai.delete(t),Oi="held";try{process.send({t:"capacity-release",terminalId:e})}catch{}r({ok:!1,code:"capacity_authority_unavailable",reason:"The bridge capacity authority did not answer. No lane was opened; retry when the bridge reconnects."})},2500);o.unref?.(),Ai.set(t,{resolve:r,timer:o,terminalId:e});try{process.send({t:"capacity-acquire",reqId:t,terminalId:e})}catch{clearTimeout(o),Ai.delete(t),Oi="held",r({ok:!1,code:"capacity_authority_unavailable",reason:"The bridge capacity authority is unavailable. No lane was opened."})}})},Ki=e=>{if(e)if(Pi.delete(e),xi)try{process.send({t:"capacity-release",terminalId:e})}catch{}else _i.release({room:rs,terminalId:e})&&Di()};xi&&process.on("message",e=>{if("capacity-acquire-result"===e?.t){const t=Ai.get(e.reqId);if(!t)return;clearTimeout(t.timer),Ai.delete(e.reqId),e.ok&&Pi.add(t.terminalId),e.ok||(Oi="held"),t.resolve({ok:!0===e.ok,code:e.code,reason:e.reason,active:e.active,limit:e.limit})}else"capacity-changed"===e?.t&&Di()});const Mi=async e=>{const t=e?.id;if(!t)return{ok:!1,code:"invalid_capacity_request",newlyAcquired:!1};if(Pi.has(t))return{ok:!0,code:"already_admitted",newlyAcquired:!1};const r=Ni.get(t);if(r)return{...await r,newlyAcquired:!1};const o=qi(t);Ni.set(t,o);try{const e=await o;return{...e,newlyAcquired:!0===e.ok}}finally{Ni.get(t)===o&&Ni.delete(t)}},Ui=(e,t)=>{t?.newlyAcquired&&queueMicrotask(()=>{e?.session?.started||e?.session?.turnActive||Ki(e?.id)})},Fi=new Map;let Bi=null;function Li(e,t={},r=4e3){if("1"===process.env.TP_CROSSROOM_OFF)return Promise.resolve({error:"Cross-session reach is turned off in this room."});if(!xi)return Promise.resolve({error:`Cross-session reach needs the thinkpool account bridge running your sessions (${Ue}). This room is running standalone, so it can only see its own terminals — use read_terminal.`});const o=c();return new Promise(n=>{const s=setTimeout(()=>{Fi.delete(o),n({error:"The other session did not respond in time."})},r);s.unref?.(),Fi.set(o,{resolve:n,timer:s});try{process.send({t:e,reqId:o,...t})}catch{clearTimeout(s),Fi.delete(o),n({error:"Could not reach the account bridge."})}})}function Wi(e,t){const r={kind:"needs-input",subtype:"pair-control",summary:"A protected action requires a durable decision.",permissionId:String(t?.id||"").slice(0,160)};return _a(e,r),wi("code-event",{term:e.id,evt:r}),{...t,...e.scheduleRunId?{runId:e.scheduleRunId}:{},source:{epoch:0,cid:r.cid,seq:r.seq}}}async function Hi({fromRoom:e,fromHost:t,fromTerminalName:r,text:o,terminal:n}){if("1"===process.env.TP_PAIRBUS_OFF)return{error:"Cross-room posting is turned off in this room."};const s=String(o||"").trim();if(!s)return{error:"Empty cross-room post ignored."};const i=Tr({selfId:null,sessions:Js,terms:zs,names:vi});let a=null;if(n){const e=Ir(i,n);if(e&&"agent"!==e.kind)return{error:`Terminal ${e.ref} in room ${rs} is a shell, not an agent — cross-room posts go to agents only.`};a=e?.id||null}else{const e=[...Js.keys()];1===e.length&&(a=e[0])}if(!a){const e=i.filter(e=>"agent"===e.kind);return{error:e.length?`Name which agent lane in room ${rs} to deliver to (${e.map(e=>e.ref).join(", ")}).`:`No agent terminal is open in room ${rs} to receive this.`}}const l=Js.get(a);if(!l?.session)return{error:`That terminal in room ${rs} is no longer live.`};const d=`${e}${t?` on ${t}`:""}`;let u="deny";try{u=await(m=l,p={id:c(),toolName:"mcp__thinkpool__post_to_session",input:{session:e,host:t,terminalName:r,text:s,incoming:!0},risk:"high"},new Promise(e=>{if(!m?.pending)return e("deny");const t=Wi(m,{term:m.id,id:p.id,toolName:p.toolName,input:p.input,risk:p.risk});m.pending.set(p.id,{resolve:e,payload:t}),Ii(),wi("code-perm-req",t),process.stderr.write(`\n ● incoming cross-room task for ${String(m.id).slice(0,8)} — approve in the room.\n`)}))}catch{u="deny"}var m,p;if("allow"!==u)return{error:`The people in room ${rs} declined the incoming task from ${d}.`};const h=await Mi(l);if(!h.ok)return{error:h.reason||`The host cannot start terminal ${String(a).slice(0,8)} yet.`};l.roomHop=1,l.hop=(l.hop||0)+1,l.peekCount=0,l.peekRosterCount=0,l.postCount=0,l.pairPeekCount=0,l.crossRoomPostCount=0;const f=`[From: room ${d} — relayed via the thinkpool cross-room Ensemble, approved by a person in this room]\n${s}`,w={kind:"you",text:f,by:`room ${e}`,crosspost:!0,relaySourceName:String(r||"").trim().slice(0,80)||void 0};Ci(a,s);const g=Qs(l,f,{visibleEvent:w,rejectionMessage:"The incoming cross-room task was not accepted; retry after the lane is available."});return g.accepted?{ok:!0,ref:String(a).slice(0,8)}:(Ui(l,h),{error:g.error?`Could not deliver to room ${rs} — the lane may have just closed.`:`Could not deliver to room ${rs} — the lane refused the turn (check its visible host-memory/runtime error).`})}!async function(){if(xi||"1"===process.env.TP_PAIRBUS_OFF||"1"===process.env.TP_CROSSROOM_OFF)return;if(!zn||!Ds)return;let t=null;try{const e=`${Un}/rest/v1/code_sessions?code=eq.${encodeURIComponent(rs)}&select=code,name,owner_id,participants`,r=await fetch(e,{headers:{apikey:Wn,Authorization:`Bearer ${zn}`}});if(!r.ok)return;const o=await r.json().catch(()=>[]);t=Array.isArray(o)?o[0]:null}catch{return}const r=Gr({row:t,myUid:Ds});if(!r?.topic)return;const o=Jr({room:rs,roomName:t?.name||null,host:e.hostname().replace(/\.local$/,""),formatPeek:e=>kr({selfId:null,sessions:Js,terms:zs,names:vi,terminal:e.terminal,lines:e.lines}),receivePost:e=>Hi(e)}),n=Ns.channel(r.topic,{config:{private:!0,broadcast:{self:!1}}}),s=async(e,t)=>{if(t)try{await n.send({type:"broadcast",event:e,payload:t})}catch{}};n.on("broadcast",{event:"peer-list-req"},({payload:e})=>{s("peer-list-res",o.list(e))}).on("broadcast",{event:"peer-peek-req"},({payload:e})=>{const t=o.peek(e);t&&s("peer-peek-res",t)}).on("broadcast",{event:"peer-post-req"},({payload:e})=>{o.post(e).then(e=>{if(e)return s("peer-post-res",e)})}).subscribe(e=>{"SUBSCRIBED"===e?process.stderr.write("\n ◆ standalone pair bus subscribed — this live room can receive approval-gated cross-session tasks.\n"):"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e||process.stderr.write(`\n ◇ standalone pair bus ${e.toLowerCase().replace("_"," ")} — cross-session reach will retry with realtime.\n`)}),Bi=n}(),xi&&process.on("message",e=>{if(e&&e.t){if("pair-list-res"===e.t||"pair-peek-res"===e.t||"pair-post-res"===e.t){const t=Fi.get(e.reqId);if(!t)return;return clearTimeout(t.timer),Fi.delete(e.reqId),void t.resolve(e)}if("pair-peek-local"===e.t){let t,r;try{t=kr({selfId:null,sessions:Js,terms:zs,names:vi,terminal:e.terminal,lines:e.lines})}catch{r="Could not read that session."}try{process.send({t:"pair-peek-res",reqId:e.reqId,text:t,error:r})}catch{}return}"pair-post-local"!==e.t||Hi(e).then(t=>{try{process.send({t:"pair-post-res",reqId:e.reqId,...t})}catch{}})}});const zi=()=>{const e=mi();for(const[t,r]of zs){if(!r.buf)continue;if(!e){r.buf="",ai=Date.now();continue}const o=Buffer.from(r.buf,"utf8").toString("base64");r.buf="",wi("pty-out",{term:t,b64:o})}},Ji=setInterval(zi,35);Ji.unref?.();const Gi=r.join(e.tmpdir(),"thinkpool-mockups",rs);try{t.mkdirSync(Gi,{recursive:!0}),process.env.TP_MOCKUP_OUTBOX=Gi}catch{}const Yi=new Map,Vi=new Map,Qi=new Map,Xi=new Map,Zi=new Map;function ea(e){e?.scheduleDeadlineTimer&&clearTimeout(e.scheduleDeadlineTimer),e&&(e.scheduleDeadlineTimer=null)}const ta=new Set;async function ra(e){const t=e?.scheduleAdmissionLease;return!t||!!(await hn(t)).ok&&(e.scheduleAdmissionLease=null,!0)}async function oa(e){const t=an(e?.scheduleOutcomePending);if(!e?.id||!t||e.scheduleOutcomeRecorded)return!1;const r=`${e.id}:${t.runId}`;if(ta.has(r))return!1;ta.add(r);try{if(!(await nn({supabaseUrl:Un,anonKey:Wn,token:zn,roomCode:rs,runId:t.runId,bridgeId:bs,bridgeFencing:$s,result:t.result,canceled:t.canceled,evidenceRefs:t.evidenceRefs})).ok)return!1;if(await ra(e),Js.get(e.id)!==e)return!!$o(rs,e.id,t.runId)&&Io(rs,e.id);const r=e.scheduleOutcomePending;e.scheduleOutcomeRecorded=!0,e.scheduleOutcomePending=null;const o=To(rs,e.id,()=>e.flush?.());return o.snapshotRecorded?o.ok:(e.scheduleOutcomeRecorded=!1,e.scheduleOutcomePending=r,!1)}finally{ta.delete(r)}}function na(e,t,{canceled:r=!1}={}){if(!e?.scheduleRunId||e.scheduleOutcomeRecorded||e.scheduleOutcomePending)return!1;const o=an({runId:e.scheduleRunId,result:t,canceled:r,evidenceRefs:(n=e.id,[...Vi.values()].filter(e=>e?.term===n&&"string"==typeof e.previewId).slice(0,16).map(e=>({type:"preview",id:e.previewId})))});var n;return!!o&&!!Co(rs,e.id,o)&&(e.scheduleOutcomePending=o,ea(e),e.flush?.(),oa(e),!0)}function sa(e){if(ea(e),!ln({runId:e?.scheduleRunId,deadlineAt:e?.scheduleDeadlineAt,outcomeRecorded:e?.scheduleOutcomeRecorded,outcomePending:e?.scheduleOutcomePending}))return;const t=Math.max(0,e.scheduleDeadlineAt-Date.now());e.scheduleDeadlineTimer=setTimeout(async()=>{if(e.scheduleDeadlineTimer=null,e.scheduleOutcomeRecorded)return;e.scheduleTimedOut=!0,Fa(e),await qe(e);const t={kind:"error",subtype:"runtime_limit",message:"Scheduled run reached its configured runtime ceiling."};_a(e,t),wi("code-event",{term:e.id,evt:t}),na(e,t),e.flush?.(),Ii()},t),e.scheduleDeadlineTimer.unref?.()}const ia=e=>Ws.send({type:"broadcast",event:"design-status",payload:{ts:Date.now(),...e}}),aa=(e,t,r={})=>{const o=Xi.get(e);if(o){if(o.timer&&clearTimeout(o.timer),Xi.delete(e),ia({previewId:o.record.previewId,requestId:o.request.cid,state:t,...r}),"verified-live"===t){const t=Qi.get(e)||[];for(const e of t.splice(0))ia({previewId:e.record.previewId,requestId:e.request.cid,state:"stale",message:"The artifact changed. Reselect the element on the new revision."})}queueMicrotask(()=>la(e))}},ca=e=>{const t=Xi.get(e);t?.resultOk&&t.proof&&aa(e,"verified-live",{message:"Verified at desktop and mobile.",artifact:t.proof.artifact,...t.proof.artifactHtml?{artifactHtml:t.proof.artifactHtml}:{},canRestore:"preview"!==t.record.sourceKind})};async function la(e){if(Xi.has(e))return;const t=Qi.get(e)||[],r=t[0];if(!r)return;const o=Js.get(e);if(!o)return t.shift(),ia({previewId:r.record.previewId,requestId:r.request.cid,state:"needs-lane",message:"The producing lane is no longer available."}),la(e);if(o.session?.turnActive)return;t.shift();const n=Vi.get(r.record.previewId),s=n&&At(n);if(!n||!s||s.revision!==r.record.revision)return ia({previewId:r.record.previewId,requestId:r.request.cid,state:"stale",message:"The artifact changed. Reselect the element."}),la(e);const i=await Mi(o);if(!i.ok)return ia({previewId:r.record.previewId,requestId:r.request.cid,state:"failed",message:i.reason||"The host cannot start the producing lane yet."}),la(e);const a={...r,resultOk:!1,proof:null,timer:null};Xi.set(e,a);const c={kind:"you",text:xt(r.request,{restore:!!r.restoreRecord}),cid:r.request.cid,by:r.by,design:!0};Ys(o);let l=!1;try{l=!1!==o.session.sendTurn(Ct({record:r.record,request:r.request,by:r.by,restore:!!r.restoreRecord,priorRecord:r.restoreRecord}))}catch{l=!1}if(l&&Vs(o),xo(c),_a(o,c),wi("code-event",{term:e,evt:c}),l&&ia({previewId:r.record.previewId,requestId:r.request.cid,state:"applying"}),!l){Ui(o,i),Ys(o);const t={kind:"error",message:"The producing lane could not start the edit.",recoverable:!0};_a(o,t),wi("code-event",{term:e,evt:t}),aa(e,"failed",{message:"The producing lane could not start the edit."})}Ii()}const da=(e,o,n,s)=>{try{const i=r.join(e,`${o}.receipt.json`),a=`${i}.tmp`;t.writeFileSync(a,JSON.stringify({ok:n,status:s,ts:Date.now()})),t.renameSync(a,i)}catch{}},ua=new Nn({deliver:async({box:e,term:o,trustedDesignSource:n=!1,slug:s,m:i})=>{const a=n?Js.get(o):null,l=a?Pt(i,a.cwd||process.cwd(),{box:e}):null,d=l?Nt(i,l,{box:e}):null,u=l?Xi.get(o):null,m=!(!u||i.designRequestId!==u.request.cid||i.parentRevision!==u.record.revision),p=u?.restoreRecord?.revision,h=p?l?.revision===p:l?.revision!==u?.record?.revision,f="preview"===u?.record?.sourceKind?"preview"===l?.sourceKind&&l?.captureKey===u.record.captureKey:l?.sourcePath===u?.record?.sourcePath,w=m&&f&&h?u.record.revision:null,g=e=>{try{return e&&t.readFileSync(e).toString("base64")}catch(t){return e&&process.stderr.write(`\n ◇ mockup asset unreadable: ${e} (${t?.code||t?.message||t})\n`),null}},v=e=>{try{return e&&t.readFileSync(e,"utf8")}catch(t){return e&&process.stderr.write(`\n ◇ mockup asset unreadable: ${e} (${t?.code||t?.message||t})\n`),null}},y=c(),k=Date.now();if(l&&!d)return da(e,s,!1,"invalid-snapshot"),void process.stderr.write(`\n ◇ mockup "${i.slug}" rendered snapshot was not trusted.\n`);try{const n={"Content-Type":"application/json"};zn&&(n.Authorization=`Bearer ${zn}`);const a=await fetch(`${Fn}/api/code-mockup`,{method:"POST",headers:n,body:JSON.stringify({code:rs,slug:i.slug,title:i.title,cid:y,ts:k,term:o,desktopPng:g(i.desktop),mobilePng:g(i.mobile),html:l?d:v(i.html),...l?{previewId:l.previewId,revision:l.revision,sourceKnown:!0}:{},...w?{verified:!0,parentRevision:w}:{}})});if(!a.ok)return da(e,s,!1,a.status),void process.stderr.write(`\n ◇ mockup "${i.slug}" upload failed (${a.status}).\n`);const c=await a.json(),{paths:m}=c,p=!(!l||!c?.payload?.sourceKnown),h=!(!p||!w||!0!==c?.payload?.verified||c.payload.parentRevision!==w),f="string"==typeof c?.payload?.artifactHtml?c.payload.artifactHtml:null,b={kind:"mockup",__struct:!0,cid:y,term:o,slug:i.slug,title:i.title||i.slug,ts:k,paths:m,...p?{previewId:l.previewId,revision:l.revision,sourceKnown:!0,...h?{verified:!0,parentRevision:w}:{}}:{},...f?{artifactHtml:f}:{}};if(p){Object.assign(l,{term:o,slug:i.slug,title:i.title||i.slug,desktop:i.desktop,mobile:i.mobile});try{const o=r.join(e,".design-revisions");t.mkdirSync(o,{recursive:!0}),l.backupPath=r.join(o,`${l.revision}.html`),t.existsSync(l.backupPath)||t.writeFileSync(l.backupPath,l.source)}catch{}Vi.set(l.previewId,l);const n=u,s=h,a=!!(m?.html&&m?.desktop&&m?.mobile&&i.desktop&&i.mobile);if(s&&a){"preview"!==n.record.sourceKind&&Zi.set(l.previewId,{priorRecord:n.record,request:n.request});const e=f||(Buffer.byteLength(d,"utf8")<=131072?d:null);n.proof={artifact:b,artifactHtml:e},ca(o)}}wi("code-event",{term:o,evt:b}),da(e,s,!0,200),process.stderr.write(`\n ◆ mockup "${i.title||i.slug}" pushed to the room.\n`)}catch(t){da(e,s,!1,"error"),process.stderr.write(`\n ◇ mockup "${i.slug}" send failed: ${t?.message||t}\n`)}}});function ma(e,o,n=!1){try{t.mkdirSync(e,{recursive:!0})}catch{return null}try{return t.watch(e,(s,i)=>function(e,o,n,s=!1){const i=((e,o,n,s=!1)=>{if(!o||o.endsWith(".receipt.json")||!o.endsWith(".json"))return null;const i=r.join(e,o);let a;try{a=t.statSync(i)}catch{return null}const c=o.replace(/\.json$/,""),l=`${n}/${c}`;if(Yi.get(l)===a.mtimeMs)return null;if(Yi.set(l,a.mtimeMs),!n)return null;let d;try{d=JSON.parse(t.readFileSync(i,"utf8"))}catch{return null}return d?.slug?On(d,{isReadyFile:e=>{try{const r=t.statSync(e);return r.isFile()&&r.size>0}catch{return!1}}})?{box:e,file:o,term:n,trustedDesignSource:s,slug:c,m:d}:(da(e,c,!1,"incomplete"),process.stderr.write(`\n ◇ mockup "${d.title||d.slug}" is incomplete — desktop, mobile, and source are all required.\n`),null):null})(e,o,n,s);if(!i)return;const a=Js.get(n),c=!!a&&(!0===a._busyAnn||!0===a.session?.turnActive),l="preview"===i.m.sourceKind?`preview:${i.m.captureKey||i.m.route||i.m.slug}:${i.m.title||""}`:`authored:${i.m.slug}`,d=ua.enqueue(n,i,{active:c,key:l});d.queued?(da(e,i.slug,!0,"queued"),process.stderr.write(`\n ◆ mockup "${i.m.title||i.m.slug}" ready — ${d.replaced?"replaced an earlier queued render":"queued after the final response"}.\n`)):d.delivery.catch(()=>{})}(e,i,o(),n))}catch{return null}}const pa=(e,t)=>r.join(Gi,e,t);ma(Gi,()=>[...Js.keys()][0]||ti||[...zs.keys()][0]);const ha="1"===process.env.TP_FOLLOW,fa=parseInt(process.env.TP_COLS,10)||null,wa=parseInt(process.env.TP_ROWS,10)||null,ga=()=>({cols:fa||(ha?process.stdout.columns||100:Math.min(process.stdout.columns||100,120)),rows:wa||(ha?process.stdout.rows||28:Math.min(process.stdout.rows||28,32))});function va({id:e,cmd:t,args:r=[],attached:o=!1,cols:n,rows:s}){if(zs.has(e))return;if(zs.size>=8)return process.stderr.write(`\n ⚠ can't open "${t}" — terminal cap (8) reached; close one first.\n`),void wi("term-exit",{id:e});if(!Jn)return process.stderr.write(`\n ⚠ can't open "${t}" — node-pty isn't built (PTY mode disabled).\n`),void wi("term-exit",{id:e});const i=Ee(`start the ${t} terminal`);if(!i.ok)return ji(),process.stderr.write(`\n ⚠ ${i.reason}\n`),void wi("term-exit",{id:e,reason:i.reason});const a=o?ga():null,c=pa("terms",e),l=Jn.spawn(t,r,{name:"xterm-256color",cols:n||(o?a.cols:fa||120),rows:s||(o?a.rows:wa||32),cwd:process.cwd(),env:{...process.env,TP_MOCKUP_OUTBOX:c}}),d={term:l,cmd:t,attached:o,scrollback:"",buf:"",lastActionAt:null,mockupWatcher:ma(c,()=>e)};return zs.set(e,d),o&&(ti=e),l.onData(e=>{o&&process.stdout.write(e),d.buf+=e,d.lastActionAt=Date.now(),d.scrollback=(d.scrollback+e).slice(-12e4)}),l.onExit(()=>{try{d.mockupWatcher?.close()}catch{}zs.delete(e),Ki(e),e===ti&&(ti=null,Va()),ri||(wi("term-exit",{id:e}),Ii(),0!==zs.size||ss?process.stderr.write(`\n ◇ terminal "${t}" ended — still relaying ${zs.size} terminal(s). Ctrl-C to stop.\n`):ac())}),Ii(),d}const ya=2e3,ka="",ba="",$a="",Ta="",Ia="",Ra="",Sa=e=>{const t=e&&(e.command||e.file_path||e.path||e.pattern||e.url||e.query||e.description);return t?" "+String(t).replace(/\s+/g," ").slice(0,100):""};function Ca(e){const t=e=>process.stderr.write(e+"\n");switch(e.kind){case"you":return t(`${$a}❯ ${e.text}${ba}${e.by?` ${ka}(${e.by})${ba}`:""}`);case"chat":return t(`${ka}${e.by}: ${e.text}${ba}`);case"whisper":return t(`${ka}// ${e.by}: ${e.text}${ba}`);case"pool":return t(e.pending?`${$a}◌ pool dispatching…${ba}`:`${$a}◆ pool → ${e.text}${ba}`);case"note":return t(`${ka}— ${e.text} —${ba}`);case"clear":return t(`${ka}— context cleared —${ba}`);case"usage":{const r=e.ctx;return r?t(`${ka} ctx ${r.pct}% · ${Math.round(r.used/1e3)}k/${Math.round(r.max/1e3)}k${null!=e.costUsd?` · $${e.costUsd.toFixed(3)}`:""}${ba}`):void 0}case"error":return t(`${Ra}✗ ${e.message}${ba}`);case"tool_result":{const r=e.content,o=("string"==typeof r?r:Array.isArray(r)?r.map(e=>e?.text||"").join(" "):"").replace(/\s+/g," ").slice(0,120);return t(` ${e.isError?Ra:ka}⎿ ${o||(e.isError?"error":"ok")}${ba}`)}case"assistant":for(const r of e.blocks||[])"text"===r.type&&r.text?.trim()?t(`⏺${ba} ${r.text.trim()}`):"thinking"===r.type&&r.text?.trim()?t(`${ka}✶ ${r.text.trim().slice(0,160)}${ba}`):"tool_use"===r.type&&t(` ${$a}${r.name}${ba}${Sa(r.input)}`);return;default:return}}function xa(e,t){const r=rn(t);return process.stderr.write(`\n ◇ ${r.message}\n`),e?.id&&(_a(e,r),wi("code-event",{term:e.id,evt:r})),r}function _a(e,t){if(!tn(t).known)return xa(e,t),null;ei(e,t),xo(t),e.mcpFlight=en(e.mcpFlight,t,{now:t.ts}),e.lastActionAt=t.ts,e.lastEvent=t,e.seq&&Po(t)&&(t.seq=e.seq.next()),e.id&&Po(t)&&(fo(e.room,e.id,[t]),null==e.archiveOldestSeq&&(e.archiveOldestSeq=t.seq));const r=Eo(t);for(e.log.push(r),e.logBytes=(e.logBytes||0)+JSON.stringify(r).length+1;e.log.length>ya||e.log.length>1&&e.logBytes>hr;){const t=e.log.shift();e.logBytes-=JSON.stringify(t).length+1}return t}function Aa(e){for(let t=e.length-1;t>=0;t--){const r=e[t]?.kind;if("result"===r||"error"===r||"propose"===r||"pool"===r)return!1;if("assistant"===r||"you"===r||"tool_result"===r)return!0}return!1}function Pa(e,t,r=null){const o={kind:"control",text:t,by:r};_a(e,o),wi("code-event",{term:e.id,evt:o})}function Na(e){const t=Bo(e?.log);return!!t&&(e.pendingCheckpoint=t,!0)}function Oa(e,t={}){if(!e||"codex"!==e.runtime||e.codexCompactionPromise)return!1;const r=async function(e,t={}){const r=Lo(e.log,Ho,{reason:"compact"});if(!r)return void Pa(e,"nothing to compact — context unchanged",t.by);const o=e.lastUsage?.ctx?.used||null;wi("code-event",{term:e.id,evt:{kind:"compact",status:"start",ts:Date.now()}});let n=!1;try{n=await(e.session.compactContext?.())}catch{n=null}finally{!e.session.turnActive&&Mr(e)&&Ii()}if(!0===n){Na(e);const r={kind:"compaction",trigger:"manual",preTokens:o,by:t.by,native:!0};return _a(e,r),wi("code-event",{term:e.id,evt:r}),wi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),void e.flush?.()}if(null==n)return wi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),Pa(e,"Native compaction is still settling; existing context was preserved.",t.by),void e.flush?.();if(!1===e.session.clearContext?.())return wi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),void Pa(e,"Codex context compaction unavailable right now",t.by);const s=Wo(r,e.pendingCheckpoint);e.pendingRecap=s.pendingRecap,e.pendingCheckpoint=s.pendingCheckpoint;const i={kind:"compaction",trigger:"manual",preTokens:o,by:t.by};if(_a(e,i),wi("code-event",{term:e.id,evt:i}),e.lastUsage?.ctx?.max){const t=Math.ceil(r.length/4),o=e.lastUsage.ctx.max,n={kind:"usage",ctx:{...e.lastUsage.ctx,used:t,max:o,pct:Math.min(100,Math.round(t/o*100)),over:t>o}};e.lastUsage=n,wi("code-event",{term:e.id,evt:n})}wi("code-event",{term:e.id,evt:{kind:"compact",status:"done",ts:Date.now()}}),e.flush?.()}(e,t);return e.codexCompactionPromise=r,r.finally(()=>{e.codexCompactionPromise===r&&(e.codexCompactionPromise=null)}).catch(()=>{}),!0}const Ea=new Map;function Da(e,t="parent"){const o=r.resolve(e||process.cwd()),n=s("git",["-C",o,"rev-parse","--verify","HEAD^{commit}"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).trim();if(!/^[0-9a-f]{40}$/i.test(n))throw new Error("parent review source has no immutable HEAD");return{taskKey:t,cwd:o,sha:n}}function ja({id:e,runtime:t="claude",model:o,models:n,effort:i,resume:a,log:l,commands:d,mode:u,spawnedBy:m,spawnDepth:p,cascadeRole:h,hop:f,sideParent:w,sideTask:g,pendingSideContexts:I,pendingWorkerCompletions:_,workerCompletionsInFlight:A,rolePrompt:E,sliceType:D,flowSessionId:j,flowTaskKey:K,flowTaskContract:M,flowRole:U,flowReviewTarget:z,flowReviewTargets:J,flowReviewSnapshots:G,flowReviewRound:Y,flowReviewConclusion:V,dispatchBaseSha:ee,revertTarget:te,cwd:ne,managedWorktree:ae,reviewSliceRoots:ce,openedAt:le,defer:he,provider:we,carryRecap:ge,carryCheckpoint:$e,lastUsage:Re,receivedTurnCids:Se,mcpFlight:xe,scheduleRunId:_e,scheduleDeadlineAt:Ae,scheduleOutcomeRecorded:Pe,scheduleAdmissionLease:Ne}){if(Js.has(e))return;t=de(t)?t:"claude";const De=Z({runtime:t,capabilityId:"terminal_interrupt",input:{}});if(!De.ok)throw new TypeError(`Structured runtime contract rejected: ${De.code}`);u=ie(t,{mode:u,sliceType:D,flowRole:U}),u=ze.has(u)&&ue(t,u)?u:re(t),pt({runtime:t,provider:we,model:o});const je="codex"===t?H():[],qe="codex"===t&&(o||W())||void 0,Ke="codex"===t?qe?ut(qe,je):at({sliceType:"feature",runtime:"codex",catalog:je}):"hermes"===t?o||void 0:O({provider:we,model:o,configuredModel:R(we)?.ANTHROPIC_MODEL}),Me=Number.isInteger(p)&&p>=0?p:w||m&&!String(m).startsWith("flow:")?1:0,Ue=Number.isInteger(f)&&f>=0?f:Me;i=oe(t,i,{model:Ke,models:je,spawnedBy:m,spawnDepth:Me,cascadeRole:h,sideParent:w,sliceType:D,flowSessionId:j,flowRole:U,scheduleRunId:_e});const Fe=Array.isArray(l)?l.slice(-ya):[],Be=pr(Fe),Le=Fe.length-Be.length,We=_e&&!0!==Pe?an(Ro(rs,e)):null,He=We?.runId===_e?We:null,Je={cmd:t,runtime:t,kind:"structured",log:Be,pending:new Map,receivedTurnCids:new Set(Array.isArray(Se)?Se.filter(Boolean).slice(-1e3):[]),mcpFlight:Zo(xe),session:null,recovered:!1,commands:pe(t,d),mode:u,effort:i,models:"codex"===t?je:"hermes"===t?Array.isArray(n)&&n.length?n:Ln:void 0,model:"codex"===t||"hermes"===t?Ke||null:we&&"anthropic"!==we?Ke||x()[we]||we:Ke||null,provider:we||null,spawnedBy:m||void 0,spawnDepth:Me,cascadeRole:"conductor"===h||"worker"===h?h:null,hop:Ue,sideParent:w||void 0,sideTask:g||void 0,scheduleRunId:_e||null,scheduleDeadlineAt:Number.isFinite(Number(Ae))?Number(Ae):null,scheduleOutcomeRecorded:!0===Pe,scheduleOutcomePending:He,scheduleAdmissionLease:Ne||null,pendingSideContexts:Array.isArray(I)?I.filter(Boolean).slice(-4):[],pendingWorkerCompletions:Array.isArray(_)?_.filter(e=>e?.workerId&&Number(e?.turnRev)>0).slice(-6):[],workerCompletionsInFlight:Array.isArray(A)?A.filter(e=>e?.workerId&&Number(e?.turnRev)>0).slice(-6):[],flowSessionId:j||null,flowTaskKey:K||null,cwd:ne||null,managedWorktree:ae||null,sliceType:"review"===D?"review":null,flowRole:U||(j?K?J?.length||ce?.length?"reviewer":"builder":"conductor":null),flowReviewTarget:z||null,flowReviewTargets:Array.isArray(J)&&J.length?J.filter(Boolean):z?[z]:[],flowReviewSnapshots:Array.isArray(G)?G.filter(e=>e?.taskKey&&e?.sha&&e?.cwd):[],flowReviewRound:Number.isInteger(Y)&&Y>=0?Y:0,flowReviewConclusion:V?.taskKey&&["pass","reject","surface"].includes(V?.action)&&Wt(V?.receipt)?{taskKey:V.taskKey,action:V.action,round:V.round,receipt:V.receipt}:null,dispatchBaseSha:ee||null,revertTarget:te||null,openedAt:le||Array.isArray(l)&&l.find(e=>e?.ts)?.ts||Date.now(),snapshotNeedsCompaction:Le>0||Be.some((e,t)=>e!==Fe[t+Le]),logBytes:Be.reduce((e,t)=>e+JSON.stringify(t).length+1,0)};Je._turnRev=Je.log.reduce((e,t)=>Math.max(e,Number(t?.turnRev)||0),0);const Ge=[...Je.log].reverse().find(e=>"result"===e?.kind&&Number(e?.turnRev)>0);Je._settledTurnRev=Number(Ge?.turnRev)||null,Je._turnSettledAt=Number(Ge?.ts)||null,Je.interruptedRecap=Aa(Je.log)?Lo(Je.log,Ho):null,Je.workerCompletionsInFlight.length&&!Je.interruptedRecap&&(Je.workerCompletionsInFlight=[]),Je.permNotifier=v({onArm:(t,r)=>Us({kind:"needs-input",term:e,termName:vi[e]||null,model:Je.model||null,permissionId:t,summary:r,pushEligible:!1}),onFire:(t,r)=>Us({kind:"needs-input",term:e,termName:vi[e]||null,model:Je.model||null,permissionId:t,summary:r,pushEligible:!0}),onResolve:t=>Us({kind:"needs-resolved",term:e,termName:vi[e]||null,model:Je.model||null,permissionId:t})}),Je.seq=_o(Ao(Je.log)),Je.rolePrompt=E||null,Je.flowTaskContract=M&&"object"==typeof M?M:null,Je.lastUsage=Re||null,Je.reviewSliceRoots=Array.isArray(ce)?ce.filter(Boolean):[];const Ye=async({reviewPass:t=!1,baselineEvidence:r=""}={})=>{if(!Je.flowSessionId||!Je.flowTaskKey)return"Not a Dispatch lane — nothing to mark done.";if("builder"!==Je.flowRole&&(!t||"reviewer"!==Je.flowRole))return"This Dispatch role cannot mark a builder slice done.";if(Je.flowDone)return"This slice is already recorded as done.";let o="";const n=!t&&!!Je.flowTaskContract?.baseline?.gate;if(n)try{o=tt(r)}catch(e){return`Slice "${Je.flowTaskKey}" is not done: submit the real bounded baselineEvidence receipt (${e?.message||e}). Observe the assigned pre-edit gate; do not fabricate a RED sentence.`}let i=null;try{i=s("git",["-C",Je.cwd||process.cwd(),"rev-parse","HEAD"],{encoding:"utf8"}).trim()}catch{}if(!t&&Je.dispatchBaseSha&&i===Je.dispatchBaseSha)return`Slice "${Je.flowTaskKey}" is not done: HEAD is still the dispatch base (${i.slice(0,8)}). Commit the verified implementation first.`;if(!t){const e=(e=>{try{return s("git",["-C",e,"status","--porcelain=v1","--untracked-files=all"],{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).split("\n").map(e=>e.trim()).filter(Boolean)}catch{return null}})(Je.cwd||process.cwd());if(null==e)return`Slice "${Je.flowTaskKey}" is not done: the bridge could not verify a clean worktree.`;if(e.length)return`Slice "${Je.flowTaskKey}" is not done: commit or remove every remaining worktree change before completion (${e.slice(0,4).join(", ")}).`}let a=null;if(!t&&Je.flowTaskContract?.scopePaths?.length){const e=yr(Je.cwd||process.cwd(),Je.dispatchBaseSha,i);if(!e)return`Slice "${Je.flowTaskKey}" is not done: the bridge could not derive its Git scope footprint.`;if(a=Ht({log:Je.log,repoRoot:Je.cwd||process.cwd(),declared:Je.flowTaskContract.scopePaths,changed:e}),!a.held)return`Slice "${Je.flowTaskKey}" is not done: scope drift detected in ${a.unexpected.join(", ")}. The approved scope must be amended before these files can ship.`}let c=null;try{c=(await kt({dir:Je.cwd||process.cwd(),id:`lane:${Je.flowSessionId}:${e}`})).url}catch{}try{const t=Je.cwd||process.cwd(),r=ht(Je.flowSessionId,Je.flowTaskKey,"_slice.done",JSON.stringify({taskKey:Je.flowTaskKey,commitSha:i||null,previewUrl:c||null}),{worktreeDir:t}),n=gt(Je.flowSessionId,{worktreeDir:t}),s=[{taskKey:Je.flowTaskKey,name:"_slice.done",path:r.path,sha:r.sha},...n.map(e=>({taskKey:e.taskKey,name:e.name,path:e.path,sha:e.sha}))],a=ft({key:Je.flowTaskKey,title:vi[e]||Je.flowTaskKey},{acceptanceProof:`${o?`baseline: ${o}; `:""}${i?`committed ${i.slice(0,8)}`:"slice done"}`,artifacts:s});wt(Je.flowSessionId,a,{baseDir:process.cwd()})}catch(e){process.stderr.write(`\n ${ka}◆ flow digest skip ${Je.flowTaskKey} — ${e?.message||e}${ba}\n`)}const l=n?{...Je.flowTaskContract,baseline:{...Je.flowTaskContract.baseline,evidence:o},...a?{scopeEvidence:a}:{}}:Je.flowTaskContract?{...Je.flowTaskContract,...a?{scopeEvidence:a}:{}}:null;return wi("flow-task-done",{term:e,flowId:Je.flowSessionId,taskKey:Je.flowTaskKey,laneId:e,commitSha:i,previewUrl:c,contract:l,...t?{reviewAction:"pass"}:{}},Ls),process.stderr.write(`\n ${$a}◆ flow slice done — ${Je.flowTaskKey} (${i?i.slice(0,8):"no commit"})${c?` · preview ${c}`:""}${ba}\n`),Je.flowDone=!0,setTimeout(()=>{try{Ha(e)}catch{}},2500),`Slice "${Je.flowTaskKey}" recorded as DONE${i?` (commit ${i.slice(0,8)})`:""}${c?`. Live preview: ${c}`:""}. The room dispatches dependent slices + assembles when all are done. You are finished — stop here.`};Je.markFlowDone=Ye;const Ve=Lt(),Xe=async t=>Je.flowReviewConclusion?{ok:!0,message:`Review already concluded for ${Je.flowReviewConclusion.taskKey}; receipt ${Je.flowReviewConclusion.receipt.cid||"recorded"}.`}:Ve(()=>(async t=>{if(!Je.flowSessionId||!Je.flowTaskKey||"reviewer"!==Je.flowRole)return{ok:!1,message:"Not a Dispatch review lane."};let r,o=null;try{r=Ut(t);const e="string"==typeof t?JSON.parse(String(t).replace(/```(?:json)?|```/g,"").trim()):t,n=e&&(e.taskKey||e.target),s=Je.flowReviewTargets;if(!s.length)throw new Error("review lane has no authorized target");if("codex"===Je.runtime&&1!==s.length)throw new Error("Codex review lane must have exactly one authorized target");if(n&&!s.includes(n))throw new Error(`taskKey ${JSON.stringify(n)} is outside this review lane`);if(o=n||(1===s.length?s[0]:null),!o)throw new Error("taskKey is required when reviewing more than one slice")}catch(e){return{ok:!1,message:"codex"===Je.runtime?`Review verdict REJECTED: ${e?.message||e}. Re-call submit_flow_review with a valid authorized taskKey.`:`Review verdict REJECTED: ${e?.message||e}. Re-Write FLOW_REVIEW.json with {"pass":<boolean>,"reasons":["<specific finding>"],"taskKey":"<the slice you reviewed>"}.`}}if(Je.flowReviewConclusion)return{ok:!0,message:`Review already concluded for ${Je.flowReviewConclusion.taskKey}; receipt ${Je.flowReviewConclusion.receipt.cid||"recorded"}.`};const n=Je.flowReviewRound=(Je.flowReviewRound||0)+1;Je.flush?.();const s=vr.get(Je.flowSessionId)||null,i=tr({round:n,maxRounds:rr.maxRounds,spentTokens:s?s.spentTokens:0,budgetCap:s?s.capTokens:null,...Ft(r)});if(!i.stop){const e=n+1;return Qs(Je,"codex"===Je.runtime?`[Dispatch review — round ${e}/${rr.maxRounds}] The happy path held, but you have NOT reported your checks exhausted. Dig one more round, then call submit_flow_review again — pass:false with specific evidence if you break it, or pass:true AND exhausted:true only when nothing remains to check.`:`[Dispatch review — round ${e}/${rr.maxRounds}] The happy path held, but you have NOT reported your checks exhausted and you are under both the round and budget ceilings. Dig one more round: hunt the edge cases, the reload, the second click, concurrent use, the error path — the places the builder didn't. Then re-Write FLOW_REVIEW.json — pass:false with a specific reason if you break it, or pass:true AND exhausted:true if you genuinely have nothing left to check.`,{rejectionMessage:"The next Dispatch review round was not accepted; retry after the lane is available."}),process.stderr.write(`\n ${ka}◆ review round ${n} inconclusive — digging again (${e}/${rr.maxRounds}) on ${o||Je.flowTaskKey}${ba}\n`),{ok:!0,message:`Round ${n} recorded (pass, not yet exhausted). Keep hunting — asked you for round ${e}/${rr.maxRounds}.`}}if("reject"===i.action&&o){const t=await Za({term:e,flowId:Je.flowSessionId,taskKey:o,reviewTaskKey:Je.flowTaskKey});t.ok||Us({kind:"needs-input",term:e,termName:vi[e]||null,summary:`Dispatch review could not revert ${o}: ${t.error||t.ignored||"unknown error"}`}),process.stderr.write(`\n ${Ia}◆ review REJECT (round ${n}) — reverting ${o}: ${r.reasons.join("; ").slice(0,120)}${ba}\n`)}else process.stderr.write(`\n ${$a}◆ review ${i.action.toUpperCase()} (round ${n}) — ${o||Je.flowTaskKey}${ba}\n`);const a=o||Je.flowTaskKey,l=Je.flowReviewSnapshots.find(e=>e.taskKey===a)||null,d=Je.flowTaskContract?.digest||null;let u,m=i.action,p=r.reasons.length?r.reasons:[i.reason];try{u=Bt({taskKey:a,outcome:"surface"===m?"held":m,rounds:n,candidateSha:l?.sha,acceptanceDigest:d,scope:l?.scopeEvidence,reasons:p})}catch(e){if("pass"!==m)return{ok:!1,message:`Review verdict REJECTED: ${e?.message||e}.`};m="surface",p=[...p,"Exact candidate or sealed acceptance proof is missing; pass was held."],u=Bt({taskKey:a,outcome:"held",rounds:n,candidateSha:l?.sha,acceptanceDigest:d,scope:l?.scopeEvidence,reasons:p})}u.cid=c(),Je.flowReviewConclusion={taskKey:a,action:m,round:n,receipt:u},Je.flush?.(),_a(Je,u),wi("code-event",{term:e,evt:u}),Je.flush?.(),wi("flow-review-verdict",{term:e,flowId:Je.flowSessionId,taskKey:a,pass:"pass"===m,reasons:p,action:m,rounds:n,surfaceToPair:"surface"===m||i.surfaceToPair,prompt:er({action:m,reason:m===i.action?i.reason:p.at(-1),taskKey:a,findings:p})},Ls);let h="";return"pass"===m?h=await Ye({reviewPass:!0}):("surface"===m&&(wi("flow-review-held",{term:e,flowId:Je.flowSessionId,reviewTaskKey:Je.flowTaskKey,taskKey:o,reasons:p},Ls),Us({eventId:u.cid,kind:"needs-input",term:e,termName:vi[e]||null,summary:`Dispatch review held ${a}: ${p.join("; ")||i.reason}`})),"reject"===m&&(Je.flowDone=!0,Je.flush?.(),setTimeout(()=>{try{Ha(e)}catch{}},2500))),{ok:!0,message:`Review verdict recorded: ${"reject"===m?`REJECT (round ${n}) — reverting ${o||"(no target)"} (${p.join("; ").slice(0,140)})`:"surface"===m?`SURFACED to the pair after ${n} round${1===n?"":"s"} — ${p.at(-1)||i.reason}`:`PASS (round ${n})`}.${h?` ${h}`:""}`}})(t));if(Je.id=e,Je.room=rs,wo(rs,e,Je.log.filter(e=>Po(e))),Je.archiveOldestSeq=vo(rs,e),Js.set(e,Je),Je.scheduleOutcomePending?oa(Je):sa(Je),Je.log.length&&Aa(Je.log)){const t={kind:"result",subtype:"aborted",recovered:!0};xo(t),_a(Je,t),process.stderr.write(`\n ◆ closed an interrupted turn on resume (${e.slice(0,8)}) — restored idle.\n`)}const Ze=pa("sessions",e);Je.mockupWatcher=ma(Ze,()=>e,!0);const nt=Ot(Ze,ne||process.cwd(),e);for(const e of nt)Vi.set(e.previewId,e);nt.length&&process.stderr.write(`\n ◆ restored ${nt.length} thinkpool Design artifact${1===nt.length?"":"s"} (${e.slice(0,8)}).\n`),Je.viewport=new Tt({workspaceRoot:ne||process.cwd(),ownerId:e,roomCode:rs,outbox:Ze,authContext:()=>({accessToken:zn,supabaseUrl:Un}),designContext:()=>{const t=Xi.get(e);return t&&"preview"===t.record.sourceKind?{requestId:t.request.cid,parentRevision:t.record.revision,captureKey:t.record.captureKey}:null}}),Je.log.length&&process.stderr.write(`\n ◆ restored ${Je.log.length} prior events (${e.slice(0,8)})${a?" + resuming live context":""}.\n`);const st=()=>({sessionId:Je.session?.sessionId||null,runtime:Je.runtime,log:Je.log,commands:Je.commands,mode:Je.mode,effort:Je.effort,model:Je.model||null,models:"hermes"===Je.runtime?Je.models||[]:void 0,provider:Je.provider||null,spawnedBy:Je.spawnedBy,spawnDepth:Je.spawnDepth||0,cascadeRole:Je.cascadeRole||null,hop:Je.hop||0,sideParent:Je.sideParent,sideTask:Je.sideTask,scheduleRunId:Je.scheduleRunId||null,scheduleDeadlineAt:Je.scheduleDeadlineAt||null,scheduleOutcomeRecorded:!0===Je.scheduleOutcomeRecorded,scheduleAdmissionLease:Je.scheduleAdmissionLease||null,pendingSideContexts:Je.pendingSideContexts,pendingWorkerCompletions:Je.pendingWorkerCompletions,workerCompletionsInFlight:Je.workerCompletionsInFlight,sliceType:Je.sliceType,flowSessionId:Je.flowSessionId,flowTaskKey:Je.flowTaskKey,flowTaskContract:Je.flowTaskContract,flowRole:Je.flowRole||null,flowReviewTargets:Je.flowReviewTargets||[],flowReviewSnapshots:Je.flowReviewSnapshots||[],flowReviewRound:Je.flowReviewRound||0,flowReviewConclusion:Je.flowReviewConclusion,dispatchBaseSha:Je.dispatchBaseSha||null,cwd:Je.cwd,managedWorktree:Je.managedWorktree,rolePrompt:Je.rolePrompt,flowReviewTarget:Je.flowReviewTarget||null,revertTarget:Je.revertTarget||null,reviewSliceRoots:Je.reviewSliceRoots||[],openedAt:Je.openedAt||null,lastUsage:Je.lastUsage||null,carryRecap:Je.pendingRecap||null,carryCheckpoint:Je.pendingCheckpoint||null,receivedTurnCids:[...Je.receivedTurnCids].slice(-1e3),mcpFlight:Je.mcpFlight}),it=()=>no(rs,e,st());if(Je.flush=()=>so(rs,e,st()),Je.flowReviewConclusion?.receipt&&!Je.log.some(e=>e?.cid===Je.flowReviewConclusion.receipt.cid)){const t={...Je.flowReviewConclusion.receipt};_a(Je,t),wi("code-event",{term:e,evt:t}),Je.flush()}Je.scheduleOutcomeRecorded&&Je.scheduleAdmissionLease&&ra(Je).then(e=>{e&&Je.flush?.()});const ct=!Je.spawnedBy&&!Je.sideParent&&!Je.flowRole&&0===(Je.spawnDepth||0),vt=ct&&"conductor"!==Je.cascadeRole,yt=ct,bt=()=>P().filter(e=>"anthropic"!==e.id).map(e=>`${e.name}${e.model?` (${e.model})`:""}`).join(", "),$t=(e,{worker:t=!1}={})=>{const r=e?.runtime||Je.runtime||"claude";if("codex"===r&&e?.provider)return{error:"A Codex terminal uses its Codex/OpenAI login in v1; custom bridge providers are not wired to Codex yet. Omit provider or open a Claude terminal for that provider."};if("hermes"===r&&e?.provider)return{error:"A Hermes terminal uses its isolated Hermes profile and ACP model catalog; bridge provider IDs do not apply. Omit provider and choose an exact Hermes model ID."};const o="hermes"===Je.runtime&&Je.models?.length?Je.models:[...Js.values()].flatMap(e=>"hermes"===e.runtime&&e.models||[]),n="codex"===r?H():"hermes"===r?o:[];if("codex"===r&&e?.model&&!dt(n).has(e.model))return{error:`Could not open a Codex terminal on ${JSON.stringify(e.model)} — that model is not in this host's visible Codex catalog.`};const s="hermes"===r?mt(e?.model,n,{strictCatalog:"hermes"===Je.runtime}):null;if(s&&!s.ok)return{error:s.error};const i="claude"===r&&e?.provider?S(e.provider):e?.provider;if("claude"===r&&e?.provider&&!i){const t=bt();return{error:`Unknown registered provider ${JSON.stringify(e.provider)}. No lane was opened and the built-in Claude login was not used.${t?` Available provider names: ${t}.`:" No custom providers are registered on this host."}`}}return"claude"===r&&!e?.provider&&e?.model&&/^gpt-/i.test(e.model)?{error:`Could not open a Claude terminal on Codex model ${JSON.stringify(e.model)}. Choose runtime="codex" or a Claude model.`}:{runtime:r,model:s?.model||e?.model||(t&&e?.sliceType?lt({sliceType:e.sliceType,runtime:r,catalog:n}):void 0),mode:t?"bypassPermissions":e?.mode||("plan"===Je.mode?"default":Je.mode),provider:i}},Rt=(e=Date.now())=>({runtime:Je.runtime,mode:Je.mode,hop:Je.hop||0,spawnTimes:Je.spawnTimes||[],now:e,spawnedLive:Hr(Js.values()),totalLive:Js.size+zs.size,plan:Os,disabled:"1"===process.env.TP_SPAWN_OFF}),St=r=>new Promise(o=>{if(Je.flowSessionId&&"plan"===r.risk)return wi("flow-plan",{term:e,flowId:Je.flowSessionId,plan:r.plan||""},Ls),process.stderr.write(`\n ${Ta}◆ flow plan ready — flow ${String(Je.flowSessionId).slice(0,8)}.${ba}\n`),void o("keep");const n=Wi(Je,{term:e,id:r.id,toolName:r.toolName,input:r.input,risk:r.risk,plan:r.plan,questions:r.questions,asker:r.asker,answerFormat:r.answerFormat,autoResolutionMs:r.autoResolutionMs}),s={resolve:o,payload:n,timer:null};Je.pending.set(r.id,s),Ii(),wi("code-perm-req",n),T(Je)&&Je.permNotifier?.arm(r.id,b(n)),process.stderr.write("plan"===r.risk?`\n ${Ta}◆ plan ready — approve in the room.${ba}\n`:"ask"===r.risk?`\n ${$a}● ${r.asker||de(t)?.label||"Agent"} is asking: ${(r.questions||[]).map(e=>e.question).join(" / ").slice(0,100)} — answer in the room.${ba}\n`:`\n ${Ia}● permission: ${r.toolName}${Sa(r.input)} — approve in the room.${ba}\n`);const i=Number(r.autoResolutionMs);"ask"===r.risk&&Number.isFinite(i)&&i>0&&(s.timer=setTimeout(()=>{if(Je.pending.get(r.id)===s){Je.pending.delete(r.id),Je.permNotifier?.resolve(r.id),wi("code-perm",{term:e,id:r.id,decision:"timeout",name:r.asker||"agent"});try{o(qa(s,{decision:"timeout",answers:{}}))}catch{}Ii()}},i),s.timer.unref?.())}),Ct=Q(()=>{const r=F({name:"thinkpool",version:"1.0.0",tools:[...Je.flowRole||"review"===Je.sliceType?[]:[B("read_mcp_flight_recorder","Read the privacy-filtered MCP flight recorder for THIS terminal. Use it to diagnose a tool path or audit recent MCP activity. It reports only tool identity, timing, outcome, byte counts, and coarse token estimates; it never records or returns arguments, result bodies, prompts, secrets, or host paths.",{limit:L.number().int().min(1).max(100).optional().describe("maximum recent calls to return (default 40)")},async e=>({content:[{type:"text",text:Xo(Je.mcpFlight,{limit:e?.limit})}]}))],..."hermes"===t&&"ordinary"===Ie({flowRole:Je.flowRole,sliceType:Je.sliceType})?[B("request_user_input","Ask the people in this thinkpool room one to three multiple-choice questions and wait for their answer. Use this for choices that genuinely block useful progress. Each question needs two or three mutually exclusive options; a free-text answer remains available in the room card.",{questions:L.array(L.object({id:L.string().min(1).max(80),header:L.string().min(1).max(12),question:L.string().min(1).max(500),options:L.array(L.object({label:L.string().min(1).max(80),description:L.string().min(1).max(240)})).min(2).max(3),multiSelect:L.boolean().optional(),isSecret:L.boolean().optional()})).min(1).max(3),autoResolutionMs:L.number().int().min(6e4).max(24e4).optional()},async e=>{const t=e.questions.map(e=>({...e,options:e.options.map(e=>({...e}))})),r=await St({id:`hermes-question:${c()}`,toolName:"AskUserQuestion",input:{questions:t},risk:"ask",questions:t,asker:"Hermes",answerFormat:"hermes",autoResolutionMs:e.autoResolutionMs});return{content:[{type:"text",text:JSON.stringify(Oe(r,t))}]}})]:[],...It({tool:B,z:L,manager:Je.viewport}),B("read_terminal","Read-only view of ANOTHER terminal in this thinkpool Code room (a sibling agent or a shell the people are using). The current ROOM NOW snapshot is the default roster. Call with no arguments only when that snapshot is missing or truncated; this optional full-roster lookup has its own one-call allowance. Call with `terminal` (a ref, id, name, or command) only when that lane’s detailed activity is needed. Targeted transcript reads have a separate bounded allowance: never poll, collect each finished owned worker once, then close it immediately.",{terminal:L.string().optional().describe("ref, id, or command of the terminal to read; omit to list the open terminals"),lines:L.number().int().positive().max(br.maxLines).optional().describe(`how many recent lines to return (default ${br.defaultLines})`)},async t=>{const r=Tr({selfId:e,sessions:Js,terms:zs,names:vi}),o=t?.terminal?Ir(r,t.terminal):null;if(t?.terminal&&!o)return{content:[{type:"text",text:kr({selfId:e,sessions:Js,terms:zs,names:vi,terminal:t.terminal,lines:t?.lines})}]};const n=$r({targeted:!!t?.terminal,targetedCount:Je.peekCount,rosterCount:Je.peekRosterCount,budgetTurnRev:Je.peekBudgetTurnRev,currentTurnRev:Je._turnRev});if(Je.peekCount=n.targetedCount,Je.peekRosterCount=n.rosterCount,Je.peekBudgetTurnRev=n.budgetTurnRev,!n.ok)return{content:[{type:"text",text:n.reason}]};const s="agent"===o?.kind?Js.get(o.id):null;return{content:[{type:"text",text:kr({selfId:e,sessions:Js,terms:zs,names:vi,terminal:t?.terminal,lines:t?.lines})+Ur({parentRuntime:Je.runtime,parentModels:Je.models,targetRuntime:s?.runtime,targetLog:s?.log})}]}}),...Je.flowRole?[]:[B("search_past_work","Search bounded saved terminal work from THIS thinkpool room. Returns privacy-filtered excerpts for prior decisions, failed attempts, commands, checks, and Dispatch receipts. Every hit cites the room, terminal, date, and event sequence. It never searches another room, exposes prompts or host paths, or changes state.",{query:L.string().min(2).max(160).describe("specific terms from the prior decision, failure, command, check, or feature"),limit:L.number().int().min(1).max(8).optional().describe("maximum cited hits; default 8")},async e=>{if(Je.pastWorkSearchTurnRev!==Je._turnRev&&(Je.pastWorkSearchTurnRev=Je._turnRev,Je.pastWorkSearchCount=0),(Je.pastWorkSearchCount||0)>=3)return{content:[{type:"text",text:"Past-work search limit reached for this turn (3). Use the cited results already returned or narrow the next room turn."}]};Je.pastWorkSearchCount=(Je.pastWorkSearchCount||0)+1;const t=new Map;for(const e of co(rs,40))e?.id&&Array.isArray(e.log)&&t.set(e.id,{id:e.id,name:vi[e.id]||e.name||"Archived terminal",savedAt:e.savedAt||e._archivedAt,log:e.log});for(const[e,r]of Js)t.set(e,{id:e,name:vi[e]||`Terminal ${String(e).slice(0,8)}`,savedAt:r.openedAt||Date.now(),log:r.log||[]});let r;try{r=Gt([...t.values()],e?.query||"",{room:rs,limit:e?.limit})}catch(e){return{content:[{type:"text",text:`Past-work search rejected: ${e?.message||e}`}]}}return{content:[{type:"text",text:Jt(r,e?.query||"")}]}})],B("list_sessions","List OTHER thinkpool Code sessions (rooms) reachable from this room: your own rooms on this machine plus your partner's shared rooms over the pair bus. Returns each room's code, name, and partner host when remote so you can read into one with read_session. This is thinkpool Ensemble across SESSIONS, not just terminals. Read-only.",{},async()=>{const e=e=>({content:[{type:"text",text:e}]});if(Je.pairPeekCount=(Je.pairPeekCount||0)+1,Je.pairPeekCount>_r.peekPerTurnCap)return e(`Cross-session read limit reached for this turn (${_r.peekPerTurnCap}). Continue with what you have.`);const t=await Li("pair-list-req",{});return e(Pr(t?.rooms,{thisRoom:rs,error:t?.error}))}),B("read_session","Read-only view INTO another thinkpool Code session returned by list_sessions—either your own room on this machine or your partner's shared room over the pair bus. The authorized durable cloud transcript takes over when the partner bridge is offline. Pass `session` (the room code) and optionally `terminal` (a ref/name in that room) to read its recent activity; omit `terminal` to list that room's terminals. It never changes the other session.",{session:L.string().describe("the room code of the other session (from list_sessions)"),terminal:L.string().optional().describe("ref, id, or name of a terminal in that room; omit to list that room's terminals"),lines:L.number().int().positive().max(br.maxLines).optional().describe(`how many recent lines to return (default ${br.defaultLines})`)},async e=>{const t=e=>({content:[{type:"text",text:e}]}),r=String(e?.session||"").toUpperCase().trim();if(!r)return t("Name a room code to read (call list_sessions to see them).");if(r===rs)return t("That is this room — use read_terminal for terminals in your own room.");if(Je.pairPeekCount=(Je.pairPeekCount||0)+1,Je.pairPeekCount>_r.peekPerTurnCap)return t(`Cross-session read limit reached for this turn (${_r.peekPerTurnCap}). Continue with what you have.`);const o=await Li("pair-peek-req",{targetRoom:r,terminal:e?.terminal,lines:e?.lines},Ar.busTimeoutMs+2e3);return t(o?.error?o.error:o?.text||`Room ${r} returned nothing.`)}),...Je.flowRole?[]:[B("post_to_session","Hand a task or message to an agent in ANOTHER of your thinkpool Code sessions — your own room on this machine, or your partner's room reachable through the pair (a room code from list_sessions). Pass `session` (the room code), `text` (what to send), and optionally `terminal` (which agent lane in that room). A person in YOUR room approves sending AND a person in the TARGET room approves receiving before it is delivered. An agent reached this way cannot post onward to a third room. Read the target with read_session first, and use this sparingly — only when the people clearly want the rooms to coordinate.",{session:L.string().describe("the room code of the other session (from list_sessions)"),text:L.string().describe("the message or task to deliver to that room's agent"),terminal:L.string().optional().describe("ref/name of the agent lane in that room; omit if it has a single agent")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=Nr({roomHop:Je.roomHop||0,postCount:Je.crossRoomPostCount||0,disabled:"1"===process.env.TP_PAIRBUS_OFF});if(!o.ok)return r(o.reason);const n=String(t?.session||"").toUpperCase().trim();if(!n)return r("Name a room code to post to (call list_sessions to see your rooms).");if(n===rs)return r("That is this room — use post_to_terminal for an agent in your own room.");const s=String(t?.text||"").trim();if(!s)return r("Nothing to send — provide the task or message text.");Je.crossRoomPostCount=(Je.crossRoomPostCount||0)+1;const i=await Li("pair-post-req",{targetRoom:n,terminal:t?.terminal,text:s,fromRoom:rs,fromTerminalName:vi[e]||void 0},18e4);return r(i?.error?i.error:i?.ok?`Delivered to room ${n}${i.ref?` (lane ${i.ref})`:""} — it will respond in its own room; check back with read_session.`:`Room ${n} did not accept the message.`)})],...Je.flowRole?[]:[B("post_to_terminal","Send a message or task to ANOTHER AGENT terminal in this thinkpool Code room. Use `terminal` (a ref/id/command from read_terminal) and `text` (what to send). A person in the room must approve before it is delivered, and an agent reached via a cross-post cannot post onward. Targets agent terminals only, not plain shells. Use read_terminal first to understand the sibling.",{terminal:L.string().describe("ref, id, or command of the AGENT terminal to send to (from read_terminal)"),text:L.string().describe("the message or task to deliver to that terminal")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=Rr({hop:Je.hop||0,postCount:Je.postCount||0,disabled:"1"===process.env.TP_CROSSPOST_OFF});if(!o.ok)return r(o.reason);const n=Tr({selfId:e,sessions:Js,terms:zs,names:vi}),s=Ir(n,t?.terminal);if(!s)return r(`No terminal matches "${t?.terminal}". Call read_terminal with no argument to list the open terminals.`);if("agent"!==s.kind)return r(`Terminal ${s.ref} is a shell, not an agent — cross-posting is only allowed to agent terminals.`);const i=Js.get(s.id);if(!i?.session)return r(`Terminal ${s.ref} is no longer live.`);if(!t?.text||!String(t.text).trim())return r("Nothing to send — provide a non-empty `text` for the post.");const a=await Mi(i);if(!a.ok)return r(a.reason||`The host cannot start terminal ${s.ref} yet.`);Je.postCount=(Je.postCount||0)+1;const c=String(e).slice(0,8),l=`[From: terminal ${c}'s agent — relayed via thinkpool cross-terminal, approved by a person in the room]\n${t.text}`;i.hop=(Je.hop||0)+1,i.peekCount=0,i.peekRosterCount=0,i.postCount=0;const d={kind:"you",text:l,by:`terminal ${c} (agent)`,crosspost:!0,relaySourceName:vi[e]||void 0};Ci(s.id,t.text);const u=Qs(i,l,{visibleEvent:d,rejectionMessage:"The cross-terminal task was not accepted; retry after the lane is available."});return u.accepted?r(`Delivered to terminal ${s.ref} (${s.cmd}). It will respond in its own lane; check back with read_terminal.`):(Ui(i,a),r(u.error?`Could not deliver to terminal ${s.ref} — it may have just closed.`:`Could not deliver to terminal ${s.ref} — it refused the turn. Check its visible host-memory/runtime error.`))})],...vt?[B("open_main_terminal","Open a separate independent MAIN terminal on any supported runtime: Claude (including a connected Anthropic-compatible BYOK provider), Codex, or Hermes. Use this whenever a person asks to open, launch, start, spawn, or create a new, separate, independent, top-level, or main terminal—even for ordinary work or a handoff and even without the words Cascade or conductor. If the wording includes new or separate terminal, main-terminal routing wins. This is the top-level room lifecycle, NOT Ensemble dispatch: the new terminal has no spawnedBy owner and appears as a main terminal. Never substitute spawn_terminal, which creates worker sub-terminals only. Give the main terminal its full initial task; it can use spawn_terminal for bounded workers.",{name:L.string().max(80).optional().describe('short label for the main conductor, e.g. "Cascade · Multi-device chaos"'),task:L.string().min(1).describe("complete initial brief for the independent main terminal"),model:L.string().optional().describe("optional main-terminal model, e.g. opus / gpt-5.6-sol / nous:z-ai/glm-5.2"),runtime:L.enum(["claude","codex","hermes"]).optional().describe("agent runtime; every top-level terminal can open every supported runtime, defaulting to its own"),provider:L.string().optional().describe("optional registered Claude-compatible provider name or id; omit for built-in Anthropic"+(bt()?`. Available now: ${bt()}`:"")),mode:L.enum(["default","acceptEdits","bypassPermissions","plan"]).optional().describe("permission mode; defaults to inheriting this main terminal, except plan falls back to default")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=$t(t);if(o.error)return r(o.error);const n=Ee("start another Cascade conductor");if(!n.ok)return ji(),r(n.reason);const s=(()=>{const e=Date.now(),t=Cr({hop:0,spawnTimes:Je.spawnTimes||[],now:e,spawnedLive:0,totalLive:Js.size+zs.size,plan:Os,disabled:"1"===process.env.TP_SPAWN_OFF});return t.ok?(Je.spawnTimes=[...(Je.spawnTimes||[]).filter(t=>Number.isFinite(t)&&t>e-xr.windowMs),e],t):t})();if(!s.ok)return r(s.reason);const i=c(),a=await qi(i);if(!a.ok)return r(a.reason||"The bridge machine cannot accept another live lane yet.");const l=String(i).slice(0,8),d=String(e).slice(0,8);t?.name&&(vi[i]=String(t.name).slice(0,80),ho(rs,vi)),ja({id:i,runtime:o.runtime,model:o.model,provider:o.provider,mode:o.mode,spawnDepth:0,cascadeRole:"conductor",hop:0});const u=Js.get(i);if(!u)return Ki(i),t?.name&&(delete vi[i],ho(rs,vi)),r("Could not open the main conductor terminal — the machine terminal cap may have just been reached.");u.peekCount=0,u.peekRosterCount=0,u.postCount=0,u.spawnTimes=[],Ii();const m=`[Task from main terminal ${d}'s agent — opened as an independent MAIN CASCADE CONDUCTOR terminal, not an Ensemble child]\n${String(t.task).trim()}`,p={kind:"you",text:m,by:`main terminal ${d} (agent)`,crosspost:!0,relaySourceName:vi[e]||void 0};Ci(i,t.task);const h=Qs(u,m,{visibleEvent:p,rejectionMessage:"The initial conductor task was not accepted; retry after the lane is available."});return h.accepted?r(`Opened independent main Cascade conductor ${l}${t?.name?` ("${t.name}")`:""} and handed it the task. It is a main terminal, not an Ensemble lane.`):r(h.error?`Opened main conductor ${l}${t?.name?` ("${t.name}")`:""}, but it may still be starting — the initial task could not be delivered.`:`Opened main conductor ${l}, but host pressure prevented its runtime from starting. Existing lanes remain connected; free memory and retry the task.`)})]:[],...yt?[B("spawn_terminal","Open a visible WORKER SUB-TERMINAL on any supported runtime—Claude (including a connected Anthropic-compatible BYOK provider), Codex, or Hermes—from any top-level terminal. spawn_terminal is worker-only: it can never create a Cascade conductor or main terminal. For ordinary workers use an appropriate non-Sol tier: gpt-5.6-luna or gpt-5.4-mini for scaffold/search, gpt-5.6-terra for feature/fix, and a balanced tier for adversarial review; never select Sol for routine workers. A Hermes sliceType=review lane is structurally reviewer-scoped before ACP startup: it can inspect files and use the bridge review-check tool, but has no terminal, write, patch, delegate, browser, skill, memory, or session-history schema. Pass sliceType=scaffold for mechanical work, feature/fix for builders, and review for adversarial verification. Give the worker a bounded initial task, collect its result with read_terminal, then ALWAYS close_terminal it.",{name:L.string().max(80).optional().describe('a short label for the new lane so the room (and you) can find it, e.g. "Research: topologies"'),task:L.string().optional().describe("an initial task to hand the new lane immediately; omit to open it idle"),model:L.string().optional().describe("model for the chosen runtime; Hermes accepts its profile default or an ACP ID such as nous:z-ai/glm-5.2"),sliceType:L.enum(["scaffold","feature","fix","review"]).optional().describe("optional cascade slice tier; omitted preserves normal inheritance/default, explicit model wins"),runtime:L.enum(["claude","codex","hermes"]).optional().describe("agent runtime for the new lane; every top-level terminal can open every supported runtime"),provider:L.string().optional().describe("optional registered Claude-compatible provider name or id; omit for built-in Anthropic"+(bt()?`. Available now: ${bt()}`:"")),mode:L.enum(["default","acceptEdits","bypassPermissions","plan"]).optional().describe("accepted for compatibility; spawned workers always run autonomously in bypassPermissions")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=$t(t,{worker:!0});if(o.error)return r(o.error);const n=Date.now(),s=Rt(n),i=Cr(s);if(!i.ok)return r(i.reason+Er(e,[...Js.entries()].map(([e,t])=>({ref:String(e).slice(0,8),name:vi[e]||void 0,spawnedBy:t.spawnedBy,busy:(t.session?.turnActive??!1)||(t.pending?.size??0)>0}))));const a=Ee("start another worker lane");if(!a.ok)return ji(),r(a.reason);const l={...t,runtime:o.runtime,model:o.model,provider:o.provider,mode:ie(o.runtime,{mode:o.mode,sliceType:t?.sliceType})};let d;try{d=Fr({args:l,initiatorTerminalId:e,roomCode:rs,bridgeAuthorityId:ks,localAuthorityId:e,context:{...s,providerName:o.provider?x()[o.provider]||o.provider:void 0,resolvedModel:o.model}})}catch(e){return process.stderr.write(`\n ${Ra}✗ dispatch preview rejected — ${e?.message||e}${ba}\n`),r("Dispatch preview could not be built safely. No lane was created.")}const u=Date.now(),m=Rt(u),p=Br({preview:d,args:l,initiatorTerminalId:e,roomCode:rs,bridgeAuthorityId:ks,localAuthorityId:e,context:{...m,providerName:o.provider?x()[o.provider]||o.provider:void 0,resolvedModel:o.model}});if(!p.ok)return r(p.reason||"Dispatch became stale or exceeded a cap. No lane was created.");Je.spawnTimes=[...(Je.spawnTimes||[]).filter(e=>Number.isFinite(e)&&e>u-xr.windowMs),u];const h=c(),f=await qi(h);if(!f.ok)return r(f.reason||"The bridge machine cannot accept another live lane yet.");const w=String(h).slice(0,8),g=String(e).slice(0,8);t?.name&&(vi[h]=String(t.name).slice(0,80),ho(rs,vi));const v=(Je.spawnDepth||0)+1,y=(Je.hop||0)+1;let k=[];if("review"===t?.sliceType)try{k=[Da(Je.cwd||process.cwd())]}catch(e){return r(`Review lane was not opened: could not pin the spawning parent’s HEAD (${e?.message||e}).`)}ja({id:h,runtime:o.runtime,model:o.model,provider:o.provider,mode:l.mode,sliceType:t?.sliceType,flowReviewTargets:k.map(e=>e.taskKey),flowReviewSnapshots:k,spawnedBy:e,spawnDepth:v,cascadeRole:"worker",hop:y});const b=Js.get(h);if(!b)return Ki(h),t?.name&&(delete vi[h],ho(rs,vi)),r("Could not open a new lane. No host-capacity slot was kept; retry after checking the runtime.");if(b.peekCount=0,b.peekRosterCount=0,b.postCount=0,b.spawnTimes=[],Ii(),t?.task){const o=k.length?`\n\n[Immutable review target: parent at spawn time — target key "parent", pinned HEAD ${k[0].sha}. Use read_review_file with target="parent" for source and run_review_check with target="parent" for fixed checks. Do not infer a target path/ref or mutate anything.]`:"",n=`[Task from terminal ${g}'s agent — relayed via thinkpool Ensemble; you are its WORKER SUB-TERMINAL, never a main terminal or Cascade conductor]\n${t.task}${o}`,s={kind:"you",text:n,by:`terminal ${g} (agent)`,crosspost:!0,relaySourceName:vi[e]||void 0};Ci(h,t.task);const i=Qs(b,n,{visibleEvent:s,rejectionMessage:"The initial worker task was not accepted; retry after the lane is available."});return i.accepted?r(`Opened agent lane ${w}${t?.name?` ("${t.name}")`:""} and handed it the task. It runs in its own lane — check back with read_terminal, then close_terminal when done.`):r(i.error?`Opened lane ${w}${t?.name?` ("${t.name}")`:""}, but it may still be starting — could not hand off the task. Try post_to_terminal shortly.`:`Opened lane ${w}${t?.name?` ("${t.name}")`:""}, but host pressure prevented its runtime from accepting the task. Existing lanes remain connected; free memory and retry.`)}return r(`Opened idle agent lane ${w}${t?.name?` ("${t.name}")`:""}. Hand it work with post_to_terminal, or a person can type into it.`)})]:[],...Je.flowRole?[]:[B("close_terminal","Close an IDLE agent lane that YOU opened with spawn_terminal (identified by ref/id/name). Active turns and permission waits are protected: collect the completed result with read_terminal before closing. You can only close lanes you spawned yourself — never a sibling someone else is working in, and never the main terminal.",{terminal:L.string().describe("ref, id, or name of the lane you spawned (from read_terminal)")},async t=>{const r=e=>({content:[{type:"text",text:e}]}),o=Tr({selfId:e,sessions:Js,terms:zs,names:vi}),n=Ir(o,t?.terminal);if(!n)return r(`No terminal matches "${t?.terminal}". Call read_terminal with no argument to list the open terminals.`);const s=Js.get(n.id);if(!s)return r(`Terminal ${n.ref} is not an agent lane (or already closed) — only spawned agent lanes can be closed this way.`);const i=Dr({callerId:e,spawnedBy:s.spawnedBy,busy:(s.session?.turnActive??!1)||(s.pending?.size??0)>0});return i.ok||"not-owner"!==i.reason?i.ok||"busy"!==i.reason?(Ha(n.id),r(`Closed agent lane ${n.ref}${n.name?` ("${n.name}")`:""}.`)):r(`Terminal ${n.ref} is still working or waiting for a permission decision. close_terminal will not kill an active turn. Wait until read_terminal reports it idle/completed, collect its result, then close it. If it is genuinely stuck, ask a person to press Stop.`):r(`Terminal ${n.ref} was not opened by you — you can only close lanes you spawned yourself. Leave it to the person running it.`)})],..."builder"===Je.flowRole?[B("mark_flow_done","thinkpool Dispatch ONLY — call this ONCE when your slice is built, RUNS, and meets its acceptance criteria. For a gate-first task, pass `baselineEvidence`: the real, bounded pre-edit command/behavior receipt proving the assigned failure/absence. Never fabricate a RED sentence. The bridge derives the edited-file footprint from Git, compares it with the sealed scopePaths, and refuses unexpected touches. Records your latest commit as the slice's atomic-revert target and signals the room that this slice is done (which unblocks slices that depended on you). Do not call before the slice actually runs + meets acceptance.",{baselineEvidence:L.string().max(1400).optional().describe("real single-line pre-edit baseline command/behavior receipt; required for new gate-first tasks")},async e=>({content:[{type:"text",text:await Ye({baselineEvidence:e?.baselineEvidence||""})}]}))]:[],..."conductor"===Je.flowRole?[B("submit_flow_plan",'thinkpool Dispatch CONDUCTOR ONLY — submit your decomposition for human approval. Call this ONCE when your task-graph is ready. Pass it as `plan`: a JSON string {"summary":"<one line; assumptions: …>","tasks":[{"key":"<kebab>","title":"…","scope":"human-readable ownership","scopePaths":["repo/file.js","repo/directory/**"],"acceptance":"observable proof","nonGoals":["bounded exclusion"],"baseline":{"gate":"what fails/is absent before edits","evidence":"optional observed receipt"},"deps":["<key>"],"sliceType":"feature|scaffold|review|fix"}]}. Each builder/fix/scaffold needs acceptance, machine-readable repo-relative scopePaths, nonGoals, and a safe bounded baseline gate; review tasks inherit one builder contract. When uncertain, choose and record a safe reversible default; ask only when a choice materially expands scope or authority. The room validates and persists the graph, then shows approval. Do NOT use ExitPlanMode or write a plan file.',{plan:L.string().describe("the task-graph as a JSON string (the {summary, tasks:[…]} object)")},async t=>{const r=e=>({content:[{type:"text",text:e}]});if(!Je.flowSessionId||"conductor"!==Je.flowRole)return r("Not a Dispatch conductor — there is no plan to submit.");let o;try{o=ot(rt(t?.plan||""),Je.runtime)}catch(e){return r(`Plan REJECTED: ${e?.message||e}. Re-call submit_flow_plan with valid JSON: a non-empty acyclic tasks array; each builder/fix/scaffold has observable acceptance, repo-relative scopePaths, bounded nonGoals, and a safe baseline gate that says what fails/is absent; each review targets exactly one builder contract.`)}return wi("flow-plan",{term:e,flowId:Je.flowSessionId,plan:JSON.stringify(o)},Ls),process.stderr.write(`\n ${Ta}◆ flow plan submitted — flow ${String(Je.flowSessionId).slice(0,8)} (${o.tasks.length} slice${1===o.tasks.length?"":"s"}).${ba}\n`),r(`Plan submitted (${o.tasks.length} slice${1===o.tasks.length?"":"s"}) with gate-first contracts. Safe reversible assumptions belong in the summary; user steering remains authoritative. The room is showing approval. You are DONE; stop here and wait for approval (lane dispatch is the room's job).`)})]:[],..."reviewer"===Je.flowRole?[B("submit_flow_review",'thinkpool Dispatch REVIEWER ONLY — submit one bounded adversarial review round. Pass `verdict` as JSON: {"pass":boolean,"reasons":["specific evidence"],"taskKey":"authorized reviewed task","exhausted":boolean}. This is the only review completion path; do not call mark_flow_done and do not write FLOW_REVIEW.json.',{verdict:L.string().describe("the structured review verdict as a JSON string")},async e=>({content:[{type:"text",text:(await Xe(e?.verdict||"")).message}]}))]:[],..."reviewer"===Je.flowRole||"review"===Je.sliceType?[B("read_review_file","Read one regular file from the declared immutable review target. This always reads the target’s pinned Git object, never a live worktree; target and path are validated and the response is byte-bounded.",{target:L.string(),path:L.string()},async e=>({content:[{type:"text",text:JSON.stringify(await Xt({target:e?.target,filePath:e?.path,snapshots:Je.flowReviewSnapshots}))}]}),Vt),B("run_review_check","Run one fixed verification check against an immutable git-archived review target. This accepts only the declared target and a fixed check id, but executes target-defined code in a scratch archive that is not an OS filesystem/network sandbox. It can require approval and must be refused by approvalPolicy=never reviewers.",{target:L.string(),checkId:L.string()},async e=>({content:[{type:"text",text:JSON.stringify(await Zt({target:e?.target,checkId:e?.checkId,snapshots:Je.flowReviewSnapshots}))}]}),Qt)]:[]]});return r.instance.registerTool("project_intelligence",{description:"Query a persistent local structural code graph for THIS terminal’s exact Git worktree. Use status to inspect freshness, search_code for definitions/types, trace_code for callers/callees, and read_symbol after an exact qualified-name hit. The first code query auto-indexes or refreshes the worktree in fast mode. Results are structured, bounded, cursor-aware, and redact the worktree plus common absolute host paths.",inputSchema:L.object({operation:L.enum(ke),query:L.string().min(1).max(240).optional().describe("search terms for search_code"),symbol:L.string().min(1).max(300).optional().describe("qualified symbol for trace_code or read_symbol"),direction:L.enum(["inbound","outbound","both"]).optional(),depth:L.number().int().min(1).max(5).optional(),includeTests:L.boolean().optional(),limit:L.number().int().min(1).max(12).optional(),cursor:L.string().regex(/^\d{1,8}$/).optional()}).strict(),outputSchema:L.object({version:L.number().int(),operation:L.string(),status:L.enum(["ok","ready","missing","stale","error"]),message:L.string().optional(),project:L.object({head:L.string(),indexedHead:L.string().nullable(),dirty:L.boolean()}).strict().optional(),items:L.array(L.record(L.string(),L.unknown())).optional(),text:L.string().optional(),total:L.number().int().optional(),hasMore:L.boolean().optional(),nextCursor:L.string().nullable().optional()}).strict(),annotations:be},async e=>{const t=Je.cwd||process.cwd();if(!Je.projectIntelligence||Je.projectIntelligence.cwd!==t){try{await(Je.projectIntelligence?.close())}catch{}Je.projectIntelligence=new ye({cwd:t})}const r=await Je.projectIntelligence.query(e);return{content:[{type:"text",text:ve(r)}],structuredContent:r}}),r}),xt=r.join(ne||process.cwd(),"FLOW_REVIEW.json"),_t=Je.reviewSliceRoots.length?({toolName:e,input:t})=>{for(const r of Je.reviewSliceRoots){const o=Yt({toolName:e,input:t,sliceRoot:r,verdictFile:xt});if(!o.allow)return o}return{allow:!0,reason:"no reviewed slice targeted"}}:null;Je.deferred=!!he;const At=Wo(ge,$e);Je.pendingRecap=At.pendingRecap,Je.pendingCheckpoint=At.pendingCheckpoint;const Pt=[qn({spawnedBy:Je.spawnedBy,spawnDepth:Je.spawnDepth,cascadeRole:Je.cascadeRole,flowRole:Je.flowRole,sideParent:Je.sideParent}),yt?Kn:""].filter(Boolean).join("\n\n"),Nt="claude"===t?C(we):null;let Et=!1;const Dt=!0===Nt?.policy?.enabled?{policy:Nt.policy,providers:N(),providerId:Nt.target.providerId,model:Nt.target.actualConfiguredModel,requestedModel:Ke||Nt.target.actualConfiguredModel,bridgeHostId:Rs,circuit:Ss,turnRev:()=>(Number(Je._turnRev)||0)+1,capGate:()=>{const t=Je.flowSessionId?vr.get(Je.flowSessionId):null,r=q(t);return r.configured||Et||(Et=!0,process.stderr.write(`\n ${ka}◇ provider resilience cap_not_configured (${String(e).slice(0,8)})${ba}\n`)),r}}:null;if(Je.session=X(t,{cwd:ne||process.cwd(),model:Ke,models:je,effort:i,allowUltraCascade:"codex"===t&&me(Je),resume:a,mode:u,terminalRolePrompt:Pt,rolePrompt:E,prepareCwd:ne||j||K?null:()=>{try{Je.managedWorktree?.dir||(Je.managedWorktree=Ce({terminalId:e,cwd:process.cwd()})),Je.cwd=Je.managedWorktree.dir,Je.viewport.setWorkspaceRoot(Je.cwd);try{Je.flush?.()}catch{}return Je.cwd}catch(t){return process.stderr.write(`\n ◇ terminal worktree unavailable (${String(e).slice(0,8)}): ${t?.message||t}; using bridge checkout.\n`),ne||process.cwd()}},suggest:!we||"anthropic"===we,roomContext:()=>{const t=function(e){const t=e||process.cwd(),r=Ea.get(t);if(r&&Date.now()-r.at<6e4)return r.list;let o=[];try{o=s("git",["-C",t,"worktree","list"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).split("\n").map(e=>e.trim()).filter(Boolean)}catch{o=[]}return Ea.set(t,{at:Date.now(),list:o}),o}(ne||process.cwd());return Or({selfId:e,sessions:Js,terms:zs,names:vi,worktrees:t.length>1?t:[]})},lazy:se({runtime:t,defer:he,cwd:ne,flowSessionId:j,flowTaskKey:K,models:Je.models}),admitStart:()=>{const e=Ee("start this agent runtime");return e.ok||ji(),e},reviewGate:_t,blockSubagents:"conductor"===Je.flowRole,onSubmitPlan:t=>{if(!Je.flowSessionId||"conductor"!==Je.flowRole)return{ok:!1,message:"Not a Dispatch conductor — nothing to submit."};let r;try{r=ot(rt(t||""),Je.runtime)}catch(e){return{ok:!1,message:`Plan REJECTED: ${e?.message||e}. Re-Write FLOW_PLAN.json with valid JSON: a non-empty acyclic tasks array; each builder/fix/scaffold has observable acceptance, bounded nonGoals, and a baseline gate that says what fails/is absent; each review targets exactly one builder contract.`}}return wi("flow-plan",{term:e,flowId:Je.flowSessionId,plan:JSON.stringify(r)},Ls),process.stderr.write(`\n ${Ta}◆ flow plan submitted — flow ${String(Je.flowSessionId).slice(0,8)} (${r.tasks.length} slice${1===r.tasks.length?"":"s"}).${ba}\n`),{ok:!0,message:`Plan SUBMITTED (${r.tasks.length} slice${1===r.tasks.length?"":"s"}) with gate-first contracts. Record safe reversible assumptions in the summary; user steering remains authoritative. The room is showing approval. You are DONE: stop here and wait for approval.`}},onLaneDone:"builder"===Je.flowRole?async e=>{let t="";try{const r=JSON.parse(String(e||"").trim());t="string"==typeof r?.baselineEvidence?r.baselineEvidence:""}catch{}return{ok:!0,message:await Ye({baselineEvidence:t})}}:null,onReviewVerdict:"reviewer"===Je.flowRole?Xe:null,mcpServers:{thinkpool:Ct},requiredMcpTools:"hermes"===t?Te(Ie({flowRole:Je.flowRole,sliceType:Je.sliceType}),{canSpawnWorkers:yt}):void 0,hermesRole:"hermes"===t?Ie({flowRole:Je.flowRole,sliceType:Je.sliceType}):void 0,crossPostGate:()=>Rr({hop:Je.hop||0,postCount:Je.postCount||0,disabled:"1"===process.env.TP_CROSSPOST_OFF}),didSpawnTarget:t=>{try{const r=Tr({selfId:e,sessions:Js,terms:zs,names:vi}),o=Ir(r,t);if(!o)return!1;const n=Js.get(o.id);return!!n&&n.spawnedBy===e}catch{return!1}},crossRoomPostGate:()=>Nr({roomHop:Je.roomHop||0,postCount:Je.crossRoomPostCount||0,disabled:"1"===process.env.TP_PAIRBUS_OFF}),env:{...process.env,...Qe({flowSessionId:j,mode:u}),...R(we)||{},TP_MOCKUP_OUTBOX:Ze},resilience:Dt,onTurnStart:(t={})=>{!0===Je._busyAnn?function(e,t=Date.now()){e._turnRev=(Number(e._turnRev)||0)+1,e._turnStart=t,e._busyAnn=!0,e._settledTurnRev=null,e._turnSettledAt=null}(Je):Vs(Je);const r=t._thinkpoolQueuedEcho;if(r){const t={kind:"you",...r};_a(Je,t),wi("code-event",{term:e,evt:t})}Ii()},onEvent:r=>{if(!tn(r).known)return Ca(xa(Je,r)),void Ii();const n="system"===r.kind&&fe({current:Je.commands,incoming:pe(t,r.commands),onChanged:e=>{Je.commands=e,Ii(),it()}});if(a&&"error"===r.kind){const t=Je.interruptedRecap||Lo(Je.log,Ho),n=Qr(Je,{message:r.message,recap:t,reopen:t=>{Je.imageQueue?.close();try{Je.mockupWatcher?.close()}catch{}return Js.delete(e),ja({id:e,runtime:Je.runtime,model:Je.model||o,effort:Je.effort,provider:Je.provider,log:Je.log,commands:Je.commands,mode:Je.mode,spawnedBy:Je.spawnedBy,spawnDepth:Je.spawnDepth,cascadeRole:Je.cascadeRole,hop:Je.hop,sideParent:Je.sideParent,sideTask:Je.sideTask,pendingSideContexts:Je.pendingSideContexts,pendingWorkerCompletions:Je.pendingWorkerCompletions,workerCompletionsInFlight:Je.workerCompletionsInFlight,sliceType:Je.sliceType,flowSessionId:Je.flowSessionId,flowTaskKey:Je.flowTaskKey,flowTaskContract:Je.flowTaskContract,flowRole:Je.flowRole,flowReviewTarget:Je.flowReviewTarget,flowReviewTargets:Je.flowReviewTargets,flowReviewSnapshots:Je.flowReviewSnapshots,flowReviewRound:Je.flowReviewRound,flowReviewConclusion:Je.flowReviewConclusion,dispatchBaseSha:Je.dispatchBaseSha,revertTarget:Je.revertTarget,cwd:Je.cwd,managedWorktree:Je.managedWorktree,rolePrompt:Je.rolePrompt,reviewSliceRoots:Je.reviewSliceRoots,openedAt:Je.openedAt,lastUsage:Je.lastUsage,mcpFlight:Je.mcpFlight,carryRecap:t,carryCheckpoint:Je.pendingCheckpoint}),Js.get(e)||null}});if(n.recovered)return void process.stderr.write(`\n ◆ saved session expired — started fresh with transcript recap (${n.delivery}).\n`)}const s="hermes"===t&&("result"===r.kind||"error"===r.kind)&&(Je.session?.queuedDepth||0)>0;s&&(r.continuesQueued=!0);const i=!s&&"result"===r.kind,c=i?Kr(Je):Ys(Je),l=En(r,{turnActive:!0===Je.session?.turnActive});if(ei(Je,r),i){const e=Qo(Je);e&&(r.work=e)}xo(r),i&&(Je._settledTurnRev=Number(r.turnRev)||Number(Je._turnRev)||null,Je._turnSettledAt=Number(r.ts)||Date.now());const d="stalled"===r.kind?!Je.stalled:!!Je.stalled;Je.stalled="stalled"===r.kind,Je.lastEvent=r,"stalled"!==r.kind&&(Je.lastActionAt=r.ts),(c||d)&&Ii();{const e=!0===de(Je.runtime)?.canSteer&&(Je.session?.canSteer??!1);e!==Je._canSteerAnn&&(Je._canSteerAnn=e,Ii())}{const e="hermes"!==Je.runtime&&(!Je.provider||"anthropic"===Je.provider),t="hermes"===Je.runtime||e?r.model||r.ctx?.model:null;t&&t!==Je.model&&(Je.model=t,Ii(),"model-switch"===r.kind&&it()),"hermes"===Je.runtime&&"models"===r.kind&&Array.isArray(r.models)&&r.models.length?(Je.models=_n(r.models),Ln=Je.models,Ii()):e&&"models"===r.kind&&Array.isArray(r.models)&&r.models.length&&(Ti=r.models,Ii())}if("model-switch"===r.kind){const t=Je.pendingModelSwitch;Je.pendingModelSwitch=null;const o=r.requested||t?.model||"requested model",n={kind:"control",text:"success"===r.status?`switched model → ${r.model||o}`:`couldn’t switch to ${o} — still using ${Je.model||"the previous model"}`,by:t?.by||null,cid:t?.cid||void 0};_a(Je,n),wi("code-event",{term:e,evt:n}),Je.flush?.(),Ii()}if("usage"===r.kind&&(Je.lastUsage=r,it()),"effort"===r.kind&&(Je.effort=r.level??r.effort??null,it(),Ii()),Je.flowSessionId&&Je.flowTaskKey&&"result"===r.kind&&r.usage){const e=vr.get(Je.flowSessionId);e&&vr.set(Je.flowSessionId,cr(e,r.usage.output_tokens||0))}var u;if("result"===r.kind&&r.usage&&(u=r.usage.output_tokens||0,!js&&zn&&rs&&u&&qs("record_spend",{p_room:rs,p_tokens:u}).catch(()=>{}),function(e,t,r){if(!zn||!rs||!e)return;const o=t||{},n=(o.input_tokens||0)+(o.cache_creation_input_tokens||0)+(o.cache_read_input_tokens||0),s=o.output_tokens||0,i=o.cache_read_input_tokens||0;(n||s)&&Cn(e).then(t=>qs("record_code_usage",{p_room:rs,p_model:e,p_input:n,p_output:s,p_cached:i,p_provider:r||"unknown",p_input_usd_per_mtok:t?.input??null,p_output_usd_per_mtok:t?.output??null,p_cached_input_usd_per_mtok:t?.cached??null,p_rate_source:t?.source??null})).catch(()=>{})}(r.model,r.usage,Je.provider)),Je.flowSessionId&&Je.flowTaskKey&&!Je.flowDone&&et({runtime:Je.runtime,flowRole:Je.flowRole,eventKind:r.kind,eventSubtype:r.subtype})&&Promise.resolve().then(()=>Ye()).catch(()=>{}),"system"===r.kind&&Je.pendingAutoResume&&Xr(Je)&&process.stderr.write(`\n ◆ auto-resumed interrupted turn (${e.slice(0,8)}) — sent continue.\n`),"system"===r.kind&&Je.pendingRecap){const t=Je.pendingRecap.length;Yr(Je)&&process.stderr.write(`\n ◆ carried ${t}c context recap into fresh session (${e.slice(0,8)}) after provider/restore switch.\n`)}"system"===r.kind&&Je.warming&&(e=>{if(e&&e.warming){e.warming=!1,e.warmed=!0,ni=Math.max(0,ni-1);try{clearTimeout(e.warmTimer)}catch{}ii()}})(Je),"compaction"===r.kind&&(Na(Je),Je.compacting?(r.by=Je.compactBy||null,Je.compacting=!1,Je.compactBy=null,wi("code-event",{term:e,evt:{kind:"compact",status:"done",ts:Date.now()}})):"auto"===r.trigger&&(wi("code-event",{term:e,evt:{kind:"compact",status:"start",ts:Date.now()}}),setTimeout(()=>{wi("code-event",{term:e,evt:{kind:"compact",status:"done",ts:Date.now()}})},2500)));const m="mode"===r.kind||"usage"===r.kind||"effort"===r.kind||"clear"===r.kind||"compact"===r.kind||"stalled"===r.kind||"suggestion"===r.kind||"assistant_stream"===r.kind||"model-switch"===r.kind;if(("result"===r.kind||"error"===r.kind)&&Je.compacting){const t=Je.compactBy||null;Je.compacting=!1,Je.compactBy=null,wi("code-event",{term:e,evt:{kind:"compact",status:"done",ts:Date.now()}});const o={kind:"control",text:("error"===r.kind?"compaction failed":"aborted"===r.subtype?"compaction canceled":"nothing to compact")+" — context unchanged",by:t};_a(Je,o),wi("code-event",{term:e,evt:o})}if(("result"===r.kind||"error"===r.kind)&&"codex"===Je.runtime&&Je.pendingCodexCompaction){const e=Je.pendingCodexCompaction;Je.pendingCodexCompaction=null,Oa(Je,e)}if("result"===r.kind||"error"===r.kind){i&&Je.workerCompletionsInFlight?.length&&(Je.pendingWorkerCompletions=$n(Je.pendingWorkerCompletions,Je.workerCompletionsInFlight),Je.workerCompletionsInFlight=[],Je.flush?.());const t=Xi.get(e);if(t?"result"!==r.kind||r.subtype&&"success"!==r.subtype?aa(e,"failed",{message:"The producing lane did not complete the edit."}):(t.resultOk=!0,ia({previewId:t.record.previewId,requestId:t.request.cid,state:"verifying",message:"Waiting for correlated desktop and mobile renders…"}),t.timer=setTimeout(()=>aa(e,"failed",{message:"The edit finished without a correlated desktop and mobile render."}),12e4),t.timer.unref?.(),ca(e)):(Qi.get(e)||[]).length&&queueMicrotask(()=>la(e)),Je.sideHandback){const t=Je.sideHandback;Je.sideHandback=null;const o=Js.get(t.parentId),n="result"!==r.kind||r.subtype&&"success"!==r.subtype?"":String(r.resultText||"").trim()||vn(Je.log,t.afterSeq);if(o&&n){const r=kn({sideId:e,sideName:vi[e],task:Je.sideTask,summary:n});o.pendingSideContexts=gn(o.pendingSideContexts,r);const s={kind:"side-handback",sideId:e,sideName:vi[e]||"Side lane",task:Je.sideTask||"",text:n,by:t.by};xo(s),_a(o,s),wi("code-event",{term:t.parentId,evt:s});const i={kind:"control",text:"Brought to main.",by:t.by};xo(i),_a(Je,i),wi("code-event",{term:e,evt:i}),o.flush?.(),Xs(o)}else{const r={kind:"control",text:o?"Couldn’t prepare a handoff — try again.":"The main terminal is no longer available.",by:t.by};xo(r),_a(Je,r),wi("code-event",{term:e,evt:r})}Je.flush?.(),Ii()}const o=Je._turnStart;Je._turnStart=null;const n=[...Je.pending.keys()];Fa(Je);for(const t of n)wi("code-perm",{term:e,id:t,decision:"deny",name:"agent"});if(i&&Je.spawnedBy&&!String(Je.spawnedBy).startsWith("flow:")){const t=Js.get(Je.spawnedBy),o=Number(r.turnRev)||Number(Je._turnRev)||0;if(t&&o>0&&Je._ownerNotifiedTurnRev!==o){const n=Rn({workerId:e,workerName:vi[e],turnRev:o,subtype:r.subtype});n&&(Je._ownerNotifiedTurnRev=o,t.pendingWorkerCompletions=Tn(t.pendingWorkerCompletions,n),t.flush?.(),Zs(t))}}Xs(Je),Zs(Je);const s=Date.now();k({entry:Je,subtype:r.subtype,startedAt:o,now:s})&&Us({kind:"turn-done",term:e,termName:vi[e]||null,model:Je.model||null,summary:$("result"===r.kind?r.resultText:r.message),subtype:r.subtype||("error"===r.kind?"error":null),pushEligible:y({entry:Je,subtype:r.subtype,startedAt:o,now:s,minTurnMs:Ms})})}const p=Do(r);!function(e,t,r,o,n){e.imageQueue||=new jo({maxPending:Bn.maxPending,maxBytes:Bn.maxBytes,upload:(e,r,o)=>async function(e,t,r,o){return Ko({webBase:Fn,room:rs,authToken:zn,term:e,cid:t,image:r,timeoutMs:Bn.uploadTimeoutMs,activeUploads:o})}(t,e.cid,r,o),onUploadError:e=>process.stderr.write(`\n ◇ screenshot upload failed (${e?.message||e}).\n`),onOverload:({maxPending:e,maxBytes:t})=>process.stderr.write(`\n ◇ screenshot omitted (image queue cap: ${e} pending / ${t} encoded bytes).\n`)}),e.imageQueue.enqueue(r,o,n)}(Je,e,r,p,t=>{if(!n&&(m||_a(Je,t),wi("code-event",{term:e,evt:t}),Ca(t),m||it(),l&&queueMicrotask(()=>{ua.flush(e).catch(()=>{})}),i&&Je.scheduleRunId&&("result"===t.kind||"error"===t.kind))){const e=Je.scheduleTimedOut?{...t,subtype:"runtime_limit"}:t;na(Je,e,{canceled:!Je.scheduleTimedOut&&"aborted"===t.subtype})}})},requestPermission:St}),"codex"===t&&Je.session?.usageSnapshot?.context){const{used:e,max:t}=Je.session.usageSnapshot.context;Je.lastUsage={kind:"usage",ctx:{used:e,max:t,pct:Math.min(100,Math.max(0,Math.round(e/t*100))),over:e>t,model:Je.model}}}return Je.log.length||Je.flush(),Zs(Je),Ii(),Je.log.length||process.stderr.write(`\n ◆ structured ${de(t)?.label||"agent"} session (${e.slice(0,8)}) — driven from the room.\n`),Je}function qa(e,t={}){const r=t.decision||"deny";return"dispatch"===e?.payload?.answerFormat?{decision:r,dispatchFingerprint:t.dispatchFingerprint||null,controlItemId:t.controlItemId||null}:"ask"===e?.payload?.risk||"codex"===e?.payload?.answerFormat||"hermes"===e?.payload?.answerFormat?{decision:r,answers:t.answers||{},responder:t.responder||null}:r}function Ka(e,t=null,r="permission_aborted",o=!1){const n=t||[...e?.pending?.entries?.()||[]].map(([e])=>e);n.length&&e?.id&&(o?w:g)({supabaseUrl:Un,anonKey:Wn,token:zn,roomCode:rs,bridgeId:ks,terminalId:e.id,permissionIds:n,reason:r}).then(e=>{!e.ok&&process.env.TP_DEBUG&&process.stderr.write(`\n ◇ durable permission cleanup incomplete (${e.code})\n`)})}let Ma=!1;async function Ua(){Ma=!0;const e=await g({supabaseUrl:Un,anonKey:Wn,token:zn,roomCode:rs,currentBridgeId:ks,reason:"bridge_restarted"});return e.ok?Ma=!1:process.env.TP_DEBUG&&process.stderr.write(`\n ◇ restored permission cleanup incomplete (${e.code})\n`),e}function Fa(e){if(e?.pending){to(e),Ka(e,null,"permission_aborted");for(const[,t]of e.pending){t?.timer&&clearTimeout(t.timer);try{t.resolve(qa(t,{decision:"deny"}))}catch{}}e.pending.clear(),e.permNotifier?.clearAll()}}function Ba(e){if(e?.pending)for(const[t,r]of e.pending)if("plan"!==r?.payload?.risk&&"ask"!==r?.payload?.risk&&"dispatch"!==r?.payload?.answerFormat){r?.timer&&clearTimeout(r.timer);try{r.resolve("allow")}catch{}e.pending.delete(t),e.permNotifier?.resolve(t)}}const La=new Set(["Write","Edit","MultiEdit","NotebookEdit"]);function Wa(e){if(e?.pending)for(const[t,r]of e.pending){const o=r?.payload?.toolName,n=r?.payload?.risk;if("plan"!==n&&"ask"!==n&&"high"!==n&&La.has(o)){r?.timer&&clearTimeout(r.timer);try{r.resolve("allow")}catch{}e.pending.delete(t),e.permNotifier?.resolve(t)}}}function Ha(e){if(!e)return;const r=Js.get(e);if(r){na(r,{subtype:"canceled"},{canceled:!0}),ea(r),r.imageQueue?.close(),ua.clear(e),Fa(r);try{r.session?.end()}catch{}try{r.projectIntelligence?.close()}catch{}try{r.mockupWatcher?.close()}catch{}try{r.viewport?.stop()?.catch(()=>{})}catch{}const o=Xi.get(e);o?.timer&&clearTimeout(o.timer),Xi.delete(e),Qi.delete(e);for(const[t,r]of Vi)r.term===e&&Vi.delete(t);for(const[t,r]of Zi)r.priorRecord?.term===e&&Zi.delete(t);try{t.rmSync(pa("sessions",e),{recursive:!0,force:!0})}catch{}Js.delete(e),Ki(e),wi("term-exit",{id:e}),function(e){h({id:e,token:zn,supabaseUrl:Un,anonKey:Wn,shuttingDown:ri,onFailure:({error:t,status:r})=>process.stderr.write(`\n ⚠ terminal row reap failed (${String(e).slice(0,8)}${r?`, HTTP ${r}`:""}): ${t||"unknown error"}\n`)})}(e),function(e){if(e)try{const t={"Content-Type":"application/json"};zn&&(t.Authorization=`Bearer ${zn}`),fetch(`${Fn}/api/code-image-cleanup`,{method:"POST",headers:t,body:JSON.stringify({code:rs,term:e})}).catch(()=>{})}catch{}}(e);try{xe({terminalId:e,managedWorktree:r.managedWorktree})}catch{}for(const[t,r]of[...Js])r.spawnedBy!==e&&r.sideParent!==e||Ha(t)}io(rs,e),r&&Ii()}function za(e,t=4e3){if(!e)return;const r=`flow:${e}`;vr.delete(e),setTimeout(()=>{for(const[t,o]of[...Js])if(o.flowSessionId===e||o.spawnedBy===r)try{Ha(t)}catch{}},t)}function Ja(e){if(e&&li!==e){li=e;for(const t of Js.keys())wi("code-event",{term:t,evt:{kind:"update-available",version:e}});Ii()}}const Ga=()=>{if(oo(Js))return!1;for(const e of zs.values())if(e.buf)return!1;return!0};async function Ya(){if(!di||!li||ui)return!1;if(process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD)return!1;if(!Ga())return!1;ui=!0;try{const e=await import("./service.mjs");if(!e.serviceActive(rs))return!1;const t=!1!==e.updateService(rs);return t||(ui=!1),t}catch(e){return ui=!1,process.stderr.write(`\n ⚠ bridge update failed: ${e?.message||e}\n`),!1}}setInterval(()=>{di&&Ya()},5e3).unref();const Va=()=>{try{process.stdin.isTTY&&process.stdin.setRawMode(!1)}catch{}};fs&&process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.on("data",e=>{const t=ti&&zs.get(ti);if(t)try{t.term.write(e.toString("utf8"))}catch{}else e.includes(3)&&ac()}),process.stdout.on("resize",()=>{const e=ti&&zs.get(ti);if(!e)return;const{cols:t,rows:r}=ga();if(e.term.cols!==t||e.term.rows!==r)try{e.term.resize(t,r),Ii()}catch{}});let Qa=!1,Xa=Date.now();async function Za(e){try{return await fr({payload:e,bridgeName:ys,lanes:[...Js.entries()],prepareLane:(e,t)=>dr({lane:{cwd:e.cwd,session:e.session,commitSha:e.commitSha,revertTarget:t.commitSha??e.commitSha??e.revertTarget??null},sanitize:mr}),rememberRedispatch:(e,t,r)=>{wr.set(ur(r.flowId,r.taskKey),{resumeSessionId:e.resumeSessionId,revertTarget:e.revertTarget}),e.healed&&process.stderr.write(`\n ${ka}◆ flow re-dispatch heal — ${r.taskKey}: ${e.healed} dangling tool block(s) healed before resume.${ba}\n`)},endLane:e=>{try{Ha(e)}catch{}},stopPreview:jt,wait:()=>new Promise(e=>setTimeout(e,400)),revert:e=>Mt({flowId:e.flowId,taskKey:e.taskKey}),broadcastReverted:e=>{wi("flow-reverted",{term:"flow",flowId:e.flowId,taskKey:e.taskKey,reviewTaskKey:e.reviewTaskKey,branch:e.branch},Ls),process.stderr.write(`\n ${Ia}◆ flow slice reverted — ${e.taskKey} (${e.branch}).${ba}\n`)},onPrepError:(e,t,r)=>process.stderr.write(`\n ${Ia}◆ flow re-dispatch prep failed (${r.taskKey}): ${e?.message||e} — will re-dispatch fresh.${ba}\n`)})}catch(e){return process.stderr.write(`\n ${Ia}◆ flow revert failed: ${e?.message||e}${ba}\n`),{ok:!1,error:e?.message||String(e)}}}Hs.on("broadcast",{event:"apply-update"},()=>{if(li&&(di=!0,process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD))try{process.send({t:"apply-update"})}catch{}}).on("broadcast",{event:"bridge-update"},async({payload:e})=>{const t=e?.nonce,r=(e,r,o)=>Hs.send({type:"broadcast",event:"bridge-update-res",payload:{nonce:t,ok:e,...r?{error:r}:{},...o?{state:o}:{}}});if(!t)return r(!1,"invalid request");const o="string"==typeof e?.v&&/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(e.v)?e.v:null;if(!o)return r(!1,"invalid bridge version");if(Ja(o),di=!0,process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD){try{process.send({t:"apply-update"})}catch{return r(!1,"account supervisor is unavailable")}return r(!0,null,"queued")}let n=!1;try{n=(await import("./service.mjs")).serviceActive(rs)}catch{}return n?Ga()?(await r(!0,null,"applying"),void Ya()):r(!0,null,"queued"):(di=!1,r(!1,"This bridge is running in a terminal. Restart it once with npx thinkpool-pair@latest, or install the background service to enable remote updates."))}).on("broadcast",{event:"providers-list-req"},({payload:e})=>{Hs.send({type:"broadcast",event:"providers-list-res",payload:{nonce:e?.nonce,ok:!0,providers:N()}})}).on("broadcast",{event:"provider-switch"},({payload:e})=>{const t=e?.nonce,r=(e,r,o)=>Hs.send({type:"broadcast",event:"provider-switch-res",payload:{nonce:t,ok:e,...r?{error:r}:{},...void 0===o?{}:{restarted:o}}}),o=e?.term,n=o?Js.get(o):null;if(!n)return r(!1,"no such live lane");const s=K({provider:e?.provider,currentProvider:n.provider,registeredIds:N().map(e=>e.id)});if(!s.ok)return r(!1,s.error);const i=e?.provider===U?null:e?.provider,a=M({provider:e?.provider,currentProvider:n.provider,sameEnv:E(n.provider,i),targetModel:D(i)});if("noop"===a.action)return r(!0,void 0,!1);if("in-place"===a.action&&function(e,t){const r=Js.get(e);if(!r?.session)return!1;const o=D(t);if(!o)return!1;r.provider=t||null,r.model=o;try{r.session.setModel(o)}catch{return!1}try{r.flush?.()}catch{}return!0}(o,i))return process.stderr.write(`\n ◆ lane ${String(o).slice(0,8)} switched model → ${D(i)} (same key, context kept).\n`),Ii(),r(!0,void 0,!1);const c=function(e,t){const r=Js.get(e);if(!r)return!1;r.imageQueue?.close();const{runtime:o,log:n,commands:s,mode:i,spawnedBy:a,spawnDepth:c,cascadeRole:l,hop:d,sideParent:u,sideTask:m,pendingSideContexts:p,pendingWorkerCompletions:h,workerCompletionsInFlight:f,sliceType:w,flowSessionId:g,flowTaskKey:v,flowTaskContract:y,flowRole:k,flowReviewTarget:b,flowReviewTargets:$,flowReviewSnapshots:T,flowReviewRound:I,flowReviewConclusion:R,dispatchBaseSha:S,revertTarget:C,cwd:x,managedWorktree:_,rolePrompt:A,reviewSliceRoots:P,openedAt:N,lastUsage:O,mcpFlight:E,pendingCheckpoint:D}=r,j=g?null:Lo(n,Ho);Fa(r);try{r.session?.end()}catch{}try{r.mockupWatcher?.close()}catch{}try{r.viewport?.stop()?.catch(()=>{})}catch{}return Js.delete(e),ja({id:e,runtime:o,provider:t,log:n,commands:s,mode:i,spawnedBy:a,spawnDepth:c,cascadeRole:l,hop:d,sideParent:u,sideTask:m,pendingSideContexts:p,pendingWorkerCompletions:h,workerCompletionsInFlight:f,sliceType:w,flowSessionId:g,flowTaskKey:v,flowTaskContract:y,flowRole:k,flowReviewTarget:b,flowReviewTargets:$,flowReviewSnapshots:T,flowReviewRound:I,flowReviewConclusion:R,dispatchBaseSha:S,revertTarget:C,cwd:x,managedWorktree:_,rolePrompt:A,reviewSliceRoots:P,openedAt:N,lastUsage:O,mcpFlight:E,carryRecap:j,carryCheckpoint:D}),!0}(o,i);if(!c)return r(!1,"no such live lane");process.stderr.write(`\n ◆ lane ${String(o).slice(0,8)} switched provider → ${i||"anthropic"} (memory reset, transcript kept).\n`),r(!0,void 0,!0)}).subscribe(e=>{"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||process.stderr.write(`\n ⚠ private bridge control ${e} (tpcontrol:${rs}).\n`)}),Bs.on("broadcast",{event:"pty-in"},({payload:e})=>{if(!e?.data)return;ci();const t=zs.get(e.term)||(null==e.term&&ti?zs.get(ti):null);if(t)try{t.term.write(e.data)}catch{}}).on("broadcast",{event:"resize"},({payload:e})=>{if(!e?.cols||!e?.rows)return;const t=zs.get(e.term);if(t&&!t.attached)try{t.term.resize(Math.max(e.cols,80),Math.max(e.rows,20)),Ii()}catch{}}).on("broadcast",{event:"session-deleted"},async()=>{if(process.stderr.write("\n ◆ this room was deleted — closing the bridge.\n"),"1"===process.env.THINKPOOL_PAIR_AUTOUPDATE)try{(await import("./service.mjs")).uninstallService(rs)}catch{}ac()}).on("broadcast",{event:"term-open"},async({payload:e})=>{if(!e?.id||!e?.cmd)return;if(e.host&&e.host!==ys)return;if(zs.has(e.id))return void ki(e.id,"pty",zs.get(e.id));let t=[];if(e.resume){const r=Gn.find(t=>t.cmd===e.cmd);if(r?.resume)try{r.resume.probe()&&(t=[...r.resume.args])}catch{}}if(cs(e.cmd)){const t=Js.get(e.id);if(t)return void ki(e.id,"structured",t);let r=as(e.cmd),o=null,n=null;if(e.sideParent){const t=Js.get(e.sideParent);if(o=t?.sideParent||e.sideParent,n=Js.get(o),!n||!String(e.sideTask||"").trim())return void wi("side-open-failed",{id:e.id,parent:o,message:n?"Add a task after /side.":"The main terminal is not live."});r=n.runtime||r,e.name&&(vi[e.id]=String(e.name).slice(0,80),ho(rs,vi))}if(ja({id:e.id,runtime:r,mode:n?.mode||e.mode,model:n?.model||e.model||void 0,provider:"claude"===r&&(n?.provider||e.provider)||void 0,cwd:n?n.cwd||process.cwd():void 0,sideParent:o||void 0,sideTask:o?String(e.sideTask).trim():void 0,rolePrompt:o?wn:void 0,defer:!0}),o){const t=Js.get(e.id),r=String(e.sideTask).trim(),s=Array.isArray(e.files)?e.files:[],i=String(e.by||"A room member"),a=vi[e.id]||"Side lane";if(!t)return void wi("side-open-failed",{id:e.id,parent:o,message:"The side lane could not start."});const c=await Mi(t);if(!c.ok){const t=c.reason||"This bridge machine cannot start another agent runtime yet.";return wi("side-open-failed",{id:e.id,parent:o,message:t}),void Ha(e.id)}t.hop=0;const l={kind:"you",text:r,by:i,...s.length?{files:s}:{}},d={kind:"side-started",sideId:e.id,sideName:a,task:r,by:i};_a(n,d),wi("code-event",{term:o,evt:d});const u=bn(n.log.filter(e=>e.cid!==d.cid)),m=s.map(e=>Re(e,{updir:Ps})).filter(Boolean),p=m.length?`${r}\n\n${m.map(e=>`"${e}"`).join(" ")}`:r,h=u?`${u}\n\n--- side task ---\n${p}`:p,f="codex"===t.runtime||"hermes"===t.runtime?await Se(s,{updir:Ps}):[];return Qs(t,h,{options:f.length?{images:f}:void 0,visibleEvent:l,rejectionMessage:"The side-lane task was not accepted; retry after the lane is available."}).accepted?(t.flush?.(),n.flush?.(),Ii(),ki(e.id,"structured",t),void process.stderr.write(`\n ◆ ${i} opened side lane ${String(e.id).slice(0,8)} under ${String(o).slice(0,8)}.\n`)):(Ui(t,c),wi("side-open-failed",{id:e.id,parent:o,message:"The side agent could not start."}),void Ha(e.id))}const s=Js.get(e.id);return s&&ki(e.id,"structured",s),void process.stderr.write(`\n ◆ web opened a structured "${e.cmd}" session (${e.mode||"default"}${e.model?`, model ${e.model}`:""}).\n`)}const r=await qi(e.id);r.ok?(va({id:e.id,cmd:e.cmd,args:t}),zs.has(e.id)?ki(e.id,"pty",zs.get(e.id)):Ki(e.id),process.stderr.write(`\n ◆ web opened a "${e.cmd}"${t.length?" (continue)":""} terminal (headless).\n`)):wi("term-exit",{id:e.id,reason:r.reason||"This bridge machine cannot accept another live lane yet."})}).on("broadcast",{event:"term-close"},({payload:e})=>{const t=e?.id&&zs.get(e.id);if(t&&!t.attached)try{t.term.kill()}catch{}else t||Ha(e?.id)}).on("broadcast",{event:"replay-request"},({payload:e})=>{zi();const t=e?.to??null,r=String(e?.requestId||c?.()||`${Date.now()}`),o=[];for(const[n,s]of Yo(zs,e?.terms,e?.priority)){if(!s.scrollback)continue;const e=s.scrollback.length>1e5?s.scrollback.slice(-1e5):s.scrollback;o.push({event:"pty-replay",payload:{to:t,term:n,requestId:r,b64:Buffer.from(e,"utf8").toString("base64")}})}const n=Yo(Js,e?.terms,e?.priority);for(const[s,i]of n){if(!i.log.length){o.push({event:"code-replay",payload:{to:t,term:s,requestId:r,chunkIndex:0,chunkCount:1,events:[],empty:!0}});continue}const n=Number(e?.cursors?.[s])||0,a=Ao(i.log),c=n>a,l=(n>0&&!c?i.log.filter(e=>null==e.seq||e.seq>n):i.log).map(e=>Eo(e)),d=Oo(l),u=c?0:n,m=zo(Jo(d[0]||[]),u,i.archiveOldestSeq);for(let e=0;e<d.length;e++){const n=d[e];o.push({event:"code-replay",payload:{to:t,term:s,requestId:r,chunkIndex:e,chunkCount:d.length,events:n,...c?{reset:!0}:{},...0===e&&null!=m?{trimmedBefore:m}:{},...0===e&&i.lastUsage?.ctx?{lastUsage:i.lastUsage}:{}}})}}gi.enqueue(t||"*",o,async()=>{for(const[,e]of Js)for(const[,t]of e.pending)await hi("code-perm-req",t.payload);Ii()})}).on("broadcast",{event:"history-page-request"},({payload:e})=>{const t=e?.term;if(!t)return;if(!bo({payloadHost:e?.host,bridgeName:ys,hasSession:Js.has(t),hasArchive:ko(rs,t)}))return;const{events:r,hasMore:o}=go(rs,t,Number(e?.beforeSeq)||null,200),n=e?.to??null,s=String(e?.requestId||c?.()||`${Date.now()}`);if(!r.length)return void wi("history-page",{to:n,term:t,requestId:s,chunkIndex:0,chunkCount:1,events:[],hasMore:!1});const i=Oo(r.map(e=>Eo(e)));i.forEach((e,r)=>wi("history-page",{to:n,term:t,requestId:s,chunkIndex:r,chunkCount:i.length,events:e,hasMore:0!==r||o}))}).on("broadcast",{event:"session-search-request"},({payload:e})=>{if(e?.host&&e.host!==ys)return;const t=String(e?.query||"").trim().slice(0,200),r=String(e?.requestId||""),o=e?.to??null;if(!t||!r)return;const n=[...Js.keys()].map(e=>({term:e,termName:vi[e]||"terminal"})),{results:s,truncated:i}=yo(rs,n,t,{limit:200});wi("session-search",{to:o,requestId:r,host:ys,results:s,truncated:i})}).on("broadcast",{event:"file-put"},({payload:e})=>{e?.id&&e?.url&&(e.host&&e.host!==ys||(async()=>{try{const o=Re(e,{updir:Ps});if(!o)throw new Error("invalid attachment metadata");const n=await(async e=>{const t=zn&&(e=>{const t=String(e||""),r=`code/${rs}/`;return!t.startsWith(r)||t.includes("..")||t.split("/").some(e=>!e)?null:`${Un}/storage/v1/object/authenticated/session-attachments/${t.split("/").map(encodeURIComponent).join("/")}`})(e?.path),r=[{url:e?.url,headers:void 0},...t?[{url:t,headers:{apikey:Wn,Authorization:`Bearer ${zn}`}}]:[]].filter(e=>e.url);let o=new Error("no attachment source");for(let e=0;e<3;e++){for(const e of r)try{const t=await fetch(e.url,{headers:e.headers});if(!t.ok)throw new Error(`HTTP ${t.status}`);return Buffer.from(await t.arrayBuffer())}catch(e){o=e}e<2&&await new Promise(t=>setTimeout(t,250*(e+1)))}throw o})(e);if(n.length>26214400)throw new Error("file too large");t.mkdirSync(Ps,{recursive:!0}),t.writeFileSync(o,n),process.stderr.write(`\n ◆ file from the room: ${o}\n`),wi("file-done",{id:e.id,path:o.split(r.sep).join("/"),host:ys})}catch(t){process.stderr.write(`\n ◇ room file download failed (${o=e.name,String(o||"file").replace(/[^a-zA-Z0-9._-]/g,"_").slice(-80)||e.id}): ${t.message}\n`)}var o})())}).on("broadcast",{event:"code-open"},async({payload:e})=>{if(e?.host&&e.host!==ys)return;const t=e?.id||c();Js.has(t)||ja({id:t,runtime:e?.runtime,model:e?.model,provider:"claude"===e?.runtime?e?.provider:void 0,resume:e?.resume,mode:e?.mode,defer:!0})}).on("broadcast",{event:"side-handback-request"},async({payload:e})=>{const t=e?.term&&Js.get(e.term);if(!t?.sideParent||t.sideParent!==e?.parent)return;const r=String(e?.by||"A room member");if(t.sideHandback||t.session?.turnActive){const o={kind:"control",text:"Finish or stop the current side-lane turn before bringing it to main.",by:r};return xo(o),_a(t,o),void wi("code-event",{term:e.term,evt:o})}t.sideHandback={parentId:t.sideParent,by:r,afterSeq:Ao(t.log)};const o={kind:"control",text:"Preparing a compact handoff for main…",by:r};xo(o),_a(t,o),wi("code-event",{term:e.term,evt:o}),t.flush?.(),Ii();const n=await Mi(t);if(!n.ok){t.sideHandback=null;const o={kind:"control",text:n.reason||"The host cannot start another agent runtime yet.",by:r,tone:"caution"};return xo(o),_a(t,o),wi("code-event",{term:e.term,evt:o}),t.flush?.(),void Ii()}if(!Qs(t,fn,{rejectionMessage:"The side-lane handoff was not accepted; retry after the lane is available."}).accepted){Ui(t,n),t.sideHandback=null;const o={kind:"control",text:"Couldn’t start the handoff — try again.",by:r};xo(o),_a(t,o),wi("code-event",{term:e.term,evt:o}),t.flush?.(),Ii()}}).on("broadcast",{event:"code-turn"},async({payload:e})=>{const t=e?.term&&Js.get(e.term);if(!t||null==e.text)return;if(await Me(t),Js.get(e.term)!==t||!t.session)return;const r=e.cid&&String(e.cid);if(r){t.receivedTurnCids||(t.receivedTurnCids=new Set);const o=t.receivedTurnCids.has(r)||t.log?.some(e=>e?.cid===r&&("you"===e.kind||"control"===e.kind));if(!o){if(t.receivedTurnCids.add(r),t.receivedTurnCids.size>1e3){const e=t.receivedTurnCids.values().next().value;t.receivedTurnCids.delete(e)}t.flush?.()}if(wi("code-turn-ack",{term:e.term,cid:r,duplicate:o}),o)return}ci(),t.peekCount=0,t.peekRosterCount=0,t.postCount=0,t.pairPeekCount=0,t.crossRoomPostCount=0,t.spawnTimes=[],t.hop=0,t.roomHop=0;const o=String(e.text),n=function(e){const t=to(e);if(!t)return null;const r=e.pending?.get(t.permissionId);Ka(e,[t.permissionId],"dispatch_superseded",!0),r?.timer&&clearTimeout(r.timer),e.pending?.delete(t.permissionId),e.permNotifier?.resolve(t.permissionId);try{r?.resolve(qa(r,{decision:"deny"}))}catch{}return t.permissionId}(t);n&&Ii(),eo(t);const s=()=>{if(e.silent)return;const r={kind:"you",text:null!=e.body?String(e.body):o,cid:e.cid,by:e.by,...e.authorId?{authorId:e.authorId}:{},...e.steered?{steered:!0}:{},...Array.isArray(e.files)&&e.files.length?{files:e.files}:{},...Array.isArray(e.pastes)&&e.pastes.length?{pastes:e.pastes}:{}};_a(t,r),wi("code-event",{term:e.term,evt:r})},i=(r,o={})=>{const n={kind:"control",text:r,by:e.by,cid:e.cid,...o};_a(t,n),wi("code-event",{term:e.term,evt:n})},a=async({echo:r=!1}={})=>{const o=await Mi(t);if(o.ok)return o;r&&s();const n={kind:"error",message:o.reason||"This bridge machine cannot start another agent runtime yet. Close a running lane and retry.",recoverable:!0};return _a(t,n),wi("code-event",{term:e.term,evt:n}),Ii(),null};if(/^\/help\s*$/.test(o)&&"hermes"!==t.runtime)return void i(`Available commands · ${he(t.commands)}`);if(/^\/status\s*$/.test(o)&&"hermes"!==t.runtime){const e=de(t.runtime)?.label||t.runtime,r=t.session?.turnActive?"working":"idle";return void i(`${e} · ${r} · model ${t.model||"default"} · ${t.mode||"default"} permissions · effort ${t.effort||"default"}`)}if(/^\/context\s*$/.test(o)&&"hermes"!==t.runtime){const e=t.lastUsage?.ctx;return void i(e?.max?`Context · ${Number(e.used||0).toLocaleString("en-US")} / ${Number(e.max).toLocaleString("en-US")} tokens (${e.pct??Math.round(Number(e.used||0)/Number(e.max)*100)}%)`:"Context usage unavailable until the runtime reports a completed turn")}if(/^\/diff\s*$/.test(o)){try{const e=t.cwd||process.cwd();i(we({cwd:e}))}catch{i("Working-tree diff unavailable outside a readable Git checkout")}return}const c=o.match(/^\/find(?:\s+([\s\S]+))?$/i);if(c){const r={kind:"repo-search",...ge({cwd:t.cwd||process.cwd(),query:c[1]||""}),by:e.by,cid:e.cid};return _a(t,r),void wi("code-event",{term:e.term,evt:r})}if(/^\/credits\s*$/.test(o)&&"hermes"!==t.runtime)return"codex"!==t.runtime||"function"!=typeof t.session?.accountUsage?void i("Credit balance is unavailable for this runtime; use /usage for provider limits"):void Promise.resolve(t.session.accountUsage()).then(e=>{i(Y(e?.limits))}).catch(()=>i("Codex credits unavailable for this account"));const l=o.match(/^\/model\b\s*(\S+)?/);if(l){if(l[1]){if("hermes"===t.runtime&&t.pendingModelSwitch)return void i("finish the current Hermes model switch before choosing another model");if(!1===t.session.setModel(l[1]))return void i(`finish or stop the current ${de(t.runtime)?.label||"agent"} turn before switching models`);if("hermes"===t.runtime)return t.pendingModelSwitch={model:l[1],by:e.by,cid:e.cid},void wi("code-event",{term:e.term,evt:{kind:"model-switch",status:"pending",requested:l[1],ts:Date.now()}});t.model=l[1],Ii(),t.flush?.(),i(`switched model → ${l[1]}`)}else i("use /model <name> to switch — e.g. opus, sonnet, haiku");return}if(/^\/clear\s*$/.test(o)){if(t.pendingRecap=null,t.pendingCheckpoint=null,t.pendingCodexCompaction=null,"codex"===t.runtime||"hermes"===t.runtime)t.session.clearContext?.();else{const e=await a();if(!e)return;!1===t.session.sendTurn(o)&&Ui(t,e)}return t.log=[],t.logBytes=0,t.seq=_o(0),t.archiveOldestSeq=null,wi("code-event",{term:e.term,evt:{kind:"clear"}}),so(rs,e.term,{sessionId:t.session?.sessionId||null,log:[]}),void i("context cleared. You can continue with these answers in mind.")}if(/^\/compact\s*$/.test(o)){if("codex"===t.runtime){if(t.codexCompactionPromise||t.pendingCodexCompaction)return;if(t.session.turnActive)return t.pendingCodexCompaction={by:e.by,cid:e.cid},void i("Compaction queued for after this turn.",{tone:"caution"});if(!await a())return;return void Oa(t,{by:e.by,cid:e.cid})}const r=await a();if(!r)return;return t.compacting=!0,t.compactBy=e.by,wi("code-event",{term:e.term,evt:{kind:"compact",status:"start",ts:Date.now()}}),void(!1===t.session.sendTurn(o)&&Ui(t,r))}if(/^\/usage\s*$/.test(o))return i("codex"===t.runtime?Uo(t.model,t.session?.usageSnapshot):Mo(t.model,t.log)),void("codex"===t.runtime?Promise.resolve(t.session?.accountUsage?.()).then(e=>{const t=G(e?.usage);t&&i(t),i(V(e?.limits))}).catch(()=>i("Codex provider limits unavailable")):Sn().then(e=>{e&&i(e)}).catch(()=>{}));if("codex"===t.runtime&&/^\/review(?:\s|$)/.test(o)&&(t.flowSessionId||t.flowRole||"review"===t.sliceType))return void i("Native /review is unavailable in Dispatch and reviewer lanes; their immutable review contract already owns scope and authority");const d=await a({echo:!0});if(!d)return;let u=o;const m=[];t.pendingRecap&&(m.push(t.pendingRecap),t.pendingRecap=null),t.pendingCheckpoint&&(m.push(t.pendingCheckpoint),t.pendingCheckpoint=null),t.pendingSideContexts?.length&&(m.push(...t.pendingSideContexts),t.pendingSideContexts=[]),m.length&&(u=Fo(m,o),t.flush?.());const p="codex"===t.runtime||"hermes"===t.runtime?await Se(e.files,{updir:Ps}):[],h="hermes"===t.runtime&&t.session.turnActive&&/^\s*\/queue\s+/i.test(o),f={...p.length?{images:p}:{},...h&&!e.silent?{_thinkpoolQueuedEcho:{text:null!=e.body?String(e.body):o,cid:e.cid,by:e.by,...Array.isArray(e.files)&&e.files.length?{files:e.files}:{},...Array.isArray(e.pastes)&&e.pastes.length?{pastes:e.pastes}:{}}}:{}};Ys(t),Ci(e.term,null!=e.body?String(e.body):o);const w=t.session.sendTurn(u,Object.keys(f).length?f:void 0);if(!1===w?(Ys(t),Ui(t,d)):Vs(t),h&&!1!==w||s(),!1===w){const r={kind:"error",message:`${de(t.runtime)?.label||"Agent"} did not accept this turn; retry after the lane is available.`,recoverable:!0};_a(t,r),wi("code-event",{term:e.term,evt:r})}if(Ii(),!1!==w&&Ke(t,{turnRev:t._turnRev,turnCid:r})&&(Fa(t),qe(t).finally(()=>Ii()),Ii()),e.pooled&&!e.silent){const r={kind:"pool",text:"dispatched to agent"};_a(t,r),wi("code-event",{term:e.term,evt:r})}}).on("broadcast",{event:"code-perm"},({payload:e})=>{const t=e?.term&&Js.get(e.term),r=t&&e.id&&t.pending.get(e.id);r&&on({supabaseUrl:Un,anonKey:Wn,token:zn,roomCode:rs,bridgeId:ks,payload:e}).then(o=>{o.ok&&Js.get(e.term)?.pending.get(e.id)===r?(r.timer&&clearTimeout(r.timer),t.pending.delete(e.id),t.permNotifier?.resolve(e.id),r.resolve(qa(r,{...e,decision:o.decision,answers:o.answers,responder:o.responder})),Ii()):!o.ok&&process.env.TP_DEBUG&&process.stderr.write(`\n ◇ ignored unverified permission delivery (${o.code})\n`)})}).on("broadcast",{event:"code-abort"},({payload:e})=>{const t=e?.term&&Js.get(e.term);if(t){const r=je(t,e);wi("code-abort-ack",{term:e.term,cid:e.cid,turnRev:e.turnRev,action:r.action,code:r.code,currentTurnRev:r.currentTurnRev}),"abort"===r.action&&(Fa(t),qe(t).finally(()=>Ii()),Ii())}}).on("broadcast",{event:"code-mode"},({payload:e})=>{const t=e?.term&&Js.get(e.term);if(t&&ze.has(e.mode)){if(ae(t)&&e.mode!==t.mode){const r={kind:"control",text:`This ${t.flowRole||"review"} lane is structurally locked to ${t.mode}; Dispatch and reviewer restrictions take precedence.`};return _a(t,r),wi("code-event",{term:e.term,evt:r}),void Ii()}if("codex"===t.runtime||"hermes"===t.runtime){if(!t.session.setMode(e.mode)){const r={kind:"control",text:`finish or stop the current ${de(t.runtime)?.label||"agent"} turn before switching permissions`};return _a(t,r),wi("code-event",{term:e.term,evt:r}),void Ii()}return t.mode=e.mode,"bypassPermissions"===e.mode?Ba(t):"acceptEdits"===e.mode?Wa(t):"plan"===e.mode&&Fa(t),t.flush?.(),void Ii()}t.mode=e.mode,t.session.setMode(e.mode),"bypassPermissions"===e.mode?Ba(t):"acceptEdits"===e.mode&&Wa(t),Ii()}}).on("broadcast",{event:"code-effort"},({payload:e})=>{const t=e?.term&&Js.get(e.term);if(t){if(!ne(t.runtime,t).includes(e.level)){const r={kind:"control",text:"ultra"===e.level?"Ultra Cascade is available only in an independent Codex terminal on a model that supports it.":`Reasoning effort ${e.level||"unknown"} is unavailable for this model.`};return _a(t,r),wi("code-event",{term:e.term,evt:r}),void wi("code-event",{term:e.term,evt:{kind:"effort",level:t.effort||"high"}})}if(t.session?.turnActive){const r={kind:"control",text:"finish or stop the current turn before switching thinking power"};return _a(t,r),void wi("code-event",{term:e.term,evt:r})}Promise.resolve(t.session.setEffort?.(e.level)).then(r=>{!1!==r&&(t.effort=e.level,t.flush?.(),Ii())}).catch(()=>{})}}).on("broadcast",{event:"code-close"},({payload:e})=>{Ha(e?.id)}).on("broadcast",{event:"term-rename"},({payload:e})=>{e?.id&&(yi.add(e.id),$i.delete(e.id),e.name?vi[e.id]=String(e.name).slice(0,80):delete vi[e.id],ho(rs,vi),Ii())}).on("broadcast",{event:"who"},Ii).subscribe(async e=>{if("SUBSCRIBED"===e){Qa=!0,Xa=0,t={name:ys,role:"bridge",bridge_id:ks,started_at:Ts},(Fs||=An(Bs,{minMs:5e3}))(t);const e=fs||is,r=[];if(e&&!zs.size&&!Js.size)if(cs(e)){const e=ao(rs),t=e=>e._bt||e.openedAt||e.savedAt||0;if(e.sort((e,r)=>t(e)-t(r)),await Ua(),e.length)for(const t of e){const e=Aa(t.log||[]),o=t.runtime||"claude",n="hermes"===o?Array.isArray(t.models)&&t.models.length?t.models:Ln:t.models,s=!t.flowSessionId&&!e,i=!se({runtime:o,defer:s,cwd:t.cwd,flowSessionId:t.flowSessionId,flowTaskKey:t.flowTaskKey,models:n});if(i){const e=await qi(t.id);if(!e.ok){process.stderr.write(`\n ◇ active restore held for ${String(t.id).slice(0,8)} — ${e.reason||"host runtime capacity is full"}\n`);continue}}const a=Zr(t,{canResume:lo,codexThreadCanResume:J}),c=e?Lo(t.log||[],Ho):"";ja({id:t.id,runtime:o,model:t.model||void 0,models:t.models,effort:t.effort,provider:"claude"===t.runtime&&t.provider||void 0,resume:a?t.sessionId:void 0,log:t.log,commands:t.commands,mode:t.mode,spawnedBy:t.spawnedBy,spawnDepth:t.spawnDepth,cascadeRole:t.cascadeRole,hop:t.hop,sideParent:t.sideParent,sideTask:t.sideTask,scheduleRunId:t.scheduleRunId,scheduleDeadlineAt:t.scheduleDeadlineAt,scheduleOutcomeRecorded:t.scheduleOutcomeRecorded,scheduleAdmissionLease:t.scheduleAdmissionLease,pendingSideContexts:t.pendingSideContexts,pendingWorkerCompletions:t.pendingWorkerCompletions,workerCompletionsInFlight:t.workerCompletionsInFlight,sliceType:t.sliceType,flowSessionId:t.flowSessionId,flowTaskKey:t.flowTaskKey,flowTaskContract:t.flowTaskContract,flowRole:t.flowRole,flowReviewTarget:t.flowReviewTarget,flowReviewTargets:t.flowReviewTargets,flowReviewSnapshots:t.flowReviewSnapshots,flowReviewRound:t.flowReviewRound,flowReviewConclusion:t.flowReviewConclusion,dispatchBaseSha:t.dispatchBaseSha,revertTarget:t.revertTarget,cwd:t.cwd,managedWorktree:t.managedWorktree,rolePrompt:t.rolePrompt,reviewSliceRoots:t.reviewSliceRoots,openedAt:t.openedAt,lastUsage:t.lastUsage,receivedTurnCids:t.receivedTurnCids,mcpFlight:t.mcpFlight,carryRecap:e?c:t.carryRecap,carryCheckpoint:t.carryCheckpoint,defer:s});const l=Js.get(t.id);!l&&i&&Ki(t.id);const d=[...t.log||[]].reverse().find(e=>"result"===e?.kind||"error"===e?.kind);l&&t.flowTaskKey&&et({runtime:l.runtime,flowRole:l.flowRole,eventKind:d?.kind,eventSubtype:d?.subtype,interrupted:e})&&setTimeout(()=>{try{l.markFlowDone?.()}catch{}},2e3),l&&e&&(l.pendingInterruptedRecovery={resumable:a,recap:c},r.push(l))}else if(fs){const e=c();(await qi(e)).ok&&(ja({id:e,runtime:as(fs)}),Js.has(e)||Ki(e))}si&&setTimeout(()=>{for(const[,e]of Js)!e.deferred||e.warmed||e.warming||e.session?.started||oi.push(e);oi.length&&(process.stderr.write(`\n ◆ background-warming ${oi.length} idle terminal(s) (≤3 at a time)…\n`),ii())},6e3)}else{const t=uo(rs)||c();mo(rs,t),(await qi(t)).ok&&(va({id:t,cmd:e,args:ws,attached:!is}),zs.has(t)||Ki(t))}if(await Ii(),f({room:rs,hostId:Rs,liveIds:[...zs.keys(),...Js.keys()],token:zn,supabaseUrl:Un,anonKey:Wn,shuttingDown:ri,onFailure:({error:e,status:t})=>process.stderr.write(`\n ⚠ terminal row reconcile failed${t?` (HTTP ${t})`:""}: ${e||"unknown error"}\n`)}).then(({reaped:e})=>{e.length&&process.stderr.write(`\n ◆ removed ${e.length} stale terminal row${1===e.length?"":"s"} after restore.\n`)}),process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD)try{process.send({t:"room-ready",room:rs,bridgeId:ks})}catch{}r.forEach((e,t)=>{const r=setTimeout(()=>{const t=e.pendingInterruptedRecovery;if(e.pendingInterruptedRecovery=null,!t||Js.get(e.id)!==e)return;const r=Vr(e,t);"sent"===r?process.stderr.write(`\n ◆ auto-resumed interrupted Codex turn (${e.id.slice(0,8)}) — sent continue.\n`):"recap-sent"===r&&process.stderr.write(`\n ◆ resumed interrupted Codex turn (${e.id.slice(0,8)}) with a fresh context recap.\n`)},1e3+5e3*t);r.unref?.()}),setImmediate(()=>{for(const e of Js.values())if(e.snapshotNeedsCompaction){e.snapshotNeedsCompaction=!1;try{e.flush?.()}catch{}}}),process.stderr.write(ss?`\n ◆ thinkpool — relaying room ${rs} (headless). Open terminals from the web UI.\n\n`:`\n ◆ thinkpool — sharing "${fs}"${gs?" (continuing your latest session)":""} into room ${rs}. Open the web UI and you're both in.\n\n`)}else"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||(!Qa&&Xa||(Xa=Date.now()),Qa=!1,process.stderr.write(`\n ⚠ realtime ${e} — reconnecting…\n`));var t}),Ls.on("broadcast",{event:"flow-start"},async({payload:e})=>{if(!e?.flowId)return;if(e.host&&e.host!==ys)return;for(const[,t]of Js)if(t.flowSessionId===e.flowId)return;const t=e.originTerm?Js.get(e.originTerm):null;if(e.originTerm&&!t)return;const r=t?it(t.runtime,null):"claude";if(!r)return;const o="codex"===r?t?.models||H():"hermes"===r&&t?.models||[],n=ct({runtime:r,originModel:t?.model,catalog:o}),s=Wr({totalLive:Js.size+zs.size,disabled:"1"===process.env.TP_SPAWN_OFF});if(!s.ok)return process.stderr.write(`\n ${Ia}◆ flow start held — ${s.reason}${ba}\n`),void wi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:null,reason:s.reason},Ls);const i=Ee("start the Dispatch conductor");if(!i.ok)return ji(),process.stderr.write(`\n ${Ia}◆ flow start held — ${i.reason}${ba}\n`),void wi("flow-host-pressure",{term:"flow",flowId:e.flowId,reason:i.reason},Ls);const a=c(),l=await qi(a);if(!l.ok){const t=l.reason||"This bridge machine cannot accept another live lane yet.";return process.stderr.write(`\n ${Ia}◆ dispatch start held — ${t}${ba}\n`),void wi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:null,reason:t},Ls)}vi[a]=`Dispatch · ${String(e.flowId).slice(0,6)}`,ho(rs,vi),ja({id:a,runtime:r,model:n,mode:"codex"===r?"plan":"default",rolePrompt:"claude"===r?Je:Ye,flowSessionId:e.flowId,flowRole:"conductor",spawnedBy:`flow:${e.flowId}`});const d=Js.get(a);if(!d)return Ki(a),delete vi[a],void ho(rs,vi);d?.session&&Qs(d,e.prompt||"",{rejectionMessage:"The Dispatch conductor task was not accepted; retry after the lane is available."}),process.stderr.write(`\n ${Ta}◆ flow conductor launched — flow ${String(e.flowId).slice(0,8)} (plan mode).${ba}\n`),Ii()}).on("broadcast",{event:"flow-dispatch"},async({payload:e})=>{if(!e?.flowId||!Array.isArray(e.tasks))return;if(e.host&&e.host!==ys)return;const t=[...Js.values()].find(t=>t.flowSessionId===e.flowId&&"conductor"===t.flowRole);if(!t)return void process.stderr.write(`\n ${Ia}◆ flow dispatch held — this bridge has no live/restored conductor for ${String(e.flowId).slice(0,8)}.${ba}\n`);const r=it(t.runtime,null);if(!r)return;const o="codex"===r?t.models||H():"hermes"===r&&t.models||[],n=[];let i=Hr(Js.values());const a=lr();if(a.disabled)return void process.stderr.write(`\n ${Ia}◆ flow dispatch refused — TP_FLOW_OFF kill-switch is on.${ba}\n`);const l=e.mode||"guide",d=null!=a.capFromEnv?a.capFromEnv:null!=e.budgetCap?Number(e.budgetCap):null;let u=vr.get(e.flowId)||ar({capTokens:d});u.capTokens!==d&&(u={...u,capTokens:d}),vr.set(e.flowId,u);for(const t of e.tasks){if([...Js.values()].some(r=>r.flowSessionId===e.flowId&&r.flowTaskKey===t.task_key&&!r.flowDone)){process.stderr.write(`\n ${ka}◆ flow dispatch skip ${t.task_key} — lane already live.${ba}\n`);continue}const a=ur(e.flowId,t.task_key);if(gr.has(a))process.stderr.write(`\n ${ka}◆ flow dispatch skip ${t.task_key} — admission already in flight.${ba}\n`);else{gr.add(a);try{const a=ir({mode:l,budget:u});if(!a.ok){process.stderr.write(`\n ${Ia}◆ flow dispatch held (${a.reason}) — ${n.length} spawned this wave.${ba}\n`);break}const d=Lr({spawnedLive:i,totalLive:Js.size+zs.size,plan:Os,disabled:"1"===process.env.TP_SPAWN_OFF});if(!d.ok){process.stderr.write(`\n ${Ia}◆ flow dispatch held — ${d.reason} ${n.length} spawned this wave; remaining slices stay queued.${ba}\n`),wi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:t.task_key||null,reason:d.reason},Ls);break}const m=Ee("start another Dispatch lane");if(!m.ok){ji(),process.stderr.write(`\n ${Ia}◆ flow dispatch held — ${m.reason}${ba}\n`),wi("flow-host-pressure",{term:"flow",flowId:e.flowId,reason:m.reason},Ls);break}const p=c(),h=await qi(p);if(!h.ok){const r=h.reason||"This bridge machine cannot accept another live lane yet.";process.stderr.write(`\n ${Ia}◆ dispatch held — ${r}${ba}\n`),wi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:t.task_key||null,reason:r},Ls);break}try{const a="review"===t.slice_type;try{nt(t,{legacy:null==t.contract})}catch(r){process.stderr.write(`\n ${Ia}◆ flow dispatch held — ${t.task_key||"task"} failed its sealed acceptance contract: ${r?.message||r}${ba}\n`),wi("flow-dispatch-held",{term:"flow",flowId:e.flowId,taskKey:t.task_key||null,reason:"sealed acceptance contract mismatch"},Ls),Ki(p);continue}if(!st(t,r)){process.stderr.write(`\n ${Ia}◆ flow dispatch held — ${"hermes"===r?"Hermes":"Codex"} review ${t.task_key} must target exactly one dependency.${ba}\n`),Ki(p);continue}const{dir:c}=vt({flowId:e.flowId,taskKey:t.task_key});let l=null;try{l=s("git",["-C",c,"rev-parse","HEAD"],{encoding:"utf8"}).trim()}catch{}vi[p]=`Dispatch · ${t.task_key}`,ho(rs,vi);const d=ur(e.flowId,t.task_key),u=wr.get(d)||null;u&&wr.delete(d);const m=a?(t.deps||[]).map(t=>yt({flowId:e.flowId,taskKey:t}).dir):[],h=a?(t.deps||[]).map(r=>{const o=yt({flowId:e.flowId,taskKey:r}).dir;let n=null;try{n=s("git",["-C",o,"rev-parse","HEAD"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).trim()}catch{}let i=null;if(n&&t.contract?.scopePaths?.length){let e=null;try{e=s("git",["-C",o,"merge-base",n,"origin/main"],{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]}).trim()}catch{}const r=yr(o,e,n);if(r){const e=Ht({log:[],repoRoot:o,declared:t.contract.scopePaths,changed:r}),n=zt(t.contract.scopeEvidence);i=n?{...e,read:n.read,verified:n.verified}:e}}return{taskKey:r,cwd:o,sha:n,...i?{scopeEvidence:i}:{}}}).filter(e=>e.sha):[],f=Ze({base:"codex"===r||"hermes"===r?a?Kt:Ve:a?qt:Ge}),w=t.contract?.acceptancePack?.task?.acceptance;ja({id:p,runtime:r,cwd:c,model:at({sliceType:t.slice_type,runtime:r,catalog:o}),mode:ie(r,{mode:"bypassPermissions",flowRole:a?"reviewer":"builder"}),rolePrompt:f,flowSessionId:e.flowId,flowTaskKey:t.task_key,flowTaskContract:t.contract||null,flowRole:a?"reviewer":"builder",flowReviewTargets:a&&t.deps||[],flowReviewSnapshots:h,dispatchBaseSha:l,revertTarget:u?.revertTarget||null,spawnedBy:`flow:${e.flowId}`,resume:u?.resumeSessionId||void 0,reviewSliceRoots:m});const g=Js.get(p);g&&(u&&(g.revertTarget=u.revertTarget??null),a&&(g.flowReviewTarget=t.deps&&t.deps[0]||null),g.session&&!u)&&Qs(g,a?`[Dispatch REVIEW lane — slice "${t.task_key}" of run ${String(e.flowId).slice(0,8)}]\nYou are ADVERSARIALLY reviewing the slice(s): ${(t.deps||[]).join(", ")||t.title}\n`+(Array.isArray(t.deps)&&t.deps.length?"Reviewed slice worktree(s) — check out + RUN each yourself:\n"+t.deps.map(t=>{const r=yt({flowId:e.flowId,taskKey:t});return` - ${t}: dir ${r.dir} (branch ${r.branch})`}).join("\n")+"\n":"")+`ACCEPTANCE to INDEPENDENTLY verify: ${w||t.acceptance||t.title}\n`+`INHERITED NON-GOALS (must remain untouched): ${(t.contract?.nonGoals||[]).join(" | ")||"(legacy task: none recorded)"}\n`+`INHERITED BASELINE GATE: ${t.contract?.baseline?.gate||"(legacy task: none recorded)"}\n`+`BUILDER BASELINE EVIDENCE (verify; never invent another baseline): ${t.contract?.baseline?.evidence||"(missing — reject unless this is a legacy task)"}\n`+`\nProject (context): ${e.flowPrompt||""}\n\n`+("codex"===r||"hermes"===r?"Review it without mutating the builder worktree. For write-producing install/build/test commands, copy its source into scratch under your own current worktree first. Submit the structured verdict with the thinkpool submit_flow_review MCP tool; never write FLOW_REVIEW.json or call mark_flow_done.":'Review it — run it, hunt for failure. When done, use the Write tool to write FLOW_REVIEW.json with {"pass":<boolean>,"reasons":["<specific finding>"],"taskKey":"<the slice you reviewed>"}. That Write IS your verdict.'):`[Dispatch lane — slice "${t.task_key}" of run ${String(e.flowId).slice(0,8)}]\nTITLE: ${t.title}\nSCOPE (files you OWN — edit ONLY these): ${t.scope||"(none stated)"}\nACCEPTANCE (done = this runs + proves it): ${t.acceptance||"(meet the title)"}\nNON-GOALS (must remain untouched): ${(t.contract?.nonGoals||[]).join(" | ")||"(legacy task: none recorded)"}\nBASELINE GATE (before edits, observe this real failure/absence): ${t.contract?.baseline?.gate||"(legacy task: none recorded)"}\nBASELINE EVIDENCE: run/observe the pre-edit gate, then retain one real bounded command/behavior receipt for mark_flow_done; never fabricate a RED sentence.\n`+(t.deps&&t.deps.length?`DEPENDS ON (already built): ${t.deps.join(", ")}\n`:"")+(e=>e?`${e}\n`:"")(Xe(e.flowId,{baseDir:process.cwd(),deps:t.deps}).text)+`\nProject (context): ${e.flowPrompt||""}\n\nBuild your slice. Own only your files. Done = it runs + meets acceptance. Commit when done.`+("codex"===r||"hermes"===r?" Then call the thinkpool mark_flow_done MCP tool; do not write FLOW_DONE.":""),{rejectionMessage:`Dispatch slice ${t.task_key} was not accepted; retry after the lane is available.`}),g?(n.push({task_key:t.task_key,laneId:p}),i++):Ki(p)}catch(e){Ki(p),process.stderr.write(`\n ${Ia}◆ flow dispatch failed for ${t.task_key}: ${e?.message||e}${ba}\n`)}}finally{gr.delete(a)}}}n.length&&(wi("flow-dispatched",{term:"flow",flowId:e.flowId,assignments:n},Ls),process.stderr.write(`\n ${Ta}◆ flow dispatched ${n.length} lane(s) — flow ${String(e.flowId).slice(0,8)}.${ba}\n`),Ii())}).on("broadcast",{event:"flow-assemble"},async({payload:e})=>{if(e?.flowId&&Array.isArray(e.tasks)&&(!e.host||e.host===ys))try{const o=String(e.flowId).replace(/-/g,"").slice(0,8),n=e.tasks.map(t=>yt({flowId:e.flowId,taskKey:t.task_key}).dir).filter(e=>t.existsSync(e));if(!n.length)return void process.stderr.write(`\n ${Ia}◆ flow assemble: no lane worktrees for ${o}.${ba}\n`);const s=r.join(process.cwd(),".claude","worktrees",`flow-${o}-assembled`);t.rmSync(s,{recursive:!0,force:!0});const i=or({dirs:n,outDir:s}),a=r.join(s,"index.html");if(t.existsSync(a))try{t.writeFileSync(a,nr({htmlPath:a,root:s}))}catch(e){process.stderr.write(`\n ${Ia}◆ inline failed: ${e?.message||e}${ba}\n`)}try{sr({dir:s})}catch{}let c=null;try{c=(await kt({dir:s,id:`assembled:${e.flowId}`})).url}catch{}jt(e.flowId),wi("flow-assembled",{term:"flow",flowId:e.flowId,previewUrl:c,outDir:s,files:i.files,conflicts:i.conflicts},Ls),process.stderr.write(`\n ${Ta}◆ flow assembled — ${i.files.length} file(s)${i.conflicts.length?`, ${i.conflicts.length} conflict(s)`:""}${c?` · preview ${c}`:""} (flow ${o}).${ba}\n`),Ii(),za(e.flowId)}catch(e){process.stderr.write(`\n ${Ia}◆ flow assemble failed: ${e?.message||e}${ba}\n`)}}).on("broadcast",{event:"flow-revert"},async({payload:e})=>{await Za(e)}).on("broadcast",{event:"flow-cancel"},({payload:e})=>{e?.flowId&&(e.host&&e.host!==ys||(za(e.flowId,600),process.stderr.write(`\n ${Ia}◆ flow cancelled — closing its lanes (${String(e.flowId).replace(/-/g,"").slice(0,8)}).${ba}\n`)))}).subscribe(e=>{"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||process.stderr.write(`\n ⚠ flow realtime ${e} (tpflow:${rs}).\n`)});const ec=new Set;Ws.on("broadcast",{event:"design-capability"},({payload:e})=>{const t=e?.previewId&&Vi.get(String(e.previewId)),r=t&&At(t),o=!!t&&!!r&&r.revision===t.revision&&t.revision===e?.revision&&Js.has(t.term);Ws.send({type:"broadcast",event:"design-capability-res",payload:{previewId:String(e?.previewId||""),revision:String(e?.revision||""),ok:o}})}).on("broadcast",{event:"design-apply"},async({payload:e})=>{const t=Dt(e,Vi,rs),r=String(e?.previewId||""),o=String(e?.cid||"").slice(0,80);if(!t.ok){const e=Number.isSafeInteger(t.editIndex)?`Edit ${t.editIndex+1}: `:"";return void ia({previewId:r,requestId:o,state:"stale-preview"===t.error?"stale":"failed",message:`${e}${t.error}`})}if(!o||ec.has(o))return;ec.add(o),ec.size>500&&ec.delete(ec.values().next().value);const n=t.record.term,s=Qi.get(n)||[];if(Qi.set(n,s),s.length>=8)return void ia({previewId:r,requestId:o,state:"failed",message:"Too many Design batches are queued for this lane."});const i="batch"===t.request.mode?t.request.edits:[t.request],a=[];for(let e=0;e<i.length;e++){const t=i[e];if("image"!==t.mode)continue;const n=await _t({webBase:Fn,token:zn,room:rs,asset:t.asset,requestId:`${o}-${e+1}`,cleanup:!1});if(!n)return void ia({previewId:r,requestId:o,state:"failed",message:`Edit ${e+1}: The private image draft could not be opened.`});t.asset.localPath=n,a.push(t.asset.path)}await Promise.all(a.map(e=>St({webBase:Fn,token:zn,room:rs,path:e})));const c=String(e?.by||"A room member").replace(/\0/g,"").trim().slice(0,120)||"A room member";s.push({...t,by:c});const l="batch"===t.request.mode?t.request.edits.length:1;ia({previewId:r,requestId:o,state:"queued",message:`${l} edit${1===l?"":"s"} pooled to the producing lane.`}),la(n)}).on("broadcast",{event:"design-restore"},({payload:e})=>{const t=String(e?.previewId||""),r=String(e?.cid||"").slice(0,80),o=Vi.get(t),n=Zi.get(t),s=o&&At(o);if(!(r&&o&&n?.priorRecord?.backupPath&&s&&s.revision===o.revision&&e?.revision===o.revision))return void ia({previewId:t,requestId:r,state:"stale",message:"That verified revision can no longer be restored safely."});if(ec.has(r))return;ec.add(r);const i=Qi.get(o.term)||[];if(Qi.set(o.term,i),i.length>=8)return void ia({previewId:t,requestId:r,state:"failed",message:"Too many Design edits are queued for this lane."});const a=String(e?.by||"A room member").replace(/\0/g,"").trim().slice(0,120)||"A room member";i.push({record:o,restoreRecord:n.priorRecord,request:{previewId:t,revision:o.revision,mode:"restore",intent:"restore previous verified revision",target:n.request.target||{selector:"html",tag:"artifact",name:`${n.request.edits?.length||1} pooled edits`},cid:r},by:a}),ia({previewId:t,requestId:r,state:"queued",message:"Restore queued in the producing lane."}),la(o.term)}).subscribe(e=>{"CHANNEL_ERROR"!==e&&"TIMED_OUT"!==e&&"CLOSED"!==e||process.stderr.write(`\n ⚠ design realtime ${e} (tpdesign:${rs}).\n`)});let tc=!1;const rc=e=>{const t=e?.runtime,r=e?.provider_id||"anthropic";return"claude"===t?!(!N().some(e=>e.id===r)||"anthropic"!==r&&e?.model&&D(r)!==e.model):!e?.provider_id&&("codex"===t?!e?.model||dt(H()).has(e.model):"hermes"===t&&(!e?.model||Ln.some(t=>(t?.id||t?.model)===e.model)))},oc=async()=>{if(!tc&&!ri&&zn&&Ds&&bs&&Number.isSafeInteger($s)&&!($s<1)){tc=!0;try{if(!await async function(){if(!zn||!bs||!Number.isSafeInteger($s)||$s<1)return!1;const e=new Map(ao(rs).map(e=>[e?.id,e]).filter(([e])=>e));for(const{terminalId:t,intent:r,acknowledged:o}of So(rs)){if(o){Io(rs,t);continue}const n=an(r);if(!n){Io(rs,t);continue}let s=Js.get(t);const i=e.get(t);(!0===s?.scheduleOutcomeRecorded?s.scheduleRunId:!0===i?.scheduleOutcomeRecorded?i.scheduleRunId:null)!==n.runId?!s&&i||s&&s.scheduleRunId&&s.scheduleRunId!==n.runId||(s||(s={id:t,scheduleRunId:n.runId,scheduleOutcomeRecorded:!1}),s.scheduleOutcomePending=n,await oa(s)):Io(rs,t)}return cn(So(rs))}())return;if(!mn())return;const e=await sn({enabled:!0,supabaseUrl:Un,anonKey:Wn,token:zn,roomCode:rs,bridgeId:bs,bridgeFencing:$s,ownerId:Ds,providerAvailable:rc,admitRun:async({runId:e,terminalId:t,deadlineAt:r})=>{const o=dn({spawnTimes:[],totalLive:Js.size+zs.size,disabled:"1"===process.env.TP_SPAWN_OFF});return o.ok?pn({runId:e,terminalId:t,deadlineAt:r}):o},releaseRun:e=>hn(e),openTerminal:async({schedule:e,run:t,terminalId:r,admission:o})=>{const n=Date.parse(t.lease_expires_at),s=Number.isFinite(n)?n-6e4:NaN;if(!Number.isFinite(s)||s<=Date.now())return null;if(!(await qi(r)).ok)return null;const i=ja({id:r,runtime:e.runtime,provider:e.provider_id||void 0,model:e.model||void 0,mode:"default",scheduleRunId:t.id,scheduleDeadlineAt:s,scheduleAdmissionLease:o});if(!i)return Ki(r),null;vi[r]=String(e.title||"Scheduled run").slice(0,80),ho(rs,vi);const a=Qs(i,String(e.prompt||""),{visibleEvent:{kind:"you",text:String(e.prompt||""),by:"Scheduled run"},rejectionMessage:"The scheduled run could not start; no hidden fallback was used."});return a?.accepted?(sa(i),i.flush?.(),Ii(),r):(i.scheduleRunId=null,ea(i),Ha(r),null)}});!e.ok&&process.env.TP_DEBUG&&"runner_read_failed"!==e.code&&process.stderr.write(`\n ◇ scheduled-run poll: ${e.code}\n`)}finally{tc=!1}}};oc(),setInterval(()=>{oc()},15e3).unref();let nc=!1,sc=0,ic=0;if(setInterval(async()=>{if(Qa||!Xa)return sc=0,void(ic=0);const e=Date.now();if(e-Xa<6e4||nc||e<ic)return;nc=!0;const t=await(async()=>{const e=new AbortController,t=setTimeout(()=>e.abort(),5e3);try{return(await fetch(`${Un}/auth/v1/health`,{headers:{apikey:Wn},signal:e.signal})).ok}catch{return!1}finally{clearTimeout(t)}})(),r=ro({brokenSince:Xa,now:Date.now(),httpHealthy:t,activeTurn:oo(Js)});if("restart"===r)return process.stderr.write("\n ⚠ realtime wedged while HTTP is healthy — exiting for a clean restart.\n"),void ac(1);const o=Pn(sc);sc+=1,ic=Date.now()+o,process.stderr.write(`\n ◇ realtime unavailable (${r}) — preserving local agents; retrying in ${Math.round(o/1e3)}s.\n`);try{Ns.realtime?.disconnect?.()}catch{}try{Ns.realtime?.connect?.()}catch{}nc=!1},15e3).unref(),"1"===process.env.THINKPOOL_PAIR_AUTOUPDATE&&_s){const e=1e3*Math.max(60,parseInt(process.env.THINKPOOL_PAIR_UPDATE_INTERVAL,10)||1800),t=1e3*Math.max(10,parseInt(process.env.THINKPOOL_PAIR_UPDATE_IDLE,10)||90),r=()=>{if(oo(Js))return!1;for(const e of zs.values())if(e.buf)return!1;return!0},o=()=>r()&&Date.now()-ai>=t,n=(e,t)=>{const r=e=>String(e).split("-")[0].split(".").map(e=>parseInt(e,10)||0),o=r(e),n=r(t);for(let e=0;e<3;e++){if((o[e]||0)>(n[e]||0))return!0;if((o[e]||0)<(n[e]||0))return!1}return!1},s=async()=>{const e=new AbortController,t=setTimeout(()=>e.abort(),8e3);try{const t=await fetch("https://registry.npmjs.org/thinkpool-pair/latest",{signal:e.signal,headers:{accept:"application/json"}});if(!t.ok)return null;const r=await t.json();return"string"==typeof r?.version?r.version:null}catch{return null}finally{clearTimeout(t)}},i=()=>{if(li){if(di){if(!r())return}else if(!o()||mi())return;process.stderr.write(`\n ◆ thinkpool-pair ${li} ready (running ${_s}) — restarting to update; the session resumes.\n`),ac(0,!1)}},a=async()=>{const e=await s();e&&n(e,_s)&&(li||process.stderr.write(`\n ◆ thinkpool-pair ${e} published — "update ready" in the room; applies between turns.\n`),Ja(e),i())};setInterval(a,e).unref(),setInterval(i,15e3).unref(),setTimeout(a,6e4).unref()}else if(process.send&&"1"===process.env.THINKPOOL_PAIR_ACCOUNT_CHILD){const e=1e3*Math.max(10,parseInt(process.env.THINKPOOL_PAIR_UPDATE_IDLE,10)||90),t=()=>{if(oo(Js))return!1;for(const e of zs.values())if(e.buf)return!1;return!0},r=()=>t()&&Date.now()-ai>=e;process.on("message",e=>{if(e)if("update-available"===e.t)Ja(e.version);else if("agent-visibility-changed"===e.t)Ii();else if("restart-probe"===e.t)try{process.send({t:"restart-probe-result",nonce:e.nonce,between:t()})}catch{}else"token"===e.t&&(zn=e.accessToken||null,Et(Ns,zn,Wn).then(e=>{!e&&zn&&process.stderr.write("\n ⚠ realtime auth refresh failed; private bridge features may need a reconnect.\n")}),Es(),Ma&&Ua())}),setInterval(()=>{try{process.send({t:"idle",idle:r(),between:t(),webPeer:mi()})}catch{}},5e3).unref()}else _s&&setTimeout(async()=>{try{const e=new AbortController,t=setTimeout(()=>e.abort(),8e3),r=await fetch("https://registry.npmjs.org/thinkpool-pair/latest",{signal:e.signal,headers:{accept:"application/json"}}).finally(()=>clearTimeout(t));if(!r.ok)return;const o=await r.json(),n="string"==typeof o?.version?o.version:null;if(!n)return;const s=e=>String(e).split("-")[0].split(".").map(e=>parseInt(e,10)||0),i=s(n),a=s(_s);let c=!1;for(let e=0;e<3;e++){if((i[e]||0)>(a[e]||0)){c=!0;break}if((i[e]||0)<(a[e]||0))break}c&&process.stderr.write(`\n ◆ thinkpool-pair ${n} is out (you're on ${_s}).\n To update: stop this bridge (Ctrl-C), then rerun:\n npx thinkpool-pair@latest ${rs}\n Your session resumes on restart (you'll be asked to continue it).\n For hands-off updates with no interruption, install the background\n service: npx thinkpool-pair@latest install-service ${rs}\n`)}catch{}},6e4).unref();async function ac(e=0,t=!0){if(!ri){ri=!0,fi.close(),setTimeout(()=>process.exit(e),1500),clearInterval(Ji);try{bt()}catch{}try{Rt.close().catch(()=>{})}catch{}if(t)try{const e=Buffer.from("\r\n[ shared session ended ]\r\n","utf8").toString("base64");for(const t of zs.keys())wi("pty-out",{term:t,b64:e})}catch{}for(const e of Js.values())try{e.imageQueue?.close()}catch{}for(const e of Js.values())try{e.flush?.()}catch{}for(const e of zs.values())try{e.term.kill()}catch{}for(const e of Js.values())try{e.session.end()}catch{}Va();try{await Bs.untrack()}catch{}try{await Ns.removeChannel(Bs)}catch{}try{Bi&&await Ns.removeChannel(Bi)}catch{}try{await Ns.removeChannel(Ls)}catch{}try{await Ns.removeChannel(Ws)}catch{}try{await Ns.removeChannel(Hs)}catch{}setTimeout(()=>process.exit(e),250)}}process.on("SIGINT",()=>ac(0)),process.on("SIGTERM",()=>ac(0)),process.on("uncaughtException",e=>{if(!e||"EPIPE"!==e.code&&"ECONNRESET"!==e.code&&"ERR_STREAM_WRITE_AFTER_END"!==e.code&&"ERR_STREAM_DESTROYED"!==e.code){try{process.stderr.write(`\n ⚠ uncaughtException: ${e?.stack||e}\n ◆ shutting down cleanly for a fresh respawn.\n`)}catch{}ac(1)}else try{process.stderr.write(`\n ⚠ ignored benign ${e.code} (not fatal): ${e?.message||""}\n`)}catch{}}),process.on("unhandledRejection",e=>{try{process.stderr.write(`\n ⚠ unhandledRejection (non-fatal, continuing): ${e?.stack||e}\n`)}catch{}});